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 22cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 23cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx" 24cdf0e10cSrcweir 25cdf0e10cSrcweir #include <drawinglayer/processor2d/vclmetafileprocessor2d.hxx> 26cdf0e10cSrcweir #include <tools/gen.hxx> 27cdf0e10cSrcweir #include <vcl/virdev.hxx> 28cdf0e10cSrcweir #include <vcl/gdimtf.hxx> 29cdf0e10cSrcweir #include <vcl/gradient.hxx> 30cdf0e10cSrcweir #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> 31cdf0e10cSrcweir #include <drawinglayer/primitive2d/textprimitive2d.hxx> 32cdf0e10cSrcweir #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> 33cdf0e10cSrcweir #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> 34cdf0e10cSrcweir #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> 35cdf0e10cSrcweir #include <drawinglayer/primitive2d/maskprimitive2d.hxx> 36cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygonclipper.hxx> 37cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx> 38cdf0e10cSrcweir #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> 39cdf0e10cSrcweir #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> 40cdf0e10cSrcweir #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx> 41cdf0e10cSrcweir #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx> 42cdf0e10cSrcweir #include <drawinglayer/processor2d/vclpixelprocessor2d.hxx> 43cdf0e10cSrcweir #include <tools/stream.hxx> 44cdf0e10cSrcweir #include <drawinglayer/primitive2d/transformprimitive2d.hxx> 45cdf0e10cSrcweir #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx> 46cdf0e10cSrcweir #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx> 47cdf0e10cSrcweir #include <vcl/graphictools.hxx> 48cdf0e10cSrcweir #include <vcl/metaact.hxx> 49cdf0e10cSrcweir #include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx> 50cdf0e10cSrcweir #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx> 51cdf0e10cSrcweir #include <comphelper/processfactory.hxx> 52cdf0e10cSrcweir #include <rtl/ustring.hxx> 53cdf0e10cSrcweir #include <com/sun/star/i18n/CharacterIteratorMode.hdl> 54cdf0e10cSrcweir #include <com/sun/star/i18n/WordType.hpp> 55cdf0e10cSrcweir #include <drawinglayer/primitive2d/controlprimitive2d.hxx> 56cdf0e10cSrcweir #include <drawinglayer/primitive2d/graphicprimitive2d.hxx> 57cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx> 58cdf0e10cSrcweir #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx> 59cdf0e10cSrcweir #include <drawinglayer/primitive2d/epsprimitive2d.hxx> 60cdf0e10cSrcweir #include <basegfx/polygon/b2dlinegeometry.hxx> 6145fd3b9aSArmin Le Grand #include <vcl/dibtools.hxx> 62cdf0e10cSrcweir 63cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 64cdf0e10cSrcweir // for PDFExtOutDevData Graphic support 65cdf0e10cSrcweir 66cdf0e10cSrcweir #include <vcl/graph.hxx> 67cdf0e10cSrcweir #include <vcl/svapp.hxx> 68cdf0e10cSrcweir #include <toolkit/helper/formpdfexport.hxx> 69cdf0e10cSrcweir 70cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 71cdf0e10cSrcweir // for Control printing 72cdf0e10cSrcweir 73cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp> 74cdf0e10cSrcweir 75cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 76cdf0e10cSrcweir // for StructureTagPrimitive support in sd's unomodel.cxx 77cdf0e10cSrcweir 78cdf0e10cSrcweir #include <drawinglayer/primitive2d/structuretagprimitive2d.hxx> 79cdf0e10cSrcweir 80cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 81cdf0e10cSrcweir 82cdf0e10cSrcweir using namespace com::sun::star; 83cdf0e10cSrcweir 84cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 85cdf0e10cSrcweir // #112245# definition for maximum allowed point count due to Metafile target. 86cdf0e10cSrcweir // To be on the safe side with the old tools polygon, use slightly less then 87cdf0e10cSrcweir // the theoretical maximum (bad experiences with tools polygon) 88cdf0e10cSrcweir 89cdf0e10cSrcweir #define MAX_POLYGON_POINT_COUNT_METAFILE (0x0000fff0) 90cdf0e10cSrcweir 91cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 92cdf0e10cSrcweir 93cdf0e10cSrcweir namespace 94cdf0e10cSrcweir { 95cdf0e10cSrcweir // #112245# helper to split line polygon in half 96cdf0e10cSrcweir void splitLinePolygon( 97cdf0e10cSrcweir const basegfx::B2DPolygon& rBasePolygon, 98cdf0e10cSrcweir basegfx::B2DPolygon& o_aLeft, 99cdf0e10cSrcweir basegfx::B2DPolygon& o_aRight) 100cdf0e10cSrcweir { 101cdf0e10cSrcweir const sal_uInt32 nCount(rBasePolygon.count()); 102cdf0e10cSrcweir 103cdf0e10cSrcweir if(nCount) 104cdf0e10cSrcweir { 105cdf0e10cSrcweir const sal_uInt32 nHalfCount((nCount - 1) >> 1); 106cdf0e10cSrcweir 107cdf0e10cSrcweir o_aLeft = basegfx::B2DPolygon(rBasePolygon, 0, nHalfCount + 1); 108cdf0e10cSrcweir o_aLeft.setClosed(false); 109cdf0e10cSrcweir 110cdf0e10cSrcweir o_aRight = basegfx::B2DPolygon(rBasePolygon, nHalfCount, nCount - nHalfCount); 111cdf0e10cSrcweir o_aRight.setClosed(false); 112cdf0e10cSrcweir 113cdf0e10cSrcweir if(rBasePolygon.isClosed()) 114cdf0e10cSrcweir { 115cdf0e10cSrcweir o_aRight.append(rBasePolygon.getB2DPoint(0)); 116cdf0e10cSrcweir 117cdf0e10cSrcweir if(rBasePolygon.areControlPointsUsed()) 118cdf0e10cSrcweir { 119cdf0e10cSrcweir o_aRight.setControlPoints( 120cdf0e10cSrcweir o_aRight.count() - 1, 121cdf0e10cSrcweir rBasePolygon.getPrevControlPoint(0), 122cdf0e10cSrcweir rBasePolygon.getNextControlPoint(0)); 123cdf0e10cSrcweir } 124cdf0e10cSrcweir } 125cdf0e10cSrcweir } 126cdf0e10cSrcweir else 127cdf0e10cSrcweir { 128cdf0e10cSrcweir o_aLeft.clear(); 129cdf0e10cSrcweir o_aRight.clear(); 130cdf0e10cSrcweir } 131cdf0e10cSrcweir } 132cdf0e10cSrcweir 133cdf0e10cSrcweir // #112245# helper to evtl. split filled polygons to maximum metafile point count 134cdf0e10cSrcweir bool fillPolyPolygonNeededToBeSplit(basegfx::B2DPolyPolygon& rPolyPolygon) 135cdf0e10cSrcweir { 136cdf0e10cSrcweir bool bRetval(false); 137cdf0e10cSrcweir const sal_uInt32 nPolyCount(rPolyPolygon.count()); 138cdf0e10cSrcweir 139cdf0e10cSrcweir if(nPolyCount) 140cdf0e10cSrcweir { 141cdf0e10cSrcweir basegfx::B2DPolyPolygon aSplitted; 142cdf0e10cSrcweir 143cdf0e10cSrcweir for(sal_uInt32 a(0); a < nPolyCount; a++) 144cdf0e10cSrcweir { 145cdf0e10cSrcweir const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a)); 146cdf0e10cSrcweir const sal_uInt32 nPointCount(aCandidate.count()); 147cdf0e10cSrcweir bool bNeedToSplit(false); 148cdf0e10cSrcweir 149cdf0e10cSrcweir if(aCandidate.areControlPointsUsed()) 150cdf0e10cSrcweir { 151cdf0e10cSrcweir // compare with the maximum for bezier curved polygons 152cdf0e10cSrcweir bNeedToSplit = nPointCount > ((MAX_POLYGON_POINT_COUNT_METAFILE / 3L) - 1L); 153cdf0e10cSrcweir } 154cdf0e10cSrcweir else 155cdf0e10cSrcweir { 156cdf0e10cSrcweir // compare with the maximum for simple point polygons 157cdf0e10cSrcweir bNeedToSplit = nPointCount > (MAX_POLYGON_POINT_COUNT_METAFILE - 1); 158cdf0e10cSrcweir } 159cdf0e10cSrcweir 160cdf0e10cSrcweir if(bNeedToSplit) 161cdf0e10cSrcweir { 162cdf0e10cSrcweir // need to split the partial polygon 163cdf0e10cSrcweir const basegfx::B2DRange aRange(aCandidate.getB2DRange()); 164cdf0e10cSrcweir const basegfx::B2DPoint aCenter(aRange.getCenter()); 165cdf0e10cSrcweir 166cdf0e10cSrcweir if(aRange.getWidth() > aRange.getHeight()) 167cdf0e10cSrcweir { 168cdf0e10cSrcweir // clip in left and right 169cdf0e10cSrcweir const basegfx::B2DPolyPolygon aLeft( 170cdf0e10cSrcweir basegfx::tools::clipPolygonOnParallelAxis( 171cdf0e10cSrcweir aCandidate, 172cdf0e10cSrcweir false, 173cdf0e10cSrcweir true, 174cdf0e10cSrcweir aCenter.getX(), 175cdf0e10cSrcweir false)); 176cdf0e10cSrcweir const basegfx::B2DPolyPolygon aRight( 177cdf0e10cSrcweir basegfx::tools::clipPolygonOnParallelAxis( 178cdf0e10cSrcweir aCandidate, 179cdf0e10cSrcweir false, 180cdf0e10cSrcweir false, 181cdf0e10cSrcweir aCenter.getX(), 182cdf0e10cSrcweir false)); 183cdf0e10cSrcweir 184cdf0e10cSrcweir aSplitted.append(aLeft); 185cdf0e10cSrcweir aSplitted.append(aRight); 186cdf0e10cSrcweir } 187cdf0e10cSrcweir else 188cdf0e10cSrcweir { 189cdf0e10cSrcweir // clip in top and bottom 190cdf0e10cSrcweir const basegfx::B2DPolyPolygon aTop( 191cdf0e10cSrcweir basegfx::tools::clipPolygonOnParallelAxis( 192cdf0e10cSrcweir aCandidate, 193cdf0e10cSrcweir true, 194cdf0e10cSrcweir true, 195cdf0e10cSrcweir aCenter.getY(), 196cdf0e10cSrcweir false)); 197cdf0e10cSrcweir const basegfx::B2DPolyPolygon aBottom( 198cdf0e10cSrcweir basegfx::tools::clipPolygonOnParallelAxis( 199cdf0e10cSrcweir aCandidate, 200cdf0e10cSrcweir true, 201cdf0e10cSrcweir false, 202cdf0e10cSrcweir aCenter.getY(), 203cdf0e10cSrcweir false)); 204cdf0e10cSrcweir 205cdf0e10cSrcweir aSplitted.append(aTop); 206cdf0e10cSrcweir aSplitted.append(aBottom); 207cdf0e10cSrcweir } 208cdf0e10cSrcweir } 209cdf0e10cSrcweir else 210cdf0e10cSrcweir { 211cdf0e10cSrcweir aSplitted.append(aCandidate); 212cdf0e10cSrcweir } 213cdf0e10cSrcweir } 214cdf0e10cSrcweir 215cdf0e10cSrcweir if(aSplitted.count() != nPolyCount) 216cdf0e10cSrcweir { 217cdf0e10cSrcweir rPolyPolygon = aSplitted; 218cdf0e10cSrcweir } 219cdf0e10cSrcweir } 220cdf0e10cSrcweir 221cdf0e10cSrcweir return bRetval; 222cdf0e10cSrcweir } 223cdf0e10cSrcweir } // end of anonymous namespace 224cdf0e10cSrcweir 225cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 226cdf0e10cSrcweir 227cdf0e10cSrcweir namespace drawinglayer 228cdf0e10cSrcweir { 229cdf0e10cSrcweir namespace processor2d 230cdf0e10cSrcweir { 231cdf0e10cSrcweir Rectangle VclMetafileProcessor2D::impDumpToMetaFile( 232cdf0e10cSrcweir const primitive2d::Primitive2DSequence& rContent, 233cdf0e10cSrcweir GDIMetaFile& o_rContentMetafile) 234cdf0e10cSrcweir { 235cdf0e10cSrcweir // Prepare VDev, MetaFile and connections 236cdf0e10cSrcweir OutputDevice* pLastOutputDevice = mpOutputDevice; 237cdf0e10cSrcweir GDIMetaFile* pLastMetafile = mpMetaFile; 238cdf0e10cSrcweir basegfx::B2DRange aPrimitiveRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D())); 239cdf0e10cSrcweir 240cdf0e10cSrcweir // transform primitive range with current transformation (e.g shadow offset) 241cdf0e10cSrcweir aPrimitiveRange.transform(maCurrentTransformation); 242cdf0e10cSrcweir 243cdf0e10cSrcweir const Rectangle aPrimitiveRectangle( 244cdf0e10cSrcweir basegfx::fround(aPrimitiveRange.getMinX()), basegfx::fround(aPrimitiveRange.getMinY()), 245cdf0e10cSrcweir basegfx::fround(aPrimitiveRange.getMaxX()), basegfx::fround(aPrimitiveRange.getMaxY())); 246cdf0e10cSrcweir VirtualDevice aContentVDev; 247cdf0e10cSrcweir MapMode aNewMapMode(pLastOutputDevice->GetMapMode()); 248cdf0e10cSrcweir 249cdf0e10cSrcweir mpOutputDevice = &aContentVDev; 250cdf0e10cSrcweir mpMetaFile = &o_rContentMetafile; 251cdf0e10cSrcweir aContentVDev.EnableOutput(false); 252cdf0e10cSrcweir aContentVDev.SetMapMode(pLastOutputDevice->GetMapMode()); 253cdf0e10cSrcweir o_rContentMetafile.Record(&aContentVDev); 254cdf0e10cSrcweir aContentVDev.SetLineColor(pLastOutputDevice->GetLineColor()); 255cdf0e10cSrcweir aContentVDev.SetFillColor(pLastOutputDevice->GetFillColor()); 256cdf0e10cSrcweir aContentVDev.SetFont(pLastOutputDevice->GetFont()); 257cdf0e10cSrcweir aContentVDev.SetDrawMode(pLastOutputDevice->GetDrawMode()); 258cdf0e10cSrcweir aContentVDev.SetSettings(pLastOutputDevice->GetSettings()); 259cdf0e10cSrcweir aContentVDev.SetRefPoint(pLastOutputDevice->GetRefPoint()); 260cdf0e10cSrcweir 261cdf0e10cSrcweir // dump to MetaFile 262cdf0e10cSrcweir process(rContent); 263cdf0e10cSrcweir 264cdf0e10cSrcweir // cleanups 265cdf0e10cSrcweir o_rContentMetafile.Stop(); 266cdf0e10cSrcweir o_rContentMetafile.WindStart(); 267cdf0e10cSrcweir aNewMapMode.SetOrigin(aPrimitiveRectangle.TopLeft()); 268cdf0e10cSrcweir o_rContentMetafile.SetPrefMapMode(aNewMapMode); 269cdf0e10cSrcweir o_rContentMetafile.SetPrefSize(aPrimitiveRectangle.GetSize()); 270cdf0e10cSrcweir mpOutputDevice = pLastOutputDevice; 271cdf0e10cSrcweir mpMetaFile = pLastMetafile; 272cdf0e10cSrcweir 273cdf0e10cSrcweir return aPrimitiveRectangle; 274cdf0e10cSrcweir } 275cdf0e10cSrcweir 276cdf0e10cSrcweir void VclMetafileProcessor2D::impConvertFillGradientAttributeToVCLGradient( 277cdf0e10cSrcweir Gradient& o_rVCLGradient, 278cdf0e10cSrcweir const attribute::FillGradientAttribute& rFiGrAtt, 279cdf0e10cSrcweir bool bIsTransparenceGradient) 280cdf0e10cSrcweir { 281cdf0e10cSrcweir if(bIsTransparenceGradient) 282cdf0e10cSrcweir { 283cdf0e10cSrcweir // it's about transparence channel intensities (black/white), do not use color modifier 284cdf0e10cSrcweir o_rVCLGradient.SetStartColor(Color(rFiGrAtt.getStartColor())); 285cdf0e10cSrcweir o_rVCLGradient.SetEndColor(Color(rFiGrAtt.getEndColor())); 286cdf0e10cSrcweir } 287cdf0e10cSrcweir else 288cdf0e10cSrcweir { 289cdf0e10cSrcweir // use color modifier to influence start/end color of gradient 290cdf0e10cSrcweir o_rVCLGradient.SetStartColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getStartColor()))); 291cdf0e10cSrcweir o_rVCLGradient.SetEndColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getEndColor()))); 292cdf0e10cSrcweir } 293cdf0e10cSrcweir 294cdf0e10cSrcweir o_rVCLGradient.SetAngle(static_cast< sal_uInt16 >(rFiGrAtt.getAngle() * (1.0 / F_PI1800))); 295cdf0e10cSrcweir o_rVCLGradient.SetBorder(static_cast< sal_uInt16 >(rFiGrAtt.getBorder() * 100.0)); 296cdf0e10cSrcweir o_rVCLGradient.SetOfsX(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetX() * 100.0)); 297cdf0e10cSrcweir o_rVCLGradient.SetOfsY(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetY() * 100.0)); 298cdf0e10cSrcweir o_rVCLGradient.SetSteps(rFiGrAtt.getSteps()); 299cdf0e10cSrcweir 300cdf0e10cSrcweir // defaults for intensity; those were computed into the start/end colors already 301cdf0e10cSrcweir o_rVCLGradient.SetStartIntensity(100); 302cdf0e10cSrcweir o_rVCLGradient.SetEndIntensity(100); 303cdf0e10cSrcweir 304cdf0e10cSrcweir switch(rFiGrAtt.getStyle()) 305cdf0e10cSrcweir { 306cdf0e10cSrcweir default : // attribute::GRADIENTSTYLE_LINEAR : 307cdf0e10cSrcweir { 308cdf0e10cSrcweir o_rVCLGradient.SetStyle(GRADIENT_LINEAR); 309cdf0e10cSrcweir break; 310cdf0e10cSrcweir } 311cdf0e10cSrcweir case attribute::GRADIENTSTYLE_AXIAL : 312cdf0e10cSrcweir { 313cdf0e10cSrcweir o_rVCLGradient.SetStyle(GRADIENT_AXIAL); 314cdf0e10cSrcweir break; 315cdf0e10cSrcweir } 316cdf0e10cSrcweir case attribute::GRADIENTSTYLE_RADIAL : 317cdf0e10cSrcweir { 318cdf0e10cSrcweir o_rVCLGradient.SetStyle(GRADIENT_RADIAL); 319cdf0e10cSrcweir break; 320cdf0e10cSrcweir } 321cdf0e10cSrcweir case attribute::GRADIENTSTYLE_ELLIPTICAL : 322cdf0e10cSrcweir { 323cdf0e10cSrcweir o_rVCLGradient.SetStyle(GRADIENT_ELLIPTICAL); 324cdf0e10cSrcweir break; 325cdf0e10cSrcweir } 326cdf0e10cSrcweir case attribute::GRADIENTSTYLE_SQUARE : 327cdf0e10cSrcweir { 328cdf0e10cSrcweir o_rVCLGradient.SetStyle(GRADIENT_SQUARE); 329cdf0e10cSrcweir break; 330cdf0e10cSrcweir } 331cdf0e10cSrcweir case attribute::GRADIENTSTYLE_RECT : 332cdf0e10cSrcweir { 333cdf0e10cSrcweir o_rVCLGradient.SetStyle(GRADIENT_RECT); 334cdf0e10cSrcweir break; 335cdf0e10cSrcweir } 336cdf0e10cSrcweir } 337cdf0e10cSrcweir } 338cdf0e10cSrcweir 339cdf0e10cSrcweir void VclMetafileProcessor2D::impStartSvtGraphicFill(SvtGraphicFill* pSvtGraphicFill) 340cdf0e10cSrcweir { 341cdf0e10cSrcweir if(pSvtGraphicFill && !mnSvtGraphicFillCount) 342cdf0e10cSrcweir { 343cdf0e10cSrcweir SvMemoryStream aMemStm; 344cdf0e10cSrcweir 345cdf0e10cSrcweir aMemStm << *pSvtGraphicFill; 346cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_BEGIN", 0, static_cast< const sal_uInt8* >(aMemStm.GetData()), aMemStm.Seek(STREAM_SEEK_TO_END))); 347cdf0e10cSrcweir mnSvtGraphicFillCount++; 348cdf0e10cSrcweir } 349cdf0e10cSrcweir } 350cdf0e10cSrcweir 351cdf0e10cSrcweir void VclMetafileProcessor2D::impEndSvtGraphicFill(SvtGraphicFill* pSvtGraphicFill) 352cdf0e10cSrcweir { 353cdf0e10cSrcweir if(pSvtGraphicFill && mnSvtGraphicFillCount) 354cdf0e10cSrcweir { 355cdf0e10cSrcweir mnSvtGraphicFillCount--; 356cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_END")); 357cdf0e10cSrcweir delete pSvtGraphicFill; 358cdf0e10cSrcweir } 359cdf0e10cSrcweir } 360cdf0e10cSrcweir 361cdf0e10cSrcweir SvtGraphicStroke* VclMetafileProcessor2D::impTryToCreateSvtGraphicStroke( 362cdf0e10cSrcweir const basegfx::B2DPolygon& rB2DPolygon, 363cdf0e10cSrcweir const basegfx::BColor* pColor, 364cdf0e10cSrcweir const attribute::LineAttribute* pLineAttribute, 365cdf0e10cSrcweir const attribute::StrokeAttribute* pStrokeAttribute, 366cdf0e10cSrcweir const attribute::LineStartEndAttribute* pStart, 367cdf0e10cSrcweir const attribute::LineStartEndAttribute* pEnd) 368cdf0e10cSrcweir { 369cdf0e10cSrcweir SvtGraphicStroke* pRetval = 0; 370cdf0e10cSrcweir 371cdf0e10cSrcweir if(rB2DPolygon.count() && !mnSvtGraphicStrokeCount) 372cdf0e10cSrcweir { 3739d531167SArmin Le Grand basegfx::B2DPolygon aLocalPolygon(rB2DPolygon); 374cdf0e10cSrcweir basegfx::BColor aStrokeColor; 375cdf0e10cSrcweir basegfx::B2DPolyPolygon aStartArrow; 376cdf0e10cSrcweir basegfx::B2DPolyPolygon aEndArrow; 377cdf0e10cSrcweir 378cdf0e10cSrcweir if(pColor) 379cdf0e10cSrcweir { 380cdf0e10cSrcweir aStrokeColor = *pColor; 381cdf0e10cSrcweir } 382cdf0e10cSrcweir else if(pLineAttribute) 383cdf0e10cSrcweir { 384cdf0e10cSrcweir aStrokeColor = maBColorModifierStack.getModifiedColor(pLineAttribute->getColor()); 385cdf0e10cSrcweir } 386cdf0e10cSrcweir 387cdf0e10cSrcweir // It IS needed to record the stroke color at all in the metafile, 388cdf0e10cSrcweir // SvtGraphicStroke has NO entry for stroke color(!) 389cdf0e10cSrcweir mpOutputDevice->SetLineColor(Color(aStrokeColor)); 390cdf0e10cSrcweir 3919d531167SArmin Le Grand if(!aLocalPolygon.isClosed()) 392cdf0e10cSrcweir { 393cdf0e10cSrcweir double fPolyLength(0.0); 3949d531167SArmin Le Grand double fStart(0.0); 3959d531167SArmin Le Grand double fEnd(0.0); 396cdf0e10cSrcweir 397cdf0e10cSrcweir if(pStart && pStart->isActive()) 398cdf0e10cSrcweir { 3999d531167SArmin Le Grand fPolyLength = basegfx::tools::getLength(aLocalPolygon); 400cdf0e10cSrcweir 401cdf0e10cSrcweir aStartArrow = basegfx::tools::createAreaGeometryForLineStartEnd( 4029d531167SArmin Le Grand aLocalPolygon, pStart->getB2DPolyPolygon(), true, pStart->getWidth(), 4039d531167SArmin Le Grand fPolyLength, pStart->isCentered() ? 0.5 : 0.0, &fStart); 404cdf0e10cSrcweir } 405cdf0e10cSrcweir 406cdf0e10cSrcweir if(pEnd && pEnd->isActive()) 407cdf0e10cSrcweir { 408cdf0e10cSrcweir if(basegfx::fTools::equalZero(fPolyLength)) 409cdf0e10cSrcweir { 4109d531167SArmin Le Grand fPolyLength = basegfx::tools::getLength(aLocalPolygon); 411cdf0e10cSrcweir } 412cdf0e10cSrcweir 413cdf0e10cSrcweir aEndArrow = basegfx::tools::createAreaGeometryForLineStartEnd( 4149d531167SArmin Le Grand aLocalPolygon, pEnd->getB2DPolyPolygon(), false, pEnd->getWidth(), 4159d531167SArmin Le Grand fPolyLength, pEnd->isCentered() ? 0.5 : 0.0, &fEnd); 416cdf0e10cSrcweir } 4179d531167SArmin Le Grand 4189d531167SArmin Le Grand if(0.0 != fStart || 0.0 != fEnd) 4199d531167SArmin Le Grand { 4209d531167SArmin Le Grand // build new poly, consume something from old poly 4219d531167SArmin Le Grand aLocalPolygon = basegfx::tools::getSnippetAbsolute(aLocalPolygon, fStart, fPolyLength - fEnd, fPolyLength); 4229d531167SArmin Le Grand } 423cdf0e10cSrcweir } 424cdf0e10cSrcweir 4255aaf853bSArmin Le Grand SvtGraphicStroke::JoinType eJoin(SvtGraphicStroke::joinNone); 4265aaf853bSArmin Le Grand SvtGraphicStroke::CapType eCap(SvtGraphicStroke::capButt); 427cdf0e10cSrcweir double fLineWidth(0.0); 428cdf0e10cSrcweir double fMiterLength(0.0); 429cdf0e10cSrcweir SvtGraphicStroke::DashArray aDashArray; 430cdf0e10cSrcweir 431cdf0e10cSrcweir if(pLineAttribute) 432cdf0e10cSrcweir { 433b22f5784SArmin Le Grand // pre-fill fLineWidth #119198# Need to apply maCurrentTransformation, too (!) 434b22f5784SArmin Le Grand const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation * basegfx::B2DVector(pLineAttribute->getWidth(), 0.0)); 435b22f5784SArmin Le Grand fLineWidth = aDiscreteUnit.getLength(); 436cdf0e10cSrcweir 437cdf0e10cSrcweir // pre-fill fMiterLength 438cdf0e10cSrcweir fMiterLength = fLineWidth; 439cdf0e10cSrcweir 440cdf0e10cSrcweir // get Join 441cdf0e10cSrcweir switch(pLineAttribute->getLineJoin()) 442cdf0e10cSrcweir { 443cdf0e10cSrcweir default : // basegfx::B2DLINEJOIN_NONE : 444cdf0e10cSrcweir { 445cdf0e10cSrcweir eJoin = SvtGraphicStroke::joinNone; 446cdf0e10cSrcweir break; 447cdf0e10cSrcweir } 448cdf0e10cSrcweir case basegfx::B2DLINEJOIN_BEVEL : 449cdf0e10cSrcweir { 450cdf0e10cSrcweir eJoin = SvtGraphicStroke::joinBevel; 451cdf0e10cSrcweir break; 452cdf0e10cSrcweir } 453cdf0e10cSrcweir case basegfx::B2DLINEJOIN_MIDDLE : 454cdf0e10cSrcweir case basegfx::B2DLINEJOIN_MITER : 455cdf0e10cSrcweir { 456cdf0e10cSrcweir eJoin = SvtGraphicStroke::joinMiter; 457cdf0e10cSrcweir // ATM 15 degrees is assumed 458cdf0e10cSrcweir fMiterLength /= rtl::math::sin(M_PI * (15.0 / 360.0)); 459cdf0e10cSrcweir break; 460cdf0e10cSrcweir } 461cdf0e10cSrcweir case basegfx::B2DLINEJOIN_ROUND : 462cdf0e10cSrcweir { 463cdf0e10cSrcweir eJoin = SvtGraphicStroke::joinRound; 464cdf0e10cSrcweir break; 465cdf0e10cSrcweir } 466cdf0e10cSrcweir } 4675aaf853bSArmin Le Grand 4685aaf853bSArmin Le Grand // get stroke 4695aaf853bSArmin Le Grand switch(pLineAttribute->getLineCap()) 4705aaf853bSArmin Le Grand { 4715aaf853bSArmin Le Grand default: /* com::sun::star::drawing::LineCap_BUTT */ 4725aaf853bSArmin Le Grand { 4735aaf853bSArmin Le Grand eCap = SvtGraphicStroke::capButt; 4745aaf853bSArmin Le Grand break; 4755aaf853bSArmin Le Grand } 4765aaf853bSArmin Le Grand case com::sun::star::drawing::LineCap_ROUND: 4775aaf853bSArmin Le Grand { 4785aaf853bSArmin Le Grand eCap = SvtGraphicStroke::capRound; 4795aaf853bSArmin Le Grand break; 4805aaf853bSArmin Le Grand } 4815aaf853bSArmin Le Grand case com::sun::star::drawing::LineCap_SQUARE: 4825aaf853bSArmin Le Grand { 4835aaf853bSArmin Le Grand eCap = SvtGraphicStroke::capSquare; 4845aaf853bSArmin Le Grand break; 4855aaf853bSArmin Le Grand } 4865aaf853bSArmin Le Grand } 487cdf0e10cSrcweir } 488cdf0e10cSrcweir 489cdf0e10cSrcweir if(pStrokeAttribute) 490cdf0e10cSrcweir { 491cdf0e10cSrcweir // copy dash array 492cdf0e10cSrcweir aDashArray = pStrokeAttribute->getDotDashArray(); 493cdf0e10cSrcweir } 494cdf0e10cSrcweir 495cdf0e10cSrcweir // #i101734# apply current object transformation to created geometry. 496cdf0e10cSrcweir // This is a partial fix. When a object transformation is used which 497cdf0e10cSrcweir // e.g. contains a scaleX != scaleY, an unproportional scaling would 498cdf0e10cSrcweir // have to be applied to the evtl. existing fat line. The current 499cdf0e10cSrcweir // concept of PDF export and SvtGraphicStroke usage does simply not 500cdf0e10cSrcweir // allow handling such definitions. The only clean way would be to 501cdf0e10cSrcweir // add the transformation to SvtGraphicStroke and to handle it there 5029d531167SArmin Le Grand aLocalPolygon.transform(maCurrentTransformation); 503cdf0e10cSrcweir aStartArrow.transform(maCurrentTransformation); 504cdf0e10cSrcweir aEndArrow.transform(maCurrentTransformation); 505cdf0e10cSrcweir 506cdf0e10cSrcweir pRetval = new SvtGraphicStroke( 5079d531167SArmin Le Grand Polygon(aLocalPolygon), 508cdf0e10cSrcweir PolyPolygon(aStartArrow), 509cdf0e10cSrcweir PolyPolygon(aEndArrow), 510cdf0e10cSrcweir mfCurrentUnifiedTransparence, 511cdf0e10cSrcweir fLineWidth, 5125aaf853bSArmin Le Grand eCap, 513cdf0e10cSrcweir eJoin, 514cdf0e10cSrcweir fMiterLength, 515cdf0e10cSrcweir aDashArray); 516cdf0e10cSrcweir } 517cdf0e10cSrcweir 518cdf0e10cSrcweir return pRetval; 519cdf0e10cSrcweir } 520cdf0e10cSrcweir 521cdf0e10cSrcweir void VclMetafileProcessor2D::impStartSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke) 522cdf0e10cSrcweir { 523cdf0e10cSrcweir if(pSvtGraphicStroke && !mnSvtGraphicStrokeCount) 524cdf0e10cSrcweir { 525cdf0e10cSrcweir SvMemoryStream aMemStm; 526cdf0e10cSrcweir 527cdf0e10cSrcweir aMemStm << *pSvtGraphicStroke; 528cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_BEGIN", 0, static_cast< const sal_uInt8* >(aMemStm.GetData()), aMemStm.Seek(STREAM_SEEK_TO_END))); 529cdf0e10cSrcweir mnSvtGraphicStrokeCount++; 530cdf0e10cSrcweir } 531cdf0e10cSrcweir } 532cdf0e10cSrcweir 533cdf0e10cSrcweir void VclMetafileProcessor2D::impEndSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke) 534cdf0e10cSrcweir { 535cdf0e10cSrcweir if(pSvtGraphicStroke && mnSvtGraphicStrokeCount) 536cdf0e10cSrcweir { 537cdf0e10cSrcweir mnSvtGraphicStrokeCount--; 538cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_END")); 539cdf0e10cSrcweir delete pSvtGraphicStroke; 540cdf0e10cSrcweir } 541cdf0e10cSrcweir } 542cdf0e10cSrcweir 543cdf0e10cSrcweir // init static break iterator 544cdf0e10cSrcweir uno::Reference< ::com::sun::star::i18n::XBreakIterator > VclMetafileProcessor2D::mxBreakIterator; 545cdf0e10cSrcweir 546cdf0e10cSrcweir VclMetafileProcessor2D::VclMetafileProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev) 547cdf0e10cSrcweir : VclProcessor2D(rViewInformation, rOutDev), 548cdf0e10cSrcweir mpMetaFile(rOutDev.GetConnectMetaFile()), 549cdf0e10cSrcweir mnSvtGraphicFillCount(0), 550cdf0e10cSrcweir mnSvtGraphicStrokeCount(0), 551cdf0e10cSrcweir mfCurrentUnifiedTransparence(0.0), 552cdf0e10cSrcweir mpPDFExtOutDevData(dynamic_cast< vcl::PDFExtOutDevData* >(rOutDev.GetExtOutDevData())) 553cdf0e10cSrcweir { 554cdf0e10cSrcweir OSL_ENSURE(rOutDev.GetConnectMetaFile(), "VclMetafileProcessor2D: Used on OutDev which has no MetaFile Target (!)"); 555cdf0e10cSrcweir // draw to logic coordinates, do not initialize maCurrentTransformation to viewTransformation 556cdf0e10cSrcweir // but only to ObjectTransformation. Do not change MapMode of destination. 557cdf0e10cSrcweir maCurrentTransformation = rViewInformation.getObjectTransformation(); 558cdf0e10cSrcweir } 559cdf0e10cSrcweir 560cdf0e10cSrcweir VclMetafileProcessor2D::~VclMetafileProcessor2D() 561cdf0e10cSrcweir { 562cdf0e10cSrcweir // MapMode was not changed, no restore necessary 563cdf0e10cSrcweir } 564cdf0e10cSrcweir 565cdf0e10cSrcweir /*********************************************************************************************** 566cdf0e10cSrcweir 567cdf0e10cSrcweir Support of MetaCommentActions in the VclMetafileProcessor2D 568cdf0e10cSrcweir Found MetaCommentActions and how they are supported: 569cdf0e10cSrcweir 570cdf0e10cSrcweir XGRAD_SEQ_BEGIN, XGRAD_SEQ_END: 571cdf0e10cSrcweir 572cdf0e10cSrcweir Used inside OutputDevice::DrawGradient to mark the start and end of a MetaGradientEx action. 573cdf0e10cSrcweir It is used in various exporters/importers to have direct access to the gradient before it 574cdf0e10cSrcweir is rendered by VCL (and thus fragmented to polygon color actions and others). On that base, e.g. 575cdf0e10cSrcweir the Metafile to SdrObject import creates it's gradient objects. 576cdf0e10cSrcweir Best (and safest) way to support it here is to use PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D, 577cdf0e10cSrcweir map it back to the corresponding tools PolyPolygon and the Gradient and just call 578cdf0e10cSrcweir OutputDevice::DrawGradient which creates the necessary compatible actions. 579cdf0e10cSrcweir 580cdf0e10cSrcweir XPATHFILL_SEQ_BEGIN, XPATHFILL_SEQ_END: 581cdf0e10cSrcweir 582cdf0e10cSrcweir Two producers, one is vcl/source/gdi/gdimtf.cxx, line 1273. There, it is transformed 583cdf0e10cSrcweir inside GDIMetaFile::Rotate, nothing to take care of here. 584cdf0e10cSrcweir The second producer is in graphics/svx/source/svdraw/impgrfll.cxx, line 374. This is used 585cdf0e10cSrcweir with each incarnation of Imp_GraphicFill when a metafile is recorded, fillstyle is not 586cdf0e10cSrcweir XFILL_NONE and not completely transparent. It creates a SvtGraphicFill and streams it 587cdf0e10cSrcweir to the comment action. A closing end token is created in the destructor. 588cdf0e10cSrcweir Usages of Imp_GraphicFill are in Do_Paint_Object-methods of SdrCircObj, SdrPathObj and 589cdf0e10cSrcweir SdrRectObj. 590cdf0e10cSrcweir The token users pick various actions from SvtGraphicFill, so it may need to be added for all kind 591cdf0e10cSrcweir of filled objects, even simple colored polygons. It is added as extra information; the 592cdf0e10cSrcweir Metafile actions between the two tokens are interpreted as output generated from those 593cdf0e10cSrcweir fills. Thus, users have the choice to use the SvtGraphicFill info or the created output 594cdf0e10cSrcweir actions. 595cdf0e10cSrcweir Even for XFillTransparenceItem it is used, thus it may need to be supported in 596cdf0e10cSrcweir UnifiedTransparencePrimitive2D, too, when interpreted as normally filled PolyPolygon. 597cdf0e10cSrcweir Implemented for: 598035a2f44SArmin Le Grand PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D, 599cdf0e10cSrcweir PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D, 600cdf0e10cSrcweir PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D, 601cdf0e10cSrcweir PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D, 602cdf0e10cSrcweir and for PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D when detected unified transparence 603cdf0e10cSrcweir 604cdf0e10cSrcweir XPATHSTROKE_SEQ_BEGIN, XPATHSTROKE_SEQ_END: 605cdf0e10cSrcweir 606cdf0e10cSrcweir Similar to pathfill, but using SvtGraphicStroke instead. It also has two producers where one 607cdf0e10cSrcweir is also the GDIMetaFile::Rotate. Another user is MetaCommentAction::Move which modifies the 608cdf0e10cSrcweir contained path accordingly. 609cdf0e10cSrcweir The other one is SdrObject::Imp_DrawLineGeometry. It's done when MetaFile is set at OutDev and 610cdf0e10cSrcweir only when geometry is a single polygon (!). I see no reason for that; in the PS exporter this 611cdf0e10cSrcweir would hinder to make use of PolyPolygon strokes. I will need to add support at: 612cdf0e10cSrcweir PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D 613cdf0e10cSrcweir PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D 614cdf0e10cSrcweir PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D 615cdf0e10cSrcweir This can be done hierarchical, too. 616cdf0e10cSrcweir Okay, base implementation done based on those three primitives. 617cdf0e10cSrcweir 618cdf0e10cSrcweir FIELD_SEQ_BEGIN, FIELD_SEQ_END 619cdf0e10cSrcweir 620cdf0e10cSrcweir Used from slideshow for URLs, created from diverse SvxField implementations inside 621cdf0e10cSrcweir createBeginComment()/createEndComment(). createBeginComment() is used from editeng\impedit3.cxx 622cdf0e10cSrcweir inside ImpEditEngine::Paint. 623cdf0e10cSrcweir Created TextHierarchyFieldPrimitive2D and added needed infos there; it is an group primitive and wraps 624cdf0e10cSrcweir text primitives (but is not limited to that). It contains the field type if special actions for the 625cdf0e10cSrcweir support of FIELD_SEQ_BEGIN/END are needed; this is the case for Page and URL fields. If more is 626cdf0e10cSrcweir needed, it may be supported there. 627cdf0e10cSrcweir FIELD_SEQ_BEGIN;PageField 628cdf0e10cSrcweir FIELD_SEQ_END 629cdf0e10cSrcweir Okay, these are now completely supported by TextHierarchyFieldPrimitive2D. URL works, too. 630cdf0e10cSrcweir 631cdf0e10cSrcweir XTEXT 632cdf0e10cSrcweir 633cdf0e10cSrcweir XTEXT_EOC(i) end of character 634cdf0e10cSrcweir XTEXT_EOW(i) end of word 635cdf0e10cSrcweir XTEXT_EOS(i) end of sentence 636cdf0e10cSrcweir 637cdf0e10cSrcweir this three are with index and are created with the help of a i18n::XBreakIterator in 638cdf0e10cSrcweir ImplDrawWithComments. Simplifying, moving out text painting, reworking to create some 639cdf0e10cSrcweir data structure for holding those TEXT infos. 640cdf0e10cSrcweir Supported directly by TextSimplePortionPrimitive2D with adding a Locale to the basic text 641cdf0e10cSrcweir primitive. In the MetaFileRenderer, the creation is now done (see below). This has the advantage 642cdf0e10cSrcweir that this creations do not need to be done for all paints all the time. This would be 643cdf0e10cSrcweir expensive since the BreakIterator and it's usage is expensive and for each paint also the 644cdf0e10cSrcweir whole character stops would need to be created. 645cdf0e10cSrcweir Created only for TextDecoratedPortionPrimitive2D due to XTEXT_EOL and XTEXT_EOP (see below) 646cdf0e10cSrcweir 647cdf0e10cSrcweir XTEXT_EOL() end of line 648cdf0e10cSrcweir XTEXT_EOP() end of paragraph 649cdf0e10cSrcweir 650cdf0e10cSrcweir First try with boolean marks at TextDecoratedPortionPrimitive2D did not work too well, 651cdf0e10cSrcweir i decided to solve it with structure. I added the TextHierarchyPrimitives for this, 652cdf0e10cSrcweir namely: 653cdf0e10cSrcweir - TextHierarchyLinePrimitive2D: Encapsulates single line 654cdf0e10cSrcweir - TextHierarchyParagraphPrimitive2D: Encapsulates single paragraph 655cdf0e10cSrcweir - TextHierarchyBlockPrimitive2D: encapsulates object texts (only one ATM) 656cdf0e10cSrcweir Those are now supported in hierarchy. This means the MetaFile renderer will support them 657cdf0e10cSrcweir by using them, reculrively using their content and adding MetaFile comments as needed. 658cdf0e10cSrcweir This also means that when another text layouter will be used it will be necessary to 659cdf0e10cSrcweir create/support the same HierarchyPrimitives to support users. 660cdf0e10cSrcweir To transport the information using this hierarchy is best suited to all future needs; 661cdf0e10cSrcweir the slideshow will be able to profit from it directly when using primitives; all other 662cdf0e10cSrcweir renderers not interested in the text structure will just ignore the encapsulations. 663cdf0e10cSrcweir 664cdf0e10cSrcweir XTEXT_PAINTSHAPE_BEGIN, XTEXT_PAINTSHAPE_END 665cdf0e10cSrcweir Supported now by the TextHierarchyBlockPrimitive2D. 666cdf0e10cSrcweir 667cdf0e10cSrcweir EPSReplacementGraphic: 668cdf0e10cSrcweir Only used in goodies\source\filter.vcl\ieps\ieps.cxx and svx\source\xml\xmlgrhlp.cxx to 669cdf0e10cSrcweir hold the original EPS which was imported in the same MetaFile as first 2 entries. Only 670cdf0e10cSrcweir used to export the original again (if exists). 671cdf0e10cSrcweir Not necessary to support with MetaFuleRenderer. 672cdf0e10cSrcweir 673cdf0e10cSrcweir XTEXT_SCROLLRECT, XTEXT_PAINTRECT 674cdf0e10cSrcweir Currently used to get extra MetaFile infos using GraphicExporter which again uses 675cdf0e10cSrcweir SdrTextObj::GetTextScrollMetaFileAndRectangle(). ATM works with primitives since 676cdf0e10cSrcweir the rectangle data is added directly by the GraphicsExporter as comment. Does not need 677cdf0e10cSrcweir to be adapted at once. 678cdf0e10cSrcweir When adapting later, the only user - the diashow - should directly use the provided 679cdf0e10cSrcweir Anination infos in the appropriate primitives (e.g. AnimatedSwitchPrimitive2D) 680cdf0e10cSrcweir 681cdf0e10cSrcweir PRNSPOOL_TRANSPARENTBITMAP_BEGIN, PRNSPOOL_TRANSPARENTBITMAP_END 682cdf0e10cSrcweir VCL usage when printing PL -> THB. Okay, THB confirms that it is only used as 683cdf0e10cSrcweir a fix (hack) while VCL printing. It is needed to not downscale a bitmap which 684cdf0e10cSrcweir was explicitely created for the printer already again to some default maximum 685cdf0e10cSrcweir bitmap sizes. 686cdf0e10cSrcweir Nothing to do here for the primitive renderer. 687cdf0e10cSrcweir 688cdf0e10cSrcweir Support for vcl::PDFExtOutDevData: 689cdf0e10cSrcweir PL knows that SJ did that stuff, it's used to hold a pointer to PDFExtOutDevData at 690cdf0e10cSrcweir the OutDev. When set, some extra data is written there. Trying simple PDF export and 691cdf0e10cSrcweir watching if i get those infos. 692cdf0e10cSrcweir Well, a PDF export does not use e.g. ImpEditEngine::Paint since the PdfFilter uses 693cdf0e10cSrcweir the SdXImpressDocument::render and thus uses the VclMetafileProcessor2D. I will check 694cdf0e10cSrcweir if i get a PDFExtOutDevData at the target output device. 695cdf0e10cSrcweir Indeed, i get one. Checking what all may be done when that extra-device-info is there. 696cdf0e10cSrcweir 697cdf0e10cSrcweir All in all i have to talk to SJ. I will need to emulate some of those actions, but 698cdf0e10cSrcweir i need to discuss which ones. 699cdf0e10cSrcweir In the future, all those infos would be taken from the primitive sequence anyways, 700cdf0e10cSrcweir thus these extensions would potentially be temporary, too. 701cdf0e10cSrcweir Discussed with SJ, added the necessary support and tested it. Details follow. 702cdf0e10cSrcweir 703cdf0e10cSrcweir - In ImpEditEngine::Paint, paragraph infos and URL stuff is added. 704cdf0e10cSrcweir Added in primitive MetaFile renderer. 705cdf0e10cSrcweir Checking URL: Indeed, current version exports it, but it is missing in primitive 706cdf0e10cSrcweir CWS version. Adding support. 707cdf0e10cSrcweir Okay, URLs work. Checked, Done. 708cdf0e10cSrcweir 709cdf0e10cSrcweir - UnoControlPDFExportContact is only created when PDFExtOutDevData is used at the 710cdf0e10cSrcweir target and uno control data is created in UnoControlPDFExportContact::do_PaintObject. 711cdf0e10cSrcweir This may be added in primitive MetaFile renderer. 712cdf0e10cSrcweir Adding support... 713cdf0e10cSrcweir OOps, the necessary helper stuff is in svx/source/form/formpdxexport.cxx in namespace 714cdf0e10cSrcweir svxform. Have to talk to FS if this has to be like that. Especially since 715cdf0e10cSrcweir ::vcl::PDFWriter::AnyWidget is filled out, which is already part of vcl. 716cdf0e10cSrcweir Wrote an eMail to FS, he is on vacation currently. I see no reason why not to move 717cdf0e10cSrcweir that stuff to somewhere else, maybe tools or svtools ?!? We will see... 718cdf0e10cSrcweir Moved to toolkit, so i have to link against it. I tried VCL first, but it did 719cdf0e10cSrcweir not work since VCLUnoHelper::CreateFont is unresolved in VCL (!). Other then the name 720cdf0e10cSrcweir may imply, it is defined in toolkit (!). Since toolkit is linked against VCL itself, 721cdf0e10cSrcweir the lowest move,ment plave is toolkit. 722cdf0e10cSrcweir Checked form control export, it works well. Done. 723cdf0e10cSrcweir 724cdf0e10cSrcweir - In goodies, in GraphicObject::Draw, when the used Graphic is linked, infos are 725cdf0e10cSrcweir generated. I will need to check what happens here with primitives. 726cdf0e10cSrcweir To support, use of GraphicPrimitive2D (PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D) may be needed. 727cdf0e10cSrcweir Added support, but feature is broken in main version, so i cannot test at all. 728cdf0e10cSrcweir Writing a bug to CL (or SJ) and seeing what happens (#i80380#). 729cdf0e10cSrcweir SJ took a look and we got it working. Tested VCL MetaFile Renderer based export, 730cdf0e10cSrcweir as intended, the original file is exported. Works, Done. 731cdf0e10cSrcweir 732cdf0e10cSrcweir 733cdf0e10cSrcweir 734cdf0e10cSrcweir 735cdf0e10cSrcweir To be done: 736cdf0e10cSrcweir 737cdf0e10cSrcweir - Maybe there are more places to take care of for vcl::PDFExtOutDevData! 738cdf0e10cSrcweir 739cdf0e10cSrcweir 740cdf0e10cSrcweir 741cdf0e10cSrcweir ****************************************************************************************************/ 742cdf0e10cSrcweir 743cdf0e10cSrcweir void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate) 744cdf0e10cSrcweir { 745cdf0e10cSrcweir switch(rCandidate.getPrimitive2DID()) 746cdf0e10cSrcweir { 747cdf0e10cSrcweir case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D : 748cdf0e10cSrcweir { 749cdf0e10cSrcweir // directdraw of wrong spell primitive 750cdf0e10cSrcweir // Ignore for VclMetafileProcessor2D, this is for printing and MetaFile recording only 751cdf0e10cSrcweir break; 752cdf0e10cSrcweir } 753cdf0e10cSrcweir case PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D : 754cdf0e10cSrcweir { 755cdf0e10cSrcweir const primitive2d::GraphicPrimitive2D& rGraphicPrimitive = static_cast< const primitive2d::GraphicPrimitive2D& >(rCandidate); 756cdf0e10cSrcweir bool bUsingPDFExtOutDevData(false); 757cdf0e10cSrcweir basegfx::B2DVector aTranslate, aScale; 758cdf0e10cSrcweir static bool bSuppressPDFExtOutDevDataSupport(false); 759cdf0e10cSrcweir 760cdf0e10cSrcweir if(mpPDFExtOutDevData && !bSuppressPDFExtOutDevDataSupport) 761cdf0e10cSrcweir { 762cdf0e10cSrcweir // emulate data handling from UnoControlPDFExportContact, original see 763cdf0e10cSrcweir // svtools/source/graphic/grfmgr.cxx 764cdf0e10cSrcweir const Graphic& rGraphic = rGraphicPrimitive.getGraphicObject().GetGraphic(); 765cdf0e10cSrcweir 766cdf0e10cSrcweir if(rGraphic.IsLink()) 767cdf0e10cSrcweir { 768cdf0e10cSrcweir const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr(); 769cdf0e10cSrcweir 770cdf0e10cSrcweir if(!rAttr.IsSpecialDrawMode() && !rAttr.IsAdjusted()) 771cdf0e10cSrcweir { 772cdf0e10cSrcweir const basegfx::B2DHomMatrix& rTransform = rGraphicPrimitive.getTransform(); 773cdf0e10cSrcweir double fRotate, fShearX; 774cdf0e10cSrcweir rTransform.decompose(aScale, aTranslate, fRotate, fShearX); 775cdf0e10cSrcweir 776cdf0e10cSrcweir if( basegfx::fTools::equalZero( fRotate ) && ( aScale.getX() > 0.0 ) && ( aScale.getY() > 0.0 ) ) 777cdf0e10cSrcweir { 778cdf0e10cSrcweir bUsingPDFExtOutDevData = true; 779cdf0e10cSrcweir mpPDFExtOutDevData->BeginGroup(); 780cdf0e10cSrcweir } 781cdf0e10cSrcweir } 782cdf0e10cSrcweir } 783cdf0e10cSrcweir } 784cdf0e10cSrcweir 785cdf0e10cSrcweir // process recursively and add MetaFile comment 786cdf0e10cSrcweir process(rGraphicPrimitive.get2DDecomposition(getViewInformation2D())); 787cdf0e10cSrcweir 788cdf0e10cSrcweir if(bUsingPDFExtOutDevData) 789cdf0e10cSrcweir { 790cdf0e10cSrcweir // emulate data handling from UnoControlPDFExportContact, original see 791cdf0e10cSrcweir // svtools/source/graphic/grfmgr.cxx 792cdf0e10cSrcweir const basegfx::B2DRange aCurrentRange( 793cdf0e10cSrcweir aTranslate.getX(), aTranslate.getY(), 794cdf0e10cSrcweir aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY()); 795cdf0e10cSrcweir const Rectangle aCurrentRect( 796cdf0e10cSrcweir sal_Int32(floor(aCurrentRange.getMinX())), sal_Int32(floor(aCurrentRange.getMinY())), 797cdf0e10cSrcweir sal_Int32(ceil(aCurrentRange.getMaxX())), sal_Int32(ceil(aCurrentRange.getMaxY()))); 798cdf0e10cSrcweir const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr(); 799ff9ad81eSArmin Le Grand 800ff9ad81eSArmin Le Grand // #123295# As described below this is the expanded, uncropped region 801ff9ad81eSArmin Le Grand // and needs to be given in any case, especially when no cropping it is 802ff9ad81eSArmin Le Grand // equal to the current rect. To make clear: normally the uncropped region 803ff9ad81eSArmin Le Grand // (aka the aCropRect) is bigger than the CurrentRect. Or in other words: 804ff9ad81eSArmin Le Grand // The current rect is the object area. This internal crop definition is 805ff9ad81eSArmin Le Grand // somewhat crude, but used (and defined in graphic-dependent units what 806ff9ad81eSArmin Le Grand // leads to even more problems, percentages would have been better). All 807ff9ad81eSArmin Le Grand // in all this is a place that makes clear that a pure PDF export which does 808ff9ad81eSArmin Le Grand // not use Metafile and the associated hacks (like this one) but is based on 809ff9ad81eSArmin Le Grand // Primitves and uses a Primitive Renderer would be the better choice for 810ff9ad81eSArmin Le Grand // the future. 811ff9ad81eSArmin Le Grand Rectangle aCropRect(aCurrentRect); 812cdf0e10cSrcweir 813cdf0e10cSrcweir if(rAttr.IsCropped()) 814cdf0e10cSrcweir { 815cdf0e10cSrcweir // calculate scalings between real image size and logic object size. This 816cdf0e10cSrcweir // is necessary since the crop values are relative to original bitmap size 817cdf0e10cSrcweir double fFactorX(1.0); 818cdf0e10cSrcweir double fFactorY(1.0); 819cdf0e10cSrcweir 820cdf0e10cSrcweir { 821cdf0e10cSrcweir const MapMode aMapMode100thmm(MAP_100TH_MM); 822cdf0e10cSrcweir const Size aBitmapSize(Application::GetDefaultDevice()->LogicToLogic( 823cdf0e10cSrcweir rGraphicPrimitive.getGraphicObject().GetPrefSize(), 824cdf0e10cSrcweir rGraphicPrimitive.getGraphicObject().GetPrefMapMode(), aMapMode100thmm)); 825cdf0e10cSrcweir const double fDivX(aBitmapSize.Width() - rAttr.GetLeftCrop() - rAttr.GetRightCrop()); 826cdf0e10cSrcweir const double fDivY(aBitmapSize.Height() - rAttr.GetTopCrop() - rAttr.GetBottomCrop()); 827cdf0e10cSrcweir 828cdf0e10cSrcweir if(!basegfx::fTools::equalZero(fDivX)) 829cdf0e10cSrcweir { 830cdf0e10cSrcweir fFactorX = aScale.getX() / fDivX; 831cdf0e10cSrcweir } 832cdf0e10cSrcweir 833cdf0e10cSrcweir if(!basegfx::fTools::equalZero(fDivY)) 834cdf0e10cSrcweir { 835cdf0e10cSrcweir fFactorY = aScale.getY() / fDivY; 836cdf0e10cSrcweir } 837cdf0e10cSrcweir } 838cdf0e10cSrcweir 839cdf0e10cSrcweir // calculate crop range and rect 840cdf0e10cSrcweir basegfx::B2DRange aCropRange; 841cdf0e10cSrcweir aCropRange.expand(aCurrentRange.getMinimum() - basegfx::B2DPoint(rAttr.GetLeftCrop() * fFactorX, rAttr.GetTopCrop() * fFactorY)); 842cdf0e10cSrcweir aCropRange.expand(aCurrentRange.getMaximum() + basegfx::B2DPoint(rAttr.GetRightCrop() * fFactorX, rAttr.GetBottomCrop() * fFactorY)); 843cdf0e10cSrcweir 844cdf0e10cSrcweir aCropRect = Rectangle( 845cdf0e10cSrcweir sal_Int32(floor(aCropRange.getMinX())), sal_Int32(floor(aCropRange.getMinY())), 846cdf0e10cSrcweir sal_Int32(ceil(aCropRange.getMaxX())), sal_Int32(ceil(aCropRange.getMaxY()))); 847cdf0e10cSrcweir } 848cdf0e10cSrcweir 849a133aed6SArmin Le Grand // #123295# 3rd param is uncropped rect, 4th is cropped. The primitive has the cropped 850a133aed6SArmin Le Grand // object transformation, thus aCurrentRect *is* the clip region while aCropRect is the expanded, 851a133aed6SArmin Le Grand // uncropped region. Thus, correct order is aCropRect, aCurrentRect 852a133aed6SArmin Le Grand mpPDFExtOutDevData->EndGroup(rGraphicPrimitive.getGraphicObject().GetGraphic(), 853a133aed6SArmin Le Grand rAttr.GetTransparency(), 854a133aed6SArmin Le Grand aCropRect, 855a133aed6SArmin Le Grand aCurrentRect); 856a133aed6SArmin Le Grand } 857cdf0e10cSrcweir 858cdf0e10cSrcweir break; 859cdf0e10cSrcweir } 860cdf0e10cSrcweir case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D : 861cdf0e10cSrcweir { 862cdf0e10cSrcweir const primitive2d::ControlPrimitive2D& rControlPrimitive = static_cast< const primitive2d::ControlPrimitive2D& >(rCandidate); 863cdf0e10cSrcweir const uno::Reference< awt::XControl >& rXControl(rControlPrimitive.getXControl()); 864cdf0e10cSrcweir bool bIsPrintableControl(false); 865cdf0e10cSrcweir 866cdf0e10cSrcweir // find out if control is printable 867cdf0e10cSrcweir if(rXControl.is()) 868cdf0e10cSrcweir { 869cdf0e10cSrcweir try 870cdf0e10cSrcweir { 871cdf0e10cSrcweir uno::Reference< beans::XPropertySet > xModelProperties(rXControl->getModel(), uno::UNO_QUERY); 872cdf0e10cSrcweir uno::Reference< beans::XPropertySetInfo > xPropertyInfo(xModelProperties.is() 873cdf0e10cSrcweir ? xModelProperties->getPropertySetInfo() 874cdf0e10cSrcweir : uno::Reference< beans::XPropertySetInfo >()); 875cdf0e10cSrcweir const ::rtl::OUString sPrintablePropertyName(RTL_CONSTASCII_USTRINGPARAM("Printable")); 876cdf0e10cSrcweir 877cdf0e10cSrcweir if(xPropertyInfo.is() && xPropertyInfo->hasPropertyByName(sPrintablePropertyName)) 878cdf0e10cSrcweir { 879cdf0e10cSrcweir OSL_VERIFY(xModelProperties->getPropertyValue(sPrintablePropertyName) >>= bIsPrintableControl); 880cdf0e10cSrcweir } 881cdf0e10cSrcweir } 882cdf0e10cSrcweir catch(const uno::Exception&) 883cdf0e10cSrcweir { 884cdf0e10cSrcweir OSL_ENSURE(false, "VclMetafileProcessor2D: No access to printable flag of Control, caught an exception!"); 885cdf0e10cSrcweir } 886cdf0e10cSrcweir } 887cdf0e10cSrcweir 888cdf0e10cSrcweir // PDF export and printing only for printable controls 889cdf0e10cSrcweir if(bIsPrintableControl) 890cdf0e10cSrcweir { 891cdf0e10cSrcweir const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields()); 892cdf0e10cSrcweir bool bDoProcessRecursively(true); 893cdf0e10cSrcweir 894cdf0e10cSrcweir if(bPDFExport) 895cdf0e10cSrcweir { 896cdf0e10cSrcweir // PDF export. Emulate data handling from UnoControlPDFExportContact 897cdf0e10cSrcweir // I have now moved describePDFControl to toolkit, thus i can implement the PDF 898cdf0e10cSrcweir // form control support now as follows 899cdf0e10cSrcweir ::std::auto_ptr< ::vcl::PDFWriter::AnyWidget > pPDFControl; 900cdf0e10cSrcweir ::toolkitform::describePDFControl( rXControl, pPDFControl, *mpPDFExtOutDevData ); 901cdf0e10cSrcweir 902cdf0e10cSrcweir if(pPDFControl.get()) 903cdf0e10cSrcweir { 904cdf0e10cSrcweir // still need to fill in the location (is a class Rectangle) 905cdf0e10cSrcweir const basegfx::B2DRange aRangeLogic(rControlPrimitive.getB2DRange(getViewInformation2D())); 906cdf0e10cSrcweir const Rectangle aRectLogic( 907cdf0e10cSrcweir (sal_Int32)floor(aRangeLogic.getMinX()), (sal_Int32)floor(aRangeLogic.getMinY()), 908cdf0e10cSrcweir (sal_Int32)ceil(aRangeLogic.getMaxX()), (sal_Int32)ceil(aRangeLogic.getMaxY())); 909cdf0e10cSrcweir pPDFControl->Location = aRectLogic; 910cdf0e10cSrcweir 911cdf0e10cSrcweir Size aFontSize(pPDFControl->TextFont.GetSize()); 912cdf0e10cSrcweir aFontSize = mpOutputDevice->LogicToLogic(aFontSize, MapMode(MAP_POINT), mpOutputDevice->GetMapMode()); 913cdf0e10cSrcweir pPDFControl->TextFont.SetSize(aFontSize); 914cdf0e10cSrcweir 915cdf0e10cSrcweir mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Form); 916cdf0e10cSrcweir mpPDFExtOutDevData->CreateControl(*pPDFControl.get()); 917cdf0e10cSrcweir mpPDFExtOutDevData->EndStructureElement(); 918cdf0e10cSrcweir 919cdf0e10cSrcweir // no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject); 920cdf0e10cSrcweir // do not process recursively 921cdf0e10cSrcweir bDoProcessRecursively = false; 922cdf0e10cSrcweir } 923cdf0e10cSrcweir else 924cdf0e10cSrcweir { 925cdf0e10cSrcweir // PDF export did not work, try simple output. 926cdf0e10cSrcweir // Fallback to printer output by not setting bDoProcessRecursively 927cdf0e10cSrcweir // to false. 928cdf0e10cSrcweir } 929cdf0e10cSrcweir } 930cdf0e10cSrcweir 931cdf0e10cSrcweir // #i93169# used flag the wrong way; true means that nothing was done yet 932cdf0e10cSrcweir if(bDoProcessRecursively) 933cdf0e10cSrcweir { 934cdf0e10cSrcweir // printer output 935cdf0e10cSrcweir try 936cdf0e10cSrcweir { 937cdf0e10cSrcweir // remember old graphics and create new 938cdf0e10cSrcweir uno::Reference< awt::XView > xControlView(rXControl, uno::UNO_QUERY_THROW); 939cdf0e10cSrcweir const uno::Reference< awt::XGraphics > xOriginalGraphics(xControlView->getGraphics()); 940cdf0e10cSrcweir const uno::Reference< awt::XGraphics > xNewGraphics(mpOutputDevice->CreateUnoGraphics()); 941cdf0e10cSrcweir 942cdf0e10cSrcweir if(xNewGraphics.is()) 943cdf0e10cSrcweir { 944cdf0e10cSrcweir // link graphics and view 945cdf0e10cSrcweir xControlView->setGraphics(xNewGraphics); 946cdf0e10cSrcweir 947cdf0e10cSrcweir // get position 948cdf0e10cSrcweir const basegfx::B2DHomMatrix aObjectToDiscrete(getViewInformation2D().getObjectToViewTransformation() * rControlPrimitive.getTransform()); 949cdf0e10cSrcweir const basegfx::B2DPoint aTopLeftDiscrete(aObjectToDiscrete * basegfx::B2DPoint(0.0, 0.0)); 950cdf0e10cSrcweir 951cdf0e10cSrcweir // draw it 952cdf0e10cSrcweir xControlView->draw(basegfx::fround(aTopLeftDiscrete.getX()), basegfx::fround(aTopLeftDiscrete.getY())); 953cdf0e10cSrcweir bDoProcessRecursively = false; 954cdf0e10cSrcweir 955cdf0e10cSrcweir // restore original graphics 956cdf0e10cSrcweir xControlView->setGraphics(xOriginalGraphics); 957cdf0e10cSrcweir } 958cdf0e10cSrcweir } 959cdf0e10cSrcweir catch( const uno::Exception& ) 960cdf0e10cSrcweir { 961cdf0e10cSrcweir OSL_ENSURE(false, "VclMetafileProcessor2D: Printing of Control failed, caught an exception!"); 962cdf0e10cSrcweir } 963cdf0e10cSrcweir } 964cdf0e10cSrcweir 965cdf0e10cSrcweir // process recursively if not done yet to export as decomposition (bitmap) 966cdf0e10cSrcweir if(bDoProcessRecursively) 967cdf0e10cSrcweir { 968cdf0e10cSrcweir process(rControlPrimitive.get2DDecomposition(getViewInformation2D())); 969cdf0e10cSrcweir } 970cdf0e10cSrcweir } 971cdf0e10cSrcweir 972cdf0e10cSrcweir break; 973cdf0e10cSrcweir } 974cdf0e10cSrcweir case PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D : 975cdf0e10cSrcweir { 976cdf0e10cSrcweir // support for FIELD_SEQ_BEGIN, FIELD_SEQ_END and URL. It wraps text primitives (but is not limited to) 977cdf0e10cSrcweir // thus do the MetafileAction embedding stuff but just handle recursively. 978cdf0e10cSrcweir const primitive2d::TextHierarchyFieldPrimitive2D& rFieldPrimitive = static_cast< const primitive2d::TextHierarchyFieldPrimitive2D& >(rCandidate); 979cdf0e10cSrcweir static const ByteString aCommentStringCommon("FIELD_SEQ_BEGIN"); 980cdf0e10cSrcweir static const ByteString aCommentStringPage("FIELD_SEQ_BEGIN;PageField"); 981cdf0e10cSrcweir static const ByteString aCommentStringEnd("FIELD_SEQ_END"); 982cdf0e10cSrcweir 983cdf0e10cSrcweir switch(rFieldPrimitive.getType()) 984cdf0e10cSrcweir { 985cdf0e10cSrcweir default : // case drawinglayer::primitive2d::FIELD_TYPE_COMMON : 986cdf0e10cSrcweir { 987cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon)); 988cdf0e10cSrcweir break; 989cdf0e10cSrcweir } 990cdf0e10cSrcweir case drawinglayer::primitive2d::FIELD_TYPE_PAGE : 991cdf0e10cSrcweir { 992cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringPage)); 993cdf0e10cSrcweir break; 994cdf0e10cSrcweir } 995cdf0e10cSrcweir case drawinglayer::primitive2d::FIELD_TYPE_URL : 996cdf0e10cSrcweir { 997cdf0e10cSrcweir const rtl::OUString& rURL = rFieldPrimitive.getString(); 998cdf0e10cSrcweir const String aOldString(rURL); 999cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast< const sal_uInt8* >(aOldString.GetBuffer()), 2 * aOldString.Len())); 1000cdf0e10cSrcweir break; 1001cdf0e10cSrcweir } 1002cdf0e10cSrcweir } 1003cdf0e10cSrcweir 1004cdf0e10cSrcweir // process recursively 1005cdf0e10cSrcweir const primitive2d::Primitive2DSequence rContent = rFieldPrimitive.get2DDecomposition(getViewInformation2D()); 1006cdf0e10cSrcweir process(rContent); 1007cdf0e10cSrcweir 1008cdf0e10cSrcweir // for the end comment the type is not relevant yet, they are all the same. Just add. 1009cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringEnd)); 1010cdf0e10cSrcweir 1011cdf0e10cSrcweir if(mpPDFExtOutDevData && drawinglayer::primitive2d::FIELD_TYPE_URL == rFieldPrimitive.getType()) 1012cdf0e10cSrcweir { 1013cdf0e10cSrcweir // emulate data handling from ImpEditEngine::Paint 1014cdf0e10cSrcweir const basegfx::B2DRange aViewRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D())); 1015cdf0e10cSrcweir const Rectangle aRectLogic( 1016cdf0e10cSrcweir (sal_Int32)floor(aViewRange.getMinX()), (sal_Int32)floor(aViewRange.getMinY()), 1017cdf0e10cSrcweir (sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY())); 1018cdf0e10cSrcweir vcl::PDFExtOutDevBookmarkEntry aBookmark; 1019cdf0e10cSrcweir aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic); 1020cdf0e10cSrcweir aBookmark.aBookmark = rFieldPrimitive.getString(); 1021cdf0e10cSrcweir std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = mpPDFExtOutDevData->GetBookmarks(); 1022cdf0e10cSrcweir rBookmarks.push_back( aBookmark ); 1023cdf0e10cSrcweir } 1024cdf0e10cSrcweir 1025cdf0e10cSrcweir break; 1026cdf0e10cSrcweir } 1027cdf0e10cSrcweir case PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D : 1028cdf0e10cSrcweir { 1029cdf0e10cSrcweir const primitive2d::TextHierarchyLinePrimitive2D& rLinePrimitive = static_cast< const primitive2d::TextHierarchyLinePrimitive2D& >(rCandidate); 1030cdf0e10cSrcweir static const ByteString aCommentString("XTEXT_EOL"); 1031cdf0e10cSrcweir 1032cdf0e10cSrcweir // process recursively and add MetaFile comment 1033cdf0e10cSrcweir process(rLinePrimitive.get2DDecomposition(getViewInformation2D())); 1034cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentString)); 1035cdf0e10cSrcweir 1036cdf0e10cSrcweir break; 1037cdf0e10cSrcweir } 1038cdf0e10cSrcweir case PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D : 1039cdf0e10cSrcweir { 1040cdf0e10cSrcweir // in Outliner::PaintBullet(), a MetafileComment for bullets is added, too. The 1041cdf0e10cSrcweir // "XTEXT_EOC" is used, use here, too. 1042cdf0e10cSrcweir const primitive2d::TextHierarchyBulletPrimitive2D& rBulletPrimitive = static_cast< const primitive2d::TextHierarchyBulletPrimitive2D& >(rCandidate); 1043cdf0e10cSrcweir static const ByteString aCommentString("XTEXT_EOC"); 1044cdf0e10cSrcweir 1045cdf0e10cSrcweir // process recursively and add MetaFile comment 1046cdf0e10cSrcweir process(rBulletPrimitive.get2DDecomposition(getViewInformation2D())); 1047cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentString)); 1048cdf0e10cSrcweir 1049cdf0e10cSrcweir break; 1050cdf0e10cSrcweir } 1051cdf0e10cSrcweir case PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D : 1052cdf0e10cSrcweir { 1053cdf0e10cSrcweir const primitive2d::TextHierarchyParagraphPrimitive2D& rParagraphPrimitive = static_cast< const primitive2d::TextHierarchyParagraphPrimitive2D& >(rCandidate); 1054cdf0e10cSrcweir static const ByteString aCommentString("XTEXT_EOP"); 1055cdf0e10cSrcweir 1056cdf0e10cSrcweir if(mpPDFExtOutDevData) 1057cdf0e10cSrcweir { 1058cdf0e10cSrcweir // emulate data handling from ImpEditEngine::Paint 1059cdf0e10cSrcweir mpPDFExtOutDevData->BeginStructureElement( vcl::PDFWriter::Paragraph ); 1060cdf0e10cSrcweir } 1061cdf0e10cSrcweir 1062cdf0e10cSrcweir // process recursively and add MetaFile comment 1063cdf0e10cSrcweir process(rParagraphPrimitive.get2DDecomposition(getViewInformation2D())); 1064cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentString)); 1065cdf0e10cSrcweir 1066cdf0e10cSrcweir if(mpPDFExtOutDevData) 1067cdf0e10cSrcweir { 1068cdf0e10cSrcweir // emulate data handling from ImpEditEngine::Paint 1069cdf0e10cSrcweir mpPDFExtOutDevData->EndStructureElement(); 1070cdf0e10cSrcweir } 1071cdf0e10cSrcweir 1072cdf0e10cSrcweir break; 1073cdf0e10cSrcweir } 1074cdf0e10cSrcweir case PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D : 1075cdf0e10cSrcweir { 1076cdf0e10cSrcweir const primitive2d::TextHierarchyBlockPrimitive2D& rBlockPrimitive = static_cast< const primitive2d::TextHierarchyBlockPrimitive2D& >(rCandidate); 1077cdf0e10cSrcweir static const ByteString aCommentStringA("XTEXT_PAINTSHAPE_BEGIN"); 1078cdf0e10cSrcweir static const ByteString aCommentStringB("XTEXT_PAINTSHAPE_END"); 1079cdf0e10cSrcweir 1080cdf0e10cSrcweir // add MetaFile comment, process recursively and add MetaFile comment 1081cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA)); 1082cdf0e10cSrcweir process(rBlockPrimitive.get2DDecomposition(getViewInformation2D())); 1083cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB)); 1084cdf0e10cSrcweir 1085cdf0e10cSrcweir break; 1086cdf0e10cSrcweir } 1087cdf0e10cSrcweir case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D : 1088cdf0e10cSrcweir case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D : 1089cdf0e10cSrcweir { 1090cdf0e10cSrcweir // for supporting TEXT_ MetaFile actions there is more to do here; get the candidate 1091cdf0e10cSrcweir const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate = static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate); 1092cdf0e10cSrcweir // const primitive2d::TextDecoratedPortionPrimitive2D* pTextDecoratedCandidate = dynamic_cast< const primitive2d::TextDecoratedPortionPrimitive2D* >(&rCandidate); 1093cdf0e10cSrcweir 1094cdf0e10cSrcweir // Adapt evtl. used special DrawMode 1095cdf0e10cSrcweir const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode()); 1096cdf0e10cSrcweir adaptTextToFillDrawMode(); 1097cdf0e10cSrcweir 1098cdf0e10cSrcweir // directdraw of text simple portion; use default processing 1099cdf0e10cSrcweir RenderTextSimpleOrDecoratedPortionPrimitive2D(rTextCandidate); 1100cdf0e10cSrcweir 1101cdf0e10cSrcweir // restore DrawMode 1102cdf0e10cSrcweir mpOutputDevice->SetDrawMode(nOriginalDrawMode); 1103cdf0e10cSrcweir 1104cdf0e10cSrcweir // #i101169# if(pTextDecoratedCandidate) 1105cdf0e10cSrcweir { 1106cdf0e10cSrcweir // support for TEXT_ MetaFile actions only for decorated texts 1107cdf0e10cSrcweir if(!mxBreakIterator.is()) 1108cdf0e10cSrcweir { 1109cdf0e10cSrcweir uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory()); 1110cdf0e10cSrcweir mxBreakIterator.set(xMSF->createInstance(rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator")), uno::UNO_QUERY); 1111cdf0e10cSrcweir } 1112cdf0e10cSrcweir 1113cdf0e10cSrcweir if(mxBreakIterator.is()) 1114cdf0e10cSrcweir { 1115cdf0e10cSrcweir const rtl::OUString& rTxt = rTextCandidate.getText(); 1116cdf0e10cSrcweir const sal_Int32 nTextLength(rTextCandidate.getTextLength()); // rTxt.getLength()); 1117cdf0e10cSrcweir 1118cdf0e10cSrcweir if(nTextLength) 1119cdf0e10cSrcweir { 1120cdf0e10cSrcweir const ::com::sun::star::lang::Locale& rLocale = rTextCandidate.getLocale(); 1121cdf0e10cSrcweir const sal_Int32 nTextPosition(rTextCandidate.getTextPosition()); 1122cdf0e10cSrcweir 1123cdf0e10cSrcweir sal_Int32 nDone; 1124cdf0e10cSrcweir sal_Int32 nNextCellBreak(mxBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone)); 1125cdf0e10cSrcweir ::com::sun::star::i18n::Boundary nNextWordBoundary(mxBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True)); 1126cdf0e10cSrcweir sal_Int32 nNextSentenceBreak(mxBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale)); 1127cdf0e10cSrcweir static const ByteString aCommentStringA("XTEXT_EOC"); 1128cdf0e10cSrcweir static const ByteString aCommentStringB("XTEXT_EOW"); 1129cdf0e10cSrcweir static const ByteString aCommentStringC("XTEXT_EOS"); 1130cdf0e10cSrcweir 1131cdf0e10cSrcweir for(sal_Int32 i(nTextPosition); i < nTextPosition + nTextLength; i++) 1132cdf0e10cSrcweir { 1133cdf0e10cSrcweir // create the entries for the respective break positions 1134cdf0e10cSrcweir if(i == nNextCellBreak) 1135cdf0e10cSrcweir { 1136cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA, i - nTextPosition)); 1137cdf0e10cSrcweir nNextCellBreak = mxBreakIterator->nextCharacters(rTxt, i, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone); 1138cdf0e10cSrcweir } 1139cdf0e10cSrcweir if(i == nNextWordBoundary.endPos) 1140cdf0e10cSrcweir { 1141cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB, i - nTextPosition)); 1142cdf0e10cSrcweir nNextWordBoundary = mxBreakIterator->getWordBoundary(rTxt, i + 1, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True); 1143cdf0e10cSrcweir } 1144cdf0e10cSrcweir if(i == nNextSentenceBreak) 1145cdf0e10cSrcweir { 1146cdf0e10cSrcweir mpMetaFile->AddAction(new MetaCommentAction(aCommentStringC, i - nTextPosition)); 1147cdf0e10cSrcweir nNextSentenceBreak = mxBreakIterator->endOfSentence(rTxt, i + 1, rLocale); 1148cdf0e10cSrcweir } 1149cdf0e10cSrcweir } 1150cdf0e10cSrcweir } 1151cdf0e10cSrcweir } 1152cdf0e10cSrcweir } 1153cdf0e10cSrcweir 1154cdf0e10cSrcweir break; 1155cdf0e10cSrcweir } 1156cdf0e10cSrcweir case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D : 1157cdf0e10cSrcweir { 1158cdf0e10cSrcweir const primitive2d::PolygonHairlinePrimitive2D& rHairlinePrimitive = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate); 1159cdf0e10cSrcweir const basegfx::B2DPolygon& rBasePolygon = rHairlinePrimitive.getB2DPolygon(); 1160cdf0e10cSrcweir 1161cdf0e10cSrcweir if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1)) 1162cdf0e10cSrcweir { 1163cdf0e10cSrcweir // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 1164cdf0e10cSrcweir // per polygon. If there are more, split the polygon in half and call recursively 1165cdf0e10cSrcweir basegfx::B2DPolygon aLeft, aRight; 1166cdf0e10cSrcweir splitLinePolygon(rBasePolygon, aLeft, aRight); 1167cdf0e10cSrcweir const primitive2d::PolygonHairlinePrimitive2D aPLeft(aLeft, rHairlinePrimitive.getBColor()); 1168cdf0e10cSrcweir const primitive2d::PolygonHairlinePrimitive2D aPRight(aRight, rHairlinePrimitive.getBColor()); 1169cdf0e10cSrcweir 1170cdf0e10cSrcweir processBasePrimitive2D(aPLeft); 1171cdf0e10cSrcweir processBasePrimitive2D(aPRight); 1172cdf0e10cSrcweir } 1173cdf0e10cSrcweir else 1174cdf0e10cSrcweir { 1175cdf0e10cSrcweir // direct draw of hairline; use default processing 1176cdf0e10cSrcweir // support SvtGraphicStroke MetaCommentAction 1177cdf0e10cSrcweir const basegfx::BColor aLineColor(maBColorModifierStack.getModifiedColor(rHairlinePrimitive.getBColor())); 11784665f8d3SArmin Le Grand SvtGraphicStroke* pSvtGraphicStroke = 0; 11794665f8d3SArmin Le Grand 11804665f8d3SArmin Le Grand // #121267# Not needed, does not give better quality compared with 11814665f8d3SArmin Le Grand // the META_POLYPOLYGON_ACTION written by RenderPolygonHairlinePrimitive2D 11824665f8d3SArmin Le Grand // below 11834665f8d3SArmin Le Grand bool bSupportSvtGraphicStroke(false); 11844665f8d3SArmin Le Grand 11854665f8d3SArmin Le Grand if(bSupportSvtGraphicStroke) 11864665f8d3SArmin Le Grand { 11874665f8d3SArmin Le Grand pSvtGraphicStroke = impTryToCreateSvtGraphicStroke( 11884665f8d3SArmin Le Grand rHairlinePrimitive.getB2DPolygon(), 11894665f8d3SArmin Le Grand &aLineColor, 11904665f8d3SArmin Le Grand 0, 0, 0, 0); 11914665f8d3SArmin Le Grand 11924665f8d3SArmin Le Grand impStartSvtGraphicStroke(pSvtGraphicStroke); 11934665f8d3SArmin Le Grand } 1194cdf0e10cSrcweir 1195cdf0e10cSrcweir RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate), false); 11964665f8d3SArmin Le Grand 11974665f8d3SArmin Le Grand if(bSupportSvtGraphicStroke) 11984665f8d3SArmin Le Grand { 11994665f8d3SArmin Le Grand impEndSvtGraphicStroke(pSvtGraphicStroke); 12004665f8d3SArmin Le Grand } 1201cdf0e10cSrcweir } 1202cdf0e10cSrcweir break; 1203cdf0e10cSrcweir } 1204cdf0e10cSrcweir case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D : 1205cdf0e10cSrcweir { 1206cdf0e10cSrcweir const primitive2d::PolygonStrokePrimitive2D& rStrokePrimitive = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate); 1207cdf0e10cSrcweir const basegfx::B2DPolygon& rBasePolygon = rStrokePrimitive.getB2DPolygon(); 1208cdf0e10cSrcweir 1209cdf0e10cSrcweir if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1)) 1210cdf0e10cSrcweir { 1211cdf0e10cSrcweir // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 1212cdf0e10cSrcweir // per polygon. If there are more, split the polygon in half and call recursively 1213cdf0e10cSrcweir basegfx::B2DPolygon aLeft, aRight; 1214cdf0e10cSrcweir splitLinePolygon(rBasePolygon, aLeft, aRight); 1215cdf0e10cSrcweir const primitive2d::PolygonStrokePrimitive2D aPLeft( 1216cdf0e10cSrcweir aLeft, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute()); 1217cdf0e10cSrcweir const primitive2d::PolygonStrokePrimitive2D aPRight( 1218cdf0e10cSrcweir aRight, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute()); 1219cdf0e10cSrcweir 1220cdf0e10cSrcweir processBasePrimitive2D(aPLeft); 1221cdf0e10cSrcweir processBasePrimitive2D(aPRight); 1222cdf0e10cSrcweir } 1223cdf0e10cSrcweir else 1224cdf0e10cSrcweir { 1225cdf0e10cSrcweir // support SvtGraphicStroke MetaCommentAction 1226cdf0e10cSrcweir SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke( 1227cdf0e10cSrcweir rBasePolygon, 0, 1228cdf0e10cSrcweir &rStrokePrimitive.getLineAttribute(), 1229cdf0e10cSrcweir &rStrokePrimitive.getStrokeAttribute(), 1230cdf0e10cSrcweir 0, 0); 1231cdf0e10cSrcweir 1232cdf0e10cSrcweir impStartSvtGraphicStroke(pSvtGraphicStroke); 1233cdf0e10cSrcweir const attribute::LineAttribute& rLine = rStrokePrimitive.getLineAttribute(); 1234cdf0e10cSrcweir 1235cdf0e10cSrcweir // create MetaPolyLineActions, but without LINE_DASH 1236cdf0e10cSrcweir if(basegfx::fTools::more(rLine.getWidth(), 0.0)) 1237cdf0e10cSrcweir { 1238cdf0e10cSrcweir const attribute::StrokeAttribute& rStroke = rStrokePrimitive.getStrokeAttribute(); 1239cdf0e10cSrcweir basegfx::B2DPolyPolygon aHairLinePolyPolygon; 1240cdf0e10cSrcweir 1241cdf0e10cSrcweir if(0.0 == rStroke.getFullDotDashLen()) 1242cdf0e10cSrcweir { 1243cdf0e10cSrcweir aHairLinePolyPolygon.append(rBasePolygon); 1244cdf0e10cSrcweir } 1245cdf0e10cSrcweir else 1246cdf0e10cSrcweir { 1247cdf0e10cSrcweir basegfx::tools::applyLineDashing( 1248cdf0e10cSrcweir rBasePolygon, rStroke.getDotDashArray(), 1249cdf0e10cSrcweir &aHairLinePolyPolygon, 0, rStroke.getFullDotDashLen()); 1250cdf0e10cSrcweir } 1251cdf0e10cSrcweir 1252cdf0e10cSrcweir const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLine.getColor())); 1253cdf0e10cSrcweir mpOutputDevice->SetLineColor(Color(aHairlineColor)); 1254cdf0e10cSrcweir mpOutputDevice->SetFillColor(); 1255cdf0e10cSrcweir aHairLinePolyPolygon.transform(maCurrentTransformation); 1256cdf0e10cSrcweir 1257cdf0e10cSrcweir // #i113922# LineWidth needs to be transformed, too 1258cdf0e10cSrcweir const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation * basegfx::B2DVector(rLine.getWidth(), 0.0)); 1259cdf0e10cSrcweir const double fDiscreteLineWidth(aDiscreteUnit.getLength()); 1260cdf0e10cSrcweir 1261cdf0e10cSrcweir LineInfo aLineInfo(LINE_SOLID, basegfx::fround(fDiscreteLineWidth)); 1262cdf0e10cSrcweir aLineInfo.SetLineJoin(rLine.getLineJoin()); 12635aaf853bSArmin Le Grand aLineInfo.SetLineCap(rLine.getLineCap()); 1264cdf0e10cSrcweir 1265cdf0e10cSrcweir for(sal_uInt32 a(0); a < aHairLinePolyPolygon.count(); a++) 1266cdf0e10cSrcweir { 1267cdf0e10cSrcweir const basegfx::B2DPolygon aCandidate(aHairLinePolyPolygon.getB2DPolygon(a)); 1268cdf0e10cSrcweir 1269cdf0e10cSrcweir if(aCandidate.count() > 1) 1270cdf0e10cSrcweir { 1271cdf0e10cSrcweir const Polygon aToolsPolygon(aCandidate); 1272cdf0e10cSrcweir 1273cdf0e10cSrcweir mpMetaFile->AddAction(new MetaPolyLineAction(aToolsPolygon, aLineInfo)); 1274cdf0e10cSrcweir } 1275cdf0e10cSrcweir } 1276cdf0e10cSrcweir } 1277cdf0e10cSrcweir else 1278cdf0e10cSrcweir { 1279cdf0e10cSrcweir process(rCandidate.get2DDecomposition(getViewInformation2D())); 1280cdf0e10cSrcweir } 1281cdf0e10cSrcweir 1282cdf0e10cSrcweir impEndSvtGraphicStroke(pSvtGraphicStroke); 1283cdf0e10cSrcweir } 1284cdf0e10cSrcweir 1285cdf0e10cSrcweir break; 1286cdf0e10cSrcweir } 1287cdf0e10cSrcweir case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D : 1288cdf0e10cSrcweir { 1289cdf0e10cSrcweir const primitive2d::PolygonStrokeArrowPrimitive2D& rStrokeArrowPrimitive = static_cast< const primitive2d::PolygonStrokeArrowPrimitive2D& >(rCandidate); 1290cdf0e10cSrcweir const basegfx::B2DPolygon& rBasePolygon = rStrokeArrowPrimitive.getB2DPolygon(); 1291cdf0e10cSrcweir 1292cdf0e10cSrcweir if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1)) 1293cdf0e10cSrcweir { 1294cdf0e10cSrcweir // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 1295cdf0e10cSrcweir // per polygon. If there are more, split the polygon in half and call recursively 1296cdf0e10cSrcweir basegfx::B2DPolygon aLeft, aRight; 1297cdf0e10cSrcweir splitLinePolygon(rBasePolygon, aLeft, aRight); 1298cdf0e10cSrcweir const attribute::LineStartEndAttribute aEmpty; 1299cdf0e10cSrcweir const primitive2d::PolygonStrokeArrowPrimitive2D aPLeft( 1300cdf0e10cSrcweir aLeft, 1301cdf0e10cSrcweir rStrokeArrowPrimitive.getLineAttribute(), 1302cdf0e10cSrcweir rStrokeArrowPrimitive.getStrokeAttribute(), 1303cdf0e10cSrcweir rStrokeArrowPrimitive.getStart(), 1304cdf0e10cSrcweir aEmpty); 1305cdf0e10cSrcweir const primitive2d::PolygonStrokeArrowPrimitive2D aPRight( 1306cdf0e10cSrcweir aRight, 1307cdf0e10cSrcweir rStrokeArrowPrimitive.getLineAttribute(), 1308cdf0e10cSrcweir rStrokeArrowPrimitive.getStrokeAttribute(), 1309cdf0e10cSrcweir aEmpty, 1310cdf0e10cSrcweir rStrokeArrowPrimitive.getEnd()); 1311cdf0e10cSrcweir 1312cdf0e10cSrcweir processBasePrimitive2D(aPLeft); 1313cdf0e10cSrcweir processBasePrimitive2D(aPRight); 1314cdf0e10cSrcweir } 1315cdf0e10cSrcweir else 1316cdf0e10cSrcweir { 1317cdf0e10cSrcweir // support SvtGraphicStroke MetaCommentAction 1318cdf0e10cSrcweir SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke( 1319cdf0e10cSrcweir rBasePolygon, 0, 1320cdf0e10cSrcweir &rStrokeArrowPrimitive.getLineAttribute(), 1321cdf0e10cSrcweir &rStrokeArrowPrimitive.getStrokeAttribute(), 1322cdf0e10cSrcweir &rStrokeArrowPrimitive.getStart(), 1323cdf0e10cSrcweir &rStrokeArrowPrimitive.getEnd()); 1324cdf0e10cSrcweir 132578137d97SArmin Le Grand // write LineGeometry start marker 1326cdf0e10cSrcweir impStartSvtGraphicStroke(pSvtGraphicStroke); 132778137d97SArmin Le Grand 132878137d97SArmin Le Grand // #116162# When B&W is set as DrawMode, DRAWMODE_WHITEFILL is used 132978137d97SArmin Le Grand // to let all fills be just white; for lines DRAWMODE_BLACKLINE is used 133078137d97SArmin Le Grand // so all line geometry is supposed to get black. Since in the in-between 133178137d97SArmin Le Grand // stages of line geometry drawing filled polygons are used (e.g. line 133278137d97SArmin Le Grand // start/ends) it is necessary to change these drawmodes to preserve 133378137d97SArmin Le Grand // that lines shall be black; thus change DRAWMODE_WHITEFILL to 133478137d97SArmin Le Grand // DRAWMODE_BLACKFILL during line geometry processing to have line geometry 133578137d97SArmin Le Grand // parts filled black. 133678137d97SArmin Le Grand const sal_uLong nOldDrawMode(mpOutputDevice->GetDrawMode()); 133778137d97SArmin Le Grand const bool bDrawmodeChange(nOldDrawMode & DRAWMODE_WHITEFILL && mnSvtGraphicStrokeCount); 133878137d97SArmin Le Grand 133978137d97SArmin Le Grand if(bDrawmodeChange) 134078137d97SArmin Le Grand { 134178137d97SArmin Le Grand mpOutputDevice->SetDrawMode((nOldDrawMode & ~DRAWMODE_WHITEFILL) | DRAWMODE_BLACKFILL); 134278137d97SArmin Le Grand } 134378137d97SArmin Le Grand 134478137d97SArmin Le Grand // process sub-line geometry (evtl. filled PolyPolygons) 134578137d97SArmin Le Grand process(rCandidate.get2DDecomposition(getViewInformation2D())); 134678137d97SArmin Le Grand 134778137d97SArmin Le Grand if(bDrawmodeChange) 134878137d97SArmin Le Grand { 134978137d97SArmin Le Grand mpOutputDevice->SetDrawMode(nOldDrawMode); 135078137d97SArmin Le Grand } 135178137d97SArmin Le Grand 135278137d97SArmin Le Grand // write LineGeometry end marker 135378137d97SArmin Le Grand impEndSvtGraphicStroke(pSvtGraphicStroke); 1354cdf0e10cSrcweir } 1355cdf0e10cSrcweir 1356cdf0e10cSrcweir break; 1357cdf0e10cSrcweir } 1358cdf0e10cSrcweir case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D : 1359cdf0e10cSrcweir { 1360cf95e506SArmin Le Grand // direct draw of transformed BitmapEx primitive; use default processing, but without 1361cf95e506SArmin Le Grand // former testing if graphic content is inside discrete local viewport; this is not 1362cf95e506SArmin Le Grand // setup for metafile targets (metafile renderer tries to render in logic coordinates, 1363cf95e506SArmin Le Grand // the mapping is kept to the OutputDevice for better Metafile recording) 1364cdf0e10cSrcweir RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate)); 1365cdf0e10cSrcweir break; 1366cdf0e10cSrcweir } 1367035a2f44SArmin Le Grand case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D : 1368cdf0e10cSrcweir { 1369035a2f44SArmin Le Grand // need to handle PolyPolygonGraphicPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END 1370035a2f44SArmin Le Grand const primitive2d::PolyPolygonGraphicPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonGraphicPrimitive2D& >(rCandidate); 1371cdf0e10cSrcweir basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon()); 1372cdf0e10cSrcweir 1373cdf0e10cSrcweir if(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) 1374cdf0e10cSrcweir { 1375cdf0e10cSrcweir // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 1376cdf0e10cSrcweir // per polygon. If there are more use the splitted polygon and call recursively 1377035a2f44SArmin Le Grand const primitive2d::PolyPolygonGraphicPrimitive2D aSplitted( 1378cdf0e10cSrcweir aLocalPolyPolygon, 1379035a2f44SArmin Le Grand rBitmapCandidate.getFillGraphic()); 1380cdf0e10cSrcweir 1381cdf0e10cSrcweir processBasePrimitive2D(aSplitted); 1382cdf0e10cSrcweir } 1383cdf0e10cSrcweir else 1384cdf0e10cSrcweir { 1385cdf0e10cSrcweir SvtGraphicFill* pSvtGraphicFill = 0; 1386cdf0e10cSrcweir 1387cdf0e10cSrcweir if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count()) 1388cdf0e10cSrcweir { 1389035a2f44SArmin Le Grand // #121194# Changed implementation and checked usages fo convert to metafile, 1390035a2f44SArmin Le Grand // presentation start (uses SvtGraphicFill) and printing. 1391cdf0e10cSrcweir 1392035a2f44SArmin Le Grand // calculate transformation. Get real object size, all values in FillGraphicAttribute 1393035a2f44SArmin Le Grand // are relative to the unified object 1394035a2f44SArmin Le Grand aLocalPolyPolygon.transform(maCurrentTransformation); 1395035a2f44SArmin Le Grand const basegfx::B2DVector aOutlineSize(aLocalPolyPolygon.getB2DRange().getRange()); 1396cdf0e10cSrcweir 1397cdf0e10cSrcweir // the scaling needs scale from pixel to logic coordinate system 1398035a2f44SArmin Le Grand const attribute::FillGraphicAttribute& rFillGraphicAttribute = rBitmapCandidate.getFillGraphic(); 1399035a2f44SArmin Le Grand const Size aBmpSizePixel(rFillGraphicAttribute.getGraphic().GetSizePixel()); 1400035a2f44SArmin Le Grand 1401035a2f44SArmin Le Grand // setup transformation like in impgrfll. Multiply with aOutlineSize 1402035a2f44SArmin Le Grand // to get from unit coordinates in rFillGraphicAttribute.getGraphicRange() 1403035a2f44SArmin Le Grand // to object coordinates with object's top left being at (0,0). Divide 1404035a2f44SArmin Le Grand // by pixel size so that scale from pixel to logic will work in SvtGraphicFill. 1405035a2f44SArmin Le Grand const basegfx::B2DVector aTransformScale( 1406035a2f44SArmin Le Grand rFillGraphicAttribute.getGraphicRange().getRange() / 1407035a2f44SArmin Le Grand basegfx::B2DVector( 1408035a2f44SArmin Le Grand std::max(1.0, double(aBmpSizePixel.Width())), 1409035a2f44SArmin Le Grand std::max(1.0, double(aBmpSizePixel.Height()))) * 1410035a2f44SArmin Le Grand aOutlineSize); 1411035a2f44SArmin Le Grand const basegfx::B2DPoint aTransformPosition( 1412035a2f44SArmin Le Grand rFillGraphicAttribute.getGraphicRange().getMinimum() * aOutlineSize); 1413cdf0e10cSrcweir 1414cdf0e10cSrcweir // setup transformation like in impgrfll 1415cdf0e10cSrcweir SvtGraphicFill::Transform aTransform; 1416cdf0e10cSrcweir 1417cdf0e10cSrcweir // scale values are divided by bitmap pixel sizes 1418035a2f44SArmin Le Grand aTransform.matrix[0] = aTransformScale.getX(); 1419035a2f44SArmin Le Grand aTransform.matrix[4] = aTransformScale.getY(); 1420cdf0e10cSrcweir 1421cdf0e10cSrcweir // translates are absolute 1422035a2f44SArmin Le Grand aTransform.matrix[2] = aTransformPosition.getX(); 1423035a2f44SArmin Le Grand aTransform.matrix[5] = aTransformPosition.getY(); 1424cdf0e10cSrcweir 1425035a2f44SArmin Le Grand pSvtGraphicFill = new SvtGraphicFill( 1426cdf0e10cSrcweir PolyPolygon(aLocalPolyPolygon), 1427cdf0e10cSrcweir Color(), 1428cdf0e10cSrcweir 0.0, 1429cdf0e10cSrcweir SvtGraphicFill::fillEvenOdd, 1430cdf0e10cSrcweir SvtGraphicFill::fillTexture, 1431cdf0e10cSrcweir aTransform, 1432035a2f44SArmin Le Grand rFillGraphicAttribute.getTiling(), 1433cdf0e10cSrcweir SvtGraphicFill::hatchSingle, 1434cdf0e10cSrcweir Color(), 1435cdf0e10cSrcweir SvtGraphicFill::gradientLinear, 1436cdf0e10cSrcweir Color(), 1437cdf0e10cSrcweir Color(), 1438cdf0e10cSrcweir 0, 1439035a2f44SArmin Le Grand rFillGraphicAttribute.getGraphic()); 1440cdf0e10cSrcweir } 1441cdf0e10cSrcweir 1442cdf0e10cSrcweir // Do use decomposition; encapsulate with SvtGraphicFill 1443cdf0e10cSrcweir impStartSvtGraphicFill(pSvtGraphicFill); 1444cdf0e10cSrcweir process(rCandidate.get2DDecomposition(getViewInformation2D())); 1445cdf0e10cSrcweir impEndSvtGraphicFill(pSvtGraphicFill); 1446cdf0e10cSrcweir } 1447cdf0e10cSrcweir 1448cdf0e10cSrcweir break; 1449cdf0e10cSrcweir } 145064b14621SArmin Le Grand case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D : 145164b14621SArmin Le Grand { 145264b14621SArmin Le Grand // need to handle PolyPolygonHatchPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END 145364b14621SArmin Le Grand const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate); 145464b14621SArmin Le Grand const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch(); 145564b14621SArmin Le Grand basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon()); 145664b14621SArmin Le Grand 145764b14621SArmin Le Grand if(aLocalPolyPolygon.getB2DRange() != rHatchCandidate.getDefinitionRange()) 145864b14621SArmin Le Grand { 145964b14621SArmin Le Grand // the range which defines the hatch is different from the range of the 146064b14621SArmin Le Grand // geometry (used for writer frames). This cannot be done calling vcl, thus use 146164b14621SArmin Le Grand // decomposition here 146264b14621SArmin Le Grand process(rCandidate.get2DDecomposition(getViewInformation2D())); 146364b14621SArmin Le Grand break; 146464b14621SArmin Le Grand } 1465cdf0e10cSrcweir 1466cdf0e10cSrcweir // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 1467cdf0e10cSrcweir // per polygon. Split polygon until there are less than that 1468cdf0e10cSrcweir while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) 1469cdf0e10cSrcweir ; 1470cdf0e10cSrcweir 147164b14621SArmin Le Grand if(rFillHatchAttribute.isFillBackground()) 147264b14621SArmin Le Grand { 147364b14621SArmin Le Grand // with fixing #i111954# (see below) the possible background 147464b14621SArmin Le Grand // fill of a hatched object was lost.Generate a background fill 147564b14621SArmin Le Grand // primitive and render it 147664b14621SArmin Le Grand const primitive2d::Primitive2DReference xBackground( 147764b14621SArmin Le Grand new primitive2d::PolyPolygonColorPrimitive2D( 147864b14621SArmin Le Grand aLocalPolyPolygon, 147964b14621SArmin Le Grand rHatchCandidate.getBackgroundColor())); 148064b14621SArmin Le Grand 148164b14621SArmin Le Grand process(primitive2d::Primitive2DSequence(&xBackground, 1)); 148264b14621SArmin Le Grand } 1483cdf0e10cSrcweir 1484cdf0e10cSrcweir SvtGraphicFill* pSvtGraphicFill = 0; 148564b14621SArmin Le Grand aLocalPolyPolygon.transform(maCurrentTransformation); 1486cdf0e10cSrcweir 148764b14621SArmin Le Grand if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count()) 148864b14621SArmin Le Grand { 148964b14621SArmin Le Grand // re-create a VCL hatch as base data 149064b14621SArmin Le Grand SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle); 1491cdf0e10cSrcweir 149264b14621SArmin Le Grand switch(rFillHatchAttribute.getStyle()) 149364b14621SArmin Le Grand { 149464b14621SArmin Le Grand default: // attribute::HATCHSTYLE_SINGLE : 149564b14621SArmin Le Grand { 149664b14621SArmin Le Grand eHatch = SvtGraphicFill::hatchSingle; 149764b14621SArmin Le Grand break; 149864b14621SArmin Le Grand } 149964b14621SArmin Le Grand case attribute::HATCHSTYLE_DOUBLE : 150064b14621SArmin Le Grand { 150164b14621SArmin Le Grand eHatch = SvtGraphicFill::hatchDouble; 150264b14621SArmin Le Grand break; 150364b14621SArmin Le Grand } 150464b14621SArmin Le Grand case attribute::HATCHSTYLE_TRIPLE : 150564b14621SArmin Le Grand { 150664b14621SArmin Le Grand eHatch = SvtGraphicFill::hatchTriple; 150764b14621SArmin Le Grand break; 150864b14621SArmin Le Grand } 150964b14621SArmin Le Grand } 1510cdf0e10cSrcweir 151164b14621SArmin Le Grand SvtGraphicFill::Transform aTransform; 151264b14621SArmin Le Grand 151364b14621SArmin Le Grand // scale 151464b14621SArmin Le Grand aTransform.matrix[0] *= rFillHatchAttribute.getDistance(); 151564b14621SArmin Le Grand aTransform.matrix[4] *= rFillHatchAttribute.getDistance(); 151664b14621SArmin Le Grand 151764b14621SArmin Le Grand // rotate (was never correct in impgrfll anyways, use correct angle now) 151864b14621SArmin Le Grand aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle()); 151964b14621SArmin Le Grand aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle()); 152064b14621SArmin Le Grand aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle()); 152164b14621SArmin Le Grand aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle()); 152264b14621SArmin Le Grand 152364b14621SArmin Le Grand pSvtGraphicFill = new SvtGraphicFill( 152464b14621SArmin Le Grand PolyPolygon(aLocalPolyPolygon), 152564b14621SArmin Le Grand Color(), 152664b14621SArmin Le Grand 0.0, 152764b14621SArmin Le Grand SvtGraphicFill::fillEvenOdd, 152864b14621SArmin Le Grand SvtGraphicFill::fillHatch, 152964b14621SArmin Le Grand aTransform, 153064b14621SArmin Le Grand false, 153164b14621SArmin Le Grand eHatch, 153264b14621SArmin Le Grand Color(rFillHatchAttribute.getColor()), 153364b14621SArmin Le Grand SvtGraphicFill::gradientLinear, 153464b14621SArmin Le Grand Color(), 153564b14621SArmin Le Grand Color(), 153664b14621SArmin Le Grand 0, 153764b14621SArmin Le Grand Graphic()); 153864b14621SArmin Le Grand } 1539cdf0e10cSrcweir 154064b14621SArmin Le Grand // Do use decomposition; encapsulate with SvtGraphicFill 154164b14621SArmin Le Grand impStartSvtGraphicFill(pSvtGraphicFill); 1542cdf0e10cSrcweir 1543cdf0e10cSrcweir // #i111954# do NOT use decomposition, but use direct VCL-command 154464b14621SArmin Le Grand // process(rCandidate.get2DDecomposition(getViewInformation2D())); 154564b14621SArmin Le Grand const PolyPolygon aToolsPolyPolygon(aLocalPolyPolygon); 1546cdf0e10cSrcweir const HatchStyle aHatchStyle( 1547cdf0e10cSrcweir attribute::HATCHSTYLE_SINGLE == rFillHatchAttribute.getStyle() ? HATCH_SINGLE : 1548cdf0e10cSrcweir attribute::HATCHSTYLE_DOUBLE == rFillHatchAttribute.getStyle() ? HATCH_DOUBLE : 1549cdf0e10cSrcweir HATCH_TRIPLE); 1550cdf0e10cSrcweir 1551cdf0e10cSrcweir mpOutputDevice->DrawHatch(aToolsPolyPolygon, 1552cdf0e10cSrcweir Hatch(aHatchStyle, 1553cdf0e10cSrcweir Color(rFillHatchAttribute.getColor()), 1554cdf0e10cSrcweir basegfx::fround(rFillHatchAttribute.getDistance()), 1555cdf0e10cSrcweir basegfx::fround(rFillHatchAttribute.getAngle() / F_PI1800))); 1556cdf0e10cSrcweir 1557cdf0e10cSrcweir impEndSvtGraphicFill(pSvtGraphicFill); 1558cdf0e10cSrcweir 155964b14621SArmin Le Grand break; 156064b14621SArmin Le Grand } 156164b14621SArmin Le Grand case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D : 1562cdf0e10cSrcweir { 15636d3fd5d0SArmin Le Grand basegfx::B2DVector aScale, aTranslate; 15646d3fd5d0SArmin Le Grand double fRotate, fShearX; 1565cdf0e10cSrcweir 15666d3fd5d0SArmin Le Grand maCurrentTransformation.decompose(aScale, aTranslate, fRotate, fShearX); 1567cdf0e10cSrcweir 15686d3fd5d0SArmin Le Grand if(!basegfx::fTools::equalZero(fRotate) || !basegfx::fTools::equalZero(fShearX)) 15696d3fd5d0SArmin Le Grand { 15706d3fd5d0SArmin Le Grand // #121185# When rotation or shear is used, a VCL Gradient cannot be used directly. 15716d3fd5d0SArmin Le Grand // This is because VCL Gradient mechanism does *not* support to rotate the gradient 15726d3fd5d0SArmin Le Grand // with objects and this case is not expressable in a Metafile (and cannot be added 15736d3fd5d0SArmin Le Grand // since the FileFormats used, e.g. *.wmf, do not support it either). 15746d3fd5d0SArmin Le Grand // Such cases happen when a graphic object uses a Metafile as graphic information or 15756d3fd5d0SArmin Le Grand // a fill style definition uses a Metafile. In this cases the graphic content is 15766d3fd5d0SArmin Le Grand // rotated with the graphic or filled object; this is not supported by the target 15776d3fd5d0SArmin Le Grand // format of this conversion renderer - Metafiles. 15786d3fd5d0SArmin Le Grand // To solve this, not a Gradient is written, but the decomposition of this object 15796d3fd5d0SArmin Le Grand // is written to the Metafile. This is the PolyPolygons building the gradient fill. 15806d3fd5d0SArmin Le Grand // These will need more space and time, but the result will be as if the Gradient 15816d3fd5d0SArmin Le Grand // was rotated with the object. 15826d3fd5d0SArmin Le Grand // This mechanism is used by all exporters still not using Primtives (e.g. Print, 15836d3fd5d0SArmin Le Grand // Slideshow, Export rto PDF, export to Picture, ...) but relying on Metafile 15846d3fd5d0SArmin Le Grand // transfers. One more reason to *change* these to primitives. 15856d3fd5d0SArmin Le Grand // BTW: One more example how useful the principles of primitives are; the decomposition 15866d3fd5d0SArmin Le Grand // is by definition a simpler, maybe more expensive representation of the same content. 15876d3fd5d0SArmin Le Grand process(rCandidate.get2DDecomposition(getViewInformation2D())); 158864b14621SArmin Le Grand break; 15896d3fd5d0SArmin Le Grand } 159064b14621SArmin Le Grand 159164b14621SArmin Le Grand const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate); 159264b14621SArmin Le Grand basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon()); 159364b14621SArmin Le Grand 159464b14621SArmin Le Grand if(aLocalPolyPolygon.getB2DRange() != rGradientCandidate.getDefinitionRange()) 15956d3fd5d0SArmin Le Grand { 159664b14621SArmin Le Grand // the range which defines the gradient is different from the range of the 159764b14621SArmin Le Grand // geometry (used for writer frames). This cannot be done calling vcl, thus use 159864b14621SArmin Le Grand // decomposition here 159964b14621SArmin Le Grand process(rCandidate.get2DDecomposition(getViewInformation2D())); 160064b14621SArmin Le Grand break; 160164b14621SArmin Le Grand } 1602cdf0e10cSrcweir 160364b14621SArmin Le Grand // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 160464b14621SArmin Le Grand // per polygon. Split polygon until there are less than that 160564b14621SArmin Le Grand while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) 160664b14621SArmin Le Grand ; 160764b14621SArmin Le Grand 160864b14621SArmin Le Grand // for support of MetaCommentActions of the form XGRAD_SEQ_BEGIN, XGRAD_SEQ_END 160964b14621SArmin Le Grand // it is safest to use the VCL OutputDevice::DrawGradient method which creates those. 161064b14621SArmin Le Grand // re-create a VCL-gradient from FillGradientPrimitive2D and the needed tools PolyPolygon 161164b14621SArmin Le Grand Gradient aVCLGradient; 161264b14621SArmin Le Grand impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rGradientCandidate.getFillGradient(), false); 161364b14621SArmin Le Grand aLocalPolyPolygon.transform(maCurrentTransformation); 16146d3fd5d0SArmin Le Grand 161564b14621SArmin Le Grand // #i82145# ATM VCL printing of gradients using curved shapes does not work, 161664b14621SArmin Le Grand // i submitted the bug with the given ID to THB. When that task is fixed it is 161764b14621SArmin Le Grand // necessary to again remove this subdivision since it decreases possible 161864b14621SArmin Le Grand // printing quality (not even resolution-dependent for now). THB will tell 161964b14621SArmin Le Grand // me when that task is fixed in the master 162064b14621SArmin Le Grand const PolyPolygon aToolsPolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(aLocalPolyPolygon)); 162164b14621SArmin Le Grand 162264b14621SArmin Le Grand // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support 162364b14621SArmin Le Grand SvtGraphicFill* pSvtGraphicFill = 0; 162464b14621SArmin Le Grand 162564b14621SArmin Le Grand if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count()) 162664b14621SArmin Le Grand { 162764b14621SArmin Le Grand // setup gradient stuff like in like in impgrfll 162864b14621SArmin Le Grand SvtGraphicFill::GradientType eGrad(SvtGraphicFill::gradientLinear); 162964b14621SArmin Le Grand 163064b14621SArmin Le Grand switch(aVCLGradient.GetStyle()) 163164b14621SArmin Le Grand { 163264b14621SArmin Le Grand default : // GRADIENT_LINEAR: 163364b14621SArmin Le Grand case GRADIENT_AXIAL: 163464b14621SArmin Le Grand eGrad = SvtGraphicFill::gradientLinear; 163564b14621SArmin Le Grand break; 163664b14621SArmin Le Grand case GRADIENT_RADIAL: 163764b14621SArmin Le Grand case GRADIENT_ELLIPTICAL: 163864b14621SArmin Le Grand eGrad = SvtGraphicFill::gradientRadial; 163964b14621SArmin Le Grand break; 164064b14621SArmin Le Grand case GRADIENT_SQUARE: 164164b14621SArmin Le Grand case GRADIENT_RECT: 164264b14621SArmin Le Grand eGrad = SvtGraphicFill::gradientRectangular; 164364b14621SArmin Le Grand break; 164464b14621SArmin Le Grand } 164564b14621SArmin Le Grand 164664b14621SArmin Le Grand pSvtGraphicFill = new SvtGraphicFill( 164764b14621SArmin Le Grand aToolsPolyPolygon, 164864b14621SArmin Le Grand Color(), 164964b14621SArmin Le Grand 0.0, 165064b14621SArmin Le Grand SvtGraphicFill::fillEvenOdd, 165164b14621SArmin Le Grand SvtGraphicFill::fillGradient, 165264b14621SArmin Le Grand SvtGraphicFill::Transform(), 165364b14621SArmin Le Grand false, 165464b14621SArmin Le Grand SvtGraphicFill::hatchSingle, 165564b14621SArmin Le Grand Color(), 165664b14621SArmin Le Grand eGrad, 165764b14621SArmin Le Grand aVCLGradient.GetStartColor(), 165864b14621SArmin Le Grand aVCLGradient.GetEndColor(), 165964b14621SArmin Le Grand aVCLGradient.GetSteps(), 166064b14621SArmin Le Grand Graphic()); 16616d3fd5d0SArmin Le Grand } 1662cdf0e10cSrcweir 166364b14621SArmin Le Grand // call VCL directly; encapsulate with SvtGraphicFill 166464b14621SArmin Le Grand impStartSvtGraphicFill(pSvtGraphicFill); 166564b14621SArmin Le Grand mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient); 166664b14621SArmin Le Grand impEndSvtGraphicFill(pSvtGraphicFill); 166764b14621SArmin Le Grand 1668cdf0e10cSrcweir break; 1669cdf0e10cSrcweir } 1670cdf0e10cSrcweir case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D : 1671cdf0e10cSrcweir { 1672cdf0e10cSrcweir const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate)); 1673cdf0e10cSrcweir basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon()); 1674cdf0e10cSrcweir 1675cdf0e10cSrcweir // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 1676cdf0e10cSrcweir // per polygon. Split polygon until there are less than that 1677cdf0e10cSrcweir while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) 1678cdf0e10cSrcweir ; 1679cdf0e10cSrcweir 1680cdf0e10cSrcweir const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor())); 1681cdf0e10cSrcweir aLocalPolyPolygon.transform(maCurrentTransformation); 1682cdf0e10cSrcweir 1683cdf0e10cSrcweir // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support 1684cdf0e10cSrcweir SvtGraphicFill* pSvtGraphicFill = 0; 1685cdf0e10cSrcweir 16864665f8d3SArmin Le Grand // #121267# Not needed, does not give better quality compared with 16874665f8d3SArmin Le Grand // the META_POLYPOLYGON_ACTION written by the DrawPolyPolygon command 16884665f8d3SArmin Le Grand // below 16894665f8d3SArmin Le Grand bool bSupportSvtGraphicFill(false); 16904665f8d3SArmin Le Grand 16914665f8d3SArmin Le Grand if(bSupportSvtGraphicFill && !mnSvtGraphicFillCount && aLocalPolyPolygon.count()) 1692cdf0e10cSrcweir { 1693cdf0e10cSrcweir // setup simple color fill stuff like in impgrfll 1694cdf0e10cSrcweir pSvtGraphicFill = new SvtGraphicFill( 1695cdf0e10cSrcweir PolyPolygon(aLocalPolyPolygon), 1696cdf0e10cSrcweir Color(aPolygonColor), 1697cdf0e10cSrcweir 0.0, 1698cdf0e10cSrcweir SvtGraphicFill::fillEvenOdd, 1699cdf0e10cSrcweir SvtGraphicFill::fillSolid, 1700cdf0e10cSrcweir SvtGraphicFill::Transform(), 1701cdf0e10cSrcweir false, 1702cdf0e10cSrcweir SvtGraphicFill::hatchSingle, 1703cdf0e10cSrcweir Color(), 1704cdf0e10cSrcweir SvtGraphicFill::gradientLinear, 1705cdf0e10cSrcweir Color(), 1706cdf0e10cSrcweir Color(), 1707cdf0e10cSrcweir 0, 1708cdf0e10cSrcweir Graphic()); 1709cdf0e10cSrcweir } 1710cdf0e10cSrcweir 1711cdf0e10cSrcweir // set line and fill color 1712cdf0e10cSrcweir mpOutputDevice->SetFillColor(Color(aPolygonColor)); 1713cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 1714cdf0e10cSrcweir 1715cdf0e10cSrcweir // call VCL directly; encapsulate with SvtGraphicFill 17164665f8d3SArmin Le Grand if(bSupportSvtGraphicFill) 17174665f8d3SArmin Le Grand { 17184665f8d3SArmin Le Grand impStartSvtGraphicFill(pSvtGraphicFill); 17194665f8d3SArmin Le Grand } 17204665f8d3SArmin Le Grand 17214665f8d3SArmin Le Grand mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon); 17224665f8d3SArmin Le Grand 17234665f8d3SArmin Le Grand if(bSupportSvtGraphicFill) 17244665f8d3SArmin Le Grand { 17254665f8d3SArmin Le Grand impEndSvtGraphicFill(pSvtGraphicFill); 17264665f8d3SArmin Le Grand } 1727cdf0e10cSrcweir 1728cdf0e10cSrcweir break; 1729cdf0e10cSrcweir } 1730cdf0e10cSrcweir case PRIMITIVE2D_ID_MASKPRIMITIVE2D : 1731cdf0e10cSrcweir { 1732cdf0e10cSrcweir // mask group. Special handling for MetaFiles. 1733cdf0e10cSrcweir const primitive2d::MaskPrimitive2D& rMaskCandidate = static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate); 1734cdf0e10cSrcweir 1735cdf0e10cSrcweir if(rMaskCandidate.getChildren().hasElements()) 1736cdf0e10cSrcweir { 1737cdf0e10cSrcweir basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask()); 1738cdf0e10cSrcweir 1739cdf0e10cSrcweir if(aMask.count()) 1740cdf0e10cSrcweir { 1741cdf0e10cSrcweir // prepare new mask polygon and rescue current one 1742cdf0e10cSrcweir aMask.transform(maCurrentTransformation); 1743cdf0e10cSrcweir const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon); 1744*54d1d3e3SArmin Le Grand 1745cdf0e10cSrcweir if(maClipPolyPolygon.count()) 1746cdf0e10cSrcweir { 1747*54d1d3e3SArmin Le Grand // there is already a clip polygon set; build clipped union of 1748*54d1d3e3SArmin Le Grand // current mask polygon and new one 1749*54d1d3e3SArmin Le Grand maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon( 1750*54d1d3e3SArmin Le Grand aMask, 1751*54d1d3e3SArmin Le Grand maClipPolyPolygon, 1752*54d1d3e3SArmin Le Grand true, // #i106516# we want the inside of aMask, not the outside 1753*54d1d3e3SArmin Le Grand false); 1754cdf0e10cSrcweir } 1755cdf0e10cSrcweir else 1756cdf0e10cSrcweir { 1757*54d1d3e3SArmin Le Grand // use mask directly 1758cdf0e10cSrcweir maClipPolyPolygon = aMask; 1759cdf0e10cSrcweir } 1760cdf0e10cSrcweir 1761cdf0e10cSrcweir if(maClipPolyPolygon.count()) 1762cdf0e10cSrcweir { 1763cdf0e10cSrcweir // set VCL clip region; subdivide before conversion to tools polygon. Subdivision necessary (!) 1764cdf0e10cSrcweir // Removed subdivision and fixed in Region::ImplPolyPolyRegionToBandRegionFunc() in VCL where 1765cdf0e10cSrcweir // the ClipRegion is built from the Polygon. A AdaptiveSubdivide on the source polygon was missing there 1766*54d1d3e3SArmin Le Grand mpOutputDevice->Push(PUSH_CLIPREGION); 1767*54d1d3e3SArmin Le Grand mpOutputDevice->SetClipRegion(Region(maClipPolyPolygon)); 17684665f8d3SArmin Le Grand 17694665f8d3SArmin Le Grand // recursively paint content 17704665f8d3SArmin Le Grand // #121267# Only need to process sub-content when clip polygon is *not* empty. 17714665f8d3SArmin Le Grand // If it is empty, the clip is empty and there can be nothing inside. 17724665f8d3SArmin Le Grand process(rMaskCandidate.getChildren()); 1773cdf0e10cSrcweir 1774cdf0e10cSrcweir // restore VCL clip region 1775*54d1d3e3SArmin Le Grand mpOutputDevice->Pop(); 1776cdf0e10cSrcweir } 1777cdf0e10cSrcweir 1778cdf0e10cSrcweir // restore to rescued clip polygon 1779cdf0e10cSrcweir maClipPolyPolygon = aLastClipPolyPolygon; 1780cdf0e10cSrcweir } 1781cdf0e10cSrcweir else 1782cdf0e10cSrcweir { 1783cdf0e10cSrcweir // no mask, no clipping. recursively paint content 1784cdf0e10cSrcweir process(rMaskCandidate.getChildren()); 1785cdf0e10cSrcweir } 1786cdf0e10cSrcweir } 1787cdf0e10cSrcweir 1788cdf0e10cSrcweir break; 1789cdf0e10cSrcweir } 1790cdf0e10cSrcweir case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D : 1791cdf0e10cSrcweir { 1792cdf0e10cSrcweir // modified color group. Force output to unified color. Use default pocessing. 1793cdf0e10cSrcweir RenderModifiedColorPrimitive2D(static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate)); 1794cdf0e10cSrcweir break; 1795cdf0e10cSrcweir } 1796cdf0e10cSrcweir case PRIMITIVE2D_ID_HIDDENGEOMETRYPRIMITIVE2D : 1797cdf0e10cSrcweir { 1798cdf0e10cSrcweir // HiddenGeometryPrimitive2D; to rebuilt the old MetaFile creation, it is necessary to 1799cdf0e10cSrcweir // not ignore them (as it was thought), but to add a MetaFile entry for them. 1800cdf0e10cSrcweir basegfx::B2DRange aInvisibleRange(rCandidate.getB2DRange(getViewInformation2D())); 1801cdf0e10cSrcweir 1802cdf0e10cSrcweir if(!aInvisibleRange.isEmpty()) 1803cdf0e10cSrcweir { 1804cdf0e10cSrcweir aInvisibleRange.transform(maCurrentTransformation); 1805cdf0e10cSrcweir const Rectangle aRectLogic( 1806cdf0e10cSrcweir (sal_Int32)floor(aInvisibleRange.getMinX()), (sal_Int32)floor(aInvisibleRange.getMinY()), 1807cdf0e10cSrcweir (sal_Int32)ceil(aInvisibleRange.getMaxX()), (sal_Int32)ceil(aInvisibleRange.getMaxY())); 1808cdf0e10cSrcweir 1809cdf0e10cSrcweir mpOutputDevice->SetFillColor(); 1810cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 1811cdf0e10cSrcweir mpOutputDevice->DrawRect(aRectLogic); 1812cdf0e10cSrcweir } 1813cdf0e10cSrcweir 1814cdf0e10cSrcweir break; 1815cdf0e10cSrcweir } 1816cdf0e10cSrcweir case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D : 1817cdf0e10cSrcweir { 1818cdf0e10cSrcweir // for metafile: Need to examine what the pure vcl version is doing here actually 1819cdf0e10cSrcweir // - uses DrawTransparent with metafile for content and a gradient 1820cdf0e10cSrcweir // - uses DrawTransparent for single PolyPoylgons directly. Can be detected by 1821cdf0e10cSrcweir // checking the content for single PolyPolygonColorPrimitive2D 1822cdf0e10cSrcweir const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate = static_cast< const primitive2d::UnifiedTransparencePrimitive2D& >(rCandidate); 1823cdf0e10cSrcweir const primitive2d::Primitive2DSequence rContent = rUniTransparenceCandidate.getChildren(); 1824cdf0e10cSrcweir 1825cdf0e10cSrcweir if(rContent.hasElements()) 1826cdf0e10cSrcweir { 1827cdf0e10cSrcweir if(0.0 == rUniTransparenceCandidate.getTransparence()) 1828cdf0e10cSrcweir { 1829cdf0e10cSrcweir // not transparent at all, use content 1830cdf0e10cSrcweir process(rUniTransparenceCandidate.getChildren()); 1831cdf0e10cSrcweir } 1832cdf0e10cSrcweir else if(rUniTransparenceCandidate.getTransparence() > 0.0 && rUniTransparenceCandidate.getTransparence() < 1.0) 1833cdf0e10cSrcweir { 1834cdf0e10cSrcweir // try to identify a single PolyPolygonColorPrimitive2D in the 1835cdf0e10cSrcweir // content part of the transparence primitive 1836cdf0e10cSrcweir const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = 0; 1837cdf0e10cSrcweir static bool bForceToMetafile(false); 1838cdf0e10cSrcweir 1839cdf0e10cSrcweir if(!bForceToMetafile && 1 == rContent.getLength()) 1840cdf0e10cSrcweir { 1841cdf0e10cSrcweir const primitive2d::Primitive2DReference xReference(rContent[0]); 1842cdf0e10cSrcweir pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get()); 1843cdf0e10cSrcweir } 1844cdf0e10cSrcweir 1845cdf0e10cSrcweir // PolyPolygonGradientPrimitive2D, PolyPolygonHatchPrimitive2D and 1846035a2f44SArmin Le Grand // PolyPolygonGraphicPrimitive2D are derived from PolyPolygonColorPrimitive2D. 1847cdf0e10cSrcweir // Check also for correct ID to exclude derived implementations 1848cdf0e10cSrcweir if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID()) 1849cdf0e10cSrcweir { 1850cdf0e10cSrcweir // single transparent PolyPolygon identified, use directly 1851cdf0e10cSrcweir const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor())); 1852cdf0e10cSrcweir basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon()); 1853cdf0e10cSrcweir 1854cdf0e10cSrcweir // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points 1855cdf0e10cSrcweir // per polygon. Split polygon until there are less than that 1856cdf0e10cSrcweir while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) 1857cdf0e10cSrcweir ; 1858cdf0e10cSrcweir 1859cdf0e10cSrcweir // now transform 1860cdf0e10cSrcweir aLocalPolyPolygon.transform(maCurrentTransformation); 1861cdf0e10cSrcweir 1862cdf0e10cSrcweir // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support 1863cdf0e10cSrcweir SvtGraphicFill* pSvtGraphicFill = 0; 18644665f8d3SArmin Le Grand 18654665f8d3SArmin Le Grand // #121267# Not needed, does not give better quality compared with 18664665f8d3SArmin Le Grand // the META_POLYPOLYGON_ACTION written by the DrawPolyPolygon command 18674665f8d3SArmin Le Grand // below 18684665f8d3SArmin Le Grand bool bSupportSvtGraphicFill(false); 1869cdf0e10cSrcweir 18704665f8d3SArmin Le Grand if(bSupportSvtGraphicFill && !mnSvtGraphicFillCount && aLocalPolyPolygon.count()) 1871cdf0e10cSrcweir { 1872cdf0e10cSrcweir // setup simple color with transparence fill stuff like in impgrfll 1873cdf0e10cSrcweir pSvtGraphicFill = new SvtGraphicFill( 1874cdf0e10cSrcweir PolyPolygon(aLocalPolyPolygon), 1875cdf0e10cSrcweir Color(aPolygonColor), 1876cdf0e10cSrcweir rUniTransparenceCandidate.getTransparence(), 1877cdf0e10cSrcweir SvtGraphicFill::fillEvenOdd, 1878cdf0e10cSrcweir SvtGraphicFill::fillSolid, 1879cdf0e10cSrcweir SvtGraphicFill::Transform(), 1880cdf0e10cSrcweir false, 1881cdf0e10cSrcweir SvtGraphicFill::hatchSingle, 1882cdf0e10cSrcweir Color(), 1883cdf0e10cSrcweir SvtGraphicFill::gradientLinear, 1884cdf0e10cSrcweir Color(), 1885cdf0e10cSrcweir Color(), 1886cdf0e10cSrcweir 0, 1887cdf0e10cSrcweir Graphic()); 1888cdf0e10cSrcweir } 1889cdf0e10cSrcweir 1890cdf0e10cSrcweir // set line and fill color 1891cdf0e10cSrcweir const sal_uInt16 nTransPercentVcl((sal_uInt16)basegfx::fround(rUniTransparenceCandidate.getTransparence() * 100.0)); 1892cdf0e10cSrcweir mpOutputDevice->SetFillColor(Color(aPolygonColor)); 1893cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 1894cdf0e10cSrcweir 1895cdf0e10cSrcweir // call VCL directly; encapsulate with SvtGraphicFill 18964665f8d3SArmin Le Grand if(bSupportSvtGraphicFill) 18974665f8d3SArmin Le Grand { 18984665f8d3SArmin Le Grand impStartSvtGraphicFill(pSvtGraphicFill); 18994665f8d3SArmin Le Grand } 19004665f8d3SArmin Le Grand 1901cdf0e10cSrcweir mpOutputDevice->DrawTransparent( 1902cdf0e10cSrcweir PolyPolygon(aLocalPolyPolygon), 1903cdf0e10cSrcweir nTransPercentVcl); 19044665f8d3SArmin Le Grand 19054665f8d3SArmin Le Grand if(bSupportSvtGraphicFill) 19064665f8d3SArmin Le Grand { 19074665f8d3SArmin Le Grand impEndSvtGraphicFill(pSvtGraphicFill); 19084665f8d3SArmin Le Grand } 1909cdf0e10cSrcweir } 1910cdf0e10cSrcweir else 1911cdf0e10cSrcweir { 1912cdf0e10cSrcweir // svae old mfCurrentUnifiedTransparence and set new one 1913cdf0e10cSrcweir // so that contained SvtGraphicStroke may use the current one 1914cdf0e10cSrcweir const double fLastCurrentUnifiedTransparence(mfCurrentUnifiedTransparence); 1915cdf0e10cSrcweir // #i105377# paint the content metafile opaque as the transparency gets 1916cdf0e10cSrcweir // split of into the gradient below 1917cdf0e10cSrcweir // mfCurrentUnifiedTransparence = rUniTransparenceCandidate.getTransparence(); 1918cdf0e10cSrcweir mfCurrentUnifiedTransparence = 0; 1919cdf0e10cSrcweir 1920cdf0e10cSrcweir // various content, create content-metafile 1921cdf0e10cSrcweir GDIMetaFile aContentMetafile; 1922cdf0e10cSrcweir const Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile)); 1923cdf0e10cSrcweir 1924cdf0e10cSrcweir // restore mfCurrentUnifiedTransparence; it may have been used 1925cdf0e10cSrcweir // while processing the sub-content in impDumpToMetaFile 1926cdf0e10cSrcweir mfCurrentUnifiedTransparence = fLastCurrentUnifiedTransparence; 1927cdf0e10cSrcweir 1928cdf0e10cSrcweir // create uniform VCL gradient for uniform transparency 1929cdf0e10cSrcweir Gradient aVCLGradient; 1930cdf0e10cSrcweir const sal_uInt8 nTransPercentVcl((sal_uInt8)basegfx::fround(rUniTransparenceCandidate.getTransparence() * 255.0)); 1931cdf0e10cSrcweir const Color aTransColor(nTransPercentVcl, nTransPercentVcl, nTransPercentVcl); 1932cdf0e10cSrcweir 1933cdf0e10cSrcweir aVCLGradient.SetStyle(GRADIENT_LINEAR); 1934cdf0e10cSrcweir aVCLGradient.SetStartColor(aTransColor); 1935cdf0e10cSrcweir aVCLGradient.SetEndColor(aTransColor); 1936cdf0e10cSrcweir aVCLGradient.SetAngle(0); 1937cdf0e10cSrcweir aVCLGradient.SetBorder(0); 1938cdf0e10cSrcweir aVCLGradient.SetOfsX(0); 1939cdf0e10cSrcweir aVCLGradient.SetOfsY(0); 1940cdf0e10cSrcweir aVCLGradient.SetStartIntensity(100); 1941cdf0e10cSrcweir aVCLGradient.SetEndIntensity(100); 1942cdf0e10cSrcweir aVCLGradient.SetSteps(2); 1943cdf0e10cSrcweir 1944cdf0e10cSrcweir // render it to VCL 1945cdf0e10cSrcweir mpOutputDevice->DrawTransparent( 1946cdf0e10cSrcweir aContentMetafile, aPrimitiveRectangle.TopLeft(), 1947cdf0e10cSrcweir aPrimitiveRectangle.GetSize(), aVCLGradient); 1948cdf0e10cSrcweir } 1949cdf0e10cSrcweir } 1950cdf0e10cSrcweir } 1951cdf0e10cSrcweir 1952cdf0e10cSrcweir break; 1953cdf0e10cSrcweir } 1954cdf0e10cSrcweir case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D : 1955cdf0e10cSrcweir { 1956cdf0e10cSrcweir // for metafile: Need to examine what the pure vcl version is doing here actually 1957cdf0e10cSrcweir // - uses DrawTransparent with metafile for content and a gradient 1958cdf0e10cSrcweir // i can detect this here with checking the gradient part for a single 1959cdf0e10cSrcweir // FillGradientPrimitive2D and reconstruct the gradient. 1960cdf0e10cSrcweir // If that detection goes wrong, i have to create an transparence-blended bitmap. Eventually 1961cdf0e10cSrcweir // do that in stripes, else RenderTransparencePrimitive2D may just be used 1962cdf0e10cSrcweir const primitive2d::TransparencePrimitive2D& rTransparenceCandidate = static_cast< const primitive2d::TransparencePrimitive2D& >(rCandidate); 1963cdf0e10cSrcweir const primitive2d::Primitive2DSequence rContent = rTransparenceCandidate.getChildren(); 1964cdf0e10cSrcweir const primitive2d::Primitive2DSequence rTransparence = rTransparenceCandidate.getTransparence(); 1965cdf0e10cSrcweir 1966cdf0e10cSrcweir if(rContent.hasElements() && rTransparence.hasElements()) 1967cdf0e10cSrcweir { 1968cdf0e10cSrcweir // try to identify a single FillGradientPrimitive2D in the 1969cdf0e10cSrcweir // transparence part of the primitive 1970cdf0e10cSrcweir const primitive2d::FillGradientPrimitive2D* pFiGradient = 0; 1971cdf0e10cSrcweir static bool bForceToBigTransparentVDev(false); 1972cdf0e10cSrcweir 1973cdf0e10cSrcweir if(!bForceToBigTransparentVDev && 1 == rTransparence.getLength()) 1974cdf0e10cSrcweir { 1975cdf0e10cSrcweir const primitive2d::Primitive2DReference xReference(rTransparence[0]); 1976cdf0e10cSrcweir pFiGradient = dynamic_cast< const primitive2d::FillGradientPrimitive2D* >(xReference.get()); 1977cdf0e10cSrcweir } 1978cdf0e10cSrcweir 1979cdf0e10cSrcweir // Check also for correct ID to exclude derived implementations 1980cdf0e10cSrcweir if(pFiGradient && PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D == pFiGradient->getPrimitive2DID()) 1981cdf0e10cSrcweir { 1982cdf0e10cSrcweir // various content, create content-metafile 1983cdf0e10cSrcweir GDIMetaFile aContentMetafile; 1984cdf0e10cSrcweir const Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile)); 1985cdf0e10cSrcweir 1986cdf0e10cSrcweir // re-create a VCL-gradient from FillGradientPrimitive2D 1987cdf0e10cSrcweir Gradient aVCLGradient; 1988cdf0e10cSrcweir impConvertFillGradientAttributeToVCLGradient(aVCLGradient, pFiGradient->getFillGradient(), true); 1989cdf0e10cSrcweir 1990cdf0e10cSrcweir // render it to VCL 1991cdf0e10cSrcweir mpOutputDevice->DrawTransparent( 1992cdf0e10cSrcweir aContentMetafile, aPrimitiveRectangle.TopLeft(), 1993cdf0e10cSrcweir aPrimitiveRectangle.GetSize(), aVCLGradient); 1994cdf0e10cSrcweir } 1995cdf0e10cSrcweir else 1996cdf0e10cSrcweir { 1997cdf0e10cSrcweir // sub-transparence group. Draw to VDev first. 1998cdf0e10cSrcweir // this may get refined to tiling when resolution is too big here 1999cdf0e10cSrcweir 2000cdf0e10cSrcweir // need to avoid switching off MapMode stuff here; maybe need another 2001cdf0e10cSrcweir // tooling class, cannot just do the same as with the pixel renderer. 2002cdf0e10cSrcweir // Need to experiment... 2003cdf0e10cSrcweir 2004cdf0e10cSrcweir // Okay, basic implementation finished and tested. The DPI stuff was hard 2005cdf0e10cSrcweir // and not easy to find out that it's needed. 200607a3d7f1SPedro Giffuni // Since this will not yet happen normally (as long as no one constructs 2007cdf0e10cSrcweir // transparence primitives with non-trivial transparence content) i will for now not 2008cdf0e10cSrcweir // refine to tiling here. 2009cdf0e10cSrcweir 2010cdf0e10cSrcweir basegfx::B2DRange aViewRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D())); 2011cdf0e10cSrcweir aViewRange.transform(maCurrentTransformation); 2012cdf0e10cSrcweir const Rectangle aRectLogic( 2013cdf0e10cSrcweir (sal_Int32)floor(aViewRange.getMinX()), (sal_Int32)floor(aViewRange.getMinY()), 2014cdf0e10cSrcweir (sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY())); 2015cdf0e10cSrcweir const Rectangle aRectPixel(mpOutputDevice->LogicToPixel(aRectLogic)); 201689cebadeSArmin Le Grand Size aSizePixel(aRectPixel.GetSize()); 2017cdf0e10cSrcweir const Point aEmptyPoint; 2018cdf0e10cSrcweir VirtualDevice aBufferDevice; 201989cebadeSArmin Le Grand const sal_uInt32 nMaxQuadratPixels(500000); 202089cebadeSArmin Le Grand const sal_uInt32 nViewVisibleArea(aSizePixel.getWidth() * aSizePixel.getHeight()); 202189cebadeSArmin Le Grand double fReduceFactor(1.0); 202289cebadeSArmin Le Grand 202389cebadeSArmin Le Grand if(nViewVisibleArea > nMaxQuadratPixels) 202489cebadeSArmin Le Grand { 202589cebadeSArmin Le Grand // reduce render size 202689cebadeSArmin Le Grand fReduceFactor = sqrt((double)nMaxQuadratPixels / (double)nViewVisibleArea); 202789cebadeSArmin Le Grand aSizePixel = Size(basegfx::fround((double)aSizePixel.getWidth() * fReduceFactor), 202889cebadeSArmin Le Grand basegfx::fround((double)aSizePixel.getHeight() * fReduceFactor)); 202989cebadeSArmin Le Grand } 2030cdf0e10cSrcweir 2031cdf0e10cSrcweir if(aBufferDevice.SetOutputSizePixel(aSizePixel)) 2032cdf0e10cSrcweir { 2033cdf0e10cSrcweir // create and set MapModes for target devices 2034cdf0e10cSrcweir MapMode aNewMapMode(mpOutputDevice->GetMapMode()); 2035cdf0e10cSrcweir aNewMapMode.SetOrigin(Point(-aRectLogic.Left(), -aRectLogic.Top())); 2036cdf0e10cSrcweir aBufferDevice.SetMapMode(aNewMapMode); 2037cdf0e10cSrcweir 2038cdf0e10cSrcweir // prepare view transformation for target renderers 2039cdf0e10cSrcweir // ATTENTION! Need to apply another scaling because of the potential DPI differences 2040cdf0e10cSrcweir // between Printer and VDev (mpOutputDevice and aBufferDevice here). 2041cdf0e10cSrcweir // To get the DPI, LogicToPixel from (1,1) from MAP_INCH needs to be used. 2042cdf0e10cSrcweir basegfx::B2DHomMatrix aViewTransform(aBufferDevice.GetViewTransformation()); 2043cdf0e10cSrcweir const Size aDPIOld(mpOutputDevice->LogicToPixel(Size(1, 1), MAP_INCH)); 2044cdf0e10cSrcweir const Size aDPINew(aBufferDevice.LogicToPixel(Size(1, 1), MAP_INCH)); 2045cdf0e10cSrcweir const double fDPIXChange((double)aDPIOld.getWidth() / (double)aDPINew.getWidth()); 2046cdf0e10cSrcweir const double fDPIYChange((double)aDPIOld.getHeight() / (double)aDPINew.getHeight()); 2047cdf0e10cSrcweir 2048cdf0e10cSrcweir if(!basegfx::fTools::equal(fDPIXChange, 1.0) || !basegfx::fTools::equal(fDPIYChange, 1.0)) 2049cdf0e10cSrcweir { 2050cdf0e10cSrcweir aViewTransform.scale(fDPIXChange, fDPIYChange); 2051cdf0e10cSrcweir } 2052cdf0e10cSrcweir 205389cebadeSArmin Le Grand // also take scaling from Size reduction into acount 205489cebadeSArmin Le Grand if(!basegfx::fTools::equal(fReduceFactor, 1.0)) 205589cebadeSArmin Le Grand { 205689cebadeSArmin Le Grand aViewTransform.scale(fReduceFactor, fReduceFactor); 205789cebadeSArmin Le Grand } 205889cebadeSArmin Le Grand 2059cdf0e10cSrcweir // create view information and pixel renderer. Reuse known ViewInformation 2060cdf0e10cSrcweir // except new transformation and range 2061cdf0e10cSrcweir const geometry::ViewInformation2D aViewInfo( 2062cdf0e10cSrcweir getViewInformation2D().getObjectTransformation(), 2063cdf0e10cSrcweir aViewTransform, 2064cdf0e10cSrcweir aViewRange, 2065cdf0e10cSrcweir getViewInformation2D().getVisualizedPage(), 2066cdf0e10cSrcweir getViewInformation2D().getViewTime(), 2067cdf0e10cSrcweir getViewInformation2D().getExtendedInformationSequence()); 2068cdf0e10cSrcweir 2069cdf0e10cSrcweir VclPixelProcessor2D aBufferProcessor(aViewInfo, aBufferDevice); 2070cdf0e10cSrcweir 2071cdf0e10cSrcweir // draw content using pixel renderer 2072cdf0e10cSrcweir aBufferProcessor.process(rContent); 2073cdf0e10cSrcweir const Bitmap aBmContent(aBufferDevice.GetBitmap(aEmptyPoint, aSizePixel)); 2074cdf0e10cSrcweir 2075cdf0e10cSrcweir // draw transparence using pixel renderer 2076cdf0e10cSrcweir aBufferDevice.Erase(); 2077cdf0e10cSrcweir aBufferProcessor.process(rTransparence); 2078cdf0e10cSrcweir const AlphaMask aBmAlpha(aBufferDevice.GetBitmap(aEmptyPoint, aSizePixel)); 2079cdf0e10cSrcweir 2080cdf0e10cSrcweir #ifdef DBG_UTIL 2081cdf0e10cSrcweir static bool bDoSaveForVisualControl(false); 2082cdf0e10cSrcweir if(bDoSaveForVisualControl) 2083cdf0e10cSrcweir { 2084cdf0e10cSrcweir SvFileStream aNew(String(ByteString( "c:\\test.bmp" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC); 208545fd3b9aSArmin Le Grand 208645fd3b9aSArmin Le Grand WriteDIB(aBmContent, aNew, false, true); 2087cdf0e10cSrcweir } 2088cdf0e10cSrcweir #endif 2089cdf0e10cSrcweir 2090cdf0e10cSrcweir // paint 2091cdf0e10cSrcweir mpOutputDevice->DrawBitmapEx( 2092cdf0e10cSrcweir aRectLogic.TopLeft(), 2093cdf0e10cSrcweir aRectLogic.GetSize(), 2094cdf0e10cSrcweir BitmapEx(aBmContent, aBmAlpha)); 2095cdf0e10cSrcweir } 2096cdf0e10cSrcweir } 2097cdf0e10cSrcweir } 2098cdf0e10cSrcweir 2099cdf0e10cSrcweir break; 2100cdf0e10cSrcweir } 2101cdf0e10cSrcweir case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D : 2102cdf0e10cSrcweir { 2103cdf0e10cSrcweir // use default transform group pocessing 2104cdf0e10cSrcweir RenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate)); 2105cdf0e10cSrcweir break; 2106cdf0e10cSrcweir } 2107cdf0e10cSrcweir case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D : 2108cdf0e10cSrcweir { 2109cdf0e10cSrcweir // new XDrawPage for ViewInformation2D 2110cdf0e10cSrcweir RenderPagePreviewPrimitive2D(static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate)); 2111cdf0e10cSrcweir break; 2112cdf0e10cSrcweir } 2113cdf0e10cSrcweir case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D : 2114cdf0e10cSrcweir { 2115cdf0e10cSrcweir // use default marker array pocessing 2116cdf0e10cSrcweir RenderMarkerArrayPrimitive2D(static_cast< const primitive2d::MarkerArrayPrimitive2D& >(rCandidate)); 2117cdf0e10cSrcweir break; 2118cdf0e10cSrcweir } 2119cdf0e10cSrcweir case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D : 2120cdf0e10cSrcweir { 2121cdf0e10cSrcweir // use default point array pocessing 2122cdf0e10cSrcweir RenderPointArrayPrimitive2D(static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate)); 2123cdf0e10cSrcweir break; 2124cdf0e10cSrcweir } 2125cdf0e10cSrcweir case PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D : 2126cdf0e10cSrcweir { 2127cdf0e10cSrcweir // structured tag primitive 2128cdf0e10cSrcweir const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate = static_cast< const primitive2d::StructureTagPrimitive2D& >(rCandidate); 2129cdf0e10cSrcweir const vcl::PDFWriter::StructElement& rTagElement(rStructureTagCandidate.getStructureElement()); 2130cdf0e10cSrcweir const bool bTagUsed(vcl::PDFWriter::NonStructElement != rTagElement); 2131cdf0e10cSrcweir 2132cdf0e10cSrcweir if(mpPDFExtOutDevData && bTagUsed) 2133cdf0e10cSrcweir { 2134cdf0e10cSrcweir // write start tag 2135cdf0e10cSrcweir mpPDFExtOutDevData->BeginStructureElement(rTagElement); 2136cdf0e10cSrcweir } 2137cdf0e10cSrcweir 213807a3d7f1SPedro Giffuni // process childs normally 2139cdf0e10cSrcweir process(rStructureTagCandidate.getChildren()); 2140cdf0e10cSrcweir 2141cdf0e10cSrcweir if(mpPDFExtOutDevData && bTagUsed) 2142cdf0e10cSrcweir { 2143cdf0e10cSrcweir // write end tag 2144cdf0e10cSrcweir mpPDFExtOutDevData->EndStructureElement(); 2145cdf0e10cSrcweir } 2146cdf0e10cSrcweir 2147cdf0e10cSrcweir break; 2148cdf0e10cSrcweir } 2149cdf0e10cSrcweir case PRIMITIVE2D_ID_EPSPRIMITIVE2D : 2150cdf0e10cSrcweir { 2151cdf0e10cSrcweir RenderEpsPrimitive2D(static_cast< const primitive2d::EpsPrimitive2D& >(rCandidate)); 2152cdf0e10cSrcweir break; 2153cdf0e10cSrcweir } 2154cdf0e10cSrcweir default : 2155cdf0e10cSrcweir { 2156cdf0e10cSrcweir // process recursively 2157cdf0e10cSrcweir process(rCandidate.get2DDecomposition(getViewInformation2D())); 2158cdf0e10cSrcweir break; 2159cdf0e10cSrcweir } 2160cdf0e10cSrcweir } 2161cdf0e10cSrcweir } 2162cdf0e10cSrcweir } // end of namespace processor2d 2163cdf0e10cSrcweir } // end of namespace drawinglayer 2164cdf0e10cSrcweir 2165cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 2166cdf0e10cSrcweir // eof 2167