LCOV - code coverage report
Current view: top level - libreoffice/drawinglayer/source/processor2d - canvasprocessor.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 408 0.0 %
Date: 2012-12-27 Functions: 0 12 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <drawinglayer/processor2d/canvasprocessor.hxx>
      21             : #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
      22             : #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
      23             : #include <com/sun/star/rendering/XCanvas.hpp>
      24             : #include <vcl/canvastools.hxx>
      25             : #include <basegfx/tools/canvastools.hxx>
      26             : #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
      27             : #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
      28             : #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
      29             : #include <canvas/canvastools.hxx>
      30             : #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
      31             : #include <basegfx/polygon/b2dpolygonclipper.hxx>
      32             : #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
      33             : #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
      34             : #include <cppcanvas/basegfxfactory.hxx>
      35             : #include <com/sun/star/rendering/XBitmapCanvas.hpp>
      36             : #include <cppcanvas/vclfactory.hxx>
      37             : #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
      38             : #include <drawinglayer/primitive2d/textprimitive2d.hxx>
      39             : #include <com/sun/star/rendering/TextDirection.hpp>
      40             : #include <vclhelperbitmaptransform.hxx>
      41             : #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
      42             : #include <basegfx/polygon/b2dpolygontools.hxx>
      43             : #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
      44             : #include <basegfx/tuple/b2i64tuple.hxx>
      45             : #include <basegfx/range/b2irange.hxx>
      46             : #include <com/sun/star/rendering/XIntegerReadOnlyBitmap.hpp>
      47             : #include <com/sun/star/rendering/PanoseProportion.hpp>
      48             : #include <com/sun/star/rendering/CompositeOperation.hpp>
      49             : #include <com/sun/star/rendering/StrokeAttributes.hpp>
      50             : #include <com/sun/star/rendering/PathJoinType.hpp>
      51             : #include <com/sun/star/rendering/PathCapType.hpp>
      52             : #include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
      53             : #include <com/sun/star/rendering/TexturingMode.hpp>
      54             : #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
      55             : #include <vclhelperbufferdevice.hxx>
      56             : #include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
      57             : #include <helperwrongspellrenderer.hxx>
      58             : #include <basegfx/matrix/b2dhommatrixtools.hxx>
      59             : 
      60             : #include "getdigitlanguage.hxx"
      61             : 
      62             : //////////////////////////////////////////////////////////////////////////////
      63             : 
      64             : using namespace com::sun::star;
      65             : 
      66             : //////////////////////////////////////////////////////////////////////////////
      67             : 
      68             : namespace drawinglayer
      69             : {
      70             :     namespace processor2d
      71             :     {
      72             :         //////////////////////////////////////////////////////////////////////////////
      73             :         // single primitive renderers
      74             : 
      75           0 :         void canvasProcessor2D::impRenderMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate)
      76             :         {
      77           0 :             const primitive2d::Primitive2DSequence& rChildren = rMaskCandidate.getChildren();
      78             :             static bool bUseMaskBitmapMethod(true);
      79             : 
      80           0 :             if(rChildren.hasElements())
      81             :             {
      82           0 :                 basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
      83             : 
      84           0 :                 if(!aMask.count())
      85             :                 {
      86             :                     // no mask, no clipping. recursively paint content
      87           0 :                     process(rChildren);
      88             :                 }
      89             :                 else
      90             :                 {
      91             :                     // there are principally two methods for implementing the mask primitive. One
      92             :                     // is to set a clip polygon at the canvas, the other is to create and use a
      93             :                     // transparence-using XBitmap for content and draw the mask as transparence. Both have their
      94             :                     // advantages and disadvantages, so here are both with a bool allowing simple
      95             :                     // change
      96           0 :                     if(bUseMaskBitmapMethod)
      97             :                     {
      98             :                         // get logic range of transparent part, clip with ViewRange
      99           0 :                         basegfx::B2DRange aLogicRange(aMask.getB2DRange());
     100             : 
     101           0 :                         if(!getViewInformation2D().getViewport().isEmpty())
     102             :                         {
     103           0 :                             aLogicRange.intersect(getViewInformation2D().getViewport());
     104             :                         }
     105             : 
     106           0 :                         if(!aLogicRange.isEmpty())
     107             :                         {
     108             :                             // get discrete range of transparent part
     109           0 :                             basegfx::B2DRange aDiscreteRange(aLogicRange);
     110           0 :                             aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation());
     111             : 
     112             :                             // expand to next covering discrete values (pixel bounds)
     113           0 :                             aDiscreteRange.expand(basegfx::B2DTuple(floor(aDiscreteRange.getMinX()), floor(aDiscreteRange.getMinY())));
     114           0 :                             aDiscreteRange.expand(basegfx::B2DTuple(ceil(aDiscreteRange.getMaxX()), ceil(aDiscreteRange.getMaxY())));
     115             : 
     116             :                             // use VCL-based buffer device
     117           0 :                             impBufferDevice aBufferDevice(*mpOutputDevice, aDiscreteRange, false);
     118             : 
     119           0 :                             if(aBufferDevice.isVisible())
     120             :                             {
     121             :                                 // remember current OutDev, Canvas and ViewInformation
     122           0 :                                 OutputDevice* pLastOutputDevice = mpOutputDevice;
     123           0 :                                 uno::Reference< rendering::XCanvas > xLastCanvas(mxCanvas);
     124           0 :                                 const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
     125             : 
     126             :                                 // prepare discrete offset for XBitmap, do not forget that the buffer bitmap
     127             :                                 // may be truncated to discrete visible pixels
     128             :                                 const basegfx::B2DHomMatrix aDiscreteOffset(basegfx::tools::createTranslateB2DHomMatrix(
     129           0 :                                     aDiscreteRange.getMinX() > 0.0 ? -aDiscreteRange.getMinX() : 0.0,
     130           0 :                                     aDiscreteRange.getMinY() > 0.0 ? -aDiscreteRange.getMinY() : 0.0));
     131             : 
     132             :                                 // create new local ViewInformation2D with new transformation
     133             :                                 const geometry::ViewInformation2D aViewInformation2D(
     134           0 :                                     getViewInformation2D().getObjectTransformation(),
     135           0 :                                     aDiscreteOffset * getViewInformation2D().getViewTransformation(),
     136           0 :                                     getViewInformation2D().getViewport(),
     137           0 :                                     getViewInformation2D().getVisualizedPage(),
     138           0 :                                     getViewInformation2D().getViewTime(),
     139           0 :                                     getViewInformation2D().getExtendedInformationSequence());
     140           0 :                                 updateViewInformation(aViewInformation2D);
     141             : 
     142             :                                 // set OutDev and Canvas to content target
     143           0 :                                 mpOutputDevice = &aBufferDevice.getContent();
     144           0 :                                 mxCanvas = mpOutputDevice->GetCanvas();
     145           0 :                                 canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
     146             : 
     147             :                                 // if ViewState transform is changed, the clipping polygon needs to be adapted, too
     148           0 :                                 const basegfx::B2DPolyPolygon aOldClipPolyPolygon(maClipPolyPolygon);
     149             : 
     150           0 :                                 if(maClipPolyPolygon.count())
     151             :                                 {
     152           0 :                                     maClipPolyPolygon.transform(aDiscreteOffset);
     153           0 :                                     maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
     154             :                                 }
     155             : 
     156             :                                 // paint content
     157           0 :                                 process(rChildren);
     158             : 
     159             :                                 // draw mask
     160           0 :                                 const basegfx::BColor aBlack(0.0, 0.0, 0.0);
     161           0 :                                 maRenderState.DeviceColor = aBlack.colorToDoubleSequence(mxCanvas->getDevice());
     162             : 
     163           0 :                                 if(getOptionsDrawinglayer().IsAntiAliasing())
     164             :                                 {
     165             :                                     // with AA, use 8bit AlphaMask to get nice borders
     166           0 :                                     VirtualDevice& rTransparence = aBufferDevice.getTransparence();
     167           0 :                                     rTransparence.GetCanvas()->fillPolyPolygon(
     168           0 :                                         basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), aMask),
     169           0 :                                         maViewState, maRenderState);
     170             :                                 }
     171             :                                 else
     172             :                                 {
     173             :                                     // No AA, use 1bit mask
     174           0 :                                     VirtualDevice& rMask = aBufferDevice.getMask();
     175           0 :                                     rMask.GetCanvas()->fillPolyPolygon(
     176           0 :                                         basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), aMask),
     177           0 :                                         maViewState, maRenderState);
     178             :                                 }
     179             : 
     180             :                                 // back to old color stack, OutDev, Canvas and ViewTransform
     181           0 :                                 mpOutputDevice = pLastOutputDevice;
     182           0 :                                 mxCanvas = xLastCanvas;
     183           0 :                                 updateViewInformation(aLastViewInformation2D);
     184           0 :                                 canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
     185             : 
     186             :                                 // restore clipping polygon
     187           0 :                                 maClipPolyPolygon = aOldClipPolyPolygon;
     188             : 
     189           0 :                                 if(maClipPolyPolygon.count())
     190             :                                 {
     191           0 :                                     maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
     192             :                                 }
     193             : 
     194             :                                 // dump buffer to outdev
     195           0 :                                 aBufferDevice.paint();
     196           0 :                             }
     197             :                         }
     198             :                     }
     199             :                     else
     200             :                     {
     201             :                         // transform new mask polygon to view coordinates for processing. All masks
     202             :                         // are processed in view coordinates and clipped against each other evtl. to
     203             :                         // create multi-clips
     204           0 :                         aMask.transform(getViewInformation2D().getObjectTransformation());
     205             : 
     206             :                         // remember last current clip polygon
     207           0 :                         const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon);
     208             : 
     209           0 :                         if(maClipPolyPolygon.count())
     210             :                         {
     211             :                             // there is already a clip polygon set; build clipped union of
     212             :                             // current mask polygon and new one
     213           0 :                             maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(aMask, maClipPolyPolygon, false, false);
     214             :                         }
     215             :                         else
     216             :                         {
     217             :                             // use mask directly
     218           0 :                             maClipPolyPolygon = aMask;
     219             :                         }
     220             : 
     221             :                         // set at ViewState
     222           0 :                         if(maClipPolyPolygon.count())
     223             :                         {
     224             :                             // set new as clip polygon
     225           0 :                             maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
     226             :                         }
     227             :                         else
     228             :                         {
     229             :                             // empty, reset
     230           0 :                             maViewState.Clip.clear();
     231             :                         }
     232             : 
     233             :                         // paint content
     234           0 :                         process(rChildren);
     235             : 
     236             :                         // restore local current to rescued clip polygon
     237           0 :                         maClipPolyPolygon = aLastClipPolyPolygon;
     238             : 
     239             :                         // set at ViewState
     240           0 :                         if(maClipPolyPolygon.count())
     241             :                         {
     242             :                             // set new as clip polygon
     243           0 :                             maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
     244             :                         }
     245             :                         else
     246             :                         {
     247             :                             // empty, reset
     248           0 :                             maViewState.Clip.clear();
     249           0 :                         }
     250             :                     }
     251           0 :                 }
     252             :             }
     253           0 :         }
     254             : 
     255           0 :         void canvasProcessor2D::impRenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rMetaCandidate)
     256             :         {
     257           0 :             GDIMetaFile aMetaFile;
     258             : 
     259           0 :             if(maBColorModifierStack.count())
     260             :             {
     261           0 :                 const basegfx::BColor aRGBBaseColor(0, 0, 0);
     262           0 :                 const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor));
     263           0 :                 aMetaFile = rMetaCandidate.getMetaFile().GetMonochromeMtf(Color(aRGBColor));
     264             :             }
     265             :             else
     266             :             {
     267           0 :                 aMetaFile = rMetaCandidate.getMetaFile();
     268             :             }
     269             : 
     270           0 :             cppcanvas::BitmapCanvasSharedPtr pCanvas(cppcanvas::VCLFactory::getInstance().createCanvas(
     271           0 :                     uno::Reference<rendering::XBitmapCanvas>(mxCanvas, uno::UNO_QUERY_THROW)));
     272           0 :             cppcanvas::RendererSharedPtr pMtfRenderer(cppcanvas::VCLFactory::getInstance().createRenderer(
     273           0 :                     pCanvas, aMetaFile, cppcanvas::Renderer::Parameters()));
     274             : 
     275           0 :             if(pMtfRenderer)
     276             :             {
     277           0 :                 pCanvas->setTransformation(getViewInformation2D().getObjectToViewTransformation());
     278           0 :                 pMtfRenderer->setTransformation(rMetaCandidate.getTransform());
     279           0 :                 pMtfRenderer->draw();
     280           0 :             }
     281           0 :         }
     282             : 
     283           0 :         void canvasProcessor2D::impRenderTextSimplePortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate)
     284             :         {
     285           0 :             if(rTextCandidate.getTextLength())
     286             :             {
     287           0 :                 double fShearX(0.0);
     288             :                 {
     289           0 :                     const basegfx::B2DHomMatrix aLocalTransform(getViewInformation2D().getObjectToViewTransformation() * rTextCandidate.getTextTransform());
     290           0 :                     basegfx::B2DVector aScale, aTranslate;
     291             :                     double fRotate;
     292           0 :                     aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
     293             :                 }
     294             : 
     295           0 :                 if(!basegfx::fTools::equalZero(fShearX))
     296             :                 {
     297             :                     // text is sheared. As long as the canvas renderers do not support this,
     298             :                     // use the decomposed primitive
     299           0 :                     process(rTextCandidate.get2DDecomposition(getViewInformation2D()));
     300             :                 }
     301             :                 else
     302             :                 {
     303           0 :                     const attribute::FontAttribute& rFontAttr(rTextCandidate.getFontAttribute());
     304           0 :                     rendering::FontRequest aFontRequest;
     305             : 
     306           0 :                     aFontRequest.FontDescription.FamilyName = rFontAttr.getFamilyName();
     307           0 :                     aFontRequest.FontDescription.StyleName = rFontAttr.getStyleName();
     308           0 :                     aFontRequest.FontDescription.IsSymbolFont = rFontAttr.getSymbol() ? util::TriState_YES : util::TriState_NO;
     309           0 :                     aFontRequest.FontDescription.IsVertical = rFontAttr.getVertical() ? util::TriState_YES : util::TriState_NO;
     310             :                     // TODO(F2): improve vclenum->panose conversion
     311           0 :                     aFontRequest.FontDescription.FontDescription.Weight = static_cast< sal_uInt8 >(rFontAttr.getWeight());
     312             :                     aFontRequest.FontDescription.FontDescription.Proportion =
     313           0 :                         rFontAttr.getMonospaced()
     314             :                             ? rendering::PanoseProportion::MONO_SPACED
     315           0 :                             : rendering::PanoseProportion::ANYTHING;
     316           0 :                     aFontRequest.FontDescription.FontDescription.Letterform = rFontAttr.getItalic() ? 9 : 0;
     317             : 
     318             :                     // init CellSize to 1.0, else a default font height will be used
     319           0 :                     aFontRequest.CellSize = 1.0;
     320           0 :                     aFontRequest.Locale = rTextCandidate.getLocale();
     321             : 
     322             :                     // font matrix should only be used for glyph rotations etc.
     323           0 :                     com::sun::star::geometry::Matrix2D aFontMatrix;
     324           0 :                     canvas::tools::setIdentityMatrix2D(aFontMatrix);
     325             : 
     326           0 :                     uno::Reference<rendering::XCanvasFont> xFont(mxCanvas->createFont(
     327           0 :                         aFontRequest, uno::Sequence< beans::PropertyValue >(), aFontMatrix));
     328             : 
     329           0 :                     if(xFont.is())
     330             :                     {
     331             :                         // got a font, now try to get a TextLayout
     332             :                         const rendering::StringContext aStringContext(
     333           0 :                             rTextCandidate.getText(), rTextCandidate.getTextPosition(), rTextCandidate.getTextLength());
     334           0 :                         uno::Reference<rendering::XTextLayout> xLayout(xFont->createTextLayout(
     335           0 :                             aStringContext, com::sun::star::rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0));
     336             : 
     337           0 :                         if(xLayout.is())
     338             :                         {
     339             :                             // got a text layout, apply DXArray if given
     340           0 :                             const ::std::vector< double >& rDXArray = rTextCandidate.getDXArray();
     341           0 :                             const sal_uInt32 nDXCount(rDXArray.size());
     342             : 
     343           0 :                             if(nDXCount)
     344             :                             {
     345             :                                 // DXArray does not need to be adapted to getTextPosition/getTextLength,
     346             :                                 // it is already provided correctly
     347           0 :                                 const uno::Sequence< double > aDXSequence(&rDXArray[0], nDXCount);
     348           0 :                                 xLayout->applyLogicalAdvancements(aDXSequence);
     349             :                             }
     350             : 
     351             :                             // set text color
     352           0 :                             const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rTextCandidate.getFontColor()));
     353           0 :                             maRenderState.DeviceColor = aRGBColor.colorToDoubleSequence(mxCanvas->getDevice());
     354             : 
     355             :                             // set text transformation
     356             :                             canvas::tools::setRenderStateTransform(maRenderState,
     357           0 :                                 getViewInformation2D().getObjectTransformation() * rTextCandidate.getTextTransform());
     358             : 
     359             :                             // paint
     360           0 :                             mxCanvas->drawTextLayout(xLayout, maViewState, maRenderState);
     361           0 :                         }
     362           0 :                     }
     363             :                 }
     364             :             }
     365           0 :         }
     366             : 
     367           0 :         void canvasProcessor2D::impRenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
     368             :         {
     369             :             // apply possible color modification to BitmapEx
     370           0 :             BitmapEx aModifiedBitmapEx(impModifyBitmapEx(maBColorModifierStack, rBitmapCandidate.getBitmapEx()));
     371             : 
     372           0 :             if(aModifiedBitmapEx.IsEmpty())
     373             :             {
     374             :                 // replace with color filled polygon
     375           0 :                 const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
     376           0 :                 const basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon());
     377             : 
     378           0 :                 maRenderState.DeviceColor = aModifiedColor.colorToDoubleSequence(mxCanvas->getDevice());
     379             :                 canvas::tools::setRenderStateTransform(maRenderState,
     380           0 :                     getViewInformation2D().getObjectTransformation() * rBitmapCandidate.getTransform());
     381             : 
     382           0 :                 mxCanvas->fillPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
     383           0 :                     mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aPolygon)), maViewState,  maRenderState);
     384             :             }
     385             :             else
     386             :             {
     387             :                 // adapt object's transformation to the correct scale
     388           0 :                 basegfx::B2DVector aScale, aTranslate;
     389           0 :                 const Size aSizePixel(aModifiedBitmapEx.GetSizePixel());
     390             : 
     391           0 :                 if(0 != aSizePixel.Width() && 0 != aSizePixel.Height())
     392             :                 {
     393             :                     double fRotate, fShearX;
     394           0 :                     rBitmapCandidate.getTransform().decompose(aScale, aTranslate, fRotate, fShearX);
     395             :                     const basegfx::B2DHomMatrix aNewMatrix(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
     396           0 :                         aScale.getX() / aSizePixel.Width(), aScale.getY() / aSizePixel.Height(),
     397           0 :                         fShearX, fRotate, aTranslate.getX(), aTranslate.getY()));
     398             : 
     399             :                     canvas::tools::setRenderStateTransform(maRenderState,
     400           0 :                         getViewInformation2D().getObjectTransformation() * aNewMatrix);
     401             : 
     402           0 :                     mxCanvas->drawBitmap(
     403           0 :                         vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(), aModifiedBitmapEx),
     404           0 :                         maViewState, maRenderState);
     405           0 :                 }
     406           0 :             }
     407           0 :         }
     408             : 
     409           0 :         void canvasProcessor2D::impRenderTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D& rTransparenceCandidate)
     410             :         {
     411           0 :             const primitive2d::Primitive2DSequence& rChildren = rTransparenceCandidate.getChildren();
     412           0 :             const primitive2d::Primitive2DSequence& rTransparence = rTransparenceCandidate.getTransparence();
     413             : 
     414           0 :             if(rChildren.hasElements() && rTransparence.hasElements())
     415             :             {
     416             :                 // get logic range of transparent part and clip with ViewRange
     417           0 :                 basegfx::B2DRange aLogicRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rChildren, getViewInformation2D()));
     418             : 
     419           0 :                 if(!getViewInformation2D().getViewport().isEmpty())
     420             :                 {
     421           0 :                     aLogicRange.intersect(getViewInformation2D().getViewport());
     422             :                 }
     423             : 
     424           0 :                 if(!aLogicRange.isEmpty())
     425             :                 {
     426             :                     // get discrete range of transparent part
     427           0 :                     basegfx::B2DRange aDiscreteRange(aLogicRange);
     428           0 :                     aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation());
     429             : 
     430             :                     // expand to next covering discrete values (pixel bounds)
     431           0 :                     aDiscreteRange.expand(basegfx::B2DTuple(floor(aDiscreteRange.getMinX()), floor(aDiscreteRange.getMinY())));
     432           0 :                     aDiscreteRange.expand(basegfx::B2DTuple(ceil(aDiscreteRange.getMaxX()), ceil(aDiscreteRange.getMaxY())));
     433             : 
     434             :                     // use VCL-based buffer device
     435           0 :                     impBufferDevice aBufferDevice(*mpOutputDevice, aDiscreteRange, false);
     436             : 
     437           0 :                     if(aBufferDevice.isVisible())
     438             :                     {
     439             :                         // remember current OutDev, Canvas and ViewInformation
     440           0 :                         OutputDevice* pLastOutputDevice = mpOutputDevice;
     441           0 :                         uno::Reference< rendering::XCanvas > xLastCanvas(mxCanvas);
     442           0 :                         const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
     443             : 
     444             :                         // prepare discrete offset for XBitmap, do not forget that the buffer bitmap
     445             :                         // may be truncated to discrete visible pixels
     446             :                         const basegfx::B2DHomMatrix aDiscreteOffset(basegfx::tools::createTranslateB2DHomMatrix(
     447           0 :                             aDiscreteRange.getMinX() > 0.0 ? -aDiscreteRange.getMinX() : 0.0,
     448           0 :                             aDiscreteRange.getMinY() > 0.0 ? -aDiscreteRange.getMinY() : 0.0));
     449             : 
     450             :                         // create new local ViewInformation2D with new transformation
     451             :                         const geometry::ViewInformation2D aViewInformation2D(
     452           0 :                             getViewInformation2D().getObjectTransformation(),
     453           0 :                             aDiscreteOffset * getViewInformation2D().getViewTransformation(),
     454           0 :                             getViewInformation2D().getViewport(),
     455           0 :                             getViewInformation2D().getVisualizedPage(),
     456           0 :                             getViewInformation2D().getViewTime(),
     457           0 :                             getViewInformation2D().getExtendedInformationSequence());
     458           0 :                         updateViewInformation(aViewInformation2D);
     459             : 
     460             :                         // set OutDev and Canvas to content target
     461           0 :                         mpOutputDevice = &aBufferDevice.getContent();
     462           0 :                         mxCanvas = mpOutputDevice->GetCanvas();
     463           0 :                         canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
     464             : 
     465             :                         // if ViewState transform is changed, the clipping polygon needs to be adapted, too
     466           0 :                         const basegfx::B2DPolyPolygon aOldClipPolyPolygon(maClipPolyPolygon);
     467             : 
     468           0 :                         if(maClipPolyPolygon.count())
     469             :                         {
     470           0 :                             maClipPolyPolygon.transform(aDiscreteOffset);
     471           0 :                             maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
     472             :                         }
     473             : 
     474             :                         // paint content
     475           0 :                         process(rChildren);
     476             : 
     477             :                         // set to mask
     478           0 :                         mpOutputDevice = &aBufferDevice.getTransparence();
     479           0 :                         mxCanvas = mpOutputDevice->GetCanvas();
     480           0 :                         canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
     481             : 
     482             :                         // when painting transparence masks, reset the color stack
     483           0 :                         basegfx::BColorModifierStack aLastBColorModifierStack(maBColorModifierStack);
     484           0 :                         maBColorModifierStack = basegfx::BColorModifierStack();
     485             : 
     486             :                         // paint mask to it (always with transparence intensities, evtl. with AA)
     487           0 :                         process(rTransparence);
     488             : 
     489             :                         // back to old color stack, OutDev, Canvas and ViewTransform
     490           0 :                         maBColorModifierStack = aLastBColorModifierStack;
     491           0 :                         mpOutputDevice = pLastOutputDevice;
     492           0 :                         mxCanvas = xLastCanvas;
     493           0 :                         updateViewInformation(aLastViewInformation2D);
     494           0 :                         canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
     495             : 
     496             :                         // restore clipping polygon
     497           0 :                         maClipPolyPolygon = aOldClipPolyPolygon;
     498             : 
     499           0 :                         if(maClipPolyPolygon.count())
     500             :                         {
     501           0 :                             maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
     502             :                         }
     503             : 
     504             :                         // dump buffer to outdev
     505           0 :                         aBufferDevice.paint();
     506           0 :                     }
     507             :                 }
     508             :             }
     509           0 :         }
     510             : 
     511           0 :         void canvasProcessor2D::impRenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive)
     512             :         {
     513             :             // support direct fat line geometry. This moves the decomposition to the canvas.
     514             :             // As long as our canvases are used (which also use basegfx tooling) this makes
     515             :             // no difference, but potentially canvases may better support this
     516             :             static bool bSupportFatLineDirectly(true);
     517           0 :             bool bOutputDone(false);
     518             : 
     519           0 :             if(bSupportFatLineDirectly)
     520             :             {
     521           0 :                 const attribute::LineAttribute& rLineAttribute = rPolygonStrokePrimitive.getLineAttribute();
     522           0 :                 const attribute::StrokeAttribute& rStrokeAttribute = rPolygonStrokePrimitive.getStrokeAttribute();
     523             : 
     524           0 :                 if(0.0 < rLineAttribute.getWidth() || 0 != rStrokeAttribute.getDotDashArray().size())
     525             :                 {
     526           0 :                     rendering::StrokeAttributes aStrokeAttribute;
     527             : 
     528           0 :                     aStrokeAttribute.StrokeWidth = rLineAttribute.getWidth();
     529           0 :                     aStrokeAttribute.MiterLimit = 15.0; // degrees; maybe here (15.0 * F_PI180) is needed, not clear in the documentation
     530           0 :                     const ::std::vector< double >& rDotDashArray = rStrokeAttribute.getDotDashArray();
     531             : 
     532           0 :                     if(!rDotDashArray.empty())
     533             :                     {
     534           0 :                         aStrokeAttribute.DashArray = uno::Sequence< double >(&rDotDashArray[0], rDotDashArray.size());
     535             :                     }
     536             : 
     537           0 :                     switch(rLineAttribute.getLineJoin())
     538             :                     {
     539             :                         default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE
     540           0 :                             aStrokeAttribute.JoinType = rendering::PathJoinType::NONE;
     541           0 :                             break;
     542             :                         case basegfx::B2DLINEJOIN_BEVEL:
     543           0 :                             aStrokeAttribute.JoinType = rendering::PathJoinType::BEVEL;
     544           0 :                             break;
     545             :                         case basegfx::B2DLINEJOIN_MITER:
     546           0 :                             aStrokeAttribute.JoinType = rendering::PathJoinType::MITER;
     547           0 :                             break;
     548             :                         case basegfx::B2DLINEJOIN_ROUND:
     549           0 :                             aStrokeAttribute.JoinType = rendering::PathJoinType::ROUND;
     550           0 :                             break;
     551             :                     }
     552             : 
     553           0 :                     switch(rLineAttribute.getLineCap())
     554             :                     {
     555             :                         case com::sun::star::drawing::LineCap_ROUND:
     556           0 :                             aStrokeAttribute.StartCapType = rendering::PathCapType::ROUND;
     557           0 :                             aStrokeAttribute.EndCapType = rendering::PathCapType::ROUND;
     558           0 :                             break;
     559             :                         case com::sun::star::drawing::LineCap_SQUARE:
     560           0 :                             aStrokeAttribute.StartCapType = rendering::PathCapType::SQUARE;
     561           0 :                             aStrokeAttribute.EndCapType = rendering::PathCapType::SQUARE;
     562           0 :                             break;
     563             :                         default: // com::sun::star::drawing::LineCap_BUTT
     564           0 :                             aStrokeAttribute.StartCapType = rendering::PathCapType::BUTT;
     565           0 :                             aStrokeAttribute.EndCapType = rendering::PathCapType::BUTT;
     566           0 :                             break;
     567             :                     }
     568             : 
     569           0 :                     const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLineAttribute.getColor()));
     570           0 :                     maRenderState.DeviceColor = aHairlineColor.colorToDoubleSequence(mxCanvas->getDevice());
     571           0 :                     canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
     572             : 
     573           0 :                     mxCanvas->strokePolyPolygon(
     574           0 :                         basegfx::unotools::xPolyPolygonFromB2DPolygon(mxCanvas->getDevice(), rPolygonStrokePrimitive.getB2DPolygon()),
     575           0 :                         maViewState,  maRenderState, aStrokeAttribute);
     576             : 
     577           0 :                     bOutputDone = true;
     578             :                 }
     579             :             }
     580             : 
     581           0 :             if(!bOutputDone)
     582             :             {
     583             :                 // process decomposition
     584           0 :                 process(rPolygonStrokePrimitive.get2DDecomposition(getViewInformation2D()));
     585             :             }
     586           0 :         }
     587             : 
     588           0 :         void canvasProcessor2D::impRenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapPrimitive2D)
     589             :         {
     590             :             // support tiled fills directly when tiling is on
     591             :             static bool bSupportFillBitmapDirectly(true);
     592           0 :             bool bOutputDone(false);
     593             : 
     594           0 :             if(bSupportFillBitmapDirectly)
     595             :             {
     596           0 :                 const attribute::FillBitmapAttribute& rFillBitmapAttribute = rFillBitmapPrimitive2D.getFillBitmap();
     597             : 
     598           0 :                 if(rFillBitmapAttribute.getTiling())
     599             :                 {
     600             :                     // apply possible color modification to Bitmap
     601           0 :                     const BitmapEx aChangedBitmapEx(impModifyBitmapEx(maBColorModifierStack, rFillBitmapAttribute.getBitmapEx()));
     602             : 
     603           0 :                     if(aChangedBitmapEx.IsEmpty())
     604             :                     {
     605             :                         // replace with color filled polygon
     606           0 :                         const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
     607           0 :                         const basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon());
     608             : 
     609           0 :                         maRenderState.DeviceColor = aModifiedColor.colorToDoubleSequence(mxCanvas->getDevice());
     610             :                         canvas::tools::setRenderStateTransform(maRenderState,
     611           0 :                             getViewInformation2D().getObjectTransformation() * rFillBitmapPrimitive2D.getTransformation());
     612             : 
     613           0 :                         mxCanvas->fillPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
     614           0 :                             mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aPolygon)), maViewState,  maRenderState);
     615             :                     }
     616             :                     else
     617             :                     {
     618           0 :                         const Size aSizePixel(aChangedBitmapEx.GetSizePixel());
     619             : 
     620           0 :                         if(0 != aSizePixel.Width() && 0 != aSizePixel.Height())
     621             :                         {
     622             :                             // create texture matrix from texture to object (where object is unit square here),
     623             :                             // so use values directly
     624             :                             const basegfx::B2DHomMatrix aTextureMatrix(basegfx::tools::createScaleTranslateB2DHomMatrix(
     625           0 :                                 rFillBitmapAttribute.getSize().getX(), rFillBitmapAttribute.getSize().getY(),
     626           0 :                                 rFillBitmapAttribute.getTopLeft().getX(), rFillBitmapAttribute.getTopLeft().getY()));
     627             : 
     628             :                             // create and fill texture
     629           0 :                             rendering::Texture aTexture;
     630             : 
     631           0 :                             basegfx::unotools::affineMatrixFromHomMatrix(aTexture.AffineTransform, aTextureMatrix);
     632           0 :                             aTexture.Alpha = 1.0;
     633           0 :                             aTexture.Bitmap = vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(), aChangedBitmapEx);
     634           0 :                             aTexture.RepeatModeX = rendering::TexturingMode::REPEAT;
     635           0 :                             aTexture.RepeatModeY = rendering::TexturingMode::REPEAT;
     636             : 
     637             :                             // canvas needs a polygon to fill, create unit rectangle polygon
     638           0 :                             const basegfx::B2DPolygon aOutlineRectangle(basegfx::tools::createUnitPolygon());
     639             : 
     640             :                             // set primitive's transformation as render state transform
     641             :                             canvas::tools::setRenderStateTransform(maRenderState,
     642           0 :                                 getViewInformation2D().getObjectTransformation() * rFillBitmapPrimitive2D.getTransformation());
     643             : 
     644             :                             // put texture into a uno sequence for handover
     645           0 :                             uno::Sequence< rendering::Texture > aSeq(1);
     646           0 :                             aSeq[0] = aTexture;
     647             : 
     648             :                             // draw textured rectangle
     649           0 :                             mxCanvas->fillTexturedPolyPolygon(
     650           0 :                                 basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aOutlineRectangle)),
     651           0 :                                 maViewState, maRenderState, aSeq);
     652             :                         }
     653             :                     }
     654             : 
     655           0 :                     bOutputDone = true;
     656             :                 }
     657             :             }
     658             : 
     659           0 :             if(!bOutputDone)
     660             :             {
     661             :                 // process decomposition
     662           0 :                 process(rFillBitmapPrimitive2D.get2DDecomposition(getViewInformation2D()));
     663             :             }
     664           0 :         }
     665             : 
     666           0 :         void canvasProcessor2D::impRenderUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate)
     667             :         {
     668           0 :             if(0.0 == rUniTransparenceCandidate.getTransparence())
     669             :             {
     670             :                 // not transparent at all, directly use content
     671           0 :                 process(rUniTransparenceCandidate.getChildren());
     672             :             }
     673           0 :             else if(rUniTransparenceCandidate.getTransparence() > 0.0 && rUniTransparenceCandidate.getTransparence() < 1.0)
     674             :             {
     675           0 :                 const primitive2d::Primitive2DSequence rChildren = rUniTransparenceCandidate.getChildren();
     676             : 
     677           0 :                 if(rChildren.hasElements())
     678             :                 {
     679           0 :                     bool bOutputDone(false);
     680             : 
     681             :                     // Detect if a single PolyPolygonColorPrimitive2D is contained; in that case,
     682             :                     // use the fillPolyPolygon method with correctly set transparence. This is a often used
     683             :                     // case, so detectiong it is valuable
     684           0 :                     if(1 == rChildren.getLength())
     685             :                     {
     686           0 :                         const primitive2d::Primitive2DReference xReference(rChildren[0]);
     687           0 :                         const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get());
     688             : 
     689           0 :                         if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID())
     690             :                         {
     691             :                             // direct draw of PolyPolygon with color and transparence
     692           0 :                             const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
     693             : 
     694             :                             // add transparence modulation value to DeviceColor
     695           0 :                             uno::Sequence< double > aColor(4);
     696             : 
     697           0 :                             aColor[0] = aPolygonColor.getRed();
     698           0 :                             aColor[1] = aPolygonColor.getGreen();
     699           0 :                             aColor[2] = aPolygonColor.getBlue();
     700           0 :                             aColor[3] = 1.0 - rUniTransparenceCandidate.getTransparence();
     701           0 :                             maRenderState.DeviceColor = aColor;
     702             : 
     703           0 :                             canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
     704           0 :                             mxCanvas->fillPolyPolygon(
     705           0 :                                 basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), pPoPoColor->getB2DPolyPolygon()),
     706           0 :                                 maViewState,  maRenderState);
     707           0 :                             bOutputDone = true;
     708           0 :                         }
     709             :                     }
     710             : 
     711           0 :                     if(!bOutputDone)
     712             :                     {
     713             :                         // process decomposition. This will be decomposed to an TransparencePrimitive2D
     714             :                         // with the same child context and a single polygon for transparent context. This could be
     715             :                         // directly handled here with known VCL-buffer technology, but would only
     716             :                         // make a small difference compared to directly rendering the TransparencePrimitive2D
     717             :                         // using impRenderTransparencePrimitive2D above.
     718           0 :                         process(rUniTransparenceCandidate.get2DDecomposition(getViewInformation2D()));
     719             :                     }
     720           0 :                 }
     721             :             }
     722           0 :         }
     723             : 
     724             :         //////////////////////////////////////////////////////////////////////////////
     725             :         // internal processing support
     726             : 
     727           0 :         void canvasProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
     728             :         {
     729           0 :             switch(rCandidate.getPrimitive2DID())
     730             :             {
     731             :                 case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
     732             :                 {
     733             :                     // direct draw of hairline
     734           0 :                     const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate);
     735           0 :                     const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
     736             : 
     737           0 :                     maRenderState.DeviceColor = aHairlineColor.colorToDoubleSequence(mxCanvas->getDevice());
     738           0 :                     canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
     739           0 :                     mxCanvas->drawPolyPolygon(
     740           0 :                         basegfx::unotools::xPolyPolygonFromB2DPolygon(mxCanvas->getDevice(), rPolygonCandidate.getB2DPolygon()),
     741           0 :                         maViewState,  maRenderState);
     742             : 
     743           0 :                     break;
     744             :                 }
     745             :                 case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
     746             :                 {
     747             :                     // direct draw of PolyPolygon with color
     748           0 :                        const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate = static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate);
     749           0 :                     const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
     750             : 
     751           0 :                     maRenderState.DeviceColor = aPolygonColor.colorToDoubleSequence(mxCanvas->getDevice());
     752           0 :                     canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
     753           0 :                     mxCanvas->fillPolyPolygon(
     754           0 :                         basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), rPolygonCandidate.getB2DPolyPolygon()),
     755           0 :                         maViewState,  maRenderState);
     756             : 
     757           0 :                     break;
     758             :                 }
     759             :                 case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
     760             :                 {
     761             :                     // modified color group. Force output to unified color.
     762           0 :                     const primitive2d::ModifiedColorPrimitive2D& rModifiedCandidate = static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate);
     763             : 
     764           0 :                     if(rModifiedCandidate.getChildren().hasElements())
     765             :                     {
     766           0 :                         maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
     767           0 :                         process(rModifiedCandidate.getChildren());
     768           0 :                         maBColorModifierStack.pop();
     769             :                     }
     770             : 
     771           0 :                     break;
     772             :                 }
     773             :                 case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
     774             :                 {
     775             :                     // mask group
     776           0 :                     impRenderMaskPrimitive2D(static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate));
     777             : 
     778           0 :                     break;
     779             :                 }
     780             :                 case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
     781             :                 {
     782             :                     // transform group. Remember current ViewInformation2D
     783           0 :                     const primitive2d::TransformPrimitive2D& rTransformCandidate = static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate);
     784           0 :                     const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
     785             : 
     786             :                     // create new local ViewInformation2D with new transformation
     787             :                     const geometry::ViewInformation2D aViewInformation2D(
     788           0 :                         getViewInformation2D().getObjectTransformation()  * rTransformCandidate.getTransformation(),
     789           0 :                         getViewInformation2D().getViewTransformation(),
     790           0 :                         getViewInformation2D().getViewport(),
     791           0 :                         getViewInformation2D().getVisualizedPage(),
     792           0 :                         getViewInformation2D().getViewTime(),
     793           0 :                         getViewInformation2D().getExtendedInformationSequence());
     794           0 :                     updateViewInformation(aViewInformation2D);
     795             : 
     796             :                     // set at canvas
     797           0 :                     canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
     798             : 
     799             :                     // proccess content
     800           0 :                     process(rTransformCandidate.getChildren());
     801             : 
     802             :                     // restore transformations
     803           0 :                     updateViewInformation(aLastViewInformation2D);
     804             : 
     805             :                     // restore at canvas
     806           0 :                     canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
     807             : 
     808           0 :                     break;
     809             :                 }
     810             :                 case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
     811             :                 {
     812             :                     // new XDrawPage for ViewInformation2D
     813           0 :                     const primitive2d::PagePreviewPrimitive2D& rPagePreviewCandidate = static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate);
     814             : 
     815             :                     // remember current transformation and ViewInformation
     816           0 :                     const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
     817             : 
     818             :                     // create new local ViewInformation2D
     819             :                     const geometry::ViewInformation2D aViewInformation2D(
     820           0 :                         getViewInformation2D().getObjectTransformation(),
     821           0 :                         getViewInformation2D().getViewTransformation(),
     822           0 :                         getViewInformation2D().getViewport(),
     823           0 :                         rPagePreviewCandidate.getXDrawPage(),
     824           0 :                         getViewInformation2D().getViewTime(),
     825           0 :                         getViewInformation2D().getExtendedInformationSequence());
     826           0 :                     updateViewInformation(aViewInformation2D);
     827             : 
     828             :                     // proccess decomposed content
     829           0 :                     process(rPagePreviewCandidate.get2DDecomposition(getViewInformation2D()));
     830             : 
     831             :                     // restore transformations
     832           0 :                     updateViewInformation(aLastViewInformation2D);
     833           0 :                     break;
     834             :                 }
     835             :                 case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
     836             :                 {
     837             :                     // MetaFile primitive
     838           0 :                     impRenderMetafilePrimitive2D(static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate));
     839             : 
     840           0 :                     break;
     841             :                 }
     842             :                 case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
     843             :                 {
     844             :                     // PointArray primitive
     845           0 :                     const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate = static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate);
     846             : 
     847             :                     // set point color
     848           0 :                     const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rPointArrayCandidate.getRGBColor()));
     849           0 :                     maRenderState.DeviceColor = aRGBColor.colorToDoubleSequence(mxCanvas->getDevice());
     850           0 :                     canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
     851             : 
     852           0 :                     const std::vector< basegfx::B2DPoint >& rPointVector = rPointArrayCandidate.getPositions();
     853           0 :                     const sal_uInt32 nPointCount(rPointVector.size());
     854             : 
     855           0 :                     for(sal_uInt32 a(0); a < nPointCount; a++)
     856             :                     {
     857           0 :                         const basegfx::B2DPoint& rPoint = rPointVector[a];
     858           0 :                         mxCanvas->drawPoint(basegfx::unotools::point2DFromB2DPoint(rPoint), maViewState, maRenderState);
     859             :                     }
     860             : 
     861           0 :                     break;
     862             :                 }
     863             :                 case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
     864             :                 {
     865             :                     // TextSimplePortion primitive
     866           0 :                     impRenderTextSimplePortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate));
     867             : 
     868           0 :                     break;
     869             :                 }
     870             :                 case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
     871             :                 {
     872             :                     // Bitmap primitive
     873           0 :                     impRenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
     874             : 
     875           0 :                     break;
     876             :                 }
     877             :                 case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D :
     878             :                 {
     879             :                     // Transparence primitive
     880           0 :                     impRenderTransparencePrimitive2D(static_cast< const primitive2d::TransparencePrimitive2D& >(rCandidate));
     881             : 
     882           0 :                     break;
     883             :                 }
     884             :                 case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
     885             :                 {
     886             :                     // PolygonStrokePrimitive
     887           0 :                     impRenderPolygonStrokePrimitive2D(static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate));
     888             : 
     889           0 :                     break;
     890             :                 }
     891             :                 case PRIMITIVE2D_ID_FILLBITMAPPRIMITIVE2D :
     892             :                 {
     893             :                     // FillBitmapPrimitive2D
     894           0 :                     impRenderFillBitmapPrimitive2D(static_cast< const primitive2d::FillBitmapPrimitive2D& >(rCandidate));
     895             : 
     896           0 :                     break;
     897             :                 }
     898             :                 case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D :
     899             :                 {
     900             :                     // UnifiedTransparencePrimitive2D
     901           0 :                     impRenderUnifiedTransparencePrimitive2D(static_cast< const primitive2d::UnifiedTransparencePrimitive2D& >(rCandidate));
     902             : 
     903           0 :                     break;
     904             :                 }
     905             :                 case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
     906             :                 {
     907             :                     // wrong spell primitive. Handled directly here using VCL since VCL has a nice and
     908             :                     // very direct waveline painting which is needed for this. If VCL is to be avoided,
     909             :                     // this can be removed anytime and the decomposition may be used
     910           0 :                     const primitive2d::WrongSpellPrimitive2D& rWrongSpellPrimitive = static_cast< const primitive2d::WrongSpellPrimitive2D& >(rCandidate);
     911             : 
     912           0 :                     if(!renderWrongSpellPrimitive2D(
     913             :                         rWrongSpellPrimitive,
     914             :                         *mpOutputDevice,
     915           0 :                         getViewInformation2D().getObjectToViewTransformation(),
     916           0 :                         maBColorModifierStack))
     917             :                     {
     918             :                         // fallback to decomposition (MetaFile)
     919           0 :                         process(rWrongSpellPrimitive.get2DDecomposition(getViewInformation2D()));
     920             :                     }
     921             : 
     922           0 :                     break;
     923             :                 }
     924             : 
     925             :                 // nice to have:
     926             :                 //
     927             :                 // case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
     928             :                 // - support FormControls more direct eventually, not sure if this is needed
     929             :                 //   with the canvas renderer. The decomposition provides a bitmap representation
     930             :                 //   of the control which will work
     931             :                 //
     932             : 
     933             :                 default :
     934             :                 {
     935             :                     // process recursively
     936           0 :                     process(rCandidate.get2DDecomposition(getViewInformation2D()));
     937             : 
     938           0 :                     break;
     939             :                 }
     940             :             }
     941           0 :         }
     942             : 
     943             :         //////////////////////////////////////////////////////////////////////////////
     944             :         // process support
     945             : 
     946           0 :         canvasProcessor2D::canvasProcessor2D(
     947             :             const geometry::ViewInformation2D& rViewInformation,
     948             :             OutputDevice& rOutDev)
     949             :         :   BaseProcessor2D(rViewInformation),
     950             :             mpOutputDevice(&rOutDev),
     951             :             mxCanvas(rOutDev.GetCanvas()),
     952             :             maViewState(),
     953             :             maRenderState(),
     954             :             maBColorModifierStack(),
     955             :             maDrawinglayerOpt(),
     956             :             maClipPolyPolygon(),
     957           0 :             meLang(drawinglayer::detail::getDigitLanguage())
     958             :         {
     959           0 :             canvas::tools::initViewState(maViewState);
     960           0 :             canvas::tools::initRenderState(maRenderState);
     961           0 :             canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
     962             : 
     963             :             // set digit language, derived from SvtCTLOptions to have the correct
     964             :             // number display for arabic/hindi numerals
     965           0 :             rOutDev.SetDigitLanguage(meLang);
     966             : 
     967             :             // prepare output directly to pixels
     968           0 :                mpOutputDevice->Push(PUSH_MAPMODE);
     969           0 :             mpOutputDevice->SetMapMode();
     970             : 
     971             :             // react on AntiAliasing settings
     972           0 :             if(getOptionsDrawinglayer().IsAntiAliasing())
     973             :             {
     974           0 :                 mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW);
     975             :             }
     976             :             else
     977             :             {
     978           0 :                 mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW);
     979             :             }
     980           0 :         }
     981             : 
     982           0 :         canvasProcessor2D::~canvasProcessor2D()
     983             :         {
     984             :             // restore MapMode
     985           0 :                mpOutputDevice->Pop();
     986             : 
     987             :             // restore AntiAliasing
     988           0 :             mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW);
     989           0 :         }
     990             :     } // end of namespace processor2d
     991             : } // end of namespace drawinglayer
     992             : 
     993             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10