update dev300-m58
[ooovba.git] / cppcanvas / source / mtfrenderer / mtftools.cxx
blobb8a2ec14232ed2a86dbb95b0a9d30442e182369f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: mtftools.cxx,v $
10 * $Revision: 1.14.6.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_cppcanvas.hxx"
34 #include <canvas/debug.hxx>
35 #include <tools/diagnose_ex.h>
36 #include <canvas/verbosetrace.hxx>
38 #include <com/sun/star/rendering/RenderState.hpp>
39 #include <com/sun/star/rendering/XCanvas.hpp>
41 #include <basegfx/numeric/ftools.hxx>
42 #include <basegfx/tools/canvastools.hxx>
43 #include <basegfx/polygon/b2dpolygontools.hxx>
44 #include <basegfx/polygon/b2dpolygon.hxx>
45 #include <basegfx/range/b2drectangle.hxx>
46 #include <basegfx/vector/b2dvector.hxx>
47 #include <canvas/canvastools.hxx>
49 #include <vcl/gdimtf.hxx>
50 #include <vcl/metaact.hxx>
51 #include <vcl/virdev.hxx>
52 #include <vcl/metric.hxx>
53 #include <tools/poly.hxx>
55 #include "mtftools.hxx"
56 #include "outdevstate.hxx"
57 #include "polypolyaction.hxx"
61 using namespace ::com::sun::star;
63 namespace cppcanvas
65 namespace tools
67 void initRenderState( rendering::RenderState& renderState,
68 const ::cppcanvas::internal::OutDevState& outdevState )
70 ::canvas::tools::initRenderState( renderState );
71 ::canvas::tools::setRenderStateTransform( renderState,
72 outdevState.transform );
73 renderState.Clip = outdevState.xClipPoly;
76 ::Size getBaselineOffset( const ::cppcanvas::internal::OutDevState& outdevState,
77 const VirtualDevice& rVDev )
79 const ::FontMetric& aMetric = rVDev.GetFontMetric();
81 // calc offset for text output, the XCanvas always renders
82 // baseline offset.
83 switch( outdevState.textReferencePoint )
85 case ALIGN_TOP:
86 return ::Size( 0,
87 aMetric.GetIntLeading() + aMetric.GetAscent() );
89 default:
90 ENSURE_OR_THROW( false,
91 "tools::getBaselineOffset(): Unexpected TextAlign value" );
92 // FALLTHROUGH intended (to calm compiler warning - case won't happen)
93 case ALIGN_BASELINE:
94 return ::Size( 0, 0 );
96 case ALIGN_BOTTOM:
97 return ::Size( 0,
98 -aMetric.GetDescent() );
103 ::basegfx::B2DHomMatrix& calcLogic2PixelLinearTransform( ::basegfx::B2DHomMatrix& o_rMatrix,
104 const VirtualDevice& rVDev )
106 // select size value in the middle of the available range,
107 // to have headroom both when map mode scales up, and when
108 // it scales down.
109 const ::Size aSizeLogic( 0x00010000L,
110 0x00010000L );
112 const ::Size aSizePixel( rVDev.LogicToPixel( aSizeLogic ) );
114 o_rMatrix.identity();
115 o_rMatrix.scale( aSizePixel.Width() / (double)aSizeLogic.Width(),
116 aSizePixel.Height() / (double)aSizeLogic.Height() );
118 return o_rMatrix;
121 ::basegfx::B2DHomMatrix& calcLogic2PixelAffineTransform( ::basegfx::B2DHomMatrix& o_rMatrix,
122 const VirtualDevice& rVDev )
124 // retrieves scale
125 calcLogic2PixelLinearTransform(o_rMatrix, rVDev);
127 // translate according to curr map mode/pref map mode offset
128 const ::Point aEmptyPoint;
129 const ::Point& rTranslatedPoint(
130 rVDev.LogicToPixel( aEmptyPoint ));
132 o_rMatrix.translate(rTranslatedPoint.X(),
133 rTranslatedPoint.Y());
135 return o_rMatrix;
138 bool modifyClip( rendering::RenderState& o_rRenderState,
139 const struct ::cppcanvas::internal::OutDevState& rOutdevState,
140 const CanvasSharedPtr& rCanvas,
141 const ::basegfx::B2DPoint& rOffset,
142 const ::basegfx::B2DVector* pScaling,
143 const double* pRotation )
145 const ::Point aEmptyPoint;
147 const bool bOffsetting( !rOffset.equalZero() );
148 const bool bScaling( pScaling &&
149 pScaling->getX() != 1.0 &&
150 pScaling->getY() != 1.0 );
151 const bool bRotation( pRotation &&
152 *pRotation != 0.0 );
154 if( !bOffsetting && !bScaling && !bRotation )
155 return false; // nothing to do
157 if( rOutdevState.clip.count() )
159 // general polygon case
161 ::basegfx::B2DPolyPolygon aLocalClip( rOutdevState.clip );
162 ::basegfx::B2DHomMatrix aTransform;
164 if( bOffsetting )
165 aTransform.translate( -rOffset.getX(),
166 -rOffset.getY() );
167 if( bScaling )
168 aTransform.scale( 1.0/pScaling->getX(), 1.0/pScaling->getY() );
170 if( bRotation )
171 aTransform.rotate( - *pRotation );
173 aLocalClip.transform( aTransform );
175 o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
176 rCanvas->getUNOCanvas()->getDevice(),
177 aLocalClip );
179 return true;
181 else if( !rOutdevState.clipRect.IsEmpty() )
183 // simple rect case
185 const ::Rectangle aLocalClipRect( rOutdevState.clipRect );
187 if( bRotation )
189 // rotation involved - convert to polygon first,
190 // then transform that
191 ::basegfx::B2DPolygon aLocalClip(
192 ::basegfx::tools::createPolygonFromRect(
193 ::basegfx::B2DRectangle(
194 (double)(aLocalClipRect.Left()),
195 (double)(aLocalClipRect.Top()),
196 (double)(aLocalClipRect.Right()),
197 (double)(aLocalClipRect.Bottom()) ) ) );
198 ::basegfx::B2DHomMatrix aTransform;
200 if( bOffsetting )
201 aTransform.translate( -rOffset.getX(),
202 -rOffset.getY() );
203 if( bScaling )
204 aTransform.scale( 1.0/pScaling->getX(), 1.0/pScaling->getY() );
206 aTransform.rotate( - *pRotation );
208 aLocalClip.transform( aTransform );
210 o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
211 rCanvas->getUNOCanvas()->getDevice(),
212 ::basegfx::B2DPolyPolygon( aLocalClip ) );
214 else if( bScaling )
216 // scale and offset - do it on the fly, have to
217 // convert to float anyway.
218 o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
219 rCanvas->getUNOCanvas()->getDevice(),
220 ::basegfx::B2DPolyPolygon(
221 ::basegfx::tools::createPolygonFromRect(
222 ::basegfx::B2DRectangle(
223 (double)(aLocalClipRect.Left() - rOffset.getX())/pScaling->getX(),
224 (double)(aLocalClipRect.Top() - rOffset.getY())/pScaling->getY(),
225 (double)(aLocalClipRect.Right() - rOffset.getX())/pScaling->getX(),
226 (double)(aLocalClipRect.Bottom() - rOffset.getY())/pScaling->getY() ) ) ) );
228 else
230 // offset only - do it on the fly, have to convert
231 // to float anyway.
232 o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
233 rCanvas->getUNOCanvas()->getDevice(),
234 ::basegfx::B2DPolyPolygon(
235 ::basegfx::tools::createPolygonFromRect(
236 ::basegfx::B2DRectangle( aLocalClipRect.Left() - rOffset.getX(),
237 aLocalClipRect.Top() - rOffset.getY(),
238 aLocalClipRect.Right() - rOffset.getX(),
239 aLocalClipRect.Bottom() - rOffset.getY() ) ) ) );
242 return true;
245 // empty clip, nothing to do
246 return false;
249 bool modifyClip( rendering::RenderState& o_rRenderState,
250 const struct ::cppcanvas::internal::OutDevState& rOutdevState,
251 const CanvasSharedPtr& rCanvas,
252 const ::Point& rOffset,
253 const ::basegfx::B2DVector* pScaling,
254 const double* pRotation )
256 return modifyClip( o_rRenderState,
257 rOutdevState,
258 rCanvas,
259 ::basegfx::B2DPoint( rOffset.X(),
260 rOffset.Y() ),
261 pScaling,
262 pRotation );
265 bool modifyClip( rendering::RenderState& o_rRenderState,
266 const struct ::cppcanvas::internal::OutDevState& rOutdevState,
267 const CanvasSharedPtr& rCanvas,
268 const ::basegfx::B2DHomMatrix& rTransform )
270 if( !rTransform.isIdentity() ||
271 !rTransform.isInvertible() )
272 return false; // nothing to do
274 ::basegfx::B2DPolyPolygon aLocalClip;
276 if( rOutdevState.clip.count() )
278 aLocalClip = rOutdevState.clip;
280 else if( !rOutdevState.clipRect.IsEmpty() )
282 const ::Rectangle aLocalClipRect( rOutdevState.clipRect );
284 aLocalClip = ::basegfx::B2DPolyPolygon(
285 ::basegfx::tools::createPolygonFromRect(
286 ::basegfx::B2DRectangle(
287 aLocalClipRect.Left(),
288 aLocalClipRect.Top(),
289 aLocalClipRect.Right(),
290 aLocalClipRect.Bottom() ) ) );
292 else
294 // empty clip, nothing to do
295 return false;
298 // invert transformation and modify
299 ::basegfx::B2DHomMatrix aLocalTransform( rTransform );
300 aLocalTransform.invert();
302 aLocalClip.transform( aLocalTransform );
304 o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
305 rCanvas->getUNOCanvas()->getDevice(),
306 aLocalClip );
308 return true;
311 // create overline/underline/strikeout line info struct
312 TextLineInfo createTextLineInfo( const ::VirtualDevice& rVDev,
313 const ::cppcanvas::internal::OutDevState& rState )
315 const BOOL bOldMode( rVDev.IsMapModeEnabled() );
317 // #i68512# Force metric regeneration with mapmode enabled
318 // (prolly OutDev bug)
319 rVDev.GetFontMetric();
321 // will restore map mode below
322 const_cast< ::VirtualDevice& >(rVDev).EnableMapMode( FALSE );
324 const ::FontMetric aMetric = rVDev.GetFontMetric();
326 TextLineInfo aTextInfo(
327 (aMetric.GetDescent() + 2) / 4.0,
328 ((aMetric.GetIntLeading() + 1.5) / 3.0),
329 (aMetric.GetIntLeading() / 2.0) - aMetric.GetAscent(),
330 aMetric.GetDescent() / 2.0,
331 (aMetric.GetIntLeading() - aMetric.GetAscent()) / 3.0,
332 rState.textOverlineStyle,
333 rState.textUnderlineStyle,
334 rState.textStrikeoutStyle );
336 const_cast< ::VirtualDevice& >(rVDev).EnableMapMode( bOldMode );
338 return aTextInfo;
341 namespace
343 void appendRect( ::basegfx::B2DPolyPolygon& o_rPoly,
344 const ::basegfx::B2DPoint& rStartPos,
345 const double nX1,
346 const double nY1,
347 const double nX2,
348 const double nY2 )
350 const double x( rStartPos.getX() );
351 const double y( rStartPos.getY() );
353 o_rPoly.append(
354 ::basegfx::tools::createPolygonFromRect(
355 ::basegfx::B2DRectangle( x + nX1, y + nY1, x + nX2, y + nY2 ) ) );
358 void appendRect( ::basegfx::B2DPolyPolygon& o_rPoly,
359 const double nX1,
360 const double nY1,
361 const double nX2,
362 const double nY2 )
364 o_rPoly.append(
365 ::basegfx::tools::createPolygonFromRect(
366 ::basegfx::B2DRectangle( nX1, nY1, nX2, nY2 ) ) );
369 void appendDashes( ::basegfx::B2DPolyPolygon& o_rPoly,
370 const double nX,
371 const double nY,
372 const double nLineWidth,
373 const double nLineHeight,
374 const double nDashWidth,
375 const double nDashSkip )
377 const sal_Int32 nNumLoops(
378 static_cast< sal_Int32 >(
379 ::std::max( 1.0,
380 nLineWidth / nDashSkip ) + .5) );
382 double x = nX;
383 for( sal_Int32 i=0; i<nNumLoops; ++i )
385 appendRect( o_rPoly,
386 x, nY,
387 x + nDashWidth, nY + nLineHeight );
389 x += nDashSkip;
394 // create line actions for text such as underline and
395 // strikeout
396 ::basegfx::B2DPolyPolygon createTextLinesPolyPolygon( const ::basegfx::B2DPoint rStartPos,
397 const double& rLineWidth,
398 const TextLineInfo& rTextLineInfo )
400 // fill the polypolygon with all text lines
401 ::basegfx::B2DPolyPolygon aTextLinesPolyPoly;
403 switch( rTextLineInfo.mnOverlineStyle )
405 case UNDERLINE_NONE: // nothing to do
406 // FALLTHROUGH intended
407 case UNDERLINE_DONTKNOW:
408 break;
410 case UNDERLINE_SMALLWAVE: // TODO(F3): NYI
411 // FALLTHROUGH intended
412 case UNDERLINE_WAVE: // TODO(F3): NYI
413 // FALLTHROUGH intended
414 case UNDERLINE_SINGLE:
415 appendRect(
416 aTextLinesPolyPoly,
417 rStartPos,
419 rTextLineInfo.mnOverlineOffset,
420 rLineWidth,
421 rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight );
422 break;
424 case UNDERLINE_BOLDDOTTED: // TODO(F3): NYI
425 // FALLTHROUGH intended
426 case UNDERLINE_BOLDDASH: // TODO(F3): NYI
427 // FALLTHROUGH intended
428 case UNDERLINE_BOLDLONGDASH: // TODO(F3): NYI
429 // FALLTHROUGH intended
430 case UNDERLINE_BOLDDASHDOT: // TODO(F3): NYI
431 // FALLTHROUGH intended
432 case UNDERLINE_BOLDDASHDOTDOT:// TODO(F3): NYI
433 // FALLTHROUGH intended
434 case UNDERLINE_BOLDWAVE: // TODO(F3): NYI
435 // FALLTHROUGH intended
436 case UNDERLINE_BOLD:
437 appendRect(
438 aTextLinesPolyPoly,
439 rStartPos,
441 rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight,
442 rLineWidth,
443 rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight );
444 break;
446 case UNDERLINE_DOUBLEWAVE: // TODO(F3): NYI
447 // FALLTHROUGH intended
448 case UNDERLINE_DOUBLE:
449 appendRect(
450 aTextLinesPolyPoly,
451 rStartPos,
453 rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight * 2.0 ,
454 rLineWidth,
455 rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight );
457 appendRect(
458 aTextLinesPolyPoly,
459 rStartPos,
461 rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight,
462 rLineWidth,
463 rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight * 2.0 );
464 break;
466 case UNDERLINE_DASHDOTDOT: // TODO(F3): NYI
467 // FALLTHROUGH intended
468 case UNDERLINE_DOTTED:
469 appendDashes(
470 aTextLinesPolyPoly,
471 rStartPos.getX(),
472 rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
473 rLineWidth,
474 rTextLineInfo.mnOverlineHeight,
475 rTextLineInfo.mnOverlineHeight,
476 2*rTextLineInfo.mnOverlineHeight );
477 break;
479 case UNDERLINE_DASHDOT: // TODO(F3): NYI
480 // FALLTHROUGH intended
481 case UNDERLINE_DASH:
482 appendDashes(
483 aTextLinesPolyPoly,
484 rStartPos.getX(),
485 rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
486 rLineWidth,
487 rTextLineInfo.mnOverlineHeight,
488 3*rTextLineInfo.mnOverlineHeight,
489 6*rTextLineInfo.mnOverlineHeight );
490 break;
492 case UNDERLINE_LONGDASH:
493 appendDashes(
494 aTextLinesPolyPoly,
495 rStartPos.getX(),
496 rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
497 rLineWidth,
498 rTextLineInfo.mnOverlineHeight,
499 6*rTextLineInfo.mnOverlineHeight,
500 12*rTextLineInfo.mnOverlineHeight );
501 break;
503 default:
504 ENSURE_OR_THROW( false,
505 "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected overline case" );
508 switch( rTextLineInfo.mnUnderlineStyle )
510 case UNDERLINE_NONE: // nothing to do
511 // FALLTHROUGH intended
512 case UNDERLINE_DONTKNOW:
513 break;
515 case UNDERLINE_SMALLWAVE: // TODO(F3): NYI
516 // FALLTHROUGH intended
517 case UNDERLINE_WAVE: // TODO(F3): NYI
518 // FALLTHROUGH intended
519 case UNDERLINE_SINGLE:
520 appendRect(
521 aTextLinesPolyPoly,
522 rStartPos,
524 rTextLineInfo.mnUnderlineOffset,
525 rLineWidth,
526 rTextLineInfo.mnUnderlineOffset + rTextLineInfo.mnLineHeight );
527 break;
529 case UNDERLINE_BOLDDOTTED: // TODO(F3): NYI
530 // FALLTHROUGH intended
531 case UNDERLINE_BOLDDASH: // TODO(F3): NYI
532 // FALLTHROUGH intended
533 case UNDERLINE_BOLDLONGDASH: // TODO(F3): NYI
534 // FALLTHROUGH intended
535 case UNDERLINE_BOLDDASHDOT: // TODO(F3): NYI
536 // FALLTHROUGH intended
537 case UNDERLINE_BOLDDASHDOTDOT:// TODO(F3): NYI
538 // FALLTHROUGH intended
539 case UNDERLINE_BOLDWAVE: // TODO(F3): NYI
540 // FALLTHROUGH intended
541 case UNDERLINE_BOLD:
542 appendRect(
543 aTextLinesPolyPoly,
544 rStartPos,
546 rTextLineInfo.mnUnderlineOffset,
547 rLineWidth,
548 rTextLineInfo.mnUnderlineOffset + 2*rTextLineInfo.mnLineHeight );
549 break;
551 case UNDERLINE_DOUBLEWAVE: // TODO(F3): NYI
552 // FALLTHROUGH intended
553 case UNDERLINE_DOUBLE:
554 appendRect(
555 aTextLinesPolyPoly,
556 rStartPos,
558 rTextLineInfo.mnUnderlineOffset - rTextLineInfo.mnLineHeight,
559 rLineWidth,
560 rTextLineInfo.mnUnderlineOffset );
562 appendRect(
563 aTextLinesPolyPoly,
564 rStartPos,
566 rTextLineInfo.mnUnderlineOffset + 2*rTextLineInfo.mnLineHeight,
567 rLineWidth,
568 rTextLineInfo.mnUnderlineOffset + 3*rTextLineInfo.mnLineHeight );
569 break;
571 case UNDERLINE_DASHDOTDOT: // TODO(F3): NYI
572 // FALLTHROUGH intended
573 case UNDERLINE_DOTTED:
574 appendDashes(
575 aTextLinesPolyPoly,
576 rStartPos.getX(),
577 rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
578 rLineWidth,
579 rTextLineInfo.mnLineHeight,
580 rTextLineInfo.mnLineHeight,
581 2*rTextLineInfo.mnLineHeight );
582 break;
584 case UNDERLINE_DASHDOT: // TODO(F3): NYI
585 // FALLTHROUGH intended
586 case UNDERLINE_DASH:
587 appendDashes(
588 aTextLinesPolyPoly,
589 rStartPos.getX(),
590 rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
591 rLineWidth,
592 rTextLineInfo.mnLineHeight,
593 3*rTextLineInfo.mnLineHeight,
594 6*rTextLineInfo.mnLineHeight );
595 break;
597 case UNDERLINE_LONGDASH:
598 appendDashes(
599 aTextLinesPolyPoly,
600 rStartPos.getX(),
601 rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
602 rLineWidth,
603 rTextLineInfo.mnLineHeight,
604 6*rTextLineInfo.mnLineHeight,
605 12*rTextLineInfo.mnLineHeight );
606 break;
608 default:
609 ENSURE_OR_THROW( false,
610 "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected underline case" );
613 switch( rTextLineInfo.mnStrikeoutStyle )
615 case STRIKEOUT_NONE: // nothing to do
616 // FALLTHROUGH intended
617 case STRIKEOUT_DONTKNOW:
618 break;
620 case STRIKEOUT_SLASH: // TODO(Q1): we should handle this in the text layer
621 // FALLTHROUGH intended
622 case STRIKEOUT_X:
623 break;
625 case STRIKEOUT_SINGLE:
626 appendRect(
627 aTextLinesPolyPoly,
628 rStartPos,
630 rTextLineInfo.mnStrikeoutOffset,
631 rLineWidth,
632 rTextLineInfo.mnStrikeoutOffset + rTextLineInfo.mnLineHeight );
633 break;
635 case STRIKEOUT_BOLD:
636 appendRect(
637 aTextLinesPolyPoly,
638 rStartPos,
640 rTextLineInfo.mnStrikeoutOffset,
641 rLineWidth,
642 rTextLineInfo.mnStrikeoutOffset + 2*rTextLineInfo.mnLineHeight );
643 break;
645 case STRIKEOUT_DOUBLE:
646 appendRect(
647 aTextLinesPolyPoly,
648 rStartPos,
650 rTextLineInfo.mnStrikeoutOffset - rTextLineInfo.mnLineHeight,
651 rLineWidth,
652 rTextLineInfo.mnStrikeoutOffset );
654 appendRect(
655 aTextLinesPolyPoly,
656 rStartPos,
658 rTextLineInfo.mnStrikeoutOffset + 2*rTextLineInfo.mnLineHeight,
659 rLineWidth,
660 rTextLineInfo.mnStrikeoutOffset + 3*rTextLineInfo.mnLineHeight );
661 break;
663 default:
664 ENSURE_OR_THROW( false,
665 "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected strikeout case" );
668 return aTextLinesPolyPoly;
671 ::basegfx::B2DRange calcDevicePixelBounds( const ::basegfx::B2DRange& rBounds,
672 const rendering::ViewState& viewState,
673 const rendering::RenderState& renderState )
675 ::basegfx::B2DHomMatrix aTransform;
676 ::canvas::tools::mergeViewAndRenderTransform( aTransform,
677 viewState,
678 renderState );
680 ::basegfx::B2DRange aTransformedBounds;
681 return ::canvas::tools::calcTransformedRectBounds( aTransformedBounds,
682 rBounds,
683 aTransform );
686 // create line actions for text such as underline and
687 // strikeout
688 ::basegfx::B2DPolyPolygon createTextLinesPolyPolygon( const double& rStartOffset,
689 const double& rLineWidth,
690 const TextLineInfo& rTextLineInfo )
692 return createTextLinesPolyPolygon(
693 ::basegfx::B2DPoint( rStartOffset,
694 0.0 ),
695 rLineWidth,
696 rTextLineInfo );