1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <canvas/debug.hxx>
31 #include <tools/diagnose_ex.h>
32 #include <canvas/verbosetrace.hxx>
34 #include <rtl/logfile.hxx>
36 #include <com/sun/star/rendering/PathCapType.hpp>
37 #include <com/sun/star/rendering/PathJoinType.hpp>
38 #include <com/sun/star/rendering/XCanvas.hpp>
39 #include <com/sun/star/rendering/XCanvasFont.hpp>
41 #include <basegfx/numeric/ftools.hxx>
42 #include <basegfx/matrix/b2dhommatrix.hxx>
43 #include <basegfx/range/b2drectangle.hxx>
44 #include <basegfx/vector/b2dsize.hxx>
45 #include <basegfx/polygon/b2dpolypolygontools.hxx>
46 #include <basegfx/polygon/b2dpolygontools.hxx>
47 #include <basegfx/matrix/b2dhommatrixtools.hxx>
49 #include <tools/gen.hxx>
50 #include <vcl/canvastools.hxx>
51 #include <vcl/virdev.hxx>
53 #include <basegfx/tools/canvastools.hxx>
54 #include <canvas/canvastools.hxx>
56 #include <boost/scoped_array.hpp>
57 #include <boost/bind.hpp>
58 #include <boost/utility.hpp>
60 #include "textaction.hxx"
61 #include "outdevstate.hxx"
62 #include "mtftools.hxx"
65 using namespace ::com::sun::star
;
73 void init( rendering::RenderState
& o_rRenderState
,
74 const ::basegfx::B2DPoint
& rStartPoint
,
75 const OutDevState
& rState
,
76 const CanvasSharedPtr
& rCanvas
)
78 tools::initRenderState(o_rRenderState
,rState
);
80 // #i36950# Offset clip back to origin (as it's also moved
82 // #i53964# Also take VCL font rotation into account,
83 // since this, opposed to the FontMatrix rotation
84 // elsewhere, _does_ get incorporated into the render
86 tools::modifyClip( o_rRenderState
,
91 &rState
.fontRotation
);
93 basegfx::B2DHomMatrix
aLocalTransformation(basegfx::tools::createRotateB2DHomMatrix(rState
.fontRotation
));
94 aLocalTransformation
.translate( rStartPoint
.getX(),
96 ::canvas::tools::appendToRenderState( o_rRenderState
,
97 aLocalTransformation
);
99 o_rRenderState
.DeviceColor
= rState
.textColor
;
102 void init( rendering::RenderState
& o_rRenderState
,
103 const ::basegfx::B2DPoint
& rStartPoint
,
104 const OutDevState
& rState
,
105 const CanvasSharedPtr
& rCanvas
,
106 const ::basegfx::B2DHomMatrix
& rTextTransform
)
108 init( o_rRenderState
, rStartPoint
, rState
, rCanvas
);
110 // TODO(F2): Also inversely-transform clip with
111 // rTextTransform (which is actually rather hard, as the
112 // text transform is _prepended_ to the render state)!
114 // prepend extra font transform to render state
115 // (prepend it, because it's interpreted in the unit
116 // rect coordinate space)
117 ::canvas::tools::prependToRenderState( o_rRenderState
,
121 void init( rendering::RenderState
& o_rRenderState
,
122 uno::Reference
< rendering::XCanvasFont
>& o_rFont
,
123 const ::basegfx::B2DPoint
& rStartPoint
,
124 const OutDevState
& rState
,
125 const CanvasSharedPtr
& rCanvas
)
127 // ensure that o_rFont is valid. It is possible that
128 // text actions are generated without previously
129 // setting a font. Then, just take a default font
132 // Use completely default FontRequest
133 const rendering::FontRequest aFontRequest
;
135 geometry::Matrix2D aFontMatrix
;
136 ::canvas::tools::setIdentityMatrix2D( aFontMatrix
);
138 o_rFont
= rCanvas
->getUNOCanvas()->createFont(
140 uno::Sequence
< beans::PropertyValue
>(),
144 init( o_rRenderState
,
150 void init( rendering::RenderState
& o_rRenderState
,
151 uno::Reference
< rendering::XCanvasFont
>& o_rFont
,
152 const ::basegfx::B2DPoint
& rStartPoint
,
153 const OutDevState
& rState
,
154 const CanvasSharedPtr
& rCanvas
,
155 const ::basegfx::B2DHomMatrix
& rTextTransform
)
157 init( o_rRenderState
, o_rFont
, rStartPoint
, rState
, rCanvas
);
159 // TODO(F2): Also inversely-transform clip with
160 // rTextTransform (which is actually rather hard, as the
161 // text transform is _prepended_ to the render state)!
163 // prepend extra font transform to render state
164 // (prepend it, because it's interpreted in the unit
165 // rect coordinate space)
166 ::canvas::tools::prependToRenderState( o_rRenderState
,
170 ::basegfx::B2DPolyPolygon
textLinesFromLogicalOffsets( const uno::Sequence
< double >& rOffsets
,
171 const tools::TextLineInfo
& rTextLineInfo
)
173 return tools::createTextLinesPolyPolygon(
175 // extract character cell furthest to the right
176 *(::std::max_element(
177 rOffsets
.getConstArray(),
178 rOffsets
.getConstArray() + rOffsets
.getLength() )),
182 uno::Sequence
< double > setupDXArray( const sal_Int32
* pCharWidths
,
184 const OutDevState
& rState
)
186 // convert character widths from logical units
187 uno::Sequence
< double > aCharWidthSeq( nLen
);
188 double* pOutputWidths( aCharWidthSeq
.getArray() );
190 // #143885# maintain (nearly) full precision of DX
191 // array, by circumventing integer-based
193 const double nScale( rState
.mapModeTransform
.get(0,0) );
194 for( int i
= 0; i
< nLen
; ++i
)
196 // TODO(F2): use correct scale direction
197 *pOutputWidths
++ = *pCharWidths
++ * nScale
;
200 return aCharWidthSeq
;
203 uno::Sequence
< double > setupDXArray( const ::String
& rText
,
206 VirtualDevice
& rVDev
,
207 const OutDevState
& rState
)
209 // no external DX array given, create one from given
211 ::boost::scoped_array
< sal_Int32
> pCharWidths( new sal_Int32
[nLen
] );
213 rVDev
.GetTextArray( rText
, pCharWidths
.get(),
214 static_cast<sal_uInt16
>(nStartPos
),
215 static_cast<sal_uInt16
>(nLen
) );
217 return setupDXArray( pCharWidths
.get(), nLen
, rState
);
220 ::basegfx::B2DPoint
adaptStartPoint( const ::basegfx::B2DPoint
& rStartPoint
,
221 const OutDevState
& rState
,
222 const uno::Sequence
< double >& rOffsets
)
224 ::basegfx::B2DPoint
aLocalPoint( rStartPoint
);
226 if( rState
.textAlignment
)
228 // text origin is right, not left. Modify start point
229 // accordingly, because XCanvas::drawTextLayout()
230 // always aligns left!
232 const double nOffset( rOffsets
[ rOffsets
.getLength()-1 ] );
234 // correct start point for rotated text: rotate around
235 // former start point
236 aLocalPoint
.setX( aLocalPoint
.getX() + cos( rState
.fontRotation
)*nOffset
);
237 aLocalPoint
.setY( aLocalPoint
.getY() + sin( rState
.fontRotation
)*nOffset
);
243 /** Perform common setup for array text actions
245 This method creates the XTextLayout object and
246 initializes it, e.g. with the logical advancements.
248 void initArrayAction( rendering::RenderState
& o_rRenderState
,
249 uno::Reference
< rendering::XTextLayout
>& o_rTextLayout
,
250 const ::basegfx::B2DPoint
& rStartPoint
,
251 const ::rtl::OUString
& rText
,
254 const uno::Sequence
< double >& rOffsets
,
255 const CanvasSharedPtr
& rCanvas
,
256 const OutDevState
& rState
,
257 const ::basegfx::B2DHomMatrix
* pTextTransform
)
259 ENSURE_OR_THROW( rOffsets
.getLength(),
260 "::cppcanvas::internal::initArrayAction(): zero-length DX array" );
262 const ::basegfx::B2DPoint
aLocalStartPoint(
263 adaptStartPoint( rStartPoint
, rState
, rOffsets
) );
265 uno::Reference
< rendering::XCanvasFont
> xFont( rState
.xFont
);
268 init( o_rRenderState
, xFont
, aLocalStartPoint
, rState
, rCanvas
, *pTextTransform
);
270 init( o_rRenderState
, xFont
, aLocalStartPoint
, rState
, rCanvas
);
272 o_rTextLayout
= xFont
->createTextLayout(
273 rendering::StringContext( rText
, nStartPos
, nLen
),
274 rState
.textDirection
,
277 ENSURE_OR_THROW( o_rTextLayout
.is(),
278 "::cppcanvas::internal::initArrayAction(): Invalid font" );
280 o_rTextLayout
->applyLogicalAdvancements( rOffsets
);
283 double getLineWidth( ::VirtualDevice
& rVDev
,
284 const OutDevState
& rState
,
285 const rendering::StringContext
& rStringContext
)
287 // TODO(F2): use correct scale direction
288 const ::basegfx::B2DSize
aSize( rVDev
.GetTextWidth( rStringContext
.Text
,
289 static_cast<sal_uInt16
>(rStringContext
.StartPosition
),
290 static_cast<sal_uInt16
>(rStringContext
.Length
) ),
293 return (rState
.mapModeTransform
* aSize
).getX();
296 uno::Sequence
< double >
297 calcSubsetOffsets( rendering::RenderState
& io_rRenderState
,
300 const uno::Reference
< rendering::XTextLayout
>& rOrigTextLayout
,
301 const ::cppcanvas::internal::Action::Subset
& rSubset
)
303 ENSURE_OR_THROW( rSubset
.mnSubsetEnd
> rSubset
.mnSubsetBegin
,
304 "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );
306 uno::Sequence
< double > aOrigOffsets( rOrigTextLayout
->queryLogicalAdvancements() );
307 const double* pOffsets( aOrigOffsets
.getConstArray() );
309 ENSURE_OR_THROW( aOrigOffsets
.getLength() >= rSubset
.mnSubsetEnd
,
310 "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );
312 // TODO(F3): It currently seems that for RTL text, the
313 // DX offsets are nevertheless increasing in logical
314 // text order (I'd expect they are decreasing,
315 // mimicking the fact that the text is output
316 // right-to-left). This breaks text effects for ALL
319 // determine leftmost position in given subset range -
320 // as the DX array contains the output positions
321 // starting with the second character (the first is
322 // assumed to have output position 0), correct begin
324 const double nMinPos( rSubset
.mnSubsetBegin
<= 0 ? 0 :
325 *(::std::min_element( pOffsets
+rSubset
.mnSubsetBegin
-1,
326 pOffsets
+rSubset
.mnSubsetEnd
)) );
328 // determine rightmost position in given subset range
329 // - as the DX array contains the output positions
330 // starting with the second character (the first is
331 // assumed to have output position 0), correct begin
333 const double nMaxPos(
334 *(::std::max_element( pOffsets
+ (rSubset
.mnSubsetBegin
<= 0 ?
335 0 : rSubset
.mnSubsetBegin
-1),
336 pOffsets
+ rSubset
.mnSubsetEnd
)) );
339 // adapt render state, to move text output to given offset
340 // -------------------------------------------------------
342 // TODO(F1): Strictly speaking, we also have to adapt
343 // the clip here, which normally should _not_ move
344 // with the output offset. Neglected for now, as it
345 // does not matter for drawing layer output
347 if( rSubset
.mnSubsetBegin
> 0 )
349 ::basegfx::B2DHomMatrix aTranslation
;
350 if( rOrigTextLayout
->getFont()->getFontRequest().FontDescription
.IsVertical
)
352 // vertical text -> offset in y direction
353 aTranslation
.translate( 0.0, nMinPos
);
357 // horizontal text -> offset in x direction
358 aTranslation
.translate( nMinPos
, 0.0 );
361 ::canvas::tools::appendToRenderState( io_rRenderState
,
366 // reduce DX array to given substring
367 // ----------------------------------
369 const sal_Int32
nNewElements( rSubset
.mnSubsetEnd
- rSubset
.mnSubsetBegin
);
370 uno::Sequence
< double > aAdaptedOffsets( nNewElements
);
371 double* pAdaptedOffsets( aAdaptedOffsets
.getArray() );
373 // move to new output position (subtract nMinPos,
374 // which is the new '0' position), copy only the range
375 // as given by rSubset.
376 ::std::transform( pOffsets
+ rSubset
.mnSubsetBegin
,
377 pOffsets
+ rSubset
.mnSubsetEnd
,
379 ::boost::bind( ::std::minus
<double>(),
386 return aAdaptedOffsets
;
389 uno::Reference
< rendering::XTextLayout
>
390 createSubsetLayout( const rendering::StringContext
& rOrigContext
,
391 const ::cppcanvas::internal::Action::Subset
& rSubset
,
392 const uno::Reference
< rendering::XTextLayout
>& rOrigTextLayout
)
394 // create temporary new text layout with subset string
395 // ---------------------------------------------------
397 const sal_Int32
nNewStartPos( rOrigContext
.StartPosition
+ ::std::min(
398 rSubset
.mnSubsetBegin
, rOrigContext
.Length
-1 ) );
399 const sal_Int32
nNewLength( ::std::max(
401 rSubset
.mnSubsetEnd
- rSubset
.mnSubsetBegin
,
402 rOrigContext
.Length
),
405 const rendering::StringContext
aContext( rOrigContext
.Text
,
409 uno::Reference
< rendering::XTextLayout
> xTextLayout(
410 rOrigTextLayout
->getFont()->createTextLayout( aContext
,
411 rOrigTextLayout
->getMainTextDirection(),
413 uno::UNO_QUERY_THROW
);
418 /** Setup subset text layout
420 @param io_rTextLayout
421 Must contain original (full set) text layout on input,
422 will contain subsetted text layout (or empty
423 reference, for empty subsets) on output.
425 @param io_rRenderState
426 Must contain original render state on input, will
427 contain shifted render state concatenated with
428 rTransformation on output.
430 @param rTransformation
431 Additional transformation, to be prepended to render
437 void createSubsetLayout( uno::Reference
< rendering::XTextLayout
>& io_rTextLayout
,
438 rendering::RenderState
& io_rRenderState
,
441 const ::basegfx::B2DHomMatrix
& rTransformation
,
442 const Action::Subset
& rSubset
)
444 ::canvas::tools::prependToRenderState(io_rRenderState
, rTransformation
);
446 if( rSubset
.mnSubsetBegin
== rSubset
.mnSubsetEnd
)
448 // empty range, empty layout
449 io_rTextLayout
.clear();
454 ENSURE_OR_THROW( io_rTextLayout
.is(),
455 "createSubsetLayout(): Invalid input layout" );
457 const rendering::StringContext
& rOrigContext( io_rTextLayout
->getText() );
459 if( rSubset
.mnSubsetBegin
== 0 &&
460 rSubset
.mnSubsetEnd
== rOrigContext
.Length
)
462 // full range, no need for subsetting
466 uno::Reference
< rendering::XTextLayout
> xTextLayout(
467 createSubsetLayout( rOrigContext
, rSubset
, io_rTextLayout
) );
469 if( xTextLayout
.is() )
471 xTextLayout
->applyLogicalAdvancements(
472 calcSubsetOffsets( io_rRenderState
,
479 io_rTextLayout
= xTextLayout
;
483 /** Interface for renderEffectText functor below.
485 This is interface is used from the renderEffectText()
486 method below, to call the client implementation.
491 virtual ~TextRenderer() {}
493 /// Render text with given RenderState
494 virtual bool operator()( const rendering::RenderState
& rRenderState
) const = 0;
497 /** Render effect text.
500 Functor object, will be called to render the actual
501 part of the text effect (the text itself and the means
502 to render it are unknown to this method)
504 bool renderEffectText( const TextRenderer
& rRenderer
,
505 const rendering::RenderState
& rRenderState
,
506 const rendering::ViewState
& /*rViewState*/,
507 const uno::Reference
< rendering::XCanvas
>& xCanvas
,
508 const ::Color
& rShadowColor
,
509 const ::basegfx::B2DSize
& rShadowOffset
,
510 const ::Color
& rReliefColor
,
511 const ::basegfx::B2DSize
& rReliefOffset
)
513 ::Color
aEmptyColor( COL_AUTO
);
514 uno::Reference
<rendering::XColorSpace
> xColorSpace(
515 xCanvas
->getDevice()->getDeviceColorSpace() );
517 // draw shadow text, if enabled
518 if( rShadowColor
!= aEmptyColor
)
520 rendering::RenderState
aShadowState( rRenderState
);
521 ::basegfx::B2DHomMatrix aTranslate
;
523 aTranslate
.translate( rShadowOffset
.getX(),
524 rShadowOffset
.getY() );
526 ::canvas::tools::appendToRenderState(aShadowState
, aTranslate
);
528 aShadowState
.DeviceColor
=
529 ::vcl::unotools::colorToDoubleSequence( rShadowColor
,
532 rRenderer( aShadowState
);
535 // draw relief text, if enabled
536 if( rReliefColor
!= aEmptyColor
)
538 rendering::RenderState
aReliefState( rRenderState
);
539 ::basegfx::B2DHomMatrix aTranslate
;
541 aTranslate
.translate( rReliefOffset
.getX(),
542 rReliefOffset
.getY() );
544 ::canvas::tools::appendToRenderState(aReliefState
, aTranslate
);
546 aReliefState
.DeviceColor
=
547 ::vcl::unotools::colorToDoubleSequence( rReliefColor
,
550 rRenderer( aReliefState
);
554 rRenderer( rRenderState
);
560 ::basegfx::B2DRange
calcEffectTextBounds( const ::basegfx::B2DRange
& rTextBounds
,
561 const ::basegfx::B2DRange
& rLineBounds
,
562 const ::basegfx::B2DSize
& rReliefOffset
,
563 const ::basegfx::B2DSize
& rShadowOffset
,
564 const rendering::RenderState
& rRenderState
,
565 const rendering::ViewState
& rViewState
)
567 ::basegfx::B2DRange
aBounds( rTextBounds
);
569 // add extends of text lines
570 aBounds
.expand( rLineBounds
);
572 // TODO(Q3): Provide this functionality at the B2DRange
573 ::basegfx::B2DRange
aTotalBounds( aBounds
);
575 ::basegfx::B2DRange( aBounds
.getMinX() + rReliefOffset
.getX(),
576 aBounds
.getMinY() + rReliefOffset
.getY(),
577 aBounds
.getMaxX() + rReliefOffset
.getX(),
578 aBounds
.getMaxY() + rReliefOffset
.getY() ) );
580 ::basegfx::B2DRange( aBounds
.getMinX() + rShadowOffset
.getX(),
581 aBounds
.getMinY() + rShadowOffset
.getY(),
582 aBounds
.getMaxX() + rShadowOffset
.getX(),
583 aBounds
.getMaxY() + rShadowOffset
.getY() ) );
585 return tools::calcDevicePixelBounds( aTotalBounds
,
590 void initEffectLinePolyPolygon( ::basegfx::B2DSize
& o_rOverallSize
,
591 uno::Reference
< rendering::XPolyPolygon2D
>& o_rTextLines
,
592 const CanvasSharedPtr
& rCanvas
,
593 const uno::Sequence
< double >& rOffsets
,
594 const tools::TextLineInfo rLineInfo
)
596 const ::basegfx::B2DPolyPolygon
aPoly(
597 textLinesFromLogicalOffsets(
601 o_rOverallSize
= ::basegfx::tools::getRange( aPoly
).getRange();
603 o_rTextLines
= ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
604 rCanvas
->getUNOCanvas()->getDevice(),
608 void initEffectLinePolyPolygon( ::basegfx::B2DSize
& o_rOverallSize
,
609 uno::Reference
< rendering::XPolyPolygon2D
>& o_rTextLines
,
610 const CanvasSharedPtr
& rCanvas
,
612 const tools::TextLineInfo rLineInfo
)
614 const ::basegfx::B2DPolyPolygon
aPoly(
615 tools::createTextLinesPolyPolygon( 0.0, nLineWidth
,
618 o_rOverallSize
= ::basegfx::tools::getRange( aPoly
).getRange();
620 o_rTextLines
= ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
621 rCanvas
->getUNOCanvas()->getDevice(),
626 // -------------------------------------------------------------------------
628 class TextAction
: public Action
, private ::boost::noncopyable
631 TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
632 const ::rtl::OUString
& rString
,
635 const CanvasSharedPtr
& rCanvas
,
636 const OutDevState
& rState
);
638 TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
639 const ::rtl::OUString
& rString
,
642 const CanvasSharedPtr
& rCanvas
,
643 const OutDevState
& rState
,
644 const ::basegfx::B2DHomMatrix
& rTextTransform
);
646 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
647 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
648 const Subset
& rSubset
) const;
650 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
651 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
652 const Subset
& rSubset
) const;
654 virtual sal_Int32
getActionCount() const;
657 // TODO(P2): This is potentially a real mass object
658 // (every character might be a separate TextAction),
659 // thus, make it as lightweight as possible. For
660 // example, share common RenderState among several
661 // TextActions, maybe using maOffsets for the
664 uno::Reference
< rendering::XCanvasFont
> mxFont
;
665 const rendering::StringContext maStringContext
;
666 const CanvasSharedPtr mpCanvas
;
667 rendering::RenderState maState
;
668 const sal_Int8 maTextDirection
;
671 TextAction::TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
672 const ::rtl::OUString
& rString
,
675 const CanvasSharedPtr
& rCanvas
,
676 const OutDevState
& rState
) :
677 mxFont( rState
.xFont
),
678 maStringContext( rString
, nStartPos
, nLen
),
681 maTextDirection( rState
.textDirection
)
683 init( maState
, mxFont
,
687 ENSURE_OR_THROW( mxFont
.is(),
688 "::cppcanvas::internal::TextAction(): Invalid font" );
691 TextAction::TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
692 const ::rtl::OUString
& rString
,
695 const CanvasSharedPtr
& rCanvas
,
696 const OutDevState
& rState
,
697 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
698 mxFont( rState
.xFont
),
699 maStringContext( rString
, nStartPos
, nLen
),
702 maTextDirection( rState
.textDirection
)
704 init( maState
, mxFont
,
706 rState
, rCanvas
, rTextTransform
);
708 ENSURE_OR_THROW( mxFont
.is(),
709 "::cppcanvas::internal::TextAction(): Invalid font" );
712 bool TextAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
714 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::TextAction::render()" );
715 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::TextAction: 0x%X", this );
717 rendering::RenderState
aLocalState( maState
);
718 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
720 mpCanvas
->getUNOCanvas()->drawText( maStringContext
, mxFont
,
721 mpCanvas
->getViewState(), aLocalState
, maTextDirection
);
726 bool TextAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
727 const Subset
& /*rSubset*/ ) const
729 OSL_FAIL( "TextAction::renderSubset(): Subset not supported by this object" );
731 // TODO(P1): Retrieve necessary font metric info for
732 // TextAction from XCanvas. Currently, the
733 // TextActionFactory does not generate this object for
734 // _subsettable_ text
735 return render( rTransformation
);
738 ::basegfx::B2DRange
TextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
740 // create XTextLayout, to have the
741 // XTextLayout::queryTextBounds() method available
742 uno::Reference
< rendering::XTextLayout
> xTextLayout(
743 mxFont
->createTextLayout(
748 rendering::RenderState
aLocalState( maState
);
749 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
751 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
752 xTextLayout
->queryTextBounds() ),
753 mpCanvas
->getViewState(),
757 ::basegfx::B2DRange
TextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
758 const Subset
& /*rSubset*/ ) const
760 OSL_FAIL( "TextAction::getBounds(): Subset not supported by this object" );
762 // TODO(P1): Retrieve necessary font metric info for
763 // TextAction from XCanvas. Currently, the
764 // TextActionFactory does not generate this object for
765 // _subsettable_ text
766 return getBounds( rTransformation
);
769 sal_Int32
TextAction::getActionCount() const
771 // TODO(P1): Retrieve necessary font metric info for
772 // TextAction from XCanvas. Currently, the
773 // TextActionFactory does not generate this object for
774 // _subsettable_ text
779 // -------------------------------------------------------------------------
781 class EffectTextAction
:
784 private ::boost::noncopyable
787 EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
788 const ::basegfx::B2DSize
& rReliefOffset
,
789 const ::Color
& rReliefColor
,
790 const ::basegfx::B2DSize
& rShadowOffset
,
791 const ::Color
& rShadowColor
,
792 const ::rtl::OUString
& rText
,
795 VirtualDevice
& rVDev
,
796 const CanvasSharedPtr
& rCanvas
,
797 const OutDevState
& rState
);
799 EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
800 const ::basegfx::B2DSize
& rReliefOffset
,
801 const ::Color
& rReliefColor
,
802 const ::basegfx::B2DSize
& rShadowOffset
,
803 const ::Color
& rShadowColor
,
804 const ::rtl::OUString
& rText
,
807 VirtualDevice
& rVDev
,
808 const CanvasSharedPtr
& rCanvas
,
809 const OutDevState
& rState
,
810 const ::basegfx::B2DHomMatrix
& rTextTransform
);
812 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
813 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
814 const Subset
& rSubset
) const;
816 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
817 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
818 const Subset
& rSubset
) const;
820 virtual sal_Int32
getActionCount() const;
823 /// Interface TextRenderer
824 virtual bool operator()( const rendering::RenderState
& rRenderState
) const;
826 // TODO(P2): This is potentially a real mass object
827 // (every character might be a separate TextAction),
828 // thus, make it as lightweight as possible. For
829 // example, share common RenderState among several
830 // TextActions, maybe using maOffsets for the
833 uno::Reference
< rendering::XCanvasFont
> mxFont
;
834 const rendering::StringContext maStringContext
;
835 const CanvasSharedPtr mpCanvas
;
836 rendering::RenderState maState
;
837 const tools::TextLineInfo maTextLineInfo
;
838 ::basegfx::B2DSize maLinesOverallSize
;
839 const double mnLineWidth
;
840 uno::Reference
< rendering::XPolyPolygon2D
> mxTextLines
;
841 const ::basegfx::B2DSize maReliefOffset
;
842 const ::Color maReliefColor
;
843 const ::basegfx::B2DSize maShadowOffset
;
844 const ::Color maShadowColor
;
845 const sal_Int8 maTextDirection
;
848 EffectTextAction::EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
849 const ::basegfx::B2DSize
& rReliefOffset
,
850 const ::Color
& rReliefColor
,
851 const ::basegfx::B2DSize
& rShadowOffset
,
852 const ::Color
& rShadowColor
,
853 const ::rtl::OUString
& rText
,
856 VirtualDevice
& rVDev
,
857 const CanvasSharedPtr
& rCanvas
,
858 const OutDevState
& rState
) :
859 mxFont( rState
.xFont
),
860 maStringContext( rText
, nStartPos
, nLen
),
863 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
864 maLinesOverallSize(),
865 mnLineWidth( getLineWidth( rVDev
, rState
, maStringContext
) ),
867 maReliefOffset( rReliefOffset
),
868 maReliefColor( rReliefColor
),
869 maShadowOffset( rShadowOffset
),
870 maShadowColor( rShadowColor
),
871 maTextDirection( rState
.textDirection
)
873 initEffectLinePolyPolygon( maLinesOverallSize
,
879 init( maState
, mxFont
,
883 ENSURE_OR_THROW( mxFont
.is() && mxTextLines
.is(),
884 "::cppcanvas::internal::EffectTextAction(): Invalid font or lines" );
887 EffectTextAction::EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
888 const ::basegfx::B2DSize
& rReliefOffset
,
889 const ::Color
& rReliefColor
,
890 const ::basegfx::B2DSize
& rShadowOffset
,
891 const ::Color
& rShadowColor
,
892 const ::rtl::OUString
& rText
,
895 VirtualDevice
& rVDev
,
896 const CanvasSharedPtr
& rCanvas
,
897 const OutDevState
& rState
,
898 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
899 mxFont( rState
.xFont
),
900 maStringContext( rText
, nStartPos
, nLen
),
903 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
904 maLinesOverallSize(),
905 mnLineWidth( getLineWidth( rVDev
, rState
, maStringContext
) ),
907 maReliefOffset( rReliefOffset
),
908 maReliefColor( rReliefColor
),
909 maShadowOffset( rShadowOffset
),
910 maShadowColor( rShadowColor
),
911 maTextDirection( rState
.textDirection
)
913 initEffectLinePolyPolygon( maLinesOverallSize
,
919 init( maState
, mxFont
,
921 rState
, rCanvas
, rTextTransform
);
923 ENSURE_OR_THROW( mxFont
.is() && mxTextLines
.is(),
924 "::cppcanvas::internal::EffectTextAction(): Invalid font or lines" );
927 bool EffectTextAction::operator()( const rendering::RenderState
& rRenderState
) const
929 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
930 const uno::Reference
< rendering::XCanvas
>& rCanvas( mpCanvas
->getUNOCanvas() );
932 rCanvas
->fillPolyPolygon( mxTextLines
,
936 rCanvas
->drawText( maStringContext
, mxFont
,
944 bool EffectTextAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
946 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::EffectTextAction::render()" );
947 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::EffectTextAction: 0x%X", this );
949 rendering::RenderState
aLocalState( maState
);
950 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
952 return renderEffectText( *this,
954 mpCanvas
->getViewState(),
955 mpCanvas
->getUNOCanvas(),
962 bool EffectTextAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
963 const Subset
& /*rSubset*/ ) const
965 OSL_FAIL( "EffectTextAction::renderSubset(): Subset not supported by this object" );
967 // TODO(P1): Retrieve necessary font metric info for
968 // TextAction from XCanvas. Currently, the
969 // TextActionFactory does not generate this object for
971 return render( rTransformation
);
974 ::basegfx::B2DRange
EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
976 // create XTextLayout, to have the
977 // XTextLayout::queryTextBounds() method available
978 uno::Reference
< rendering::XTextLayout
> xTextLayout(
979 mxFont
->createTextLayout(
984 rendering::RenderState
aLocalState( maState
);
985 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
987 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
988 xTextLayout
->queryTextBounds() ),
989 ::basegfx::B2DRange( 0,0,
990 maLinesOverallSize
.getX(),
991 maLinesOverallSize
.getY() ),
995 mpCanvas
->getViewState() );
998 ::basegfx::B2DRange
EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
999 const Subset
& /*rSubset*/ ) const
1001 OSL_FAIL( "EffectTextAction::getBounds(): Subset not supported by this object" );
1003 // TODO(P1): Retrieve necessary font metric info for
1004 // TextAction from XCanvas. Currently, the
1005 // TextActionFactory does not generate this object for
1006 // _subsettable_ text
1007 return getBounds( rTransformation
);
1010 sal_Int32
EffectTextAction::getActionCount() const
1012 // TODO(P1): Retrieve necessary font metric info for
1013 // TextAction from XCanvas. Currently, the
1014 // TextActionFactory does not generate this object for
1020 // -------------------------------------------------------------------------
1022 class TextArrayAction
: public Action
, private ::boost::noncopyable
1025 TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1026 const ::rtl::OUString
& rString
,
1027 sal_Int32 nStartPos
,
1029 const uno::Sequence
< double >& rOffsets
,
1030 const CanvasSharedPtr
& rCanvas
,
1031 const OutDevState
& rState
);
1033 TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1034 const ::rtl::OUString
& rString
,
1035 sal_Int32 nStartPos
,
1037 const uno::Sequence
< double >& rOffsets
,
1038 const CanvasSharedPtr
& rCanvas
,
1039 const OutDevState
& rState
,
1040 const ::basegfx::B2DHomMatrix
& rTextTransform
);
1042 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1043 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1044 const Subset
& rSubset
) const;
1046 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1047 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1048 const Subset
& rSubset
) const;
1050 virtual sal_Int32
getActionCount() const;
1053 // TODO(P2): This is potentially a real mass object
1054 // (every character might be a separate TextAction),
1055 // thus, make it as lightweight as possible. For
1056 // example, share common RenderState among several
1057 // TextActions, maybe using maOffsets for the
1060 uno::Reference
< rendering::XTextLayout
> mxTextLayout
;
1061 const CanvasSharedPtr mpCanvas
;
1062 rendering::RenderState maState
;
1065 TextArrayAction::TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1066 const ::rtl::OUString
& rString
,
1067 sal_Int32 nStartPos
,
1069 const uno::Sequence
< double >& rOffsets
,
1070 const CanvasSharedPtr
& rCanvas
,
1071 const OutDevState
& rState
) :
1073 mpCanvas( rCanvas
),
1076 initArrayAction( maState
,
1087 TextArrayAction::TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1088 const ::rtl::OUString
& rString
,
1089 sal_Int32 nStartPos
,
1091 const uno::Sequence
< double >& rOffsets
,
1092 const CanvasSharedPtr
& rCanvas
,
1093 const OutDevState
& rState
,
1094 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
1096 mpCanvas( rCanvas
),
1099 initArrayAction( maState
,
1111 bool TextArrayAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1113 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::TextArrayAction::render()" );
1114 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::TextArrayAction: 0x%X", this );
1116 rendering::RenderState
aLocalState( maState
);
1117 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1119 mpCanvas
->getUNOCanvas()->drawTextLayout( mxTextLayout
,
1120 mpCanvas
->getViewState(),
1126 bool TextArrayAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1127 const Subset
& rSubset
) const
1129 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::TextArrayAction::renderSubset()" );
1130 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::TextArrayAction: 0x%X", this );
1132 rendering::RenderState
aLocalState( maState
);
1133 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1135 double nDummy0
, nDummy1
;
1136 createSubsetLayout( xTextLayout
,
1143 if( !xTextLayout
.is() )
1144 return true; // empty layout, render nothing
1146 mpCanvas
->getUNOCanvas()->drawTextLayout( xTextLayout
,
1147 mpCanvas
->getViewState(),
1153 ::basegfx::B2DRange
TextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1155 rendering::RenderState
aLocalState( maState
);
1156 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1158 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1159 mxTextLayout
->queryTextBounds() ),
1160 mpCanvas
->getViewState(),
1164 ::basegfx::B2DRange
TextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1165 const Subset
& rSubset
) const
1167 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::TextArrayAction::getBounds( subset )" );
1168 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::TextArrayAction: 0x%X", this );
1170 rendering::RenderState
aLocalState( maState
);
1171 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1173 double nDummy0
, nDummy1
;
1174 createSubsetLayout( xTextLayout
,
1181 if( !xTextLayout
.is() )
1182 return ::basegfx::B2DRange(); // empty layout, empty bounds
1184 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1185 xTextLayout
->queryTextBounds() ),
1186 mpCanvas
->getViewState(),
1190 sal_Int32
TextArrayAction::getActionCount() const
1192 const rendering::StringContext
& rOrigContext( mxTextLayout
->getText() );
1194 return rOrigContext
.Length
;
1198 // -------------------------------------------------------------------------
1200 class EffectTextArrayAction
:
1202 public TextRenderer
,
1203 private ::boost::noncopyable
1206 EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1207 const ::basegfx::B2DSize
& rReliefOffset
,
1208 const ::Color
& rReliefColor
,
1209 const ::basegfx::B2DSize
& rShadowOffset
,
1210 const ::Color
& rShadowColor
,
1211 const ::rtl::OUString
& rText
,
1212 sal_Int32 nStartPos
,
1214 const uno::Sequence
< double >& rOffsets
,
1215 VirtualDevice
& rVDev
,
1216 const CanvasSharedPtr
& rCanvas
,
1217 const OutDevState
& rState
);
1218 EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1219 const ::basegfx::B2DSize
& rReliefOffset
,
1220 const ::Color
& rReliefColor
,
1221 const ::basegfx::B2DSize
& rShadowOffset
,
1222 const ::Color
& rShadowColor
,
1223 const ::rtl::OUString
& rText
,
1224 sal_Int32 nStartPos
,
1226 const uno::Sequence
< double >& rOffsets
,
1227 VirtualDevice
& rVDev
,
1228 const CanvasSharedPtr
& rCanvas
,
1229 const OutDevState
& rState
,
1230 const ::basegfx::B2DHomMatrix
& rTextTransform
);
1232 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1233 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1234 const Subset
& rSubset
) const;
1236 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1237 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1238 const Subset
& rSubset
) const;
1240 virtual sal_Int32
getActionCount() const;
1243 // TextRenderer interface
1244 virtual bool operator()( const rendering::RenderState
& rRenderState
) const;
1246 // TODO(P2): This is potentially a real mass object
1247 // (every character might be a separate TextAction),
1248 // thus, make it as lightweight as possible. For
1249 // example, share common RenderState among several
1250 // TextActions, maybe using maOffsets for the
1253 uno::Reference
< rendering::XTextLayout
> mxTextLayout
;
1254 const CanvasSharedPtr mpCanvas
;
1255 rendering::RenderState maState
;
1256 const tools::TextLineInfo maTextLineInfo
;
1257 ::basegfx::B2DSize maLinesOverallSize
;
1258 uno::Reference
< rendering::XPolyPolygon2D
> mxTextLines
;
1259 const ::basegfx::B2DSize maReliefOffset
;
1260 const ::Color maReliefColor
;
1261 const ::basegfx::B2DSize maShadowOffset
;
1262 const ::Color maShadowColor
;
1265 EffectTextArrayAction::EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1266 const ::basegfx::B2DSize
& rReliefOffset
,
1267 const ::Color
& rReliefColor
,
1268 const ::basegfx::B2DSize
& rShadowOffset
,
1269 const ::Color
& rShadowColor
,
1270 const ::rtl::OUString
& rText
,
1271 sal_Int32 nStartPos
,
1273 const uno::Sequence
< double >& rOffsets
,
1274 VirtualDevice
& rVDev
,
1275 const CanvasSharedPtr
& rCanvas
,
1276 const OutDevState
& rState
) :
1278 mpCanvas( rCanvas
),
1280 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1281 maLinesOverallSize(),
1283 maReliefOffset( rReliefOffset
),
1284 maReliefColor( rReliefColor
),
1285 maShadowOffset( rShadowOffset
),
1286 maShadowColor( rShadowColor
)
1288 initEffectLinePolyPolygon( maLinesOverallSize
,
1294 initArrayAction( maState
,
1305 EffectTextArrayAction::EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1306 const ::basegfx::B2DSize
& rReliefOffset
,
1307 const ::Color
& rReliefColor
,
1308 const ::basegfx::B2DSize
& rShadowOffset
,
1309 const ::Color
& rShadowColor
,
1310 const ::rtl::OUString
& rText
,
1311 sal_Int32 nStartPos
,
1313 const uno::Sequence
< double >& rOffsets
,
1314 VirtualDevice
& rVDev
,
1315 const CanvasSharedPtr
& rCanvas
,
1316 const OutDevState
& rState
,
1317 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
1319 mpCanvas( rCanvas
),
1321 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1322 maLinesOverallSize(),
1324 maReliefOffset( rReliefOffset
),
1325 maReliefColor( rReliefColor
),
1326 maShadowOffset( rShadowOffset
),
1327 maShadowColor( rShadowColor
)
1329 initEffectLinePolyPolygon( maLinesOverallSize
,
1335 initArrayAction( maState
,
1347 bool EffectTextArrayAction::operator()( const rendering::RenderState
& rRenderState
) const
1349 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
1350 const uno::Reference
< rendering::XCanvas
>& rCanvas( mpCanvas
->getUNOCanvas() );
1352 rCanvas
->fillPolyPolygon( mxTextLines
,
1356 rCanvas
->drawTextLayout( mxTextLayout
,
1363 bool EffectTextArrayAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1365 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::EffectTextArrayAction::render()" );
1366 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
1368 rendering::RenderState
aLocalState( maState
);
1369 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1371 return renderEffectText( *this,
1373 mpCanvas
->getViewState(),
1374 mpCanvas
->getUNOCanvas(),
1381 class EffectTextArrayRenderHelper
: public TextRenderer
1384 EffectTextArrayRenderHelper( const uno::Reference
< rendering::XCanvas
>& rCanvas
,
1385 const uno::Reference
< rendering::XTextLayout
>& rTextLayout
,
1386 const uno::Reference
< rendering::XPolyPolygon2D
>& rLinePolygon
,
1387 const rendering::ViewState
& rViewState
) :
1388 mrCanvas( rCanvas
),
1389 mrTextLayout( rTextLayout
),
1390 mrLinePolygon( rLinePolygon
),
1391 mrViewState( rViewState
)
1395 // TextRenderer interface
1396 virtual bool operator()( const rendering::RenderState
& rRenderState
) const
1398 mrCanvas
->fillPolyPolygon( mrLinePolygon
,
1402 mrCanvas
->drawTextLayout( mrTextLayout
,
1410 const uno::Reference
< rendering::XCanvas
>& mrCanvas
;
1411 const uno::Reference
< rendering::XTextLayout
>& mrTextLayout
;
1412 const uno::Reference
< rendering::XPolyPolygon2D
>& mrLinePolygon
;
1413 const rendering::ViewState
& mrViewState
;
1416 bool EffectTextArrayAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1417 const Subset
& rSubset
) const
1419 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::EffectTextArrayAction::renderSubset()" );
1420 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
1422 rendering::RenderState
aLocalState( maState
);
1423 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1424 const geometry::RealRectangle2D
aTextBounds( mxTextLayout
->queryTextBounds() );
1426 double nMinPos(0.0);
1427 double nMaxPos(aTextBounds
.X2
- aTextBounds
.X1
);
1429 createSubsetLayout( xTextLayout
,
1436 if( !xTextLayout
.is() )
1437 return true; // empty layout, render nothing
1440 // create and setup local line polygon
1441 // ===================================
1443 uno::Reference
< rendering::XCanvas
> xCanvas( mpCanvas
->getUNOCanvas() );
1444 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
1446 uno::Reference
< rendering::XPolyPolygon2D
> xTextLines(
1447 ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
1448 xCanvas
->getDevice(),
1449 tools::createTextLinesPolyPolygon(
1450 0.0, nMaxPos
- nMinPos
,
1451 maTextLineInfo
) ) );
1454 // render everything
1455 // =================
1457 return renderEffectText(
1458 EffectTextArrayRenderHelper( xCanvas
,
1471 ::basegfx::B2DRange
EffectTextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1473 rendering::RenderState
aLocalState( maState
);
1474 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1476 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1477 mxTextLayout
->queryTextBounds() ),
1478 ::basegfx::B2DRange( 0,0,
1479 maLinesOverallSize
.getX(),
1480 maLinesOverallSize
.getY() ),
1484 mpCanvas
->getViewState() );
1487 ::basegfx::B2DRange
EffectTextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1488 const Subset
& rSubset
) const
1490 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::EffectTextArrayAction::getBounds( subset )" );
1491 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
1493 rendering::RenderState
aLocalState( maState
);
1494 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1495 const geometry::RealRectangle2D
aTextBounds( mxTextLayout
->queryTextBounds() );
1497 double nMinPos(0.0);
1498 double nMaxPos(aTextBounds
.X2
- aTextBounds
.X1
);
1500 createSubsetLayout( xTextLayout
,
1507 if( !xTextLayout
.is() )
1508 return ::basegfx::B2DRange(); // empty layout, empty bounds
1511 // create and setup local line polygon
1512 // ===================================
1514 const ::basegfx::B2DPolyPolygon
aPoly(
1515 tools::createTextLinesPolyPolygon(
1516 0.0, nMaxPos
- nMinPos
,
1519 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1520 xTextLayout
->queryTextBounds() ),
1521 ::basegfx::tools::getRange( aPoly
),
1525 mpCanvas
->getViewState() );
1528 sal_Int32
EffectTextArrayAction::getActionCount() const
1530 const rendering::StringContext
& rOrigContext( mxTextLayout
->getText() );
1532 return rOrigContext
.Length
;
1536 // -------------------------------------------------------------------------
1538 class OutlineAction
:
1540 public TextRenderer
,
1541 private ::boost::noncopyable
1544 OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1545 const ::basegfx::B2DSize
& rReliefOffset
,
1546 const ::Color
& rReliefColor
,
1547 const ::basegfx::B2DSize
& rShadowOffset
,
1548 const ::Color
& rShadowColor
,
1549 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1550 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1551 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1552 const uno::Sequence
< double >& rOffsets
,
1553 VirtualDevice
& rVDev
,
1554 const CanvasSharedPtr
& rCanvas
,
1555 const OutDevState
& rState
);
1556 OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1557 const ::basegfx::B2DSize
& rReliefOffset
,
1558 const ::Color
& rReliefColor
,
1559 const ::basegfx::B2DSize
& rShadowOffset
,
1560 const ::Color
& rShadowColor
,
1561 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1562 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1563 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1564 const uno::Sequence
< double >& rOffsets
,
1565 VirtualDevice
& rVDev
,
1566 const CanvasSharedPtr
& rCanvas
,
1567 const OutDevState
& rState
,
1568 const ::basegfx::B2DHomMatrix
& rTextTransform
);
1570 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1571 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1572 const Subset
& rSubset
) const;
1574 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1575 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1576 const Subset
& rSubset
) const;
1578 virtual sal_Int32
getActionCount() const;
1581 // TextRenderer interface
1582 virtual bool operator()( const rendering::RenderState
& rRenderState
) const;
1584 // TODO(P2): This is potentially a real mass object
1585 // (every character might be a separate TextAction),
1586 // thus, make it as lightweight as possible. For
1587 // example, share common RenderState among several
1588 // TextActions, maybe using maOffsets for the
1591 uno::Reference
< rendering::XPolyPolygon2D
> mxTextPoly
;
1593 /** This vector denotes the index of the start polygon
1594 for the respective glyph sequence.
1596 To get a polygon index range for a given character
1597 index i, take [ maPolygonGlyphMap[i],
1598 maPolygonGlyphMap[i+1] ). Note that this is wrong
1601 const ::std::vector
< sal_Int32
> maPolygonGlyphMap
;
1602 const uno::Sequence
< double > maOffsets
;
1603 const CanvasSharedPtr mpCanvas
;
1604 rendering::RenderState maState
;
1605 double mnOutlineWidth
;
1606 const uno::Sequence
< double > maFillColor
;
1607 const tools::TextLineInfo maTextLineInfo
;
1608 ::basegfx::B2DSize maLinesOverallSize
;
1609 const ::basegfx::B2DRectangle maOutlineBounds
;
1610 uno::Reference
< rendering::XPolyPolygon2D
> mxTextLines
;
1611 const ::basegfx::B2DSize maReliefOffset
;
1612 const ::Color maReliefColor
;
1613 const ::basegfx::B2DSize maShadowOffset
;
1614 const ::Color maShadowColor
;
1617 double calcOutlineWidth( const OutDevState
& rState
,
1618 VirtualDevice
& rVDev
)
1620 const ::basegfx::B2DSize
aFontSize( 0,
1621 rVDev
.GetFont().GetHeight() / 64.0 );
1623 const double nOutlineWidth(
1624 (rState
.mapModeTransform
* aFontSize
).getY() );
1626 return nOutlineWidth
< 1.0 ? 1.0 : nOutlineWidth
;
1629 OutlineAction::OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1630 const ::basegfx::B2DSize
& rReliefOffset
,
1631 const ::Color
& rReliefColor
,
1632 const ::basegfx::B2DSize
& rShadowOffset
,
1633 const ::Color
& rShadowColor
,
1634 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1635 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1636 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1637 const uno::Sequence
< double >& rOffsets
,
1638 VirtualDevice
& rVDev
,
1639 const CanvasSharedPtr
& rCanvas
,
1640 const OutDevState
& rState
) :
1641 mxTextPoly( rTextPoly
),
1642 maPolygonGlyphMap( rPolygonGlyphMap
),
1643 maOffsets( rOffsets
),
1644 mpCanvas( rCanvas
),
1646 mnOutlineWidth( calcOutlineWidth(rState
,rVDev
) ),
1648 ::vcl::unotools::colorToDoubleSequence(
1649 ::Color( COL_WHITE
),
1650 rCanvas
->getUNOCanvas()->getDevice()->getDeviceColorSpace() )),
1651 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1652 maLinesOverallSize(),
1653 maOutlineBounds( rOutlineBounds
),
1655 maReliefOffset( rReliefOffset
),
1656 maReliefColor( rReliefColor
),
1657 maShadowOffset( rShadowOffset
),
1658 maShadowColor( rShadowColor
)
1660 initEffectLinePolyPolygon( maLinesOverallSize
,
1672 OutlineAction::OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1673 const ::basegfx::B2DSize
& rReliefOffset
,
1674 const ::Color
& rReliefColor
,
1675 const ::basegfx::B2DSize
& rShadowOffset
,
1676 const ::Color
& rShadowColor
,
1677 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1678 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1679 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1680 const uno::Sequence
< double >& rOffsets
,
1681 VirtualDevice
& rVDev
,
1682 const CanvasSharedPtr
& rCanvas
,
1683 const OutDevState
& rState
,
1684 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
1685 mxTextPoly( rTextPoly
),
1686 maPolygonGlyphMap( rPolygonGlyphMap
),
1687 maOffsets( rOffsets
),
1688 mpCanvas( rCanvas
),
1690 mnOutlineWidth( calcOutlineWidth(rState
,rVDev
) ),
1692 ::vcl::unotools::colorToDoubleSequence(
1693 ::Color( COL_WHITE
),
1694 rCanvas
->getUNOCanvas()->getDevice()->getDeviceColorSpace() )),
1695 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1696 maLinesOverallSize(),
1697 maOutlineBounds( rOutlineBounds
),
1699 maReliefOffset( rReliefOffset
),
1700 maReliefColor( rReliefColor
),
1701 maShadowOffset( rShadowOffset
),
1702 maShadowColor( rShadowColor
)
1704 initEffectLinePolyPolygon( maLinesOverallSize
,
1717 bool OutlineAction::operator()( const rendering::RenderState
& rRenderState
) const
1719 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
1720 const uno::Reference
< rendering::XCanvas
>& rCanvas( mpCanvas
->getUNOCanvas() );
1722 rendering::StrokeAttributes aStrokeAttributes
;
1724 aStrokeAttributes
.StrokeWidth
= mnOutlineWidth
;
1725 aStrokeAttributes
.MiterLimit
= 1.0;
1726 aStrokeAttributes
.StartCapType
= rendering::PathCapType::BUTT
;
1727 aStrokeAttributes
.EndCapType
= rendering::PathCapType::BUTT
;
1728 aStrokeAttributes
.JoinType
= rendering::PathJoinType::MITER
;
1730 rendering::RenderState
aLocalState( rRenderState
);
1731 aLocalState
.DeviceColor
= maFillColor
;
1733 // TODO(P1): implement caching
1735 // background of text
1736 rCanvas
->fillPolyPolygon( mxTextPoly
,
1740 // border line of text
1741 rCanvas
->strokePolyPolygon( mxTextPoly
,
1744 aStrokeAttributes
);
1746 // underlines/strikethrough - background
1747 rCanvas
->fillPolyPolygon( mxTextLines
,
1750 // underlines/strikethrough - border
1751 rCanvas
->strokePolyPolygon( mxTextLines
,
1754 aStrokeAttributes
);
1759 bool OutlineAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1761 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::EffectTextArrayAction::render()" );
1762 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );
1764 rendering::RenderState
aLocalState( maState
);
1765 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1767 return renderEffectText( *this,
1769 mpCanvas
->getViewState(),
1770 mpCanvas
->getUNOCanvas(),
1777 class OutlineTextArrayRenderHelper
: public TextRenderer
1780 OutlineTextArrayRenderHelper( const uno::Reference
< rendering::XCanvas
>& rCanvas
,
1781 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPolygon
,
1782 const uno::Reference
< rendering::XPolyPolygon2D
>& rLinePolygon
,
1783 const rendering::ViewState
& rViewState
,
1784 double nOutlineWidth
) :
1786 ::vcl::unotools::colorToDoubleSequence(
1787 ::Color( COL_WHITE
),
1788 rCanvas
->getDevice()->getDeviceColorSpace() )),
1789 mnOutlineWidth( nOutlineWidth
),
1790 mrCanvas( rCanvas
),
1791 mrTextPolygon( rTextPolygon
),
1792 mrLinePolygon( rLinePolygon
),
1793 mrViewState( rViewState
)
1797 // TextRenderer interface
1798 virtual bool operator()( const rendering::RenderState
& rRenderState
) const
1800 rendering::StrokeAttributes aStrokeAttributes
;
1802 aStrokeAttributes
.StrokeWidth
= mnOutlineWidth
;
1803 aStrokeAttributes
.MiterLimit
= 1.0;
1804 aStrokeAttributes
.StartCapType
= rendering::PathCapType::BUTT
;
1805 aStrokeAttributes
.EndCapType
= rendering::PathCapType::BUTT
;
1806 aStrokeAttributes
.JoinType
= rendering::PathJoinType::MITER
;
1808 rendering::RenderState
aLocalState( rRenderState
);
1809 aLocalState
.DeviceColor
= maFillColor
;
1811 // TODO(P1): implement caching
1813 // background of text
1814 mrCanvas
->fillPolyPolygon( mrTextPolygon
,
1818 // border line of text
1819 mrCanvas
->strokePolyPolygon( mrTextPolygon
,
1822 aStrokeAttributes
);
1824 // underlines/strikethrough - background
1825 mrCanvas
->fillPolyPolygon( mrLinePolygon
,
1828 // underlines/strikethrough - border
1829 mrCanvas
->strokePolyPolygon( mrLinePolygon
,
1832 aStrokeAttributes
);
1838 const uno::Sequence
< double > maFillColor
;
1839 double mnOutlineWidth
;
1840 const uno::Reference
< rendering::XCanvas
>& mrCanvas
;
1841 const uno::Reference
< rendering::XPolyPolygon2D
>& mrTextPolygon
;
1842 const uno::Reference
< rendering::XPolyPolygon2D
>& mrLinePolygon
;
1843 const rendering::ViewState
& mrViewState
;
1846 bool OutlineAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1847 const Subset
& rSubset
) const
1849 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::OutlineAction::renderSubset()" );
1850 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::OutlineAction: 0x%X", this );
1852 if( rSubset
.mnSubsetBegin
== rSubset
.mnSubsetEnd
)
1853 return true; // empty range, render nothing
1856 // TODO(F3): Subsetting NYI for outline text!
1857 return render( rTransformation
);
1859 const rendering::StringContext
rOrigContext( mxTextLayout
->getText() );
1861 if( rSubset
.mnSubsetBegin
== 0 &&
1862 rSubset
.mnSubsetEnd
== rOrigContext
.Length
)
1864 // full range, no need for subsetting
1865 return render( rTransformation
);
1868 rendering::RenderState
aLocalState( maState
);
1869 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1872 // create and setup local Text polygon
1873 // ===================================
1875 uno::Reference
< rendering::XPolyPolygon2D
> xTextPolygon();
1877 // TODO(P3): Provide an API method for that!
1879 if( !xTextLayout
.is() )
1882 // render everything
1883 // =================
1885 return renderEffectText(
1886 OutlineTextArrayRenderHelper(
1902 ::basegfx::B2DRange
OutlineAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1904 rendering::RenderState
aLocalState( maState
);
1905 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1907 return calcEffectTextBounds( maOutlineBounds
,
1908 ::basegfx::B2DRange( 0,0,
1909 maLinesOverallSize
.getX(),
1910 maLinesOverallSize
.getY() ),
1914 mpCanvas
->getViewState() );
1917 ::basegfx::B2DRange
OutlineAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1918 const Subset
& /*rSubset*/ ) const
1920 OSL_FAIL( "OutlineAction::getBounds(): Subset not yet supported by this object" );
1922 return getBounds( rTransformation
);
1925 sal_Int32
OutlineAction::getActionCount() const
1927 // TODO(F3): Subsetting NYI for outline text!
1928 return maOffsets
.getLength();
1932 // ======================================================================
1934 // Action factory methods
1936 // ======================================================================
1938 /** Create an outline action
1940 This method extracts the polygonal outline from the
1941 text, and creates a properly setup OutlineAction from
1944 ActionSharedPtr
createOutline( const ::basegfx::B2DPoint
& rStartPoint
,
1945 const ::basegfx::B2DSize
& rReliefOffset
,
1946 const ::Color
& rReliefColor
,
1947 const ::basegfx::B2DSize
& rShadowOffset
,
1948 const ::Color
& rShadowColor
,
1949 const String
& rText
,
1950 sal_Int32 nStartPos
,
1952 const sal_Int32
* pDXArray
,
1953 VirtualDevice
& rVDev
,
1954 const CanvasSharedPtr
& rCanvas
,
1955 const OutDevState
& rState
,
1956 const Renderer::Parameters
& rParms
)
1958 // operate on raw DX array here (in logical coordinate
1959 // system), to have a higher resolution
1960 // PolyPolygon. That polygon is then converted to
1961 // device coordinate system.
1963 // #i68512# Temporarily switch off font rotation
1964 // (which is already contained in the render state
1965 // transformation matrix - otherwise, glyph polygons
1966 // will be rotated twice)
1967 const ::Font
aOrigFont( rVDev
.GetFont() );
1968 ::Font
aUnrotatedFont( aOrigFont
);
1969 aUnrotatedFont
.SetOrientation(0);
1970 rVDev
.SetFont( aUnrotatedFont
);
1972 // TODO(F3): Don't understand parameter semantics of
1973 // GetTextOutlines()
1974 ::basegfx::B2DPolyPolygon aResultingPolyPolygon
;
1975 PolyPolyVector aVCLPolyPolyVector
;
1976 const bool bHaveOutlines( rVDev
.GetTextOutlines( aVCLPolyPolyVector
, rText
,
1977 static_cast<sal_uInt16
>(nStartPos
),
1978 static_cast<sal_uInt16
>(nStartPos
),
1979 static_cast<sal_uInt16
>(nLen
),
1980 sal_True
, 0, pDXArray
) );
1981 rVDev
.SetFont(aOrigFont
);
1983 if( !bHaveOutlines
)
1984 return ActionSharedPtr();
1986 ::std::vector
< sal_Int32
> aPolygonGlyphMap
;
1988 // first glyph starts at polygon index 0
1989 aPolygonGlyphMap
.push_back( 0 );
1991 // remove offsetting from mapmode transformation
1992 // (outline polygons must stay at origin, only need to
1994 ::basegfx::B2DHomMatrix
aMapModeTransform(
1995 rState
.mapModeTransform
);
1996 aMapModeTransform
.set(0,2, 0.0);
1997 aMapModeTransform
.set(1,2, 0.0);
1999 PolyPolyVector::const_iterator
aIter( aVCLPolyPolyVector
.begin() );
2000 const PolyPolyVector::const_iterator
aEnd( aVCLPolyPolyVector
.end() );
2001 for( ; aIter
!= aEnd
; ++aIter
)
2003 ::basegfx::B2DPolyPolygon aPolyPolygon
;
2005 aPolyPolygon
= aIter
->getB2DPolyPolygon();
2006 aPolyPolygon
.transform( aMapModeTransform
);
2008 // append result to collecting polypoly
2009 for( sal_uInt32 i
=0; i
<aPolyPolygon
.count(); ++i
)
2011 // #i47795# Ensure closed polygons (since
2012 // FreeType returns the glyph outlines
2014 const ::basegfx::B2DPolygon
& rPoly( aPolyPolygon
.getB2DPolygon( i
) );
2015 const sal_uInt32
nCount( rPoly
.count() );
2019 // polygon either degenerate, or
2021 aResultingPolyPolygon
.append( rPoly
);
2025 ::basegfx::B2DPolygon
aPoly(rPoly
);
2026 aPoly
.setClosed(true);
2028 aResultingPolyPolygon
.append( aPoly
);
2032 // TODO(F3): Depending on the semantics of
2033 // GetTextOutlines(), this here is wrong!
2035 // calc next glyph index
2036 aPolygonGlyphMap
.push_back( aResultingPolyPolygon
.count() );
2039 const uno::Sequence
< double > aCharWidthSeq(
2041 setupDXArray( pDXArray
, nLen
, rState
) :
2042 setupDXArray( rText
,
2047 const uno::Reference
< rendering::XPolyPolygon2D
> xTextPoly(
2048 ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
2049 rCanvas
->getUNOCanvas()->getDevice(),
2050 aResultingPolyPolygon
) );
2052 if( rParms
.maTextTransformation
.is_initialized() )
2054 return ActionSharedPtr(
2061 ::basegfx::tools::getRange(aResultingPolyPolygon
),
2068 *rParms
.maTextTransformation
) );
2072 return ActionSharedPtr(
2079 ::basegfx::tools::getRange(aResultingPolyPolygon
),
2092 // ---------------------------------------------------------------------------------
2094 ActionSharedPtr
TextActionFactory::createTextAction( const ::Point
& rStartPoint
,
2095 const ::Size
& rReliefOffset
,
2096 const ::Color
& rReliefColor
,
2097 const ::Size
& rShadowOffset
,
2098 const ::Color
& rShadowColor
,
2099 const String
& rText
,
2100 sal_Int32 nStartPos
,
2102 const sal_Int32
* pDXArray
,
2103 VirtualDevice
& rVDev
,
2104 const CanvasSharedPtr
& rCanvas
,
2105 const OutDevState
& rState
,
2106 const Renderer::Parameters
& rParms
,
2109 const ::Size
aBaselineOffset( tools::getBaselineOffset( rState
,
2111 // #143885# maintain (nearly) full precision positioning,
2112 // by circumventing integer-based OutDev-mapping
2113 const ::basegfx::B2DPoint
aStartPoint(
2114 rState
.mapModeTransform
*
2115 ::basegfx::B2DPoint(rStartPoint
.X() + aBaselineOffset
.Width(),
2116 rStartPoint
.Y() + aBaselineOffset
.Height()) );
2118 const ::basegfx::B2DSize
aReliefOffset(
2119 rState
.mapModeTransform
* ::vcl::unotools::b2DSizeFromSize( rReliefOffset
) );
2120 const ::basegfx::B2DSize
aShadowOffset(
2121 rState
.mapModeTransform
* ::vcl::unotools::b2DSizeFromSize( rShadowOffset
) );
2123 if( rState
.isTextOutlineModeSet
)
2125 return createOutline(
2141 // convert DX array to device coordinate system (and
2142 // create it in the first place, if pDXArray is NULL)
2143 const uno::Sequence
< double > aCharWidths(
2145 setupDXArray( pDXArray
, nLen
, rState
) :
2146 setupDXArray( rText
,
2152 // determine type of text action to create
2153 // =======================================
2155 const ::Color
aEmptyColor( COL_AUTO
);
2157 // no DX array, and no need to subset - no need to store
2159 if( !pDXArray
&& !bSubsettable
)
2162 if( !rState
.textOverlineStyle
&&
2163 !rState
.textUnderlineStyle
&&
2164 !rState
.textStrikeoutStyle
&&
2165 rReliefColor
== aEmptyColor
&&
2166 rShadowColor
== aEmptyColor
)
2169 if( rParms
.maTextTransformation
.is_initialized() )
2171 return ActionSharedPtr( new TextAction(
2178 *rParms
.maTextTransformation
) );
2182 return ActionSharedPtr( new TextAction(
2193 // at least one of the effects requested
2194 if( rParms
.maTextTransformation
.is_initialized() )
2195 return ActionSharedPtr( new EffectTextAction(
2207 *rParms
.maTextTransformation
) );
2209 return ActionSharedPtr( new EffectTextAction(
2225 // DX array necessary - any effects?
2226 if( !rState
.textOverlineStyle
&&
2227 !rState
.textUnderlineStyle
&&
2228 !rState
.textStrikeoutStyle
&&
2229 rReliefColor
== aEmptyColor
&&
2230 rShadowColor
== aEmptyColor
)
2233 if( rParms
.maTextTransformation
.is_initialized() )
2234 return ActionSharedPtr( new TextArrayAction(
2242 *rParms
.maTextTransformation
) );
2244 return ActionSharedPtr( new TextArrayAction(
2255 // at least one of the effects requested
2256 if( rParms
.maTextTransformation
.is_initialized() )
2257 return ActionSharedPtr( new EffectTextArrayAction(
2270 *rParms
.maTextTransformation
) );
2272 return ActionSharedPtr( new EffectTextArrayAction(
2287 #if defined(__GNUC__)
2288 return ActionSharedPtr();
2294 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */