[Libreoffice-commits] core.git: Branch 'feature/slideshowprimitives' - drawinglayer/Library_drawinglayer.mk drawinglayer/source include/drawinglayer

Thorsten Behrens tbehrens at suse.com
Thu Oct 10 14:30:12 PDT 2013


Rebased ref, commits from common ancestor:
commit 6d8f77beefe95d0e6f3075f16aba3e0a14a0e9f3
Author: Thorsten Behrens <tbehrens at suse.com>
Date:   Thu Oct 10 23:21:55 2013 +0200

    First cut at resuscitating primitive2canvas processor.
    
    Change-Id: Ib7b3277bf9a98c07771f70ae1d0d3c2d48def813

diff --git a/drawinglayer/Library_drawinglayer.mk b/drawinglayer/Library_drawinglayer.mk
index 21242a6..2308200 100644
--- a/drawinglayer/Library_drawinglayer.mk
+++ b/drawinglayer/Library_drawinglayer.mk
@@ -137,6 +137,7 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\
     drawinglayer/source/primitive3d/transformprimitive3d \
     drawinglayer/source/processor2d/baseprocessor2d \
 	drawinglayer/source/processor2d/processor2dtools \
+    drawinglayer/source/processor2d/canvasprocessor2d \
     drawinglayer/source/processor2d/contourextractor2d \
     drawinglayer/source/processor2d/getdigitlanguage \
     drawinglayer/source/processor2d/helperwrongspellrenderer \
diff --git a/drawinglayer/source/processor2d/canvasprocessor2d.cxx b/drawinglayer/source/processor2d/canvasprocessor2d.cxx
new file mode 100644
index 0000000..a9559be
--- /dev/null
+++ b/drawinglayer/source/processor2d/canvasprocessor2d.cxx
@@ -0,0 +1,1101 @@
+/* -*- 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/canvasprocessor2d.hxx"
+
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/backgroundcolorprimitive2d.hxx>
+#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
+#include <drawinglayer/primitive2d/textprimitive2d.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
+#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
+#include <com/sun/star/rendering/TextDirection.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.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 <com/sun/star/rendering/TexturingMode.hpp>
+
+#include <com/sun/star/geometry/Matrix2D.hpp>
+#include <com/sun/star/geometry/IntegerSize2D.hpp>
+#include <com/sun/star/geometry/IntegerRectangle2D.hpp>
+
+#include <canvas/canvastools.hxx>
+#include <vcl/canvastools.hxx>
+#include <vcl/graph.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/tuple/b2i64tuple.hxx>
+#include <basegfx/range/b2irange.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+#include "getdigitlanguage.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+    namespace processor2d
+    {
+        //////////////////////////////////////////////////////////////////////////////
+        // single primitive renderers
+
+        void CanvasProcessor2D::impRenderTextSimpleOrDecoratedPortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate)
+        {
+            if(rTextCandidate.getTextLength())
+            {
+                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.
+                css::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,
+                            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()));
+                        maVolatileRenderState.DeviceColor =
+                            aRGBColor.colorToDoubleSequence(mxCanvas->getDevice());
+
+                        // set text transformation
+                        canvas::tools::setRenderStateTransform(maVolatileRenderState,
+                                                               getViewInformation2D().getObjectTransformation() * rTextCandidate.getTextTransform());
+
+                        // paint
+                        mxCanvas->drawTextLayout(xLayout, maViewState, maVolatileRenderState);
+
+                        // and restore
+                        canvas::tools::setRenderStateTransform(
+                            maVolatileRenderState,
+                            getViewInformation2D().getObjectTransformation());
+                    }
+                }
+            }
+        }
+
+        void CanvasProcessor2D::impRenderPolygonHairlinePrimitive2D(const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate)
+        {
+            const basegfx::BColor aHairlineColor(
+                maBColorModifierStack.getModifiedColor(
+                    rPolygonCandidate.getBColor()));
+
+            maVolatileRenderState.DeviceColor = aHairlineColor.colorToDoubleSequence(
+                mxCanvas->getDevice());
+
+            mxCanvas->drawPolyPolygon(
+                basegfx::unotools::xPolyPolygonFromB2DPolygon(
+                    mxCanvas->getDevice(),
+                    rPolygonCandidate.getB2DPolygon()),
+                maViewState,  maVolatileRenderState);
+        }
+
+        void CanvasProcessor2D::impRenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
+        {
+            BitmapEx aBitmapEx(rBitmapCandidate.getBitmapEx());
+            if(maBColorModifierStack.count())
+            {
+                aBitmapEx = aBitmapEx.ModifyBitmapEx(maBColorModifierStack);
+                if(aBitmapEx.IsEmpty())
+                {
+                    // replace with color filled polygon
+                    const basegfx::BColor aModifiedColor(
+                        maBColorModifierStack.getModifiedColor(basegfx::BColor()));
+                    const basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon());
+
+                    maVolatileRenderState.DeviceColor = aModifiedColor.colorToDoubleSequence(
+                        mxCanvas->getDevice());
+                    canvas::tools::setRenderStateTransform(
+                        maVolatileRenderState,
+                        getViewInformation2D().getObjectTransformation() *
+                        rBitmapCandidate.getTransform());
+
+                    mxCanvas->fillPolyPolygon(
+                        basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+                            mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aPolygon)),
+                        maViewState,  maVolatileRenderState);
+
+                    // and restore
+                    canvas::tools::setRenderStateTransform(
+                        maVolatileRenderState,
+                        getViewInformation2D().getObjectTransformation());
+
+                    return;
+                }
+            }
+
+            // adapt object's transformation to the correct scale
+            basegfx::B2DVector aScale, aTranslate;
+            const Size aSizePixel(aBitmapEx.GetSizePixel());
+
+            if(0 != aSizePixel.Width() && 0 != aSizePixel.Height())
+            {
+                // scale object transform with bitmap matrix (and
+                // align with canvas conventions, which places bitmaps
+                // into [0,1]^2 unit range
+                canvas::tools::setRenderStateTransform(
+                    maVolatileRenderState,
+                    getViewInformation2D().getObjectTransformation()
+                    * rBitmapCandidate.getTransform()
+                    * basegfx::tools::createScaleB2DHomMatrix(
+                        basegfx::B2DTuple(1.0/aSizePixel.Width(),
+                                          1.0/aSizePixel.Height())) );
+
+                mxCanvas->drawBitmap(
+                    vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(),
+                                                       aBitmapEx),
+                    maViewState, maVolatileRenderState);
+
+                // and restore
+                canvas::tools::setRenderStateTransform(
+                    maVolatileRenderState,
+                    getViewInformation2D().getObjectTransformation());
+            }
+        }
+
+        void CanvasProcessor2D::impRenderFillGraphicPrimitive2D(const primitive2d::FillGraphicPrimitive2D& rFillBitmapCandidate)
+        {
+            // TODO(P2): if we've a plain bitmap fill, use XCanvas
+            // texturing. Otherwise, fallback to decomposition
+            // if( rFillGraphicAttribute.getTiling()
+            //     && GRAPHIC_BITMAP == rFillGraphicAttribute.getGraphic().GetType()
+            //     && !rFillGraphicAttribute.getGraphic().getSvgData().get()
+            //     && !rFillGraphicAttribute.getGraphic().IsAnimated() )
+            // {
+            // }
+            process(rFillBitmapCandidate.get2DDecomposition(getViewInformation2D()));
+        }
+
+        void CanvasProcessor2D::impRenderPolyPolygonGraphicPrimitive2D(const primitive2d::PolyPolygonGraphicPrimitive2D& rPolygonCandidate)
+        {
+            const basegfx::B2DPolyPolygon& rPolyPolygon = rPolygonCandidate.getB2DPolyPolygon();
+            if(!rPolyPolygon.count())
+                return; // clearly a no-op
+
+            const attribute::FillGraphicAttribute& rFillGraphicAttribute =
+                rPolygonCandidate.getFillGraphic();
+
+            // try to catch cases where the graphic will be color-modified to a single
+            // color (e.g. shadow)
+            if( GRAPHIC_BITMAP == rFillGraphicAttribute.getGraphic().GetType() )
+            {
+                if( !rFillGraphicAttribute.getGraphic().IsTransparent()
+                    && !rFillGraphicAttribute.getGraphic().IsAlpha())
+                {
+                    // bitmap is not transparent and has no alpha
+                    const sal_uInt32 nBColorModifierStackCount(maBColorModifierStack.count());
+                    if(nBColorModifierStackCount)
+                    {
+                        const basegfx::BColorModifier& rTopmostModifier =
+                            maBColorModifierStack.getBColorModifier(
+                                nBColorModifierStackCount - 1);
+
+                        if(basegfx::BCOLORMODIFYMODE_REPLACE == rTopmostModifier.getMode())
+                        {
+                            // the bitmap fill is in unified color, so we can replace it with
+                            // a single polygon fill. The form of the fill depends on tiling
+                            if(rFillGraphicAttribute.getTiling())
+                            {
+                                // with tiling, fill the whole PolyPolygon with the modifier color
+                                const basegfx::BColor aPolygonColor(
+                                    rTopmostModifier.getBColor());
+
+                                maVolatileRenderState.DeviceColor =
+                                    aPolygonColor.colorToDoubleSequence(
+                                        mxCanvas->getDevice());
+
+                                mxCanvas->fillPolyPolygon(
+                                    basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+                                        mxCanvas->getDevice(),
+                                        rPolyPolygon),
+                                    maViewState,  maVolatileRenderState);
+                            }
+                            else
+                            {
+                                // without tiling, only the area common to the bitmap tile and the
+                                // PolyPolygon is filled. Create the bitmap tile area in object
+                                // coordinates. For this, the object transformation needs to be created
+                                // from the already scaled PolyPolygon. The tile area in object
+                                // coordinates wil always be non-rotated, so it's not necessary to
+                                // work with a polygon here
+                                basegfx::B2DRange aTileRange(rFillGraphicAttribute.getGraphicRange());
+                                const basegfx::B2DRange aPolyPolygonRange(rPolyPolygon.getB2DRange());
+                                const basegfx::B2DHomMatrix aNewObjectTransform(
+                                    basegfx::tools::createScaleTranslateB2DHomMatrix(
+                                        aPolyPolygonRange.getRange(),
+                                        aPolyPolygonRange.getMinimum()));
+
+                                aTileRange.transform(aNewObjectTransform);
+
+                                // now clip the object polyPolygon against the tile range
+                                // to get the common area
+                                basegfx::B2DPolyPolygon aTarget = basegfx::tools::clipPolyPolygonOnRange(
+                                    rPolyPolygon,
+                                    aTileRange,
+                                    true,
+                                    false);
+
+                                if(aTarget.count())
+                                {
+                                    const basegfx::BColor aPolygonColor(
+                                        rTopmostModifier.getBColor());
+
+                                    maVolatileRenderState.DeviceColor =
+                                        aPolygonColor.colorToDoubleSequence(
+                                            mxCanvas->getDevice());
+
+                                    mxCanvas->fillPolyPolygon(
+                                        basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+                                            mxCanvas->getDevice(),
+                                            aTarget),
+                                        maViewState,  maVolatileRenderState);
+                                }
+                            }
+
+                            // rendering done
+                            return;
+                        }
+                    }
+                }
+
+                // TODO(P2): if we've a plain bitmap fill, use XCanvas
+                // texturing. Otherwise, fallback to decomposition
+            }
+
+            // use default decomposition, if all else failed
+            process(rPolygonCandidate.get2DDecomposition(getViewInformation2D()));
+        }
+
+        void CanvasProcessor2D::impRenderPolyPolygonColorPrimitive2D(const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate)
+        {
+            const basegfx::BColor aPolygonColor(
+                maBColorModifierStack.getModifiedColor(
+                    rPolygonCandidate.getBColor()));
+
+            maVolatileRenderState.DeviceColor = aPolygonColor.colorToDoubleSequence(
+                mxCanvas->getDevice());
+
+            mxCanvas->fillPolyPolygon(
+                basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+                    mxCanvas->getDevice(),
+                    rPolygonCandidate.getB2DPolyPolygon()),
+                maViewState,  maVolatileRenderState);
+        }
+
+        void CanvasProcessor2D::impRenderMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate)
+        {
+            const primitive2d::Primitive2DSequence& rChildren = rMaskCandidate.getChildren();
+            if(rChildren.hasElements())
+            {
+                basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
+
+                if(!aMask.count())
+                {
+                    // no mask, no clipping. just paint content as-is
+                    process(rChildren);
+                }
+                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);
+                    const uno::Reference< rendering::XPolyPolygon2D > xLastClipPolyPolygon =
+                        maVolatileRenderState.Clip;
+
+                    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
+                        maVolatileRenderState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+                            mxCanvas->getDevice(), maClipPolyPolygon);
+                    }
+                    else
+                    {
+                        // empty, reset
+                        maVolatileRenderState.Clip.clear();
+                    }
+
+                    // now paint children (clipped to aMask)
+                    process(rChildren);
+
+                    // restore clip
+                    maClipPolyPolygon = aLastClipPolyPolygon;
+                    maVolatileRenderState.Clip = xLastClipPolyPolygon;
+                }
+            }
+        }
+
+        void CanvasProcessor2D::impRenderUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate)
+        {
+            if( !rUniTransparenceCandidate.getChildren().hasElements() )
+                return; // now, that was easy
+
+            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())
+                {
+                    // 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();
+                            maVolatileRenderState.DeviceColor = aColor;
+
+                            mxCanvas->fillPolyPolygon(
+                                basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+                                    mxCanvas->getDevice(),
+                                    pPoPoColor->getB2DPolyPolygon()),
+                                maViewState,  maVolatileRenderState);
+
+                            return; // done
+                        }
+                    }
+
+                    // 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()));
+                }
+            }
+        }
+
+        void CanvasProcessor2D::impRenderTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D& rTransCandidate)
+        {
+            if(rTransCandidate.getChildren().hasElements())
+            {
+                // this is the full mask primitive - render mask
+                // content as alpha, then blit original content
+                // through that alphamask.
+                //
+                // See also http://www.w3.org/TR/SVG/masking.html#Masking
+
+                // how big is the resulting image?
+                const basegfx::B2DRange aRange(primitive2d::getB2DRangeFromPrimitive2DSequence(
+                                                   rTransCandidate.getChildren(),
+                                                   getViewInformation2D()));
+                const basegfx::B2IRange aIntRange(
+                    canvas::tools::spritePixelAreaFromB2DRange(aRange));
+                const css::geometry::IntegerSize2D aMaskSize(
+                    aIntRange.getWidth(), aIntRange.getHeight());
+
+                // TODO(E1): in theory, could also get a float bitmap here...
+                uno::Reference< rendering::XIntegerBitmap > xContent(
+                    mxCanvas->getDevice()->createCompatibleAlphaBitmap(aMaskSize),
+                    uno::UNO_QUERY_THROW);
+
+                // TODO(E1): in theory, could also get a float bitmap here...
+                uno::Reference< rendering::XIntegerBitmap > xMask(
+                    mxCanvas->getDevice()->createCompatibleAlphaBitmap(aMaskSize),
+                    uno::UNO_QUERY_THROW);
+
+                // buffer current XCanvas output instance, then divert
+                // output to content and mask
+                uno::Reference< rendering::XCanvas > xLastCanvas(mxCanvas);
+                mxCanvas.set(xContent, uno::UNO_QUERY_THROW);
+
+                // paint content to it
+                process(rTransCandidate.getChildren());
+
+                // set to mask
+                mxCanvas.set(xMask, uno::UNO_QUERY_THROW);
+
+                // when painting transparence masks, reset the color stack
+                basegfx::BColorModifierStack aLastBColorModifierStack(maBColorModifierStack);
+                maBColorModifierStack = basegfx::BColorModifierStack();
+
+                // paint mask to it
+                process(rTransCandidate.getTransparence());
+
+                // back to old color stack
+                maBColorModifierStack = aLastBColorModifierStack;
+
+                // back to old XCanvas instance
+                mxCanvas = xLastCanvas;
+
+                // now merge the two bitmaps
+                // TODO(P3): the below uses IEEE double images. worst
+                // possible performance to blend masks, evar
+                rendering::IntegerBitmapLayout aMaskLayout;
+                const css::geometry::IntegerRectangle2D aMaskArea(
+                    0,0,
+                    aMaskSize.Width,
+                    aMaskSize.Height);
+                uno::Sequence< rendering::ARGBColor > aARGBMask =
+                    aMaskLayout.ColorSpace->convertIntegerToARGB(
+                        xMask->getData(
+                            aMaskLayout,
+                            aMaskArea));
+                rendering::IntegerBitmapLayout aContentLayout;
+                uno::Sequence< rendering::ARGBColor > aARGBContent =
+                    aContentLayout.ColorSpace->convertIntegerToARGB(
+                        xContent->getData(
+                            aContentLayout,
+                            aMaskArea));
+
+                rendering::ARGBColor* pARGBContent( aARGBContent.getArray() );
+                const rendering::ARGBColor* const pARGBContentEnd(
+                    pARGBContent+aARGBContent.getLength() );
+                const rendering::ARGBColor* pARGBMask( aARGBMask.getConstArray() );
+                while( pARGBContent != pARGBContentEnd )
+                {
+                    // blend mask with content alpha - std sRGB luminance formula below
+                    pARGBContent->Alpha *=
+                        pARGBMask->Alpha * (0.2126*pARGBMask->Red
+                                            + 0.7152*pARGBMask->Green
+                                            + 0.0722*pARGBMask->Blue);
+                    ++pARGBContent;
+                    ++pARGBMask;
+                }
+
+                xContent->setData(
+                    aContentLayout.ColorSpace->convertIntegerFromARGB( aARGBContent ),
+                    aContentLayout,
+                    aMaskArea);
+
+                // render to target - with identity transformation, we
+                // want 1:1 pixel
+                basegfx::B2DHomMatrix aIdentMatrix;
+                canvas::tools::setViewStateTransform(maViewState,
+                                                     aIdentMatrix);
+                canvas::tools::setRenderStateTransform(maVolatileRenderState,
+                                                       aIdentMatrix);
+
+                mxCanvas->drawBitmap(xContent,
+                                     maViewState,
+                                     maVolatileRenderState);
+
+                canvas::tools::setViewStateTransform(maViewState,
+                                                     getViewInformation2D().getViewTransformation());
+                canvas::tools::setRenderStateTransform(maVolatileRenderState,
+                                                       getViewInformation2D().getObjectTransformation());
+            }
+        }
+
+        void CanvasProcessor2D::impRenderTransformPrimitive2D(const primitive2d::TransformPrimitive2D& rTransformCandidate)
+        {
+            // buffer last transform, to later restore it
+            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(maVolatileRenderState,
+                                                   getViewInformation2D().getObjectTransformation());
+
+            // proccess content
+            process(rTransformCandidate.getChildren());
+
+            // restore transformations
+            updateViewInformation(aLastViewInformation2D);
+
+            // restore at canvas
+            canvas::tools::setRenderStateTransform(maVolatileRenderState,
+                                                   getViewInformation2D().getObjectTransformation());
+        }
+
+        void CanvasProcessor2D::impRenderPagePreviewPrimitive2D(const primitive2d::PagePreviewPrimitive2D& rPagePreviewCandidate)
+        {
+            // 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);
+        }
+
+        void CanvasProcessor2D::impRenderPointArrayPrimitive2D(const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate)
+        {
+            // set point color
+            const basegfx::BColor aRGBColor(
+                maBColorModifierStack.getModifiedColor(
+                    rPointArrayCandidate.getRGBColor()));
+            maVolatileRenderState.DeviceColor = aRGBColor.colorToDoubleSequence(
+                mxCanvas->getDevice());
+
+            const std::vector< basegfx::B2DPoint >& rPointVector =
+                rPointArrayCandidate.getPositions();
+            std::vector< basegfx::B2DPoint >::const_iterator aIter=rPointVector.begin();
+            const std::vector< basegfx::B2DPoint >::const_iterator aEnd=rPointVector.end();
+            for( ; aIter != aEnd; ++aIter )
+            {
+                mxCanvas->drawPoint(
+                    basegfx::unotools::point2DFromB2DPoint(*aIter),
+                    maViewState, maVolatileRenderState);
+            }
+        }
+
+        void CanvasProcessor2D::impRenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive)
+        {
+            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 = F_PI180 * 15.0; // 15 degrees
+                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()));
+                maVolatileRenderState.DeviceColor =
+                    aHairlineColor.colorToDoubleSequence(mxCanvas->getDevice());
+
+                mxCanvas->strokePolyPolygon(
+                    basegfx::unotools::xPolyPolygonFromB2DPolygon(
+                        mxCanvas->getDevice(),
+                        rPolygonStrokePrimitive.getB2DPolygon()),
+                    maViewState,  maVolatileRenderState, aStrokeAttribute);
+
+                return; // and done
+            }
+
+            // falback: process decomposition
+            process(rPolygonStrokePrimitive.get2DDecomposition(getViewInformation2D()));
+        }
+
+        void CanvasProcessor2D::impRenderBackgroundColorPrimitive2D(const primitive2d::BackgroundColorPrimitive2D& rCandidate)
+        {
+            const basegfx::BColor aFillColor(
+                maBColorModifierStack.getModifiedColor(rCandidate.getBColor()));
+            maVolatileRenderState.DeviceColor =
+                aFillColor.colorToDoubleSequence(mxCanvas->getDevice());
+
+            const basegfx::B2DRange& aViewport(getViewInformation2D().getDiscreteViewport());
+
+            // render to target - with identity transformation, we
+            // want the viewport 1:1 filled
+            basegfx::B2DHomMatrix aIdentMatrix;
+            canvas::tools::setViewStateTransform(maViewState,
+                                                 aIdentMatrix);
+            canvas::tools::setRenderStateTransform(maVolatileRenderState,
+                                                   aIdentMatrix);
+            mxCanvas->fillPolyPolygon(
+                basegfx::unotools::xPolyPolygonFromB2DPolygon(
+                    mxCanvas->getDevice(),
+                    basegfx::tools::createPolygonFromRect(aViewport)),
+                maViewState,  maVolatileRenderState);
+
+            // and reset transforms to default again
+            canvas::tools::setViewStateTransform(maViewState,
+                                                 getViewInformation2D().getViewTransformation());
+            canvas::tools::setRenderStateTransform(maVolatileRenderState,
+                                                   getViewInformation2D().getObjectTransformation());
+        }
+
+        void CanvasProcessor2D::impRenderSvgLinearGradientPrimitive2D(const primitive2d::SvgLinearGradientPrimitive2D& rCandidate)
+        {
+            if( rCandidate.getSpreadMethod() == primitive2d::Spread_reflect )
+            {
+                // TODO(P2): drats. we miss reflection as a texture
+                // mode on XCanvas!
+                process(rCandidate.get2DDecomposition(getViewInformation2D()));
+                return;
+            }
+
+            const basegfx::B2DPolyPolygon& rPoly = rCandidate.getPolyPolygon();
+            const primitive2d::SvgGradientEntryVector& rEntries = rCandidate.getGradientEntries();
+            if( !rPoly.count() || rEntries.empty() )
+                return; // empty output, quit
+
+            // create matching linear gradient stops
+            const size_t nEntries = rEntries.size();
+            uno::Sequence< uno::Sequence < double > > aColors(nEntries);
+            uno::Sequence< double > aStops(nEntries);
+
+            for( size_t i=0; i<nEntries; ++i )
+            {
+                aStops[i] = rEntries[i].getOffset();
+                aColors[i] = rEntries[i].getColor().colorToDoubleSequence(
+                    mxCanvas->getDevice());
+                aColors[i][4] = rEntries[i].getOpacity();
+            }
+
+            // fill service params
+            uno::Sequence<uno::Any> args(2);
+            beans::PropertyValue aProp;
+            aProp.Name = "Colors";
+            aProp.Value <<= aColors;
+            args[0] <<= aProp;
+            aProp.Name = "Stops";
+            aProp.Value <<= aStops;
+            args[1] <<= aProp;
+
+            // setup texture transform (from gradient transform and
+            // start points)
+
+            // gradient goes from start to end - instead of
+            // (0,0)-(1,0) for the default case.
+            const basegfx::B2DVector aDir(rCandidate.getEnd() - rCandidate.getStart());
+
+            // get up/down-scale, relative to [0,1] default len
+            const double fScale( aDir.getLength() );
+
+            // get rotation angle away from default (which is horizontal)
+            const double fRot( acos(aDir.scalar( basegfx::B2DVector(1.0, 0.0))) );
+
+            // tweak gradient transform to accomodate above changes
+            basegfx::B2DHomMatrix aTotalTransform = rCandidate.getGradientTransform();
+            aTotalTransform *= basegfx::tools::createTranslateB2DHomMatrix(rCandidate.getStart());
+            aTotalTransform *= basegfx::tools::createRotateB2DHomMatrix(fRot);
+            aTotalTransform *= basegfx::tools::createScaleB2DHomMatrix(fScale, fScale);
+
+            // fill texture params
+            rendering::Texture aTexture;
+            // TODO(F2): drats. we miss reflect mode here!
+            aTexture.RepeatModeX = aTexture.RepeatModeY =
+                rCandidate.getSpreadMethod() == primitive2d::Spread_pad ?
+                rendering::TexturingMode::CLAMP :
+                rendering::TexturingMode::REPEAT;
+
+            aTexture.Alpha = 1.0;
+            ::basegfx::unotools::affineMatrixFromHomMatrix(
+                aTexture.AffineTransform,
+                aTotalTransform);
+            aTexture.Gradient.set(
+                mxParametricPolygonFactory->createInstanceWithArguments(
+                    "LinearGradient",
+                    args),
+                uno::UNO_QUERY_THROW);
+
+            // and render, into given polypolygon
+            mxCanvas->drawPolyPolygon(
+                basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+                    mxCanvas->getDevice(),
+                    rCandidate.getPolyPolygon()),
+                maViewState,  maVolatileRenderState);
+        }
+
+        void CanvasProcessor2D::impRenderSvgRadialGradientPrimitive2D(const primitive2d::SvgRadialGradientPrimitive2D& rCandidate)
+        {
+            if( rCandidate.getSpreadMethod() == primitive2d::Spread_reflect ||
+                rCandidate.isFocalSet() )
+            {
+                // TODO(P2): drats. we miss reflection as a texture
+                // mode on XCanvas!
+                // TODO(P2): drats. we also miss focal point setting
+                // for radial gradient on XCanvas!
+                process(rCandidate.get2DDecomposition(getViewInformation2D()));
+                return;
+            }
+
+            const basegfx::B2DPolyPolygon& rPoly = rCandidate.getPolyPolygon();
+            const primitive2d::SvgGradientEntryVector& rEntries = rCandidate.getGradientEntries();
+            if( !rPoly.count() || rEntries.empty() )
+                return; // empty output, quit
+
+            // create matching radial gradient stops
+            const size_t nEntries = rEntries.size();
+            uno::Sequence< uno::Sequence < double > > aColors(nEntries);
+            uno::Sequence< double > aStops(nEntries);
+
+            for( size_t i=0; i<nEntries; ++i )
+            {
+                aStops[i] = rEntries[i].getOffset();
+                aColors[i] = rEntries[i].getColor().colorToDoubleSequence(
+                    mxCanvas->getDevice());
+                aColors[i][4] = rEntries[i].getOpacity();
+            }
+
+            // fill service params
+            uno::Sequence<uno::Any> args(2);
+            beans::PropertyValue aProp;
+            aProp.Name = "Colors";
+            aProp.Value <<= aColors;
+            args[0] <<= aProp;
+            aProp.Name = "Stops";
+            aProp.Value <<= aStops;
+            args[1] <<= aProp;
+
+            // setup texture transform (from gradient transform and
+            // start points)
+
+            // get up/down-scale, relative to 0.5 default radius
+            const double fScale( rCandidate.getRadius() * 2.0 );
+
+            // tweak gradient transform to accomodate above changes
+            // (default center is 0.5/0.5)
+            basegfx::B2DHomMatrix aTotalTransform = rCandidate.getGradientTransform();
+            aTotalTransform *= basegfx::tools::createTranslateB2DHomMatrix(
+                rCandidate.getStart()-basegfx::B2DPoint(0.5, 0.5));
+            aTotalTransform *= basegfx::tools::createScaleB2DHomMatrix(fScale, fScale);
+
+            // fill texture params
+            rendering::Texture aTexture;
+            // TODO(F2): drats. we miss reflect mode here!
+            aTexture.RepeatModeX = aTexture.RepeatModeY =
+                rCandidate.getSpreadMethod() == primitive2d::Spread_pad ?
+                rendering::TexturingMode::CLAMP :
+                rendering::TexturingMode::REPEAT;
+
+            aTexture.Alpha = 1.0;
+            ::basegfx::unotools::affineMatrixFromHomMatrix(
+                aTexture.AffineTransform,
+                aTotalTransform);
+            aTexture.Gradient.set(
+                mxParametricPolygonFactory->createInstanceWithArguments(
+                    "EllipticalGradient",
+                    args),
+                uno::UNO_QUERY_THROW);
+
+            // and render, into given polypolygon
+            mxCanvas->drawPolyPolygon(
+                basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+                    mxCanvas->getDevice(),
+                    rCandidate.getPolyPolygon()),
+                maViewState,  maVolatileRenderState);
+        }
+
+        //////////////////////////////////////////////////////////////////////////////
+        // internal processing support
+
+        void CanvasProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+        {
+            switch(rCandidate.getPrimitive2DID())
+            {
+                // The following base primitives are not handled on
+                // purpose - we rely on the recursive breaking up
+                // (either because emulation would be ~comparable in
+                // effort to breaking up, or needs vcl, or is only
+                // relevant for edit mode currently, or stuff like
+                // e.g. hatches is currently not implemented in
+                // canvas):
+                //   case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D          (fallback good)
+                //   case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D            (fallback excellent)
+                //   case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D         (fallback good)
+                //   case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D (fallback good)
+                //   case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D             (fallback needs vcl)
+                //   case PRIMITIVE2D_ID_FILLHATCHPRIMITIVE2D           (NYI in canvas)
+                //   case PRIMITIVE2D_ID_INVERTPRIMITIVE2D              (edit mode only)
+                //   case PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D       (should not happen, and if: fallback good)
+                //   case PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D       (should not happen, and if: fallback good)
+                //
+                // TODO(F1):
+                //   case PRIMITIVE2D_ID_EPSPRIMITIVE2D                 (needs ghostscript/Xpost help)
+
+
+                case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
+                    // new XDrawPage for ViewInformation2D
+                    impRenderPagePreviewPrimitive2D(static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate));
+                    break;
+
+                case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
+                    // directdraw of text simple portion; added test possibility to check text decompose
+                    if(getOptionsDrawinglayer().IsRenderSimpleTextDirect())
+                    {
+                        impRenderTextSimpleOrDecoratedPortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate));
+                    }
+                    else
+                    {
+                        process(rCandidate.get2DDecomposition(getViewInformation2D()));
+                    }
+                    break;
+
+                case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D :
+                    // directdraw of text simple portion; added test possibility to check text decompose
+                    if(getOptionsDrawinglayer().IsRenderDecoratedTextDirect())
+                    {
+                        impRenderTextSimpleOrDecoratedPortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate));
+                    }
+                    else
+                    {
+                        process(rCandidate.get2DDecomposition(getViewInformation2D()));
+                    }
+                    break;
+
+                case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
+                    // direct draw of hairline
+                    impRenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate));
+                    break;
+
+                case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
+                    // direct draw of bitmaps
+                    impRenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
+                    break;
+
+                case PRIMITIVE2D_ID_FILLGRAPHICPRIMITIVE2D :
+                    // direct draw of fillBitmapPrimitive
+                    impRenderFillGraphicPrimitive2D(static_cast< const primitive2d::FillGraphicPrimitive2D& >(rCandidate));
+                    break;
+
+                case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D :
+                    // direct draw of bitmap
+                    impRenderPolyPolygonGraphicPrimitive2D(static_cast< const primitive2d::PolyPolygonGraphicPrimitive2D& >(rCandidate));
+                    break;
+
+                case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
+                    // direct draw of PolyPolygon with color
+                    impRenderPolyPolygonColorPrimitive2D(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
+                    break;
+
+                case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
+                    // mask group.
+                    impRenderMaskPrimitive2D(static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate));
+                    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_UNIFIEDTRANSPARENCEPRIMITIVE2D :
+                    // unified sub-transparence
+                    impRenderUnifiedTransparencePrimitive2D(static_cast< const primitive2d::UnifiedTransparencePrimitive2D& >(rCandidate));
+                    break;
+
+                case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D :
+                    // sub-transparence group
+                    impRenderTransparencePrimitive2D(static_cast< const primitive2d::TransparencePrimitive2D& >(rCandidate));
+                    break;
+
+                case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
+                    // transform group.
+                    impRenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
+                    break;
+
+                case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
+                    // point array
+                    impRenderPointArrayPrimitive2D(static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate));
+                    break;
+
+                case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
+                    // direct draw of stroked polygon
+                    impRenderPolygonStrokePrimitive2D(static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate));
+                    break;
+
+                case PRIMITIVE2D_ID_BACKGROUNDCOLORPRIMITIVE2D :
+                    impRenderBackgroundColorPrimitive2D(static_cast< const primitive2d::BackgroundColorPrimitive2D& >(rCandidate));
+                    break;
+
+                case PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D :
+                    impRenderSvgLinearGradientPrimitive2D(static_cast< const primitive2d::SvgLinearGradientPrimitive2D& >(rCandidate));
+                    break;
+
+                case PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D:
+                    impRenderSvgRadialGradientPrimitive2D(static_cast< const primitive2d::SvgRadialGradientPrimitive2D& >(rCandidate));
+                    break;
+
+                default:
+                    // handle recursively
+                    process(rCandidate.get2DDecomposition(getViewInformation2D()));
+                    break;
+            }
+        }
+
+        CanvasProcessor2D::CanvasProcessor2D( const geometry::ViewInformation2D& rViewInformation,
+                                              const uno::Reference< rendering::XCanvas >& xCanvas ) :
+            BaseProcessor2D(rViewInformation),
+            mxCanvas(xCanvas),
+            mxParametricPolygonFactory(
+                mxCanvas->getDevice()->getParametricPolyPolygonFactory()),
+            maViewState(),
+            maVolatileRenderState(),
+            maBColorModifierStack(),
+            maDrawinglayerOpt(),
+            maClipPolyPolygon()
+        {
+            canvas::tools::initViewState(maViewState);
+            canvas::tools::initRenderState(maVolatileRenderState);
+            canvas::tools::setViewStateTransform(maViewState,
+                                                 getViewInformation2D().getViewTransformation());
+            canvas::tools::setRenderStateTransform(maVolatileRenderState,
+                                                   getViewInformation2D().getObjectTransformation());
+        }
+    } // end of namespace processor2d
+} // end of namespace drawinglayer
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/drawinglayer/processor2d/canvasprocessor.hxx b/include/drawinglayer/processor2d/canvasprocessor2d.hxx
similarity index 51%
rename from include/drawinglayer/processor2d/canvasprocessor.hxx
rename to include/drawinglayer/processor2d/canvasprocessor2d.hxx
index 5dea3b4..482654d 100644
--- a/include/drawinglayer/processor2d/canvasprocessor.hxx
+++ b/include/drawinglayer/processor2d/canvasprocessor2d.hxx
@@ -17,20 +17,17 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#ifndef _DRAWINGLAYER_PROCESSOR_CANVASPROCESSOR_HXX
-#define _DRAWINGLAYER_PROCESSOR_CANVASPROCESSOR_HXX
+#ifndef _DRAWINGLAYER_PROCESSOR_CANVASPROCESSOR2D_HXX
+#define _DRAWINGLAYER_PROCESSOR_CANVASPROCESSOR2D_HXX
 
 #include <drawinglayer/drawinglayerdllapi.h>
 
 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
-#include <basegfx/matrix/b2dhommatrix.hxx>
 #include <basegfx/color/bcolormodifier.hxx>
 #include <svtools/optionsdrawinglayer.hxx>
 #include <com/sun/star/rendering/ViewState.hpp>
 #include <com/sun/star/rendering/RenderState.hpp>
-#include <i18nlangtag/lang.h>
 #include <basegfx/polygon/b2dpolypolygon.hxx>
-#include <vcl/mapmod.hxx>
 
 //////////////////////////////////////////////////////////////////////////////
 // forward declaration
@@ -46,14 +43,24 @@ namespace com { namespace sun { namespace star { namespace rendering {
 }}}}
 
 namespace drawinglayer { namespace primitive2d {
-    class MaskPrimitive2D;
-    class MetafilePrimitive2D;
     class TextSimplePortionPrimitive2D;
+    class PolygonHairlinePrimitive2D;
     class BitmapPrimitive2D;
+    class FillGraphicPrimitive2D;
+    class PolyPolygonGradientPrimitive2D;
+    class PolyPolygonGraphicPrimitive2D;
+    class PolyPolygonColorPrimitive2D;
+    class BackgroundColorPrimitive2D;
+    class MaskPrimitive2D;
+    class UnifiedTransparencePrimitive2D;
     class TransparencePrimitive2D;
+    class TransformPrimitive2D;
+    class PointArrayPrimitive2D;
+    class ModifiedColorPrimitive2D;
     class PolygonStrokePrimitive2D;
-    class FillBitmapPrimitive2D;
-    class UnifiedTransparencePrimitive2D;
+    class PagePreviewPrimitive2D;
+    class SvgLinearGradientPrimitive2D;
+    class SvgRadialGradientPrimitive2D;
 }}
 
 //////////////////////////////////////////////////////////////////////////////
@@ -62,52 +69,62 @@ namespace drawinglayer
 {
     namespace processor2d
     {
-        /** canvasProcessor2D class
+        /** CanvasProcessor2D class
 
-            A basic implementation of a renderer for com::sun::star::rendering::XCanvas
+            An implementation of a renderer for com::sun::star::rendering::XCanvas
             as a target
          */
-        class DRAWINGLAYER_DLLPUBLIC canvasProcessor2D : public BaseProcessor2D
+        class DRAWINGLAYER_DLLPUBLIC CanvasProcessor2D : public BaseProcessor2D
         {
         private:
-            // the (current) destination OutDev and canvas
-            OutputDevice*                                           mpOutputDevice;
-            com::sun::star::uno::Reference< com::sun::star::rendering::XCanvas >    mxCanvas;
-            com::sun::star::rendering::ViewState                    maViewState;
-            com::sun::star::rendering::RenderState                  maRenderState;
+            // the (current) destination canvas
+            com::sun::star::uno::Reference<
+                com::sun::star::rendering::XCanvas >        mxCanvas;
+            com::sun::star::uno::Reference<
+                com::sun::star::lang::XMultiServiceFactory> mxParametricPolygonFactory;
+            com::sun::star::rendering::ViewState            maViewState;
+
+            // entirely volatile - but since we need it for ~every canvas call ...
+            com::sun::star::rendering::RenderState          maVolatileRenderState;
 
             // the modifiedColorPrimitive stack
-            basegfx::BColorModifierStack                            maBColorModifierStack;
+            basegfx::BColorModifierStack                    maBColorModifierStack;
 
             // SvtOptionsDrawinglayer incarnation to react on diverse settings
-            const SvtOptionsDrawinglayer                            maDrawinglayerOpt;
+            const SvtOptionsDrawinglayer                    maDrawinglayerOpt;
 
             // the current clipping PolyPolygon from MaskPrimitive2D, always in
             // object coordinates
-            basegfx::B2DPolyPolygon                                 maClipPolyPolygon;
-
-            // determined LanguageType
-            LanguageType                                            meLang;
+            basegfx::B2DPolyPolygon                         maClipPolyPolygon;
 
             // as tooling, the process() implementation takes over API handling and calls this
             // virtual render method when the primitive implementation is BasePrimitive2D-based.
             virtual void processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate);
 
             // direct primitive renderer support
-            void impRenderMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate);
-            void impRenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rMetaCandidate);
-            void impRenderTextSimplePortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate);
+            void impRenderTextSimpleOrDecoratedPortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate);
+            void impRenderPolygonHairlinePrimitive2D(const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate);
             void impRenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate);
-            void impRenderTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D& rTransparenceCandidate);
-            void impRenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive);
-            void impRenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapPrimitive2D);
-            void impRenderUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate);
+            void impRenderFillGraphicPrimitive2D(const primitive2d::FillGraphicPrimitive2D& rFillBitmapCandidate);
+            void impRenderPolyPolygonGraphicPrimitive2D(const primitive2d::PolyPolygonGraphicPrimitive2D& rPolygonCandidate);
+            void impRenderPolyPolygonColorPrimitive2D(const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate);
+            void impRenderBackgroundColorPrimitive2D(const primitive2d::BackgroundColorPrimitive2D& rCandidate);
+            void impRenderSvgLinearGradientPrimitive2D(const primitive2d::SvgLinearGradientPrimitive2D& rCandidate);
+            void impRenderSvgRadialGradientPrimitive2D(const primitive2d::SvgRadialGradientPrimitive2D& rCandidate);
+            void impRenderMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate);
+            void impRenderModifiedColorPrimitive2D(const primitive2d::ModifiedColorPrimitive2D& rModifiedCandidate);
+            void impRenderUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D& rTransCandidate);
+            void impRenderTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D& rTransCandidate);
+            void impRenderTransformPrimitive2D(const primitive2d::TransformPrimitive2D& rTransformCandidate);
+            void impRenderPagePreviewPrimitive2D(const primitive2d::PagePreviewPrimitive2D& rPagePreviewCandidate);
+            void impRenderPointArrayPrimitive2D(const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate);
+            void impRenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokeCandidate);
 
         public:
-            canvasProcessor2D(
+            CanvasProcessor2D(
                 const geometry::ViewInformation2D& rViewInformation,
-                OutputDevice& rOutDev);
-            virtual ~canvasProcessor2D();
+                const com::sun::star::uno::Reference<
+                    com::sun::star::rendering::XCanvas >& xCanvas);
 
             // access to Drawinglayer configuration options
             const SvtOptionsDrawinglayer& getOptionsDrawinglayer() const { return maDrawinglayerOpt; }
@@ -117,6 +134,6 @@ namespace drawinglayer
 
 //////////////////////////////////////////////////////////////////////////////
 
-#endif //_DRAWINGLAYER_PROCESSOR_CANVASPROCESSOR_HXX
+#endif //_DRAWINGLAYER_PROCESSOR_CANVASPROCESSOR2D_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list