1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <drawinglayer/processor2d/vclprocessor2d.hxx> 32*cdf0e10cSrcweir #include <drawinglayer/primitive2d/textprimitive2d.hxx> 33*cdf0e10cSrcweir #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx> 34*cdf0e10cSrcweir #include <tools/debug.hxx> 35*cdf0e10cSrcweir #include <vcl/outdev.hxx> 36*cdf0e10cSrcweir #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> 37*cdf0e10cSrcweir #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> 38*cdf0e10cSrcweir #include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx> 39*cdf0e10cSrcweir #include <vclhelperbitmaptransform.hxx> 40*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx> 41*cdf0e10cSrcweir #include <vclhelperbitmaprender.hxx> 42*cdf0e10cSrcweir #include <drawinglayer/attribute/sdrfillbitmapattribute.hxx> 43*cdf0e10cSrcweir #include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx> 44*cdf0e10cSrcweir #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> 45*cdf0e10cSrcweir #include <vclhelpergradient.hxx> 46*cdf0e10cSrcweir #include <drawinglayer/primitive2d/metafileprimitive2d.hxx> 47*cdf0e10cSrcweir #include <drawinglayer/primitive2d/maskprimitive2d.hxx> 48*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx> 49*cdf0e10cSrcweir #include <vclhelperbufferdevice.hxx> 50*cdf0e10cSrcweir #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> 51*cdf0e10cSrcweir #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> 52*cdf0e10cSrcweir #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx> 53*cdf0e10cSrcweir #include <drawinglayer/primitive2d/transformprimitive2d.hxx> 54*cdf0e10cSrcweir #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx> 55*cdf0e10cSrcweir #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx> 56*cdf0e10cSrcweir #include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx> 57*cdf0e10cSrcweir #include <svl/ctloptions.hxx> 58*cdf0e10cSrcweir #include <vcl/svapp.hxx> 59*cdf0e10cSrcweir #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx> 60*cdf0e10cSrcweir #include <tools/diagnose_ex.h> 61*cdf0e10cSrcweir #include <vcl/metric.hxx> 62*cdf0e10cSrcweir #include <drawinglayer/primitive2d/textenumsprimitive2d.hxx> 63*cdf0e10cSrcweir #include <drawinglayer/primitive2d/epsprimitive2d.hxx> 64*cdf0e10cSrcweir #include <vcl/rendergraphicrasterizer.hxx> 65*cdf0e10cSrcweir 66*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 67*cdf0e10cSrcweir // control support 68*cdf0e10cSrcweir 69*cdf0e10cSrcweir #include <com/sun/star/awt/XWindow2.hpp> 70*cdf0e10cSrcweir #include <com/sun/star/awt/PosSize.hpp> 71*cdf0e10cSrcweir #include <com/sun/star/awt/XView.hpp> 72*cdf0e10cSrcweir #include <drawinglayer/primitive2d/controlprimitive2d.hxx> 73*cdf0e10cSrcweir #include <drawinglayer/primitive2d/textlayoutdevice.hxx> 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 76*cdf0e10cSrcweir // for test, can be removed again 77*cdf0e10cSrcweir 78*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygonclipper.hxx> 79*cdf0e10cSrcweir #include <basegfx/polygon/b2dtrapezoid.hxx> 80*cdf0e10cSrcweir 81*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 82*cdf0e10cSrcweir 83*cdf0e10cSrcweir using namespace com::sun::star; 84*cdf0e10cSrcweir 85*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 86*cdf0e10cSrcweir 87*cdf0e10cSrcweir namespace drawinglayer 88*cdf0e10cSrcweir { 89*cdf0e10cSrcweir namespace processor2d 90*cdf0e10cSrcweir { 91*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 92*cdf0e10cSrcweir // UNO class usages 93*cdf0e10cSrcweir using ::com::sun::star::uno::Reference; 94*cdf0e10cSrcweir using ::com::sun::star::uno::UNO_QUERY; 95*cdf0e10cSrcweir using ::com::sun::star::uno::UNO_QUERY_THROW; 96*cdf0e10cSrcweir using ::com::sun::star::uno::Exception; 97*cdf0e10cSrcweir using ::com::sun::star::awt::XView; 98*cdf0e10cSrcweir using ::com::sun::star::awt::XGraphics; 99*cdf0e10cSrcweir using ::com::sun::star::awt::XWindow; 100*cdf0e10cSrcweir using ::com::sun::star::awt::PosSize::POSSIZE; 101*cdf0e10cSrcweir 102*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 103*cdf0e10cSrcweir // rendering support 104*cdf0e10cSrcweir 105*cdf0e10cSrcweir // directdraw of text simple portion or decorated portion primitive. When decorated, all the extra 106*cdf0e10cSrcweir // information is translated to VCL parameters and set at the font. 107*cdf0e10cSrcweir // Acceptance is restricted to no shearing and positive scaling in X and Y (no font mirroring 108*cdf0e10cSrcweir // for VCL) 109*cdf0e10cSrcweir void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate) 110*cdf0e10cSrcweir { 111*cdf0e10cSrcweir // decompose matrix to have position and size of text 112*cdf0e10cSrcweir basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rTextCandidate.getTextTransform()); 113*cdf0e10cSrcweir basegfx::B2DVector aFontScaling, aTranslate; 114*cdf0e10cSrcweir double fRotate, fShearX; 115*cdf0e10cSrcweir aLocalTransform.decompose(aFontScaling, aTranslate, fRotate, fShearX); 116*cdf0e10cSrcweir bool bPrimitiveAccepted(false); 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir if(basegfx::fTools::equalZero(fShearX)) 119*cdf0e10cSrcweir { 120*cdf0e10cSrcweir if(basegfx::fTools::less(aFontScaling.getX(), 0.0) && basegfx::fTools::less(aFontScaling.getY(), 0.0)) 121*cdf0e10cSrcweir { 122*cdf0e10cSrcweir // handle special case: If scale is negative in (x,y) (3rd quadrant), it can 123*cdf0e10cSrcweir // be expressed as rotation by PI. Use this since the Font rendering will not 124*cdf0e10cSrcweir // apply the negative scales in any form 125*cdf0e10cSrcweir aFontScaling = basegfx::absolute(aFontScaling); 126*cdf0e10cSrcweir fRotate += F_PI; 127*cdf0e10cSrcweir } 128*cdf0e10cSrcweir 129*cdf0e10cSrcweir if(basegfx::fTools::more(aFontScaling.getX(), 0.0) && basegfx::fTools::more(aFontScaling.getY(), 0.0)) 130*cdf0e10cSrcweir { 131*cdf0e10cSrcweir // Get the VCL font (use FontHeight as FontWidth) 132*cdf0e10cSrcweir Font aFont(primitive2d::getVclFontFromFontAttribute( 133*cdf0e10cSrcweir rTextCandidate.getFontAttribute(), 134*cdf0e10cSrcweir aFontScaling.getX(), 135*cdf0e10cSrcweir aFontScaling.getY(), 136*cdf0e10cSrcweir fRotate, 137*cdf0e10cSrcweir rTextCandidate.getLocale())); 138*cdf0e10cSrcweir 139*cdf0e10cSrcweir // handle additional font attributes 140*cdf0e10cSrcweir const primitive2d::TextDecoratedPortionPrimitive2D* pTCPP = 141*cdf0e10cSrcweir dynamic_cast<const primitive2d::TextDecoratedPortionPrimitive2D*>( &rTextCandidate ); 142*cdf0e10cSrcweir 143*cdf0e10cSrcweir if( pTCPP != NULL ) 144*cdf0e10cSrcweir { 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir // set the color of text decorations 147*cdf0e10cSrcweir const basegfx::BColor aTextlineColor = maBColorModifierStack.getModifiedColor(pTCPP->getTextlineColor()); 148*cdf0e10cSrcweir mpOutputDevice->SetTextLineColor( Color(aTextlineColor) ); 149*cdf0e10cSrcweir 150*cdf0e10cSrcweir // set Overline attribute 151*cdf0e10cSrcweir const FontUnderline eFontOverline(primitive2d::mapTextLineToFontUnderline( pTCPP->getFontOverline() )); 152*cdf0e10cSrcweir if( eFontOverline != UNDERLINE_NONE ) 153*cdf0e10cSrcweir { 154*cdf0e10cSrcweir aFont.SetOverline( eFontOverline ); 155*cdf0e10cSrcweir const basegfx::BColor aOverlineColor = maBColorModifierStack.getModifiedColor(pTCPP->getOverlineColor()); 156*cdf0e10cSrcweir mpOutputDevice->SetOverlineColor( Color(aOverlineColor) ); 157*cdf0e10cSrcweir if( pTCPP->getWordLineMode() ) 158*cdf0e10cSrcweir aFont.SetWordLineMode( true ); 159*cdf0e10cSrcweir } 160*cdf0e10cSrcweir 161*cdf0e10cSrcweir // set Underline attribute 162*cdf0e10cSrcweir const FontUnderline eFontUnderline(primitive2d::mapTextLineToFontUnderline( pTCPP->getFontUnderline() )); 163*cdf0e10cSrcweir if( eFontUnderline != UNDERLINE_NONE ) 164*cdf0e10cSrcweir { 165*cdf0e10cSrcweir aFont.SetUnderline( eFontUnderline ); 166*cdf0e10cSrcweir if( pTCPP->getWordLineMode() ) 167*cdf0e10cSrcweir aFont.SetWordLineMode( true ); 168*cdf0e10cSrcweir //TODO: ??? if( pTCPP->getUnderlineAbove() ) 169*cdf0e10cSrcweir // aFont.SetUnderlineAbove( true ); 170*cdf0e10cSrcweir } 171*cdf0e10cSrcweir 172*cdf0e10cSrcweir // set Strikeout attribute 173*cdf0e10cSrcweir const FontStrikeout eFontStrikeout(primitive2d::mapTextStrikeoutToFontStrikeout(pTCPP->getTextStrikeout())); 174*cdf0e10cSrcweir 175*cdf0e10cSrcweir if( eFontStrikeout != STRIKEOUT_NONE ) 176*cdf0e10cSrcweir aFont.SetStrikeout( eFontStrikeout ); 177*cdf0e10cSrcweir 178*cdf0e10cSrcweir // set EmphasisMark attribute 179*cdf0e10cSrcweir FontEmphasisMark eFontEmphasisMark = EMPHASISMARK_NONE; 180*cdf0e10cSrcweir switch( pTCPP->getTextEmphasisMark() ) 181*cdf0e10cSrcweir { 182*cdf0e10cSrcweir default: 183*cdf0e10cSrcweir DBG_WARNING1( "DrawingLayer: Unknown EmphasisMark style (%d)!", pTCPP->getTextEmphasisMark() ); 184*cdf0e10cSrcweir // fall through 185*cdf0e10cSrcweir case primitive2d::TEXT_EMPHASISMARK_NONE: eFontEmphasisMark = EMPHASISMARK_NONE; break; 186*cdf0e10cSrcweir case primitive2d::TEXT_EMPHASISMARK_DOT: eFontEmphasisMark = EMPHASISMARK_DOT; break; 187*cdf0e10cSrcweir case primitive2d::TEXT_EMPHASISMARK_CIRCLE: eFontEmphasisMark = EMPHASISMARK_CIRCLE; break; 188*cdf0e10cSrcweir case primitive2d::TEXT_EMPHASISMARK_DISC: eFontEmphasisMark = EMPHASISMARK_DISC; break; 189*cdf0e10cSrcweir case primitive2d::TEXT_EMPHASISMARK_ACCENT: eFontEmphasisMark = EMPHASISMARK_ACCENT; break; 190*cdf0e10cSrcweir } 191*cdf0e10cSrcweir 192*cdf0e10cSrcweir if( eFontEmphasisMark != EMPHASISMARK_NONE ) 193*cdf0e10cSrcweir { 194*cdf0e10cSrcweir DBG_ASSERT( (pTCPP->getEmphasisMarkAbove() != pTCPP->getEmphasisMarkBelow()), 195*cdf0e10cSrcweir "DrawingLayer: Bad EmphasisMark position!" ); 196*cdf0e10cSrcweir if( pTCPP->getEmphasisMarkAbove() ) 197*cdf0e10cSrcweir eFontEmphasisMark |= EMPHASISMARK_POS_ABOVE; 198*cdf0e10cSrcweir else 199*cdf0e10cSrcweir eFontEmphasisMark |= EMPHASISMARK_POS_BELOW; 200*cdf0e10cSrcweir aFont.SetEmphasisMark( eFontEmphasisMark ); 201*cdf0e10cSrcweir } 202*cdf0e10cSrcweir 203*cdf0e10cSrcweir // set Relief attribute 204*cdf0e10cSrcweir FontRelief eFontRelief = RELIEF_NONE; 205*cdf0e10cSrcweir switch( pTCPP->getTextRelief() ) 206*cdf0e10cSrcweir { 207*cdf0e10cSrcweir default: 208*cdf0e10cSrcweir DBG_WARNING1( "DrawingLayer: Unknown Relief style (%d)!", pTCPP->getTextRelief() ); 209*cdf0e10cSrcweir // fall through 210*cdf0e10cSrcweir case primitive2d::TEXT_RELIEF_NONE: eFontRelief = RELIEF_NONE; break; 211*cdf0e10cSrcweir case primitive2d::TEXT_RELIEF_EMBOSSED: eFontRelief = RELIEF_EMBOSSED; break; 212*cdf0e10cSrcweir case primitive2d::TEXT_RELIEF_ENGRAVED: eFontRelief = RELIEF_ENGRAVED; break; 213*cdf0e10cSrcweir } 214*cdf0e10cSrcweir 215*cdf0e10cSrcweir if( eFontRelief != RELIEF_NONE ) 216*cdf0e10cSrcweir aFont.SetRelief( eFontRelief ); 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir // set Shadow attribute 219*cdf0e10cSrcweir if( pTCPP->getShadow() ) 220*cdf0e10cSrcweir aFont.SetShadow( true ); 221*cdf0e10cSrcweir } 222*cdf0e10cSrcweir 223*cdf0e10cSrcweir // create transformed integer DXArray in view coordinate system 224*cdf0e10cSrcweir ::std::vector< sal_Int32 > aTransformedDXArray; 225*cdf0e10cSrcweir 226*cdf0e10cSrcweir if(rTextCandidate.getDXArray().size()) 227*cdf0e10cSrcweir { 228*cdf0e10cSrcweir aTransformedDXArray.reserve(rTextCandidate.getDXArray().size()); 229*cdf0e10cSrcweir const basegfx::B2DVector aPixelVector(maCurrentTransformation * basegfx::B2DVector(1.0, 0.0)); 230*cdf0e10cSrcweir const double fPixelVectorFactor(aPixelVector.getLength()); 231*cdf0e10cSrcweir 232*cdf0e10cSrcweir for(::std::vector< double >::const_iterator aStart(rTextCandidate.getDXArray().begin()); 233*cdf0e10cSrcweir aStart != rTextCandidate.getDXArray().end(); aStart++) 234*cdf0e10cSrcweir { 235*cdf0e10cSrcweir aTransformedDXArray.push_back(basegfx::fround((*aStart) * fPixelVectorFactor)); 236*cdf0e10cSrcweir } 237*cdf0e10cSrcweir } 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir // set parameters and paint text snippet 240*cdf0e10cSrcweir const basegfx::BColor aRGBFontColor(maBColorModifierStack.getModifiedColor(rTextCandidate.getFontColor())); 241*cdf0e10cSrcweir const basegfx::B2DPoint aPoint(aLocalTransform * basegfx::B2DPoint(0.0, 0.0)); 242*cdf0e10cSrcweir const Point aStartPoint(basegfx::fround(aPoint.getX()), basegfx::fround(aPoint.getY())); 243*cdf0e10cSrcweir const sal_uInt32 nOldLayoutMode(mpOutputDevice->GetLayoutMode()); 244*cdf0e10cSrcweir 245*cdf0e10cSrcweir if(rTextCandidate.getFontAttribute().getRTL()) 246*cdf0e10cSrcweir { 247*cdf0e10cSrcweir sal_uInt32 nRTLLayoutMode(nOldLayoutMode & ~(TEXT_LAYOUT_COMPLEX_DISABLED|TEXT_LAYOUT_BIDI_STRONG)); 248*cdf0e10cSrcweir nRTLLayoutMode |= TEXT_LAYOUT_BIDI_RTL|TEXT_LAYOUT_TEXTORIGIN_LEFT; 249*cdf0e10cSrcweir mpOutputDevice->SetLayoutMode(nRTLLayoutMode); 250*cdf0e10cSrcweir } 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir mpOutputDevice->SetFont(aFont); 253*cdf0e10cSrcweir mpOutputDevice->SetTextColor(Color(aRGBFontColor)); 254*cdf0e10cSrcweir 255*cdf0e10cSrcweir if(aTransformedDXArray.size()) 256*cdf0e10cSrcweir { 257*cdf0e10cSrcweir mpOutputDevice->DrawTextArray( 258*cdf0e10cSrcweir aStartPoint, 259*cdf0e10cSrcweir rTextCandidate.getText(), 260*cdf0e10cSrcweir &(aTransformedDXArray[0]), 261*cdf0e10cSrcweir rTextCandidate.getTextPosition(), 262*cdf0e10cSrcweir rTextCandidate.getTextLength()); 263*cdf0e10cSrcweir } 264*cdf0e10cSrcweir else 265*cdf0e10cSrcweir { 266*cdf0e10cSrcweir mpOutputDevice->DrawText( 267*cdf0e10cSrcweir aStartPoint, 268*cdf0e10cSrcweir rTextCandidate.getText(), 269*cdf0e10cSrcweir rTextCandidate.getTextPosition(), 270*cdf0e10cSrcweir rTextCandidate.getTextLength()); 271*cdf0e10cSrcweir } 272*cdf0e10cSrcweir 273*cdf0e10cSrcweir if(rTextCandidate.getFontAttribute().getRTL()) 274*cdf0e10cSrcweir { 275*cdf0e10cSrcweir mpOutputDevice->SetLayoutMode(nOldLayoutMode); 276*cdf0e10cSrcweir } 277*cdf0e10cSrcweir 278*cdf0e10cSrcweir bPrimitiveAccepted = true; 279*cdf0e10cSrcweir } 280*cdf0e10cSrcweir } 281*cdf0e10cSrcweir 282*cdf0e10cSrcweir if(!bPrimitiveAccepted) 283*cdf0e10cSrcweir { 284*cdf0e10cSrcweir // let break down 285*cdf0e10cSrcweir process(rTextCandidate.get2DDecomposition(getViewInformation2D())); 286*cdf0e10cSrcweir } 287*cdf0e10cSrcweir } 288*cdf0e10cSrcweir 289*cdf0e10cSrcweir // direct draw of hairline 290*cdf0e10cSrcweir void VclProcessor2D::RenderPolygonHairlinePrimitive2D(const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate, bool bPixelBased) 291*cdf0e10cSrcweir { 292*cdf0e10cSrcweir const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor())); 293*cdf0e10cSrcweir mpOutputDevice->SetLineColor(Color(aHairlineColor)); 294*cdf0e10cSrcweir mpOutputDevice->SetFillColor(); 295*cdf0e10cSrcweir 296*cdf0e10cSrcweir basegfx::B2DPolygon aLocalPolygon(rPolygonCandidate.getB2DPolygon()); 297*cdf0e10cSrcweir aLocalPolygon.transform(maCurrentTransformation); 298*cdf0e10cSrcweir 299*cdf0e10cSrcweir static bool bCheckTrapezoidDecomposition(false); 300*cdf0e10cSrcweir static bool bShowOutlinesThere(false); 301*cdf0e10cSrcweir if(bCheckTrapezoidDecomposition) 302*cdf0e10cSrcweir { 303*cdf0e10cSrcweir // clip against discrete ViewPort 304*cdf0e10cSrcweir const basegfx::B2DRange& rDiscreteViewport = getViewInformation2D().getDiscreteViewport(); 305*cdf0e10cSrcweir basegfx::B2DPolyPolygon aLocalPolyPolygon(basegfx::tools::clipPolygonOnRange( 306*cdf0e10cSrcweir aLocalPolygon, rDiscreteViewport, true, false)); 307*cdf0e10cSrcweir 308*cdf0e10cSrcweir if(aLocalPolyPolygon.count()) 309*cdf0e10cSrcweir { 310*cdf0e10cSrcweir // subdivide 311*cdf0e10cSrcweir aLocalPolyPolygon = basegfx::tools::adaptiveSubdivideByDistance( 312*cdf0e10cSrcweir aLocalPolyPolygon, 0.5); 313*cdf0e10cSrcweir 314*cdf0e10cSrcweir // trapezoidize 315*cdf0e10cSrcweir static double fLineWidth(2.0); 316*cdf0e10cSrcweir basegfx::B2DTrapezoidVector aB2DTrapezoidVector; 317*cdf0e10cSrcweir basegfx::tools::createLineTrapezoidFromB2DPolyPolygon(aB2DTrapezoidVector, aLocalPolyPolygon, fLineWidth); 318*cdf0e10cSrcweir 319*cdf0e10cSrcweir const sal_uInt32 nCount(aB2DTrapezoidVector.size()); 320*cdf0e10cSrcweir 321*cdf0e10cSrcweir if(nCount) 322*cdf0e10cSrcweir { 323*cdf0e10cSrcweir basegfx::BColor aInvPolygonColor(aHairlineColor); 324*cdf0e10cSrcweir aInvPolygonColor.invert(); 325*cdf0e10cSrcweir 326*cdf0e10cSrcweir for(sal_uInt32 a(0); a < nCount; a++) 327*cdf0e10cSrcweir { 328*cdf0e10cSrcweir const basegfx::B2DPolygon aTempPolygon(aB2DTrapezoidVector[a].getB2DPolygon()); 329*cdf0e10cSrcweir 330*cdf0e10cSrcweir if(bShowOutlinesThere) 331*cdf0e10cSrcweir { 332*cdf0e10cSrcweir mpOutputDevice->SetFillColor(Color(aHairlineColor)); 333*cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 334*cdf0e10cSrcweir } 335*cdf0e10cSrcweir 336*cdf0e10cSrcweir mpOutputDevice->DrawPolygon(aTempPolygon); 337*cdf0e10cSrcweir 338*cdf0e10cSrcweir if(bShowOutlinesThere) 339*cdf0e10cSrcweir { 340*cdf0e10cSrcweir mpOutputDevice->SetFillColor(); 341*cdf0e10cSrcweir mpOutputDevice->SetLineColor(Color(aInvPolygonColor)); 342*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aTempPolygon, 0.0); 343*cdf0e10cSrcweir } 344*cdf0e10cSrcweir } 345*cdf0e10cSrcweir } 346*cdf0e10cSrcweir } 347*cdf0e10cSrcweir } 348*cdf0e10cSrcweir else 349*cdf0e10cSrcweir { 350*cdf0e10cSrcweir if(bPixelBased && getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete()) 351*cdf0e10cSrcweir { 352*cdf0e10cSrcweir // #i98289# 353*cdf0e10cSrcweir // when a Hairline is painted and AntiAliasing is on the option SnapHorVerLinesToDiscrete 354*cdf0e10cSrcweir // allows to suppress AntiAliasing for pure horizontal or vertical lines. This is done since 355*cdf0e10cSrcweir // not-AntiAliased such lines look more pleasing to the eye (e.g. 2D chart content). This 356*cdf0e10cSrcweir // NEEDS to be done in discrete coordinates, so only useful for pixel based rendering. 357*cdf0e10cSrcweir aLocalPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aLocalPolygon); 358*cdf0e10cSrcweir } 359*cdf0e10cSrcweir 360*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aLocalPolygon, 0.0); 361*cdf0e10cSrcweir } 362*cdf0e10cSrcweir } 363*cdf0e10cSrcweir 364*cdf0e10cSrcweir // direct draw of transformed BitmapEx primitive 365*cdf0e10cSrcweir void VclProcessor2D::RenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate) 366*cdf0e10cSrcweir { 367*cdf0e10cSrcweir // create local transform 368*cdf0e10cSrcweir basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rBitmapCandidate.getTransform()); 369*cdf0e10cSrcweir BitmapEx aBitmapEx(rBitmapCandidate.getBitmapEx()); 370*cdf0e10cSrcweir bool bPainted(false); 371*cdf0e10cSrcweir 372*cdf0e10cSrcweir if(maBColorModifierStack.count()) 373*cdf0e10cSrcweir { 374*cdf0e10cSrcweir aBitmapEx = impModifyBitmapEx(maBColorModifierStack, aBitmapEx); 375*cdf0e10cSrcweir 376*cdf0e10cSrcweir if(aBitmapEx.IsEmpty()) 377*cdf0e10cSrcweir { 378*cdf0e10cSrcweir // color gets completely replaced, get it 379*cdf0e10cSrcweir const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor())); 380*cdf0e10cSrcweir basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon()); 381*cdf0e10cSrcweir aPolygon.transform(aLocalTransform); 382*cdf0e10cSrcweir 383*cdf0e10cSrcweir mpOutputDevice->SetFillColor(Color(aModifiedColor)); 384*cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 385*cdf0e10cSrcweir mpOutputDevice->DrawPolygon(aPolygon); 386*cdf0e10cSrcweir 387*cdf0e10cSrcweir bPainted = true; 388*cdf0e10cSrcweir } 389*cdf0e10cSrcweir } 390*cdf0e10cSrcweir 391*cdf0e10cSrcweir if(!bPainted) 392*cdf0e10cSrcweir { 393*cdf0e10cSrcweir static bool bForceUseOfOwnTransformer(false); 394*cdf0e10cSrcweir static bool bUseGraphicManager(true); 395*cdf0e10cSrcweir 396*cdf0e10cSrcweir // decompose matrix to check for shear, rotate and mirroring 397*cdf0e10cSrcweir basegfx::B2DVector aScale, aTranslate; 398*cdf0e10cSrcweir double fRotate, fShearX; 399*cdf0e10cSrcweir aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX); 400*cdf0e10cSrcweir 401*cdf0e10cSrcweir if(!bForceUseOfOwnTransformer && basegfx::fTools::equalZero(fShearX)) 402*cdf0e10cSrcweir { 403*cdf0e10cSrcweir if(!bUseGraphicManager && basegfx::fTools::equalZero(fRotate)) 404*cdf0e10cSrcweir { 405*cdf0e10cSrcweir RenderBitmapPrimitive2D_BitmapEx(*mpOutputDevice, aBitmapEx, aLocalTransform); 406*cdf0e10cSrcweir } 407*cdf0e10cSrcweir else 408*cdf0e10cSrcweir { 409*cdf0e10cSrcweir RenderBitmapPrimitive2D_GraphicManager(*mpOutputDevice, aBitmapEx, aLocalTransform); 410*cdf0e10cSrcweir } 411*cdf0e10cSrcweir } 412*cdf0e10cSrcweir else 413*cdf0e10cSrcweir { 414*cdf0e10cSrcweir if(!aBitmapEx.IsTransparent() && (!basegfx::fTools::equalZero(fShearX) || !basegfx::fTools::equalZero(fRotate))) 415*cdf0e10cSrcweir { 416*cdf0e10cSrcweir // parts will be uncovered, extend aBitmapEx with a mask bitmap 417*cdf0e10cSrcweir const Bitmap aContent(aBitmapEx.GetBitmap()); 418*cdf0e10cSrcweir aBitmapEx = BitmapEx(aContent, Bitmap(aContent.GetSizePixel(), 1)); 419*cdf0e10cSrcweir } 420*cdf0e10cSrcweir 421*cdf0e10cSrcweir RenderBitmapPrimitive2D_self(*mpOutputDevice, aBitmapEx, aLocalTransform); 422*cdf0e10cSrcweir } 423*cdf0e10cSrcweir } 424*cdf0e10cSrcweir } 425*cdf0e10cSrcweir 426*cdf0e10cSrcweir void VclProcessor2D::RenderRenderGraphicPrimitive2D(const primitive2d::RenderGraphicPrimitive2D& rRenderGraphicCandidate) 427*cdf0e10cSrcweir { 428*cdf0e10cSrcweir // create local transform 429*cdf0e10cSrcweir basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rRenderGraphicCandidate.getTransform()); 430*cdf0e10cSrcweir vcl::RenderGraphic aRenderGraphic(rRenderGraphicCandidate.getRenderGraphic()); 431*cdf0e10cSrcweir bool bPainted(false); 432*cdf0e10cSrcweir 433*cdf0e10cSrcweir if(maBColorModifierStack.count()) 434*cdf0e10cSrcweir { 435*cdf0e10cSrcweir // !!! TODO 436*cdf0e10cSrcweir // aRenderGraphic = impModifyRenderGraphic(maBColorModifierStack, aRenderGraphic); 437*cdf0e10cSrcweir 438*cdf0e10cSrcweir if(aRenderGraphic.IsEmpty()) 439*cdf0e10cSrcweir { 440*cdf0e10cSrcweir // color gets completely replaced, get it 441*cdf0e10cSrcweir const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor())); 442*cdf0e10cSrcweir basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon()); 443*cdf0e10cSrcweir aPolygon.transform(aLocalTransform); 444*cdf0e10cSrcweir 445*cdf0e10cSrcweir mpOutputDevice->SetFillColor(Color(aModifiedColor)); 446*cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 447*cdf0e10cSrcweir mpOutputDevice->DrawPolygon(aPolygon); 448*cdf0e10cSrcweir 449*cdf0e10cSrcweir bPainted = true; 450*cdf0e10cSrcweir } 451*cdf0e10cSrcweir } 452*cdf0e10cSrcweir 453*cdf0e10cSrcweir if(!bPainted) 454*cdf0e10cSrcweir { 455*cdf0e10cSrcweir // decompose matrix to check for shear, rotate and mirroring 456*cdf0e10cSrcweir basegfx::B2DVector aScale, aTranslate; 457*cdf0e10cSrcweir double fRotate, fShearX; 458*cdf0e10cSrcweir aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX); 459*cdf0e10cSrcweir 460*cdf0e10cSrcweir basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0); 461*cdf0e10cSrcweir 462*cdf0e10cSrcweir if( basegfx::fTools::equalZero( fRotate ) ) 463*cdf0e10cSrcweir { 464*cdf0e10cSrcweir aOutlineRange.transform( aLocalTransform ); 465*cdf0e10cSrcweir } 466*cdf0e10cSrcweir else 467*cdf0e10cSrcweir { 468*cdf0e10cSrcweir // !!! TODO 469*cdf0e10cSrcweir // if rotated, create the unrotated output rectangle for the GraphicManager paint 470*cdf0e10cSrcweir /* 471*cdf0e10cSrcweir const basegfx::B2DHomMatrix aSimpleObjectMatrix(basegfx::tools::createScaleTranslateB2DHomMatrix( 472*cdf0e10cSrcweir fabs(aScale.getX()), fabs(aScale.getY()), 473*cdf0e10cSrcweir aTranslate.getX(), aTranslate.getY())); 474*cdf0e10cSrcweir 475*cdf0e10cSrcweir aOutlineRange.transform(aSimpleObjectMatrix); 476*cdf0e10cSrcweir */ 477*cdf0e10cSrcweir } 478*cdf0e10cSrcweir 479*cdf0e10cSrcweir // prepare dest coordinates 480*cdf0e10cSrcweir const Point aPoint( basegfx::fround(aOutlineRange.getMinX() ), 481*cdf0e10cSrcweir basegfx::fround(aOutlineRange.getMinY() ) ); 482*cdf0e10cSrcweir const Size aSize( basegfx::fround(aOutlineRange.getWidth() ), 483*cdf0e10cSrcweir basegfx::fround(aOutlineRange.getHeight() ) ); 484*cdf0e10cSrcweir const Size aSizePixel( mpOutputDevice->LogicToPixel( aSize ) ); 485*cdf0e10cSrcweir const vcl::RenderGraphicRasterizer aRasterizer( aRenderGraphic ); 486*cdf0e10cSrcweir const BitmapEx aBitmapEx( aRasterizer.Rasterize( aSizePixel, fRotate, fShearX ) ); 487*cdf0e10cSrcweir 488*cdf0e10cSrcweir if( !aBitmapEx.IsEmpty() ) 489*cdf0e10cSrcweir { 490*cdf0e10cSrcweir mpOutputDevice->DrawBitmapEx( aPoint, aSize, aBitmapEx ); 491*cdf0e10cSrcweir } 492*cdf0e10cSrcweir } 493*cdf0e10cSrcweir } 494*cdf0e10cSrcweir 495*cdf0e10cSrcweir void VclProcessor2D::RenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapCandidate) 496*cdf0e10cSrcweir { 497*cdf0e10cSrcweir const attribute::FillBitmapAttribute& rFillBitmapAttribute(rFillBitmapCandidate.getFillBitmap()); 498*cdf0e10cSrcweir bool bPrimitiveAccepted(false); 499*cdf0e10cSrcweir 500*cdf0e10cSrcweir if(rFillBitmapAttribute.getTiling()) 501*cdf0e10cSrcweir { 502*cdf0e10cSrcweir // decompose matrix to check for shear, rotate and mirroring 503*cdf0e10cSrcweir basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rFillBitmapCandidate.getTransformation()); 504*cdf0e10cSrcweir basegfx::B2DVector aScale, aTranslate; 505*cdf0e10cSrcweir double fRotate, fShearX; 506*cdf0e10cSrcweir aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX); 507*cdf0e10cSrcweir 508*cdf0e10cSrcweir if(basegfx::fTools::equalZero(fRotate) && basegfx::fTools::equalZero(fShearX)) 509*cdf0e10cSrcweir { 510*cdf0e10cSrcweir // no shear or rotate, draw direct in pixel coordinates 511*cdf0e10cSrcweir bPrimitiveAccepted = true; 512*cdf0e10cSrcweir BitmapEx aBitmapEx(rFillBitmapAttribute.getBitmapEx()); 513*cdf0e10cSrcweir bool bPainted(false); 514*cdf0e10cSrcweir 515*cdf0e10cSrcweir if(maBColorModifierStack.count()) 516*cdf0e10cSrcweir { 517*cdf0e10cSrcweir aBitmapEx = impModifyBitmapEx(maBColorModifierStack, aBitmapEx); 518*cdf0e10cSrcweir 519*cdf0e10cSrcweir if(aBitmapEx.IsEmpty()) 520*cdf0e10cSrcweir { 521*cdf0e10cSrcweir // color gets completely replaced, get it 522*cdf0e10cSrcweir const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor())); 523*cdf0e10cSrcweir basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon()); 524*cdf0e10cSrcweir aPolygon.transform(aLocalTransform); 525*cdf0e10cSrcweir 526*cdf0e10cSrcweir mpOutputDevice->SetFillColor(Color(aModifiedColor)); 527*cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 528*cdf0e10cSrcweir mpOutputDevice->DrawPolygon(aPolygon); 529*cdf0e10cSrcweir 530*cdf0e10cSrcweir bPainted = true; 531*cdf0e10cSrcweir } 532*cdf0e10cSrcweir } 533*cdf0e10cSrcweir 534*cdf0e10cSrcweir if(!bPainted) 535*cdf0e10cSrcweir { 536*cdf0e10cSrcweir const basegfx::B2DPoint aObjTopLeft(aTranslate.getX(), aTranslate.getY()); 537*cdf0e10cSrcweir const basegfx::B2DPoint aObjBottomRight(aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY()); 538*cdf0e10cSrcweir const Point aObjTL(mpOutputDevice->LogicToPixel(Point((sal_Int32)aObjTopLeft.getX(), (sal_Int32)aObjTopLeft.getY()))); 539*cdf0e10cSrcweir const Point aObjBR(mpOutputDevice->LogicToPixel(Point((sal_Int32)aObjBottomRight.getX(), (sal_Int32)aObjBottomRight.getY()))); 540*cdf0e10cSrcweir 541*cdf0e10cSrcweir const basegfx::B2DPoint aBmpTopLeft(aLocalTransform * rFillBitmapAttribute.getTopLeft()); 542*cdf0e10cSrcweir const basegfx::B2DPoint aBmpBottomRight(aLocalTransform * basegfx::B2DPoint(rFillBitmapAttribute.getTopLeft() + rFillBitmapAttribute.getSize())); 543*cdf0e10cSrcweir const Point aBmpTL(mpOutputDevice->LogicToPixel(Point((sal_Int32)aBmpTopLeft.getX(), (sal_Int32)aBmpTopLeft.getY()))); 544*cdf0e10cSrcweir const Point aBmpBR(mpOutputDevice->LogicToPixel(Point((sal_Int32)aBmpBottomRight.getX(), (sal_Int32)aBmpBottomRight.getY()))); 545*cdf0e10cSrcweir 546*cdf0e10cSrcweir sal_Int32 nOWidth(aObjBR.X() - aObjTL.X()); 547*cdf0e10cSrcweir sal_Int32 nOHeight(aObjBR.Y() - aObjTL.Y()); 548*cdf0e10cSrcweir 549*cdf0e10cSrcweir // only do something when object has a size in discrete units 550*cdf0e10cSrcweir if(nOWidth > 0 && nOHeight > 0) 551*cdf0e10cSrcweir { 552*cdf0e10cSrcweir sal_Int32 nBWidth(aBmpBR.X() - aBmpTL.X()); 553*cdf0e10cSrcweir sal_Int32 nBHeight(aBmpBR.Y() - aBmpTL.Y()); 554*cdf0e10cSrcweir 555*cdf0e10cSrcweir // only do something when bitmap fill has a size in discrete units 556*cdf0e10cSrcweir if(nBWidth > 0 && nBHeight > 0) 557*cdf0e10cSrcweir { 558*cdf0e10cSrcweir sal_Int32 nBLeft(aBmpTL.X()); 559*cdf0e10cSrcweir sal_Int32 nBTop(aBmpTL.Y()); 560*cdf0e10cSrcweir 561*cdf0e10cSrcweir if(nBLeft > aObjTL.X()) 562*cdf0e10cSrcweir { 563*cdf0e10cSrcweir nBLeft -= ((nBLeft / nBWidth) + 1L) * nBWidth; 564*cdf0e10cSrcweir } 565*cdf0e10cSrcweir 566*cdf0e10cSrcweir if(nBLeft + nBWidth <= aObjTL.X()) 567*cdf0e10cSrcweir { 568*cdf0e10cSrcweir nBLeft -= (nBLeft / nBWidth) * nBWidth; 569*cdf0e10cSrcweir } 570*cdf0e10cSrcweir 571*cdf0e10cSrcweir if(nBTop > aObjTL.Y()) 572*cdf0e10cSrcweir { 573*cdf0e10cSrcweir nBTop -= ((nBTop / nBHeight) + 1L) * nBHeight; 574*cdf0e10cSrcweir } 575*cdf0e10cSrcweir 576*cdf0e10cSrcweir if(nBTop + nBHeight <= aObjTL.Y()) 577*cdf0e10cSrcweir { 578*cdf0e10cSrcweir nBTop -= (nBTop / nBHeight) * nBHeight; 579*cdf0e10cSrcweir } 580*cdf0e10cSrcweir 581*cdf0e10cSrcweir // nBWidth, nBHeight is the pixel size of the neede bitmap. To not need to scale it 582*cdf0e10cSrcweir // in vcl many times, create a size-optimized version 583*cdf0e10cSrcweir const Size aNeededBitmapSizePixel(nBWidth, nBHeight); 584*cdf0e10cSrcweir 585*cdf0e10cSrcweir if(aNeededBitmapSizePixel != aBitmapEx.GetSizePixel()) 586*cdf0e10cSrcweir { 587*cdf0e10cSrcweir aBitmapEx.Scale(aNeededBitmapSizePixel); 588*cdf0e10cSrcweir } 589*cdf0e10cSrcweir 590*cdf0e10cSrcweir // prepare OutDev 591*cdf0e10cSrcweir const Point aEmptyPoint(0, 0); 592*cdf0e10cSrcweir const Rectangle aVisiblePixel(aEmptyPoint, mpOutputDevice->GetOutputSizePixel()); 593*cdf0e10cSrcweir const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled()); 594*cdf0e10cSrcweir mpOutputDevice->EnableMapMode(false); 595*cdf0e10cSrcweir 596*cdf0e10cSrcweir for(sal_Int32 nXPos(nBLeft); nXPos < aObjTL.X() + nOWidth; nXPos += nBWidth) 597*cdf0e10cSrcweir { 598*cdf0e10cSrcweir for(sal_Int32 nYPos(nBTop); nYPos < aObjTL.Y() + nOHeight; nYPos += nBHeight) 599*cdf0e10cSrcweir { 600*cdf0e10cSrcweir const Rectangle aOutRectPixel(Point(nXPos, nYPos), aNeededBitmapSizePixel); 601*cdf0e10cSrcweir 602*cdf0e10cSrcweir if(aOutRectPixel.IsOver(aVisiblePixel)) 603*cdf0e10cSrcweir { 604*cdf0e10cSrcweir mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmapEx); 605*cdf0e10cSrcweir } 606*cdf0e10cSrcweir } 607*cdf0e10cSrcweir } 608*cdf0e10cSrcweir 609*cdf0e10cSrcweir // restore OutDev 610*cdf0e10cSrcweir mpOutputDevice->EnableMapMode(bWasEnabled); 611*cdf0e10cSrcweir } 612*cdf0e10cSrcweir } 613*cdf0e10cSrcweir } 614*cdf0e10cSrcweir } 615*cdf0e10cSrcweir } 616*cdf0e10cSrcweir 617*cdf0e10cSrcweir if(!bPrimitiveAccepted) 618*cdf0e10cSrcweir { 619*cdf0e10cSrcweir // do not accept, use decomposition 620*cdf0e10cSrcweir process(rFillBitmapCandidate.get2DDecomposition(getViewInformation2D())); 621*cdf0e10cSrcweir } 622*cdf0e10cSrcweir } 623*cdf0e10cSrcweir 624*cdf0e10cSrcweir // direct draw of gradient 625*cdf0e10cSrcweir void VclProcessor2D::RenderPolyPolygonGradientPrimitive2D(const primitive2d::PolyPolygonGradientPrimitive2D& rPolygonCandidate) 626*cdf0e10cSrcweir { 627*cdf0e10cSrcweir const attribute::FillGradientAttribute& rGradient(rPolygonCandidate.getFillGradient()); 628*cdf0e10cSrcweir basegfx::BColor aStartColor(maBColorModifierStack.getModifiedColor(rGradient.getStartColor())); 629*cdf0e10cSrcweir basegfx::BColor aEndColor(maBColorModifierStack.getModifiedColor(rGradient.getEndColor())); 630*cdf0e10cSrcweir basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon()); 631*cdf0e10cSrcweir 632*cdf0e10cSrcweir if(aLocalPolyPolygon.count()) 633*cdf0e10cSrcweir { 634*cdf0e10cSrcweir aLocalPolyPolygon.transform(maCurrentTransformation); 635*cdf0e10cSrcweir 636*cdf0e10cSrcweir if(aStartColor == aEndColor) 637*cdf0e10cSrcweir { 638*cdf0e10cSrcweir // no gradient at all, draw as polygon in AA and non-AA case 639*cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 640*cdf0e10cSrcweir mpOutputDevice->SetFillColor(Color(aStartColor)); 641*cdf0e10cSrcweir mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon); 642*cdf0e10cSrcweir } 643*cdf0e10cSrcweir else if(getOptionsDrawinglayer().IsAntiAliasing()) 644*cdf0e10cSrcweir { 645*cdf0e10cSrcweir // For AA, direct render has to be avoided since it uses XOR maskings which will not 646*cdf0e10cSrcweir // work with AA. Instead, the decompose which uses MaskPrimitive2D with fillings is 647*cdf0e10cSrcweir // used 648*cdf0e10cSrcweir process(rPolygonCandidate.get2DDecomposition(getViewInformation2D())); 649*cdf0e10cSrcweir } 650*cdf0e10cSrcweir else 651*cdf0e10cSrcweir { 652*cdf0e10cSrcweir impDrawGradientToOutDev( 653*cdf0e10cSrcweir *mpOutputDevice, aLocalPolyPolygon, rGradient.getStyle(), rGradient.getSteps(), 654*cdf0e10cSrcweir aStartColor, aEndColor, rGradient.getBorder(), 655*cdf0e10cSrcweir rGradient.getAngle(), rGradient.getOffsetX(), rGradient.getOffsetY(), false); 656*cdf0e10cSrcweir } 657*cdf0e10cSrcweir } 658*cdf0e10cSrcweir } 659*cdf0e10cSrcweir 660*cdf0e10cSrcweir // direct draw of bitmap 661*cdf0e10cSrcweir void VclProcessor2D::RenderPolyPolygonBitmapPrimitive2D(const primitive2d::PolyPolygonBitmapPrimitive2D& rPolygonCandidate) 662*cdf0e10cSrcweir { 663*cdf0e10cSrcweir bool bDone(false); 664*cdf0e10cSrcweir const basegfx::B2DPolyPolygon& rPolyPolygon = rPolygonCandidate.getB2DPolyPolygon(); 665*cdf0e10cSrcweir 666*cdf0e10cSrcweir if(rPolyPolygon.count()) 667*cdf0e10cSrcweir { 668*cdf0e10cSrcweir const attribute::FillBitmapAttribute& rFillBitmapAttribute = rPolygonCandidate.getFillBitmap(); 669*cdf0e10cSrcweir const BitmapEx& rBitmapEx = rFillBitmapAttribute.getBitmapEx(); 670*cdf0e10cSrcweir 671*cdf0e10cSrcweir if(rBitmapEx.IsEmpty()) 672*cdf0e10cSrcweir { 673*cdf0e10cSrcweir // empty bitmap, done 674*cdf0e10cSrcweir bDone = true; 675*cdf0e10cSrcweir } 676*cdf0e10cSrcweir else 677*cdf0e10cSrcweir { 678*cdf0e10cSrcweir // try to catch cases where the bitmap will be color-modified to a single 679*cdf0e10cSrcweir // color (e.g. shadow). This would NOT be optimizable with an transparence channel 680*cdf0e10cSrcweir // at the Bitmap which we do not have here. When this should change, this 681*cdf0e10cSrcweir // optimization has to be reworked accordingly. 682*cdf0e10cSrcweir const sal_uInt32 nBColorModifierStackCount(maBColorModifierStack.count()); 683*cdf0e10cSrcweir 684*cdf0e10cSrcweir if(nBColorModifierStackCount) 685*cdf0e10cSrcweir { 686*cdf0e10cSrcweir const basegfx::BColorModifier& rTopmostModifier = maBColorModifierStack.getBColorModifier(nBColorModifierStackCount - 1); 687*cdf0e10cSrcweir 688*cdf0e10cSrcweir if(basegfx::BCOLORMODIFYMODE_REPLACE == rTopmostModifier.getMode()) 689*cdf0e10cSrcweir { 690*cdf0e10cSrcweir // the bitmap fill is in unified color, so we can replace it with 691*cdf0e10cSrcweir // a single polygon fill. The form of the fill depends on tiling 692*cdf0e10cSrcweir if(rFillBitmapAttribute.getTiling()) 693*cdf0e10cSrcweir { 694*cdf0e10cSrcweir // with tiling, fill the whole PolyPolygon with the modifier color 695*cdf0e10cSrcweir basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolyPolygon); 696*cdf0e10cSrcweir 697*cdf0e10cSrcweir aLocalPolyPolygon.transform(maCurrentTransformation); 698*cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 699*cdf0e10cSrcweir mpOutputDevice->SetFillColor(Color(rTopmostModifier.getBColor())); 700*cdf0e10cSrcweir mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon); 701*cdf0e10cSrcweir } 702*cdf0e10cSrcweir else 703*cdf0e10cSrcweir { 704*cdf0e10cSrcweir // without tiling, only the area common to the bitmap tile and the 705*cdf0e10cSrcweir // PolyPolygon is filled. Create the bitmap tile area in object 706*cdf0e10cSrcweir // coordinates. For this, the object transformation needs to be created 707*cdf0e10cSrcweir // from the already scaled PolyPolygon. The tile area in object 708*cdf0e10cSrcweir // coordinates wil always be non-rotated, so it's not necessary to 709*cdf0e10cSrcweir // work with a polygon here 710*cdf0e10cSrcweir basegfx::B2DRange aTileRange(rFillBitmapAttribute.getTopLeft(), 711*cdf0e10cSrcweir rFillBitmapAttribute.getTopLeft() + rFillBitmapAttribute.getSize()); 712*cdf0e10cSrcweir const basegfx::B2DRange aPolyPolygonRange(rPolyPolygon.getB2DRange()); 713*cdf0e10cSrcweir basegfx::B2DHomMatrix aNewObjectTransform; 714*cdf0e10cSrcweir 715*cdf0e10cSrcweir aNewObjectTransform.set(0, 0, aPolyPolygonRange.getWidth()); 716*cdf0e10cSrcweir aNewObjectTransform.set(1, 1, aPolyPolygonRange.getHeight()); 717*cdf0e10cSrcweir aNewObjectTransform.set(0, 2, aPolyPolygonRange.getMinX()); 718*cdf0e10cSrcweir aNewObjectTransform.set(1, 2, aPolyPolygonRange.getMinY()); 719*cdf0e10cSrcweir aTileRange.transform(aNewObjectTransform); 720*cdf0e10cSrcweir 721*cdf0e10cSrcweir // now clip the object polyPolygon against the tile range 722*cdf0e10cSrcweir // to get the common area (OR) 723*cdf0e10cSrcweir basegfx::B2DPolyPolygon aTarget = basegfx::tools::clipPolyPolygonOnRange(rPolyPolygon, aTileRange, true, false); 724*cdf0e10cSrcweir 725*cdf0e10cSrcweir if(aTarget.count()) 726*cdf0e10cSrcweir { 727*cdf0e10cSrcweir aTarget.transform(maCurrentTransformation); 728*cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 729*cdf0e10cSrcweir mpOutputDevice->SetFillColor(Color(rTopmostModifier.getBColor())); 730*cdf0e10cSrcweir mpOutputDevice->DrawPolyPolygon(aTarget); 731*cdf0e10cSrcweir } 732*cdf0e10cSrcweir } 733*cdf0e10cSrcweir 734*cdf0e10cSrcweir bDone = true; 735*cdf0e10cSrcweir } 736*cdf0e10cSrcweir } 737*cdf0e10cSrcweir } 738*cdf0e10cSrcweir } 739*cdf0e10cSrcweir else 740*cdf0e10cSrcweir { 741*cdf0e10cSrcweir // empty polyPolygon, done 742*cdf0e10cSrcweir bDone = true; 743*cdf0e10cSrcweir } 744*cdf0e10cSrcweir 745*cdf0e10cSrcweir if(!bDone) 746*cdf0e10cSrcweir { 747*cdf0e10cSrcweir // use default decomposition 748*cdf0e10cSrcweir process(rPolygonCandidate.get2DDecomposition(getViewInformation2D())); 749*cdf0e10cSrcweir } 750*cdf0e10cSrcweir } 751*cdf0e10cSrcweir 752*cdf0e10cSrcweir // direct draw of PolyPolygon with color 753*cdf0e10cSrcweir void VclProcessor2D::RenderPolyPolygonColorPrimitive2D(const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate) 754*cdf0e10cSrcweir { 755*cdf0e10cSrcweir const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor())); 756*cdf0e10cSrcweir mpOutputDevice->SetFillColor(Color(aPolygonColor)); 757*cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 758*cdf0e10cSrcweir 759*cdf0e10cSrcweir basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon()); 760*cdf0e10cSrcweir aLocalPolyPolygon.transform(maCurrentTransformation); 761*cdf0e10cSrcweir 762*cdf0e10cSrcweir static bool bCheckTrapezoidDecomposition(false); 763*cdf0e10cSrcweir static bool bShowOutlinesThere(false); 764*cdf0e10cSrcweir if(bCheckTrapezoidDecomposition) 765*cdf0e10cSrcweir { 766*cdf0e10cSrcweir // clip against discrete ViewPort 767*cdf0e10cSrcweir const basegfx::B2DRange& rDiscreteViewport = getViewInformation2D().getDiscreteViewport(); 768*cdf0e10cSrcweir aLocalPolyPolygon = basegfx::tools::clipPolyPolygonOnRange( 769*cdf0e10cSrcweir aLocalPolyPolygon, rDiscreteViewport, true, false); 770*cdf0e10cSrcweir 771*cdf0e10cSrcweir if(aLocalPolyPolygon.count()) 772*cdf0e10cSrcweir { 773*cdf0e10cSrcweir // subdivide 774*cdf0e10cSrcweir aLocalPolyPolygon = basegfx::tools::adaptiveSubdivideByDistance( 775*cdf0e10cSrcweir aLocalPolyPolygon, 0.5); 776*cdf0e10cSrcweir 777*cdf0e10cSrcweir // trapezoidize 778*cdf0e10cSrcweir basegfx::B2DTrapezoidVector aB2DTrapezoidVector; 779*cdf0e10cSrcweir basegfx::tools::trapezoidSubdivide(aB2DTrapezoidVector, aLocalPolyPolygon); 780*cdf0e10cSrcweir 781*cdf0e10cSrcweir const sal_uInt32 nCount(aB2DTrapezoidVector.size()); 782*cdf0e10cSrcweir 783*cdf0e10cSrcweir if(nCount) 784*cdf0e10cSrcweir { 785*cdf0e10cSrcweir basegfx::BColor aInvPolygonColor(aPolygonColor); 786*cdf0e10cSrcweir aInvPolygonColor.invert(); 787*cdf0e10cSrcweir 788*cdf0e10cSrcweir for(sal_uInt32 a(0); a < nCount; a++) 789*cdf0e10cSrcweir { 790*cdf0e10cSrcweir const basegfx::B2DPolygon aTempPolygon(aB2DTrapezoidVector[a].getB2DPolygon()); 791*cdf0e10cSrcweir 792*cdf0e10cSrcweir if(bShowOutlinesThere) 793*cdf0e10cSrcweir { 794*cdf0e10cSrcweir mpOutputDevice->SetFillColor(Color(aPolygonColor)); 795*cdf0e10cSrcweir mpOutputDevice->SetLineColor(); 796*cdf0e10cSrcweir } 797*cdf0e10cSrcweir 798*cdf0e10cSrcweir mpOutputDevice->DrawPolygon(aTempPolygon); 799*cdf0e10cSrcweir 800*cdf0e10cSrcweir if(bShowOutlinesThere) 801*cdf0e10cSrcweir { 802*cdf0e10cSrcweir mpOutputDevice->SetFillColor(); 803*cdf0e10cSrcweir mpOutputDevice->SetLineColor(Color(aInvPolygonColor)); 804*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aTempPolygon, 0.0); 805*cdf0e10cSrcweir } 806*cdf0e10cSrcweir } 807*cdf0e10cSrcweir } 808*cdf0e10cSrcweir } 809*cdf0e10cSrcweir } 810*cdf0e10cSrcweir else 811*cdf0e10cSrcweir { 812*cdf0e10cSrcweir mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon); 813*cdf0e10cSrcweir 814*cdf0e10cSrcweir if(mnPolygonStrokePrimitive2D 815*cdf0e10cSrcweir && getOptionsDrawinglayer().IsAntiAliasing() 816*cdf0e10cSrcweir && (mpOutputDevice->GetAntialiasing() & ANTIALIASING_ENABLE_B2DDRAW)) 817*cdf0e10cSrcweir { 818*cdf0e10cSrcweir // when AA is on and this filled polygons are the result of stroked line geometry, 819*cdf0e10cSrcweir // draw the geometry once extra as lines to avoid AA 'gaps' between partial polygons 820*cdf0e10cSrcweir mpOutputDevice->SetFillColor(); 821*cdf0e10cSrcweir mpOutputDevice->SetLineColor(Color(aPolygonColor)); 822*cdf0e10cSrcweir const sal_uInt32 nCount(aLocalPolyPolygon.count()); 823*cdf0e10cSrcweir 824*cdf0e10cSrcweir for(sal_uInt32 a(0); a < nCount; a++) 825*cdf0e10cSrcweir { 826*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aLocalPolyPolygon.getB2DPolygon(a), 0.0); 827*cdf0e10cSrcweir } 828*cdf0e10cSrcweir } 829*cdf0e10cSrcweir } 830*cdf0e10cSrcweir } 831*cdf0e10cSrcweir 832*cdf0e10cSrcweir // direct draw of MetaFile 833*cdf0e10cSrcweir void VclProcessor2D::RenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rMetaCandidate) 834*cdf0e10cSrcweir { 835*cdf0e10cSrcweir // decompose matrix to check for shear, rotate and mirroring 836*cdf0e10cSrcweir basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rMetaCandidate.getTransform()); 837*cdf0e10cSrcweir basegfx::B2DVector aScale, aTranslate; 838*cdf0e10cSrcweir double fRotate, fShearX; 839*cdf0e10cSrcweir aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX); 840*cdf0e10cSrcweir 841*cdf0e10cSrcweir if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0)) 842*cdf0e10cSrcweir { 843*cdf0e10cSrcweir // #i102175# handle special case: If scale is negative in (x,y) (3rd quadrant), it can 844*cdf0e10cSrcweir // be expressed as rotation by PI. This needs to be done for Metafiles since 845*cdf0e10cSrcweir // these can be rotated, but not really mirrored 846*cdf0e10cSrcweir aScale = basegfx::absolute(aScale); 847*cdf0e10cSrcweir fRotate += F_PI; 848*cdf0e10cSrcweir } 849*cdf0e10cSrcweir 850*cdf0e10cSrcweir // get BoundRect 851*cdf0e10cSrcweir basegfx::B2DRange aOutlineRange(rMetaCandidate.getB2DRange(getViewInformation2D())); 852*cdf0e10cSrcweir aOutlineRange.transform(maCurrentTransformation); 853*cdf0e10cSrcweir 854*cdf0e10cSrcweir // Due to the integer MapModes used from VCL aind inside MetaFiles errors of up to three 855*cdf0e10cSrcweir // pixels in size may happen. As long as there is no better way (e.g. convert the MetaFile 856*cdf0e10cSrcweir // to primitives) it is necessary to reduce maximum pixel size by 1 in X and Y and to use 857*cdf0e10cSrcweir // the inner pixel bounds accordingly (ceil resp. floor). This will also be done for logic 858*cdf0e10cSrcweir // units e.g. when creating a new MetaFile, but since much huger value ranges are used 859*cdf0e10cSrcweir // there typically will be okay for this compromize. 860*cdf0e10cSrcweir Rectangle aDestRectView( 861*cdf0e10cSrcweir // !!CAUTION!! Here, ceil and floor are exchanged BY PURPOSE, do NOT copy when 862*cdf0e10cSrcweir // looking for a standard conversion to rectangle (!) 863*cdf0e10cSrcweir (sal_Int32)ceil(aOutlineRange.getMinX()), (sal_Int32)ceil(aOutlineRange.getMinY()), 864*cdf0e10cSrcweir (sal_Int32)floor(aOutlineRange.getMaxX()), (sal_Int32)floor(aOutlineRange.getMaxY())); 865*cdf0e10cSrcweir 866*cdf0e10cSrcweir // get metafile (copy it) 867*cdf0e10cSrcweir GDIMetaFile aMetaFile; 868*cdf0e10cSrcweir 869*cdf0e10cSrcweir if(maBColorModifierStack.count()) 870*cdf0e10cSrcweir { 871*cdf0e10cSrcweir const basegfx::BColor aRGBBaseColor(0, 0, 0); 872*cdf0e10cSrcweir const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor)); 873*cdf0e10cSrcweir aMetaFile = rMetaCandidate.getMetaFile().GetMonochromeMtf(Color(aRGBColor)); 874*cdf0e10cSrcweir } 875*cdf0e10cSrcweir else 876*cdf0e10cSrcweir { 877*cdf0e10cSrcweir aMetaFile = rMetaCandidate.getMetaFile(); 878*cdf0e10cSrcweir } 879*cdf0e10cSrcweir 880*cdf0e10cSrcweir // rotation 881*cdf0e10cSrcweir if(!basegfx::fTools::equalZero(fRotate)) 882*cdf0e10cSrcweir { 883*cdf0e10cSrcweir // #i103530# 884*cdf0e10cSrcweir // MetaFile::Rotate has no input parameter check, so the parameter needs to be 885*cdf0e10cSrcweir // well-aligned to the old range [0..3600] 10th degrees with inverse orientation 886*cdf0e10cSrcweir sal_Int16 nRotation((sal_Int16)((fRotate / F_PI180) * -10.0)); 887*cdf0e10cSrcweir 888*cdf0e10cSrcweir while(nRotation < 0) 889*cdf0e10cSrcweir nRotation += 3600; 890*cdf0e10cSrcweir 891*cdf0e10cSrcweir while(nRotation >= 3600) 892*cdf0e10cSrcweir nRotation -= 3600; 893*cdf0e10cSrcweir 894*cdf0e10cSrcweir aMetaFile.Rotate(nRotation); 895*cdf0e10cSrcweir } 896*cdf0e10cSrcweir 897*cdf0e10cSrcweir // Prepare target output size 898*cdf0e10cSrcweir Size aDestSize(aDestRectView.GetSize()); 899*cdf0e10cSrcweir 900*cdf0e10cSrcweir if(aDestSize.getWidth() && aDestSize.getHeight()) 901*cdf0e10cSrcweir { 902*cdf0e10cSrcweir // Get preferred Metafile output size. When it's very equal to the output size, it's probably 903*cdf0e10cSrcweir // a rounding error somewhere, so correct it to get a 1:1 output without single pixel scalings 904*cdf0e10cSrcweir // of the Metafile (esp. for contaned Bitmaps, e.g 3D charts) 905*cdf0e10cSrcweir const Size aPrefSize(mpOutputDevice->LogicToPixel(aMetaFile.GetPrefSize(), aMetaFile.GetPrefMapMode())); 906*cdf0e10cSrcweir 907*cdf0e10cSrcweir if(aPrefSize.getWidth() && (aPrefSize.getWidth() - 1 == aDestSize.getWidth() || aPrefSize.getWidth() + 1 == aDestSize.getWidth())) 908*cdf0e10cSrcweir { 909*cdf0e10cSrcweir aDestSize.setWidth(aPrefSize.getWidth()); 910*cdf0e10cSrcweir } 911*cdf0e10cSrcweir 912*cdf0e10cSrcweir if(aPrefSize.getHeight() && (aPrefSize.getHeight() - 1 == aDestSize.getHeight() || aPrefSize.getHeight() + 1 == aDestSize.getHeight())) 913*cdf0e10cSrcweir { 914*cdf0e10cSrcweir aDestSize.setHeight(aPrefSize.getHeight()); 915*cdf0e10cSrcweir } 916*cdf0e10cSrcweir 917*cdf0e10cSrcweir // paint it 918*cdf0e10cSrcweir aMetaFile.WindStart(); 919*cdf0e10cSrcweir aMetaFile.Play(mpOutputDevice, aDestRectView.TopLeft(), aDestSize); 920*cdf0e10cSrcweir } 921*cdf0e10cSrcweir } 922*cdf0e10cSrcweir 923*cdf0e10cSrcweir // mask group. Force output to VDev and create mask from given mask 924*cdf0e10cSrcweir void VclProcessor2D::RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive2D& rMaskCandidate) 925*cdf0e10cSrcweir { 926*cdf0e10cSrcweir if(rMaskCandidate.getChildren().hasElements()) 927*cdf0e10cSrcweir { 928*cdf0e10cSrcweir basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask()); 929*cdf0e10cSrcweir 930*cdf0e10cSrcweir if(aMask.count()) 931*cdf0e10cSrcweir { 932*cdf0e10cSrcweir aMask.transform(maCurrentTransformation); 933*cdf0e10cSrcweir const basegfx::B2DRange aRange(basegfx::tools::getRange(aMask)); 934*cdf0e10cSrcweir impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true); 935*cdf0e10cSrcweir 936*cdf0e10cSrcweir if(aBufferDevice.isVisible()) 937*cdf0e10cSrcweir { 938*cdf0e10cSrcweir // remember last OutDev and set to content 939*cdf0e10cSrcweir OutputDevice* pLastOutputDevice = mpOutputDevice; 940*cdf0e10cSrcweir mpOutputDevice = &aBufferDevice.getContent(); 941*cdf0e10cSrcweir 942*cdf0e10cSrcweir // paint to it 943*cdf0e10cSrcweir process(rMaskCandidate.getChildren()); 944*cdf0e10cSrcweir 945*cdf0e10cSrcweir // back to old OutDev 946*cdf0e10cSrcweir mpOutputDevice = pLastOutputDevice; 947*cdf0e10cSrcweir 948*cdf0e10cSrcweir // draw mask 949*cdf0e10cSrcweir if(getOptionsDrawinglayer().IsAntiAliasing()) 950*cdf0e10cSrcweir { 951*cdf0e10cSrcweir // with AA, use 8bit AlphaMask to get nice borders 952*cdf0e10cSrcweir VirtualDevice& rTransparence = aBufferDevice.getTransparence(); 953*cdf0e10cSrcweir rTransparence.SetLineColor(); 954*cdf0e10cSrcweir rTransparence.SetFillColor(COL_BLACK); 955*cdf0e10cSrcweir rTransparence.DrawPolyPolygon(aMask); 956*cdf0e10cSrcweir 957*cdf0e10cSrcweir // dump buffer to outdev 958*cdf0e10cSrcweir aBufferDevice.paint(); 959*cdf0e10cSrcweir } 960*cdf0e10cSrcweir else 961*cdf0e10cSrcweir { 962*cdf0e10cSrcweir // No AA, use 1bit mask 963*cdf0e10cSrcweir VirtualDevice& rMask = aBufferDevice.getMask(); 964*cdf0e10cSrcweir rMask.SetLineColor(); 965*cdf0e10cSrcweir rMask.SetFillColor(COL_BLACK); 966*cdf0e10cSrcweir rMask.DrawPolyPolygon(aMask); 967*cdf0e10cSrcweir 968*cdf0e10cSrcweir // dump buffer to outdev 969*cdf0e10cSrcweir aBufferDevice.paint(); 970*cdf0e10cSrcweir } 971*cdf0e10cSrcweir } 972*cdf0e10cSrcweir } 973*cdf0e10cSrcweir } 974*cdf0e10cSrcweir } 975*cdf0e10cSrcweir 976*cdf0e10cSrcweir // modified color group. Force output to unified color. 977*cdf0e10cSrcweir void VclProcessor2D::RenderModifiedColorPrimitive2D(const primitive2d::ModifiedColorPrimitive2D& rModifiedCandidate) 978*cdf0e10cSrcweir { 979*cdf0e10cSrcweir if(rModifiedCandidate.getChildren().hasElements()) 980*cdf0e10cSrcweir { 981*cdf0e10cSrcweir maBColorModifierStack.push(rModifiedCandidate.getColorModifier()); 982*cdf0e10cSrcweir process(rModifiedCandidate.getChildren()); 983*cdf0e10cSrcweir maBColorModifierStack.pop(); 984*cdf0e10cSrcweir } 985*cdf0e10cSrcweir } 986*cdf0e10cSrcweir 987*cdf0e10cSrcweir // unified sub-transparence. Draw to VDev first. 988*cdf0e10cSrcweir void VclProcessor2D::RenderUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D& rTransCandidate) 989*cdf0e10cSrcweir { 990*cdf0e10cSrcweir static bool bForceToDecomposition(false); 991*cdf0e10cSrcweir 992*cdf0e10cSrcweir if(rTransCandidate.getChildren().hasElements()) 993*cdf0e10cSrcweir { 994*cdf0e10cSrcweir if(bForceToDecomposition) 995*cdf0e10cSrcweir { 996*cdf0e10cSrcweir // use decomposition 997*cdf0e10cSrcweir process(rTransCandidate.get2DDecomposition(getViewInformation2D())); 998*cdf0e10cSrcweir } 999*cdf0e10cSrcweir else 1000*cdf0e10cSrcweir { 1001*cdf0e10cSrcweir if(0.0 == rTransCandidate.getTransparence()) 1002*cdf0e10cSrcweir { 1003*cdf0e10cSrcweir // no transparence used, so just use the content 1004*cdf0e10cSrcweir process(rTransCandidate.getChildren()); 1005*cdf0e10cSrcweir } 1006*cdf0e10cSrcweir else if(rTransCandidate.getTransparence() > 0.0 && rTransCandidate.getTransparence() < 1.0) 1007*cdf0e10cSrcweir { 1008*cdf0e10cSrcweir // transparence is in visible range 1009*cdf0e10cSrcweir basegfx::B2DRange aRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rTransCandidate.getChildren(), getViewInformation2D())); 1010*cdf0e10cSrcweir aRange.transform(maCurrentTransformation); 1011*cdf0e10cSrcweir impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true); 1012*cdf0e10cSrcweir 1013*cdf0e10cSrcweir if(aBufferDevice.isVisible()) 1014*cdf0e10cSrcweir { 1015*cdf0e10cSrcweir // remember last OutDev and set to content 1016*cdf0e10cSrcweir OutputDevice* pLastOutputDevice = mpOutputDevice; 1017*cdf0e10cSrcweir mpOutputDevice = &aBufferDevice.getContent(); 1018*cdf0e10cSrcweir 1019*cdf0e10cSrcweir // paint content to it 1020*cdf0e10cSrcweir process(rTransCandidate.getChildren()); 1021*cdf0e10cSrcweir 1022*cdf0e10cSrcweir // back to old OutDev 1023*cdf0e10cSrcweir mpOutputDevice = pLastOutputDevice; 1024*cdf0e10cSrcweir 1025*cdf0e10cSrcweir // dump buffer to outdev using given transparence 1026*cdf0e10cSrcweir aBufferDevice.paint(rTransCandidate.getTransparence()); 1027*cdf0e10cSrcweir } 1028*cdf0e10cSrcweir } 1029*cdf0e10cSrcweir } 1030*cdf0e10cSrcweir } 1031*cdf0e10cSrcweir } 1032*cdf0e10cSrcweir 1033*cdf0e10cSrcweir // sub-transparence group. Draw to VDev first. 1034*cdf0e10cSrcweir void VclProcessor2D::RenderTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D& rTransCandidate) 1035*cdf0e10cSrcweir { 1036*cdf0e10cSrcweir if(rTransCandidate.getChildren().hasElements()) 1037*cdf0e10cSrcweir { 1038*cdf0e10cSrcweir basegfx::B2DRange aRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rTransCandidate.getChildren(), getViewInformation2D())); 1039*cdf0e10cSrcweir aRange.transform(maCurrentTransformation); 1040*cdf0e10cSrcweir impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true); 1041*cdf0e10cSrcweir 1042*cdf0e10cSrcweir if(aBufferDevice.isVisible()) 1043*cdf0e10cSrcweir { 1044*cdf0e10cSrcweir // remember last OutDev and set to content 1045*cdf0e10cSrcweir OutputDevice* pLastOutputDevice = mpOutputDevice; 1046*cdf0e10cSrcweir mpOutputDevice = &aBufferDevice.getContent(); 1047*cdf0e10cSrcweir 1048*cdf0e10cSrcweir // paint content to it 1049*cdf0e10cSrcweir process(rTransCandidate.getChildren()); 1050*cdf0e10cSrcweir 1051*cdf0e10cSrcweir // set to mask 1052*cdf0e10cSrcweir mpOutputDevice = &aBufferDevice.getTransparence(); 1053*cdf0e10cSrcweir 1054*cdf0e10cSrcweir // when painting transparence masks, reset the color stack 1055*cdf0e10cSrcweir basegfx::BColorModifierStack aLastBColorModifierStack(maBColorModifierStack); 1056*cdf0e10cSrcweir maBColorModifierStack = basegfx::BColorModifierStack(); 1057*cdf0e10cSrcweir 1058*cdf0e10cSrcweir // paint mask to it (always with transparence intensities, evtl. with AA) 1059*cdf0e10cSrcweir process(rTransCandidate.getTransparence()); 1060*cdf0e10cSrcweir 1061*cdf0e10cSrcweir // back to old color stack 1062*cdf0e10cSrcweir maBColorModifierStack = aLastBColorModifierStack; 1063*cdf0e10cSrcweir 1064*cdf0e10cSrcweir // back to old OutDev 1065*cdf0e10cSrcweir mpOutputDevice = pLastOutputDevice; 1066*cdf0e10cSrcweir 1067*cdf0e10cSrcweir // dump buffer to outdev 1068*cdf0e10cSrcweir aBufferDevice.paint(); 1069*cdf0e10cSrcweir } 1070*cdf0e10cSrcweir } 1071*cdf0e10cSrcweir } 1072*cdf0e10cSrcweir 1073*cdf0e10cSrcweir // transform group. 1074*cdf0e10cSrcweir void VclProcessor2D::RenderTransformPrimitive2D(const primitive2d::TransformPrimitive2D& rTransformCandidate) 1075*cdf0e10cSrcweir { 1076*cdf0e10cSrcweir // remember current transformation and ViewInformation 1077*cdf0e10cSrcweir const basegfx::B2DHomMatrix aLastCurrentTransformation(maCurrentTransformation); 1078*cdf0e10cSrcweir const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D()); 1079*cdf0e10cSrcweir 1080*cdf0e10cSrcweir // create new transformations for CurrentTransformation 1081*cdf0e10cSrcweir // and for local ViewInformation2D 1082*cdf0e10cSrcweir maCurrentTransformation = maCurrentTransformation * rTransformCandidate.getTransformation(); 1083*cdf0e10cSrcweir const geometry::ViewInformation2D aViewInformation2D( 1084*cdf0e10cSrcweir getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(), 1085*cdf0e10cSrcweir getViewInformation2D().getViewTransformation(), 1086*cdf0e10cSrcweir getViewInformation2D().getViewport(), 1087*cdf0e10cSrcweir getViewInformation2D().getVisualizedPage(), 1088*cdf0e10cSrcweir getViewInformation2D().getViewTime(), 1089*cdf0e10cSrcweir getViewInformation2D().getExtendedInformationSequence()); 1090*cdf0e10cSrcweir updateViewInformation(aViewInformation2D); 1091*cdf0e10cSrcweir 1092*cdf0e10cSrcweir // proccess content 1093*cdf0e10cSrcweir process(rTransformCandidate.getChildren()); 1094*cdf0e10cSrcweir 1095*cdf0e10cSrcweir // restore transformations 1096*cdf0e10cSrcweir maCurrentTransformation = aLastCurrentTransformation; 1097*cdf0e10cSrcweir updateViewInformation(aLastViewInformation2D); 1098*cdf0e10cSrcweir } 1099*cdf0e10cSrcweir 1100*cdf0e10cSrcweir // new XDrawPage for ViewInformation2D 1101*cdf0e10cSrcweir void VclProcessor2D::RenderPagePreviewPrimitive2D(const primitive2d::PagePreviewPrimitive2D& rPagePreviewCandidate) 1102*cdf0e10cSrcweir { 1103*cdf0e10cSrcweir // remember current transformation and ViewInformation 1104*cdf0e10cSrcweir const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D()); 1105*cdf0e10cSrcweir 1106*cdf0e10cSrcweir // create new local ViewInformation2D 1107*cdf0e10cSrcweir const geometry::ViewInformation2D aViewInformation2D( 1108*cdf0e10cSrcweir getViewInformation2D().getObjectTransformation(), 1109*cdf0e10cSrcweir getViewInformation2D().getViewTransformation(), 1110*cdf0e10cSrcweir getViewInformation2D().getViewport(), 1111*cdf0e10cSrcweir rPagePreviewCandidate.getXDrawPage(), 1112*cdf0e10cSrcweir getViewInformation2D().getViewTime(), 1113*cdf0e10cSrcweir getViewInformation2D().getExtendedInformationSequence()); 1114*cdf0e10cSrcweir updateViewInformation(aViewInformation2D); 1115*cdf0e10cSrcweir 1116*cdf0e10cSrcweir // proccess decomposed content 1117*cdf0e10cSrcweir process(rPagePreviewCandidate.get2DDecomposition(getViewInformation2D())); 1118*cdf0e10cSrcweir 1119*cdf0e10cSrcweir // restore transformations 1120*cdf0e10cSrcweir updateViewInformation(aLastViewInformation2D); 1121*cdf0e10cSrcweir } 1122*cdf0e10cSrcweir 1123*cdf0e10cSrcweir // marker 1124*cdf0e10cSrcweir void VclProcessor2D::RenderMarkerArrayPrimitive2D(const primitive2d::MarkerArrayPrimitive2D& rMarkArrayCandidate) 1125*cdf0e10cSrcweir { 1126*cdf0e10cSrcweir static bool bCheckCompleteMarkerDecompose(false); 1127*cdf0e10cSrcweir if(bCheckCompleteMarkerDecompose) 1128*cdf0e10cSrcweir { 1129*cdf0e10cSrcweir process(rMarkArrayCandidate.get2DDecomposition(getViewInformation2D())); 1130*cdf0e10cSrcweir return; 1131*cdf0e10cSrcweir } 1132*cdf0e10cSrcweir 1133*cdf0e10cSrcweir // get data 1134*cdf0e10cSrcweir const std::vector< basegfx::B2DPoint >& rPositions = rMarkArrayCandidate.getPositions(); 1135*cdf0e10cSrcweir const sal_uInt32 nCount(rPositions.size()); 1136*cdf0e10cSrcweir 1137*cdf0e10cSrcweir if(nCount && !rMarkArrayCandidate.getMarker().IsEmpty()) 1138*cdf0e10cSrcweir { 1139*cdf0e10cSrcweir // get pixel size 1140*cdf0e10cSrcweir const BitmapEx& rMarker(rMarkArrayCandidate.getMarker()); 1141*cdf0e10cSrcweir const Size aBitmapSize(rMarker.GetSizePixel()); 1142*cdf0e10cSrcweir 1143*cdf0e10cSrcweir if(aBitmapSize.Width() && aBitmapSize.Height()) 1144*cdf0e10cSrcweir { 1145*cdf0e10cSrcweir // get discrete half size 1146*cdf0e10cSrcweir const basegfx::B2DVector aDiscreteHalfSize( 1147*cdf0e10cSrcweir (aBitmapSize.getWidth() - 1.0) * 0.5, 1148*cdf0e10cSrcweir (aBitmapSize.getHeight() - 1.0) * 0.5); 1149*cdf0e10cSrcweir const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled()); 1150*cdf0e10cSrcweir 1151*cdf0e10cSrcweir // do not forget evtl. moved origin in target device MapMode when 1152*cdf0e10cSrcweir // switching it off; it would be missing and lead to wrong positions. 1153*cdf0e10cSrcweir // All his could be done using logic sizes and coordinates, too, but 1154*cdf0e10cSrcweir // we want a 1:1 bitmap rendering here, so it's more safe and faster 1155*cdf0e10cSrcweir // to work with switching off MapMode usage completely. 1156*cdf0e10cSrcweir const Point aOrigin(mpOutputDevice->GetMapMode().GetOrigin()); 1157*cdf0e10cSrcweir 1158*cdf0e10cSrcweir mpOutputDevice->EnableMapMode(false); 1159*cdf0e10cSrcweir 1160*cdf0e10cSrcweir for(std::vector< basegfx::B2DPoint >::const_iterator aIter(rPositions.begin()); aIter != rPositions.end(); aIter++) 1161*cdf0e10cSrcweir { 1162*cdf0e10cSrcweir const basegfx::B2DPoint aDiscreteTopLeft((maCurrentTransformation * (*aIter)) - aDiscreteHalfSize); 1163*cdf0e10cSrcweir const Point aDiscretePoint(basegfx::fround(aDiscreteTopLeft.getX()), basegfx::fround(aDiscreteTopLeft.getY())); 1164*cdf0e10cSrcweir 1165*cdf0e10cSrcweir mpOutputDevice->DrawBitmapEx(aDiscretePoint + aOrigin, rMarker); 1166*cdf0e10cSrcweir } 1167*cdf0e10cSrcweir 1168*cdf0e10cSrcweir mpOutputDevice->EnableMapMode(bWasEnabled); 1169*cdf0e10cSrcweir } 1170*cdf0e10cSrcweir } 1171*cdf0e10cSrcweir } 1172*cdf0e10cSrcweir 1173*cdf0e10cSrcweir // point 1174*cdf0e10cSrcweir void VclProcessor2D::RenderPointArrayPrimitive2D(const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate) 1175*cdf0e10cSrcweir { 1176*cdf0e10cSrcweir const std::vector< basegfx::B2DPoint >& rPositions = rPointArrayCandidate.getPositions(); 1177*cdf0e10cSrcweir const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rPointArrayCandidate.getRGBColor())); 1178*cdf0e10cSrcweir const Color aVCLColor(aRGBColor); 1179*cdf0e10cSrcweir 1180*cdf0e10cSrcweir for(std::vector< basegfx::B2DPoint >::const_iterator aIter(rPositions.begin()); aIter != rPositions.end(); aIter++) 1181*cdf0e10cSrcweir { 1182*cdf0e10cSrcweir const basegfx::B2DPoint aViewPosition(maCurrentTransformation * (*aIter)); 1183*cdf0e10cSrcweir const Point aPos(basegfx::fround(aViewPosition.getX()), basegfx::fround(aViewPosition.getY())); 1184*cdf0e10cSrcweir 1185*cdf0e10cSrcweir mpOutputDevice->DrawPixel(aPos, aVCLColor); 1186*cdf0e10cSrcweir } 1187*cdf0e10cSrcweir } 1188*cdf0e10cSrcweir 1189*cdf0e10cSrcweir void VclProcessor2D::RenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokeCandidate) 1190*cdf0e10cSrcweir { 1191*cdf0e10cSrcweir // #i101491# method restructured to clearly use the DrawPolyLine 1192*cdf0e10cSrcweir // calls starting from a deined line width 1193*cdf0e10cSrcweir const attribute::LineAttribute& rLineAttribute = rPolygonStrokeCandidate.getLineAttribute(); 1194*cdf0e10cSrcweir const double fLineWidth(rLineAttribute.getWidth()); 1195*cdf0e10cSrcweir bool bDone(false); 1196*cdf0e10cSrcweir 1197*cdf0e10cSrcweir if(basegfx::fTools::more(fLineWidth, 0.0)) 1198*cdf0e10cSrcweir { 1199*cdf0e10cSrcweir const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation * basegfx::B2DVector(fLineWidth, 0.0)); 1200*cdf0e10cSrcweir const double fDiscreteLineWidth(aDiscreteUnit.getLength()); 1201*cdf0e10cSrcweir const attribute::StrokeAttribute& rStrokeAttribute = rPolygonStrokeCandidate.getStrokeAttribute(); 1202*cdf0e10cSrcweir const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLineAttribute.getColor())); 1203*cdf0e10cSrcweir basegfx::B2DPolyPolygon aHairlinePolyPolygon; 1204*cdf0e10cSrcweir 1205*cdf0e10cSrcweir mpOutputDevice->SetLineColor(Color(aHairlineColor)); 1206*cdf0e10cSrcweir mpOutputDevice->SetFillColor(); 1207*cdf0e10cSrcweir 1208*cdf0e10cSrcweir if(0.0 == rStrokeAttribute.getFullDotDashLen()) 1209*cdf0e10cSrcweir { 1210*cdf0e10cSrcweir // no line dashing, just copy 1211*cdf0e10cSrcweir aHairlinePolyPolygon.append(rPolygonStrokeCandidate.getB2DPolygon()); 1212*cdf0e10cSrcweir } 1213*cdf0e10cSrcweir else 1214*cdf0e10cSrcweir { 1215*cdf0e10cSrcweir // else apply LineStyle 1216*cdf0e10cSrcweir basegfx::tools::applyLineDashing(rPolygonStrokeCandidate.getB2DPolygon(), 1217*cdf0e10cSrcweir rStrokeAttribute.getDotDashArray(), 1218*cdf0e10cSrcweir &aHairlinePolyPolygon, 0, rStrokeAttribute.getFullDotDashLen()); 1219*cdf0e10cSrcweir } 1220*cdf0e10cSrcweir 1221*cdf0e10cSrcweir const sal_uInt32 nCount(aHairlinePolyPolygon.count()); 1222*cdf0e10cSrcweir 1223*cdf0e10cSrcweir if(nCount) 1224*cdf0e10cSrcweir { 1225*cdf0e10cSrcweir const bool bAntiAliased(getOptionsDrawinglayer().IsAntiAliasing()); 1226*cdf0e10cSrcweir aHairlinePolyPolygon.transform(maCurrentTransformation); 1227*cdf0e10cSrcweir 1228*cdf0e10cSrcweir for(sal_uInt32 a(0); a < nCount; a++) 1229*cdf0e10cSrcweir { 1230*cdf0e10cSrcweir basegfx::B2DPolygon aCandidate(aHairlinePolyPolygon.getB2DPolygon(a)); 1231*cdf0e10cSrcweir 1232*cdf0e10cSrcweir if(bAntiAliased) 1233*cdf0e10cSrcweir { 1234*cdf0e10cSrcweir if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 1.0)) 1235*cdf0e10cSrcweir { 1236*cdf0e10cSrcweir // line in range ]0.0 .. 1.0[ 1237*cdf0e10cSrcweir // paint as simple hairline 1238*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1239*cdf0e10cSrcweir bDone = true; 1240*cdf0e10cSrcweir } 1241*cdf0e10cSrcweir else if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 2.0)) 1242*cdf0e10cSrcweir { 1243*cdf0e10cSrcweir // line in range [1.0 .. 2.0[ 1244*cdf0e10cSrcweir // paint as 2x2 with dynamic line distance 1245*cdf0e10cSrcweir basegfx::B2DHomMatrix aMat; 1246*cdf0e10cSrcweir const double fDistance(fDiscreteLineWidth - 1.0); 1247*cdf0e10cSrcweir const double fHalfDistance(fDistance * 0.5); 1248*cdf0e10cSrcweir 1249*cdf0e10cSrcweir aMat.set(0, 2, -fHalfDistance); 1250*cdf0e10cSrcweir aMat.set(1, 2, -fHalfDistance); 1251*cdf0e10cSrcweir aCandidate.transform(aMat); 1252*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1253*cdf0e10cSrcweir 1254*cdf0e10cSrcweir aMat.set(0, 2, fDistance); 1255*cdf0e10cSrcweir aMat.set(1, 2, 0.0); 1256*cdf0e10cSrcweir aCandidate.transform(aMat); 1257*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1258*cdf0e10cSrcweir 1259*cdf0e10cSrcweir aMat.set(0, 2, 0.0); 1260*cdf0e10cSrcweir aMat.set(1, 2, fDistance); 1261*cdf0e10cSrcweir aCandidate.transform(aMat); 1262*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1263*cdf0e10cSrcweir 1264*cdf0e10cSrcweir aMat.set(0, 2, -fDistance); 1265*cdf0e10cSrcweir aMat.set(1, 2, 0.0); 1266*cdf0e10cSrcweir aCandidate.transform(aMat); 1267*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1268*cdf0e10cSrcweir bDone = true; 1269*cdf0e10cSrcweir } 1270*cdf0e10cSrcweir else if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 3.0)) 1271*cdf0e10cSrcweir { 1272*cdf0e10cSrcweir // line in range [2.0 .. 3.0] 1273*cdf0e10cSrcweir // paint as cross in a 3x3 with dynamic line distance 1274*cdf0e10cSrcweir basegfx::B2DHomMatrix aMat; 1275*cdf0e10cSrcweir const double fDistance((fDiscreteLineWidth - 1.0) * 0.5); 1276*cdf0e10cSrcweir 1277*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1278*cdf0e10cSrcweir 1279*cdf0e10cSrcweir aMat.set(0, 2, -fDistance); 1280*cdf0e10cSrcweir aMat.set(1, 2, 0.0); 1281*cdf0e10cSrcweir aCandidate.transform(aMat); 1282*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1283*cdf0e10cSrcweir 1284*cdf0e10cSrcweir aMat.set(0, 2, fDistance); 1285*cdf0e10cSrcweir aMat.set(1, 2, -fDistance); 1286*cdf0e10cSrcweir aCandidate.transform(aMat); 1287*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1288*cdf0e10cSrcweir 1289*cdf0e10cSrcweir aMat.set(0, 2, fDistance); 1290*cdf0e10cSrcweir aMat.set(1, 2, fDistance); 1291*cdf0e10cSrcweir aCandidate.transform(aMat); 1292*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1293*cdf0e10cSrcweir 1294*cdf0e10cSrcweir aMat.set(0, 2, -fDistance); 1295*cdf0e10cSrcweir aMat.set(1, 2, fDistance); 1296*cdf0e10cSrcweir aCandidate.transform(aMat); 1297*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1298*cdf0e10cSrcweir bDone = true; 1299*cdf0e10cSrcweir } 1300*cdf0e10cSrcweir else 1301*cdf0e10cSrcweir { 1302*cdf0e10cSrcweir // #i101491# line width above 3.0 1303*cdf0e10cSrcweir } 1304*cdf0e10cSrcweir } 1305*cdf0e10cSrcweir else 1306*cdf0e10cSrcweir { 1307*cdf0e10cSrcweir if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 1.5)) 1308*cdf0e10cSrcweir { 1309*cdf0e10cSrcweir // line width below 1.5, draw the basic hairline polygon 1310*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1311*cdf0e10cSrcweir bDone = true; 1312*cdf0e10cSrcweir } 1313*cdf0e10cSrcweir else if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 2.5)) 1314*cdf0e10cSrcweir { 1315*cdf0e10cSrcweir // line width is in range ]1.5 .. 2.5], use four hairlines 1316*cdf0e10cSrcweir // drawn in a square 1317*cdf0e10cSrcweir basegfx::B2DHomMatrix aMat; 1318*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1319*cdf0e10cSrcweir 1320*cdf0e10cSrcweir aMat.set(0, 2, 1.0); 1321*cdf0e10cSrcweir aMat.set(1, 2, 0.0); 1322*cdf0e10cSrcweir aCandidate.transform(aMat); 1323*cdf0e10cSrcweir 1324*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1325*cdf0e10cSrcweir 1326*cdf0e10cSrcweir aMat.set(0, 2, 0.0); 1327*cdf0e10cSrcweir aMat.set(1, 2, 1.0); 1328*cdf0e10cSrcweir aCandidate.transform(aMat); 1329*cdf0e10cSrcweir 1330*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1331*cdf0e10cSrcweir 1332*cdf0e10cSrcweir aMat.set(0, 2, -1.0); 1333*cdf0e10cSrcweir aMat.set(1, 2, 0.0); 1334*cdf0e10cSrcweir aCandidate.transform(aMat); 1335*cdf0e10cSrcweir 1336*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, 0.0); 1337*cdf0e10cSrcweir bDone = true; 1338*cdf0e10cSrcweir } 1339*cdf0e10cSrcweir else 1340*cdf0e10cSrcweir { 1341*cdf0e10cSrcweir // #i101491# line width is above 2.5 1342*cdf0e10cSrcweir } 1343*cdf0e10cSrcweir } 1344*cdf0e10cSrcweir 1345*cdf0e10cSrcweir if(!bDone && rPolygonStrokeCandidate.getB2DPolygon().count() > 1000) 1346*cdf0e10cSrcweir { 1347*cdf0e10cSrcweir // #i101491# If the polygon complexity uses more than a given amount, do 1348*cdf0e10cSrcweir // use OuputDevice::DrawPolyLine directly; this will avoid buffering all 1349*cdf0e10cSrcweir // decompositions in primtives (memory) and fallback to old line painting 1350*cdf0e10cSrcweir // for very complex polygons, too 1351*cdf0e10cSrcweir mpOutputDevice->DrawPolyLine(aCandidate, fDiscreteLineWidth, rLineAttribute.getLineJoin()); 1352*cdf0e10cSrcweir bDone = true; 1353*cdf0e10cSrcweir } 1354*cdf0e10cSrcweir } 1355*cdf0e10cSrcweir } 1356*cdf0e10cSrcweir } 1357*cdf0e10cSrcweir 1358*cdf0e10cSrcweir if(!bDone) 1359*cdf0e10cSrcweir { 1360*cdf0e10cSrcweir // remeber that we enter a PolygonStrokePrimitive2D decomposition, 1361*cdf0e10cSrcweir // used for AA thick line drawing 1362*cdf0e10cSrcweir mnPolygonStrokePrimitive2D++; 1363*cdf0e10cSrcweir 1364*cdf0e10cSrcweir // line width is big enough for standard filled polygon visualisation or zero 1365*cdf0e10cSrcweir process(rPolygonStrokeCandidate.get2DDecomposition(getViewInformation2D())); 1366*cdf0e10cSrcweir 1367*cdf0e10cSrcweir // leave PolygonStrokePrimitive2D 1368*cdf0e10cSrcweir mnPolygonStrokePrimitive2D--; 1369*cdf0e10cSrcweir } 1370*cdf0e10cSrcweir } 1371*cdf0e10cSrcweir 1372*cdf0e10cSrcweir void VclProcessor2D::RenderEpsPrimitive2D(const primitive2d::EpsPrimitive2D& rEpsPrimitive2D) 1373*cdf0e10cSrcweir { 1374*cdf0e10cSrcweir // The new decomposition of Metafiles made it necessary to add an Eps 1375*cdf0e10cSrcweir // primitive to handle embedded Eps data. On some devices, this can be 1376*cdf0e10cSrcweir // painted directly (mac, printer). 1377*cdf0e10cSrcweir // To be able to handle the replacement correctly, i need to handle it myself 1378*cdf0e10cSrcweir // since DrawEPS will not be able e.g. to rotate the replacement. To be able 1379*cdf0e10cSrcweir // to do that, i added a boolean return to OutputDevice::DrawEPS(..) 1380*cdf0e10cSrcweir // to know when EPS was handled directly already. 1381*cdf0e10cSrcweir basegfx::B2DRange aRange(0.0, 0.0, 1.0, 1.0); 1382*cdf0e10cSrcweir aRange.transform(maCurrentTransformation * rEpsPrimitive2D.getEpsTransform()); 1383*cdf0e10cSrcweir 1384*cdf0e10cSrcweir if(!aRange.isEmpty()) 1385*cdf0e10cSrcweir { 1386*cdf0e10cSrcweir const Rectangle aRectangle( 1387*cdf0e10cSrcweir (sal_Int32)floor(aRange.getMinX()), (sal_Int32)floor(aRange.getMinY()), 1388*cdf0e10cSrcweir (sal_Int32)ceil(aRange.getMaxX()), (sal_Int32)ceil(aRange.getMaxY())); 1389*cdf0e10cSrcweir 1390*cdf0e10cSrcweir if(!aRectangle.IsEmpty()) 1391*cdf0e10cSrcweir { 1392*cdf0e10cSrcweir // try to paint EPS directly without fallback visualisation 1393*cdf0e10cSrcweir const bool bEPSPaintedDirectly(mpOutputDevice->DrawEPS( 1394*cdf0e10cSrcweir aRectangle.TopLeft(), 1395*cdf0e10cSrcweir aRectangle.GetSize(), 1396*cdf0e10cSrcweir rEpsPrimitive2D.getGfxLink(), 1397*cdf0e10cSrcweir 0)); 1398*cdf0e10cSrcweir 1399*cdf0e10cSrcweir if(!bEPSPaintedDirectly) 1400*cdf0e10cSrcweir { 1401*cdf0e10cSrcweir // use the decomposition which will correctly handle the 1402*cdf0e10cSrcweir // fallback visualisation using full transformation (e.g. rotation) 1403*cdf0e10cSrcweir process(rEpsPrimitive2D.get2DDecomposition(getViewInformation2D())); 1404*cdf0e10cSrcweir } 1405*cdf0e10cSrcweir } 1406*cdf0e10cSrcweir } 1407*cdf0e10cSrcweir } 1408*cdf0e10cSrcweir 1409*cdf0e10cSrcweir void VclProcessor2D::adaptLineToFillDrawMode() const 1410*cdf0e10cSrcweir { 1411*cdf0e10cSrcweir const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode()); 1412*cdf0e10cSrcweir 1413*cdf0e10cSrcweir if(nOriginalDrawMode & (DRAWMODE_BLACKLINE|DRAWMODE_GRAYLINE|DRAWMODE_GHOSTEDLINE|DRAWMODE_WHITELINE|DRAWMODE_SETTINGSLINE)) 1414*cdf0e10cSrcweir { 1415*cdf0e10cSrcweir sal_uInt32 nAdaptedDrawMode(nOriginalDrawMode); 1416*cdf0e10cSrcweir 1417*cdf0e10cSrcweir if(nOriginalDrawMode & DRAWMODE_BLACKLINE) 1418*cdf0e10cSrcweir { 1419*cdf0e10cSrcweir nAdaptedDrawMode |= DRAWMODE_BLACKFILL; 1420*cdf0e10cSrcweir } 1421*cdf0e10cSrcweir else 1422*cdf0e10cSrcweir { 1423*cdf0e10cSrcweir nAdaptedDrawMode &= ~DRAWMODE_BLACKFILL; 1424*cdf0e10cSrcweir } 1425*cdf0e10cSrcweir 1426*cdf0e10cSrcweir if(nOriginalDrawMode & DRAWMODE_GRAYLINE) 1427*cdf0e10cSrcweir { 1428*cdf0e10cSrcweir nAdaptedDrawMode |= DRAWMODE_GRAYFILL; 1429*cdf0e10cSrcweir } 1430*cdf0e10cSrcweir else 1431*cdf0e10cSrcweir { 1432*cdf0e10cSrcweir nAdaptedDrawMode &= ~DRAWMODE_GRAYFILL; 1433*cdf0e10cSrcweir } 1434*cdf0e10cSrcweir 1435*cdf0e10cSrcweir if(nOriginalDrawMode & DRAWMODE_GHOSTEDLINE) 1436*cdf0e10cSrcweir { 1437*cdf0e10cSrcweir nAdaptedDrawMode |= DRAWMODE_GHOSTEDFILL; 1438*cdf0e10cSrcweir } 1439*cdf0e10cSrcweir else 1440*cdf0e10cSrcweir { 1441*cdf0e10cSrcweir nAdaptedDrawMode &= ~DRAWMODE_GHOSTEDFILL; 1442*cdf0e10cSrcweir } 1443*cdf0e10cSrcweir 1444*cdf0e10cSrcweir if(nOriginalDrawMode & DRAWMODE_WHITELINE) 1445*cdf0e10cSrcweir { 1446*cdf0e10cSrcweir nAdaptedDrawMode |= DRAWMODE_WHITEFILL; 1447*cdf0e10cSrcweir } 1448*cdf0e10cSrcweir else 1449*cdf0e10cSrcweir { 1450*cdf0e10cSrcweir nAdaptedDrawMode &= ~DRAWMODE_WHITEFILL; 1451*cdf0e10cSrcweir } 1452*cdf0e10cSrcweir 1453*cdf0e10cSrcweir if(nOriginalDrawMode & DRAWMODE_SETTINGSLINE) 1454*cdf0e10cSrcweir { 1455*cdf0e10cSrcweir nAdaptedDrawMode |= DRAWMODE_SETTINGSFILL; 1456*cdf0e10cSrcweir } 1457*cdf0e10cSrcweir else 1458*cdf0e10cSrcweir { 1459*cdf0e10cSrcweir nAdaptedDrawMode &= ~DRAWMODE_SETTINGSFILL; 1460*cdf0e10cSrcweir } 1461*cdf0e10cSrcweir 1462*cdf0e10cSrcweir mpOutputDevice->SetDrawMode(nAdaptedDrawMode); 1463*cdf0e10cSrcweir } 1464*cdf0e10cSrcweir } 1465*cdf0e10cSrcweir 1466*cdf0e10cSrcweir void VclProcessor2D::adaptTextToFillDrawMode() const 1467*cdf0e10cSrcweir { 1468*cdf0e10cSrcweir const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode()); 1469*cdf0e10cSrcweir if(nOriginalDrawMode & (DRAWMODE_BLACKTEXT|DRAWMODE_GRAYTEXT|DRAWMODE_GHOSTEDTEXT|DRAWMODE_WHITETEXT|DRAWMODE_SETTINGSTEXT)) 1470*cdf0e10cSrcweir { 1471*cdf0e10cSrcweir sal_uInt32 nAdaptedDrawMode(nOriginalDrawMode); 1472*cdf0e10cSrcweir 1473*cdf0e10cSrcweir if(nOriginalDrawMode & DRAWMODE_BLACKTEXT) 1474*cdf0e10cSrcweir { 1475*cdf0e10cSrcweir nAdaptedDrawMode |= DRAWMODE_BLACKFILL; 1476*cdf0e10cSrcweir } 1477*cdf0e10cSrcweir else 1478*cdf0e10cSrcweir { 1479*cdf0e10cSrcweir nAdaptedDrawMode &= ~DRAWMODE_BLACKFILL; 1480*cdf0e10cSrcweir } 1481*cdf0e10cSrcweir 1482*cdf0e10cSrcweir if(nOriginalDrawMode & DRAWMODE_GRAYTEXT) 1483*cdf0e10cSrcweir { 1484*cdf0e10cSrcweir nAdaptedDrawMode |= DRAWMODE_GRAYFILL; 1485*cdf0e10cSrcweir } 1486*cdf0e10cSrcweir else 1487*cdf0e10cSrcweir { 1488*cdf0e10cSrcweir nAdaptedDrawMode &= ~DRAWMODE_GRAYFILL; 1489*cdf0e10cSrcweir } 1490*cdf0e10cSrcweir 1491*cdf0e10cSrcweir if(nOriginalDrawMode & DRAWMODE_GHOSTEDTEXT) 1492*cdf0e10cSrcweir { 1493*cdf0e10cSrcweir nAdaptedDrawMode |= DRAWMODE_GHOSTEDFILL; 1494*cdf0e10cSrcweir } 1495*cdf0e10cSrcweir else 1496*cdf0e10cSrcweir { 1497*cdf0e10cSrcweir nAdaptedDrawMode &= ~DRAWMODE_GHOSTEDFILL; 1498*cdf0e10cSrcweir } 1499*cdf0e10cSrcweir 1500*cdf0e10cSrcweir if(nOriginalDrawMode & DRAWMODE_WHITETEXT) 1501*cdf0e10cSrcweir { 1502*cdf0e10cSrcweir nAdaptedDrawMode |= DRAWMODE_WHITEFILL; 1503*cdf0e10cSrcweir } 1504*cdf0e10cSrcweir else 1505*cdf0e10cSrcweir { 1506*cdf0e10cSrcweir nAdaptedDrawMode &= ~DRAWMODE_WHITEFILL; 1507*cdf0e10cSrcweir } 1508*cdf0e10cSrcweir 1509*cdf0e10cSrcweir if(nOriginalDrawMode & DRAWMODE_SETTINGSTEXT) 1510*cdf0e10cSrcweir { 1511*cdf0e10cSrcweir nAdaptedDrawMode |= DRAWMODE_SETTINGSFILL; 1512*cdf0e10cSrcweir } 1513*cdf0e10cSrcweir else 1514*cdf0e10cSrcweir { 1515*cdf0e10cSrcweir nAdaptedDrawMode &= ~DRAWMODE_SETTINGSFILL; 1516*cdf0e10cSrcweir } 1517*cdf0e10cSrcweir 1518*cdf0e10cSrcweir mpOutputDevice->SetDrawMode(nAdaptedDrawMode); 1519*cdf0e10cSrcweir } 1520*cdf0e10cSrcweir } 1521*cdf0e10cSrcweir 1522*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 1523*cdf0e10cSrcweir // process support 1524*cdf0e10cSrcweir 1525*cdf0e10cSrcweir VclProcessor2D::VclProcessor2D( 1526*cdf0e10cSrcweir const geometry::ViewInformation2D& rViewInformation, 1527*cdf0e10cSrcweir OutputDevice& rOutDev) 1528*cdf0e10cSrcweir : BaseProcessor2D(rViewInformation), 1529*cdf0e10cSrcweir mpOutputDevice(&rOutDev), 1530*cdf0e10cSrcweir maBColorModifierStack(), 1531*cdf0e10cSrcweir maCurrentTransformation(), 1532*cdf0e10cSrcweir maDrawinglayerOpt(), 1533*cdf0e10cSrcweir mnPolygonStrokePrimitive2D(0) 1534*cdf0e10cSrcweir { 1535*cdf0e10cSrcweir // set digit language, derived from SvtCTLOptions to have the correct 1536*cdf0e10cSrcweir // number display for arabic/hindi numerals 1537*cdf0e10cSrcweir const SvtCTLOptions aSvtCTLOptions; 1538*cdf0e10cSrcweir LanguageType eLang(LANGUAGE_SYSTEM); 1539*cdf0e10cSrcweir 1540*cdf0e10cSrcweir if(SvtCTLOptions::NUMERALS_HINDI == aSvtCTLOptions.GetCTLTextNumerals()) 1541*cdf0e10cSrcweir { 1542*cdf0e10cSrcweir eLang = LANGUAGE_ARABIC_SAUDI_ARABIA; 1543*cdf0e10cSrcweir } 1544*cdf0e10cSrcweir else if(SvtCTLOptions::NUMERALS_ARABIC == aSvtCTLOptions.GetCTLTextNumerals()) 1545*cdf0e10cSrcweir { 1546*cdf0e10cSrcweir eLang = LANGUAGE_ENGLISH; 1547*cdf0e10cSrcweir } 1548*cdf0e10cSrcweir else 1549*cdf0e10cSrcweir { 1550*cdf0e10cSrcweir eLang = (LanguageType)Application::GetSettings().GetLanguage(); 1551*cdf0e10cSrcweir } 1552*cdf0e10cSrcweir 1553*cdf0e10cSrcweir rOutDev.SetDigitLanguage(eLang); 1554*cdf0e10cSrcweir } 1555*cdf0e10cSrcweir 1556*cdf0e10cSrcweir VclProcessor2D::~VclProcessor2D() 1557*cdf0e10cSrcweir { 1558*cdf0e10cSrcweir } 1559*cdf0e10cSrcweir } // end of namespace processor2d 1560*cdf0e10cSrcweir } // end of namespace drawinglayer 1561*cdf0e10cSrcweir 1562*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 1563*cdf0e10cSrcweir // eof 1564