1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: textaction.cxx,v $
10 * $Revision: 1.22.4.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 <rtl/logfile.hxx>
40 #include <com/sun/star/rendering/PathCapType.hpp>
41 #include <com/sun/star/rendering/PathJoinType.hpp>
42 #include <com/sun/star/rendering/XCanvas.hpp>
43 #include <com/sun/star/rendering/XCanvasFont.hpp>
45 #include <basegfx/numeric/ftools.hxx>
46 #include <basegfx/matrix/b2dhommatrix.hxx>
47 #include <basegfx/range/b2drectangle.hxx>
48 #include <basegfx/vector/b2dsize.hxx>
49 #include <basegfx/polygon/b2dpolypolygontools.hxx>
50 #include <basegfx/polygon/b2dpolygontools.hxx>
52 #include <tools/gen.hxx>
53 #include <vcl/canvastools.hxx>
54 #include <vcl/virdev.hxx>
56 #include <basegfx/tools/canvastools.hxx>
57 #include <canvas/canvastools.hxx>
59 #include <boost/scoped_array.hpp>
60 #include <boost/bind.hpp>
61 #include <boost/utility.hpp>
63 #include "textaction.hxx"
64 #include "outdevstate.hxx"
65 #include "mtftools.hxx"
68 using namespace ::com::sun::star
;
76 void init( rendering::RenderState
& o_rRenderState
,
77 const ::basegfx::B2DPoint
& rStartPoint
,
78 const OutDevState
& rState
,
79 const CanvasSharedPtr
& rCanvas
)
81 tools::initRenderState(o_rRenderState
,rState
);
83 // #i36950# Offset clip back to origin (as it's also moved
85 // #i53964# Also take VCL font rotation into account,
86 // since this, opposed to the FontMatrix rotation
87 // elsewhere, _does_ get incorporated into the render
89 tools::modifyClip( o_rRenderState
,
94 &rState
.fontRotation
);
96 ::basegfx::B2DHomMatrix aLocalTransformation
;
98 aLocalTransformation
.rotate( rState
.fontRotation
);
99 aLocalTransformation
.translate( rStartPoint
.getX(),
100 rStartPoint
.getY() );
101 ::canvas::tools::appendToRenderState( o_rRenderState
,
102 aLocalTransformation
);
104 o_rRenderState
.DeviceColor
= rState
.textColor
;
107 void init( rendering::RenderState
& o_rRenderState
,
108 const ::basegfx::B2DPoint
& rStartPoint
,
109 const OutDevState
& rState
,
110 const CanvasSharedPtr
& rCanvas
,
111 const ::basegfx::B2DHomMatrix
& rTextTransform
)
113 init( o_rRenderState
, rStartPoint
, rState
, rCanvas
);
115 // TODO(F2): Also inversely-transform clip with
116 // rTextTransform (which is actually rather hard, as the
117 // text transform is _prepended_ to the render state)!
119 // prepend extra font transform to render state
120 // (prepend it, because it's interpreted in the unit
121 // rect coordinate space)
122 ::canvas::tools::prependToRenderState( o_rRenderState
,
126 void init( rendering::RenderState
& o_rRenderState
,
127 uno::Reference
< rendering::XCanvasFont
>& o_rFont
,
128 const ::basegfx::B2DPoint
& rStartPoint
,
129 const OutDevState
& rState
,
130 const CanvasSharedPtr
& rCanvas
)
132 // ensure that o_rFont is valid. It is possible that
133 // text actions are generated without previously
134 // setting a font. Then, just take a default font
137 // Use completely default FontRequest
138 const rendering::FontRequest aFontRequest
;
140 geometry::Matrix2D aFontMatrix
;
141 ::canvas::tools::setIdentityMatrix2D( aFontMatrix
);
143 o_rFont
= rCanvas
->getUNOCanvas()->createFont(
145 uno::Sequence
< beans::PropertyValue
>(),
149 init( o_rRenderState
,
155 void init( rendering::RenderState
& o_rRenderState
,
156 uno::Reference
< rendering::XCanvasFont
>& o_rFont
,
157 const ::basegfx::B2DPoint
& rStartPoint
,
158 const OutDevState
& rState
,
159 const CanvasSharedPtr
& rCanvas
,
160 const ::basegfx::B2DHomMatrix
& rTextTransform
)
162 init( o_rRenderState
, o_rFont
, rStartPoint
, rState
, rCanvas
);
164 // TODO(F2): Also inversely-transform clip with
165 // rTextTransform (which is actually rather hard, as the
166 // text transform is _prepended_ to the render state)!
168 // prepend extra font transform to render state
169 // (prepend it, because it's interpreted in the unit
170 // rect coordinate space)
171 ::canvas::tools::prependToRenderState( o_rRenderState
,
175 ::basegfx::B2DPolyPolygon
textLinesFromLogicalOffsets( const uno::Sequence
< double >& rOffsets
,
176 const tools::TextLineInfo
& rTextLineInfo
)
178 return tools::createTextLinesPolyPolygon(
180 // extract character cell furthest to the right
181 *(::std::max_element(
182 rOffsets
.getConstArray(),
183 rOffsets
.getConstArray() + rOffsets
.getLength() )),
187 uno::Sequence
< double > setupDXArray( const sal_Int32
* pCharWidths
,
189 const OutDevState
& rState
)
191 // convert character widths from logical units
192 uno::Sequence
< double > aCharWidthSeq( nLen
);
193 double* pOutputWidths( aCharWidthSeq
.getArray() );
195 // #143885# maintain (nearly) full precision of DX
196 // array, by circumventing integer-based
198 const double nScale( rState
.mapModeTransform
.get(0,0) );
199 for( int i
= 0; i
< nLen
; ++i
)
201 // TODO(F2): use correct scale direction
202 *pOutputWidths
++ = *pCharWidths
++ * nScale
;
205 return aCharWidthSeq
;
208 uno::Sequence
< double > setupDXArray( const ::String
& rText
,
211 VirtualDevice
& rVDev
,
212 const OutDevState
& rState
)
214 // no external DX array given, create one from given
216 ::boost::scoped_array
< sal_Int32
> pCharWidths( new sal_Int32
[nLen
] );
218 rVDev
.GetTextArray( rText
, pCharWidths
.get(),
219 static_cast<USHORT
>(nStartPos
),
220 static_cast<USHORT
>(nLen
) );
222 return setupDXArray( pCharWidths
.get(), nLen
, rState
);
225 ::basegfx::B2DPoint
adaptStartPoint( const ::basegfx::B2DPoint
& rStartPoint
,
226 const OutDevState
& rState
,
227 const uno::Sequence
< double >& rOffsets
)
229 ::basegfx::B2DPoint
aLocalPoint( rStartPoint
);
231 if( rState
.textAlignment
)
233 // text origin is right, not left. Modify start point
234 // accordingly, because XCanvas::drawTextLayout()
235 // always aligns left!
237 const double nOffset( rOffsets
[ rOffsets
.getLength()-1 ] );
239 // correct start point for rotated text: rotate around
240 // former start point
241 aLocalPoint
.setX( aLocalPoint
.getX() + cos( rState
.fontRotation
)*nOffset
);
242 aLocalPoint
.setY( aLocalPoint
.getY() + sin( rState
.fontRotation
)*nOffset
);
248 /** Perform common setup for array text actions
250 This method creates the XTextLayout object and
251 initializes it, e.g. with the logical advancements.
253 void initArrayAction( rendering::RenderState
& o_rRenderState
,
254 uno::Reference
< rendering::XTextLayout
>& o_rTextLayout
,
255 const ::basegfx::B2DPoint
& rStartPoint
,
256 const ::rtl::OUString
& rText
,
259 const uno::Sequence
< double >& rOffsets
,
260 const CanvasSharedPtr
& rCanvas
,
261 const OutDevState
& rState
,
262 const ::basegfx::B2DHomMatrix
* pTextTransform
)
264 ENSURE_OR_THROW( rOffsets
.getLength(),
265 "::cppcanvas::internal::initArrayAction(): zero-length DX array" );
267 const ::basegfx::B2DPoint
aLocalStartPoint(
268 adaptStartPoint( rStartPoint
, rState
, rOffsets
) );
270 uno::Reference
< rendering::XCanvasFont
> xFont( rState
.xFont
);
273 init( o_rRenderState
, xFont
, aLocalStartPoint
, rState
, rCanvas
, *pTextTransform
);
275 init( o_rRenderState
, xFont
, aLocalStartPoint
, rState
, rCanvas
);
277 o_rTextLayout
= xFont
->createTextLayout(
278 rendering::StringContext( rText
, nStartPos
, nLen
),
279 rState
.textDirection
,
282 ENSURE_OR_THROW( o_rTextLayout
.is(),
283 "::cppcanvas::internal::initArrayAction(): Invalid font" );
285 o_rTextLayout
->applyLogicalAdvancements( rOffsets
);
288 double getLineWidth( ::VirtualDevice
& rVDev
,
289 const OutDevState
& rState
,
290 const rendering::StringContext
& rStringContext
)
292 // TODO(F2): use correct scale direction
293 const ::basegfx::B2DSize
aSize( rVDev
.GetTextWidth( rStringContext
.Text
,
294 static_cast<USHORT
>(rStringContext
.StartPosition
),
295 static_cast<USHORT
>(rStringContext
.Length
) ),
298 return (rState
.mapModeTransform
* aSize
).getX();
301 uno::Sequence
< double >
302 calcSubsetOffsets( rendering::RenderState
& io_rRenderState
,
305 const uno::Reference
< rendering::XTextLayout
>& rOrigTextLayout
,
306 const ::cppcanvas::internal::Action::Subset
& rSubset
)
308 ENSURE_OR_THROW( rSubset
.mnSubsetEnd
> rSubset
.mnSubsetBegin
,
309 "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );
311 uno::Sequence
< double > aOrigOffsets( rOrigTextLayout
->queryLogicalAdvancements() );
312 const double* pOffsets( aOrigOffsets
.getConstArray() );
314 ENSURE_OR_THROW( aOrigOffsets
.getLength() >= rSubset
.mnSubsetEnd
,
315 "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );
317 // TODO(F3): It currently seems that for RTL text, the
318 // DX offsets are nevertheless increasing in logical
319 // text order (I'd expect they are decreasing,
320 // mimicking the fact that the text is output
321 // right-to-left). This breaks text effects for ALL
324 // determine leftmost position in given subset range -
325 // as the DX array contains the output positions
326 // starting with the second character (the first is
327 // assumed to have output position 0), correct begin
329 const double nMinPos( rSubset
.mnSubsetBegin
<= 0 ? 0 :
330 *(::std::min_element( pOffsets
+rSubset
.mnSubsetBegin
-1,
331 pOffsets
+rSubset
.mnSubsetEnd
)) );
333 // determine rightmost position in given subset range
334 // - as the DX array contains the output positions
335 // starting with the second character (the first is
336 // assumed to have output position 0), correct begin
338 const double nMaxPos(
339 *(::std::max_element( pOffsets
+ (rSubset
.mnSubsetBegin
<= 0 ?
340 0 : rSubset
.mnSubsetBegin
-1),
341 pOffsets
+ rSubset
.mnSubsetEnd
)) );
344 // adapt render state, to move text output to given offset
345 // -------------------------------------------------------
347 // TODO(F1): Strictly speaking, we also have to adapt
348 // the clip here, which normally should _not_ move
349 // with the output offset. Neglected for now, as it
350 // does not matter for drawing layer output
352 if( rSubset
.mnSubsetBegin
> 0 )
354 ::basegfx::B2DHomMatrix aTranslation
;
355 if( rOrigTextLayout
->getFont()->getFontRequest().FontDescription
.IsVertical
)
357 // vertical text -> offset in y direction
358 aTranslation
.translate( 0.0, nMinPos
);
362 // horizontal text -> offset in x direction
363 aTranslation
.translate( nMinPos
, 0.0 );
366 ::canvas::tools::appendToRenderState( io_rRenderState
,
371 // reduce DX array to given substring
372 // ----------------------------------
374 const sal_Int32
nNewElements( rSubset
.mnSubsetEnd
- rSubset
.mnSubsetBegin
);
375 uno::Sequence
< double > aAdaptedOffsets( nNewElements
);
376 double* pAdaptedOffsets( aAdaptedOffsets
.getArray() );
378 // move to new output position (subtract nMinPos,
379 // which is the new '0' position), copy only the range
380 // as given by rSubset.
381 ::std::transform( pOffsets
+ rSubset
.mnSubsetBegin
,
382 pOffsets
+ rSubset
.mnSubsetEnd
,
384 ::boost::bind( ::std::minus
<double>(),
391 return aAdaptedOffsets
;
394 uno::Reference
< rendering::XTextLayout
>
395 createSubsetLayout( const rendering::StringContext
& rOrigContext
,
396 const ::cppcanvas::internal::Action::Subset
& rSubset
,
397 const uno::Reference
< rendering::XTextLayout
>& rOrigTextLayout
)
399 // create temporary new text layout with subset string
400 // ---------------------------------------------------
402 const sal_Int32
nNewStartPos( rOrigContext
.StartPosition
+ ::std::min(
403 rSubset
.mnSubsetBegin
, rOrigContext
.Length
-1 ) );
404 const sal_Int32
nNewLength( ::std::max(
406 rSubset
.mnSubsetEnd
- rSubset
.mnSubsetBegin
,
407 rOrigContext
.Length
),
410 const rendering::StringContext
aContext( rOrigContext
.Text
,
414 uno::Reference
< rendering::XTextLayout
> xTextLayout(
415 rOrigTextLayout
->getFont()->createTextLayout( aContext
,
416 rOrigTextLayout
->getMainTextDirection(),
418 uno::UNO_QUERY_THROW
);
423 /** Setup subset text layout
425 @param io_rTextLayout
426 Must contain original (full set) text layout on input,
427 will contain subsetted text layout (or empty
428 reference, for empty subsets) on output.
430 @param io_rRenderState
431 Must contain original render state on input, will
432 contain shifted render state concatenated with
433 rTransformation on output.
435 @param rTransformation
436 Additional transformation, to be prepended to render
442 void createSubsetLayout( uno::Reference
< rendering::XTextLayout
>& io_rTextLayout
,
443 rendering::RenderState
& io_rRenderState
,
446 const ::basegfx::B2DHomMatrix
& rTransformation
,
447 const Action::Subset
& rSubset
)
449 ::canvas::tools::prependToRenderState(io_rRenderState
, rTransformation
);
451 if( rSubset
.mnSubsetBegin
== rSubset
.mnSubsetEnd
)
453 // empty range, empty layout
454 io_rTextLayout
.clear();
459 ENSURE_OR_THROW( io_rTextLayout
.is(),
460 "createSubsetLayout(): Invalid input layout" );
462 const rendering::StringContext
& rOrigContext( io_rTextLayout
->getText() );
464 if( rSubset
.mnSubsetBegin
== 0 &&
465 rSubset
.mnSubsetEnd
== rOrigContext
.Length
)
467 // full range, no need for subsetting
471 uno::Reference
< rendering::XTextLayout
> xTextLayout(
472 createSubsetLayout( rOrigContext
, rSubset
, io_rTextLayout
) );
474 if( xTextLayout
.is() )
476 xTextLayout
->applyLogicalAdvancements(
477 calcSubsetOffsets( io_rRenderState
,
484 io_rTextLayout
= xTextLayout
;
488 /** Interface for renderEffectText functor below.
490 This is interface is used from the renderEffectText()
491 method below, to call the client implementation.
496 virtual ~TextRenderer() {}
498 /// Render text with given RenderState
499 virtual bool operator()( const rendering::RenderState
& rRenderState
) const = 0;
502 /** Render effect text.
505 Functor object, will be called to render the actual
506 part of the text effect (the text itself and the means
507 to render it are unknown to this method)
509 bool renderEffectText( const TextRenderer
& rRenderer
,
510 const rendering::RenderState
& rRenderState
,
511 const rendering::ViewState
& /*rViewState*/,
512 const uno::Reference
< rendering::XCanvas
>& xCanvas
,
513 const ::Color
& rShadowColor
,
514 const ::basegfx::B2DSize
& rShadowOffset
,
515 const ::Color
& rReliefColor
,
516 const ::basegfx::B2DSize
& rReliefOffset
)
518 ::Color
aEmptyColor( COL_AUTO
);
519 uno::Reference
<rendering::XColorSpace
> xColorSpace(
520 xCanvas
->getDevice()->getDeviceColorSpace() );
522 // draw shadow text, if enabled
523 if( rShadowColor
!= aEmptyColor
)
525 rendering::RenderState
aShadowState( rRenderState
);
526 ::basegfx::B2DHomMatrix aTranslate
;
528 aTranslate
.translate( rShadowOffset
.getX(),
529 rShadowOffset
.getY() );
531 ::canvas::tools::appendToRenderState(aShadowState
, aTranslate
);
533 aShadowState
.DeviceColor
=
534 ::vcl::unotools::colorToDoubleSequence( rShadowColor
,
537 rRenderer( aShadowState
);
540 // draw relief text, if enabled
541 if( rReliefColor
!= aEmptyColor
)
543 rendering::RenderState
aReliefState( rRenderState
);
544 ::basegfx::B2DHomMatrix aTranslate
;
546 aTranslate
.translate( rReliefOffset
.getX(),
547 rReliefOffset
.getY() );
549 ::canvas::tools::appendToRenderState(aReliefState
, aTranslate
);
551 aReliefState
.DeviceColor
=
552 ::vcl::unotools::colorToDoubleSequence( rReliefColor
,
555 rRenderer( aReliefState
);
559 rRenderer( rRenderState
);
565 ::basegfx::B2DRange
calcEffectTextBounds( const ::basegfx::B2DRange
& rTextBounds
,
566 const ::basegfx::B2DRange
& rLineBounds
,
567 const ::basegfx::B2DSize
& rReliefOffset
,
568 const ::basegfx::B2DSize
& rShadowOffset
,
569 const rendering::RenderState
& rRenderState
,
570 const rendering::ViewState
& rViewState
)
572 ::basegfx::B2DRange
aBounds( rTextBounds
);
574 // add extends of text lines
575 aBounds
.expand( rLineBounds
);
577 // TODO(Q3): Provide this functionality at the B2DRange
578 ::basegfx::B2DRange
aTotalBounds( aBounds
);
580 ::basegfx::B2DRange( aBounds
.getMinX() + rReliefOffset
.getX(),
581 aBounds
.getMinY() + rReliefOffset
.getY(),
582 aBounds
.getMaxX() + rReliefOffset
.getX(),
583 aBounds
.getMaxY() + rReliefOffset
.getY() ) );
585 ::basegfx::B2DRange( aBounds
.getMinX() + rShadowOffset
.getX(),
586 aBounds
.getMinY() + rShadowOffset
.getY(),
587 aBounds
.getMaxX() + rShadowOffset
.getX(),
588 aBounds
.getMaxY() + rShadowOffset
.getY() ) );
590 return tools::calcDevicePixelBounds( aTotalBounds
,
595 void initEffectLinePolyPolygon( ::basegfx::B2DSize
& o_rOverallSize
,
596 uno::Reference
< rendering::XPolyPolygon2D
>& o_rTextLines
,
597 const CanvasSharedPtr
& rCanvas
,
598 const uno::Sequence
< double >& rOffsets
,
599 const tools::TextLineInfo rLineInfo
)
601 const ::basegfx::B2DPolyPolygon
aPoly(
602 textLinesFromLogicalOffsets(
606 o_rOverallSize
= ::basegfx::tools::getRange( aPoly
).getRange();
608 o_rTextLines
= ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
609 rCanvas
->getUNOCanvas()->getDevice(),
613 void initEffectLinePolyPolygon( ::basegfx::B2DSize
& o_rOverallSize
,
614 uno::Reference
< rendering::XPolyPolygon2D
>& o_rTextLines
,
615 const CanvasSharedPtr
& rCanvas
,
617 const tools::TextLineInfo rLineInfo
)
619 const ::basegfx::B2DPolyPolygon
aPoly(
620 tools::createTextLinesPolyPolygon( 0.0, nLineWidth
,
623 o_rOverallSize
= ::basegfx::tools::getRange( aPoly
).getRange();
625 o_rTextLines
= ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
626 rCanvas
->getUNOCanvas()->getDevice(),
631 // -------------------------------------------------------------------------
633 class TextAction
: public Action
, private ::boost::noncopyable
636 TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
637 const ::rtl::OUString
& rString
,
640 const CanvasSharedPtr
& rCanvas
,
641 const OutDevState
& rState
);
643 TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
644 const ::rtl::OUString
& rString
,
647 const CanvasSharedPtr
& rCanvas
,
648 const OutDevState
& rState
,
649 const ::basegfx::B2DHomMatrix
& rTextTransform
);
651 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
652 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
,
653 const Subset
& rSubset
) const;
655 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
656 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
657 const Subset
& rSubset
) const;
659 virtual sal_Int32
getActionCount() const;
662 // TODO(P2): This is potentially a real mass object
663 // (every character might be a separate TextAction),
664 // thus, make it as lightweight as possible. For
665 // example, share common RenderState among several
666 // TextActions, maybe using maOffsets for the
669 uno::Reference
< rendering::XCanvasFont
> mxFont
;
670 const rendering::StringContext maStringContext
;
671 const CanvasSharedPtr mpCanvas
;
672 rendering::RenderState maState
;
673 const sal_Int8 maTextDirection
;
676 TextAction::TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
677 const ::rtl::OUString
& rString
,
680 const CanvasSharedPtr
& rCanvas
,
681 const OutDevState
& rState
) :
682 mxFont( rState
.xFont
),
683 maStringContext( rString
, nStartPos
, nLen
),
686 maTextDirection( rState
.textDirection
)
688 init( maState
, mxFont
,
692 ENSURE_OR_THROW( mxFont
.is(),
693 "::cppcanvas::internal::TextAction(): Invalid font" );
696 TextAction::TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
697 const ::rtl::OUString
& rString
,
700 const CanvasSharedPtr
& rCanvas
,
701 const OutDevState
& rState
,
702 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
703 mxFont( rState
.xFont
),
704 maStringContext( rString
, nStartPos
, nLen
),
707 maTextDirection( rState
.textDirection
)
709 init( maState
, mxFont
,
711 rState
, rCanvas
, rTextTransform
);
713 ENSURE_OR_THROW( mxFont
.is(),
714 "::cppcanvas::internal::TextAction(): Invalid font" );
717 bool TextAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
719 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::TextAction::render()" );
720 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::TextAction: 0x%X", this );
722 rendering::RenderState
aLocalState( maState
);
723 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
725 mpCanvas
->getUNOCanvas()->drawText( maStringContext
, mxFont
,
726 mpCanvas
->getViewState(), aLocalState
, maTextDirection
);
731 bool TextAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
,
732 const Subset
& /*rSubset*/ ) const
735 "TextAction::render(): Subset not supported by this object" );
737 // TODO(P1): Retrieve necessary font metric info for
738 // TextAction from XCanvas. Currently, the
739 // TextActionFactory does not generate this object for
740 // _subsettable_ text
741 return render( rTransformation
);
744 ::basegfx::B2DRange
TextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
746 // create XTextLayout, to have the
747 // XTextLayout::queryTextBounds() method available
748 uno::Reference
< rendering::XTextLayout
> xTextLayout(
749 mxFont
->createTextLayout(
754 rendering::RenderState
aLocalState( maState
);
755 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
757 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
758 xTextLayout
->queryTextBounds() ),
759 mpCanvas
->getViewState(),
763 ::basegfx::B2DRange
TextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
764 const Subset
& /*rSubset*/ ) const
767 "TextAction::getBounds(): Subset not supported by this object" );
769 // TODO(P1): Retrieve necessary font metric info for
770 // TextAction from XCanvas. Currently, the
771 // TextActionFactory does not generate this object for
772 // _subsettable_ text
773 return getBounds( rTransformation
);
776 sal_Int32
TextAction::getActionCount() const
778 // TODO(P1): Retrieve necessary font metric info for
779 // TextAction from XCanvas. Currently, the
780 // TextActionFactory does not generate this object for
781 // _subsettable_ text
786 // -------------------------------------------------------------------------
788 class EffectTextAction
:
791 private ::boost::noncopyable
794 EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
795 const ::basegfx::B2DSize
& rReliefOffset
,
796 const ::Color
& rReliefColor
,
797 const ::basegfx::B2DSize
& rShadowOffset
,
798 const ::Color
& rShadowColor
,
799 const ::rtl::OUString
& rText
,
802 VirtualDevice
& rVDev
,
803 const CanvasSharedPtr
& rCanvas
,
804 const OutDevState
& rState
);
806 EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
807 const ::basegfx::B2DSize
& rReliefOffset
,
808 const ::Color
& rReliefColor
,
809 const ::basegfx::B2DSize
& rShadowOffset
,
810 const ::Color
& rShadowColor
,
811 const ::rtl::OUString
& rText
,
814 VirtualDevice
& rVDev
,
815 const CanvasSharedPtr
& rCanvas
,
816 const OutDevState
& rState
,
817 const ::basegfx::B2DHomMatrix
& rTextTransform
);
819 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
820 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
,
821 const Subset
& rSubset
) const;
823 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
824 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
825 const Subset
& rSubset
) const;
827 virtual sal_Int32
getActionCount() const;
830 /// Interface TextRenderer
831 virtual bool operator()( const rendering::RenderState
& rRenderState
) const;
833 // TODO(P2): This is potentially a real mass object
834 // (every character might be a separate TextAction),
835 // thus, make it as lightweight as possible. For
836 // example, share common RenderState among several
837 // TextActions, maybe using maOffsets for the
840 uno::Reference
< rendering::XCanvasFont
> mxFont
;
841 const rendering::StringContext maStringContext
;
842 const CanvasSharedPtr mpCanvas
;
843 rendering::RenderState maState
;
844 const tools::TextLineInfo maTextLineInfo
;
845 ::basegfx::B2DSize maLinesOverallSize
;
846 const double mnLineWidth
;
847 uno::Reference
< rendering::XPolyPolygon2D
> mxTextLines
;
848 const ::basegfx::B2DSize maReliefOffset
;
849 const ::Color maReliefColor
;
850 const ::basegfx::B2DSize maShadowOffset
;
851 const ::Color maShadowColor
;
852 const sal_Int8 maTextDirection
;
855 EffectTextAction::EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
856 const ::basegfx::B2DSize
& rReliefOffset
,
857 const ::Color
& rReliefColor
,
858 const ::basegfx::B2DSize
& rShadowOffset
,
859 const ::Color
& rShadowColor
,
860 const ::rtl::OUString
& rText
,
863 VirtualDevice
& rVDev
,
864 const CanvasSharedPtr
& rCanvas
,
865 const OutDevState
& rState
) :
866 mxFont( rState
.xFont
),
867 maStringContext( rText
, nStartPos
, nLen
),
870 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
871 maLinesOverallSize(),
872 mnLineWidth( getLineWidth( rVDev
, rState
, maStringContext
) ),
874 maReliefOffset( rReliefOffset
),
875 maReliefColor( rReliefColor
),
876 maShadowOffset( rShadowOffset
),
877 maShadowColor( rShadowColor
),
878 maTextDirection( rState
.textDirection
)
880 initEffectLinePolyPolygon( maLinesOverallSize
,
886 init( maState
, mxFont
,
890 ENSURE_OR_THROW( mxFont
.is() && mxTextLines
.is(),
891 "::cppcanvas::internal::EffectTextAction(): Invalid font or lines" );
894 EffectTextAction::EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
895 const ::basegfx::B2DSize
& rReliefOffset
,
896 const ::Color
& rReliefColor
,
897 const ::basegfx::B2DSize
& rShadowOffset
,
898 const ::Color
& rShadowColor
,
899 const ::rtl::OUString
& rText
,
902 VirtualDevice
& rVDev
,
903 const CanvasSharedPtr
& rCanvas
,
904 const OutDevState
& rState
,
905 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
906 mxFont( rState
.xFont
),
907 maStringContext( rText
, nStartPos
, nLen
),
910 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
911 maLinesOverallSize(),
912 mnLineWidth( getLineWidth( rVDev
, rState
, maStringContext
) ),
914 maReliefOffset( rReliefOffset
),
915 maReliefColor( rReliefColor
),
916 maShadowOffset( rShadowOffset
),
917 maShadowColor( rShadowColor
),
918 maTextDirection( rState
.textDirection
)
920 initEffectLinePolyPolygon( maLinesOverallSize
,
926 init( maState
, mxFont
,
928 rState
, rCanvas
, rTextTransform
);
930 ENSURE_OR_THROW( mxFont
.is() && mxTextLines
.is(),
931 "::cppcanvas::internal::EffectTextAction(): Invalid font or lines" );
934 bool EffectTextAction::operator()( const rendering::RenderState
& rRenderState
) const
936 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
937 const uno::Reference
< rendering::XCanvas
>& rCanvas( mpCanvas
->getUNOCanvas() );
939 rCanvas
->fillPolyPolygon( mxTextLines
,
943 rCanvas
->drawText( maStringContext
, mxFont
,
951 bool EffectTextAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
953 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::EffectTextAction::render()" );
954 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::EffectTextAction: 0x%X", this );
956 rendering::RenderState
aLocalState( maState
);
957 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
959 return renderEffectText( *this,
961 mpCanvas
->getViewState(),
962 mpCanvas
->getUNOCanvas(),
969 bool EffectTextAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
,
970 const Subset
& /*rSubset*/ ) const
973 "EffectTextAction::render(): Subset not supported by this object" );
975 // TODO(P1): Retrieve necessary font metric info for
976 // TextAction from XCanvas. Currently, the
977 // TextActionFactory does not generate this object for
979 return render( rTransformation
);
982 ::basegfx::B2DRange
EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
984 // create XTextLayout, to have the
985 // XTextLayout::queryTextBounds() method available
986 uno::Reference
< rendering::XTextLayout
> xTextLayout(
987 mxFont
->createTextLayout(
992 rendering::RenderState
aLocalState( maState
);
993 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
995 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
996 xTextLayout
->queryTextBounds() ),
997 ::basegfx::B2DRange( 0,0,
998 maLinesOverallSize
.getX(),
999 maLinesOverallSize
.getY() ),
1003 mpCanvas
->getViewState() );
1006 ::basegfx::B2DRange
EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1007 const Subset
& /*rSubset*/ ) const
1010 "EffectTextAction::getBounds(): Subset not supported by this object" );
1012 // TODO(P1): Retrieve necessary font metric info for
1013 // TextAction from XCanvas. Currently, the
1014 // TextActionFactory does not generate this object for
1015 // _subsettable_ text
1016 return getBounds( rTransformation
);
1019 sal_Int32
EffectTextAction::getActionCount() const
1021 // TODO(P1): Retrieve necessary font metric info for
1022 // TextAction from XCanvas. Currently, the
1023 // TextActionFactory does not generate this object for
1029 // -------------------------------------------------------------------------
1031 class TextArrayAction
: public Action
, private ::boost::noncopyable
1034 TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1035 const ::rtl::OUString
& rString
,
1036 sal_Int32 nStartPos
,
1038 const uno::Sequence
< double >& rOffsets
,
1039 const CanvasSharedPtr
& rCanvas
,
1040 const OutDevState
& rState
);
1042 TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1043 const ::rtl::OUString
& rString
,
1044 sal_Int32 nStartPos
,
1046 const uno::Sequence
< double >& rOffsets
,
1047 const CanvasSharedPtr
& rCanvas
,
1048 const OutDevState
& rState
,
1049 const ::basegfx::B2DHomMatrix
& rTextTransform
);
1051 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1052 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
,
1053 const Subset
& rSubset
) const;
1055 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1056 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1057 const Subset
& rSubset
) const;
1059 virtual sal_Int32
getActionCount() const;
1062 // TODO(P2): This is potentially a real mass object
1063 // (every character might be a separate TextAction),
1064 // thus, make it as lightweight as possible. For
1065 // example, share common RenderState among several
1066 // TextActions, maybe using maOffsets for the
1069 uno::Reference
< rendering::XTextLayout
> mxTextLayout
;
1070 const CanvasSharedPtr mpCanvas
;
1071 rendering::RenderState maState
;
1074 TextArrayAction::TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1075 const ::rtl::OUString
& rString
,
1076 sal_Int32 nStartPos
,
1078 const uno::Sequence
< double >& rOffsets
,
1079 const CanvasSharedPtr
& rCanvas
,
1080 const OutDevState
& rState
) :
1082 mpCanvas( rCanvas
),
1085 initArrayAction( maState
,
1096 TextArrayAction::TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1097 const ::rtl::OUString
& rString
,
1098 sal_Int32 nStartPos
,
1100 const uno::Sequence
< double >& rOffsets
,
1101 const CanvasSharedPtr
& rCanvas
,
1102 const OutDevState
& rState
,
1103 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
1105 mpCanvas( rCanvas
),
1108 initArrayAction( maState
,
1120 bool TextArrayAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1122 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::TextArrayAction::render()" );
1123 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::TextArrayAction: 0x%X", this );
1125 rendering::RenderState
aLocalState( maState
);
1126 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1128 #ifdef SPECIAL_DEBUG
1129 aLocalState
.Clip
.clear();
1130 aLocalState
.DeviceColor
=
1131 ::vcl::unotools::colorToDoubleSequence( mpCanvas
->getUNOCanvas()->getDevice(),
1132 ::Color( 0x80FF0000 ) );
1134 if( maState
.Clip
.is() )
1135 mpCanvas
->getUNOCanvas()->drawPolyPolygon( maState
.Clip
,
1136 mpCanvas
->getViewState(),
1139 aLocalState
.DeviceColor
= maState
.DeviceColor
;
1142 mpCanvas
->getUNOCanvas()->drawTextLayout( mxTextLayout
,
1143 mpCanvas
->getViewState(),
1149 bool TextArrayAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
,
1150 const Subset
& rSubset
) const
1152 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::TextArrayAction::render( subset )" );
1153 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::TextArrayAction: 0x%X", this );
1155 rendering::RenderState
aLocalState( maState
);
1156 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1158 double nDummy0
, nDummy1
;
1159 createSubsetLayout( xTextLayout
,
1166 if( !xTextLayout
.is() )
1167 return true; // empty layout, render nothing
1169 mpCanvas
->getUNOCanvas()->drawTextLayout( xTextLayout
,
1170 mpCanvas
->getViewState(),
1176 ::basegfx::B2DRange
TextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1178 rendering::RenderState
aLocalState( maState
);
1179 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1181 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1182 mxTextLayout
->queryTextBounds() ),
1183 mpCanvas
->getViewState(),
1187 ::basegfx::B2DRange
TextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1188 const Subset
& rSubset
) const
1190 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::TextArrayAction::getBounds( subset )" );
1191 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::TextArrayAction: 0x%X", this );
1193 rendering::RenderState
aLocalState( maState
);
1194 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1196 double nDummy0
, nDummy1
;
1197 createSubsetLayout( xTextLayout
,
1204 if( !xTextLayout
.is() )
1205 return ::basegfx::B2DRange(); // empty layout, empty bounds
1207 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1208 xTextLayout
->queryTextBounds() ),
1209 mpCanvas
->getViewState(),
1213 sal_Int32
TextArrayAction::getActionCount() const
1215 const rendering::StringContext
& rOrigContext( mxTextLayout
->getText() );
1217 return rOrigContext
.Length
;
1221 // -------------------------------------------------------------------------
1223 class EffectTextArrayAction
:
1225 public TextRenderer
,
1226 private ::boost::noncopyable
1229 EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1230 const ::basegfx::B2DSize
& rReliefOffset
,
1231 const ::Color
& rReliefColor
,
1232 const ::basegfx::B2DSize
& rShadowOffset
,
1233 const ::Color
& rShadowColor
,
1234 const ::rtl::OUString
& rText
,
1235 sal_Int32 nStartPos
,
1237 const uno::Sequence
< double >& rOffsets
,
1238 VirtualDevice
& rVDev
,
1239 const CanvasSharedPtr
& rCanvas
,
1240 const OutDevState
& rState
);
1241 EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1242 const ::basegfx::B2DSize
& rReliefOffset
,
1243 const ::Color
& rReliefColor
,
1244 const ::basegfx::B2DSize
& rShadowOffset
,
1245 const ::Color
& rShadowColor
,
1246 const ::rtl::OUString
& rText
,
1247 sal_Int32 nStartPos
,
1249 const uno::Sequence
< double >& rOffsets
,
1250 VirtualDevice
& rVDev
,
1251 const CanvasSharedPtr
& rCanvas
,
1252 const OutDevState
& rState
,
1253 const ::basegfx::B2DHomMatrix
& rTextTransform
);
1255 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1256 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
,
1257 const Subset
& rSubset
) const;
1259 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1260 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1261 const Subset
& rSubset
) const;
1263 virtual sal_Int32
getActionCount() const;
1266 // TextRenderer interface
1267 virtual bool operator()( const rendering::RenderState
& rRenderState
) const;
1269 // TODO(P2): This is potentially a real mass object
1270 // (every character might be a separate TextAction),
1271 // thus, make it as lightweight as possible. For
1272 // example, share common RenderState among several
1273 // TextActions, maybe using maOffsets for the
1276 uno::Reference
< rendering::XTextLayout
> mxTextLayout
;
1277 const CanvasSharedPtr mpCanvas
;
1278 rendering::RenderState maState
;
1279 const tools::TextLineInfo maTextLineInfo
;
1280 ::basegfx::B2DSize maLinesOverallSize
;
1281 uno::Reference
< rendering::XPolyPolygon2D
> mxTextLines
;
1282 const ::basegfx::B2DSize maReliefOffset
;
1283 const ::Color maReliefColor
;
1284 const ::basegfx::B2DSize maShadowOffset
;
1285 const ::Color maShadowColor
;
1288 EffectTextArrayAction::EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1289 const ::basegfx::B2DSize
& rReliefOffset
,
1290 const ::Color
& rReliefColor
,
1291 const ::basegfx::B2DSize
& rShadowOffset
,
1292 const ::Color
& rShadowColor
,
1293 const ::rtl::OUString
& rText
,
1294 sal_Int32 nStartPos
,
1296 const uno::Sequence
< double >& rOffsets
,
1297 VirtualDevice
& rVDev
,
1298 const CanvasSharedPtr
& rCanvas
,
1299 const OutDevState
& rState
) :
1301 mpCanvas( rCanvas
),
1303 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1304 maLinesOverallSize(),
1306 maReliefOffset( rReliefOffset
),
1307 maReliefColor( rReliefColor
),
1308 maShadowOffset( rShadowOffset
),
1309 maShadowColor( rShadowColor
)
1311 initEffectLinePolyPolygon( maLinesOverallSize
,
1317 initArrayAction( maState
,
1328 EffectTextArrayAction::EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1329 const ::basegfx::B2DSize
& rReliefOffset
,
1330 const ::Color
& rReliefColor
,
1331 const ::basegfx::B2DSize
& rShadowOffset
,
1332 const ::Color
& rShadowColor
,
1333 const ::rtl::OUString
& rText
,
1334 sal_Int32 nStartPos
,
1336 const uno::Sequence
< double >& rOffsets
,
1337 VirtualDevice
& rVDev
,
1338 const CanvasSharedPtr
& rCanvas
,
1339 const OutDevState
& rState
,
1340 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
1342 mpCanvas( rCanvas
),
1344 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1345 maLinesOverallSize(),
1347 maReliefOffset( rReliefOffset
),
1348 maReliefColor( rReliefColor
),
1349 maShadowOffset( rShadowOffset
),
1350 maShadowColor( rShadowColor
)
1352 initEffectLinePolyPolygon( maLinesOverallSize
,
1358 initArrayAction( maState
,
1370 bool EffectTextArrayAction::operator()( const rendering::RenderState
& rRenderState
) const
1372 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
1373 const uno::Reference
< rendering::XCanvas
>& rCanvas( mpCanvas
->getUNOCanvas() );
1375 rCanvas
->fillPolyPolygon( mxTextLines
,
1379 rCanvas
->drawTextLayout( mxTextLayout
,
1386 bool EffectTextArrayAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1388 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::EffectTextArrayAction::render()" );
1389 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
1391 rendering::RenderState
aLocalState( maState
);
1392 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1394 return renderEffectText( *this,
1396 mpCanvas
->getViewState(),
1397 mpCanvas
->getUNOCanvas(),
1404 class EffectTextArrayRenderHelper
: public TextRenderer
1407 EffectTextArrayRenderHelper( const uno::Reference
< rendering::XCanvas
>& rCanvas
,
1408 const uno::Reference
< rendering::XTextLayout
>& rTextLayout
,
1409 const uno::Reference
< rendering::XPolyPolygon2D
>& rLinePolygon
,
1410 const rendering::ViewState
& rViewState
) :
1411 mrCanvas( rCanvas
),
1412 mrTextLayout( rTextLayout
),
1413 mrLinePolygon( rLinePolygon
),
1414 mrViewState( rViewState
)
1418 // TextRenderer interface
1419 virtual bool operator()( const rendering::RenderState
& rRenderState
) const
1421 mrCanvas
->fillPolyPolygon( mrLinePolygon
,
1425 mrCanvas
->drawTextLayout( mrTextLayout
,
1433 const uno::Reference
< rendering::XCanvas
>& mrCanvas
;
1434 const uno::Reference
< rendering::XTextLayout
>& mrTextLayout
;
1435 const uno::Reference
< rendering::XPolyPolygon2D
>& mrLinePolygon
;
1436 const rendering::ViewState
& mrViewState
;
1439 bool EffectTextArrayAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
,
1440 const Subset
& rSubset
) const
1442 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::EffectTextArrayAction::render( subset )" );
1443 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
1445 rendering::RenderState
aLocalState( maState
);
1446 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1447 const geometry::RealRectangle2D
aTextBounds( mxTextLayout
->queryTextBounds() );
1449 double nMinPos(0.0);
1450 double nMaxPos(aTextBounds
.X2
- aTextBounds
.X1
);
1452 createSubsetLayout( xTextLayout
,
1459 if( !xTextLayout
.is() )
1460 return true; // empty layout, render nothing
1463 // create and setup local line polygon
1464 // ===================================
1466 uno::Reference
< rendering::XCanvas
> xCanvas( mpCanvas
->getUNOCanvas() );
1467 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
1469 uno::Reference
< rendering::XPolyPolygon2D
> xTextLines(
1470 ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
1471 xCanvas
->getDevice(),
1472 tools::createTextLinesPolyPolygon(
1473 0.0, nMaxPos
- nMinPos
,
1474 maTextLineInfo
) ) );
1477 // render everything
1478 // =================
1480 return renderEffectText(
1481 EffectTextArrayRenderHelper( xCanvas
,
1494 ::basegfx::B2DRange
EffectTextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1496 rendering::RenderState
aLocalState( maState
);
1497 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1499 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1500 mxTextLayout
->queryTextBounds() ),
1501 ::basegfx::B2DRange( 0,0,
1502 maLinesOverallSize
.getX(),
1503 maLinesOverallSize
.getY() ),
1507 mpCanvas
->getViewState() );
1510 ::basegfx::B2DRange
EffectTextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1511 const Subset
& rSubset
) const
1513 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::EffectTextArrayAction::getBounds( subset )" );
1514 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
1516 rendering::RenderState
aLocalState( maState
);
1517 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1518 const geometry::RealRectangle2D
aTextBounds( mxTextLayout
->queryTextBounds() );
1520 double nMinPos(0.0);
1521 double nMaxPos(aTextBounds
.X2
- aTextBounds
.X1
);
1523 createSubsetLayout( xTextLayout
,
1530 if( !xTextLayout
.is() )
1531 return ::basegfx::B2DRange(); // empty layout, empty bounds
1534 // create and setup local line polygon
1535 // ===================================
1537 const ::basegfx::B2DPolyPolygon
aPoly(
1538 tools::createTextLinesPolyPolygon(
1539 0.0, nMaxPos
- nMinPos
,
1542 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1543 xTextLayout
->queryTextBounds() ),
1544 ::basegfx::tools::getRange( aPoly
),
1548 mpCanvas
->getViewState() );
1551 sal_Int32
EffectTextArrayAction::getActionCount() const
1553 const rendering::StringContext
& rOrigContext( mxTextLayout
->getText() );
1555 return rOrigContext
.Length
;
1559 // -------------------------------------------------------------------------
1561 class OutlineAction
:
1563 public TextRenderer
,
1564 private ::boost::noncopyable
1567 OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1568 const ::basegfx::B2DSize
& rReliefOffset
,
1569 const ::Color
& rReliefColor
,
1570 const ::basegfx::B2DSize
& rShadowOffset
,
1571 const ::Color
& rShadowColor
,
1572 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1573 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1574 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1575 const uno::Sequence
< double >& rOffsets
,
1576 VirtualDevice
& rVDev
,
1577 const CanvasSharedPtr
& rCanvas
,
1578 const OutDevState
& rState
);
1579 OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1580 const ::basegfx::B2DSize
& rReliefOffset
,
1581 const ::Color
& rReliefColor
,
1582 const ::basegfx::B2DSize
& rShadowOffset
,
1583 const ::Color
& rShadowColor
,
1584 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1585 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1586 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1587 const uno::Sequence
< double >& rOffsets
,
1588 VirtualDevice
& rVDev
,
1589 const CanvasSharedPtr
& rCanvas
,
1590 const OutDevState
& rState
,
1591 const ::basegfx::B2DHomMatrix
& rTextTransform
);
1593 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1594 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
,
1595 const Subset
& rSubset
) const;
1597 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1598 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1599 const Subset
& rSubset
) const;
1601 virtual sal_Int32
getActionCount() const;
1604 // TextRenderer interface
1605 virtual bool operator()( const rendering::RenderState
& rRenderState
) const;
1607 // TODO(P2): This is potentially a real mass object
1608 // (every character might be a separate TextAction),
1609 // thus, make it as lightweight as possible. For
1610 // example, share common RenderState among several
1611 // TextActions, maybe using maOffsets for the
1614 uno::Reference
< rendering::XPolyPolygon2D
> mxTextPoly
;
1616 /** This vector denotes the index of the start polygon
1617 for the respective glyph sequence.
1619 To get a polygon index range for a given character
1620 index i, take [ maPolygonGlyphMap[i],
1621 maPolygonGlyphMap[i+1] ). Note that this is wrong
1624 const ::std::vector
< sal_Int32
> maPolygonGlyphMap
;
1625 const uno::Sequence
< double > maOffsets
;
1626 const CanvasSharedPtr mpCanvas
;
1627 rendering::RenderState maState
;
1628 double mnOutlineWidth
;
1629 const uno::Sequence
< double > maFillColor
;
1630 const tools::TextLineInfo maTextLineInfo
;
1631 ::basegfx::B2DSize maLinesOverallSize
;
1632 const ::basegfx::B2DRectangle maOutlineBounds
;
1633 uno::Reference
< rendering::XPolyPolygon2D
> mxTextLines
;
1634 const ::basegfx::B2DSize maReliefOffset
;
1635 const ::Color maReliefColor
;
1636 const ::basegfx::B2DSize maShadowOffset
;
1637 const ::Color maShadowColor
;
1640 double calcOutlineWidth( const OutDevState
& rState
,
1641 VirtualDevice
& rVDev
)
1643 const ::basegfx::B2DSize
aFontSize( 0,
1644 rVDev
.GetFont().GetHeight() / 64.0 );
1646 const double nOutlineWidth(
1647 (rState
.mapModeTransform
* aFontSize
).getY() );
1649 return nOutlineWidth
< 1.0 ? 1.0 : nOutlineWidth
;
1652 OutlineAction::OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1653 const ::basegfx::B2DSize
& rReliefOffset
,
1654 const ::Color
& rReliefColor
,
1655 const ::basegfx::B2DSize
& rShadowOffset
,
1656 const ::Color
& rShadowColor
,
1657 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1658 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1659 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1660 const uno::Sequence
< double >& rOffsets
,
1661 VirtualDevice
& rVDev
,
1662 const CanvasSharedPtr
& rCanvas
,
1663 const OutDevState
& rState
) :
1664 mxTextPoly( rTextPoly
),
1665 maPolygonGlyphMap( rPolygonGlyphMap
),
1666 maOffsets( rOffsets
),
1667 mpCanvas( rCanvas
),
1669 mnOutlineWidth( calcOutlineWidth(rState
,rVDev
) ),
1671 ::vcl::unotools::colorToDoubleSequence(
1672 ::Color( COL_WHITE
),
1673 rCanvas
->getUNOCanvas()->getDevice()->getDeviceColorSpace() )),
1674 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1675 maLinesOverallSize(),
1676 maOutlineBounds( rOutlineBounds
),
1678 maReliefOffset( rReliefOffset
),
1679 maReliefColor( rReliefColor
),
1680 maShadowOffset( rShadowOffset
),
1681 maShadowColor( rShadowColor
)
1683 initEffectLinePolyPolygon( maLinesOverallSize
,
1695 OutlineAction::OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1696 const ::basegfx::B2DSize
& rReliefOffset
,
1697 const ::Color
& rReliefColor
,
1698 const ::basegfx::B2DSize
& rShadowOffset
,
1699 const ::Color
& rShadowColor
,
1700 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1701 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1702 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1703 const uno::Sequence
< double >& rOffsets
,
1704 VirtualDevice
& rVDev
,
1705 const CanvasSharedPtr
& rCanvas
,
1706 const OutDevState
& rState
,
1707 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
1708 mxTextPoly( rTextPoly
),
1709 maPolygonGlyphMap( rPolygonGlyphMap
),
1710 maOffsets( rOffsets
),
1711 mpCanvas( rCanvas
),
1713 mnOutlineWidth( calcOutlineWidth(rState
,rVDev
) ),
1715 ::vcl::unotools::colorToDoubleSequence(
1716 ::Color( COL_WHITE
),
1717 rCanvas
->getUNOCanvas()->getDevice()->getDeviceColorSpace() )),
1718 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1719 maLinesOverallSize(),
1720 maOutlineBounds( rOutlineBounds
),
1722 maReliefOffset( rReliefOffset
),
1723 maReliefColor( rReliefColor
),
1724 maShadowOffset( rShadowOffset
),
1725 maShadowColor( rShadowColor
)
1727 initEffectLinePolyPolygon( maLinesOverallSize
,
1740 bool OutlineAction::operator()( const rendering::RenderState
& rRenderState
) const
1742 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
1743 const uno::Reference
< rendering::XCanvas
>& rCanvas( mpCanvas
->getUNOCanvas() );
1745 rendering::StrokeAttributes aStrokeAttributes
;
1747 aStrokeAttributes
.StrokeWidth
= mnOutlineWidth
;
1748 aStrokeAttributes
.MiterLimit
= 1.0;
1749 aStrokeAttributes
.StartCapType
= rendering::PathCapType::BUTT
;
1750 aStrokeAttributes
.EndCapType
= rendering::PathCapType::BUTT
;
1751 aStrokeAttributes
.JoinType
= rendering::PathJoinType::MITER
;
1753 rendering::RenderState
aLocalState( rRenderState
);
1754 aLocalState
.DeviceColor
= maFillColor
;
1756 // TODO(P1): implement caching
1758 // background of text
1759 rCanvas
->fillPolyPolygon( mxTextPoly
,
1763 // border line of text
1764 rCanvas
->strokePolyPolygon( mxTextPoly
,
1767 aStrokeAttributes
);
1769 // underlines/strikethrough - background
1770 rCanvas
->fillPolyPolygon( mxTextLines
,
1773 // underlines/strikethrough - border
1774 rCanvas
->strokePolyPolygon( mxTextLines
,
1777 aStrokeAttributes
);
1782 bool OutlineAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1784 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::EffectTextArrayAction::render()" );
1785 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
1787 rendering::RenderState
aLocalState( maState
);
1788 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1790 return renderEffectText( *this,
1792 mpCanvas
->getViewState(),
1793 mpCanvas
->getUNOCanvas(),
1800 class OutlineTextArrayRenderHelper
: public TextRenderer
1803 OutlineTextArrayRenderHelper( const uno::Reference
< rendering::XCanvas
>& rCanvas
,
1804 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPolygon
,
1805 const uno::Reference
< rendering::XPolyPolygon2D
>& rLinePolygon
,
1806 const rendering::ViewState
& rViewState
,
1807 double nOutlineWidth
) :
1809 ::vcl::unotools::colorToDoubleSequence(
1810 ::Color( COL_WHITE
),
1811 rCanvas
->getDevice()->getDeviceColorSpace() )),
1812 mnOutlineWidth( nOutlineWidth
),
1813 mrCanvas( rCanvas
),
1814 mrTextPolygon( rTextPolygon
),
1815 mrLinePolygon( rLinePolygon
),
1816 mrViewState( rViewState
)
1820 // TextRenderer interface
1821 virtual bool operator()( const rendering::RenderState
& rRenderState
) const
1823 rendering::StrokeAttributes aStrokeAttributes
;
1825 aStrokeAttributes
.StrokeWidth
= mnOutlineWidth
;
1826 aStrokeAttributes
.MiterLimit
= 1.0;
1827 aStrokeAttributes
.StartCapType
= rendering::PathCapType::BUTT
;
1828 aStrokeAttributes
.EndCapType
= rendering::PathCapType::BUTT
;
1829 aStrokeAttributes
.JoinType
= rendering::PathJoinType::MITER
;
1831 rendering::RenderState
aLocalState( rRenderState
);
1832 aLocalState
.DeviceColor
= maFillColor
;
1834 // TODO(P1): implement caching
1836 // background of text
1837 mrCanvas
->fillPolyPolygon( mrTextPolygon
,
1841 // border line of text
1842 mrCanvas
->strokePolyPolygon( mrTextPolygon
,
1845 aStrokeAttributes
);
1847 // underlines/strikethrough - background
1848 mrCanvas
->fillPolyPolygon( mrLinePolygon
,
1851 // underlines/strikethrough - border
1852 mrCanvas
->strokePolyPolygon( mrLinePolygon
,
1855 aStrokeAttributes
);
1861 const uno::Sequence
< double > maFillColor
;
1862 double mnOutlineWidth
;
1863 const uno::Reference
< rendering::XCanvas
>& mrCanvas
;
1864 const uno::Reference
< rendering::XPolyPolygon2D
>& mrTextPolygon
;
1865 const uno::Reference
< rendering::XPolyPolygon2D
>& mrLinePolygon
;
1866 const rendering::ViewState
& mrViewState
;
1869 bool OutlineAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
,
1870 const Subset
& rSubset
) const
1872 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::OutlineAction::render( subset )" );
1873 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::OutlineAction: 0x%X", this );
1875 if( rSubset
.mnSubsetBegin
== rSubset
.mnSubsetEnd
)
1876 return true; // empty range, render nothing
1879 // TODO(F3): Subsetting NYI for outline text!
1880 return render( rTransformation
);
1882 const rendering::StringContext
rOrigContext( mxTextLayout
->getText() );
1884 if( rSubset
.mnSubsetBegin
== 0 &&
1885 rSubset
.mnSubsetEnd
== rOrigContext
.Length
)
1887 // full range, no need for subsetting
1888 return render( rTransformation
);
1891 rendering::RenderState
aLocalState( maState
);
1892 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1895 // create and setup local Text polygon
1896 // ===================================
1898 uno::Reference
< rendering::XPolyPolygon2D
> xTextPolygon();
1900 // TODO(P3): Provide an API method for that!
1902 if( !xTextLayout
.is() )
1905 // render everything
1906 // =================
1908 return renderEffectText(
1909 OutlineTextArrayRenderHelper(
1925 ::basegfx::B2DRange
OutlineAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1927 rendering::RenderState
aLocalState( maState
);
1928 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1930 return calcEffectTextBounds( maOutlineBounds
,
1931 ::basegfx::B2DRange( 0,0,
1932 maLinesOverallSize
.getX(),
1933 maLinesOverallSize
.getY() ),
1937 mpCanvas
->getViewState() );
1940 ::basegfx::B2DRange
OutlineAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1941 const Subset
& /*rSubset*/ ) const
1944 "OutlineAction::getBounds(): Subset not yet supported by this object" );
1946 return getBounds( rTransformation
);
1949 sal_Int32
OutlineAction::getActionCount() const
1951 // TODO(F3): Subsetting NYI for outline text!
1952 return maOffsets
.getLength();
1956 // ======================================================================
1958 // Action factory methods
1960 // ======================================================================
1962 /** Create an outline action
1964 This method extracts the polygonal outline from the
1965 text, and creates a properly setup OutlineAction from
1968 ActionSharedPtr
createOutline( const ::basegfx::B2DPoint
& rStartPoint
,
1969 const ::basegfx::B2DSize
& rReliefOffset
,
1970 const ::Color
& rReliefColor
,
1971 const ::basegfx::B2DSize
& rShadowOffset
,
1972 const ::Color
& rShadowColor
,
1973 const String
& rText
,
1974 sal_Int32 nStartPos
,
1976 const sal_Int32
* pDXArray
,
1977 VirtualDevice
& rVDev
,
1978 const CanvasSharedPtr
& rCanvas
,
1979 const OutDevState
& rState
,
1980 const Renderer::Parameters
& rParms
)
1982 // operate on raw DX array here (in logical coordinate
1983 // system), to have a higher resolution
1984 // PolyPolygon. That polygon is then converted to
1985 // device coordinate system.
1987 // #i68512# Temporarily switch off font rotation
1988 // (which is already contained in the render state
1989 // transformation matrix - otherwise, glyph polygons
1990 // will be rotated twice)
1991 const ::Font
aOrigFont( rVDev
.GetFont() );
1992 ::Font
aUnrotatedFont( aOrigFont
);
1993 aUnrotatedFont
.SetOrientation(0);
1994 rVDev
.SetFont( aUnrotatedFont
);
1996 // TODO(F3): Don't understand parameter semantics of
1997 // GetTextOutlines()
1998 ::basegfx::B2DPolyPolygon aResultingPolyPolygon
;
1999 PolyPolyVector aVCLPolyPolyVector
;
2000 const bool bHaveOutlines( rVDev
.GetTextOutlines( aVCLPolyPolyVector
, rText
,
2001 static_cast<USHORT
>(nStartPos
),
2002 static_cast<USHORT
>(nStartPos
),
2003 static_cast<USHORT
>(nLen
),
2004 TRUE
, 0, pDXArray
) );
2005 rVDev
.SetFont(aOrigFont
);
2007 if( !bHaveOutlines
)
2008 return ActionSharedPtr();
2010 ::std::vector
< sal_Int32
> aPolygonGlyphMap
;
2012 // first glyph starts at polygon index 0
2013 aPolygonGlyphMap
.push_back( 0 );
2015 // remove offsetting from mapmode transformation
2016 // (outline polygons must stay at origin, only need to
2018 ::basegfx::B2DHomMatrix
aMapModeTransform(
2019 rState
.mapModeTransform
);
2020 aMapModeTransform
.set(0,2, 0.0);
2021 aMapModeTransform
.set(1,2, 0.0);
2023 PolyPolyVector::const_iterator
aIter( aVCLPolyPolyVector
.begin() );
2024 const PolyPolyVector::const_iterator
aEnd( aVCLPolyPolyVector
.end() );
2025 for( ; aIter
!= aEnd
; ++aIter
)
2027 ::basegfx::B2DPolyPolygon aPolyPolygon
;
2029 aPolyPolygon
= aIter
->getB2DPolyPolygon();
2030 aPolyPolygon
.transform( aMapModeTransform
);
2032 // append result to collecting polypoly
2033 for( sal_uInt32 i
=0; i
<aPolyPolygon
.count(); ++i
)
2035 // #i47795# Ensure closed polygons (since
2036 // FreeType returns the glyph outlines
2038 const ::basegfx::B2DPolygon
& rPoly( aPolyPolygon
.getB2DPolygon( i
) );
2039 const sal_uInt32
nCount( rPoly
.count() );
2043 // polygon either degenerate, or
2045 aResultingPolyPolygon
.append( rPoly
);
2049 ::basegfx::B2DPolygon
aPoly(rPoly
);
2050 aPoly
.setClosed(true);
2052 aResultingPolyPolygon
.append( aPoly
);
2056 // TODO(F3): Depending on the semantics of
2057 // GetTextOutlines(), this here is wrong!
2059 // calc next glyph index
2060 aPolygonGlyphMap
.push_back( aResultingPolyPolygon
.count() );
2063 const uno::Sequence
< double > aCharWidthSeq(
2065 setupDXArray( pDXArray
, nLen
, rState
) :
2066 setupDXArray( rText
,
2071 const uno::Reference
< rendering::XPolyPolygon2D
> xTextPoly(
2072 ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
2073 rCanvas
->getUNOCanvas()->getDevice(),
2074 aResultingPolyPolygon
) );
2076 if( rParms
.maTextTransformation
.isValid() )
2078 return ActionSharedPtr(
2085 ::basegfx::tools::getRange(aResultingPolyPolygon
),
2092 rParms
.maTextTransformation
.getValue() ) );
2096 return ActionSharedPtr(
2103 ::basegfx::tools::getRange(aResultingPolyPolygon
),
2116 // ---------------------------------------------------------------------------------
2118 ActionSharedPtr
TextActionFactory::createTextAction( const ::Point
& rStartPoint
,
2119 const ::Size
& rReliefOffset
,
2120 const ::Color
& rReliefColor
,
2121 const ::Size
& rShadowOffset
,
2122 const ::Color
& rShadowColor
,
2123 const String
& rText
,
2124 sal_Int32 nStartPos
,
2126 const sal_Int32
* pDXArray
,
2127 VirtualDevice
& rVDev
,
2128 const CanvasSharedPtr
& rCanvas
,
2129 const OutDevState
& rState
,
2130 const Renderer::Parameters
& rParms
,
2133 const ::Size
aBaselineOffset( tools::getBaselineOffset( rState
,
2135 // #143885# maintain (nearly) full precision positioning,
2136 // by circumventing integer-based OutDev-mapping
2137 const ::basegfx::B2DPoint
aStartPoint(
2138 rState
.mapModeTransform
*
2139 ::basegfx::B2DPoint(rStartPoint
.X() + aBaselineOffset
.Width(),
2140 rStartPoint
.Y() + aBaselineOffset
.Height()) );
2142 const ::basegfx::B2DSize
aReliefOffset(
2143 rState
.mapModeTransform
* ::vcl::unotools::b2DSizeFromSize( rReliefOffset
) );
2144 const ::basegfx::B2DSize
aShadowOffset(
2145 rState
.mapModeTransform
* ::vcl::unotools::b2DSizeFromSize( rShadowOffset
) );
2147 if( rState
.isTextOutlineModeSet
)
2149 return createOutline(
2165 // convert DX array to device coordinate system (and
2166 // create it in the first place, if pDXArray is NULL)
2167 const uno::Sequence
< double > aCharWidths(
2169 setupDXArray( pDXArray
, nLen
, rState
) :
2170 setupDXArray( rText
,
2176 // determine type of text action to create
2177 // =======================================
2179 const ::Color
aEmptyColor( COL_AUTO
);
2181 // no DX array, and no need to subset - no need to store
2183 if( !pDXArray
&& !bSubsettable
)
2186 if( !rState
.textOverlineStyle
&&
2187 !rState
.textUnderlineStyle
&&
2188 !rState
.textStrikeoutStyle
&&
2189 rReliefColor
== aEmptyColor
&&
2190 rShadowColor
== aEmptyColor
)
2193 if( rParms
.maTextTransformation
.isValid() )
2195 return ActionSharedPtr( new TextAction(
2202 rParms
.maTextTransformation
.getValue() ) );
2206 return ActionSharedPtr( new TextAction(
2217 // at least one of the effects requested
2218 if( rParms
.maTextTransformation
.isValid() )
2219 return ActionSharedPtr( new EffectTextAction(
2231 rParms
.maTextTransformation
.getValue() ) );
2233 return ActionSharedPtr( new EffectTextAction(
2249 // DX array necessary - any effects?
2250 if( !rState
.textOverlineStyle
&&
2251 !rState
.textUnderlineStyle
&&
2252 !rState
.textStrikeoutStyle
&&
2253 rReliefColor
== aEmptyColor
&&
2254 rShadowColor
== aEmptyColor
)
2257 if( rParms
.maTextTransformation
.isValid() )
2258 return ActionSharedPtr( new TextArrayAction(
2266 rParms
.maTextTransformation
.getValue() ) );
2268 return ActionSharedPtr( new TextArrayAction(
2279 // at least one of the effects requested
2280 if( rParms
.maTextTransformation
.isValid() )
2281 return ActionSharedPtr( new EffectTextArrayAction(
2294 rParms
.maTextTransformation
.getValue() ) );
2296 return ActionSharedPtr( new EffectTextArrayAction(
2311 #if defined __GNUC__
2312 #if __GNUC__ == 4 && __GNUC_MINOR__ >= 1
2313 // Unreachable; to avoid bogus warning:
2314 return ActionSharedPtr();