1464702f4SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3464702f4SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4464702f4SAndrew Rist * or more contributor license agreements. See the NOTICE file 5464702f4SAndrew Rist * distributed with this work for additional information 6464702f4SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7464702f4SAndrew Rist * to you under the Apache License, Version 2.0 (the 8464702f4SAndrew Rist * "License"); you may not use this file except in compliance 9464702f4SAndrew Rist * with the License. You may obtain a copy of the License at 10464702f4SAndrew Rist * 11464702f4SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12464702f4SAndrew Rist * 13464702f4SAndrew Rist * Unless required by applicable law or agreed to in writing, 14464702f4SAndrew Rist * software distributed under the License is distributed on an 15464702f4SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16464702f4SAndrew Rist * KIND, either express or implied. See the License for the 17464702f4SAndrew Rist * specific language governing permissions and limitations 18464702f4SAndrew Rist * under the License. 19464702f4SAndrew Rist * 20464702f4SAndrew Rist *************************************************************/ 21464702f4SAndrew Rist 22464702f4SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <drawinglayer/processor2d/vclmetafileprocessor2d.hxx> 28cdf0e10cSrcweir #include <tools/gen.hxx> 29cdf0e10cSrcweir #include <vcl/virdev.hxx> 30cdf0e10cSrcweir #include <vcl/gdimtf.hxx> 31cdf0e10cSrcweir #include <vcl/gradient.hxx> 32cdf0e10cSrcweir #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> 33cdf0e10cSrcweir #include <drawinglayer/primitive2d/textprimitive2d.hxx> 34cdf0e10cSrcweir #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> 35cdf0e10cSrcweir #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> 36cdf0e10cSrcweir #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> 37cdf0e10cSrcweir #include <drawinglayer/primitive2d/metafileprimitive2d.hxx> 38cdf0e10cSrcweir #include <drawinglayer/primitive2d/maskprimitive2d.hxx> 39cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygonclipper.hxx> 40cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx> 41cdf0e10cSrcweir #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> 42cdf0e10cSrcweir #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> 43cdf0e10cSrcweir #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx> 44cdf0e10cSrcweir #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx> 45cdf0e10cSrcweir #include <drawinglayer/processor2d/vclpixelprocessor2d.hxx> 46cdf0e10cSrcweir #include <tools/stream.hxx> 47cdf0e10cSrcweir #include <drawinglayer/primitive2d/transformprimitive2d.hxx> 48cdf0e10cSrcweir #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx> 49cdf0e10cSrcweir #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx> 50cdf0e10cSrcweir #include <vcl/graphictools.hxx> 51cdf0e10cSrcweir #include <vcl/metaact.hxx> 52cdf0e10cSrcweir #include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx> 53cdf0e10cSrcweir #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx> 54cdf0e10cSrcweir #include <comphelper/processfactory.hxx> 55cdf0e10cSrcweir #include <rtl/ustring.hxx> 56cdf0e10cSrcweir #include <com/sun/star/i18n/CharacterIteratorMode.hdl> 57cdf0e10cSrcweir #include <com/sun/star/i18n/WordType.hpp> 58cdf0e10cSrcweir #include <drawinglayer/primitive2d/controlprimitive2d.hxx> 59cdf0e10cSrcweir #include <drawinglayer/primitive2d/graphicprimitive2d.hxx> 60cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx> 61cdf0e10cSrcweir #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx> 62cdf0e10cSrcweir #include <drawinglayer/primitive2d/epsprimitive2d.hxx> 63cdf0e10cSrcweir #include <basegfx/polygon/b2dlinegeometry.hxx> 64cdf0e10cSrcweir 65cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 66cdf0e10cSrcweir // for PDFExtOutDevData Graphic support 67cdf0e10cSrcweir 68cdf0e10cSrcweir #include <vcl/graph.hxx> 69cdf0e10cSrcweir #include <vcl/svapp.hxx> 70cdf0e10cSrcweir #include <toolkit/helper/formpdfexport.hxx> 71cdf0e10cSrcweir 72cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 73cdf0e10cSrcweir // for Control printing 74cdf0e10cSrcweir 75cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp> 76cdf0e10cSrcweir 77cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 78cdf0e10cSrcweir // for StructureTagPrimitive support in sd's unomodel.cxx 79cdf0e10cSrcweir 80cdf0e10cSrcweir #include <drawinglayer/primitive2d/structuretagprimitive2d.hxx> 81cdf0e10cSrcweir 82cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 83cdf0e10cSrcweir 84cdf0e10cSrcweir using namespace com::sun::star; 85cdf0e10cSrcweir 86cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 87cdf0e10cSrcweir // #112245# definition for maximum allowed point count due to Metafile target. 88cdf0e10cSrcweir // To be on the safe side with the old tools polygon, use slightly less then 89cdf0e10cSrcweir // the theoretical maximum (bad experiences with tools polygon) 90cdf0e10cSrcweir 91cdf0e10cSrcweir #define MAX_POLYGON_POINT_COUNT_METAFILE (0x0000fff0) 92cdf0e10cSrcweir 93cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 94cdf0e10cSrcweir 95cdf0e10cSrcweir namespace 96cdf0e10cSrcweir { 97cdf0e10cSrcweir // #112245# helper to split line polygon in half 98cdf0e10cSrcweir void splitLinePolygon( 99cdf0e10cSrcweir const basegfx::B2DPolygon& rBasePolygon, 100cdf0e10cSrcweir basegfx::B2DPolygon& o_aLeft, 101cdf0e10cSrcweir basegfx::B2DPolygon& o_aRight) 102cdf0e10cSrcweir { 103cdf0e10cSrcweir const sal_uInt32 nCount(rBasePolygon.count()); 104cdf0e10cSrcweir 105cdf0e10cSrcweir if(nCount) 106cdf0e10cSrcweir { 107cdf0e10cSrcweir const sal_uInt32 nHalfCount((nCount - 1) >> 1); 108cdf0e10cSrcweir 109cdf0e10cSrcweir o_aLeft = basegfx::B2DPolygon(rBasePolygon, 0, nHalfCount + 1); 110cdf0e10cSrcweir o_aLeft.setClosed(false); 111cdf0e10cSrcweir 112cdf0e10cSrcweir o_aRight = basegfx::B2DPolygon(rBasePolygon, nHalfCount, nCount - nHalfCount); 113cdf0e10cSrcweir o_aRight.setClosed(false); 114cdf0e10cSrcweir 115cdf0e10cSrcweir if(rBasePolygon.isClosed()) 116cdf0e10cSrcweir { 117cdf0e10cSrcweir o_aRight.append(rBasePolygon.getB2DPoint(0)); 118cdf0e10cSrcweir 119cdf0e10cSrcweir if(rBasePolygon.areControlPointsUsed()) 120cdf0e10cSrcweir { 121cdf0e10cSrcweir o_aRight.setControlPoints( 122cdf0e10cSrcweir o_aRight.count() - 1, 123cdf0e10cSrcweir rBasePolygon.getPrevControlPoint(0), 124cdf0e10cSrcweir rBasePolygon.getNextControlPoint(0)); 125cdf0e10cSrcweir } 126cdf0e10cSrcweir } 127cdf0e10cSrcweir } 128cdf0e10cSrcweir else 129cdf0e10cSrcweir { 130cdf0e10cSrcweir o_aLeft.clear(); 131cdf0e10cSrcweir o_aRight.clear(); 132cdf0e10cSrcweir } 133cdf0e10cSrcweir } 134cdf0e10cSrcweir 135cdf0e10cSrcweir // #112245# helper to evtl. split filled polygons to maximum metafile point count 136cdf0e10cSrcweir bool fillPolyPolygonNeededToBeSplit(basegfx::B2DPolyPolygon& rPolyPolygon) 137cdf0e10cSrcweir { 138cdf0e10cSrcweir bool bRetval(false); 139cdf0e10cSrcweir const sal_uInt32 nPolyCount(rPolyPolygon.count()); 140cdf0e10cSrcweir 141cdf0e10cSrcweir if(nPolyCount) 142cdf0e10cSrcweir { 143cdf0e10cSrcweir basegfx::B2DPolyPolygon aSplitted; 144cdf0e10cSrcweir 145cdf0e10cSrcweir for(sal_uInt32 a(0); a < nPolyCount; a++) 146cdf0e10cSrcweir { 147cdf0e10cSrcweir const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a)); 148cdf0e10cSrcweir const sal_uInt32 nPointCount(aCandidate.count()); 149cdf0e10cSrcweir bool bNeedToSplit(false); 150cdf0e10cSrcweir 151cdf0e10cSrcweir if(aCandidate.areControlPointsUsed()) 152cdf0e10cSrcweir { 153cdf0e10cSrcweir // compare with the maximum for bezier curved polygons 154cdf0e10cSrcweir bNeedToSplit = nPointCount > ((MAX_POLYGON_POINT_COUNT_METAFILE / 3L) - 1L); 155cdf0e10cSrcweir } 156cdf0e10cSrcweir else 157cdf0e10cSrcweir { 158cdf0e10cSrcweir // compare with the maximum for simple point polygons 159cdf0e10cSrcweir bNeedToSplit = nPointCount > (MAX_POLYGON_POINT_COUNT_METAFILE - 1); 160cdf0e10cSrcweir } 161cdf0e10cSrcweir 162cdf0e10cSrcweir if(bNeedToSplit) 163cdf0e10cSrcweir { 164cdf0e10cSrcweir // need to split the partial polygon 165cdf0e10cSrcweir const basegfx::B2DRange aRange(aCandidate.getB2DRange()); 166cdf0e10cSrcweir const basegfx::B2DPoint aCenter(aRange.getCenter()); 167cdf0e10cSrcweir 168cdf0e10cSrcweir if(aRange.getWidth() > aRange.getHeight()) 169cdf0e10cSrcweir { 170cdf0e10cSrcweir // clip in left and right 171cdf0e10cSrcweir const basegfx::B2DPolyPolygon aLeft( 172cdf0e10cSrcweir basegfx::tools::clipPolygonOnParallelAxis( 173cdf0e10cSrcweir aCandidate, 174cdf0e10cSrcweir false, 175cdf0e10cSrcweir true, 176cdf0e10cSrcweir aCenter.getX(), 177cdf0e10cSrcweir false)); 178cdf0e10cSrcweir const basegfx::B2DPolyPolygon aRight( 179cdf0e10cSrcweir basegfx::tools::clipPolygonOnParallelAxis( 180cdf0e10cSrcweir aCandidate, 181cdf0e10cSrcweir false, 182cdf0e10cSrcweir false, 183cdf0e10cSrcweir aCenter.getX(), 184cdf0e10cSrcweir false)); 185cdf0e10cSrcweir 186cdf0e10cSrcweir aSplitted.append(aLeft); 187cdf0e10cSrcweir aSplitted.append(aRight); 188cdf0e10cSrcweir } 189cdf0e10cSrcweir else 190cdf0e10cSrcweir { 191cdf0e10cSrcweir // clip in top and bottom 192cdf0e10cSrcweir const basegfx::B2DPolyPolygon aTop( 193cdf0e10cSrcweir basegfx::tools::clipPolygonOnParallelAxis( 194cdf0e10cSrcweir aCandidate, 195cdf0e10cSrcweir true, 196cdf0e10cSrcweir true, 197cdf0e10cSrcweir aCenter.getY(), 198cdf0e10cSrcweir false)); 199cdf0e10cSrcweir const basegfx::B2DPolyPolygon aBottom( 200cdf0e10cSrcweir basegfx::tools::clipPolygonOnParallelAxis( 201cdf0e10cSrcweir aCandidate, 202cdf0e10cSrcweir true, 203cdf0e10cSrcweir false, 204cdf0e10cSrcweir aCenter.getY(), 205cdf0e10cSrcweir false)); 206cdf0e10cSrcweir 207cdf0e10cSrcweir aSplitted.append(aTop); 208cdf0e10cSrcweir aSplitted.append(aBottom); 209cdf0e10cSrcweir } 210cdf0e10cSrcweir } 211cdf0e10cSrcweir else 212cdf0e10cSrcweir { 213cdf0e10cSrcweir aSplitted.append(aCandidate); 214cdf0e10cSrcweir } 215cdf0e10cSrcweir } 216cdf0e10cSrcweir 217cdf0e10cSrcweir if(aSplitted.count() != nPolyCount) 218cdf0e10cSrcweir { 219cdf0e10cSrcweir rPolyPolygon = aSplitted; 220cdf0e10cSrcweir } 221cdf0e10cSrcweir } 222cdf0e10cSrcweir 223cdf0e10cSrcweir return bRetval; 224cdf0e10cSrcweir } 225cdf0e10cSrcweir } // end of anonymous namespace 226cdf0e10cSrcweir 227cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 228cdf0e10cSrcweir 229cdf0e10cSrcweir namespace drawinglayer 230cdf0e10cSrcweir { 231cdf0e10cSrcweir namespace processor2d 232cdf0e10cSrcweir { 233cdf0e10cSrcweir Rectangle VclMetafileProcessor2D::impDumpToMetaFile( 234cdf0e10cSrcweir const primitive2d::Primitive2DSequence& rContent, 235cdf0e10cSrcweir GDIMetaFile& o_rContentMetafile) 236cdf0e10cSrcweir { 237cdf0e10cSrcweir // Prepare VDev, MetaFile and connections 238cdf0e10cSrcweir OutputDevice* pLastOutputDevice = mpOutputDevice; 239cdf0e10cSrcweir GDIMetaFile* pLastMetafile = mpMetaFile; 240cdf0e10cSrcweir basegfx::B2DRange aPrimitiveRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D())); 241cdf0e10cSrcweir 242cdf0e10cSrcweir // transform primitive range with current transformation (e.g shadow offset) 243cdf0e10cSrcweir aPrimitiveRange.transform(maCurrentTransformation); 244cdf0e10cSrcweir 245cdf0e10cSrcweir const Rectangle aPrimitiveRectangle( 246cdf0e10cSrcweir basegfx::fround(aPrimitiveRange.getMinX()), basegfx::fround(aPrimitiveRange.getMinY()), 247cdf0e10cSrcweir basegfx::fround(aPrimitiveRange.getMaxX()), basegfx::fround(aPrimitiveRange.getMaxY())); 248cdf0e10cSrcweir VirtualDevice aContentVDev; 249cdf0e10cSrcweir MapMode aNewMapMode(pLastOutputDevice->GetMapMode()); 250cdf0e10cSrcweir 251cdf0e10cSrcweir mpOutputDevice = &aContentVDev; 252cdf0e10cSrcweir mpMetaFile = &o_rContentMetafile; 253cdf0e10cSrcweir aContentVDev.EnableOutput(false); 254cdf0e10cSrcweir aContentVDev.SetMapMode(pLastOutputDevice->GetMapMode()); 255cdf0e10cSrcweir o_rContentMetafile.Record(&aContentVDev); 256cdf0e10cSrcweir aContentVDev.SetLineColor(pLastOutputDevice->GetLineColor()); 257cdf0e10cSrcweir aContentVDev.SetFillColor(pLastOutputDevice->GetFillColor()); 258cdf0e10cSrcweir aContentVDev.SetFont(pLastOutputDevice->GetFont()); 259cdf0e10cSrcweir aContentVDev.SetDrawMode(pLastOutputDevice->GetDrawMode()); 260cdf0e10cSrcweir aContentVDev.SetSettings(pLastOutputDevice->GetSettings()); 261cdf0e10cSrcweir aContentVDev.SetRefPoint(pLastOutputDevice->GetRefPoint()); 262cdf0e10cSrcweir 263cdf0e10cSrcweir // dump to MetaFile 264cdf0e10cSrcweir process(rContent); 265cdf0e10cSrcweir 266cdf0e10cSrcweir // cleanups 267cdf0e10cSrcweir o_rContentMetafile.Stop(); 268cdf0e10cSrcweir o_rContentMetafile.WindStart(); 269cdf0e10cSrcweir aNewMapMode.SetOrigin(aPrimitiveRectangle.TopLeft()); 270cdf0e10cSrcweir o_rContentMetafile.SetPrefMapMode(aNewMapMode); 271cdf0e10cSrcweir o_rContentMetafile.SetPrefSize(aPrimitiveRectangle.GetSize()); 272cdf0e10cSrcweir mpOutputDevice = pLastOutputDevice; 273cdf0e10cSrcweir mpMetaFile = pLastMetafile; 274cdf0e10cSrcweir 275cdf0e10cSrcweir return aPrimitiveRectangle; 276cdf0e10cSrcweir } 277cdf0e10cSrcweir 278cdf0e10cSrcweir void VclMetafileProcessor2D::impConvertFillGradientAttributeToVCLGradient( 279cdf0e10cSrcweir Gradient& o_rVCLGradient, 280cdf0e10cSrcweir const attribute::FillGradientAttribute& rFiGrAtt, 281cdf0e10cSrcweir bool bIsTransparenceGradient) 282cdf0e10cSrcweir { 283cdf0e10cSrcweir if(bIsTransparenceGradient) 284cdf0e10cSrcweir { 285cdf0e10cSrcweir // it's about transparence channel intensities (black/white), do not use color modifier 286cdf0e10cSrcweir o_rVCLGradient.SetStartColor(Color(rFiGrAtt.getStartColor())); 287cdf0e10cSrcweir o_rVCLGradient.SetEndColor(Color(rFiGrAtt.getEndColor())); 288cdf0e10cSrcweir } 289cdf0e10cSrcweir else 290cdf0e10cSrcweir { 291cdf0e10cSrcweir // use color modifier to influence start/end color of gradient 292cdf0e10cSrcweir o_rVCLGradient.SetStartColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getStartColor()))); 293cdf0e10cSrcweir o_rVCLGradient.SetEndColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getEndColor()))); 294cdf0e10cSrcweir } 295cdf0e10cSrcweir 296cdf0e10cSrcweir o_rVCLGradient.SetAngle(static_cast< sal_uInt16 >(rFiGrAtt.getAngle() * (1.0 / F_PI1800))); 297cdf0e10cSrcweir o_rVCLGradient.SetBorder(static_cast< sal_uInt16 >(rFiGrAtt.getBorder() * 100.0)); 298cdf0e10cSrcweir o_rVCLGradient.SetOfsX(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetX() * 100.0)); 299cdf0e10cSrcweir o_rVCLGradient.SetOfsY(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetY() * 100.0)); 300cdf0e10cSrcweir o_rVCLGradient.SetSteps(rFiGrAtt.getSteps()); 301cdf0e10cSrcweir 302cdf0e10cSrcweir // defaults for intensity; those were computed into the start/end colors already 303cdf0e10cSrcweir o_rVCLGradient.SetStartIntensity(100); 304cdf0e10cSrcweir o_rVCLGradient.SetEndIntensity(100); 305cdf0e10cSrcweir 306cdf0e10cSrcweir switch(rFiGrAtt.getStyle()) 307cdf0e10cSrcweir { 308cdf0e10cSrcweir default : // attribute::GRADIENTSTYLE_LINEAR : 309cdf0e10cSrcweir { 310cdf0e10cSrcweir o_rVCLGradient.SetStyle(GRADIENT_LINEAR); 311cdf0e10cSrcweir break; 312cdf0e10cSrcweir } 313cdf0e10cSrcweir case attribute::GRADIENTSTYLE_AXIAL : 314cdf0e10cSrcweir { 315cdf0e10cSrcweir o_rVCLGradient.SetStyle(GRADIENT_AXIAL); 316cdf0e10cSrcweir break; 317cdf0e10cSrcweir } 318cdf0e10cSrcweir case attribute::GRADIENTSTYLE_RADIAL : 319cdf0e10cSrcweir { 320cdf0e10cSrcweir o_rVCLGradient.SetStyle(GRADIENT_RADIAL); 321cdf0e10cSrcweir break; 322cdf0e10cSrcweir } 323cdf0e10cSrcweir case attribute::GRADIENTSTYLE_ELLIPTICAL : 324cdf0e10cSrcweir { 325cdf0e10cSrcweir o_rVCLGradient.SetStyle(GRADIENT_ELLIPTICAL); 326cdf0e10cSrcweir break; 327cdf0e10cSrcweir } 328cdf0e10cSrcweir case attribute::GRADIENTSTYLE_SQUARE : 329cdf0e10cSrcweir { 330cdf0e10cSrcweir o_rVCLGradient.SetStyle(GRADIENT_SQUARE); 331cdf0e10cSrcweir break; 332cdf0e10cSrcweir } 333cdf0e10cSrcweir case attribute::GRADIENTSTYLE_RECT : 334cdf0e10cSrcweir { 335cdf0e10cSrcweir o_rVCLGradient.SetStyle(GRADIENT_RECT); 336cdf0e10cSrcweir break; 337cdf0e10cSrcweir } 338cdf0e10cSrcweir } 339cdf0e10cSrcweir } 340cdf0e10cSrcweir 341cdf0e10cSrcweir void VclMetafileProcessor2D::impStartSvtGraphicFill(SvtGraphicFill* pSvtGraphicFill) 342cdf0e10cSrcweir { 343cdf0e10cSrcweir if(pSvtGraphicFill && !mnSvtGraphicFillCount) 344cdf0e10cSrcweir { 345cdf0e10cSrcweir SvMemoryStream aMemStm; 346cdf0e10cSrcweir 347cdf0e10cSrcweir aMemStm << *pSvtGraphicFill; 348cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_BEGIN", 0, static_cast< const sal_uInt8* >(aMemStm.GetData()), aMemStm.Seek(STREAM_SEEK_TO_END))); 349cdf0e10cSrcweir mnSvtGraphicFillCount++; 350cdf0e10cSrcweir } 351cdf0e10cSrcweir } 352cdf0e10cSrcweir 353cdf0e10cSrcweir void VclMetafileProcessor2D::impEndSvtGraphicFill(SvtGraphicFill* pSvtGraphicFill) 354cdf0e10cSrcweir { 355cdf0e10cSrcweir if(pSvtGraphicFill && mnSvtGraphicFillCount) 356cdf0e10cSrcweir { 357cdf0e10cSrcweir mnSvtGraphicFillCount--; 358cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_END")); 359cdf0e10cSrcweir delete pSvtGraphicFill; 360cdf0e10cSrcweir } 361cdf0e10cSrcweir } 362cdf0e10cSrcweir 363cdf0e10cSrcweir SvtGraphicStroke* VclMetafileProcessor2D::impTryToCreateSvtGraphicStroke( 364cdf0e10cSrcweir const basegfx::B2DPolygon& rB2DPolygon, 365cdf0e10cSrcweir const basegfx::BColor* pColor, 366cdf0e10cSrcweir const attribute::LineAttribute* pLineAttribute, 367cdf0e10cSrcweir const attribute::StrokeAttribute* pStrokeAttribute, 368cdf0e10cSrcweir const attribute::LineStartEndAttribute* pStart, 369cdf0e10cSrcweir const attribute::LineStartEndAttribute* pEnd) 370cdf0e10cSrcweir { 371cdf0e10cSrcweir SvtGraphicStroke* pRetval = 0; 372cdf0e10cSrcweir 373cdf0e10cSrcweir if(rB2DPolygon.count() && !mnSvtGraphicStrokeCount) 374cdf0e10cSrcweir { 375cdf0e10cSrcweir basegfx::BColor aStrokeColor; 376cdf0e10cSrcweir basegfx::B2DPolyPolygon aStartArrow; 377cdf0e10cSrcweir basegfx::B2DPolyPolygon aEndArrow; 378cdf0e10cSrcweir 379cdf0e10cSrcweir if(pColor) 380cdf0e10cSrcweir { 381cdf0e10cSrcweir aStrokeColor = *pColor; 382cdf0e10cSrcweir } 383cdf0e10cSrcweir else if(pLineAttribute) 384cdf0e10cSrcweir { 385cdf0e10cSrcweir aStrokeColor = maBColorModifierStack.getModifiedColor(pLineAttribute->getColor()); 386cdf0e10cSrcweir } 387cdf0e10cSrcweir 388cdf0e10cSrcweir // It IS needed to record the stroke color at all in the metafile, 389cdf0e10cSrcweir // SvtGraphicStroke has NO entry for stroke color(!) 390cdf0e10cSrcweir mpOutputDevice->SetLineColor(Color(aStrokeColor)); 391cdf0e10cSrcweir 392cdf0e10cSrcweir if(!rB2DPolygon.isClosed()) 393cdf0e10cSrcweir { 394cdf0e10cSrcweir double fPolyLength(0.0); 395cdf0e10cSrcweir 396cdf0e10cSrcweir if(pStart && pStart->isActive()) 397cdf0e10cSrcweir { 398cdf0e10cSrcweir fPolyLength = basegfx::tools::getLength(rB2DPolygon); 399cdf0e10cSrcweir 400cdf0e10cSrcweir aStartArrow = basegfx::tools::createAreaGeometryForLineStartEnd( 401cdf0e10cSrcweir rB2DPolygon, pStart->getB2DPolyPolygon(), true, pStart->getWidth(), 402cdf0e10cSrcweir fPolyLength, pStart->isCentered() ? 0.5 : 0.0, 0); 403cdf0e10cSrcweir } 404cdf0e10cSrcweir 405cdf0e10cSrcweir if(pEnd && pEnd->isActive()) 406cdf0e10cSrcweir { 407cdf0e10cSrcweir if(basegfx::fTools::equalZero(fPolyLength)) 408cdf0e10cSrcweir { 409cdf0e10cSrcweir fPolyLength = basegfx::tools::getLength(rB2DPolygon); 410cdf0e10cSrcweir } 411cdf0e10cSrcweir 412cdf0e10cSrcweir aEndArrow = basegfx::tools::createAreaGeometryForLineStartEnd( 413cdf0e10cSrcweir rB2DPolygon, pEnd->getB2DPolyPolygon(), false, pEnd->getWidth(), 414cdf0e10cSrcweir fPolyLength, pEnd->isCentered() ? 0.5 : 0.0, 0); 415cdf0e10cSrcweir } 416cdf0e10cSrcweir } 417cdf0e10cSrcweir 4185aaf853bSArmin Le Grand SvtGraphicStroke::JoinType eJoin(SvtGraphicStroke::joinNone); 4195aaf853bSArmin Le Grand SvtGraphicStroke::CapType eCap(SvtGraphicStroke::capButt); 420cdf0e10cSrcweir double fLineWidth(0.0); 421cdf0e10cSrcweir double fMiterLength(0.0); 422cdf0e10cSrcweir SvtGraphicStroke::DashArray aDashArray; 423cdf0e10cSrcweir 424cdf0e10cSrcweir if(pLineAttribute) 425cdf0e10cSrcweir { 426b22f5784SArmin Le Grand // pre-fill fLineWidth #119198# Need to apply maCurrentTransformation, too (!) 427b22f5784SArmin Le Grand const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation * basegfx::B2DVector(pLineAttribute->getWidth(), 0.0)); 428b22f5784SArmin Le Grand fLineWidth = aDiscreteUnit.getLength(); 429cdf0e10cSrcweir 430cdf0e10cSrcweir // pre-fill fMiterLength 431cdf0e10cSrcweir fMiterLength = fLineWidth; 432cdf0e10cSrcweir 433cdf0e10cSrcweir // get Join 434cdf0e10cSrcweir switch(pLineAttribute->getLineJoin()) 435cdf0e10cSrcweir { 436cdf0e10cSrcweir default : // basegfx::B2DLINEJOIN_NONE : 437cdf0e10cSrcweir { 438cdf0e10cSrcweir eJoin = SvtGraphicStroke::joinNone; 439cdf0e10cSrcweir break; 440cdf0e10cSrcweir } 441cdf0e10cSrcweir case basegfx::B2DLINEJOIN_BEVEL : 442cdf0e10cSrcweir { 443cdf0e10cSrcweir eJoin = SvtGraphicStroke::joinBevel; 444cdf0e10cSrcweir break; 445cdf0e10cSrcweir } 446cdf0e10cSrcweir case basegfx::B2DLINEJOIN_MIDDLE : 447cdf0e10cSrcweir case basegfx::B2DLINEJOIN_MITER : 448cdf0e10cSrcweir { 449cdf0e10cSrcweir eJoin = SvtGraphicStroke::joinMiter; 450cdf0e10cSrcweir // ATM 15 degrees is assumed 451cdf0e10cSrcweir fMiterLength /= rtl::math::sin(M_PI * (15.0 / 360.0)); 452cdf0e10cSrcweir break; 453cdf0e10cSrcweir } 454cdf0e10cSrcweir case basegfx::B2DLINEJOIN_ROUND : 455cdf0e10cSrcweir { 456cdf0e10cSrcweir eJoin = SvtGraphicStroke::joinRound; 457cdf0e10cSrcweir break; 458cdf0e10cSrcweir } 459cdf0e10cSrcweir } 4605aaf853bSArmin Le Grand 4615aaf853bSArmin Le Grand // get stroke 4625aaf853bSArmin Le Grand switch(pLineAttribute->getLineCap()) 4635aaf853bSArmin Le Grand { 4645aaf853bSArmin Le Grand default: /* com::sun::star::drawing::LineCap_BUTT */ 4655aaf853bSArmin Le Grand { 4665aaf853bSArmin Le Grand eCap = SvtGraphicStroke::capButt; 4675aaf853bSArmin Le Grand break; 4685aaf853bSArmin Le Grand } 4695aaf853bSArmin Le Grand case com::sun::star::drawing::LineCap_ROUND: 4705aaf853bSArmin Le Grand { 4715aaf853bSArmin Le Grand eCap = SvtGraphicStroke::capRound; 4725aaf853bSArmin Le Grand break; 4735aaf853bSArmin Le Grand } 4745aaf853bSArmin Le Grand case com::sun::star::drawing::LineCap_SQUARE: 4755aaf853bSArmin Le Grand { 4765aaf853bSArmin Le Grand eCap = SvtGraphicStroke::capSquare; 4775aaf853bSArmin Le Grand break; 4785aaf853bSArmin Le Grand } 4795aaf853bSArmin Le Grand } 480cdf0e10cSrcweir } 481cdf0e10cSrcweir 482cdf0e10cSrcweir if(pStrokeAttribute) 483cdf0e10cSrcweir { 484cdf0e10cSrcweir // copy dash array 485cdf0e10cSrcweir aDashArray = pStrokeAttribute->getDotDashArray(); 486cdf0e10cSrcweir } 487cdf0e10cSrcweir 488cdf0e10cSrcweir // #i101734# apply current object transformation to created geometry. 489cdf0e10cSrcweir // This is a partial fix. When a object transformation is used which 490cdf0e10cSrcweir // e.g. contains a scaleX != scaleY, an unproportional scaling would 491cdf0e10cSrcweir // have to be applied to the evtl. existing fat line. The current 492cdf0e10cSrcweir // concept of PDF export and SvtGraphicStroke usage does simply not 493cdf0e10cSrcweir // allow handling such definitions. The only clean way would be to 494cdf0e10cSrcweir // add the transformation to SvtGraphicStroke and to handle it there 495cdf0e10cSrcweir basegfx::B2DPolygon aB2DPolygon(rB2DPolygon); 496cdf0e10cSrcweir 497cdf0e10cSrcweir aB2DPolygon.transform(maCurrentTransformation); 498cdf0e10cSrcweir aStartArrow.transform(maCurrentTransformation); 499cdf0e10cSrcweir aEndArrow.transform(maCurrentTransformation); 500cdf0e10cSrcweir 501cdf0e10cSrcweir pRetval = new SvtGraphicStroke( 502cdf0e10cSrcweir Polygon(aB2DPolygon), 503cdf0e10cSrcweir PolyPolygon(aStartArrow), 504cdf0e10cSrcweir PolyPolygon(aEndArrow), 505cdf0e10cSrcweir mfCurrentUnifiedTransparence, 506cdf0e10cSrcweir fLineWidth, 5075aaf853bSArmin Le Grand eCap, 508cdf0e10cSrcweir eJoin, 509cdf0e10cSrcweir fMiterLength, 510cdf0e10cSrcweir aDashArray); 511cdf0e10cSrcweir } 512cdf0e10cSrcweir 513cdf0e10cSrcweir return pRetval; 514cdf0e10cSrcweir } 515cdf0e10cSrcweir 516cdf0e10cSrcweir void VclMetafileProcessor2D::impStartSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke) 517cdf0e10cSrcweir { 518cdf0e10cSrcweir if(pSvtGraphicStroke && !mnSvtGraphicStrokeCount) 519cdf0e10cSrcweir { 520cdf0e10cSrcweir SvMemoryStream aMemStm; 521cdf0e10cSrcweir 522cdf0e10cSrcweir aMemStm << *pSvtGraphicStroke; 523cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_BEGIN", 0, static_cast< const sal_uInt8* >(aMemStm.GetData()), aMemStm.Seek(STREAM_SEEK_TO_END))); 524cdf0e10cSrcweir mnSvtGraphicStrokeCount++; 525cdf0e10cSrcweir } 526cdf0e10cSrcweir } 527cdf0e10cSrcweir 528cdf0e10cSrcweir void VclMetafileProcessor2D::impEndSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke) 529cdf0e10cSrcweir { 530cdf0e10cSrcweir if(pSvtGraphicStroke && mnSvtGraphicStrokeCount) 531cdf0e10cSrcweir { 532cdf0e10cSrcweir mnSvtGraphicStrokeCount--; 533cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_END")); 534cdf0e10cSrcweir delete pSvtGraphicStroke; 535cdf0e10cSrcweir } 536cdf0e10cSrcweir } 537cdf0e10cSrcweir 538cdf0e10cSrcweir // init static break iterator 539cdf0e10cSrcweir uno::Reference< ::com::sun::star::i18n::XBreakIterator > VclMetafileProcessor2D::mxBreakIterator; 540cdf0e10cSrcweir 541cdf0e10cSrcweir VclMetafileProcessor2D::VclMetafileProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev) 542cdf0e10cSrcweir : VclProcessor2D(rViewInformation, rOutDev), 543cdf0e10cSrcweir mpMetaFile(rOutDev.GetConnectMetaFile()), 544cdf0e10cSrcweir mnSvtGraphicFillCount(0), 545cdf0e10cSrcweir mnSvtGraphicStrokeCount(0), 546cdf0e10cSrcweir mfCurrentUnifiedTransparence(0.0), 547cdf0e10cSrcweir mpPDFExtOutDevData(dynamic_cast< vcl::PDFExtOutDevData* >(rOutDev.GetExtOutDevData())) 548cdf0e10cSrcweir { 549cdf0e10cSrcweir OSL_ENSURE(rOutDev.GetConnectMetaFile(), "VclMetafileProcessor2D: Used on OutDev which has no MetaFile Target (!)"); 550cdf0e10cSrcweir // draw to logic coordinates, do not initialize maCurrentTransformation to viewTransformation 551cdf0e10cSrcweir // but only to ObjectTransformation. Do not change MapMode of destination. 552cdf0e10cSrcweir maCurrentTransformation = rViewInformation.getObjectTransformation(); 553cdf0e10cSrcweir } 554cdf0e10cSrcweir 555cdf0e10cSrcweir VclMetafileProcessor2D::~VclMetafileProcessor2D() 556cdf0e10cSrcweir { 557cdf0e10cSrcweir // MapMode was not changed, no restore necessary 558cdf0e10cSrcweir } 559cdf0e10cSrcweir 560cdf0e10cSrcweir /*********************************************************************************************** 561cdf0e10cSrcweir 562cdf0e10cSrcweir Support of MetaCommentActions in the VclMetafileProcessor2D 563cdf0e10cSrcweir Found MetaCommentActions and how they are supported: 564cdf0e10cSrcweir 565cdf0e10cSrcweir XGRAD_SEQ_BEGIN, XGRAD_SEQ_END: 566cdf0e10cSrcweir 567cdf0e10cSrcweir Used inside OutputDevice::DrawGradient to mark the start and end of a MetaGradientEx action. 568cdf0e10cSrcweir It is used in various exporters/importers to have direct access to the gradient before it 569cdf0e10cSrcweir is rendered by VCL (and thus fragmented to polygon color actions and others). On that base, e.g. 570cdf0e10cSrcweir the Metafile to SdrObject import creates it's gradient objects. 571cdf0e10cSrcweir Best (and safest) way to support it here is to use PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D, 572cdf0e10cSrcweir map it back to the corresponding tools PolyPolygon and the Gradient and just call 573cdf0e10cSrcweir OutputDevice::DrawGradient which creates the necessary compatible actions. 574cdf0e10cSrcweir 575cdf0e10cSrcweir XPATHFILL_SEQ_BEGIN, XPATHFILL_SEQ_END: 576cdf0e10cSrcweir 577cdf0e10cSrcweir Two producers, one is vcl/source/gdi/gdimtf.cxx, line 1273. There, it is transformed 578cdf0e10cSrcweir inside GDIMetaFile::Rotate, nothing to take care of here. 579cdf0e10cSrcweir The second producer is in graphics/svx/source/svdraw/impgrfll.cxx, line 374. This is used 580cdf0e10cSrcweir with each incarnation of Imp_GraphicFill when a metafile is recorded, fillstyle is not 581cdf0e10cSrcweir XFILL_NONE and not completely transparent. It creates a SvtGraphicFill and streams it 582cdf0e10cSrcweir to the comment action. A closing end token is created in the destructor. 583cdf0e10cSrcweir Usages of Imp_GraphicFill are in Do_Paint_Object-methods of SdrCircObj, SdrPathObj and 584cdf0e10cSrcweir SdrRectObj. 585cdf0e10cSrcweir The token users pick various actions from SvtGraphicFill, so it may need to be added for all kind 586cdf0e10cSrcweir of filled objects, even simple colored polygons. It is added as extra information; the 587cdf0e10cSrcweir Metafile actions between the two tokens are interpreted as output generated from those 588cdf0e10cSrcweir fills. Thus, users have the choice to use the SvtGraphicFill info or the created output 589cdf0e10cSrcweir actions. 590cdf0e10cSrcweir Even for XFillTransparenceItem it is used, thus it may need to be supported in 591cdf0e10cSrcweir UnifiedTransparencePrimitive2D, too, when interpreted as normally filled PolyPolygon. 592cdf0e10cSrcweir Implemented for: 593035a2f44SArmin Le Grand PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D, 594cdf0e10cSrcweir PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D, 595cdf0e10cSrcweir PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D, 596cdf0e10cSrcweir PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D, 597cdf0e10cSrcweir and for PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D when detected unified transparence 598cdf0e10cSrcweir 599cdf0e10cSrcweir XPATHSTROKE_SEQ_BEGIN, XPATHSTROKE_SEQ_END: 600cdf0e10cSrcweir 601cdf0e10cSrcweir Similar to pathfill, but using SvtGraphicStroke instead. It also has two producers where one 602cdf0e10cSrcweir is also the GDIMetaFile::Rotate. Another user is MetaCommentAction::Move which modifies the 603cdf0e10cSrcweir contained path accordingly. 604cdf0e10cSrcweir The other one is SdrObject::Imp_DrawLineGeometry. It's done when MetaFile is set at OutDev and 605cdf0e10cSrcweir only when geometry is a single polygon (!). I see no reason for that; in the PS exporter this 606cdf0e10cSrcweir would hinder to make use of PolyPolygon strokes. I will need to add support at: 607cdf0e10cSrcweir PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D 608cdf0e10cSrcweir PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D 609cdf0e10cSrcweir PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D 610cdf0e10cSrcweir This can be done hierarchical, too. 611cdf0e10cSrcweir Okay, base implementation done based on those three primitives. 612cdf0e10cSrcweir 613cdf0e10cSrcweir FIELD_SEQ_BEGIN, FIELD_SEQ_END 614cdf0e10cSrcweir 615cdf0e10cSrcweir Used from slideshow for URLs, created from diverse SvxField implementations inside 616cdf0e10cSrcweir createBeginComment()/createEndComment(). createBeginComment() is used from editeng\impedit3.cxx 617cdf0e10cSrcweir inside ImpEditEngine::Paint. 618cdf0e10cSrcweir Created TextHierarchyFieldPrimitive2D and added needed infos there; it is an group primitive and wraps 619cdf0e10cSrcweir text primitives (but is not limited to that). It contains the field type if special actions for the 620cdf0e10cSrcweir support of FIELD_SEQ_BEGIN/END are needed; this is the case for Page and URL fields. If more is 621cdf0e10cSrcweir needed, it may be supported there. 622cdf0e10cSrcweir FIELD_SEQ_BEGIN;PageField 623cdf0e10cSrcweir FIELD_SEQ_END 624cdf0e10cSrcweir Okay, these are now completely supported by TextHierarchyFieldPrimitive2D. URL works, too. 625cdf0e10cSrcweir 626cdf0e10cSrcweir XTEXT 627cdf0e10cSrcweir 628cdf0e10cSrcweir XTEXT_EOC(i) end of character 629cdf0e10cSrcweir XTEXT_EOW(i) end of word 630cdf0e10cSrcweir XTEXT_EOS(i) end of sentence 631cdf0e10cSrcweir 632cdf0e10cSrcweir this three are with index and are created with the help of a i18n::XBreakIterator in 633cdf0e10cSrcweir ImplDrawWithComments. Simplifying, moving out text painting, reworking to create some 634cdf0e10cSrcweir data structure for holding those TEXT infos. 635cdf0e10cSrcweir Supported directly by TextSimplePortionPrimitive2D with adding a Locale to the basic text 636cdf0e10cSrcweir primitive. In the MetaFileRenderer, the creation is now done (see below). This has the advantage 637cdf0e10cSrcweir that this creations do not need to be done for all paints all the time. This would be 638cdf0e10cSrcweir expensive since the BreakIterator and it's usage is expensive and for each paint also the 639cdf0e10cSrcweir whole character stops would need to be created. 640cdf0e10cSrcweir Created only for TextDecoratedPortionPrimitive2D due to XTEXT_EOL and XTEXT_EOP (see below) 641cdf0e10cSrcweir 642cdf0e10cSrcweir XTEXT_EOL() end of line 643cdf0e10cSrcweir XTEXT_EOP() end of paragraph 644cdf0e10cSrcweir 645cdf0e10cSrcweir First try with boolean marks at TextDecoratedPortionPrimitive2D did not work too well, 646cdf0e10cSrcweir i decided to solve it with structure. I added the TextHierarchyPrimitives for this, 647cdf0e10cSrcweir namely: 648cdf0e10cSrcweir - TextHierarchyLinePrimitive2D: Encapsulates single line 649cdf0e10cSrcweir - TextHierarchyParagraphPrimitive2D: Encapsulates single paragraph 650cdf0e10cSrcweir - TextHierarchyBlockPrimitive2D: encapsulates object texts (only one ATM) 651cdf0e10cSrcweir Those are now supported in hierarchy. This means the MetaFile renderer will support them 652cdf0e10cSrcweir by using them, reculrively using their content and adding MetaFile comments as needed. 653cdf0e10cSrcweir This also means that when another text layouter will be used it will be necessary to 654cdf0e10cSrcweir create/support the same HierarchyPrimitives to support users. 655cdf0e10cSrcweir To transport the information using this hierarchy is best suited to all future needs; 656cdf0e10cSrcweir the slideshow will be able to profit from it directly when using primitives; all other 657cdf0e10cSrcweir renderers not interested in the text structure will just ignore the encapsulations. 658cdf0e10cSrcweir 659cdf0e10cSrcweir XTEXT_PAINTSHAPE_BEGIN, XTEXT_PAINTSHAPE_END 660cdf0e10cSrcweir Supported now by the TextHierarchyBlockPrimitive2D. 661cdf0e10cSrcweir 662cdf0e10cSrcweir EPSReplacementGraphic: 663cdf0e10cSrcweir Only used in goodies\source\filter.vcl\ieps\ieps.cxx and svx\source\xml\xmlgrhlp.cxx to 664cdf0e10cSrcweir hold the original EPS which was imported in the same MetaFile as first 2 entries. Only 665cdf0e10cSrcweir used to export the original again (if exists). 666cdf0e10cSrcweir Not necessary to support with MetaFuleRenderer. 667cdf0e10cSrcweir 668cdf0e10cSrcweir XTEXT_SCROLLRECT, XTEXT_PAINTRECT 669cdf0e10cSrcweir Currently used to get extra MetaFile infos using GraphicExporter which again uses 670cdf0e10cSrcweir SdrTextObj::GetTextScrollMetaFileAndRectangle(). ATM works with primitives since 671cdf0e10cSrcweir the rectangle data is added directly by the GraphicsExporter as comment. Does not need 672cdf0e10cSrcweir to be adapted at once. 673cdf0e10cSrcweir When adapting later, the only user - the diashow - should directly use the provided 674cdf0e10cSrcweir Anination infos in the appropriate primitives (e.g. AnimatedSwitchPrimitive2D) 675cdf0e10cSrcweir 676cdf0e10cSrcweir PRNSPOOL_TRANSPARENTBITMAP_BEGIN, PRNSPOOL_TRANSPARENTBITMAP_END 677cdf0e10cSrcweir VCL usage when printing PL -> THB. Okay, THB confirms that it is only used as 678cdf0e10cSrcweir a fix (hack) while VCL printing. It is needed to not downscale a bitmap which 679cdf0e10cSrcweir was explicitely created for the printer already again to some default maximum 680cdf0e10cSrcweir bitmap sizes. 681cdf0e10cSrcweir Nothing to do here for the primitive renderer. 682cdf0e10cSrcweir 683cdf0e10cSrcweir Support for vcl::PDFExtOutDevData: 684cdf0e10cSrcweir PL knows that SJ did that stuff, it's used to hold a pointer to PDFExtOutDevData at 685cdf0e10cSrcweir the OutDev. When set, some extra data is written there. Trying simple PDF export and 686cdf0e10cSrcweir watching if i get those infos. 687cdf0e10cSrcweir Well, a PDF export does not use e.g. ImpEditEngine::Paint since the PdfFilter uses 688cdf0e10cSrcweir the SdXImpressDocument::render and thus uses the VclMetafileProcessor2D. I will check 689cdf0e10cSrcweir if i get a PDFExtOutDevData at the target output device. 690cdf0e10cSrcweir Indeed, i get one. Checking what all may be done when that extra-device-info is there. 691cdf0e10cSrcweir 692cdf0e10cSrcweir All in all i have to talk to SJ. I will need to emulate some of those actions, but 693cdf0e10cSrcweir i need to discuss which ones. 694cdf0e10cSrcweir In the future, all those infos would be taken from the primitive sequence anyways, 695cdf0e10cSrcweir thus these extensions would potentially be temporary, too. 696cdf0e10cSrcweir Discussed with SJ, added the necessary support and tested it. Details follow. 697cdf0e10cSrcweir 698cdf0e10cSrcweir - In ImpEditEngine::Paint, paragraph infos and URL stuff is added. 699cdf0e10cSrcweir Added in primitive MetaFile renderer. 700cdf0e10cSrcweir Checking URL: Indeed, current version exports it, but it is missing in primitive 701cdf0e10cSrcweir CWS version. Adding support. 702cdf0e10cSrcweir Okay, URLs work. Checked, Done. 703cdf0e10cSrcweir 704cdf0e10cSrcweir - UnoControlPDFExportContact is only created when PDFExtOutDevData is used at the 705cdf0e10cSrcweir target and uno control data is created in UnoControlPDFExportContact::do_PaintObject. 706cdf0e10cSrcweir This may be added in primitive MetaFile renderer. 707cdf0e10cSrcweir Adding support... 708cdf0e10cSrcweir OOps, the necessary helper stuff is in svx/source/form/formpdxexport.cxx in namespace 709cdf0e10cSrcweir svxform. Have to talk to FS if this has to be like that. Especially since 710cdf0e10cSrcweir ::vcl::PDFWriter::AnyWidget is filled out, which is already part of vcl. 711cdf0e10cSrcweir Wrote an eMail to FS, he is on vacation currently. I see no reason why not to move 712cdf0e10cSrcweir that stuff to somewhere else, maybe tools or svtools ?!? We will see... 713cdf0e10cSrcweir Moved to toolkit, so i have to link against it. I tried VCL first, but it did 714cdf0e10cSrcweir not work since VCLUnoHelper::CreateFont is unresolved in VCL (!). Other then the name 715cdf0e10cSrcweir may imply, it is defined in toolkit (!). Since toolkit is linked against VCL itself, 716cdf0e10cSrcweir the lowest move,ment plave is toolkit. 717cdf0e10cSrcweir Checked form control export, it works well. Done. 718cdf0e10cSrcweir 719cdf0e10cSrcweir - In goodies, in GraphicObject::Draw, when the used Graphic is linked, infos are 720cdf0e10cSrcweir generated. I will need to check what happens here with primitives. 721cdf0e10cSrcweir To support, use of GraphicPrimitive2D (PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D) may be needed. 722cdf0e10cSrcweir Added support, but feature is broken in main version, so i cannot test at all. 723cdf0e10cSrcweir Writing a bug to CL (or SJ) and seeing what happens (#i80380#). 724cdf0e10cSrcweir SJ took a look and we got it working. Tested VCL MetaFile Renderer based export, 725cdf0e10cSrcweir as intended, the original file is exported. Works, Done. 726cdf0e10cSrcweir 727cdf0e10cSrcweir 728cdf0e10cSrcweir 729cdf0e10cSrcweir 730cdf0e10cSrcweir To be done: 731cdf0e10cSrcweir 732cdf0e10cSrcweir - Maybe there are more places to take care of for vcl::PDFExtOutDevData! 733cdf0e10cSrcweir 734cdf0e10cSrcweir 735cdf0e10cSrcweir 736cdf0e10cSrcweir ****************************************************************************************************/ 737cdf0e10cSrcweir 738cdf0e10cSrcweir void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate) 739cdf0e10cSrcweir { 740cdf0e10cSrcweir switch(rCandidate.getPrimitive2DID()) 741cdf0e10cSrcweir { 742cdf0e10cSrcweir case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D : 743cdf0e10cSrcweir { 744cdf0e10cSrcweir // directdraw of wrong spell primitive 745cdf0e10cSrcweir // Ignore for VclMetafileProcessor2D, this is for printing and MetaFile recording only 746cdf0e10cSrcweir break; 747cdf0e10cSrcweir } 748cdf0e10cSrcweir case PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D : 749cdf0e10cSrcweir { 750cdf0e10cSrcweir const primitive2d::GraphicPrimitive2D& rGraphicPrimitive = static_cast< const primitive2d::GraphicPrimitive2D& >(rCandidate); 751cdf0e10cSrcweir bool bUsingPDFExtOutDevData(false); 752cdf0e10cSrcweir basegfx::B2DVector aTranslate, aScale; 753cdf0e10cSrcweir static bool bSuppressPDFExtOutDevDataSupport(false); 754cdf0e10cSrcweir 755cdf0e10cSrcweir if(mpPDFExtOutDevData && !bSuppressPDFExtOutDevDataSupport) 756cdf0e10cSrcweir { 757cdf0e10cSrcweir // emulate data handling from UnoControlPDFExportContact, original see 758cdf0e10cSrcweir // svtools/source/graphic/grfmgr.cxx 759cdf0e10cSrcweir const Graphic& rGraphic = rGraphicPrimitive.getGraphicObject().GetGraphic(); 760cdf0e10cSrcweir 761cdf0e10cSrcweir if(rGraphic.IsLink()) 762cdf0e10cSrcweir { 763cdf0e10cSrcweir const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr(); 764cdf0e10cSrcweir 765cdf0e10cSrcweir if(!rAttr.IsSpecialDrawMode() && !rAttr.IsAdjusted()) 766cdf0e10cSrcweir { 767cdf0e10cSrcweir const basegfx::B2DHomMatrix& rTransform = rGraphicPrimitive.getTransform(); 768cdf0e10cSrcweir double fRotate, fShearX; 769cdf0e10cSrcweir rTransform.decompose(aScale, aTranslate, fRotate, fShearX); 770cdf0e10cSrcweir 771cdf0e10cSrcweir if( basegfx::fTools::equalZero( fRotate ) && ( aScale.getX() > 0.0 ) && ( aScale.getY() > 0.0 ) ) 772cdf0e10cSrcweir { 773cdf0e10cSrcweir bUsingPDFExtOutDevData = true; 774cdf0e10cSrcweir mpPDFExtOutDevData->BeginGroup(); 775cdf0e10cSrcweir } 776cdf0e10cSrcweir } 777cdf0e10cSrcweir } 778cdf0e10cSrcweir } 779cdf0e10cSrcweir 780cdf0e10cSrcweir // process recursively and add MetaFile comment 781cdf0e10cSrcweir process(rGraphicPrimitive.get2DDecomposition(getViewInformation2D())); 782cdf0e10cSrcweir 783cdf0e10cSrcweir if(bUsingPDFExtOutDevData) 784cdf0e10cSrcweir { 785cdf0e10cSrcweir // emulate data handling from UnoControlPDFExportContact, original see 786cdf0e10cSrcweir // svtools/source/graphic/grfmgr.cxx 787cdf0e10cSrcweir const basegfx::B2DRange aCurrentRange( 788cdf0e10cSrcweir aTranslate.getX(), aTranslate.getY(), 789cdf0e10cSrcweir aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY()); 790cdf0e10cSrcweir const Rectangle aCurrentRect( 791cdf0e10cSrcweir sal_Int32(floor(aCurrentRange.getMinX())), sal_Int32(floor(aCurrentRange.getMinY())), 792cdf0e10cSrcweir sal_Int32(ceil(aCurrentRange.getMaxX())), sal_Int32(ceil(aCurrentRange.getMaxY()))); 793cdf0e10cSrcweir const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr(); 794cdf0e10cSrcweir Rectangle aCropRect; 795cdf0e10cSrcweir 796cdf0e10cSrcweir if(rAttr.IsCropped()) 797cdf0e10cSrcweir { 798cdf0e10cSrcweir // calculate scalings between real image size and logic object size. This 799cdf0e10cSrcweir // is necessary since the crop values are relative to original bitmap size 800cdf0e10cSrcweir double fFactorX(1.0); 801cdf0e10cSrcweir double fFactorY(1.0); 802cdf0e10cSrcweir 803cdf0e10cSrcweir { 804cdf0e10cSrcweir const MapMode aMapMode100thmm(MAP_100TH_MM); 805cdf0e10cSrcweir const Size aBitmapSize(Application::GetDefaultDevice()->LogicToLogic( 806cdf0e10cSrcweir rGraphicPrimitive.getGraphicObject().GetPrefSize(), 807cdf0e10cSrcweir rGraphicPrimitive.getGraphicObject().GetPrefMapMode(), aMapMode100thmm)); 808cdf0e10cSrcweir const double fDivX(aBitmapSize.Width() - rAttr.GetLeftCrop() - rAttr.GetRightCrop()); 809cdf0e10cSrcweir const double fDivY(aBitmapSize.Height() - rAttr.GetTopCrop() - rAttr.GetBottomCrop()); 810cdf0e10cSrcweir 811cdf0e10cSrcweir if(!basegfx::fTools::equalZero(fDivX)) 812cdf0e10cSrcweir { 813cdf0e10cSrcweir fFactorX = aScale.getX() / fDivX; 814cdf0e10cSrcweir } 815cdf0e10cSrcweir 816cdf0e10cSrcweir if(!basegfx::fTools::equalZero(fDivY)) 817cdf0e10cSrcweir { 818cdf0e10cSrcweir fFactorY = aScale.getY() / fDivY; 819cdf0e10cSrcweir } 820cdf0e10cSrcweir } 821cdf0e10cSrcweir 822cdf0e10cSrcweir // calculate crop range and rect 823cdf0e10cSrcweir basegfx::B2DRange aCropRange; 824cdf0e10cSrcweir aCropRange.expand(aCurrentRange.getMinimum() - basegfx::B2DPoint(rAttr.GetLeftCrop() * fFactorX, rAttr.GetTopCrop() * fFactorY)); 825cdf0e10cSrcweir aCropRange.expand(aCurrentRange.getMaximum() + basegfx::B2DPoint(rAttr.GetRightCrop() * fFactorX, rAttr.GetBottomCrop() * fFactorY)); 826cdf0e10cSrcweir 827cdf0e10cSrcweir aCropRect = Rectangle( 828cdf0e10cSrcweir sal_Int32(floor(aCropRange.getMinX())), sal_Int32(floor(aCropRange.getMinY())), 829cdf0e10cSrcweir sal_Int32(ceil(aCropRange.getMaxX())), sal_Int32(ceil(aCropRange.getMaxY()))); 830cdf0e10cSrcweir } 831cdf0e10cSrcweir 832cdf0e10cSrcweir mpPDFExtOutDevData->EndGroup(rGraphicPrimitive.getGraphicObject().GetGraphic(), 833cdf0e10cSrcweir rAttr.GetTransparency(), 834cdf0e10cSrcweir aCurrentRect, 835cdf0e10cSrcweir aCropRect); 836cdf0e10cSrcweir } 837cdf0e10cSrcweir 838cdf0e10cSrcweir break; 839cdf0e10cSrcweir } 840cdf0e10cSrcweir case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D : 841cdf0e10cSrcweir { 842cdf0e10cSrcweir const primitive2d::ControlPrimitive2D& rControlPrimitive = static_cast< const primitive2d::ControlPrimitive2D& >(rCandidate); 843cdf0e10cSrcweir const uno::Reference< awt::XControl >& rXControl(rControlPrimitive.getXControl()); 844cdf0e10cSrcweir bool bIsPrintableControl(false); 845cdf0e10cSrcweir 846cdf0e10cSrcweir // find out if control is printable 847cdf0e10cSrcweir if(rXControl.is()) 848cdf0e10cSrcweir { 849cdf0e10cSrcweir try 850cdf0e10cSrcweir { 851cdf0e10cSrcweir uno::Reference< beans::XPropertySet > xModelProperties(rXControl->getModel(), uno::UNO_QUERY); 852cdf0e10cSrcweir uno::Reference< beans::XPropertySetInfo > xPropertyInfo(xModelProperties.is() 853cdf0e10cSrcweir ? xModelProperties->getPropertySetInfo() 854cdf0e10cSrcweir : uno::Reference< beans::XPropertySetInfo >()); 855cdf0e10cSrcweir const ::rtl::OUString sPrintablePropertyName(RTL_CONSTASCII_USTRINGPARAM("Printable")); 856cdf0e10cSrcweir 857cdf0e10cSrcweir if(xPropertyInfo.is() && xPropertyInfo->hasPropertyByName(sPrintablePropertyName)) 858cdf0e10cSrcweir { 859cdf0e10cSrcweir OSL_VERIFY(xModelProperties->getPropertyValue(sPrintablePropertyName) >>= bIsPrintableControl); 860cdf0e10cSrcweir } 861cdf0e10cSrcweir } 862cdf0e10cSrcweir catch(const uno::Exception&) 863cdf0e10cSrcweir { 864cdf0e10cSrcweir OSL_ENSURE(false, "VclMetafileProcessor2D: No access to printable flag of Control, caught an exception!"); 865cdf0e10cSrcweir } 866cdf0e10cSrcweir } 867cdf0e10cSrcweir 868cdf0e10cSrcweir // PDF export and printing only for printable controls 869cdf0e10cSrcweir if(bIsPrintableControl) 870cdf0e10cSrcweir { 871cdf0e10cSrcweir const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields()); 872cdf0e10cSrcweir bool bDoProcessRecursively(true); 873cdf0e10cSrcweir 874cdf0e10cSrcweir if(bPDFExport) 875cdf0e10cSrcweir { 876cdf0e10cSrcweir // PDF export. Emulate data handling from UnoControlPDFExportContact 877cdf0e10cSrcweir // I have now moved describePDFControl to toolkit, thus i can implement the PDF 878cdf0e10cSrcweir // form control support now as follows 879cdf0e10cSrcweir ::std::auto_ptr< ::vcl::PDFWriter::AnyWidget > pPDFControl; 880cdf0e10cSrcweir ::toolkitform::describePDFControl( rXControl, pPDFControl, *mpPDFExtOutDevData ); 881cdf0e10cSrcweir 882cdf0e10cSrcweir if(pPDFControl.get()) 883cdf0e10cSrcweir { 884cdf0e10cSrcweir // still need to fill in the location (is a class Rectangle) 885cdf0e10cSrcweir const basegfx::B2DRange aRangeLogic(rControlPrimitive.getB2DRange(getViewInformation2D())); 886cdf0e10cSrcweir const Rectangle aRectLogic( 887cdf0e10cSrcweir (sal_Int32)floor(aRangeLogic.getMinX()), (sal_Int32)floor(aRangeLogic.getMinY()), 888cdf0e10cSrcweir (sal_Int32)ceil(aRangeLogic.getMaxX()), (sal_Int32)ceil(aRangeLogic.getMaxY())); 889cdf0e10cSrcweir pPDFControl->Location = aRectLogic; 890cdf0e10cSrcweir 891cdf0e10cSrcweir Size aFontSize(pPDFControl->TextFont.GetSize()); 892cdf0e10cSrcweir aFontSize = mpOutputDevice->LogicToLogic(aFontSize, MapMode(MAP_POINT), mpOutputDevice->GetMapMode()); 893cdf0e10cSrcweir pPDFControl->TextFont.SetSize(aFontSize); 894cdf0e10cSrcweir 895cdf0e10cSrcweir mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Form); 896cdf0e10cSrcweir mpPDFExtOutDevData->CreateControl(*pPDFControl.get()); 897cdf0e10cSrcweir mpPDFExtOutDevData->EndStructureElement(); 898cdf0e10cSrcweir 899cdf0e10cSrcweir // no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject); 900cdf0e10cSrcweir // do not process recursively 901cdf0e10cSrcweir bDoProcessRecursively = false; 902cdf0e10cSrcweir } 903cdf0e10cSrcweir else 904cdf0e10cSrcweir { 905cdf0e10cSrcweir // PDF export did not work, try simple output. 906cdf0e10cSrcweir // Fallback to printer output by not setting bDoProcessRecursively 907cdf0e10cSrcweir // to false. 908cdf0e10cSrcweir } 909cdf0e10cSrcweir } 910cdf0e10cSrcweir 911cdf0e10cSrcweir // #i93169# used flag the wrong way; true means that nothing was done yet 912cdf0e10cSrcweir if(bDoProcessRecursively) 913cdf0e10cSrcweir { 914cdf0e10cSrcweir // printer output 915cdf0e10cSrcweir try 916cdf0e10cSrcweir { 917cdf0e10cSrcweir // remember old graphics and create new 918cdf0e10cSrcweir uno::Reference< awt::XView > xControlView(rXControl, uno::UNO_QUERY_THROW); 919cdf0e10cSrcweir const uno::Reference< awt::XGraphics > xOriginalGraphics(xControlView->getGraphics()); 920cdf0e10cSrcweir const uno::Reference< awt::XGraphics > xNewGraphics(mpOutputDevice->CreateUnoGraphics()); 921cdf0e10cSrcweir 922cdf0e10cSrcweir if(xNewGraphics.is()) 923cdf0e10cSrcweir { 924cdf0e10cSrcweir // link graphics and view 925cdf0e10cSrcweir xControlView->setGraphics(xNewGraphics); 926cdf0e10cSrcweir 927cdf0e10cSrcweir // get position 928cdf0e10cSrcweir const basegfx::B2DHomMatrix aObjectToDiscrete(getViewInformation2D().getObjectToViewTransformation() * rControlPrimitive.getTransform()); 929cdf0e10cSrcweir const basegfx::B2DPoint aTopLeftDiscrete(aObjectToDiscrete * basegfx::B2DPoint(0.0, 0.0)); 930cdf0e10cSrcweir 931cdf0e10cSrcweir // draw it 932cdf0e10cSrcweir xControlView->draw(basegfx::fround(aTopLeftDiscrete.getX()), basegfx::fround(aTopLeftDiscrete.getY())); 933cdf0e10cSrcweir bDoProcessRecursively = false; 934cdf0e10cSrcweir 935cdf0e10cSrcweir // restore original graphics 936cdf0e10cSrcweir xControlView->setGraphics(xOriginalGraphics); 937cdf0e10cSrcweir } 938cdf0e10cSrcweir } 939cdf0e10cSrcweir catch( const uno::Exception& ) 940cdf0e10cSrcweir { 941cdf0e10cSrcweir OSL_ENSURE(false, "VclMetafileProcessor2D: Printing of Control failed, caught an exception!"); 942cdf0e10cSrcweir } 943cdf0e10cSrcweir } 944cdf0e10cSrcweir 945cdf0e10cSrcweir // process recursively if not done yet to export as decomposition (bitmap) 946cdf0e10cSrcweir if(bDoProcessRecursively) 947cdf0e10cSrcweir { 948cdf0e10cSrcweir process(rControlPrimitive.get2DDecomposition(getViewInformation2D())); 949cdf0e10cSrcweir } 950cdf0e10cSrcweir } 951cdf0e10cSrcweir 952cdf0e10cSrcweir break; 953cdf0e10cSrcweir } 954cdf0e10cSrcweir case PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D : 955cdf0e10cSrcweir { 956cdf0e10cSrcweir // support for FIELD_SEQ_BEGIN, FIELD_SEQ_END and URL. It wraps text primitives (but is not limited to) 957cdf0e10cSrcweir // thus do the MetafileAction embedding stuff but just handle recursively. 958cdf0e10cSrcweir const primitive2d::TextHierarchyFieldPrimitive2D& rFieldPrimitive = static_cast< const primitive2d::TextHierarchyFieldPrimitive2D& >(rCandidate); 959cdf0e10cSrcweir static const ByteString aCommentStringCommon("FIELD_SEQ_BEGIN"); 960cdf0e10cSrcweir static const ByteString aCommentStringPage("FIELD_SEQ_BEGIN;PageField"); 961cdf0e10cSrcweir static const ByteString aCommentStringEnd("FIELD_SEQ_END"); 962cdf0e10cSrcweir 963cdf0e10cSrcweir switch(rFieldPrimitive.getType()) 964cdf0e10cSrcweir { 965cdf0e10cSrcweir default : // case drawinglayer::primitive2d::FIELD_TYPE_COMMON : 966cdf0e10cSrcweir { 967cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon)); 968cdf0e10cSrcweir break; 969cdf0e10cSrcweir } 970cdf0e10cSrcweir case drawinglayer::primitive2d::FIELD_TYPE_PAGE : 971cdf0e10cSrcweir { 972cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringPage)); 973cdf0e10cSrcweir break; 974cdf0e10cSrcweir } 975cdf0e10cSrcweir case drawinglayer::primitive2d::FIELD_TYPE_URL : 976cdf0e10cSrcweir { 977cdf0e10cSrcweir const rtl::OUString& rURL = rFieldPrimitive.getString(); 978cdf0e10cSrcweir const String aOldString(rURL); 979cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast< const sal_uInt8* >(aOldString.GetBuffer()), 2 * aOldString.Len())); 980cdf0e10cSrcweir break; 981cdf0e10cSrcweir } 982cdf0e10cSrcweir } 983cdf0e10cSrcweir 984cdf0e10cSrcweir // process recursively 985cdf0e10cSrcweir const primitive2d::Primitive2DSequence rContent = rFieldPrimitive.get2DDecomposition(getViewInformation2D()); 986cdf0e10cSrcweir process(rContent); 987cdf0e10cSrcweir 988cdf0e10cSrcweir // for the end comment the type is not relevant yet, they are all the same. Just add. 989cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringEnd)); 990cdf0e10cSrcweir 991cdf0e10cSrcweir if(mpPDFExtOutDevData && drawinglayer::primitive2d::FIELD_TYPE_URL == rFieldPrimitive.getType()) 992cdf0e10cSrcweir { 993cdf0e10cSrcweir // emulate data handling from ImpEditEngine::Paint 994cdf0e10cSrcweir const basegfx::B2DRange aViewRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D())); 995cdf0e10cSrcweir const Rectangle aRectLogic( 996cdf0e10cSrcweir (sal_Int32)floor(aViewRange.getMinX()), (sal_Int32)floor(aViewRange.getMinY()), 997cdf0e10cSrcweir (sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY())); 998cdf0e10cSrcweir vcl::PDFExtOutDevBookmarkEntry aBookmark; 999cdf0e10cSrcweir aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic); 1000cdf0e10cSrcweir aBookmark.aBookmark = rFieldPrimitive.getString(); 1001cdf0e10cSrcweir std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = mpPDFExtOutDevData->GetBookmarks(); 1002cdf0e10cSrcweir rBookmarks.push_back( aBookmark ); 1003cdf0e10cSrcweir } 1004cdf0e10cSrcweir 1005cdf0e10cSrcweir break; 1006cdf0e10cSrcweir } 1007cdf0e10cSrcweir case PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D : 1008cdf0e10cSrcweir { 1009cdf0e10cSrcweir const primitive2d::TextHierarchyLinePrimitive2D& rLinePrimitive = static_cast< const primitive2d::TextHierarchyLinePrimitive2D& >(rCandidate); 1010cdf0e10cSrcweir static const ByteString aCommentString("XTEXT_EOL"); 1011cdf0e10cSrcweir 1012cdf0e10cSrcweir // process recursively and add MetaFile comment 1013cdf0e10cSrcweir process(rLinePrimitive.get2DDecomposition(getViewInformation2D())); 1014cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentString)); 1015cdf0e10cSrcweir 1016cdf0e10cSrcweir break; 1017cdf0e10cSrcweir } 1018cdf0e10cSrcweir case PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D : 1019cdf0e10cSrcweir { 1020cdf0e10cSrcweir // in Outliner::PaintBullet(), a MetafileComment for bullets is added, too. The 1021cdf0e10cSrcweir // "XTEXT_EOC" is used, use here, too. 1022cdf0e10cSrcweir const primitive2d::TextHierarchyBulletPrimitive2D& rBulletPrimitive = static_cast< const primitive2d::TextHierarchyBulletPrimitive2D& >(rCandidate); 1023cdf0e10cSrcweir static const ByteString aCommentString("XTEXT_EOC"); 1024cdf0e10cSrcweir 1025cdf0e10cSrcweir // process recursively and add MetaFile comment 1026cdf0e10cSrcweir process(rBulletPrimitive.get2DDecomposition(getViewInformation2D())); 1027cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentString)); 1028cdf0e10cSrcweir 1029cdf0e10cSrcweir break; 1030cdf0e10cSrcweir } 1031cdf0e10cSrcweir case PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D : 1032cdf0e10cSrcweir { 1033cdf0e10cSrcweir const primitive2d::TextHierarchyParagraphPrimitive2D& rParagraphPrimitive = static_cast< const primitive2d::TextHierarchyParagraphPrimitive2D& >(rCandidate); 1034cdf0e10cSrcweir static const ByteString aCommentString("XTEXT_EOP"); 1035cdf0e10cSrcweir 1036cdf0e10cSrcweir if(mpPDFExtOutDevData) 1037cdf0e10cSrcweir { 1038cdf0e10cSrcweir // emulate data handling from ImpEditEngine::Paint 1039cdf0e10cSrcweir mpPDFExtOutDevData->BeginStructureElement( vcl::PDFWriter::Paragraph ); 1040cdf0e10cSrcweir } 1041cdf0e10cSrcweir 1042cdf0e10cSrcweir // process recursively and add MetaFile comment 1043cdf0e10cSrcweir process(rParagraphPrimitive.get2DDecomposition(getViewInformation2D())); 1044cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentString)); 1045cdf0e10cSrcweir 1046cdf0e10cSrcweir if(mpPDFExtOutDevData) 1047cdf0e10cSrcweir { 1048cdf0e10cSrcweir // emulate data handling from ImpEditEngine::Paint 1049cdf0e10cSrcweir mpPDFExtOutDevData->EndStructureElement(); 1050cdf0e10cSrcweir } 1051cdf0e10cSrcweir 1052cdf0e10cSrcweir break; 1053cdf0e10cSrcweir } 1054cdf0e10cSrcweir case PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D : 1055cdf0e10cSrcweir { 1056cdf0e10cSrcweir const primitive2d::TextHierarchyBlockPrimitive2D& rBlockPrimitive = static_cast< const primitive2d::TextHierarchyBlockPrimitive2D& >(rCandidate); 1057cdf0e10cSrcweir static const ByteString aCommentStringA("XTEXT_PAINTSHAPE_BEGIN"); 1058cdf0e10cSrcweir static const ByteString aCommentStringB("XTEXT_PAINTSHAPE_END"); 1059cdf0e10cSrcweir 1060cdf0e10cSrcweir // add MetaFile comment, process recursively and add MetaFile comment 1061cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA)); 1062cdf0e10cSrcweir process(rBlockPrimitive.get2DDecomposition(getViewInformation2D())); 1063cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB)); 1064cdf0e10cSrcweir 1065cdf0e10cSrcweir break; 1066cdf0e10cSrcweir } 1067cdf0e10cSrcweir case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D : 1068cdf0e10cSrcweir case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D : 1069cdf0e10cSrcweir { 1070cdf0e10cSrcweir // for supporting TEXT_ MetaFile actions there is more to do here; get the candidate 1071cdf0e10cSrcweir const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate = static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate); 1072cdf0e10cSrcweir // const primitive2d::TextDecoratedPortionPrimitive2D* pTextDecoratedCandidate = dynamic_cast< const primitive2d::TextDecoratedPortionPrimitive2D* >(&rCandidate); 1073cdf0e10cSrcweir 1074cdf0e10cSrcweir // Adapt evtl. used special DrawMode 1075cdf0e10cSrcweir const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode()); 1076cdf0e10cSrcweir adaptTextToFillDrawMode(); 1077cdf0e10cSrcweir 1078cdf0e10cSrcweir // directdraw of text simple portion; use default processing 1079cdf0e10cSrcweir RenderTextSimpleOrDecoratedPortionPrimitive2D(rTextCandidate); 1080cdf0e10cSrcweir 1081cdf0e10cSrcweir // restore DrawMode 1082cdf0e10cSrcweir mpOutputDevice->SetDrawMode(nOriginalDrawMode); 1083cdf0e10cSrcweir 1084cdf0e10cSrcweir // #i101169# if(pTextDecoratedCandidate) 1085cdf0e10cSrcweir { 1086cdf0e10cSrcweir // support for TEXT_ MetaFile actions only for decorated texts 1087cdf0e10cSrcweir if(!mxBreakIterator.is()) 1088cdf0e10cSrcweir { 1089cdf0e10cSrcweir uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory()); 1090cdf0e10cSrcweir mxBreakIterator.set(xMSF->createInstance(rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator")), uno::UNO_QUERY); 1091cdf0e10cSrcweir } 1092cdf0e10cSrcweir 1093cdf0e10cSrcweir if(mxBreakIterator.is()) 1094cdf0e10cSrcweir { 1095cdf0e10cSrcweir const rtl::OUString& rTxt = rTextCandidate.getText(); 1096cdf0e10cSrcweir const sal_Int32 nTextLength(rTextCandidate.getTextLength()); // rTxt.getLength()); 1097cdf0e10cSrcweir 1098cdf0e10cSrcweir if(nTextLength) 1099cdf0e10cSrcweir { 1100cdf0e10cSrcweir const ::com::sun::star::lang::Locale& rLocale = rTextCandidate.getLocale(); 1101cdf0e10cSrcweir const sal_Int32 nTextPosition(rTextCandidate.getTextPosition()); 1102cdf0e10cSrcweir 1103cdf0e10cSrcweir sal_Int32 nDone; 1104cdf0e10cSrcweir sal_Int32 nNextCellBreak(mxBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone)); 1105cdf0e10cSrcweir ::com::sun::star::i18n::Boundary nNextWordBoundary(mxBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True)); 1106cdf0e10cSrcweir sal_Int32 nNextSentenceBreak(mxBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale)); 1107cdf0e10cSrcweir static const ByteString aCommentStringA("XTEXT_EOC"); 1108cdf0e10cSrcweir static const ByteString aCommentStringB("XTEXT_EOW"); 1109cdf0e10cSrcweir static const ByteString aCommentStringC("XTEXT_EOS"); 1110cdf0e10cSrcweir 1111cdf0e10cSrcweir for(sal_Int32 i(nTextPosition); i < nTextPosition + nTextLength; i++) 1112cdf0e10cSrcweir { 1113cdf0e10cSrcweir // create the entries for the respective break positions 1114cdf0e10cSrcweir if(i == nNextCellBreak) 1115cdf0e10cSrcweir { 1116cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA, i - nTextPosition)); 1117cdf0e10cSrcweir nNextCellBreak = mxBreakIterator->nextCharacters(rTxt, i, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone); 1118cdf0e10cSrcweir } 1119cdf0e10cSrcweir if(i == nNextWordBoundary.endPos) 1120cdf0e10cSrcweir { 1121cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB, i - nTextPosition)); 1122cdf0e10cSrcweir nNextWordBoundary = mxBreakIterator->getWordBoundary(rTxt, i + 1, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True); 1123cdf0e10cSrcweir } 1124cdf0e10cSrcweir if(i == nNextSentenceBreak) 1125cdf0e10cSrcweir { 1126cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringC, i - nTextPosition)); 1127cdf0e10cSrcweir nNextSentenceBreak = mxBreakIterator->endOfSentence(rTxt, i + 1, rLocale); 1128cdf0e10cSrcweir } 1129cdf0e10cSrcweir } 1130cdf0e10cSrcweir } 1131cdf0e10cSrcweir } 1132cdf0e10cSrcweir } 1133cdf0e10cSrcweir 1134cdf0e10cSrcweir break; 1135cdf0e10cSrcweir } 1136cdf0e10cSrcweir case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D : 1137cdf0e10cSrcweir { 1138cdf0e10cSrcweir const primitive2d::PolygonHairlinePrimitive2D& rHairlinePrimitive = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate); 1139cdf0e10cSrcweir const basegfx::B2DPolygon& rBasePolygon = rHairlinePrimitive.getB2DPolygon(); 1140cdf0e10cSrcweir 1141cdf0e10cSrcweir if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1)) 1142cdf0e10cSrcweir { 1143cdf0e10cSrcweir // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 1144cdf0e10cSrcweir // per polygon. If there are more, split the polygon in half and call recursively 1145cdf0e10cSrcweir basegfx::B2DPolygon aLeft, aRight; 1146cdf0e10cSrcweir splitLinePolygon(rBasePolygon, aLeft, aRight); 1147cdf0e10cSrcweir const primitive2d::PolygonHairlinePrimitive2D aPLeft(aLeft, rHairlinePrimitive.getBColor()); 1148cdf0e10cSrcweir const primitive2d::PolygonHairlinePrimitive2D aPRight(aRight, rHairlinePrimitive.getBColor()); 1149cdf0e10cSrcweir 1150cdf0e10cSrcweir processBasePrimitive2D(aPLeft); 1151cdf0e10cSrcweir processBasePrimitive2D(aPRight); 1152cdf0e10cSrcweir } 1153cdf0e10cSrcweir else 1154cdf0e10cSrcweir { 1155cdf0e10cSrcweir // direct draw of hairline; use default processing 1156cdf0e10cSrcweir // support SvtGraphicStroke MetaCommentAction 1157cdf0e10cSrcweir const basegfx::BColor aLineColor(maBColorModifierStack.getModifiedColor(rHairlinePrimitive.getBColor())); 1158*4665f8d3SArmin Le Grand SvtGraphicStroke* pSvtGraphicStroke = 0; 1159*4665f8d3SArmin Le Grand 1160*4665f8d3SArmin Le Grand // #121267# Not needed, does not give better quality compared with 1161*4665f8d3SArmin Le Grand // the META_POLYPOLYGON_ACTION written by RenderPolygonHairlinePrimitive2D 1162*4665f8d3SArmin Le Grand // below 1163*4665f8d3SArmin Le Grand bool bSupportSvtGraphicStroke(false); 1164*4665f8d3SArmin Le Grand 1165*4665f8d3SArmin Le Grand if(bSupportSvtGraphicStroke) 1166*4665f8d3SArmin Le Grand { 1167*4665f8d3SArmin Le Grand pSvtGraphicStroke = impTryToCreateSvtGraphicStroke( 1168*4665f8d3SArmin Le Grand rHairlinePrimitive.getB2DPolygon(), 1169*4665f8d3SArmin Le Grand &aLineColor, 1170*4665f8d3SArmin Le Grand 0, 0, 0, 0); 1171*4665f8d3SArmin Le Grand 1172*4665f8d3SArmin Le Grand impStartSvtGraphicStroke(pSvtGraphicStroke); 1173*4665f8d3SArmin Le Grand } 1174cdf0e10cSrcweir 1175cdf0e10cSrcweir RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate), false); 1176*4665f8d3SArmin Le Grand 1177*4665f8d3SArmin Le Grand if(bSupportSvtGraphicStroke) 1178*4665f8d3SArmin Le Grand { 1179*4665f8d3SArmin Le Grand impEndSvtGraphicStroke(pSvtGraphicStroke); 1180*4665f8d3SArmin Le Grand } 1181cdf0e10cSrcweir } 1182cdf0e10cSrcweir break; 1183cdf0e10cSrcweir } 1184cdf0e10cSrcweir case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D : 1185cdf0e10cSrcweir { 1186cdf0e10cSrcweir const primitive2d::PolygonStrokePrimitive2D& rStrokePrimitive = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate); 1187cdf0e10cSrcweir const basegfx::B2DPolygon& rBasePolygon = rStrokePrimitive.getB2DPolygon(); 1188cdf0e10cSrcweir 1189cdf0e10cSrcweir if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1)) 1190cdf0e10cSrcweir { 1191cdf0e10cSrcweir // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 1192cdf0e10cSrcweir // per polygon. If there are more, split the polygon in half and call recursively 1193cdf0e10cSrcweir basegfx::B2DPolygon aLeft, aRight; 1194cdf0e10cSrcweir splitLinePolygon(rBasePolygon, aLeft, aRight); 1195cdf0e10cSrcweir const primitive2d::PolygonStrokePrimitive2D aPLeft( 1196cdf0e10cSrcweir aLeft, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute()); 1197cdf0e10cSrcweir const primitive2d::PolygonStrokePrimitive2D aPRight( 1198cdf0e10cSrcweir aRight, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute()); 1199cdf0e10cSrcweir 1200cdf0e10cSrcweir processBasePrimitive2D(aPLeft); 1201cdf0e10cSrcweir processBasePrimitive2D(aPRight); 1202cdf0e10cSrcweir } 1203cdf0e10cSrcweir else 1204cdf0e10cSrcweir { 1205cdf0e10cSrcweir // support SvtGraphicStroke MetaCommentAction 1206cdf0e10cSrcweir SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke( 1207cdf0e10cSrcweir rBasePolygon, 0, 1208cdf0e10cSrcweir &rStrokePrimitive.getLineAttribute(), 1209cdf0e10cSrcweir &rStrokePrimitive.getStrokeAttribute(), 1210cdf0e10cSrcweir 0, 0); 1211cdf0e10cSrcweir 1212cdf0e10cSrcweir impStartSvtGraphicStroke(pSvtGraphicStroke); 1213cdf0e10cSrcweir const attribute::LineAttribute& rLine = rStrokePrimitive.getLineAttribute(); 1214cdf0e10cSrcweir 1215cdf0e10cSrcweir // create MetaPolyLineActions, but without LINE_DASH 1216cdf0e10cSrcweir if(basegfx::fTools::more(rLine.getWidth(), 0.0)) 1217cdf0e10cSrcweir { 1218cdf0e10cSrcweir const attribute::StrokeAttribute& rStroke = rStrokePrimitive.getStrokeAttribute(); 1219cdf0e10cSrcweir basegfx::B2DPolyPolygon aHairLinePolyPolygon; 1220cdf0e10cSrcweir 1221cdf0e10cSrcweir if(0.0 == rStroke.getFullDotDashLen()) 1222cdf0e10cSrcweir { 1223cdf0e10cSrcweir aHairLinePolyPolygon.append(rBasePolygon); 1224cdf0e10cSrcweir } 1225cdf0e10cSrcweir else 1226cdf0e10cSrcweir { 1227cdf0e10cSrcweir basegfx::tools::applyLineDashing( 1228cdf0e10cSrcweir rBasePolygon, rStroke.getDotDashArray(), 1229cdf0e10cSrcweir &aHairLinePolyPolygon, 0, rStroke.getFullDotDashLen()); 1230cdf0e10cSrcweir } 1231cdf0e10cSrcweir 1232cdf0e10cSrcweir const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLine.getColor())); 1233cdf0e10cSrcweir mpOutputDevice->SetLineColor(Color(aHairlineColor)); 1234cdf0e10cSrcweir mpOutputDevice->SetFillColor(); 1235cdf0e10cSrcweir aHairLinePolyPolygon.transform(maCurrentTransformation); 1236cdf0e10cSrcweir 1237cdf0e10cSrcweir // #i113922# LineWidth needs to be transformed, too 1238cdf0e10cSrcweir const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation * basegfx::B2DVector(rLine.getWidth(), 0.0)); 1239cdf0e10cSrcweir const double fDiscreteLineWidth(aDiscreteUnit.getLength()); 1240cdf0e10cSrcweir 1241cdf0e10cSrcweir LineInfo aLineInfo(LINE_SOLID, basegfx::fround(fDiscreteLineWidth)); 1242cdf0e10cSrcweir aLineInfo.SetLineJoin(rLine.getLineJoin()); 12435aaf853bSArmin Le Grand aLineInfo.SetLineCap(rLine.getLineCap()); 1244cdf0e10cSrcweir 1245cdf0e10cSrcweir for(sal_uInt32 a(0); a < aHairLinePolyPolygon.count(); a++) 1246cdf0e10cSrcweir { 1247cdf0e10cSrcweir const basegfx::B2DPolygon aCandidate(aHairLinePolyPolygon.getB2DPolygon(a)); 1248cdf0e10cSrcweir 1249cdf0e10cSrcweir if(aCandidate.count() > 1) 1250cdf0e10cSrcweir { 1251cdf0e10cSrcweir const Polygon aToolsPolygon(aCandidate); 1252cdf0e10cSrcweir 1253cdf0e10cSrcweir mpMetaFile->AddAction(new MetaPolyLineAction(aToolsPolygon, aLineInfo)); 1254cdf0e10cSrcweir } 1255cdf0e10cSrcweir } 1256cdf0e10cSrcweir } 1257cdf0e10cSrcweir else 1258cdf0e10cSrcweir { 1259cdf0e10cSrcweir process(rCandidate.get2DDecomposition(getViewInformation2D())); 1260cdf0e10cSrcweir } 1261cdf0e10cSrcweir 1262cdf0e10cSrcweir impEndSvtGraphicStroke(pSvtGraphicStroke); 1263cdf0e10cSrcweir } 1264cdf0e10cSrcweir 1265cdf0e10cSrcweir break; 1266cdf0e10cSrcweir } 1267cdf0e10cSrcweir case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D : 1268cdf0e10cSrcweir { 1269cdf0e10cSrcweir const primitive2d::PolygonStrokeArrowPrimitive2D& rStrokeArrowPrimitive = static_cast< const primitive2d::PolygonStrokeArrowPrimitive2D& >(rCandidate); 1270cdf0e10cSrcweir const basegfx::B2DPolygon& rBasePolygon = rStrokeArrowPrimitive.getB2DPolygon(); 1271cdf0e10cSrcweir 1272cdf0e10cSrcweir if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1)) 1273cdf0e10cSrcweir { 1274cdf0e10cSrcweir // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 1275cdf0e10cSrcweir // per polygon. If there are more, split the polygon in half and call recursively 1276cdf0e10cSrcweir basegfx::B2DPolygon aLeft, aRight; 1277cdf0e10cSrcweir splitLinePolygon(rBasePolygon, aLeft, aRight); 1278cdf0e10cSrcweir const attribute::LineStartEndAttribute aEmpty; 1279cdf0e10cSrcweir const primitive2d::PolygonStrokeArrowPrimitive2D aPLeft( 1280cdf0e10cSrcweir aLeft, 1281cdf0e10cSrcweir rStrokeArrowPrimitive.getLineAttribute(), 1282cdf0e10cSrcweir rStrokeArrowPrimitive.getStrokeAttribute(), 1283cdf0e10cSrcweir rStrokeArrowPrimitive.getStart(), 1284cdf0e10cSrcweir aEmpty); 1285cdf0e10cSrcweir const primitive2d::PolygonStrokeArrowPrimitive2D aPRight( 1286cdf0e10cSrcweir aRight, 1287cdf0e10cSrcweir rStrokeArrowPrimitive.getLineAttribute(), 1288cdf0e10cSrcweir rStrokeArrowPrimitive.getStrokeAttribute(), 1289cdf0e10cSrcweir aEmpty, 1290cdf0e10cSrcweir rStrokeArrowPrimitive.getEnd()); 1291cdf0e10cSrcweir 1292cdf0e10cSrcweir processBasePrimitive2D(aPLeft); 1293cdf0e10cSrcweir processBasePrimitive2D(aPRight); 1294cdf0e10cSrcweir } 1295cdf0e10cSrcweir else 1296cdf0e10cSrcweir { 1297cdf0e10cSrcweir // support SvtGraphicStroke MetaCommentAction 1298cdf0e10cSrcweir SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke( 1299cdf0e10cSrcweir rBasePolygon, 0, 1300cdf0e10cSrcweir &rStrokeArrowPrimitive.getLineAttribute(), 1301cdf0e10cSrcweir &rStrokeArrowPrimitive.getStrokeAttribute(), 1302cdf0e10cSrcweir &rStrokeArrowPrimitive.getStart(), 1303cdf0e10cSrcweir &rStrokeArrowPrimitive.getEnd()); 1304cdf0e10cSrcweir 130578137d97SArmin Le Grand // write LineGeometry start marker 1306cdf0e10cSrcweir impStartSvtGraphicStroke(pSvtGraphicStroke); 130778137d97SArmin Le Grand 130878137d97SArmin Le Grand // #116162# When B&W is set as DrawMode, DRAWMODE_WHITEFILL is used 130978137d97SArmin Le Grand // to let all fills be just white; for lines DRAWMODE_BLACKLINE is used 131078137d97SArmin Le Grand // so all line geometry is supposed to get black. Since in the in-between 131178137d97SArmin Le Grand // stages of line geometry drawing filled polygons are used (e.g. line 131278137d97SArmin Le Grand // start/ends) it is necessary to change these drawmodes to preserve 131378137d97SArmin Le Grand // that lines shall be black; thus change DRAWMODE_WHITEFILL to 131478137d97SArmin Le Grand // DRAWMODE_BLACKFILL during line geometry processing to have line geometry 131578137d97SArmin Le Grand // parts filled black. 131678137d97SArmin Le Grand const sal_uLong nOldDrawMode(mpOutputDevice->GetDrawMode()); 131778137d97SArmin Le Grand const bool bDrawmodeChange(nOldDrawMode & DRAWMODE_WHITEFILL && mnSvtGraphicStrokeCount); 131878137d97SArmin Le Grand 131978137d97SArmin Le Grand if(bDrawmodeChange) 132078137d97SArmin Le Grand { 132178137d97SArmin Le Grand mpOutputDevice->SetDrawMode((nOldDrawMode & ~DRAWMODE_WHITEFILL) | DRAWMODE_BLACKFILL); 132278137d97SArmin Le Grand } 132378137d97SArmin Le Grand 132478137d97SArmin Le Grand // process sub-line geometry (evtl. filled PolyPolygons) 132578137d97SArmin Le Grand process(rCandidate.get2DDecomposition(getViewInformation2D())); 132678137d97SArmin Le Grand 132778137d97SArmin Le Grand if(bDrawmodeChange) 132878137d97SArmin Le Grand { 132978137d97SArmin Le Grand mpOutputDevice->SetDrawMode(nOldDrawMode); 133078137d97SArmin Le Grand } 133178137d97SArmin Le Grand 133278137d97SArmin Le Grand // write LineGeometry end marker 133378137d97SArmin Le Grand impEndSvtGraphicStroke(pSvtGraphicStroke); 1334cdf0e10cSrcweir } 1335cdf0e10cSrcweir 1336cdf0e10cSrcweir break; 1337cdf0e10cSrcweir } 1338cdf0e10cSrcweir case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D : 1339cdf0e10cSrcweir { 1340cdf0e10cSrcweir // direct draw of transformed BitmapEx primitive; use default processing 1341cdf0e10cSrcweir RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate)); 1342cdf0e10cSrcweir break; 1343cdf0e10cSrcweir } 1344035a2f44SArmin Le Grand case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D : 1345cdf0e10cSrcweir { 1346035a2f44SArmin Le Grand // need to handle PolyPolygonGraphicPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END 1347035a2f44SArmin Le Grand const primitive2d::PolyPolygonGraphicPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonGraphicPrimitive2D& >(rCandidate); 1348cdf0e10cSrcweir basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon()); 1349cdf0e10cSrcweir 1350cdf0e10cSrcweir if(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) 1351cdf0e10cSrcweir { 1352cdf0e10cSrcweir // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 1353cdf0e10cSrcweir // per polygon. If there are more use the splitted polygon and call recursively 1354035a2f44SArmin Le Grand const primitive2d::PolyPolygonGraphicPrimitive2D aSplitted( 1355cdf0e10cSrcweir aLocalPolyPolygon, 1356035a2f44SArmin Le Grand rBitmapCandidate.getFillGraphic()); 1357cdf0e10cSrcweir 1358cdf0e10cSrcweir processBasePrimitive2D(aSplitted); 1359cdf0e10cSrcweir } 1360cdf0e10cSrcweir else 1361cdf0e10cSrcweir { 1362cdf0e10cSrcweir SvtGraphicFill* pSvtGraphicFill = 0; 1363cdf0e10cSrcweir 1364cdf0e10cSrcweir if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count()) 1365cdf0e10cSrcweir { 1366035a2f44SArmin Le Grand // #121194# Changed implementation and checked usages fo convert to metafile, 1367035a2f44SArmin Le Grand // presentation start (uses SvtGraphicFill) and printing. 1368cdf0e10cSrcweir 1369035a2f44SArmin Le Grand // calculate transformation. Get real object size, all values in FillGraphicAttribute 1370035a2f44SArmin Le Grand // are relative to the unified object 1371035a2f44SArmin Le Grand aLocalPolyPolygon.transform(maCurrentTransformation); 1372035a2f44SArmin Le Grand const basegfx::B2DVector aOutlineSize(aLocalPolyPolygon.getB2DRange().getRange()); 1373cdf0e10cSrcweir 1374cdf0e10cSrcweir // the scaling needs scale from pixel to logic coordinate system 1375035a2f44SArmin Le Grand const attribute::FillGraphicAttribute& rFillGraphicAttribute = rBitmapCandidate.getFillGraphic(); 1376035a2f44SArmin Le Grand const Size aBmpSizePixel(rFillGraphicAttribute.getGraphic().GetSizePixel()); 1377035a2f44SArmin Le Grand 1378035a2f44SArmin Le Grand // setup transformation like in impgrfll. Multiply with aOutlineSize 1379035a2f44SArmin Le Grand // to get from unit coordinates in rFillGraphicAttribute.getGraphicRange() 1380035a2f44SArmin Le Grand // to object coordinates with object's top left being at (0,0). Divide 1381035a2f44SArmin Le Grand // by pixel size so that scale from pixel to logic will work in SvtGraphicFill. 1382035a2f44SArmin Le Grand const basegfx::B2DVector aTransformScale( 1383035a2f44SArmin Le Grand rFillGraphicAttribute.getGraphicRange().getRange() / 1384035a2f44SArmin Le Grand basegfx::B2DVector( 1385035a2f44SArmin Le Grand std::max(1.0, double(aBmpSizePixel.Width())), 1386035a2f44SArmin Le Grand std::max(1.0, double(aBmpSizePixel.Height()))) * 1387035a2f44SArmin Le Grand aOutlineSize); 1388035a2f44SArmin Le Grand const basegfx::B2DPoint aTransformPosition( 1389035a2f44SArmin Le Grand rFillGraphicAttribute.getGraphicRange().getMinimum() * aOutlineSize); 1390cdf0e10cSrcweir 1391cdf0e10cSrcweir // setup transformation like in impgrfll 1392cdf0e10cSrcweir SvtGraphicFill::Transform aTransform; 1393cdf0e10cSrcweir 1394cdf0e10cSrcweir // scale values are divided by bitmap pixel sizes 1395035a2f44SArmin Le Grand aTransform.matrix[0] = aTransformScale.getX(); 1396035a2f44SArmin Le Grand aTransform.matrix[4] = aTransformScale.getY(); 1397cdf0e10cSrcweir 1398cdf0e10cSrcweir // translates are absolute 1399035a2f44SArmin Le Grand aTransform.matrix[2] = aTransformPosition.getX(); 1400035a2f44SArmin Le Grand aTransform.matrix[5] = aTransformPosition.getY(); 1401cdf0e10cSrcweir 1402035a2f44SArmin Le Grand pSvtGraphicFill = new SvtGraphicFill( 1403cdf0e10cSrcweir PolyPolygon(aLocalPolyPolygon), 1404cdf0e10cSrcweir Color(), 1405cdf0e10cSrcweir 0.0, 1406cdf0e10cSrcweir SvtGraphicFill::fillEvenOdd, 1407cdf0e10cSrcweir SvtGraphicFill::fillTexture, 1408cdf0e10cSrcweir aTransform, 1409035a2f44SArmin Le Grand rFillGraphicAttribute.getTiling(), 1410cdf0e10cSrcweir SvtGraphicFill::hatchSingle, 1411cdf0e10cSrcweir Color(), 1412cdf0e10cSrcweir SvtGraphicFill::gradientLinear, 1413cdf0e10cSrcweir Color(), 1414cdf0e10cSrcweir Color(), 1415cdf0e10cSrcweir 0, 1416035a2f44SArmin Le Grand rFillGraphicAttribute.getGraphic()); 1417cdf0e10cSrcweir } 1418cdf0e10cSrcweir 1419cdf0e10cSrcweir // Do use decomposition; encapsulate with SvtGraphicFill 1420cdf0e10cSrcweir impStartSvtGraphicFill(pSvtGraphicFill); 1421cdf0e10cSrcweir process(rCandidate.get2DDecomposition(getViewInformation2D())); 1422cdf0e10cSrcweir impEndSvtGraphicFill(pSvtGraphicFill); 1423cdf0e10cSrcweir } 1424cdf0e10cSrcweir 1425cdf0e10cSrcweir break; 1426cdf0e10cSrcweir } 1427cdf0e10cSrcweir case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D : 1428cdf0e10cSrcweir { 1429cdf0e10cSrcweir // need to handle PolyPolygonHatchPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END 1430cdf0e10cSrcweir const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate); 1431cdf0e10cSrcweir const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch(); 1432cdf0e10cSrcweir basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon()); 1433cdf0e10cSrcweir 1434cdf0e10cSrcweir // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 1435cdf0e10cSrcweir // per polygon. Split polygon until there are less than that 1436cdf0e10cSrcweir while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) 1437cdf0e10cSrcweir ; 1438cdf0e10cSrcweir 1439cdf0e10cSrcweir if(rFillHatchAttribute.isFillBackground()) 1440cdf0e10cSrcweir { 1441cdf0e10cSrcweir // with fixing #i111954# (see below) the possible background 1442cdf0e10cSrcweir // fill of a hatched object was lost.Generate a background fill 1443cdf0e10cSrcweir // primitive and render it 1444cdf0e10cSrcweir const primitive2d::Primitive2DReference xBackground( 1445cdf0e10cSrcweir new primitive2d::PolyPolygonColorPrimitive2D( 1446cdf0e10cSrcweir aLocalPolyPolygon, 1447cdf0e10cSrcweir rHatchCandidate.getBackgroundColor())); 1448cdf0e10cSrcweir 1449cdf0e10cSrcweir process(primitive2d::Primitive2DSequence(&xBackground, 1)); 1450cdf0e10cSrcweir } 1451cdf0e10cSrcweir 1452cdf0e10cSrcweir SvtGraphicFill* pSvtGraphicFill = 0; 1453cdf0e10cSrcweir aLocalPolyPolygon.transform(maCurrentTransformation); 1454cdf0e10cSrcweir 1455cdf0e10cSrcweir if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count()) 1456cdf0e10cSrcweir { 1457cdf0e10cSrcweir // re-create a VCL hatch as base data 1458cdf0e10cSrcweir SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle); 1459cdf0e10cSrcweir 1460cdf0e10cSrcweir switch(rFillHatchAttribute.getStyle()) 1461cdf0e10cSrcweir { 1462cdf0e10cSrcweir default: // attribute::HATCHSTYLE_SINGLE : 1463cdf0e10cSrcweir { 1464cdf0e10cSrcweir eHatch = SvtGraphicFill::hatchSingle; 1465cdf0e10cSrcweir break; 1466cdf0e10cSrcweir } 1467cdf0e10cSrcweir case attribute::HATCHSTYLE_DOUBLE : 1468cdf0e10cSrcweir { 1469cdf0e10cSrcweir eHatch = SvtGraphicFill::hatchDouble; 1470cdf0e10cSrcweir break; 1471cdf0e10cSrcweir } 1472cdf0e10cSrcweir case attribute::HATCHSTYLE_TRIPLE : 1473cdf0e10cSrcweir { 1474cdf0e10cSrcweir eHatch = SvtGraphicFill::hatchTriple; 1475cdf0e10cSrcweir break; 1476cdf0e10cSrcweir } 1477cdf0e10cSrcweir } 1478cdf0e10cSrcweir 1479cdf0e10cSrcweir SvtGraphicFill::Transform aTransform; 1480cdf0e10cSrcweir 1481cdf0e10cSrcweir // scale 1482cdf0e10cSrcweir aTransform.matrix[0] *= rFillHatchAttribute.getDistance(); 1483cdf0e10cSrcweir aTransform.matrix[4] *= rFillHatchAttribute.getDistance(); 1484cdf0e10cSrcweir 1485cdf0e10cSrcweir // rotate (was never correct in impgrfll anyways, use correct angle now) 1486cdf0e10cSrcweir aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle()); 1487cdf0e10cSrcweir aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle()); 1488cdf0e10cSrcweir aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle()); 1489cdf0e10cSrcweir aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle()); 1490cdf0e10cSrcweir 1491cdf0e10cSrcweir pSvtGraphicFill = new SvtGraphicFill( 1492cdf0e10cSrcweir PolyPolygon(aLocalPolyPolygon), 1493cdf0e10cSrcweir Color(), 1494cdf0e10cSrcweir 0.0, 1495cdf0e10cSrcweir SvtGraphicFill::fillEvenOdd, 1496cdf0e10cSrcweir SvtGraphicFill::fillHatch, 1497cdf0e10cSrcweir aTransform, 1498cdf0e10cSrcweir false, 1499cdf0e10cSrcweir eHatch, 1500cdf0e10cSrcweir Color(rFillHatchAttribute.getColor()), 1501cdf0e10cSrcweir SvtGraphicFill::gradientLinear, 1502cdf0e10cSrcweir Color(), 1503cdf0e10cSrcweir Color(), 1504cdf0e10cSrcweir 0, 1505cdf0e10cSrcweir Graphic()); 1506cdf0e10cSrcweir } 1507cdf0e10cSrcweir 1508cdf0e10cSrcweir // Do use decomposition; encapsulate with SvtGraphicFill 1509cdf0e10cSrcweir impStartSvtGraphicFill(pSvtGraphicFill); 1510cdf0e10cSrcweir 1511cdf0e10cSrcweir // #i111954# do NOT use decomposition, but use direct VCL-command 1512cdf0e10cSrcweir // process(rCandidate.get2DDecomposition(getViewInformation2D())); 1513cdf0e10cSrcweir const PolyPolygon aToolsPolyPolygon(aLocalPolyPolygon); 1514cdf0e10cSrcweir const HatchStyle aHatchStyle( 1515cdf0e10cSrcweir attribute::HATCHSTYLE_SINGLE == rFillHatchAttribute.getStyle() ? HATCH_SINGLE : 1516cdf0e10cSrcweir attribute::HATCHSTYLE_DOUBLE == rFillHatchAttribute.getStyle() ? HATCH_DOUBLE : 1517cdf0e10cSrcweir HATCH_TRIPLE); 1518cdf0e10cSrcweir 1519cdf0e10cSrcweir mpOutputDevice->DrawHatch(aToolsPolyPolygon, 1520cdf0e10cSrcweir Hatch(aHatchStyle, 1521cdf0e10cSrcweir Color(rFillHatchAttribute.getColor()), 1522cdf0e10cSrcweir basegfx::fround(rFillHatchAttribute.getDistance()), 1523cdf0e10cSrcweir basegfx::fround(rFillHatchAttribute.getAngle() / F_PI1800))); 1524cdf0e10cSrcweir 1525cdf0e10cSrcweir impEndSvtGraphicFill(pSvtGraphicFill); 1526cdf0e10cSrcweir 1527cdf0e10cSrcweir break; 1528cdf0e10cSrcweir } 1529cdf0e10cSrcweir case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D : 1530cdf0e10cSrcweir { 15316d3fd5d0SArmin Le Grand basegfx::B2DVector aScale, aTranslate; 15326d3fd5d0SArmin Le Grand double fRotate, fShearX; 1533cdf0e10cSrcweir 15346d3fd5d0SArmin Le Grand maCurrentTransformation.decompose(aScale, aTranslate, fRotate, fShearX); 1535cdf0e10cSrcweir 15366d3fd5d0SArmin Le Grand if(!basegfx::fTools::equalZero(fRotate) || !basegfx::fTools::equalZero(fShearX)) 15376d3fd5d0SArmin Le Grand { 15386d3fd5d0SArmin Le Grand // #121185# When rotation or shear is used, a VCL Gradient cannot be used directly. 15396d3fd5d0SArmin Le Grand // This is because VCL Gradient mechanism does *not* support to rotate the gradient 15406d3fd5d0SArmin Le Grand // with objects and this case is not expressable in a Metafile (and cannot be added 15416d3fd5d0SArmin Le Grand // since the FileFormats used, e.g. *.wmf, do not support it either). 15426d3fd5d0SArmin Le Grand // Such cases happen when a graphic object uses a Metafile as graphic information or 15436d3fd5d0SArmin Le Grand // a fill style definition uses a Metafile. In this cases the graphic content is 15446d3fd5d0SArmin Le Grand // rotated with the graphic or filled object; this is not supported by the target 15456d3fd5d0SArmin Le Grand // format of this conversion renderer - Metafiles. 15466d3fd5d0SArmin Le Grand // To solve this, not a Gradient is written, but the decomposition of this object 15476d3fd5d0SArmin Le Grand // is written to the Metafile. This is the PolyPolygons building the gradient fill. 15486d3fd5d0SArmin Le Grand // These will need more space and time, but the result will be as if the Gradient 15496d3fd5d0SArmin Le Grand // was rotated with the object. 15506d3fd5d0SArmin Le Grand // This mechanism is used by all exporters still not using Primtives (e.g. Print, 15516d3fd5d0SArmin Le Grand // Slideshow, Export rto PDF, export to Picture, ...) but relying on Metafile 15526d3fd5d0SArmin Le Grand // transfers. One more reason to *change* these to primitives. 15536d3fd5d0SArmin Le Grand // BTW: One more example how useful the principles of primitives are; the decomposition 15546d3fd5d0SArmin Le Grand // is by definition a simpler, maybe more expensive representation of the same content. 15556d3fd5d0SArmin Le Grand process(rCandidate.get2DDecomposition(getViewInformation2D())); 15566d3fd5d0SArmin Le Grand } 15576d3fd5d0SArmin Le Grand else 15586d3fd5d0SArmin Le Grand { 15596d3fd5d0SArmin Le Grand const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate); 15606d3fd5d0SArmin Le Grand basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon()); 1561cdf0e10cSrcweir 15626d3fd5d0SArmin Le Grand // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 15636d3fd5d0SArmin Le Grand // per polygon. Split polygon until there are less than that 15646d3fd5d0SArmin Le Grand while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) 15656d3fd5d0SArmin Le Grand ; 15666d3fd5d0SArmin Le Grand 15676d3fd5d0SArmin Le Grand // for support of MetaCommentActions of the form XGRAD_SEQ_BEGIN, XGRAD_SEQ_END 15686d3fd5d0SArmin Le Grand // it is safest to use the VCL OutputDevice::DrawGradient method which creates those. 15696d3fd5d0SArmin Le Grand // re-create a VCL-gradient from FillGradientPrimitive2D and the needed tools PolyPolygon 15706d3fd5d0SArmin Le Grand Gradient aVCLGradient; 15716d3fd5d0SArmin Le Grand impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rGradientCandidate.getFillGradient(), false); 15726d3fd5d0SArmin Le Grand aLocalPolyPolygon.transform(maCurrentTransformation); 15736d3fd5d0SArmin Le Grand 15746d3fd5d0SArmin Le Grand // #i82145# ATM VCL printing of gradients using curved shapes does not work, 15756d3fd5d0SArmin Le Grand // i submitted the bug with the given ID to THB. When that task is fixed it is 15766d3fd5d0SArmin Le Grand // necessary to again remove this subdivision since it decreases possible 15776d3fd5d0SArmin Le Grand // printing quality (not even resolution-dependent for now). THB will tell 15786d3fd5d0SArmin Le Grand // me when that task is fixed in the master 15796d3fd5d0SArmin Le Grand const PolyPolygon aToolsPolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(aLocalPolyPolygon)); 15806d3fd5d0SArmin Le Grand 15816d3fd5d0SArmin Le Grand // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support 15826d3fd5d0SArmin Le Grand SvtGraphicFill* pSvtGraphicFill = 0; 15836d3fd5d0SArmin Le Grand 15846d3fd5d0SArmin Le Grand if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count()) 15856d3fd5d0SArmin Le Grand { 15866d3fd5d0SArmin Le Grand // setup gradient stuff like in like in impgrfll 15876d3fd5d0SArmin Le Grand SvtGraphicFill::GradientType eGrad(SvtGraphicFill::gradientLinear); 15886d3fd5d0SArmin Le Grand 15896d3fd5d0SArmin Le Grand switch(aVCLGradient.GetStyle()) 15906d3fd5d0SArmin Le Grand { 15916d3fd5d0SArmin Le Grand default : // GRADIENT_LINEAR: 15926d3fd5d0SArmin Le Grand case GRADIENT_AXIAL: 15936d3fd5d0SArmin Le Grand eGrad = SvtGraphicFill::gradientLinear; 15946d3fd5d0SArmin Le Grand break; 15956d3fd5d0SArmin Le Grand case GRADIENT_RADIAL: 15966d3fd5d0SArmin Le Grand case GRADIENT_ELLIPTICAL: 15976d3fd5d0SArmin Le Grand eGrad = SvtGraphicFill::gradientRadial; 15986d3fd5d0SArmin Le Grand break; 15996d3fd5d0SArmin Le Grand case GRADIENT_SQUARE: 16006d3fd5d0SArmin Le Grand case GRADIENT_RECT: 16016d3fd5d0SArmin Le Grand eGrad = SvtGraphicFill::gradientRectangular; 16026d3fd5d0SArmin Le Grand break; 16036d3fd5d0SArmin Le Grand } 1604cdf0e10cSrcweir 16056d3fd5d0SArmin Le Grand pSvtGraphicFill = new SvtGraphicFill( 16066d3fd5d0SArmin Le Grand aToolsPolyPolygon, 16076d3fd5d0SArmin Le Grand Color(), 16086d3fd5d0SArmin Le Grand 0.0, 16096d3fd5d0SArmin Le Grand SvtGraphicFill::fillEvenOdd, 16106d3fd5d0SArmin Le Grand SvtGraphicFill::fillGradient, 16116d3fd5d0SArmin Le Grand SvtGraphicFill::Transform(), 16126d3fd5d0SArmin Le Grand false, 16136d3fd5d0SArmin Le Grand SvtGraphicFill::hatchSingle, 16146d3fd5d0SArmin Le Grand Color(), 16156d3fd5d0SArmin Le Grand eGrad, 16166d3fd5d0SArmin Le Grand aVCLGradient.GetStartColor(), 16176d3fd5d0SArmin Le Grand aVCLGradient.GetEndColor(), 16186d3fd5d0SArmin Le Grand aVCLGradient.GetSteps(), 16196d3fd5d0SArmin Le Grand Graphic()); 16206d3fd5d0SArmin Le Grand } 16216d3fd5d0SArmin Le Grand 16226d3fd5d0SArmin Le Grand // call VCL directly; encapsulate with SvtGraphicFill 16236d3fd5d0SArmin Le Grand impStartSvtGraphicFill(pSvtGraphicFill); 16246d3fd5d0SArmin Le Grand mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient); 16256d3fd5d0SArmin Le Grand impEndSvtGraphicFill(pSvtGraphicFill); 16266d3fd5d0SArmin Le Grand 16276d3fd5d0SArmin Le Grand // NO usage of common own gradient randerer, not used ATM for VCL MetaFile, see text above 16286d3fd5d0SArmin Le Grand // RenderPolyPolygonGradientPrimitive2D(static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate)); 16296d3fd5d0SArmin Le Grand } 1630cdf0e10cSrcweir 1631cdf0e10cSrcweir break; 1632cdf0e10cSrcweir } 1633cdf0e10cSrcweir case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D : 1634cdf0e10cSrcweir { 1635cdf0e10cSrcweir const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate)); 1636cdf0e10cSrcweir basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon()); 1637cdf0e10cSrcweir 1638cdf0e10cSrcweir // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 1639cdf0e10cSrcweir // per polygon. Split polygon until there are less than that 1640cdf0e10cSrcweir while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) 1641cdf0e10cSrcweir ; 1642cdf0e10cSrcweir 1643cdf0e10cSrcweir const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor())); 1644cdf0e10cSrcweir aLocalPolyPolygon.transform(maCurrentTransformation); 1645cdf0e10cSrcweir 1646cdf0e10cSrcweir // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support 1647cdf0e10cSrcweir SvtGraphicFill* pSvtGraphicFill = 0; 1648cdf0e10cSrcweir 1649*4665f8d3SArmin Le Grand // #121267# Not needed, does not give better quality compared with 1650*4665f8d3SArmin Le Grand // the META_POLYPOLYGON_ACTION written by the DrawPolyPolygon command 1651*4665f8d3SArmin Le Grand // below 1652*4665f8d3SArmin Le Grand bool bSupportSvtGraphicFill(false); 1653*4665f8d3SArmin Le Grand 1654*4665f8d3SArmin Le Grand if(bSupportSvtGraphicFill && !mnSvtGraphicFillCount && aLocalPolyPolygon.count()) 1655cdf0e10cSrcweir { 1656cdf0e10cSrcweir // setup simple color fill stuff like in impgrfll 1657cdf0e10cSrcweir pSvtGraphicFill = new SvtGraphicFill( 1658cdf0e10cSrcweir PolyPolygon(aLocalPolyPolygon), 1659cdf0e10cSrcweir Color(aPolygonColor), 1660cdf0e10cSrcweir 0.0, 1661cdf0e10cSrcweir SvtGraphicFill::fillEvenOdd, 1662cdf0e10cSrcweir SvtGraphicFill::fillSolid, 1663cdf0e10cSrcweir SvtGraphicFill::Transform(), 1664cdf0e10cSrcweir false, 1665cdf0e10cSrcweir SvtGraphicFill::hatchSingle, 1666cdf0e10cSrcweir Color(), 1667cdf0e10cSrcweir SvtGraphicFill::gradientLinear, 1668cdf0e10cSrcweir Color(), 1669cdf0e10cSrcweir Color(), 1670cdf0e10cSrcweir 0, 1671cdf0e10cSrcweir Graphic()); 1672cdf0e10cSrcweir } 1673cdf0e10cSrcweir 1674cdf0e10cSrcweir // set line and fill color 1675cdf0e10cSrcweir mpOutputDevice->SetFillColor(Color(aPolygonColor)); 1676cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 1677cdf0e10cSrcweir 1678cdf0e10cSrcweir // call VCL directly; encapsulate with SvtGraphicFill 1679*4665f8d3SArmin Le Grand if(bSupportSvtGraphicFill) 1680*4665f8d3SArmin Le Grand { 1681*4665f8d3SArmin Le Grand impStartSvtGraphicFill(pSvtGraphicFill); 1682*4665f8d3SArmin Le Grand } 1683*4665f8d3SArmin Le Grand 1684*4665f8d3SArmin Le Grand mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon); 1685*4665f8d3SArmin Le Grand 1686*4665f8d3SArmin Le Grand if(bSupportSvtGraphicFill) 1687*4665f8d3SArmin Le Grand { 1688*4665f8d3SArmin Le Grand impEndSvtGraphicFill(pSvtGraphicFill); 1689*4665f8d3SArmin Le Grand } 1690cdf0e10cSrcweir 1691cdf0e10cSrcweir break; 1692cdf0e10cSrcweir } 1693cdf0e10cSrcweir case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D : 1694cdf0e10cSrcweir { 1695dfe9de19SHerbert Dürr static bool bUseMetaFilePrimitiveDecomposition(true); 1696dfe9de19SHerbert Dürr 1697dfe9de19SHerbert Dürr if(bUseMetaFilePrimitiveDecomposition) 1698dfe9de19SHerbert Dürr { 1699dfe9de19SHerbert Dürr // use new Metafile decomposition 1700dfe9de19SHerbert Dürr process(rCandidate.get2DDecomposition(getViewInformation2D())); 1701dfe9de19SHerbert Dürr } 1702dfe9de19SHerbert Dürr else 1703dfe9de19SHerbert Dürr { 1704dfe9de19SHerbert Dürr // direct draw of MetaFile, use default pocessing 1705dfe9de19SHerbert Dürr RenderMetafilePrimitive2D(static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate)); 1706dfe9de19SHerbert Dürr } 1707dfe9de19SHerbert Dürr 1708dfe9de19SHerbert Dürr break; 1709cdf0e10cSrcweir } 1710cdf0e10cSrcweir case PRIMITIVE2D_ID_MASKPRIMITIVE2D : 1711cdf0e10cSrcweir { 1712cdf0e10cSrcweir // mask group. Special handling for MetaFiles. 1713cdf0e10cSrcweir const primitive2d::MaskPrimitive2D& rMaskCandidate = static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate); 1714cdf0e10cSrcweir 1715cdf0e10cSrcweir if(rMaskCandidate.getChildren().hasElements()) 1716cdf0e10cSrcweir { 1717cdf0e10cSrcweir basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask()); 1718cdf0e10cSrcweir 1719cdf0e10cSrcweir if(aMask.count()) 1720cdf0e10cSrcweir { 1721cdf0e10cSrcweir // prepare new mask polygon and rescue current one 1722cdf0e10cSrcweir aMask.transform(maCurrentTransformation); 1723cdf0e10cSrcweir const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon); 1724cdf0e10cSrcweir 1725cdf0e10cSrcweir if(maClipPolyPolygon.count()) 1726cdf0e10cSrcweir { 1727cdf0e10cSrcweir // there is already a clip polygon set; build clipped union of 1728cdf0e10cSrcweir // current mask polygon and new one 1729cdf0e10cSrcweir maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon( 1730cdf0e10cSrcweir aMask, 1731cdf0e10cSrcweir maClipPolyPolygon, 1732cdf0e10cSrcweir true, // #i106516# we want the inside of aMask, not the outside 1733cdf0e10cSrcweir false); 1734cdf0e10cSrcweir } 1735cdf0e10cSrcweir else 1736cdf0e10cSrcweir { 1737cdf0e10cSrcweir // use mask directly 1738cdf0e10cSrcweir maClipPolyPolygon = aMask; 1739cdf0e10cSrcweir } 1740cdf0e10cSrcweir 1741cdf0e10cSrcweir if(maClipPolyPolygon.count()) 1742cdf0e10cSrcweir { 1743cdf0e10cSrcweir // set VCL clip region; subdivide before conversion to tools polygon. Subdivision necessary (!) 1744cdf0e10cSrcweir // Removed subdivision and fixed in Region::ImplPolyPolyRegionToBandRegionFunc() in VCL where 1745cdf0e10cSrcweir // the ClipRegion is built from the Polygon. A AdaptiveSubdivide on the source polygon was missing there 1746cdf0e10cSrcweir mpOutputDevice->Push(PUSH_CLIPREGION); 1747*4665f8d3SArmin Le Grand mpOutputDevice->SetClipRegion(Region(maClipPolyPolygon)); 1748*4665f8d3SArmin Le Grand 1749*4665f8d3SArmin Le Grand // recursively paint content 1750*4665f8d3SArmin Le Grand // #121267# Only need to process sub-content when clip polygon is *not* empty. 1751*4665f8d3SArmin Le Grand // If it is empty, the clip is empty and there can be nothing inside. 1752*4665f8d3SArmin Le Grand process(rMaskCandidate.getChildren()); 1753cdf0e10cSrcweir 1754cdf0e10cSrcweir // restore VCL clip region 1755cdf0e10cSrcweir mpOutputDevice->Pop(); 1756cdf0e10cSrcweir } 1757cdf0e10cSrcweir 1758cdf0e10cSrcweir // restore to rescued clip polygon 1759cdf0e10cSrcweir maClipPolyPolygon = aLastClipPolyPolygon; 1760cdf0e10cSrcweir } 1761cdf0e10cSrcweir else 1762cdf0e10cSrcweir { 1763cdf0e10cSrcweir // no mask, no clipping. recursively paint content 1764cdf0e10cSrcweir process(rMaskCandidate.getChildren()); 1765cdf0e10cSrcweir } 1766cdf0e10cSrcweir } 1767cdf0e10cSrcweir 1768cdf0e10cSrcweir break; 1769cdf0e10cSrcweir } 1770cdf0e10cSrcweir case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D : 1771cdf0e10cSrcweir { 1772cdf0e10cSrcweir // modified color group. Force output to unified color. Use default pocessing. 1773cdf0e10cSrcweir RenderModifiedColorPrimitive2D(static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate)); 1774cdf0e10cSrcweir break; 1775cdf0e10cSrcweir } 1776cdf0e10cSrcweir case PRIMITIVE2D_ID_HIDDENGEOMETRYPRIMITIVE2D : 1777cdf0e10cSrcweir { 1778cdf0e10cSrcweir // HiddenGeometryPrimitive2D; to rebuilt the old MetaFile creation, it is necessary to 1779cdf0e10cSrcweir // not ignore them (as it was thought), but to add a MetaFile entry for them. 1780cdf0e10cSrcweir basegfx::B2DRange aInvisibleRange(rCandidate.getB2DRange(getViewInformation2D())); 1781cdf0e10cSrcweir 1782cdf0e10cSrcweir if(!aInvisibleRange.isEmpty()) 1783cdf0e10cSrcweir { 1784cdf0e10cSrcweir aInvisibleRange.transform(maCurrentTransformation); 1785cdf0e10cSrcweir const Rectangle aRectLogic( 1786cdf0e10cSrcweir (sal_Int32)floor(aInvisibleRange.getMinX()), (sal_Int32)floor(aInvisibleRange.getMinY()), 1787cdf0e10cSrcweir (sal_Int32)ceil(aInvisibleRange.getMaxX()), (sal_Int32)ceil(aInvisibleRange.getMaxY())); 1788cdf0e10cSrcweir 1789cdf0e10cSrcweir mpOutputDevice->SetFillColor(); 1790cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 1791cdf0e10cSrcweir mpOutputDevice->DrawRect(aRectLogic); 1792cdf0e10cSrcweir } 1793cdf0e10cSrcweir 1794cdf0e10cSrcweir break; 1795cdf0e10cSrcweir } 1796cdf0e10cSrcweir case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D : 1797cdf0e10cSrcweir { 1798cdf0e10cSrcweir // for metafile: Need to examine what the pure vcl version is doing here actually 1799cdf0e10cSrcweir // - uses DrawTransparent with metafile for content and a gradient 1800cdf0e10cSrcweir // - uses DrawTransparent for single PolyPoylgons directly. Can be detected by 1801cdf0e10cSrcweir // checking the content for single PolyPolygonColorPrimitive2D 1802cdf0e10cSrcweir const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate = static_cast< const primitive2d::UnifiedTransparencePrimitive2D& >(rCandidate); 1803cdf0e10cSrcweir const primitive2d::Primitive2DSequence rContent = rUniTransparenceCandidate.getChildren(); 1804cdf0e10cSrcweir 1805cdf0e10cSrcweir if(rContent.hasElements()) 1806cdf0e10cSrcweir { 1807cdf0e10cSrcweir if(0.0 == rUniTransparenceCandidate.getTransparence()) 1808cdf0e10cSrcweir { 1809cdf0e10cSrcweir // not transparent at all, use content 1810cdf0e10cSrcweir process(rUniTransparenceCandidate.getChildren()); 1811cdf0e10cSrcweir } 1812cdf0e10cSrcweir else if(rUniTransparenceCandidate.getTransparence() > 0.0 && rUniTransparenceCandidate.getTransparence() < 1.0) 1813cdf0e10cSrcweir { 1814cdf0e10cSrcweir // try to identify a single PolyPolygonColorPrimitive2D in the 1815cdf0e10cSrcweir // content part of the transparence primitive 1816cdf0e10cSrcweir const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = 0; 1817cdf0e10cSrcweir static bool bForceToMetafile(false); 1818cdf0e10cSrcweir 1819cdf0e10cSrcweir if(!bForceToMetafile && 1 == rContent.getLength()) 1820cdf0e10cSrcweir { 1821cdf0e10cSrcweir const primitive2d::Primitive2DReference xReference(rContent[0]); 1822cdf0e10cSrcweir pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get()); 1823cdf0e10cSrcweir } 1824cdf0e10cSrcweir 1825cdf0e10cSrcweir // PolyPolygonGradientPrimitive2D, PolyPolygonHatchPrimitive2D and 1826035a2f44SArmin Le Grand // PolyPolygonGraphicPrimitive2D are derived from PolyPolygonColorPrimitive2D. 1827cdf0e10cSrcweir // Check also for correct ID to exclude derived implementations 1828cdf0e10cSrcweir if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID()) 1829cdf0e10cSrcweir { 1830cdf0e10cSrcweir // single transparent PolyPolygon identified, use directly 1831cdf0e10cSrcweir const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor())); 1832cdf0e10cSrcweir basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon()); 1833cdf0e10cSrcweir 1834cdf0e10cSrcweir // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 1835cdf0e10cSrcweir // per polygon. Split polygon until there are less than that 1836cdf0e10cSrcweir while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) 1837cdf0e10cSrcweir ; 1838cdf0e10cSrcweir 1839cdf0e10cSrcweir // now transform 1840cdf0e10cSrcweir aLocalPolyPolygon.transform(maCurrentTransformation); 1841cdf0e10cSrcweir 1842cdf0e10cSrcweir // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support 1843cdf0e10cSrcweir SvtGraphicFill* pSvtGraphicFill = 0; 1844*4665f8d3SArmin Le Grand 1845*4665f8d3SArmin Le Grand // #121267# Not needed, does not give better quality compared with 1846*4665f8d3SArmin Le Grand // the META_POLYPOLYGON_ACTION written by the DrawPolyPolygon command 1847*4665f8d3SArmin Le Grand // below 1848*4665f8d3SArmin Le Grand bool bSupportSvtGraphicFill(false); 1849cdf0e10cSrcweir 1850*4665f8d3SArmin Le Grand if(bSupportSvtGraphicFill && !mnSvtGraphicFillCount && aLocalPolyPolygon.count()) 1851cdf0e10cSrcweir { 1852cdf0e10cSrcweir // setup simple color with transparence fill stuff like in impgrfll 1853cdf0e10cSrcweir pSvtGraphicFill = new SvtGraphicFill( 1854cdf0e10cSrcweir PolyPolygon(aLocalPolyPolygon), 1855cdf0e10cSrcweir Color(aPolygonColor), 1856cdf0e10cSrcweir rUniTransparenceCandidate.getTransparence(), 1857cdf0e10cSrcweir SvtGraphicFill::fillEvenOdd, 1858cdf0e10cSrcweir SvtGraphicFill::fillSolid, 1859cdf0e10cSrcweir SvtGraphicFill::Transform(), 1860cdf0e10cSrcweir false, 1861cdf0e10cSrcweir SvtGraphicFill::hatchSingle, 1862cdf0e10cSrcweir Color(), 1863cdf0e10cSrcweir SvtGraphicFill::gradientLinear, 1864cdf0e10cSrcweir Color(), 1865cdf0e10cSrcweir Color(), 1866cdf0e10cSrcweir 0, 1867cdf0e10cSrcweir Graphic()); 1868cdf0e10cSrcweir } 1869cdf0e10cSrcweir 1870cdf0e10cSrcweir // set line and fill color 1871cdf0e10cSrcweir const sal_uInt16 nTransPercentVcl((sal_uInt16)basegfx::fround(rUniTransparenceCandidate.getTransparence() * 100.0)); 1872cdf0e10cSrcweir mpOutputDevice->SetFillColor(Color(aPolygonColor)); 1873cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 1874cdf0e10cSrcweir 1875cdf0e10cSrcweir // call VCL directly; encapsulate with SvtGraphicFill 1876*4665f8d3SArmin Le Grand if(bSupportSvtGraphicFill) 1877*4665f8d3SArmin Le Grand { 1878*4665f8d3SArmin Le Grand impStartSvtGraphicFill(pSvtGraphicFill); 1879*4665f8d3SArmin Le Grand } 1880*4665f8d3SArmin Le Grand 1881cdf0e10cSrcweir mpOutputDevice->DrawTransparent( 1882cdf0e10cSrcweir PolyPolygon(aLocalPolyPolygon), 1883cdf0e10cSrcweir nTransPercentVcl); 1884*4665f8d3SArmin Le Grand 1885*4665f8d3SArmin Le Grand if(bSupportSvtGraphicFill) 1886*4665f8d3SArmin Le Grand { 1887*4665f8d3SArmin Le Grand impEndSvtGraphicFill(pSvtGraphicFill); 1888*4665f8d3SArmin Le Grand } 1889cdf0e10cSrcweir } 1890cdf0e10cSrcweir else 1891cdf0e10cSrcweir { 1892cdf0e10cSrcweir // svae old mfCurrentUnifiedTransparence and set new one 1893cdf0e10cSrcweir // so that contained SvtGraphicStroke may use the current one 1894cdf0e10cSrcweir const double fLastCurrentUnifiedTransparence(mfCurrentUnifiedTransparence); 1895cdf0e10cSrcweir // #i105377# paint the content metafile opaque as the transparency gets 1896cdf0e10cSrcweir // split of into the gradient below 1897cdf0e10cSrcweir // mfCurrentUnifiedTransparence = rUniTransparenceCandidate.getTransparence(); 1898cdf0e10cSrcweir mfCurrentUnifiedTransparence = 0; 1899cdf0e10cSrcweir 1900cdf0e10cSrcweir // various content, create content-metafile 1901cdf0e10cSrcweir GDIMetaFile aContentMetafile; 1902cdf0e10cSrcweir const Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile)); 1903cdf0e10cSrcweir 1904cdf0e10cSrcweir // restore mfCurrentUnifiedTransparence; it may have been used 1905cdf0e10cSrcweir // while processing the sub-content in impDumpToMetaFile 1906cdf0e10cSrcweir mfCurrentUnifiedTransparence = fLastCurrentUnifiedTransparence; 1907cdf0e10cSrcweir 1908cdf0e10cSrcweir // create uniform VCL gradient for uniform transparency 1909cdf0e10cSrcweir Gradient aVCLGradient; 1910cdf0e10cSrcweir const sal_uInt8 nTransPercentVcl((sal_uInt8)basegfx::fround(rUniTransparenceCandidate.getTransparence() * 255.0)); 1911cdf0e10cSrcweir const Color aTransColor(nTransPercentVcl, nTransPercentVcl, nTransPercentVcl); 1912cdf0e10cSrcweir 1913cdf0e10cSrcweir aVCLGradient.SetStyle(GRADIENT_LINEAR); 1914cdf0e10cSrcweir aVCLGradient.SetStartColor(aTransColor); 1915cdf0e10cSrcweir aVCLGradient.SetEndColor(aTransColor); 1916cdf0e10cSrcweir aVCLGradient.SetAngle(0); 1917cdf0e10cSrcweir aVCLGradient.SetBorder(0); 1918cdf0e10cSrcweir aVCLGradient.SetOfsX(0); 1919cdf0e10cSrcweir aVCLGradient.SetOfsY(0); 1920cdf0e10cSrcweir aVCLGradient.SetStartIntensity(100); 1921cdf0e10cSrcweir aVCLGradient.SetEndIntensity(100); 1922cdf0e10cSrcweir aVCLGradient.SetSteps(2); 1923cdf0e10cSrcweir 1924cdf0e10cSrcweir // render it to VCL 1925cdf0e10cSrcweir mpOutputDevice->DrawTransparent( 1926cdf0e10cSrcweir aContentMetafile, aPrimitiveRectangle.TopLeft(), 1927cdf0e10cSrcweir aPrimitiveRectangle.GetSize(), aVCLGradient); 1928cdf0e10cSrcweir } 1929cdf0e10cSrcweir } 1930cdf0e10cSrcweir } 1931cdf0e10cSrcweir 1932cdf0e10cSrcweir break; 1933cdf0e10cSrcweir } 1934cdf0e10cSrcweir case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D : 1935cdf0e10cSrcweir { 1936cdf0e10cSrcweir // for metafile: Need to examine what the pure vcl version is doing here actually 1937cdf0e10cSrcweir // - uses DrawTransparent with metafile for content and a gradient 1938cdf0e10cSrcweir // i can detect this here with checking the gradient part for a single 1939cdf0e10cSrcweir // FillGradientPrimitive2D and reconstruct the gradient. 1940cdf0e10cSrcweir // If that detection goes wrong, i have to create an transparence-blended bitmap. Eventually 1941cdf0e10cSrcweir // do that in stripes, else RenderTransparencePrimitive2D may just be used 1942cdf0e10cSrcweir const primitive2d::TransparencePrimitive2D& rTransparenceCandidate = static_cast< const primitive2d::TransparencePrimitive2D& >(rCandidate); 1943cdf0e10cSrcweir const primitive2d::Primitive2DSequence rContent = rTransparenceCandidate.getChildren(); 1944cdf0e10cSrcweir const primitive2d::Primitive2DSequence rTransparence = rTransparenceCandidate.getTransparence(); 1945cdf0e10cSrcweir 1946cdf0e10cSrcweir if(rContent.hasElements() && rTransparence.hasElements()) 1947cdf0e10cSrcweir { 1948cdf0e10cSrcweir // try to identify a single FillGradientPrimitive2D in the 1949cdf0e10cSrcweir // transparence part of the primitive 1950cdf0e10cSrcweir const primitive2d::FillGradientPrimitive2D* pFiGradient = 0; 1951cdf0e10cSrcweir static bool bForceToBigTransparentVDev(false); 1952cdf0e10cSrcweir 1953cdf0e10cSrcweir if(!bForceToBigTransparentVDev && 1 == rTransparence.getLength()) 1954cdf0e10cSrcweir { 1955cdf0e10cSrcweir const primitive2d::Primitive2DReference xReference(rTransparence[0]); 1956cdf0e10cSrcweir pFiGradient = dynamic_cast< const primitive2d::FillGradientPrimitive2D* >(xReference.get()); 1957cdf0e10cSrcweir } 1958cdf0e10cSrcweir 1959cdf0e10cSrcweir // Check also for correct ID to exclude derived implementations 1960cdf0e10cSrcweir if(pFiGradient && PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D == pFiGradient->getPrimitive2DID()) 1961cdf0e10cSrcweir { 1962cdf0e10cSrcweir // various content, create content-metafile 1963cdf0e10cSrcweir GDIMetaFile aContentMetafile; 1964cdf0e10cSrcweir const Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile)); 1965cdf0e10cSrcweir 1966cdf0e10cSrcweir // re-create a VCL-gradient from FillGradientPrimitive2D 1967cdf0e10cSrcweir Gradient aVCLGradient; 1968cdf0e10cSrcweir impConvertFillGradientAttributeToVCLGradient(aVCLGradient, pFiGradient->getFillGradient(), true); 1969cdf0e10cSrcweir 1970cdf0e10cSrcweir // render it to VCL 1971cdf0e10cSrcweir mpOutputDevice->DrawTransparent( 1972cdf0e10cSrcweir aContentMetafile, aPrimitiveRectangle.TopLeft(), 1973cdf0e10cSrcweir aPrimitiveRectangle.GetSize(), aVCLGradient); 1974cdf0e10cSrcweir } 1975cdf0e10cSrcweir else 1976cdf0e10cSrcweir { 1977cdf0e10cSrcweir // sub-transparence group. Draw to VDev first. 1978cdf0e10cSrcweir // this may get refined to tiling when resolution is too big here 1979cdf0e10cSrcweir 1980cdf0e10cSrcweir // need to avoid switching off MapMode stuff here; maybe need another 1981cdf0e10cSrcweir // tooling class, cannot just do the same as with the pixel renderer. 1982cdf0e10cSrcweir // Need to experiment... 1983cdf0e10cSrcweir 1984cdf0e10cSrcweir // Okay, basic implementation finished and tested. The DPI stuff was hard 1985cdf0e10cSrcweir // and not easy to find out that it's needed. 1986cdf0e10cSrcweir // Since this will not yet happen normally (as long as noone constructs 1987cdf0e10cSrcweir // transparence primitives with non-trivial transparence content) i will for now not 1988cdf0e10cSrcweir // refine to tiling here. 1989cdf0e10cSrcweir 1990cdf0e10cSrcweir basegfx::B2DRange aViewRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D())); 1991cdf0e10cSrcweir aViewRange.transform(maCurrentTransformation); 1992cdf0e10cSrcweir const Rectangle aRectLogic( 1993cdf0e10cSrcweir (sal_Int32)floor(aViewRange.getMinX()), (sal_Int32)floor(aViewRange.getMinY()), 1994cdf0e10cSrcweir (sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY())); 1995cdf0e10cSrcweir const Rectangle aRectPixel(mpOutputDevice->LogicToPixel(aRectLogic)); 199689cebadeSArmin Le Grand Size aSizePixel(aRectPixel.GetSize()); 1997cdf0e10cSrcweir const Point aEmptyPoint; 1998cdf0e10cSrcweir VirtualDevice aBufferDevice; 199989cebadeSArmin Le Grand const sal_uInt32 nMaxQuadratPixels(500000); 200089cebadeSArmin Le Grand const sal_uInt32 nViewVisibleArea(aSizePixel.getWidth() * aSizePixel.getHeight()); 200189cebadeSArmin Le Grand double fReduceFactor(1.0); 200289cebadeSArmin Le Grand 200389cebadeSArmin Le Grand if(nViewVisibleArea > nMaxQuadratPixels) 200489cebadeSArmin Le Grand { 200589cebadeSArmin Le Grand // reduce render size 200689cebadeSArmin Le Grand fReduceFactor = sqrt((double)nMaxQuadratPixels / (double)nViewVisibleArea); 200789cebadeSArmin Le Grand aSizePixel = Size(basegfx::fround((double)aSizePixel.getWidth() * fReduceFactor), 200889cebadeSArmin Le Grand basegfx::fround((double)aSizePixel.getHeight() * fReduceFactor)); 200989cebadeSArmin Le Grand } 2010cdf0e10cSrcweir 2011cdf0e10cSrcweir if(aBufferDevice.SetOutputSizePixel(aSizePixel)) 2012cdf0e10cSrcweir { 2013cdf0e10cSrcweir // create and set MapModes for target devices 2014cdf0e10cSrcweir MapMode aNewMapMode(mpOutputDevice->GetMapMode()); 2015cdf0e10cSrcweir aNewMapMode.SetOrigin(Point(-aRectLogic.Left(), -aRectLogic.Top())); 2016cdf0e10cSrcweir aBufferDevice.SetMapMode(aNewMapMode); 2017cdf0e10cSrcweir 2018cdf0e10cSrcweir // prepare view transformation for target renderers 2019cdf0e10cSrcweir // ATTENTION! Need to apply another scaling because of the potential DPI differences 2020cdf0e10cSrcweir // between Printer and VDev (mpOutputDevice and aBufferDevice here). 2021cdf0e10cSrcweir // To get the DPI, LogicToPixel from (1,1) from MAP_INCH needs to be used. 2022cdf0e10cSrcweir basegfx::B2DHomMatrix aViewTransform(aBufferDevice.GetViewTransformation()); 2023cdf0e10cSrcweir const Size aDPIOld(mpOutputDevice->LogicToPixel(Size(1, 1), MAP_INCH)); 2024cdf0e10cSrcweir const Size aDPINew(aBufferDevice.LogicToPixel(Size(1, 1), MAP_INCH)); 2025cdf0e10cSrcweir const double fDPIXChange((double)aDPIOld.getWidth() / (double)aDPINew.getWidth()); 2026cdf0e10cSrcweir const double fDPIYChange((double)aDPIOld.getHeight() / (double)aDPINew.getHeight()); 2027cdf0e10cSrcweir 2028cdf0e10cSrcweir if(!basegfx::fTools::equal(fDPIXChange, 1.0) || !basegfx::fTools::equal(fDPIYChange, 1.0)) 2029cdf0e10cSrcweir { 2030cdf0e10cSrcweir aViewTransform.scale(fDPIXChange, fDPIYChange); 2031cdf0e10cSrcweir } 2032cdf0e10cSrcweir 203389cebadeSArmin Le Grand // also take scaling from Size reduction into acount 203489cebadeSArmin Le Grand if(!basegfx::fTools::equal(fReduceFactor, 1.0)) 203589cebadeSArmin Le Grand { 203689cebadeSArmin Le Grand aViewTransform.scale(fReduceFactor, fReduceFactor); 203789cebadeSArmin Le Grand } 203889cebadeSArmin Le Grand 2039cdf0e10cSrcweir // create view information and pixel renderer. Reuse known ViewInformation 2040cdf0e10cSrcweir // except new transformation and range 2041cdf0e10cSrcweir const geometry::ViewInformation2D aViewInfo( 2042cdf0e10cSrcweir getViewInformation2D().getObjectTransformation(), 2043cdf0e10cSrcweir aViewTransform, 2044cdf0e10cSrcweir aViewRange, 2045cdf0e10cSrcweir getViewInformation2D().getVisualizedPage(), 2046cdf0e10cSrcweir getViewInformation2D().getViewTime(), 2047cdf0e10cSrcweir getViewInformation2D().getExtendedInformationSequence()); 2048cdf0e10cSrcweir 2049cdf0e10cSrcweir VclPixelProcessor2D aBufferProcessor(aViewInfo, aBufferDevice); 2050cdf0e10cSrcweir 2051cdf0e10cSrcweir // draw content using pixel renderer 2052cdf0e10cSrcweir aBufferProcessor.process(rContent); 2053cdf0e10cSrcweir const Bitmap aBmContent(aBufferDevice.GetBitmap(aEmptyPoint, aSizePixel)); 2054cdf0e10cSrcweir 2055cdf0e10cSrcweir // draw transparence using pixel renderer 2056cdf0e10cSrcweir aBufferDevice.Erase(); 2057cdf0e10cSrcweir aBufferProcessor.process(rTransparence); 2058cdf0e10cSrcweir const AlphaMask aBmAlpha(aBufferDevice.GetBitmap(aEmptyPoint, aSizePixel)); 2059cdf0e10cSrcweir 2060cdf0e10cSrcweir #ifdef DBG_UTIL 2061cdf0e10cSrcweir static bool bDoSaveForVisualControl(false); 2062cdf0e10cSrcweir if(bDoSaveForVisualControl) 2063cdf0e10cSrcweir { 2064cdf0e10cSrcweir SvFileStream aNew(String(ByteString( "c:\\test.bmp" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC); 2065cdf0e10cSrcweir aNew << aBmContent; 2066cdf0e10cSrcweir } 2067cdf0e10cSrcweir #endif 2068cdf0e10cSrcweir 2069cdf0e10cSrcweir // paint 2070cdf0e10cSrcweir mpOutputDevice->DrawBitmapEx( 2071cdf0e10cSrcweir aRectLogic.TopLeft(), 2072cdf0e10cSrcweir aRectLogic.GetSize(), 2073cdf0e10cSrcweir BitmapEx(aBmContent, aBmAlpha)); 2074cdf0e10cSrcweir } 2075cdf0e10cSrcweir } 2076cdf0e10cSrcweir } 2077cdf0e10cSrcweir 2078cdf0e10cSrcweir break; 2079cdf0e10cSrcweir } 2080cdf0e10cSrcweir case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D : 2081cdf0e10cSrcweir { 2082cdf0e10cSrcweir // use default transform group pocessing 2083cdf0e10cSrcweir RenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate)); 2084cdf0e10cSrcweir break; 2085cdf0e10cSrcweir } 2086cdf0e10cSrcweir case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D : 2087cdf0e10cSrcweir { 2088cdf0e10cSrcweir // new XDrawPage for ViewInformation2D 2089cdf0e10cSrcweir RenderPagePreviewPrimitive2D(static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate)); 2090cdf0e10cSrcweir break; 2091cdf0e10cSrcweir } 2092cdf0e10cSrcweir case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D : 2093cdf0e10cSrcweir { 2094cdf0e10cSrcweir // use default marker array pocessing 2095cdf0e10cSrcweir RenderMarkerArrayPrimitive2D(static_cast< const primitive2d::MarkerArrayPrimitive2D& >(rCandidate)); 2096cdf0e10cSrcweir break; 2097cdf0e10cSrcweir } 2098cdf0e10cSrcweir case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D : 2099cdf0e10cSrcweir { 2100cdf0e10cSrcweir // use default point array pocessing 2101cdf0e10cSrcweir RenderPointArrayPrimitive2D(static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate)); 2102cdf0e10cSrcweir break; 2103cdf0e10cSrcweir } 2104cdf0e10cSrcweir case PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D : 2105cdf0e10cSrcweir { 2106cdf0e10cSrcweir // structured tag primitive 2107cdf0e10cSrcweir const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate = static_cast< const primitive2d::StructureTagPrimitive2D& >(rCandidate); 2108cdf0e10cSrcweir const vcl::PDFWriter::StructElement& rTagElement(rStructureTagCandidate.getStructureElement()); 2109cdf0e10cSrcweir const bool bTagUsed(vcl::PDFWriter::NonStructElement != rTagElement); 2110cdf0e10cSrcweir 2111cdf0e10cSrcweir if(mpPDFExtOutDevData && bTagUsed) 2112cdf0e10cSrcweir { 2113cdf0e10cSrcweir // write start tag 2114cdf0e10cSrcweir mpPDFExtOutDevData->BeginStructureElement(rTagElement); 2115cdf0e10cSrcweir } 2116cdf0e10cSrcweir 2117cdf0e10cSrcweir // proccess childs normally 2118cdf0e10cSrcweir process(rStructureTagCandidate.getChildren()); 2119cdf0e10cSrcweir 2120cdf0e10cSrcweir if(mpPDFExtOutDevData && bTagUsed) 2121cdf0e10cSrcweir { 2122cdf0e10cSrcweir // write end tag 2123cdf0e10cSrcweir mpPDFExtOutDevData->EndStructureElement(); 2124cdf0e10cSrcweir } 2125cdf0e10cSrcweir 2126cdf0e10cSrcweir break; 2127cdf0e10cSrcweir } 2128cdf0e10cSrcweir case PRIMITIVE2D_ID_EPSPRIMITIVE2D : 2129cdf0e10cSrcweir { 2130cdf0e10cSrcweir RenderEpsPrimitive2D(static_cast< const primitive2d::EpsPrimitive2D& >(rCandidate)); 2131cdf0e10cSrcweir break; 2132cdf0e10cSrcweir } 2133cdf0e10cSrcweir default : 2134cdf0e10cSrcweir { 2135cdf0e10cSrcweir // process recursively 2136cdf0e10cSrcweir process(rCandidate.get2DDecomposition(getViewInformation2D())); 2137cdf0e10cSrcweir break; 2138cdf0e10cSrcweir } 2139cdf0e10cSrcweir } 2140cdf0e10cSrcweir } 2141cdf0e10cSrcweir } // end of namespace processor2d 2142cdf0e10cSrcweir } // end of namespace drawinglayer 2143cdf0e10cSrcweir 2144cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 2145cdf0e10cSrcweir // eof 2146