1*25b11142SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*25b11142SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*25b11142SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*25b11142SAndrew Rist  * distributed with this work for additional information
6*25b11142SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*25b11142SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*25b11142SAndrew Rist  * "License"); you may not use this file except in compliance
9*25b11142SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*25b11142SAndrew Rist  *
11*25b11142SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*25b11142SAndrew Rist  *
13*25b11142SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*25b11142SAndrew Rist  * software distributed under the License is distributed on an
15*25b11142SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*25b11142SAndrew Rist  * KIND, either express or implied.  See the License for the
17*25b11142SAndrew Rist  * specific language governing permissions and limitations
18*25b11142SAndrew Rist  * under the License.
19*25b11142SAndrew Rist  *
20*25b11142SAndrew Rist  *************************************************************/
21*25b11142SAndrew Rist 
22*25b11142SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_cppcanvas.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <canvas/debug.hxx>
28cdf0e10cSrcweir #include <tools/diagnose_ex.h>
29cdf0e10cSrcweir #include <canvas/verbosetrace.hxx>
30cdf0e10cSrcweir #include <com/sun/star/rendering/RenderState.hpp>
31cdf0e10cSrcweir #include <com/sun/star/rendering/XCanvas.hpp>
32cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
33cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx>
34cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
35cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
36cdf0e10cSrcweir #include <basegfx/range/b2drectangle.hxx>
37cdf0e10cSrcweir #include <basegfx/vector/b2dvector.hxx>
38cdf0e10cSrcweir #include <canvas/canvastools.hxx>
39cdf0e10cSrcweir #include <vcl/gdimtf.hxx>
40cdf0e10cSrcweir #include <vcl/metaact.hxx>
41cdf0e10cSrcweir #include <vcl/virdev.hxx>
42cdf0e10cSrcweir #include <vcl/metric.hxx>
43cdf0e10cSrcweir #include <tools/poly.hxx>
44cdf0e10cSrcweir #include "mtftools.hxx"
45cdf0e10cSrcweir #include "outdevstate.hxx"
46cdf0e10cSrcweir #include "polypolyaction.hxx"
47cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrixtools.hxx>
48cdf0e10cSrcweir 
49cdf0e10cSrcweir 
50cdf0e10cSrcweir 
51cdf0e10cSrcweir using namespace ::com::sun::star;
52cdf0e10cSrcweir 
53cdf0e10cSrcweir namespace cppcanvas
54cdf0e10cSrcweir {
55cdf0e10cSrcweir     namespace tools
56cdf0e10cSrcweir     {
initRenderState(rendering::RenderState & renderState,const::cppcanvas::internal::OutDevState & outdevState)57cdf0e10cSrcweir         void initRenderState( rendering::RenderState&					renderState,
58cdf0e10cSrcweir                               const ::cppcanvas::internal::OutDevState&	outdevState )
59cdf0e10cSrcweir         {
60cdf0e10cSrcweir             ::canvas::tools::initRenderState( renderState );
61cdf0e10cSrcweir             ::canvas::tools::setRenderStateTransform( renderState,
62cdf0e10cSrcweir                                                       outdevState.transform );
63cdf0e10cSrcweir             renderState.Clip = outdevState.xClipPoly;
64cdf0e10cSrcweir         }
65cdf0e10cSrcweir 
getBaselineOffset(const::cppcanvas::internal::OutDevState & outdevState,const VirtualDevice & rVDev)66cdf0e10cSrcweir         ::Size getBaselineOffset( const ::cppcanvas::internal::OutDevState&	outdevState,
67cdf0e10cSrcweir                                   const VirtualDevice&						rVDev )
68cdf0e10cSrcweir         {
69cdf0e10cSrcweir             const ::FontMetric& aMetric = rVDev.GetFontMetric();
70cdf0e10cSrcweir 
71cdf0e10cSrcweir             // calc offset for text output, the XCanvas always renders
72cdf0e10cSrcweir             // baseline offset.
73cdf0e10cSrcweir             switch( outdevState.textReferencePoint )
74cdf0e10cSrcweir             {
75cdf0e10cSrcweir                 case ALIGN_TOP:
76cdf0e10cSrcweir                     return ::Size( 0,
77cdf0e10cSrcweir                                    aMetric.GetIntLeading() + aMetric.GetAscent() );
78cdf0e10cSrcweir 
79cdf0e10cSrcweir                 default:
80cdf0e10cSrcweir                     ENSURE_OR_THROW( false,
81cdf0e10cSrcweir                                       "tools::getBaselineOffset(): Unexpected TextAlign value" );
82cdf0e10cSrcweir                     // FALLTHROUGH intended (to calm compiler warning - case won't happen)
83cdf0e10cSrcweir                 case ALIGN_BASELINE:
84cdf0e10cSrcweir                     return ::Size( 0, 0 );
85cdf0e10cSrcweir 
86cdf0e10cSrcweir                 case ALIGN_BOTTOM:
87cdf0e10cSrcweir                     return ::Size( 0,
88cdf0e10cSrcweir                                    -aMetric.GetDescent() );
89cdf0e10cSrcweir 
90cdf0e10cSrcweir             }
91cdf0e10cSrcweir         }
92cdf0e10cSrcweir 
calcLogic2PixelLinearTransform(::basegfx::B2DHomMatrix & o_rMatrix,const VirtualDevice & rVDev)93cdf0e10cSrcweir         ::basegfx::B2DHomMatrix& calcLogic2PixelLinearTransform( ::basegfx::B2DHomMatrix&	o_rMatrix,
94cdf0e10cSrcweir                                                                  const VirtualDevice& 		rVDev )
95cdf0e10cSrcweir         {
96cdf0e10cSrcweir             // select size value in the middle of the available range,
97cdf0e10cSrcweir             // to have headroom both when map mode scales up, and when
98cdf0e10cSrcweir             // it scales down.
99cdf0e10cSrcweir             const ::Size aSizeLogic( 0x00010000L,
100cdf0e10cSrcweir                                      0x00010000L );
101cdf0e10cSrcweir 
102cdf0e10cSrcweir             const ::Size aSizePixel( rVDev.LogicToPixel( aSizeLogic ) );
103cdf0e10cSrcweir 
104cdf0e10cSrcweir 			o_rMatrix = basegfx::tools::createScaleB2DHomMatrix(
105cdf0e10cSrcweir 				aSizePixel.Width() / (double)aSizeLogic.Width(),
106cdf0e10cSrcweir 				aSizePixel.Height() / (double)aSizeLogic.Height() );
107cdf0e10cSrcweir 
108cdf0e10cSrcweir             return o_rMatrix;
109cdf0e10cSrcweir         }
110cdf0e10cSrcweir 
calcLogic2PixelAffineTransform(::basegfx::B2DHomMatrix & o_rMatrix,const VirtualDevice & rVDev)111cdf0e10cSrcweir         ::basegfx::B2DHomMatrix& calcLogic2PixelAffineTransform( ::basegfx::B2DHomMatrix&	o_rMatrix,
112cdf0e10cSrcweir                                                                  const VirtualDevice& 		rVDev )
113cdf0e10cSrcweir         {
114cdf0e10cSrcweir             // retrieves scale
115cdf0e10cSrcweir             calcLogic2PixelLinearTransform(o_rMatrix, rVDev);
116cdf0e10cSrcweir 
117cdf0e10cSrcweir             // translate according to curr map mode/pref map mode offset
118cdf0e10cSrcweir             const ::Point  aEmptyPoint;
119cdf0e10cSrcweir             const ::Point& rTranslatedPoint(
120cdf0e10cSrcweir                 rVDev.LogicToPixel( aEmptyPoint ));
121cdf0e10cSrcweir 
122cdf0e10cSrcweir             o_rMatrix.translate(rTranslatedPoint.X(),
123cdf0e10cSrcweir                                 rTranslatedPoint.Y());
124cdf0e10cSrcweir 
125cdf0e10cSrcweir             return o_rMatrix;
126cdf0e10cSrcweir         }
127cdf0e10cSrcweir 
modifyClip(rendering::RenderState & o_rRenderState,const struct::cppcanvas::internal::OutDevState & rOutdevState,const CanvasSharedPtr & rCanvas,const::basegfx::B2DPoint & rOffset,const::basegfx::B2DVector * pScaling,const double * pRotation)128cdf0e10cSrcweir         bool modifyClip( rendering::RenderState&							o_rRenderState,
129cdf0e10cSrcweir                          const struct ::cppcanvas::internal::OutDevState&	rOutdevState,
130cdf0e10cSrcweir                          const CanvasSharedPtr&								rCanvas,
131cdf0e10cSrcweir                          const ::basegfx::B2DPoint&							rOffset,
132cdf0e10cSrcweir                          const ::basegfx::B2DVector*						pScaling,
133cdf0e10cSrcweir                          const double*                                      pRotation )
134cdf0e10cSrcweir         {
135cdf0e10cSrcweir             const ::Point aEmptyPoint;
136cdf0e10cSrcweir 
137cdf0e10cSrcweir             const bool bOffsetting( !rOffset.equalZero() );
138cdf0e10cSrcweir             const bool bScaling( pScaling &&
139cdf0e10cSrcweir                                  pScaling->getX() != 1.0 &&
140cdf0e10cSrcweir                                  pScaling->getY() != 1.0 );
141cdf0e10cSrcweir             const bool bRotation( pRotation &&
142cdf0e10cSrcweir                                   *pRotation != 0.0 );
143cdf0e10cSrcweir 
144cdf0e10cSrcweir             if( !bOffsetting && !bScaling && !bRotation )
145cdf0e10cSrcweir                 return false; // nothing to do
146cdf0e10cSrcweir 
147cdf0e10cSrcweir             if( rOutdevState.clip.count() )
148cdf0e10cSrcweir             {
149cdf0e10cSrcweir                 // general polygon case
150cdf0e10cSrcweir 
151cdf0e10cSrcweir                 ::basegfx::B2DPolyPolygon aLocalClip( rOutdevState.clip );
152cdf0e10cSrcweir                 ::basegfx::B2DHomMatrix	  aTransform;
153cdf0e10cSrcweir 
154cdf0e10cSrcweir                 if( bOffsetting )
155cdf0e10cSrcweir                     aTransform.translate( -rOffset.getX(),
156cdf0e10cSrcweir                                           -rOffset.getY() );
157cdf0e10cSrcweir                 if( bScaling )
158cdf0e10cSrcweir                     aTransform.scale( 1.0/pScaling->getX(), 1.0/pScaling->getY() );
159cdf0e10cSrcweir 
160cdf0e10cSrcweir                 if( bRotation )
161cdf0e10cSrcweir                     aTransform.rotate( - *pRotation );
162cdf0e10cSrcweir 
163cdf0e10cSrcweir                 aLocalClip.transform( aTransform );
164cdf0e10cSrcweir 
165cdf0e10cSrcweir                 o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
166cdf0e10cSrcweir                     rCanvas->getUNOCanvas()->getDevice(),
167cdf0e10cSrcweir                     aLocalClip );
168cdf0e10cSrcweir 
169cdf0e10cSrcweir                 return true;
170cdf0e10cSrcweir             }
171cdf0e10cSrcweir             else if( !rOutdevState.clipRect.IsEmpty() )
172cdf0e10cSrcweir             {
173cdf0e10cSrcweir                 // simple rect case
174cdf0e10cSrcweir 
175cdf0e10cSrcweir                 const ::Rectangle aLocalClipRect( rOutdevState.clipRect );
176cdf0e10cSrcweir 
177cdf0e10cSrcweir                 if( bRotation )
178cdf0e10cSrcweir                 {
179cdf0e10cSrcweir                     // rotation involved - convert to polygon first,
180cdf0e10cSrcweir                     // then transform that
181cdf0e10cSrcweir                     ::basegfx::B2DPolygon aLocalClip(
182cdf0e10cSrcweir                         ::basegfx::tools::createPolygonFromRect(
183cdf0e10cSrcweir                                 ::basegfx::B2DRectangle(
184cdf0e10cSrcweir                                     (double)(aLocalClipRect.Left()),
185cdf0e10cSrcweir                                     (double)(aLocalClipRect.Top()),
186cdf0e10cSrcweir                                     (double)(aLocalClipRect.Right()),
187cdf0e10cSrcweir                                     (double)(aLocalClipRect.Bottom()) ) ) );
188cdf0e10cSrcweir                     ::basegfx::B2DHomMatrix aTransform;
189cdf0e10cSrcweir 
190cdf0e10cSrcweir                     if( bOffsetting )
191cdf0e10cSrcweir                         aTransform.translate( -rOffset.getX(),
192cdf0e10cSrcweir                                               -rOffset.getY() );
193cdf0e10cSrcweir                     if( bScaling )
194cdf0e10cSrcweir                         aTransform.scale( 1.0/pScaling->getX(), 1.0/pScaling->getY() );
195cdf0e10cSrcweir 
196cdf0e10cSrcweir                     aTransform.rotate( - *pRotation );
197cdf0e10cSrcweir 
198cdf0e10cSrcweir                     aLocalClip.transform( aTransform );
199cdf0e10cSrcweir 
200cdf0e10cSrcweir                     o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
201cdf0e10cSrcweir                         rCanvas->getUNOCanvas()->getDevice(),
202cdf0e10cSrcweir                         ::basegfx::B2DPolyPolygon( aLocalClip ) );
203cdf0e10cSrcweir                 }
204cdf0e10cSrcweir                 else if( bScaling )
205cdf0e10cSrcweir                 {
206cdf0e10cSrcweir                     // scale and offset - do it on the fly, have to
207cdf0e10cSrcweir                     // convert to float anyway.
208cdf0e10cSrcweir                     o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
209cdf0e10cSrcweir                         rCanvas->getUNOCanvas()->getDevice(),
210cdf0e10cSrcweir                         ::basegfx::B2DPolyPolygon(
211cdf0e10cSrcweir                             ::basegfx::tools::createPolygonFromRect(
212cdf0e10cSrcweir                                 ::basegfx::B2DRectangle(
213cdf0e10cSrcweir                                     (double)(aLocalClipRect.Left() - rOffset.getX())/pScaling->getX(),
214cdf0e10cSrcweir                                     (double)(aLocalClipRect.Top() - rOffset.getY())/pScaling->getY(),
215cdf0e10cSrcweir                                     (double)(aLocalClipRect.Right() - rOffset.getX())/pScaling->getX(),
216cdf0e10cSrcweir                                     (double)(aLocalClipRect.Bottom() - rOffset.getY())/pScaling->getY() ) ) ) );
217cdf0e10cSrcweir                 }
218cdf0e10cSrcweir                 else
219cdf0e10cSrcweir                 {
220cdf0e10cSrcweir                     // offset only - do it on the fly, have to convert
221cdf0e10cSrcweir                     // to float anyway.
222cdf0e10cSrcweir                     o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
223cdf0e10cSrcweir                         rCanvas->getUNOCanvas()->getDevice(),
224cdf0e10cSrcweir                         ::basegfx::B2DPolyPolygon(
225cdf0e10cSrcweir                             ::basegfx::tools::createPolygonFromRect(
226cdf0e10cSrcweir                                 ::basegfx::B2DRectangle( aLocalClipRect.Left() - rOffset.getX(),
227cdf0e10cSrcweir                                                          aLocalClipRect.Top() - rOffset.getY(),
228cdf0e10cSrcweir                                                          aLocalClipRect.Right() - rOffset.getX(),
229cdf0e10cSrcweir                                                          aLocalClipRect.Bottom() - rOffset.getY() ) ) ) );
230cdf0e10cSrcweir                 }
231cdf0e10cSrcweir 
232cdf0e10cSrcweir                 return true;
233cdf0e10cSrcweir             }
234cdf0e10cSrcweir 
235cdf0e10cSrcweir             // empty clip, nothing to do
236cdf0e10cSrcweir             return false;
237cdf0e10cSrcweir         }
238cdf0e10cSrcweir 
modifyClip(rendering::RenderState & o_rRenderState,const struct::cppcanvas::internal::OutDevState & rOutdevState,const CanvasSharedPtr & rCanvas,const::Point & rOffset,const::basegfx::B2DVector * pScaling,const double * pRotation)239cdf0e10cSrcweir         bool modifyClip( rendering::RenderState&							o_rRenderState,
240cdf0e10cSrcweir                          const struct ::cppcanvas::internal::OutDevState&	rOutdevState,
241cdf0e10cSrcweir                          const CanvasSharedPtr&								rCanvas,
242cdf0e10cSrcweir                          const ::Point&										rOffset,
243cdf0e10cSrcweir                          const ::basegfx::B2DVector*						pScaling,
244cdf0e10cSrcweir                          const double*                                      pRotation )
245cdf0e10cSrcweir         {
246cdf0e10cSrcweir             return modifyClip( o_rRenderState,
247cdf0e10cSrcweir                                rOutdevState,
248cdf0e10cSrcweir                                rCanvas,
249cdf0e10cSrcweir                                ::basegfx::B2DPoint( rOffset.X(),
250cdf0e10cSrcweir                                                     rOffset.Y() ),
251cdf0e10cSrcweir                                pScaling,
252cdf0e10cSrcweir                                pRotation );
253cdf0e10cSrcweir         }
254cdf0e10cSrcweir 
modifyClip(rendering::RenderState & o_rRenderState,const struct::cppcanvas::internal::OutDevState & rOutdevState,const CanvasSharedPtr & rCanvas,const::basegfx::B2DHomMatrix & rTransform)255cdf0e10cSrcweir         bool modifyClip( rendering::RenderState&							o_rRenderState,
256cdf0e10cSrcweir                          const struct ::cppcanvas::internal::OutDevState&	rOutdevState,
257cdf0e10cSrcweir                          const CanvasSharedPtr&								rCanvas,
258cdf0e10cSrcweir                          const ::basegfx::B2DHomMatrix&						rTransform )
259cdf0e10cSrcweir         {
260cdf0e10cSrcweir             if( !rTransform.isIdentity() ||
261cdf0e10cSrcweir                 !rTransform.isInvertible() )
262cdf0e10cSrcweir                 return false; // nothing to do
263cdf0e10cSrcweir 
264cdf0e10cSrcweir             ::basegfx::B2DPolyPolygon aLocalClip;
265cdf0e10cSrcweir 
266cdf0e10cSrcweir             if( rOutdevState.clip.count() )
267cdf0e10cSrcweir             {
268cdf0e10cSrcweir                 aLocalClip = rOutdevState.clip;
269cdf0e10cSrcweir             }
270cdf0e10cSrcweir             else if( !rOutdevState.clipRect.IsEmpty() )
271cdf0e10cSrcweir             {
272cdf0e10cSrcweir                 const ::Rectangle aLocalClipRect( rOutdevState.clipRect );
273cdf0e10cSrcweir 
274cdf0e10cSrcweir                 aLocalClip = ::basegfx::B2DPolyPolygon(
275cdf0e10cSrcweir                     ::basegfx::tools::createPolygonFromRect(
276cdf0e10cSrcweir                         ::basegfx::B2DRectangle(
277cdf0e10cSrcweir                             aLocalClipRect.Left(),
278cdf0e10cSrcweir                             aLocalClipRect.Top(),
279cdf0e10cSrcweir                             aLocalClipRect.Right(),
280cdf0e10cSrcweir                             aLocalClipRect.Bottom() ) ) );
281cdf0e10cSrcweir             }
282cdf0e10cSrcweir             else
283cdf0e10cSrcweir             {
284cdf0e10cSrcweir                 // empty clip, nothing to do
285cdf0e10cSrcweir                 return false;
286cdf0e10cSrcweir             }
287cdf0e10cSrcweir 
288cdf0e10cSrcweir             // invert transformation and modify
289cdf0e10cSrcweir             ::basegfx::B2DHomMatrix aLocalTransform( rTransform );
290cdf0e10cSrcweir             aLocalTransform.invert();
291cdf0e10cSrcweir 
292cdf0e10cSrcweir             aLocalClip.transform( aLocalTransform );
293cdf0e10cSrcweir 
294cdf0e10cSrcweir             o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
295cdf0e10cSrcweir                 rCanvas->getUNOCanvas()->getDevice(),
296cdf0e10cSrcweir                 aLocalClip );
297cdf0e10cSrcweir 
298cdf0e10cSrcweir             return true;
299cdf0e10cSrcweir         }
300cdf0e10cSrcweir 
301cdf0e10cSrcweir         // create overline/underline/strikeout line info struct
createTextLineInfo(const::VirtualDevice & rVDev,const::cppcanvas::internal::OutDevState & rState)302cdf0e10cSrcweir         TextLineInfo createTextLineInfo( const ::VirtualDevice& 					rVDev,
303cdf0e10cSrcweir                                          const ::cppcanvas::internal::OutDevState&	rState )
304cdf0e10cSrcweir         {
305cdf0e10cSrcweir             const sal_Bool bOldMode( rVDev.IsMapModeEnabled() );
306cdf0e10cSrcweir 
307cdf0e10cSrcweir             // #i68512# Force metric regeneration with mapmode enabled
308cdf0e10cSrcweir             // (prolly OutDev bug)
309cdf0e10cSrcweir             rVDev.GetFontMetric();
310cdf0e10cSrcweir 
311cdf0e10cSrcweir             // will restore map mode below
312cdf0e10cSrcweir             const_cast< ::VirtualDevice& >(rVDev).EnableMapMode( sal_False );
313cdf0e10cSrcweir 
314cdf0e10cSrcweir             const ::FontMetric aMetric = rVDev.GetFontMetric();
315cdf0e10cSrcweir 
316cdf0e10cSrcweir             TextLineInfo aTextInfo(
317cdf0e10cSrcweir                 (aMetric.GetDescent() + 2) / 4.0,
318cdf0e10cSrcweir                 ((aMetric.GetIntLeading() + 1.5) / 3.0),
319cdf0e10cSrcweir                 (aMetric.GetIntLeading() / 2.0) - aMetric.GetAscent(),
320cdf0e10cSrcweir                 aMetric.GetDescent() / 2.0,
321cdf0e10cSrcweir                 (aMetric.GetIntLeading() - aMetric.GetAscent()) / 3.0,
322cdf0e10cSrcweir                 rState.textOverlineStyle,
323cdf0e10cSrcweir                 rState.textUnderlineStyle,
324cdf0e10cSrcweir                 rState.textStrikeoutStyle );
325cdf0e10cSrcweir 
326cdf0e10cSrcweir             const_cast< ::VirtualDevice& >(rVDev).EnableMapMode( bOldMode );
327cdf0e10cSrcweir 
328cdf0e10cSrcweir             return aTextInfo;
329cdf0e10cSrcweir         }
330cdf0e10cSrcweir 
331cdf0e10cSrcweir         namespace
332cdf0e10cSrcweir         {
appendRect(::basegfx::B2DPolyPolygon & o_rPoly,const::basegfx::B2DPoint & rStartPos,const double nX1,const double nY1,const double nX2,const double nY2)333cdf0e10cSrcweir             void appendRect( ::basegfx::B2DPolyPolygon& o_rPoly,
334cdf0e10cSrcweir                              const ::basegfx::B2DPoint& rStartPos,
335cdf0e10cSrcweir                              const double 				nX1,
336cdf0e10cSrcweir                              const double 				nY1,
337cdf0e10cSrcweir                              const double 				nX2,
338cdf0e10cSrcweir                              const double 				nY2 )
339cdf0e10cSrcweir             {
340cdf0e10cSrcweir                 const double x( rStartPos.getX() );
341cdf0e10cSrcweir                 const double y( rStartPos.getY() );
342cdf0e10cSrcweir 
343cdf0e10cSrcweir                 o_rPoly.append(
344cdf0e10cSrcweir                     ::basegfx::tools::createPolygonFromRect(
345cdf0e10cSrcweir                         ::basegfx::B2DRectangle( x + nX1, y + nY1, x + nX2, y + nY2 ) ) );
346cdf0e10cSrcweir             }
347cdf0e10cSrcweir 
appendRect(::basegfx::B2DPolyPolygon & o_rPoly,const double nX1,const double nY1,const double nX2,const double nY2)348cdf0e10cSrcweir             void appendRect( ::basegfx::B2DPolyPolygon& o_rPoly,
349cdf0e10cSrcweir                              const double 				nX1,
350cdf0e10cSrcweir                              const double 				nY1,
351cdf0e10cSrcweir                              const double 				nX2,
352cdf0e10cSrcweir                              const double 				nY2 )
353cdf0e10cSrcweir             {
354cdf0e10cSrcweir                 o_rPoly.append(
355cdf0e10cSrcweir                     ::basegfx::tools::createPolygonFromRect(
356cdf0e10cSrcweir                         ::basegfx::B2DRectangle( nX1, nY1, nX2, nY2 ) ) );
357cdf0e10cSrcweir             }
358cdf0e10cSrcweir 
appendDashes(::basegfx::B2DPolyPolygon & o_rPoly,const double nX,const double nY,const double nLineWidth,const double nLineHeight,const double nDashWidth,const double nDashSkip)359cdf0e10cSrcweir             void appendDashes( ::basegfx::B2DPolyPolygon&	o_rPoly,
360cdf0e10cSrcweir                                const double 				nX,
361cdf0e10cSrcweir                                const double 				nY,
362cdf0e10cSrcweir                                const double 				nLineWidth,
363cdf0e10cSrcweir                                const double 				nLineHeight,
364cdf0e10cSrcweir                                const double 				nDashWidth,
365cdf0e10cSrcweir                                const double 				nDashSkip )
366cdf0e10cSrcweir             {
367cdf0e10cSrcweir                 const sal_Int32 nNumLoops(
368cdf0e10cSrcweir                     static_cast< sal_Int32 >(
369cdf0e10cSrcweir                         ::std::max( 1.0,
370cdf0e10cSrcweir                                     nLineWidth / nDashSkip ) + .5) );
371cdf0e10cSrcweir 
372cdf0e10cSrcweir                 double x = nX;
373cdf0e10cSrcweir                 for( sal_Int32 i=0; i<nNumLoops; ++i )
374cdf0e10cSrcweir                 {
375cdf0e10cSrcweir                     appendRect( o_rPoly,
376cdf0e10cSrcweir                                 x, 				nY,
377cdf0e10cSrcweir                                 x + nDashWidth, nY + nLineHeight );
378cdf0e10cSrcweir 
379cdf0e10cSrcweir                     x += nDashSkip;
380cdf0e10cSrcweir                 }
381cdf0e10cSrcweir             }
382cdf0e10cSrcweir         }
383cdf0e10cSrcweir 
384cdf0e10cSrcweir         // create line actions for text such as underline and
385cdf0e10cSrcweir         // strikeout
createTextLinesPolyPolygon(const::basegfx::B2DPoint rStartPos,const double & rLineWidth,const TextLineInfo & rTextLineInfo)386cdf0e10cSrcweir         ::basegfx::B2DPolyPolygon createTextLinesPolyPolygon( const ::basegfx::B2DPoint rStartPos,
387cdf0e10cSrcweir                                                               const double&				rLineWidth,
388cdf0e10cSrcweir                                                               const TextLineInfo&		rTextLineInfo )
389cdf0e10cSrcweir         {
390cdf0e10cSrcweir             // fill the polypolygon with all text lines
391cdf0e10cSrcweir             ::basegfx::B2DPolyPolygon aTextLinesPolyPoly;
392cdf0e10cSrcweir 
393cdf0e10cSrcweir             switch( rTextLineInfo.mnOverlineStyle )
394cdf0e10cSrcweir             {
395cdf0e10cSrcweir                 case UNDERLINE_NONE:    	  // nothing to do
396cdf0e10cSrcweir                     // FALLTHROUGH intended
397cdf0e10cSrcweir                 case UNDERLINE_DONTKNOW:
398cdf0e10cSrcweir                     break;
399cdf0e10cSrcweir 
400cdf0e10cSrcweir                 case UNDERLINE_SMALLWAVE:     // TODO(F3): NYI
401cdf0e10cSrcweir                     // FALLTHROUGH intended
402cdf0e10cSrcweir                 case UNDERLINE_WAVE:          // TODO(F3): NYI
403cdf0e10cSrcweir                     // FALLTHROUGH intended
404cdf0e10cSrcweir                 case UNDERLINE_SINGLE:
405cdf0e10cSrcweir                     appendRect(
406cdf0e10cSrcweir                         aTextLinesPolyPoly,
407cdf0e10cSrcweir                         rStartPos,
408cdf0e10cSrcweir                         0,
409cdf0e10cSrcweir                         rTextLineInfo.mnOverlineOffset,
410cdf0e10cSrcweir                         rLineWidth,
411cdf0e10cSrcweir                         rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight );
412cdf0e10cSrcweir                     break;
413cdf0e10cSrcweir 
414cdf0e10cSrcweir                 case UNDERLINE_BOLDDOTTED:    // TODO(F3): NYI
415cdf0e10cSrcweir                     // FALLTHROUGH intended
416cdf0e10cSrcweir                 case UNDERLINE_BOLDDASH:      // TODO(F3): NYI
417cdf0e10cSrcweir                     // FALLTHROUGH intended
418cdf0e10cSrcweir                 case UNDERLINE_BOLDLONGDASH:  // TODO(F3): NYI
419cdf0e10cSrcweir                     // FALLTHROUGH intended
420cdf0e10cSrcweir                 case UNDERLINE_BOLDDASHDOT:   // TODO(F3): NYI
421cdf0e10cSrcweir                     // FALLTHROUGH intended
422cdf0e10cSrcweir                 case UNDERLINE_BOLDDASHDOTDOT:// TODO(F3): NYI
423cdf0e10cSrcweir                     // FALLTHROUGH intended
424cdf0e10cSrcweir                 case UNDERLINE_BOLDWAVE:      // TODO(F3): NYI
425cdf0e10cSrcweir                     // FALLTHROUGH intended
426cdf0e10cSrcweir                 case UNDERLINE_BOLD:
427cdf0e10cSrcweir                     appendRect(
428cdf0e10cSrcweir                         aTextLinesPolyPoly,
429cdf0e10cSrcweir                         rStartPos,
430cdf0e10cSrcweir                         0,
431cdf0e10cSrcweir                         rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight,
432cdf0e10cSrcweir                         rLineWidth,
433cdf0e10cSrcweir                         rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight );
434cdf0e10cSrcweir                     break;
435cdf0e10cSrcweir 
436cdf0e10cSrcweir                 case UNDERLINE_DOUBLEWAVE:    // TODO(F3): NYI
437cdf0e10cSrcweir                     // FALLTHROUGH intended
438cdf0e10cSrcweir                 case UNDERLINE_DOUBLE:
439cdf0e10cSrcweir                     appendRect(
440cdf0e10cSrcweir                         aTextLinesPolyPoly,
441cdf0e10cSrcweir                         rStartPos,
442cdf0e10cSrcweir                         0,
443cdf0e10cSrcweir                         rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight * 2.0 ,
444cdf0e10cSrcweir                         rLineWidth,
445cdf0e10cSrcweir                         rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight );
446cdf0e10cSrcweir 
447cdf0e10cSrcweir                     appendRect(
448cdf0e10cSrcweir                         aTextLinesPolyPoly,
449cdf0e10cSrcweir                         rStartPos,
450cdf0e10cSrcweir                         0,
451cdf0e10cSrcweir                         rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight,
452cdf0e10cSrcweir                         rLineWidth,
453cdf0e10cSrcweir                         rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight * 2.0 );
454cdf0e10cSrcweir                     break;
455cdf0e10cSrcweir 
456cdf0e10cSrcweir                 case UNDERLINE_DASHDOTDOT:    // TODO(F3): NYI
457cdf0e10cSrcweir                     // FALLTHROUGH intended
458cdf0e10cSrcweir                 case UNDERLINE_DOTTED:
459cdf0e10cSrcweir                     appendDashes(
460cdf0e10cSrcweir                         aTextLinesPolyPoly,
461cdf0e10cSrcweir                         rStartPos.getX(),
462cdf0e10cSrcweir                         rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
463cdf0e10cSrcweir                         rLineWidth,
464cdf0e10cSrcweir                         rTextLineInfo.mnOverlineHeight,
465cdf0e10cSrcweir                         rTextLineInfo.mnOverlineHeight,
466cdf0e10cSrcweir                         2*rTextLineInfo.mnOverlineHeight );
467cdf0e10cSrcweir                     break;
468cdf0e10cSrcweir 
469cdf0e10cSrcweir                 case UNDERLINE_DASHDOT:       // TODO(F3): NYI
470cdf0e10cSrcweir                     // FALLTHROUGH intended
471cdf0e10cSrcweir                 case UNDERLINE_DASH:
472cdf0e10cSrcweir                     appendDashes(
473cdf0e10cSrcweir                         aTextLinesPolyPoly,
474cdf0e10cSrcweir                         rStartPos.getX(),
475cdf0e10cSrcweir                         rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
476cdf0e10cSrcweir                         rLineWidth,
477cdf0e10cSrcweir                         rTextLineInfo.mnOverlineHeight,
478cdf0e10cSrcweir                         3*rTextLineInfo.mnOverlineHeight,
479cdf0e10cSrcweir                         6*rTextLineInfo.mnOverlineHeight );
480cdf0e10cSrcweir                     break;
481cdf0e10cSrcweir 
482cdf0e10cSrcweir                 case UNDERLINE_LONGDASH:
483cdf0e10cSrcweir                     appendDashes(
484cdf0e10cSrcweir                         aTextLinesPolyPoly,
485cdf0e10cSrcweir                         rStartPos.getX(),
486cdf0e10cSrcweir                         rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
487cdf0e10cSrcweir                         rLineWidth,
488cdf0e10cSrcweir                         rTextLineInfo.mnOverlineHeight,
489cdf0e10cSrcweir                         6*rTextLineInfo.mnOverlineHeight,
490cdf0e10cSrcweir                         12*rTextLineInfo.mnOverlineHeight );
491cdf0e10cSrcweir                     break;
492cdf0e10cSrcweir 
493cdf0e10cSrcweir                 default:
494cdf0e10cSrcweir                     ENSURE_OR_THROW( false,
495cdf0e10cSrcweir                                       "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected overline case" );
496cdf0e10cSrcweir             }
497cdf0e10cSrcweir 
498cdf0e10cSrcweir             switch( rTextLineInfo.mnUnderlineStyle )
499cdf0e10cSrcweir             {
500cdf0e10cSrcweir                 case UNDERLINE_NONE:    	  // nothing to do
501cdf0e10cSrcweir                     // FALLTHROUGH intended
502cdf0e10cSrcweir                 case UNDERLINE_DONTKNOW:
503cdf0e10cSrcweir                     break;
504cdf0e10cSrcweir 
505cdf0e10cSrcweir                 case UNDERLINE_SMALLWAVE:     // TODO(F3): NYI
506cdf0e10cSrcweir                     // FALLTHROUGH intended
507cdf0e10cSrcweir                 case UNDERLINE_WAVE:          // TODO(F3): NYI
508cdf0e10cSrcweir                     // FALLTHROUGH intended
509cdf0e10cSrcweir                 case UNDERLINE_SINGLE:
510cdf0e10cSrcweir                     appendRect(
511cdf0e10cSrcweir                         aTextLinesPolyPoly,
512cdf0e10cSrcweir                         rStartPos,
513cdf0e10cSrcweir                         0,
514cdf0e10cSrcweir                         rTextLineInfo.mnUnderlineOffset,
515cdf0e10cSrcweir                         rLineWidth,
516cdf0e10cSrcweir                         rTextLineInfo.mnUnderlineOffset + rTextLineInfo.mnLineHeight );
517cdf0e10cSrcweir                     break;
518cdf0e10cSrcweir 
519cdf0e10cSrcweir                 case UNDERLINE_BOLDDOTTED:    // TODO(F3): NYI
520cdf0e10cSrcweir                     // FALLTHROUGH intended
521cdf0e10cSrcweir                 case UNDERLINE_BOLDDASH:      // TODO(F3): NYI
522cdf0e10cSrcweir                     // FALLTHROUGH intended
523cdf0e10cSrcweir                 case UNDERLINE_BOLDLONGDASH:  // TODO(F3): NYI
524cdf0e10cSrcweir                     // FALLTHROUGH intended
525cdf0e10cSrcweir                 case UNDERLINE_BOLDDASHDOT:   // TODO(F3): NYI
526cdf0e10cSrcweir                     // FALLTHROUGH intended
527cdf0e10cSrcweir                 case UNDERLINE_BOLDDASHDOTDOT:// TODO(F3): NYI
528cdf0e10cSrcweir                     // FALLTHROUGH intended
529cdf0e10cSrcweir                 case UNDERLINE_BOLDWAVE:      // TODO(F3): NYI
530cdf0e10cSrcweir                     // FALLTHROUGH intended
531cdf0e10cSrcweir                 case UNDERLINE_BOLD:
532cdf0e10cSrcweir                     appendRect(
533cdf0e10cSrcweir                         aTextLinesPolyPoly,
534cdf0e10cSrcweir                         rStartPos,
535cdf0e10cSrcweir                         0,
536cdf0e10cSrcweir                         rTextLineInfo.mnUnderlineOffset,
537cdf0e10cSrcweir                         rLineWidth,
538cdf0e10cSrcweir                         rTextLineInfo.mnUnderlineOffset + 2*rTextLineInfo.mnLineHeight );
539cdf0e10cSrcweir                     break;
540cdf0e10cSrcweir 
541cdf0e10cSrcweir                 case UNDERLINE_DOUBLEWAVE:    // TODO(F3): NYI
542cdf0e10cSrcweir                     // FALLTHROUGH intended
543cdf0e10cSrcweir                 case UNDERLINE_DOUBLE:
544cdf0e10cSrcweir                     appendRect(
545cdf0e10cSrcweir                         aTextLinesPolyPoly,
546cdf0e10cSrcweir                         rStartPos,
547cdf0e10cSrcweir                         0,
548cdf0e10cSrcweir                         rTextLineInfo.mnUnderlineOffset - rTextLineInfo.mnLineHeight,
549cdf0e10cSrcweir                         rLineWidth,
550cdf0e10cSrcweir                         rTextLineInfo.mnUnderlineOffset );
551cdf0e10cSrcweir 
552cdf0e10cSrcweir                     appendRect(
553cdf0e10cSrcweir                         aTextLinesPolyPoly,
554cdf0e10cSrcweir                         rStartPos,
555cdf0e10cSrcweir                         0,
556cdf0e10cSrcweir                         rTextLineInfo.mnUnderlineOffset + 2*rTextLineInfo.mnLineHeight,
557cdf0e10cSrcweir                         rLineWidth,
558cdf0e10cSrcweir                         rTextLineInfo.mnUnderlineOffset + 3*rTextLineInfo.mnLineHeight );
559cdf0e10cSrcweir                     break;
560cdf0e10cSrcweir 
561cdf0e10cSrcweir                 case UNDERLINE_DASHDOTDOT:    // TODO(F3): NYI
562cdf0e10cSrcweir                     // FALLTHROUGH intended
563cdf0e10cSrcweir                 case UNDERLINE_DOTTED:
564cdf0e10cSrcweir                     appendDashes(
565cdf0e10cSrcweir                         aTextLinesPolyPoly,
566cdf0e10cSrcweir                         rStartPos.getX(),
567cdf0e10cSrcweir                         rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
568cdf0e10cSrcweir                         rLineWidth,
569cdf0e10cSrcweir                         rTextLineInfo.mnLineHeight,
570cdf0e10cSrcweir                         rTextLineInfo.mnLineHeight,
571cdf0e10cSrcweir                         2*rTextLineInfo.mnLineHeight );
572cdf0e10cSrcweir                     break;
573cdf0e10cSrcweir 
574cdf0e10cSrcweir                 case UNDERLINE_DASHDOT:       // TODO(F3): NYI
575cdf0e10cSrcweir                     // FALLTHROUGH intended
576cdf0e10cSrcweir                 case UNDERLINE_DASH:
577cdf0e10cSrcweir                     appendDashes(
578cdf0e10cSrcweir                         aTextLinesPolyPoly,
579cdf0e10cSrcweir                         rStartPos.getX(),
580cdf0e10cSrcweir                         rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
581cdf0e10cSrcweir                         rLineWidth,
582cdf0e10cSrcweir                         rTextLineInfo.mnLineHeight,
583cdf0e10cSrcweir                         3*rTextLineInfo.mnLineHeight,
584cdf0e10cSrcweir                         6*rTextLineInfo.mnLineHeight );
585cdf0e10cSrcweir                     break;
586cdf0e10cSrcweir 
587cdf0e10cSrcweir                 case UNDERLINE_LONGDASH:
588cdf0e10cSrcweir                     appendDashes(
589cdf0e10cSrcweir                         aTextLinesPolyPoly,
590cdf0e10cSrcweir                         rStartPos.getX(),
591cdf0e10cSrcweir                         rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
592cdf0e10cSrcweir                         rLineWidth,
593cdf0e10cSrcweir                         rTextLineInfo.mnLineHeight,
594cdf0e10cSrcweir                         6*rTextLineInfo.mnLineHeight,
595cdf0e10cSrcweir                         12*rTextLineInfo.mnLineHeight );
596cdf0e10cSrcweir                     break;
597cdf0e10cSrcweir 
598cdf0e10cSrcweir                 default:
599cdf0e10cSrcweir                     ENSURE_OR_THROW( false,
600cdf0e10cSrcweir                                       "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected underline case" );
601cdf0e10cSrcweir             }
602cdf0e10cSrcweir 
603cdf0e10cSrcweir             switch( rTextLineInfo.mnStrikeoutStyle )
604cdf0e10cSrcweir             {
605cdf0e10cSrcweir                 case STRIKEOUT_NONE:    // nothing to do
606cdf0e10cSrcweir                     // FALLTHROUGH intended
607cdf0e10cSrcweir                 case STRIKEOUT_DONTKNOW:
608cdf0e10cSrcweir                     break;
609cdf0e10cSrcweir 
610cdf0e10cSrcweir                 case STRIKEOUT_SLASH:   // TODO(Q1): we should handle this in the text layer
611cdf0e10cSrcweir                     // FALLTHROUGH intended
612cdf0e10cSrcweir                 case STRIKEOUT_X:
613cdf0e10cSrcweir                     break;
614cdf0e10cSrcweir 
615cdf0e10cSrcweir                 case STRIKEOUT_SINGLE:
616cdf0e10cSrcweir                     appendRect(
617cdf0e10cSrcweir                         aTextLinesPolyPoly,
618cdf0e10cSrcweir                         rStartPos,
619cdf0e10cSrcweir                         0,
620cdf0e10cSrcweir                         rTextLineInfo.mnStrikeoutOffset,
621cdf0e10cSrcweir                         rLineWidth,
622cdf0e10cSrcweir                         rTextLineInfo.mnStrikeoutOffset + rTextLineInfo.mnLineHeight );
623cdf0e10cSrcweir                     break;
624cdf0e10cSrcweir 
625cdf0e10cSrcweir                 case STRIKEOUT_BOLD:
626cdf0e10cSrcweir                     appendRect(
627cdf0e10cSrcweir                         aTextLinesPolyPoly,
628cdf0e10cSrcweir                         rStartPos,
629cdf0e10cSrcweir                         0,
630cdf0e10cSrcweir                         rTextLineInfo.mnStrikeoutOffset,
631cdf0e10cSrcweir                         rLineWidth,
632cdf0e10cSrcweir                         rTextLineInfo.mnStrikeoutOffset + 2*rTextLineInfo.mnLineHeight );
633cdf0e10cSrcweir                     break;
634cdf0e10cSrcweir 
635cdf0e10cSrcweir                 case STRIKEOUT_DOUBLE:
636cdf0e10cSrcweir                     appendRect(
637cdf0e10cSrcweir                         aTextLinesPolyPoly,
638cdf0e10cSrcweir                         rStartPos,
639cdf0e10cSrcweir                         0,
640cdf0e10cSrcweir                         rTextLineInfo.mnStrikeoutOffset - rTextLineInfo.mnLineHeight,
641cdf0e10cSrcweir                         rLineWidth,
642cdf0e10cSrcweir                         rTextLineInfo.mnStrikeoutOffset );
643cdf0e10cSrcweir 
644cdf0e10cSrcweir                     appendRect(
645cdf0e10cSrcweir                         aTextLinesPolyPoly,
646cdf0e10cSrcweir                         rStartPos,
647cdf0e10cSrcweir                         0,
648cdf0e10cSrcweir                         rTextLineInfo.mnStrikeoutOffset + 2*rTextLineInfo.mnLineHeight,
649cdf0e10cSrcweir                         rLineWidth,
650cdf0e10cSrcweir                         rTextLineInfo.mnStrikeoutOffset + 3*rTextLineInfo.mnLineHeight );
651cdf0e10cSrcweir                     break;
652cdf0e10cSrcweir 
653cdf0e10cSrcweir                 default:
654cdf0e10cSrcweir                     ENSURE_OR_THROW( false,
655cdf0e10cSrcweir                                       "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected strikeout case" );
656cdf0e10cSrcweir             }
657cdf0e10cSrcweir 
658cdf0e10cSrcweir             return aTextLinesPolyPoly;
659cdf0e10cSrcweir         }
660cdf0e10cSrcweir 
calcDevicePixelBounds(const::basegfx::B2DRange & rBounds,const rendering::ViewState & viewState,const rendering::RenderState & renderState)661cdf0e10cSrcweir         ::basegfx::B2DRange calcDevicePixelBounds( const ::basegfx::B2DRange& 		rBounds,
662cdf0e10cSrcweir                                                    const rendering::ViewState&		viewState,
663cdf0e10cSrcweir                                                    const rendering::RenderState&	renderState )
664cdf0e10cSrcweir         {
665cdf0e10cSrcweir             ::basegfx::B2DHomMatrix aTransform;
666cdf0e10cSrcweir             ::canvas::tools::mergeViewAndRenderTransform( aTransform,
667cdf0e10cSrcweir                                                           viewState,
668cdf0e10cSrcweir                                                           renderState );
669cdf0e10cSrcweir 
670cdf0e10cSrcweir             ::basegfx::B2DRange aTransformedBounds;
671cdf0e10cSrcweir             return ::canvas::tools::calcTransformedRectBounds( aTransformedBounds,
672cdf0e10cSrcweir                                                                rBounds,
673cdf0e10cSrcweir                                                                aTransform );
674cdf0e10cSrcweir         }
675cdf0e10cSrcweir 
676cdf0e10cSrcweir         // create line actions for text such as underline and
677cdf0e10cSrcweir         // strikeout
createTextLinesPolyPolygon(const double & rStartOffset,const double & rLineWidth,const TextLineInfo & rTextLineInfo)678cdf0e10cSrcweir         ::basegfx::B2DPolyPolygon createTextLinesPolyPolygon( const double&			rStartOffset,
679cdf0e10cSrcweir                                                               const double&			rLineWidth,
680cdf0e10cSrcweir                                                               const TextLineInfo&	rTextLineInfo )
681cdf0e10cSrcweir         {
682cdf0e10cSrcweir             return createTextLinesPolyPolygon(
683cdf0e10cSrcweir                 ::basegfx::B2DPoint( rStartOffset,
684cdf0e10cSrcweir                                      0.0 ),
685cdf0e10cSrcweir                 rLineWidth,
686cdf0e10cSrcweir                 rTextLineInfo );
687cdf0e10cSrcweir         }
688cdf0e10cSrcweir     }
689cdf0e10cSrcweir }
690