Files
loongoffice/drawinglayer/source/processor2d/canvasprocessor.cxx
Michael Meeks 44cfc7cb65 re-base on ALv2 code. Includes (at least) relevant parts of:
linecap: Reintegrating finished LineCap feature
    Patch contributed by Regina Henschel
    http://svn.apache.org/viewvc?view=revision&revision=1232507

    Patches contributed by Sven Jacobi
    impress212: #i81610# fixed animation export
    http://svn.apache.org/viewvc?view=revision&revision=1167620
    impress212: drawinglayer gbuild environment changes
    http://svn.apache.org/viewvc?view=revision&revision=1167627
    http://svn.apache.org/viewvc?view=revision&revision=1167628
    impress212: DffPropSet -> minor code improvements, removing table
    http://svn.apache.org/viewvc?view=revision&revision=1167634
    impress212: #158494# fixed excel import (text rotation)
    http://svn.apache.org/viewvc?view=revision&revision=1167638

    Patches contributed by Armin Le Grand
    Svg: Reintegrated Svg replacement from /branches/alg/svgreplavement
    http://svn.apache.org/viewvc?view=revision&revision=1220836
    #118728# changed indentifying definitions for Svg file detection
    http://svn.apache.org/viewvc?view=revision&revision=1229961
    #118838# LineGeometry creation for complicated cases optimized to
	create single Polygons
    http://svn.apache.org/viewvc?view=revision&revision=1236232
    #119176# corrected file type detection for SVG for svg files
	without xml header
    http://svn.apache.org/viewvc?view=revision&revision=1309445
    #118728# Extended Svg file detection
    http://svn.apache.org/viewvc?view=revision&revision=1230531
    #118529# solve break converters and convert commands for OLEs and images
    http://svn.apache.org/viewvc?view=revision&revision=1186168
    svg: added WaE changes from branch svgreplacement to trunc
    http://svn.apache.org/viewvc?view=revision&revision=1222974
    svg: corrected missing member initialization
    http://svn.apache.org/viewvc?view=revision&revision=1226134
    fix for #118525#: Using primitives for chart sub-geometry visualisation
    http://svn.apache.org/viewvc?view=revision&revision=1226879
    #118898# Adapted ImpGraphic::ImplGetBitmap to correctly convert
	metafiles to bitmapEx ...
    http://svn.apache.org/viewvc?view=revision&revision=1293316
    fix for #118525#: removed no longer used variable maOriginalMapMode, one
    more exception eliminated
    http://svn.apache.org/viewvc?view=revision&revision=1227097
    #16758# Added buffering to the VDev usages of the VclProcessor2D derivates...
    http://svn.apache.org/viewvc?view=revision&revision=1229521
    #116758# Secured VDev buffer device to Vcl deinit
    http://svn.apache.org/viewvc?view=revision&revision=1230574
    #116758# added remembering allocated VDevs for VDevBuffer to be able to also
    delete these when vcl goes down; it should never happen, but You never know
    http://svn.apache.org/viewvc?view=revision&revision=1230927
    #118730# Changed SvgClipPathNode to use MaskPrimitive2D for primitive
	representation instead of TransparencePrimitive2D
    http://svn.apache.org/viewvc?view=revision&revision=1231198
    #118822# secured 3D geometry creation (slices) by subdividing the 2D
    source polyPolygon early
    http://svn.apache.org/viewvc?view=revision&revision=1234749
    #118829# enhanced Svg gradient quality, obstacles avoided
    http://svn.apache.org/viewvc?view=revision&revision=1235361
    #118834# Unified usage of TextBreakupHelper as single tooling class
    for i18n text primitive breakup
    http://svn.apache.org/viewvc?view=revision&revision=1236110
    #118853# added square pixel size limit to conversion of
    TransparencePrimitive2D to Metafile action
    http://svn.apache.org/viewvc?view=revision&revision=1237656
    #118824# coreccted mirroring and boundrect when the graphicmanager
    is used for bitmap output
    http://svn.apache.org/viewvc?view=revision&revision=1240097
    #115092# Corrected VclProcessor2D::RenderPolygonStrokePrimitive2D for
    various optimization scenarios
    http://svn.apache.org/viewvc?view=revision&revision=1241434
    #118783# Corrected errors in ID strings, corrected Svg line/fill export,
    corrected polygon close state
    http://svn.apache.org/viewvc?view=revision&revision=1232006
    #118796# corrected null-pointer usage in SVG text exporter
    http://svn.apache.org/viewvc?view=revision&revision=1240262
    #118729# Use GraphicStreamUrl and GraphicUrl to allow multi image
    import with linked graphics, too
    http://svn.apache.org/viewvc?view=revision&revision=1229962
    #118898# corrected error in GDIMetaFile::GetBoundRect in handling
    MetaFloatTransparentAction
    http://svn.apache.org/viewvc?view=revision&revision=1293349
    #118855# Corrected handling of possibly created empty clipRegions
    after PolyPolygon clipping
    http://svn.apache.org/viewvc?view=revision&revision=1237725
	#115962# Better (but not yet optimal, see comments in task) handling
	of MetaFloatTransparentAction in PDF export
	http://svn.apache.org/viewvc?view=revision&revision=1241078
    IP clearance: #118466# This patch removes librsvg, libcroco, libgsf, ...
    http://svn.apache.org/viewvc?view=revision&revision=1200879
    118779# Added svg content streaming in/out to ImpGraphic stream operators
    http://svn.apache.org/viewvc?view=revision&revision=1231908
    linecap: correctons for WaE and mac drawing
    http://svn.apache.org/viewvc?view=revision&revision=1232793
    svg: uses current system Dpi for Svg replacement image creation
    http://svn.apache.org/viewvc?view=revision&revision=1233948

    Patches contributed by Mathias Bauer (and others)
    gnumake4 work variously
    http://svn.apache.org/viewvc?view=revision&revision=1394326
    http://svn.apache.org/viewvc?view=revision&revision=1396797
    http://svn.apache.org/viewvc?view=revision&revision=1397315
    http://svn.apache.org/viewvc?view=revision&revision=1394326
    Remove duplicate header includes.
    cws mba34issues01: #i117720#: convert assertion into warning
    http://svn.apache.org/viewvc?view=revision&revision=1172352
    118485 - Styles for OLEs are not saved. Submitted by Armin Le Grand.
    http://svn.apache.org/viewvc?view=revision&revision=1182166
    cws mba34issues01: #i117714#: remove assertion
    http://svn.apache.org/viewvc?view=revision&revision=1172357

    Patch contributed by Jurgen Schmidt
    add some additional checks to ensure proper reading operations
    http://svn.apache.org/viewvc?view=revision&revision=1209022
    mostly prefer our stream / bounds checking work.

    Patches contributed by Herbert Duerr
    #i118816# add clarifying comment regarding Font::*Color*() methods
    http://svn.apache.org/viewvc?view=revision&revision=1233833
    extend macro->string handling for empty strings
    http://svn.apache.org/viewvc?view=revision&revision=1175801
    avoid magic constants for SALCOLOR_NONE
    http://svn.apache.org/viewvc?view=revision&revision=1177543
    initialize slant properly in ImplFontMetricData constructor (author=iorsh)
    http://svn.apache.org/viewvc?view=revision&revision=1177551
    #i118675# make check for extension updates more stable
    http://svn.apache.org/viewvc?view=revision&revision=1214797
    #a118617# remove VBasicEventListener.dll binary
    There are no known users depending on its CLSID
    http://svn.apache.org/viewvc?view=revision&revision=1203697

    Patches contributed by Ariel Constenla-Haile
    Fix build breaker on Linux/gcc
    http://svn.apache.org/viewvc?view=revision&revision=1221104
    Fix crash when trying to instantiate css.graphic.GraphicRasterizer_RSVG
    http://svn.apache.org/viewvc?view=revision&revision=1215559

    Patches contributed by Oliver-Rainer Wittmann
    sw34bf06: #i117962# - method <SwFlyFrm::IsPaint(..)> - consider
    instances of <SwFlyDrawObj>
    http://svn.apache.org/viewvc?view=revision&revision=1172120
    sw34bf06: #i117783# - Writer's implementation of XPagePrintable -
    apply print settings to new printing routines
    http://svn.apache.org/viewvc?view=revision&revision=1172115

    gnumake4 work variously from Hans-Joachim Lankenau
    http://svn.apache.org/viewvc?view=revision&revision=1397315
    http://svn.apache.org/viewvc?view=revision&revision=1396797
    http://svn.apache.org/viewvc?view=revision&revision=1396782
    http://svn.apache.org/viewvc?view=revision&revision=1394707
    plus some amount of re-splitting of legacy headers.

    Patch contributed by Pavel Janik
    WaE: Remove unused variables.
    http://svn.apache.org/viewvc?view=revision&revision=1230697

    Patches contributed by Takashi Ono
    mingwport35: i#117795: MinGW port fix for vcl2gnumake
    http://svn.apache.org/viewvc?view=revision&revision=1172091
    mingwport35: i#117795: MinGW port fix for vcl2gnumake
    http://svn.apache.org/viewvc?view=revision&revision=1172091

    Patch contributed by Christian Lippka
    impress212: #i98044# re enable Text menu for outline and title shapes
    http://svn.apache.org/viewvc?view=revision&revision=1167639

    Patch contributed by Andre Fischer
    118674: Made category B code optional and disabled by default.
    http://svn.apache.org/viewvc?view=revision&revision=1215131
    118881: Ignore empty paragraphs after bullets.
    http://svn.apache.org/viewvc?view=revision&revision=1296205

    Patches contributed by Philipp Lohmann
    ooo340fixes: #i117780# use rtl allocator
    http://svn.apache.org/viewvc?view=revision&revision=1172087
    ooo34gsl02: #i117807# fix an off by one error (index actually
    inside the pfb section header)
    http://svn.apache.org/viewvc?view=revision&revision=1167576

various cleanups, related compilation fixes, warning cleanups, re-working
of obsolete stl template pieces to use boost instead, changed string
classes, re-adapt KDE about data, about dialog, fixing warnings,
and other fixes & improvements.
Disable svg import / render for about/ branding code-paths for now.
Restore full icon theme set.
Remove OS/2 conditionals and sources.
Remove conflicting gtk/full-screen monitors support.
Retain existing svg rasterizer files - temporarily disabled.
Standardize stringificaiton and fixup dllpostfix issues.
Rename SvgGradientHelper::== to equalTo to avoid overloading issues.
Use the flat GdiPlus API for LineCaps calls.
2012-11-06 11:58:16 +00:00

994 lines
51 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <drawinglayer/processor2d/canvasprocessor.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <com/sun/star/rendering/XCanvas.hpp>
#include <vcl/canvastools.hxx>
#include <basegfx/tools/canvastools.hxx>
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <canvas/canvastools.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <basegfx/polygon/b2dpolygonclipper.hxx>
#include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
#include <cppcanvas/basegfxfactory.hxx>
#include <com/sun/star/rendering/XBitmapCanvas.hpp>
#include <cppcanvas/vclfactory.hxx>
#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
#include <drawinglayer/primitive2d/textprimitive2d.hxx>
#include <com/sun/star/rendering/TextDirection.hpp>
#include <vclhelperbitmaptransform.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
#include <basegfx/tuple/b2i64tuple.hxx>
#include <basegfx/range/b2irange.hxx>
#include <com/sun/star/rendering/XIntegerReadOnlyBitmap.hpp>
#include <com/sun/star/rendering/PanoseProportion.hpp>
#include <com/sun/star/rendering/CompositeOperation.hpp>
#include <com/sun/star/rendering/StrokeAttributes.hpp>
#include <com/sun/star/rendering/PathJoinType.hpp>
#include <com/sun/star/rendering/PathCapType.hpp>
#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
#include <com/sun/star/rendering/TexturingMode.hpp>
#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
#include <vclhelperbufferdevice.hxx>
#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
#include <helperwrongspellrenderer.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include "getdigitlanguage.hxx"
//////////////////////////////////////////////////////////////////////////////
using namespace com::sun::star;
//////////////////////////////////////////////////////////////////////////////
namespace drawinglayer
{
namespace processor2d
{
//////////////////////////////////////////////////////////////////////////////
// single primitive renderers
void canvasProcessor2D::impRenderMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate)
{
const primitive2d::Primitive2DSequence& rChildren = rMaskCandidate.getChildren();
static bool bUseMaskBitmapMethod(true);
if(rChildren.hasElements())
{
basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
if(!aMask.count())
{
// no mask, no clipping. recursively paint content
process(rChildren);
}
else
{
// there are principally two methods for implementing the mask primitive. One
// is to set a clip polygon at the canvas, the other is to create and use a
// transparence-using XBitmap for content and draw the mask as transparence. Both have their
// advantages and disadvantages, so here are both with a bool allowing simple
// change
if(bUseMaskBitmapMethod)
{
// get logic range of transparent part, clip with ViewRange
basegfx::B2DRange aLogicRange(aMask.getB2DRange());
if(!getViewInformation2D().getViewport().isEmpty())
{
aLogicRange.intersect(getViewInformation2D().getViewport());
}
if(!aLogicRange.isEmpty())
{
// get discrete range of transparent part
basegfx::B2DRange aDiscreteRange(aLogicRange);
aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation());
// expand to next covering discrete values (pixel bounds)
aDiscreteRange.expand(basegfx::B2DTuple(floor(aDiscreteRange.getMinX()), floor(aDiscreteRange.getMinY())));
aDiscreteRange.expand(basegfx::B2DTuple(ceil(aDiscreteRange.getMaxX()), ceil(aDiscreteRange.getMaxY())));
// use VCL-based buffer device
impBufferDevice aBufferDevice(*mpOutputDevice, aDiscreteRange, false);
if(aBufferDevice.isVisible())
{
// remember current OutDev, Canvas and ViewInformation
OutputDevice* pLastOutputDevice = mpOutputDevice;
uno::Reference< rendering::XCanvas > xLastCanvas(mxCanvas);
const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
// prepare discrete offset for XBitmap, do not forget that the buffer bitmap
// may be truncated to discrete visible pixels
const basegfx::B2DHomMatrix aDiscreteOffset(basegfx::tools::createTranslateB2DHomMatrix(
aDiscreteRange.getMinX() > 0.0 ? -aDiscreteRange.getMinX() : 0.0,
aDiscreteRange.getMinY() > 0.0 ? -aDiscreteRange.getMinY() : 0.0));
// create new local ViewInformation2D with new transformation
const geometry::ViewInformation2D aViewInformation2D(
getViewInformation2D().getObjectTransformation(),
aDiscreteOffset * getViewInformation2D().getViewTransformation(),
getViewInformation2D().getViewport(),
getViewInformation2D().getVisualizedPage(),
getViewInformation2D().getViewTime(),
getViewInformation2D().getExtendedInformationSequence());
updateViewInformation(aViewInformation2D);
// set OutDev and Canvas to content target
mpOutputDevice = &aBufferDevice.getContent();
mxCanvas = mpOutputDevice->GetCanvas();
canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
// if ViewState transform is changed, the clipping polygon needs to be adapted, too
const basegfx::B2DPolyPolygon aOldClipPolyPolygon(maClipPolyPolygon);
if(maClipPolyPolygon.count())
{
maClipPolyPolygon.transform(aDiscreteOffset);
maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
}
// paint content
process(rChildren);
// draw mask
const basegfx::BColor aBlack(0.0, 0.0, 0.0);
maRenderState.DeviceColor = aBlack.colorToDoubleSequence(mxCanvas->getDevice());
if(getOptionsDrawinglayer().IsAntiAliasing())
{
// with AA, use 8bit AlphaMask to get nice borders
VirtualDevice& rTransparence = aBufferDevice.getTransparence();
rTransparence.GetCanvas()->fillPolyPolygon(
basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), aMask),
maViewState, maRenderState);
}
else
{
// No AA, use 1bit mask
VirtualDevice& rMask = aBufferDevice.getMask();
rMask.GetCanvas()->fillPolyPolygon(
basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), aMask),
maViewState, maRenderState);
}
// back to old color stack, OutDev, Canvas and ViewTransform
mpOutputDevice = pLastOutputDevice;
mxCanvas = xLastCanvas;
updateViewInformation(aLastViewInformation2D);
canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
// restore clipping polygon
maClipPolyPolygon = aOldClipPolyPolygon;
if(maClipPolyPolygon.count())
{
maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
}
// dump buffer to outdev
aBufferDevice.paint();
}
}
}
else
{
// transform new mask polygon to view coordinates for processing. All masks
// are processed in view coordinates and clipped against each other evtl. to
// create multi-clips
aMask.transform(getViewInformation2D().getObjectTransformation());
// remember last current clip polygon
const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon);
if(maClipPolyPolygon.count())
{
// there is already a clip polygon set; build clipped union of
// current mask polygon and new one
maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(aMask, maClipPolyPolygon, false, false);
}
else
{
// use mask directly
maClipPolyPolygon = aMask;
}
// set at ViewState
if(maClipPolyPolygon.count())
{
// set new as clip polygon
maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
}
else
{
// empty, reset
maViewState.Clip.clear();
}
// paint content
process(rChildren);
// restore local current to rescued clip polygon
maClipPolyPolygon = aLastClipPolyPolygon;
// set at ViewState
if(maClipPolyPolygon.count())
{
// set new as clip polygon
maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
}
else
{
// empty, reset
maViewState.Clip.clear();
}
}
}
}
}
void canvasProcessor2D::impRenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rMetaCandidate)
{
GDIMetaFile aMetaFile;
if(maBColorModifierStack.count())
{
const basegfx::BColor aRGBBaseColor(0, 0, 0);
const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor));
aMetaFile = rMetaCandidate.getMetaFile().GetMonochromeMtf(Color(aRGBColor));
}
else
{
aMetaFile = rMetaCandidate.getMetaFile();
}
cppcanvas::BitmapCanvasSharedPtr pCanvas(cppcanvas::VCLFactory::getInstance().createCanvas(
uno::Reference<rendering::XBitmapCanvas>(mxCanvas, uno::UNO_QUERY_THROW)));
cppcanvas::RendererSharedPtr pMtfRenderer(cppcanvas::VCLFactory::getInstance().createRenderer(
pCanvas, aMetaFile, cppcanvas::Renderer::Parameters()));
if(pMtfRenderer)
{
pCanvas->setTransformation(getViewInformation2D().getObjectToViewTransformation());
pMtfRenderer->setTransformation(rMetaCandidate.getTransform());
pMtfRenderer->draw();
}
}
void canvasProcessor2D::impRenderTextSimplePortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate)
{
if(rTextCandidate.getTextLength())
{
double fShearX(0.0);
{
const basegfx::B2DHomMatrix aLocalTransform(getViewInformation2D().getObjectToViewTransformation() * rTextCandidate.getTextTransform());
basegfx::B2DVector aScale, aTranslate;
double fRotate;
aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
}
if(!basegfx::fTools::equalZero(fShearX))
{
// text is sheared. As long as the canvas renderers do not support this,
// use the decomposed primitive
process(rTextCandidate.get2DDecomposition(getViewInformation2D()));
}
else
{
const attribute::FontAttribute& rFontAttr(rTextCandidate.getFontAttribute());
rendering::FontRequest aFontRequest;
aFontRequest.FontDescription.FamilyName = rFontAttr.getFamilyName();
aFontRequest.FontDescription.StyleName = rFontAttr.getStyleName();
aFontRequest.FontDescription.IsSymbolFont = rFontAttr.getSymbol() ? util::TriState_YES : util::TriState_NO;
aFontRequest.FontDescription.IsVertical = rFontAttr.getVertical() ? util::TriState_YES : util::TriState_NO;
// TODO(F2): improve vclenum->panose conversion
aFontRequest.FontDescription.FontDescription.Weight = static_cast< sal_uInt8 >(rFontAttr.getWeight());
aFontRequest.FontDescription.FontDescription.Proportion =
rFontAttr.getMonospaced()
? rendering::PanoseProportion::MONO_SPACED
: rendering::PanoseProportion::ANYTHING;
aFontRequest.FontDescription.FontDescription.Letterform = rFontAttr.getItalic() ? 9 : 0;
// init CellSize to 1.0, else a default font height will be used
aFontRequest.CellSize = 1.0;
aFontRequest.Locale = rTextCandidate.getLocale();
// font matrix should only be used for glyph rotations etc.
com::sun::star::geometry::Matrix2D aFontMatrix;
canvas::tools::setIdentityMatrix2D(aFontMatrix);
uno::Reference<rendering::XCanvasFont> xFont(mxCanvas->createFont(
aFontRequest, uno::Sequence< beans::PropertyValue >(), aFontMatrix));
if(xFont.is())
{
// got a font, now try to get a TextLayout
const rendering::StringContext aStringContext(
rTextCandidate.getText(), rTextCandidate.getTextPosition(), rTextCandidate.getTextLength());
uno::Reference<rendering::XTextLayout> xLayout(xFont->createTextLayout(
aStringContext, com::sun::star::rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0));
if(xLayout.is())
{
// got a text layout, apply DXArray if given
const ::std::vector< double >& rDXArray = rTextCandidate.getDXArray();
const sal_uInt32 nDXCount(rDXArray.size());
if(nDXCount)
{
// DXArray does not need to be adapted to getTextPosition/getTextLength,
// it is already provided correctly
const uno::Sequence< double > aDXSequence(&rDXArray[0], nDXCount);
xLayout->applyLogicalAdvancements(aDXSequence);
}
// set text color
const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rTextCandidate.getFontColor()));
maRenderState.DeviceColor = aRGBColor.colorToDoubleSequence(mxCanvas->getDevice());
// set text transformation
canvas::tools::setRenderStateTransform(maRenderState,
getViewInformation2D().getObjectTransformation() * rTextCandidate.getTextTransform());
// paint
mxCanvas->drawTextLayout(xLayout, maViewState, maRenderState);
}
}
}
}
}
void canvasProcessor2D::impRenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
{
// apply possible color modification to BitmapEx
BitmapEx aModifiedBitmapEx(impModifyBitmapEx(maBColorModifierStack, rBitmapCandidate.getBitmapEx()));
if(aModifiedBitmapEx.IsEmpty())
{
// replace with color filled polygon
const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
const basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon());
maRenderState.DeviceColor = aModifiedColor.colorToDoubleSequence(mxCanvas->getDevice());
canvas::tools::setRenderStateTransform(maRenderState,
getViewInformation2D().getObjectTransformation() * rBitmapCandidate.getTransform());
mxCanvas->fillPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aPolygon)), maViewState, maRenderState);
}
else
{
// adapt object's transformation to the correct scale
basegfx::B2DVector aScale, aTranslate;
const Size aSizePixel(aModifiedBitmapEx.GetSizePixel());
if(0 != aSizePixel.Width() && 0 != aSizePixel.Height())
{
double fRotate, fShearX;
rBitmapCandidate.getTransform().decompose(aScale, aTranslate, fRotate, fShearX);
const basegfx::B2DHomMatrix aNewMatrix(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
aScale.getX() / aSizePixel.Width(), aScale.getY() / aSizePixel.Height(),
fShearX, fRotate, aTranslate.getX(), aTranslate.getY()));
canvas::tools::setRenderStateTransform(maRenderState,
getViewInformation2D().getObjectTransformation() * aNewMatrix);
mxCanvas->drawBitmap(
vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(), aModifiedBitmapEx),
maViewState, maRenderState);
}
}
}
void canvasProcessor2D::impRenderTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D& rTransparenceCandidate)
{
const primitive2d::Primitive2DSequence& rChildren = rTransparenceCandidate.getChildren();
const primitive2d::Primitive2DSequence& rTransparence = rTransparenceCandidate.getTransparence();
if(rChildren.hasElements() && rTransparence.hasElements())
{
// get logic range of transparent part and clip with ViewRange
basegfx::B2DRange aLogicRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rChildren, getViewInformation2D()));
if(!getViewInformation2D().getViewport().isEmpty())
{
aLogicRange.intersect(getViewInformation2D().getViewport());
}
if(!aLogicRange.isEmpty())
{
// get discrete range of transparent part
basegfx::B2DRange aDiscreteRange(aLogicRange);
aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation());
// expand to next covering discrete values (pixel bounds)
aDiscreteRange.expand(basegfx::B2DTuple(floor(aDiscreteRange.getMinX()), floor(aDiscreteRange.getMinY())));
aDiscreteRange.expand(basegfx::B2DTuple(ceil(aDiscreteRange.getMaxX()), ceil(aDiscreteRange.getMaxY())));
// use VCL-based buffer device
impBufferDevice aBufferDevice(*mpOutputDevice, aDiscreteRange, false);
if(aBufferDevice.isVisible())
{
// remember current OutDev, Canvas and ViewInformation
OutputDevice* pLastOutputDevice = mpOutputDevice;
uno::Reference< rendering::XCanvas > xLastCanvas(mxCanvas);
const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
// prepare discrete offset for XBitmap, do not forget that the buffer bitmap
// may be truncated to discrete visible pixels
const basegfx::B2DHomMatrix aDiscreteOffset(basegfx::tools::createTranslateB2DHomMatrix(
aDiscreteRange.getMinX() > 0.0 ? -aDiscreteRange.getMinX() : 0.0,
aDiscreteRange.getMinY() > 0.0 ? -aDiscreteRange.getMinY() : 0.0));
// create new local ViewInformation2D with new transformation
const geometry::ViewInformation2D aViewInformation2D(
getViewInformation2D().getObjectTransformation(),
aDiscreteOffset * getViewInformation2D().getViewTransformation(),
getViewInformation2D().getViewport(),
getViewInformation2D().getVisualizedPage(),
getViewInformation2D().getViewTime(),
getViewInformation2D().getExtendedInformationSequence());
updateViewInformation(aViewInformation2D);
// set OutDev and Canvas to content target
mpOutputDevice = &aBufferDevice.getContent();
mxCanvas = mpOutputDevice->GetCanvas();
canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
// if ViewState transform is changed, the clipping polygon needs to be adapted, too
const basegfx::B2DPolyPolygon aOldClipPolyPolygon(maClipPolyPolygon);
if(maClipPolyPolygon.count())
{
maClipPolyPolygon.transform(aDiscreteOffset);
maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
}
// paint content
process(rChildren);
// set to mask
mpOutputDevice = &aBufferDevice.getTransparence();
mxCanvas = mpOutputDevice->GetCanvas();
canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
// when painting transparence masks, reset the color stack
basegfx::BColorModifierStack aLastBColorModifierStack(maBColorModifierStack);
maBColorModifierStack = basegfx::BColorModifierStack();
// paint mask to it (always with transparence intensities, evtl. with AA)
process(rTransparence);
// back to old color stack, OutDev, Canvas and ViewTransform
maBColorModifierStack = aLastBColorModifierStack;
mpOutputDevice = pLastOutputDevice;
mxCanvas = xLastCanvas;
updateViewInformation(aLastViewInformation2D);
canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
// restore clipping polygon
maClipPolyPolygon = aOldClipPolyPolygon;
if(maClipPolyPolygon.count())
{
maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
}
// dump buffer to outdev
aBufferDevice.paint();
}
}
}
}
void canvasProcessor2D::impRenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive)
{
// support direct fat line geometry. This moves the decomposition to the canvas.
// As long as our canvases are used (which also use basegfx tooling) this makes
// no difference, but potentially canvases may better support this
static bool bSupportFatLineDirectly(true);
bool bOutputDone(false);
if(bSupportFatLineDirectly)
{
const attribute::LineAttribute& rLineAttribute = rPolygonStrokePrimitive.getLineAttribute();
const attribute::StrokeAttribute& rStrokeAttribute = rPolygonStrokePrimitive.getStrokeAttribute();
if(0.0 < rLineAttribute.getWidth() || 0 != rStrokeAttribute.getDotDashArray().size())
{
rendering::StrokeAttributes aStrokeAttribute;
aStrokeAttribute.StrokeWidth = rLineAttribute.getWidth();
aStrokeAttribute.MiterLimit = 15.0; // degrees; maybe here (15.0 * F_PI180) is needed, not clear in the documentation
const ::std::vector< double >& rDotDashArray = rStrokeAttribute.getDotDashArray();
if(!rDotDashArray.empty())
{
aStrokeAttribute.DashArray = uno::Sequence< double >(&rDotDashArray[0], rDotDashArray.size());
}
switch(rLineAttribute.getLineJoin())
{
default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE
aStrokeAttribute.JoinType = rendering::PathJoinType::NONE;
break;
case basegfx::B2DLINEJOIN_BEVEL:
aStrokeAttribute.JoinType = rendering::PathJoinType::BEVEL;
break;
case basegfx::B2DLINEJOIN_MITER:
aStrokeAttribute.JoinType = rendering::PathJoinType::MITER;
break;
case basegfx::B2DLINEJOIN_ROUND:
aStrokeAttribute.JoinType = rendering::PathJoinType::ROUND;
break;
}
switch(rLineAttribute.getLineCap())
{
case com::sun::star::drawing::LineCap_ROUND:
aStrokeAttribute.StartCapType = rendering::PathCapType::ROUND;
aStrokeAttribute.EndCapType = rendering::PathCapType::ROUND;
break;
case com::sun::star::drawing::LineCap_SQUARE:
aStrokeAttribute.StartCapType = rendering::PathCapType::SQUARE;
aStrokeAttribute.EndCapType = rendering::PathCapType::SQUARE;
break;
default: // com::sun::star::drawing::LineCap_BUTT
aStrokeAttribute.StartCapType = rendering::PathCapType::BUTT;
aStrokeAttribute.EndCapType = rendering::PathCapType::BUTT;
break;
}
const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLineAttribute.getColor()));
maRenderState.DeviceColor = aHairlineColor.colorToDoubleSequence(mxCanvas->getDevice());
canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
mxCanvas->strokePolyPolygon(
basegfx::unotools::xPolyPolygonFromB2DPolygon(mxCanvas->getDevice(), rPolygonStrokePrimitive.getB2DPolygon()),
maViewState, maRenderState, aStrokeAttribute);
bOutputDone = true;
}
}
if(!bOutputDone)
{
// process decomposition
process(rPolygonStrokePrimitive.get2DDecomposition(getViewInformation2D()));
}
}
void canvasProcessor2D::impRenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapPrimitive2D)
{
// support tiled fills directly when tiling is on
static bool bSupportFillBitmapDirectly(true);
bool bOutputDone(false);
if(bSupportFillBitmapDirectly)
{
const attribute::FillBitmapAttribute& rFillBitmapAttribute = rFillBitmapPrimitive2D.getFillBitmap();
if(rFillBitmapAttribute.getTiling())
{
// apply possible color modification to Bitmap
const BitmapEx aChangedBitmapEx(impModifyBitmapEx(maBColorModifierStack, rFillBitmapAttribute.getBitmapEx()));
if(aChangedBitmapEx.IsEmpty())
{
// replace with color filled polygon
const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
const basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon());
maRenderState.DeviceColor = aModifiedColor.colorToDoubleSequence(mxCanvas->getDevice());
canvas::tools::setRenderStateTransform(maRenderState,
getViewInformation2D().getObjectTransformation() * rFillBitmapPrimitive2D.getTransformation());
mxCanvas->fillPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aPolygon)), maViewState, maRenderState);
}
else
{
const Size aSizePixel(aChangedBitmapEx.GetSizePixel());
if(0 != aSizePixel.Width() && 0 != aSizePixel.Height())
{
// create texture matrix from texture to object (where object is unit square here),
// so use values directly
const basegfx::B2DHomMatrix aTextureMatrix(basegfx::tools::createScaleTranslateB2DHomMatrix(
rFillBitmapAttribute.getSize().getX(), rFillBitmapAttribute.getSize().getY(),
rFillBitmapAttribute.getTopLeft().getX(), rFillBitmapAttribute.getTopLeft().getY()));
// create and fill texture
rendering::Texture aTexture;
basegfx::unotools::affineMatrixFromHomMatrix(aTexture.AffineTransform, aTextureMatrix);
aTexture.Alpha = 1.0;
aTexture.Bitmap = vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(), aChangedBitmapEx);
aTexture.RepeatModeX = rendering::TexturingMode::REPEAT;
aTexture.RepeatModeY = rendering::TexturingMode::REPEAT;
// canvas needs a polygon to fill, create unit rectangle polygon
const basegfx::B2DPolygon aOutlineRectangle(basegfx::tools::createUnitPolygon());
// set primitive's transformation as render state transform
canvas::tools::setRenderStateTransform(maRenderState,
getViewInformation2D().getObjectTransformation() * rFillBitmapPrimitive2D.getTransformation());
// put texture into a uno sequence for handover
uno::Sequence< rendering::Texture > aSeq(1);
aSeq[0] = aTexture;
// draw textured rectangle
mxCanvas->fillTexturedPolyPolygon(
basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aOutlineRectangle)),
maViewState, maRenderState, aSeq);
}
}
bOutputDone = true;
}
}
if(!bOutputDone)
{
// process decomposition
process(rFillBitmapPrimitive2D.get2DDecomposition(getViewInformation2D()));
}
}
void canvasProcessor2D::impRenderUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate)
{
if(0.0 == rUniTransparenceCandidate.getTransparence())
{
// not transparent at all, directly use content
process(rUniTransparenceCandidate.getChildren());
}
else if(rUniTransparenceCandidate.getTransparence() > 0.0 && rUniTransparenceCandidate.getTransparence() < 1.0)
{
const primitive2d::Primitive2DSequence rChildren = rUniTransparenceCandidate.getChildren();
if(rChildren.hasElements())
{
bool bOutputDone(false);
// Detect if a single PolyPolygonColorPrimitive2D is contained; in that case,
// use the fillPolyPolygon method with correctly set transparence. This is a often used
// case, so detectiong it is valuable
if(1 == rChildren.getLength())
{
const primitive2d::Primitive2DReference xReference(rChildren[0]);
const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get());
if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID())
{
// direct draw of PolyPolygon with color and transparence
const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
// add transparence modulation value to DeviceColor
uno::Sequence< double > aColor(4);
aColor[0] = aPolygonColor.getRed();
aColor[1] = aPolygonColor.getGreen();
aColor[2] = aPolygonColor.getBlue();
aColor[3] = 1.0 - rUniTransparenceCandidate.getTransparence();
maRenderState.DeviceColor = aColor;
canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
mxCanvas->fillPolyPolygon(
basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), pPoPoColor->getB2DPolyPolygon()),
maViewState, maRenderState);
bOutputDone = true;
}
}
if(!bOutputDone)
{
// process decomposition. This will be decomposed to an TransparencePrimitive2D
// with the same child context and a single polygon for transparent context. This could be
// directly handled here with known VCL-buffer technology, but would only
// make a small difference compared to directly rendering the TransparencePrimitive2D
// using impRenderTransparencePrimitive2D above.
process(rUniTransparenceCandidate.get2DDecomposition(getViewInformation2D()));
}
}
}
}
//////////////////////////////////////////////////////////////////////////////
// internal processing support
void canvasProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
{
switch(rCandidate.getPrimitive2DID())
{
case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
{
// direct draw of hairline
const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate);
const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
maRenderState.DeviceColor = aHairlineColor.colorToDoubleSequence(mxCanvas->getDevice());
canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
mxCanvas->drawPolyPolygon(
basegfx::unotools::xPolyPolygonFromB2DPolygon(mxCanvas->getDevice(), rPolygonCandidate.getB2DPolygon()),
maViewState, maRenderState);
break;
}
case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
{
// direct draw of PolyPolygon with color
const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate = static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate);
const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
maRenderState.DeviceColor = aPolygonColor.colorToDoubleSequence(mxCanvas->getDevice());
canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
mxCanvas->fillPolyPolygon(
basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), rPolygonCandidate.getB2DPolyPolygon()),
maViewState, maRenderState);
break;
}
case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
{
// modified color group. Force output to unified color.
const primitive2d::ModifiedColorPrimitive2D& rModifiedCandidate = static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate);
if(rModifiedCandidate.getChildren().hasElements())
{
maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
process(rModifiedCandidate.getChildren());
maBColorModifierStack.pop();
}
break;
}
case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
{
// mask group
impRenderMaskPrimitive2D(static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate));
break;
}
case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
{
// transform group. Remember current ViewInformation2D
const primitive2d::TransformPrimitive2D& rTransformCandidate = static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate);
const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
// create new local ViewInformation2D with new transformation
const geometry::ViewInformation2D aViewInformation2D(
getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
getViewInformation2D().getViewTransformation(),
getViewInformation2D().getViewport(),
getViewInformation2D().getVisualizedPage(),
getViewInformation2D().getViewTime(),
getViewInformation2D().getExtendedInformationSequence());
updateViewInformation(aViewInformation2D);
// set at canvas
canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
// proccess content
process(rTransformCandidate.getChildren());
// restore transformations
updateViewInformation(aLastViewInformation2D);
// restore at canvas
canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
break;
}
case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
{
// new XDrawPage for ViewInformation2D
const primitive2d::PagePreviewPrimitive2D& rPagePreviewCandidate = static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate);
// remember current transformation and ViewInformation
const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
// create new local ViewInformation2D
const geometry::ViewInformation2D aViewInformation2D(
getViewInformation2D().getObjectTransformation(),
getViewInformation2D().getViewTransformation(),
getViewInformation2D().getViewport(),
rPagePreviewCandidate.getXDrawPage(),
getViewInformation2D().getViewTime(),
getViewInformation2D().getExtendedInformationSequence());
updateViewInformation(aViewInformation2D);
// proccess decomposed content
process(rPagePreviewCandidate.get2DDecomposition(getViewInformation2D()));
// restore transformations
updateViewInformation(aLastViewInformation2D);
break;
}
case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
{
// MetaFile primitive
impRenderMetafilePrimitive2D(static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate));
break;
}
case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
{
// PointArray primitive
const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate = static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate);
// set point color
const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rPointArrayCandidate.getRGBColor()));
maRenderState.DeviceColor = aRGBColor.colorToDoubleSequence(mxCanvas->getDevice());
canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
const std::vector< basegfx::B2DPoint >& rPointVector = rPointArrayCandidate.getPositions();
const sal_uInt32 nPointCount(rPointVector.size());
for(sal_uInt32 a(0); a < nPointCount; a++)
{
const basegfx::B2DPoint& rPoint = rPointVector[a];
mxCanvas->drawPoint(basegfx::unotools::point2DFromB2DPoint(rPoint), maViewState, maRenderState);
}
break;
}
case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
{
// TextSimplePortion primitive
impRenderTextSimplePortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate));
break;
}
case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
{
// Bitmap primitive
impRenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
break;
}
case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D :
{
// Transparence primitive
impRenderTransparencePrimitive2D(static_cast< const primitive2d::TransparencePrimitive2D& >(rCandidate));
break;
}
case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
{
// PolygonStrokePrimitive
impRenderPolygonStrokePrimitive2D(static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate));
break;
}
case PRIMITIVE2D_ID_FILLBITMAPPRIMITIVE2D :
{
// FillBitmapPrimitive2D
impRenderFillBitmapPrimitive2D(static_cast< const primitive2d::FillBitmapPrimitive2D& >(rCandidate));
break;
}
case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D :
{
// UnifiedTransparencePrimitive2D
impRenderUnifiedTransparencePrimitive2D(static_cast< const primitive2d::UnifiedTransparencePrimitive2D& >(rCandidate));
break;
}
case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
{
// wrong spell primitive. Handled directly here using VCL since VCL has a nice and
// very direct waveline painting which is needed for this. If VCL is to be avoided,
// this can be removed anytime and the decomposition may be used
const primitive2d::WrongSpellPrimitive2D& rWrongSpellPrimitive = static_cast< const primitive2d::WrongSpellPrimitive2D& >(rCandidate);
if(!renderWrongSpellPrimitive2D(
rWrongSpellPrimitive,
*mpOutputDevice,
getViewInformation2D().getObjectToViewTransformation(),
maBColorModifierStack))
{
// fallback to decomposition (MetaFile)
process(rWrongSpellPrimitive.get2DDecomposition(getViewInformation2D()));
}
break;
}
// nice to have:
//
// case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
// - support FormControls more direct eventually, not sure if this is needed
// with the canvas renderer. The decomposition provides a bitmap representation
// of the control which will work
//
default :
{
// process recursively
process(rCandidate.get2DDecomposition(getViewInformation2D()));
break;
}
}
}
//////////////////////////////////////////////////////////////////////////////
// process support
canvasProcessor2D::canvasProcessor2D(
const geometry::ViewInformation2D& rViewInformation,
OutputDevice& rOutDev)
: BaseProcessor2D(rViewInformation),
mpOutputDevice(&rOutDev),
mxCanvas(rOutDev.GetCanvas()),
maViewState(),
maRenderState(),
maBColorModifierStack(),
maDrawinglayerOpt(),
maClipPolyPolygon(),
meLang(drawinglayer::detail::getDigitLanguage())
{
canvas::tools::initViewState(maViewState);
canvas::tools::initRenderState(maRenderState);
canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
// set digit language, derived from SvtCTLOptions to have the correct
// number display for arabic/hindi numerals
rOutDev.SetDigitLanguage(meLang);
// prepare output directly to pixels
mpOutputDevice->Push(PUSH_MAPMODE);
mpOutputDevice->SetMapMode();
// react on AntiAliasing settings
if(getOptionsDrawinglayer().IsAntiAliasing())
{
mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW);
}
else
{
mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW);
}
}
canvasProcessor2D::~canvasProcessor2D()
{
// restore MapMode
mpOutputDevice->Pop();
// restore AntiAliasing
mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW);
}
} // end of namespace processor2d
} // end of namespace drawinglayer
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */