1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <canvas/debug.hxx>
22 #include <tools/diagnose_ex.h>
23 #include <canvas/verbosetrace.hxx>
25 #include <com/sun/star/rendering/PathCapType.hpp>
26 #include <com/sun/star/rendering/PathJoinType.hpp>
27 #include <com/sun/star/rendering/XCanvas.hpp>
28 #include <com/sun/star/rendering/XCanvasFont.hpp>
30 #include <basegfx/numeric/ftools.hxx>
31 #include <basegfx/matrix/b2dhommatrix.hxx>
32 #include <basegfx/range/b2drectangle.hxx>
33 #include <basegfx/vector/b2dsize.hxx>
34 #include <basegfx/polygon/b2dpolypolygontools.hxx>
35 #include <basegfx/polygon/b2dpolygontools.hxx>
36 #include <basegfx/matrix/b2dhommatrixtools.hxx>
38 #include <tools/gen.hxx>
39 #include <vcl/canvastools.hxx>
40 #include <vcl/virdev.hxx>
42 #include <basegfx/tools/canvastools.hxx>
43 #include <canvas/canvastools.hxx>
45 #include <boost/scoped_array.hpp>
46 #include <boost/bind.hpp>
47 #include <boost/utility.hpp>
49 #include "textaction.hxx"
50 #include "outdevstate.hxx"
51 #include "mtftools.hxx"
54 using namespace ::com::sun::star
;
62 void init( rendering::RenderState
& o_rRenderState
,
63 const ::basegfx::B2DPoint
& rStartPoint
,
64 const OutDevState
& rState
,
65 const CanvasSharedPtr
& rCanvas
)
67 tools::initRenderState(o_rRenderState
,rState
);
69 // #i36950# Offset clip back to origin (as it's also moved
71 // #i53964# Also take VCL font rotation into account,
72 // since this, opposed to the FontMatrix rotation
73 // elsewhere, _does_ get incorporated into the render
75 tools::modifyClip( o_rRenderState
,
80 &rState
.fontRotation
);
82 basegfx::B2DHomMatrix
aLocalTransformation(basegfx::tools::createRotateB2DHomMatrix(rState
.fontRotation
));
83 aLocalTransformation
.translate( rStartPoint
.getX(),
85 ::canvas::tools::appendToRenderState( o_rRenderState
,
86 aLocalTransformation
);
88 o_rRenderState
.DeviceColor
= rState
.textColor
;
91 void init( rendering::RenderState
& o_rRenderState
,
92 const ::basegfx::B2DPoint
& rStartPoint
,
93 const OutDevState
& rState
,
94 const CanvasSharedPtr
& rCanvas
,
95 const ::basegfx::B2DHomMatrix
& rTextTransform
)
97 init( o_rRenderState
, rStartPoint
, rState
, rCanvas
);
99 // TODO(F2): Also inversely-transform clip with
100 // rTextTransform (which is actually rather hard, as the
101 // text transform is _prepended_ to the render state)!
103 // prepend extra font transform to render state
104 // (prepend it, because it's interpreted in the unit
105 // rect coordinate space)
106 ::canvas::tools::prependToRenderState( o_rRenderState
,
110 void init( rendering::RenderState
& o_rRenderState
,
111 uno::Reference
< rendering::XCanvasFont
>& o_rFont
,
112 const ::basegfx::B2DPoint
& rStartPoint
,
113 const OutDevState
& rState
,
114 const CanvasSharedPtr
& rCanvas
)
116 // ensure that o_rFont is valid. It is possible that
117 // text actions are generated without previously
118 // setting a font. Then, just take a default font
121 // Use completely default FontRequest
122 const rendering::FontRequest aFontRequest
;
124 geometry::Matrix2D aFontMatrix
;
125 ::canvas::tools::setIdentityMatrix2D( aFontMatrix
);
127 o_rFont
= rCanvas
->getUNOCanvas()->createFont(
129 uno::Sequence
< beans::PropertyValue
>(),
133 init( o_rRenderState
,
139 void init( rendering::RenderState
& o_rRenderState
,
140 uno::Reference
< rendering::XCanvasFont
>& o_rFont
,
141 const ::basegfx::B2DPoint
& rStartPoint
,
142 const OutDevState
& rState
,
143 const CanvasSharedPtr
& rCanvas
,
144 const ::basegfx::B2DHomMatrix
& rTextTransform
)
146 init( o_rRenderState
, o_rFont
, rStartPoint
, rState
, rCanvas
);
148 // TODO(F2): Also inversely-transform clip with
149 // rTextTransform (which is actually rather hard, as the
150 // text transform is _prepended_ to the render state)!
152 // prepend extra font transform to render state
153 // (prepend it, because it's interpreted in the unit
154 // rect coordinate space)
155 ::canvas::tools::prependToRenderState( o_rRenderState
,
159 ::basegfx::B2DPolyPolygon
textLinesFromLogicalOffsets( const uno::Sequence
< double >& rOffsets
,
160 const tools::TextLineInfo
& rTextLineInfo
)
162 return tools::createTextLinesPolyPolygon(
164 // extract character cell furthest to the right
165 *(::std::max_element(
166 rOffsets
.getConstArray(),
167 rOffsets
.getConstArray() + rOffsets
.getLength() )),
171 uno::Sequence
< double > setupDXArray( const sal_Int32
* pCharWidths
,
173 const OutDevState
& rState
)
175 // convert character widths from logical units
176 uno::Sequence
< double > aCharWidthSeq( nLen
);
177 double* pOutputWidths( aCharWidthSeq
.getArray() );
179 // #143885# maintain (nearly) full precision of DX
180 // array, by circumventing integer-based
182 const double nScale( rState
.mapModeTransform
.get(0,0) );
183 for( int i
= 0; i
< nLen
; ++i
)
185 // TODO(F2): use correct scale direction
186 *pOutputWidths
++ = *pCharWidths
++ * nScale
;
189 return aCharWidthSeq
;
192 uno::Sequence
< double > setupDXArray( const OUString
& rText
,
195 VirtualDevice
& rVDev
,
196 const OutDevState
& rState
)
198 // no external DX array given, create one from given
200 ::boost::scoped_array
< sal_Int32
> pCharWidths( new sal_Int32
[nLen
] );
202 rVDev
.GetTextArray( rText
, pCharWidths
.get(),
203 static_cast<sal_uInt16
>(nStartPos
),
204 static_cast<sal_uInt16
>(nLen
) );
206 return setupDXArray( pCharWidths
.get(), nLen
, rState
);
209 ::basegfx::B2DPoint
adaptStartPoint( const ::basegfx::B2DPoint
& rStartPoint
,
210 const OutDevState
& rState
,
211 const uno::Sequence
< double >& rOffsets
)
213 ::basegfx::B2DPoint
aLocalPoint( rStartPoint
);
215 if( rState
.textAlignment
)
217 // text origin is right, not left. Modify start point
218 // accordingly, because XCanvas::drawTextLayout()
219 // always aligns left!
221 const double nOffset( rOffsets
[ rOffsets
.getLength()-1 ] );
223 // correct start point for rotated text: rotate around
224 // former start point
225 aLocalPoint
.setX( aLocalPoint
.getX() + cos( rState
.fontRotation
)*nOffset
);
226 aLocalPoint
.setY( aLocalPoint
.getY() + sin( rState
.fontRotation
)*nOffset
);
232 /** Perform common setup for array text actions
234 This method creates the XTextLayout object and
235 initializes it, e.g. with the logical advancements.
237 void initArrayAction( rendering::RenderState
& o_rRenderState
,
238 uno::Reference
< rendering::XTextLayout
>& o_rTextLayout
,
239 const ::basegfx::B2DPoint
& rStartPoint
,
240 const OUString
& rText
,
243 const uno::Sequence
< double >& rOffsets
,
244 const CanvasSharedPtr
& rCanvas
,
245 const OutDevState
& rState
,
246 const ::basegfx::B2DHomMatrix
* pTextTransform
)
248 ENSURE_OR_THROW( rOffsets
.getLength(),
249 "::cppcanvas::internal::initArrayAction(): zero-length DX array" );
251 const ::basegfx::B2DPoint
aLocalStartPoint(
252 adaptStartPoint( rStartPoint
, rState
, rOffsets
) );
254 uno::Reference
< rendering::XCanvasFont
> xFont( rState
.xFont
);
257 init( o_rRenderState
, xFont
, aLocalStartPoint
, rState
, rCanvas
, *pTextTransform
);
259 init( o_rRenderState
, xFont
, aLocalStartPoint
, rState
, rCanvas
);
261 o_rTextLayout
= xFont
->createTextLayout(
262 rendering::StringContext( rText
, nStartPos
, nLen
),
263 rState
.textDirection
,
266 ENSURE_OR_THROW( o_rTextLayout
.is(),
267 "::cppcanvas::internal::initArrayAction(): Invalid font" );
269 o_rTextLayout
->applyLogicalAdvancements( rOffsets
);
272 double getLineWidth( ::VirtualDevice
& rVDev
,
273 const OutDevState
& rState
,
274 const rendering::StringContext
& rStringContext
)
276 // TODO(F2): use correct scale direction
277 const ::basegfx::B2DSize
aSize( rVDev
.GetTextWidth( rStringContext
.Text
,
278 static_cast<sal_uInt16
>(rStringContext
.StartPosition
),
279 static_cast<sal_uInt16
>(rStringContext
.Length
) ),
282 return (rState
.mapModeTransform
* aSize
).getX();
285 uno::Sequence
< double >
286 calcSubsetOffsets( rendering::RenderState
& io_rRenderState
,
289 const uno::Reference
< rendering::XTextLayout
>& rOrigTextLayout
,
290 const ::cppcanvas::internal::Action::Subset
& rSubset
)
292 ENSURE_OR_THROW( rSubset
.mnSubsetEnd
> rSubset
.mnSubsetBegin
,
293 "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );
295 uno::Sequence
< double > aOrigOffsets( rOrigTextLayout
->queryLogicalAdvancements() );
296 const double* pOffsets( aOrigOffsets
.getConstArray() );
298 ENSURE_OR_THROW( aOrigOffsets
.getLength() >= rSubset
.mnSubsetEnd
,
299 "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );
301 // TODO(F3): It currently seems that for RTL text, the
302 // DX offsets are nevertheless increasing in logical
303 // text order (I'd expect they are decreasing,
304 // mimicking the fact that the text is output
305 // right-to-left). This breaks text effects for ALL
308 // determine leftmost position in given subset range -
309 // as the DX array contains the output positions
310 // starting with the second character (the first is
311 // assumed to have output position 0), correct begin
313 const double nMinPos( rSubset
.mnSubsetBegin
<= 0 ? 0 :
314 *(::std::min_element( pOffsets
+rSubset
.mnSubsetBegin
-1,
315 pOffsets
+rSubset
.mnSubsetEnd
)) );
317 // determine rightmost position in given subset range
318 // - as the DX array contains the output positions
319 // starting with the second character (the first is
320 // assumed to have output position 0), correct begin
322 const double nMaxPos(
323 *(::std::max_element( pOffsets
+ (rSubset
.mnSubsetBegin
<= 0 ?
324 0 : rSubset
.mnSubsetBegin
-1),
325 pOffsets
+ rSubset
.mnSubsetEnd
)) );
328 // adapt render state, to move text output to given offset
329 // -------------------------------------------------------
331 // TODO(F1): Strictly speaking, we also have to adapt
332 // the clip here, which normally should _not_ move
333 // with the output offset. Neglected for now, as it
334 // does not matter for drawing layer output
336 if( rSubset
.mnSubsetBegin
> 0 )
338 ::basegfx::B2DHomMatrix aTranslation
;
339 if( rOrigTextLayout
->getFont()->getFontRequest().FontDescription
.IsVertical
)
341 // vertical text -> offset in y direction
342 aTranslation
.translate( 0.0, nMinPos
);
346 // horizontal text -> offset in x direction
347 aTranslation
.translate( nMinPos
, 0.0 );
350 ::canvas::tools::appendToRenderState( io_rRenderState
,
355 // reduce DX array to given substring
356 // ----------------------------------
358 const sal_Int32
nNewElements( rSubset
.mnSubsetEnd
- rSubset
.mnSubsetBegin
);
359 uno::Sequence
< double > aAdaptedOffsets( nNewElements
);
360 double* pAdaptedOffsets( aAdaptedOffsets
.getArray() );
362 // move to new output position (subtract nMinPos,
363 // which is the new '0' position), copy only the range
364 // as given by rSubset.
365 ::std::transform( pOffsets
+ rSubset
.mnSubsetBegin
,
366 pOffsets
+ rSubset
.mnSubsetEnd
,
368 ::boost::bind( ::std::minus
<double>(),
375 return aAdaptedOffsets
;
378 uno::Reference
< rendering::XTextLayout
>
379 createSubsetLayout( const rendering::StringContext
& rOrigContext
,
380 const ::cppcanvas::internal::Action::Subset
& rSubset
,
381 const uno::Reference
< rendering::XTextLayout
>& rOrigTextLayout
)
383 // create temporary new text layout with subset string
384 // ---------------------------------------------------
386 const sal_Int32
nNewStartPos( rOrigContext
.StartPosition
+ ::std::min(
387 rSubset
.mnSubsetBegin
, rOrigContext
.Length
-1 ) );
388 const sal_Int32
nNewLength( ::std::max(
390 rSubset
.mnSubsetEnd
- rSubset
.mnSubsetBegin
,
391 rOrigContext
.Length
),
394 const rendering::StringContext
aContext( rOrigContext
.Text
,
398 uno::Reference
< rendering::XTextLayout
> xTextLayout(
399 rOrigTextLayout
->getFont()->createTextLayout( aContext
,
400 rOrigTextLayout
->getMainTextDirection(),
402 uno::UNO_QUERY_THROW
);
407 /** Setup subset text layout
409 @param io_rTextLayout
410 Must contain original (full set) text layout on input,
411 will contain subsetted text layout (or empty
412 reference, for empty subsets) on output.
414 @param io_rRenderState
415 Must contain original render state on input, will
416 contain shifted render state concatenated with
417 rTransformation on output.
419 @param rTransformation
420 Additional transformation, to be prepended to render
426 void createSubsetLayout( uno::Reference
< rendering::XTextLayout
>& io_rTextLayout
,
427 rendering::RenderState
& io_rRenderState
,
430 const ::basegfx::B2DHomMatrix
& rTransformation
,
431 const Action::Subset
& rSubset
)
433 ::canvas::tools::prependToRenderState(io_rRenderState
, rTransformation
);
435 if( rSubset
.mnSubsetBegin
== rSubset
.mnSubsetEnd
)
437 // empty range, empty layout
438 io_rTextLayout
.clear();
443 ENSURE_OR_THROW( io_rTextLayout
.is(),
444 "createSubsetLayout(): Invalid input layout" );
446 const rendering::StringContext
& rOrigContext( io_rTextLayout
->getText() );
448 if( rSubset
.mnSubsetBegin
== 0 &&
449 rSubset
.mnSubsetEnd
== rOrigContext
.Length
)
451 // full range, no need for subsetting
455 uno::Reference
< rendering::XTextLayout
> xTextLayout(
456 createSubsetLayout( rOrigContext
, rSubset
, io_rTextLayout
) );
458 if( xTextLayout
.is() )
460 xTextLayout
->applyLogicalAdvancements(
461 calcSubsetOffsets( io_rRenderState
,
468 io_rTextLayout
= xTextLayout
;
472 /** Interface for renderEffectText functor below.
474 This is interface is used from the renderEffectText()
475 method below, to call the client implementation.
480 virtual ~TextRenderer() {}
482 /// Render text with given RenderState
483 virtual bool operator()( const rendering::RenderState
& rRenderState
) const = 0;
486 /** Render effect text.
489 Functor object, will be called to render the actual
490 part of the text effect (the text itself and the means
491 to render it are unknown to this method)
493 bool renderEffectText( const TextRenderer
& rRenderer
,
494 const rendering::RenderState
& rRenderState
,
495 const rendering::ViewState
& /*rViewState*/,
496 const uno::Reference
< rendering::XCanvas
>& xCanvas
,
497 const ::Color
& rShadowColor
,
498 const ::basegfx::B2DSize
& rShadowOffset
,
499 const ::Color
& rReliefColor
,
500 const ::basegfx::B2DSize
& rReliefOffset
)
502 ::Color
aEmptyColor( COL_AUTO
);
503 uno::Reference
<rendering::XColorSpace
> xColorSpace(
504 xCanvas
->getDevice()->getDeviceColorSpace() );
506 // draw shadow text, if enabled
507 if( rShadowColor
!= aEmptyColor
)
509 rendering::RenderState
aShadowState( rRenderState
);
510 ::basegfx::B2DHomMatrix aTranslate
;
512 aTranslate
.translate( rShadowOffset
.getX(),
513 rShadowOffset
.getY() );
515 ::canvas::tools::appendToRenderState(aShadowState
, aTranslate
);
517 aShadowState
.DeviceColor
=
518 ::vcl::unotools::colorToDoubleSequence( rShadowColor
,
521 rRenderer( aShadowState
);
524 // draw relief text, if enabled
525 if( rReliefColor
!= aEmptyColor
)
527 rendering::RenderState
aReliefState( rRenderState
);
528 ::basegfx::B2DHomMatrix aTranslate
;
530 aTranslate
.translate( rReliefOffset
.getX(),
531 rReliefOffset
.getY() );
533 ::canvas::tools::appendToRenderState(aReliefState
, aTranslate
);
535 aReliefState
.DeviceColor
=
536 ::vcl::unotools::colorToDoubleSequence( rReliefColor
,
539 rRenderer( aReliefState
);
543 rRenderer( rRenderState
);
549 ::basegfx::B2DRange
calcEffectTextBounds( const ::basegfx::B2DRange
& rTextBounds
,
550 const ::basegfx::B2DRange
& rLineBounds
,
551 const ::basegfx::B2DSize
& rReliefOffset
,
552 const ::basegfx::B2DSize
& rShadowOffset
,
553 const rendering::RenderState
& rRenderState
,
554 const rendering::ViewState
& rViewState
)
556 ::basegfx::B2DRange
aBounds( rTextBounds
);
558 // add extends of text lines
559 aBounds
.expand( rLineBounds
);
561 // TODO(Q3): Provide this functionality at the B2DRange
562 ::basegfx::B2DRange
aTotalBounds( aBounds
);
564 ::basegfx::B2DRange( aBounds
.getMinX() + rReliefOffset
.getX(),
565 aBounds
.getMinY() + rReliefOffset
.getY(),
566 aBounds
.getMaxX() + rReliefOffset
.getX(),
567 aBounds
.getMaxY() + rReliefOffset
.getY() ) );
569 ::basegfx::B2DRange( aBounds
.getMinX() + rShadowOffset
.getX(),
570 aBounds
.getMinY() + rShadowOffset
.getY(),
571 aBounds
.getMaxX() + rShadowOffset
.getX(),
572 aBounds
.getMaxY() + rShadowOffset
.getY() ) );
574 return tools::calcDevicePixelBounds( aTotalBounds
,
579 void initEffectLinePolyPolygon( ::basegfx::B2DSize
& o_rOverallSize
,
580 uno::Reference
< rendering::XPolyPolygon2D
>& o_rTextLines
,
581 const CanvasSharedPtr
& rCanvas
,
582 const uno::Sequence
< double >& rOffsets
,
583 const tools::TextLineInfo rLineInfo
)
585 const ::basegfx::B2DPolyPolygon
aPoly(
586 textLinesFromLogicalOffsets(
590 o_rOverallSize
= ::basegfx::tools::getRange( aPoly
).getRange();
592 o_rTextLines
= ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
593 rCanvas
->getUNOCanvas()->getDevice(),
597 void initEffectLinePolyPolygon( ::basegfx::B2DSize
& o_rOverallSize
,
598 uno::Reference
< rendering::XPolyPolygon2D
>& o_rTextLines
,
599 const CanvasSharedPtr
& rCanvas
,
601 const tools::TextLineInfo rLineInfo
)
603 const ::basegfx::B2DPolyPolygon
aPoly(
604 tools::createTextLinesPolyPolygon( 0.0, nLineWidth
,
607 o_rOverallSize
= ::basegfx::tools::getRange( aPoly
).getRange();
609 o_rTextLines
= ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
610 rCanvas
->getUNOCanvas()->getDevice(),
615 // -------------------------------------------------------------------------
617 class TextAction
: public Action
, private ::boost::noncopyable
620 TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
621 const OUString
& rString
,
624 const CanvasSharedPtr
& rCanvas
,
625 const OutDevState
& rState
);
627 TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
628 const OUString
& rString
,
631 const CanvasSharedPtr
& rCanvas
,
632 const OutDevState
& rState
,
633 const ::basegfx::B2DHomMatrix
& rTextTransform
);
635 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
636 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
637 const Subset
& rSubset
) const;
639 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
640 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
641 const Subset
& rSubset
) const;
643 virtual sal_Int32
getActionCount() const;
646 // TODO(P2): This is potentially a real mass object
647 // (every character might be a separate TextAction),
648 // thus, make it as lightweight as possible. For
649 // example, share common RenderState among several
650 // TextActions, maybe using maOffsets for the
653 uno::Reference
< rendering::XCanvasFont
> mxFont
;
654 const rendering::StringContext maStringContext
;
655 const CanvasSharedPtr mpCanvas
;
656 rendering::RenderState maState
;
657 const sal_Int8 maTextDirection
;
660 TextAction::TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
661 const OUString
& rString
,
664 const CanvasSharedPtr
& rCanvas
,
665 const OutDevState
& rState
) :
666 mxFont( rState
.xFont
),
667 maStringContext( rString
, nStartPos
, nLen
),
670 maTextDirection( rState
.textDirection
)
672 init( maState
, mxFont
,
676 ENSURE_OR_THROW( mxFont
.is(),
677 "::cppcanvas::internal::TextAction(): Invalid font" );
680 TextAction::TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
681 const OUString
& rString
,
684 const CanvasSharedPtr
& rCanvas
,
685 const OutDevState
& rState
,
686 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
687 mxFont( rState
.xFont
),
688 maStringContext( rString
, nStartPos
, nLen
),
691 maTextDirection( rState
.textDirection
)
693 init( maState
, mxFont
,
695 rState
, rCanvas
, rTextTransform
);
697 ENSURE_OR_THROW( mxFont
.is(),
698 "::cppcanvas::internal::TextAction(): Invalid font" );
701 bool TextAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
703 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextAction::render()" );
704 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextAction: 0x" << std::hex
<< this );
706 rendering::RenderState
aLocalState( maState
);
707 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
709 mpCanvas
->getUNOCanvas()->drawText( maStringContext
, mxFont
,
710 mpCanvas
->getViewState(), aLocalState
, maTextDirection
);
715 bool TextAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
716 const Subset
& /*rSubset*/ ) const
718 SAL_WARN( "cppcanvas.emf", "TextAction::renderSubset(): Subset not supported by this object" );
720 // TODO(P1): Retrieve necessary font metric info for
721 // TextAction from XCanvas. Currently, the
722 // TextActionFactory does not generate this object for
723 // _subsettable_ text
724 return render( rTransformation
);
727 ::basegfx::B2DRange
TextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
729 // create XTextLayout, to have the
730 // XTextLayout::queryTextBounds() method available
731 uno::Reference
< rendering::XTextLayout
> xTextLayout(
732 mxFont
->createTextLayout(
737 rendering::RenderState
aLocalState( maState
);
738 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
740 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
741 xTextLayout
->queryTextBounds() ),
742 mpCanvas
->getViewState(),
746 ::basegfx::B2DRange
TextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
747 const Subset
& /*rSubset*/ ) const
749 SAL_WARN( "cppcanvas.emf", "TextAction::getBounds(): Subset not supported by this object" );
751 // TODO(P1): Retrieve necessary font metric info for
752 // TextAction from XCanvas. Currently, the
753 // TextActionFactory does not generate this object for
754 // _subsettable_ text
755 return getBounds( rTransformation
);
758 sal_Int32
TextAction::getActionCount() const
760 // TODO(P1): Retrieve necessary font metric info for
761 // TextAction from XCanvas. Currently, the
762 // TextActionFactory does not generate this object for
763 // _subsettable_ text
768 // -------------------------------------------------------------------------
770 class EffectTextAction
:
773 private ::boost::noncopyable
776 EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
777 const ::basegfx::B2DSize
& rReliefOffset
,
778 const ::Color
& rReliefColor
,
779 const ::basegfx::B2DSize
& rShadowOffset
,
780 const ::Color
& rShadowColor
,
781 const OUString
& rText
,
784 VirtualDevice
& rVDev
,
785 const CanvasSharedPtr
& rCanvas
,
786 const OutDevState
& rState
);
788 EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
789 const ::basegfx::B2DSize
& rReliefOffset
,
790 const ::Color
& rReliefColor
,
791 const ::basegfx::B2DSize
& rShadowOffset
,
792 const ::Color
& rShadowColor
,
793 const OUString
& rText
,
796 VirtualDevice
& rVDev
,
797 const CanvasSharedPtr
& rCanvas
,
798 const OutDevState
& rState
,
799 const ::basegfx::B2DHomMatrix
& rTextTransform
);
801 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
802 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
803 const Subset
& rSubset
) const;
805 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
806 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
807 const Subset
& rSubset
) const;
809 virtual sal_Int32
getActionCount() const;
812 /// Interface TextRenderer
813 virtual bool operator()( const rendering::RenderState
& rRenderState
) const;
815 // TODO(P2): This is potentially a real mass object
816 // (every character might be a separate TextAction),
817 // thus, make it as lightweight as possible. For
818 // example, share common RenderState among several
819 // TextActions, maybe using maOffsets for the
822 uno::Reference
< rendering::XCanvasFont
> mxFont
;
823 const rendering::StringContext maStringContext
;
824 const CanvasSharedPtr mpCanvas
;
825 rendering::RenderState maState
;
826 const tools::TextLineInfo maTextLineInfo
;
827 ::basegfx::B2DSize maLinesOverallSize
;
828 const double mnLineWidth
;
829 uno::Reference
< rendering::XPolyPolygon2D
> mxTextLines
;
830 const ::basegfx::B2DSize maReliefOffset
;
831 const ::Color maReliefColor
;
832 const ::basegfx::B2DSize maShadowOffset
;
833 const ::Color maShadowColor
;
834 const sal_Int8 maTextDirection
;
837 EffectTextAction::EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
838 const ::basegfx::B2DSize
& rReliefOffset
,
839 const ::Color
& rReliefColor
,
840 const ::basegfx::B2DSize
& rShadowOffset
,
841 const ::Color
& rShadowColor
,
842 const OUString
& rText
,
845 VirtualDevice
& rVDev
,
846 const CanvasSharedPtr
& rCanvas
,
847 const OutDevState
& rState
) :
848 mxFont( rState
.xFont
),
849 maStringContext( rText
, nStartPos
, nLen
),
852 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
853 maLinesOverallSize(),
854 mnLineWidth( getLineWidth( rVDev
, rState
, maStringContext
) ),
856 maReliefOffset( rReliefOffset
),
857 maReliefColor( rReliefColor
),
858 maShadowOffset( rShadowOffset
),
859 maShadowColor( rShadowColor
),
860 maTextDirection( rState
.textDirection
)
862 initEffectLinePolyPolygon( maLinesOverallSize
,
868 init( maState
, mxFont
,
872 ENSURE_OR_THROW( mxFont
.is() && mxTextLines
.is(),
873 "::cppcanvas::internal::EffectTextAction(): Invalid font or lines" );
876 EffectTextAction::EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
877 const ::basegfx::B2DSize
& rReliefOffset
,
878 const ::Color
& rReliefColor
,
879 const ::basegfx::B2DSize
& rShadowOffset
,
880 const ::Color
& rShadowColor
,
881 const OUString
& rText
,
884 VirtualDevice
& rVDev
,
885 const CanvasSharedPtr
& rCanvas
,
886 const OutDevState
& rState
,
887 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
888 mxFont( rState
.xFont
),
889 maStringContext( rText
, nStartPos
, nLen
),
892 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
893 maLinesOverallSize(),
894 mnLineWidth( getLineWidth( rVDev
, rState
, maStringContext
) ),
896 maReliefOffset( rReliefOffset
),
897 maReliefColor( rReliefColor
),
898 maShadowOffset( rShadowOffset
),
899 maShadowColor( rShadowColor
),
900 maTextDirection( rState
.textDirection
)
902 initEffectLinePolyPolygon( maLinesOverallSize
,
908 init( maState
, mxFont
,
910 rState
, rCanvas
, rTextTransform
);
912 ENSURE_OR_THROW( mxFont
.is() && mxTextLines
.is(),
913 "::cppcanvas::internal::EffectTextAction(): Invalid font or lines" );
916 bool EffectTextAction::operator()( const rendering::RenderState
& rRenderState
) const
918 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
919 const uno::Reference
< rendering::XCanvas
>& rCanvas( mpCanvas
->getUNOCanvas() );
921 rCanvas
->fillPolyPolygon( mxTextLines
,
925 rCanvas
->drawText( maStringContext
, mxFont
,
933 bool EffectTextAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
935 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextAction::render()" );
936 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextAction: 0x" << std::hex
<< this );
938 rendering::RenderState
aLocalState( maState
);
939 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
941 return renderEffectText( *this,
943 mpCanvas
->getViewState(),
944 mpCanvas
->getUNOCanvas(),
951 bool EffectTextAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
952 const Subset
& /*rSubset*/ ) const
954 SAL_WARN( "cppcanvas.emf", "EffectTextAction::renderSubset(): Subset not supported by this object" );
956 // TODO(P1): Retrieve necessary font metric info for
957 // TextAction from XCanvas. Currently, the
958 // TextActionFactory does not generate this object for
960 return render( rTransformation
);
963 ::basegfx::B2DRange
EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
965 // create XTextLayout, to have the
966 // XTextLayout::queryTextBounds() method available
967 uno::Reference
< rendering::XTextLayout
> xTextLayout(
968 mxFont
->createTextLayout(
973 rendering::RenderState
aLocalState( maState
);
974 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
976 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
977 xTextLayout
->queryTextBounds() ),
978 ::basegfx::B2DRange( 0,0,
979 maLinesOverallSize
.getX(),
980 maLinesOverallSize
.getY() ),
984 mpCanvas
->getViewState() );
987 ::basegfx::B2DRange
EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
988 const Subset
& /*rSubset*/ ) const
990 SAL_WARN( "cppcanvas.emf", "EffectTextAction::getBounds(): Subset not supported by this object" );
992 // TODO(P1): Retrieve necessary font metric info for
993 // TextAction from XCanvas. Currently, the
994 // TextActionFactory does not generate this object for
995 // _subsettable_ text
996 return getBounds( rTransformation
);
999 sal_Int32
EffectTextAction::getActionCount() const
1001 // TODO(P1): Retrieve necessary font metric info for
1002 // TextAction from XCanvas. Currently, the
1003 // TextActionFactory does not generate this object for
1009 // -------------------------------------------------------------------------
1011 class TextArrayAction
: public Action
, private ::boost::noncopyable
1014 TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1015 const OUString
& rString
,
1016 sal_Int32 nStartPos
,
1018 const uno::Sequence
< double >& rOffsets
,
1019 const CanvasSharedPtr
& rCanvas
,
1020 const OutDevState
& rState
);
1022 TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1023 const OUString
& rString
,
1024 sal_Int32 nStartPos
,
1026 const uno::Sequence
< double >& rOffsets
,
1027 const CanvasSharedPtr
& rCanvas
,
1028 const OutDevState
& rState
,
1029 const ::basegfx::B2DHomMatrix
& rTextTransform
);
1031 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1032 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1033 const Subset
& rSubset
) const;
1035 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1036 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1037 const Subset
& rSubset
) const;
1039 virtual sal_Int32
getActionCount() const;
1042 // TODO(P2): This is potentially a real mass object
1043 // (every character might be a separate TextAction),
1044 // thus, make it as lightweight as possible. For
1045 // example, share common RenderState among several
1046 // TextActions, maybe using maOffsets for the
1049 uno::Reference
< rendering::XTextLayout
> mxTextLayout
;
1050 const CanvasSharedPtr mpCanvas
;
1051 rendering::RenderState maState
;
1054 TextArrayAction::TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1055 const OUString
& rString
,
1056 sal_Int32 nStartPos
,
1058 const uno::Sequence
< double >& rOffsets
,
1059 const CanvasSharedPtr
& rCanvas
,
1060 const OutDevState
& rState
) :
1062 mpCanvas( rCanvas
),
1065 initArrayAction( maState
,
1076 TextArrayAction::TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1077 const OUString
& rString
,
1078 sal_Int32 nStartPos
,
1080 const uno::Sequence
< double >& rOffsets
,
1081 const CanvasSharedPtr
& rCanvas
,
1082 const OutDevState
& rState
,
1083 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
1085 mpCanvas( rCanvas
),
1088 initArrayAction( maState
,
1100 bool TextArrayAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1102 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextArrayAction::render()" );
1103 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextArrayAction: 0x" << std::hex
<< this );
1105 rendering::RenderState
aLocalState( maState
);
1106 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1108 mpCanvas
->getUNOCanvas()->drawTextLayout( mxTextLayout
,
1109 mpCanvas
->getViewState(),
1115 bool TextArrayAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1116 const Subset
& rSubset
) const
1118 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextArrayAction::renderSubset()" );
1119 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextArrayAction: 0x" << std::hex
<< this );
1121 rendering::RenderState
aLocalState( maState
);
1122 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1124 double nDummy0
, nDummy1
;
1125 createSubsetLayout( xTextLayout
,
1132 if( !xTextLayout
.is() )
1133 return true; // empty layout, render nothing
1135 mpCanvas
->getUNOCanvas()->drawTextLayout( xTextLayout
,
1136 mpCanvas
->getViewState(),
1142 ::basegfx::B2DRange
TextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1144 rendering::RenderState
aLocalState( maState
);
1145 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1147 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1148 mxTextLayout
->queryTextBounds() ),
1149 mpCanvas
->getViewState(),
1153 ::basegfx::B2DRange
TextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1154 const Subset
& rSubset
) const
1156 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextArrayAction::getBounds( subset )" );
1157 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextArrayAction: 0x" << std::hex
<< this );
1159 rendering::RenderState
aLocalState( maState
);
1160 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1162 double nDummy0
, nDummy1
;
1163 createSubsetLayout( xTextLayout
,
1170 if( !xTextLayout
.is() )
1171 return ::basegfx::B2DRange(); // empty layout, empty bounds
1173 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1174 xTextLayout
->queryTextBounds() ),
1175 mpCanvas
->getViewState(),
1179 sal_Int32
TextArrayAction::getActionCount() const
1181 const rendering::StringContext
& rOrigContext( mxTextLayout
->getText() );
1183 return rOrigContext
.Length
;
1187 // -------------------------------------------------------------------------
1189 class EffectTextArrayAction
:
1191 public TextRenderer
,
1192 private ::boost::noncopyable
1195 EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1196 const ::basegfx::B2DSize
& rReliefOffset
,
1197 const ::Color
& rReliefColor
,
1198 const ::basegfx::B2DSize
& rShadowOffset
,
1199 const ::Color
& rShadowColor
,
1200 const OUString
& rText
,
1201 sal_Int32 nStartPos
,
1203 const uno::Sequence
< double >& rOffsets
,
1204 VirtualDevice
& rVDev
,
1205 const CanvasSharedPtr
& rCanvas
,
1206 const OutDevState
& rState
);
1207 EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1208 const ::basegfx::B2DSize
& rReliefOffset
,
1209 const ::Color
& rReliefColor
,
1210 const ::basegfx::B2DSize
& rShadowOffset
,
1211 const ::Color
& rShadowColor
,
1212 const OUString
& rText
,
1213 sal_Int32 nStartPos
,
1215 const uno::Sequence
< double >& rOffsets
,
1216 VirtualDevice
& rVDev
,
1217 const CanvasSharedPtr
& rCanvas
,
1218 const OutDevState
& rState
,
1219 const ::basegfx::B2DHomMatrix
& rTextTransform
);
1221 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1222 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1223 const Subset
& rSubset
) const;
1225 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1226 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1227 const Subset
& rSubset
) const;
1229 virtual sal_Int32
getActionCount() const;
1232 // TextRenderer interface
1233 virtual bool operator()( const rendering::RenderState
& rRenderState
) const;
1235 // TODO(P2): This is potentially a real mass object
1236 // (every character might be a separate TextAction),
1237 // thus, make it as lightweight as possible. For
1238 // example, share common RenderState among several
1239 // TextActions, maybe using maOffsets for the
1242 uno::Reference
< rendering::XTextLayout
> mxTextLayout
;
1243 const CanvasSharedPtr mpCanvas
;
1244 rendering::RenderState maState
;
1245 const tools::TextLineInfo maTextLineInfo
;
1246 ::basegfx::B2DSize maLinesOverallSize
;
1247 uno::Reference
< rendering::XPolyPolygon2D
> mxTextLines
;
1248 const ::basegfx::B2DSize maReliefOffset
;
1249 const ::Color maReliefColor
;
1250 const ::basegfx::B2DSize maShadowOffset
;
1251 const ::Color maShadowColor
;
1254 EffectTextArrayAction::EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1255 const ::basegfx::B2DSize
& rReliefOffset
,
1256 const ::Color
& rReliefColor
,
1257 const ::basegfx::B2DSize
& rShadowOffset
,
1258 const ::Color
& rShadowColor
,
1259 const OUString
& rText
,
1260 sal_Int32 nStartPos
,
1262 const uno::Sequence
< double >& rOffsets
,
1263 VirtualDevice
& rVDev
,
1264 const CanvasSharedPtr
& rCanvas
,
1265 const OutDevState
& rState
) :
1267 mpCanvas( rCanvas
),
1269 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1270 maLinesOverallSize(),
1272 maReliefOffset( rReliefOffset
),
1273 maReliefColor( rReliefColor
),
1274 maShadowOffset( rShadowOffset
),
1275 maShadowColor( rShadowColor
)
1277 initEffectLinePolyPolygon( maLinesOverallSize
,
1283 initArrayAction( maState
,
1294 EffectTextArrayAction::EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1295 const ::basegfx::B2DSize
& rReliefOffset
,
1296 const ::Color
& rReliefColor
,
1297 const ::basegfx::B2DSize
& rShadowOffset
,
1298 const ::Color
& rShadowColor
,
1299 const OUString
& rText
,
1300 sal_Int32 nStartPos
,
1302 const uno::Sequence
< double >& rOffsets
,
1303 VirtualDevice
& rVDev
,
1304 const CanvasSharedPtr
& rCanvas
,
1305 const OutDevState
& rState
,
1306 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
1308 mpCanvas( rCanvas
),
1310 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1311 maLinesOverallSize(),
1313 maReliefOffset( rReliefOffset
),
1314 maReliefColor( rReliefColor
),
1315 maShadowOffset( rShadowOffset
),
1316 maShadowColor( rShadowColor
)
1318 initEffectLinePolyPolygon( maLinesOverallSize
,
1324 initArrayAction( maState
,
1336 bool EffectTextArrayAction::operator()( const rendering::RenderState
& rRenderState
) const
1338 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
1339 const uno::Reference
< rendering::XCanvas
>& rCanvas( mpCanvas
->getUNOCanvas() );
1341 rCanvas
->fillPolyPolygon( mxTextLines
,
1345 rCanvas
->drawTextLayout( mxTextLayout
,
1352 bool EffectTextArrayAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1354 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction::render()" );
1355 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction: 0x" << std::hex
<< this );
1357 rendering::RenderState
aLocalState( maState
);
1358 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1360 return renderEffectText( *this,
1362 mpCanvas
->getViewState(),
1363 mpCanvas
->getUNOCanvas(),
1370 class EffectTextArrayRenderHelper
: public TextRenderer
1373 EffectTextArrayRenderHelper( const uno::Reference
< rendering::XCanvas
>& rCanvas
,
1374 const uno::Reference
< rendering::XTextLayout
>& rTextLayout
,
1375 const uno::Reference
< rendering::XPolyPolygon2D
>& rLinePolygon
,
1376 const rendering::ViewState
& rViewState
) :
1377 mrCanvas( rCanvas
),
1378 mrTextLayout( rTextLayout
),
1379 mrLinePolygon( rLinePolygon
),
1380 mrViewState( rViewState
)
1384 // TextRenderer interface
1385 virtual bool operator()( const rendering::RenderState
& rRenderState
) const
1387 mrCanvas
->fillPolyPolygon( mrLinePolygon
,
1391 mrCanvas
->drawTextLayout( mrTextLayout
,
1399 const uno::Reference
< rendering::XCanvas
>& mrCanvas
;
1400 const uno::Reference
< rendering::XTextLayout
>& mrTextLayout
;
1401 const uno::Reference
< rendering::XPolyPolygon2D
>& mrLinePolygon
;
1402 const rendering::ViewState
& mrViewState
;
1405 bool EffectTextArrayAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1406 const Subset
& rSubset
) const
1408 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction::renderSubset()" );
1409 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction: 0x" << std::hex
<< this );
1411 rendering::RenderState
aLocalState( maState
);
1412 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1413 const geometry::RealRectangle2D
aTextBounds( mxTextLayout
->queryTextBounds() );
1415 double nMinPos(0.0);
1416 double nMaxPos(aTextBounds
.X2
- aTextBounds
.X1
);
1418 createSubsetLayout( xTextLayout
,
1425 if( !xTextLayout
.is() )
1426 return true; // empty layout, render nothing
1429 // create and setup local line polygon
1430 // ===================================
1432 uno::Reference
< rendering::XCanvas
> xCanvas( mpCanvas
->getUNOCanvas() );
1433 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
1435 uno::Reference
< rendering::XPolyPolygon2D
> xTextLines(
1436 ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
1437 xCanvas
->getDevice(),
1438 tools::createTextLinesPolyPolygon(
1439 0.0, nMaxPos
- nMinPos
,
1440 maTextLineInfo
) ) );
1443 // render everything
1444 // =================
1446 return renderEffectText(
1447 EffectTextArrayRenderHelper( xCanvas
,
1460 ::basegfx::B2DRange
EffectTextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1462 rendering::RenderState
aLocalState( maState
);
1463 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1465 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1466 mxTextLayout
->queryTextBounds() ),
1467 ::basegfx::B2DRange( 0,0,
1468 maLinesOverallSize
.getX(),
1469 maLinesOverallSize
.getY() ),
1473 mpCanvas
->getViewState() );
1476 ::basegfx::B2DRange
EffectTextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1477 const Subset
& rSubset
) const
1479 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction::getBounds( subset )" );
1480 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction: 0x" << std::hex
<< this );
1482 rendering::RenderState
aLocalState( maState
);
1483 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1484 const geometry::RealRectangle2D
aTextBounds( mxTextLayout
->queryTextBounds() );
1486 double nMinPos(0.0);
1487 double nMaxPos(aTextBounds
.X2
- aTextBounds
.X1
);
1489 createSubsetLayout( xTextLayout
,
1496 if( !xTextLayout
.is() )
1497 return ::basegfx::B2DRange(); // empty layout, empty bounds
1500 // create and setup local line polygon
1501 // ===================================
1503 const ::basegfx::B2DPolyPolygon
aPoly(
1504 tools::createTextLinesPolyPolygon(
1505 0.0, nMaxPos
- nMinPos
,
1508 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1509 xTextLayout
->queryTextBounds() ),
1510 ::basegfx::tools::getRange( aPoly
),
1514 mpCanvas
->getViewState() );
1517 sal_Int32
EffectTextArrayAction::getActionCount() const
1519 const rendering::StringContext
& rOrigContext( mxTextLayout
->getText() );
1521 return rOrigContext
.Length
;
1525 // -------------------------------------------------------------------------
1527 class OutlineAction
:
1529 public TextRenderer
,
1530 private ::boost::noncopyable
1533 OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1534 const ::basegfx::B2DSize
& rReliefOffset
,
1535 const ::Color
& rReliefColor
,
1536 const ::basegfx::B2DSize
& rShadowOffset
,
1537 const ::Color
& rShadowColor
,
1538 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1539 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1540 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1541 const uno::Sequence
< double >& rOffsets
,
1542 VirtualDevice
& rVDev
,
1543 const CanvasSharedPtr
& rCanvas
,
1544 const OutDevState
& rState
);
1545 OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1546 const ::basegfx::B2DSize
& rReliefOffset
,
1547 const ::Color
& rReliefColor
,
1548 const ::basegfx::B2DSize
& rShadowOffset
,
1549 const ::Color
& rShadowColor
,
1550 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1551 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1552 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1553 const uno::Sequence
< double >& rOffsets
,
1554 VirtualDevice
& rVDev
,
1555 const CanvasSharedPtr
& rCanvas
,
1556 const OutDevState
& rState
,
1557 const ::basegfx::B2DHomMatrix
& rTextTransform
);
1559 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1560 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1561 const Subset
& rSubset
) const;
1563 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
1564 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1565 const Subset
& rSubset
) const;
1567 virtual sal_Int32
getActionCount() const;
1570 // TextRenderer interface
1571 virtual bool operator()( const rendering::RenderState
& rRenderState
) const;
1573 // TODO(P2): This is potentially a real mass object
1574 // (every character might be a separate TextAction),
1575 // thus, make it as lightweight as possible. For
1576 // example, share common RenderState among several
1577 // TextActions, maybe using maOffsets for the
1580 uno::Reference
< rendering::XPolyPolygon2D
> mxTextPoly
;
1582 /** This vector denotes the index of the start polygon
1583 for the respective glyph sequence.
1585 To get a polygon index range for a given character
1586 index i, take [ maPolygonGlyphMap[i],
1587 maPolygonGlyphMap[i+1] ). Note that this is wrong
1590 const ::std::vector
< sal_Int32
> maPolygonGlyphMap
;
1591 const uno::Sequence
< double > maOffsets
;
1592 const CanvasSharedPtr mpCanvas
;
1593 rendering::RenderState maState
;
1594 double mnOutlineWidth
;
1595 const uno::Sequence
< double > maFillColor
;
1596 const tools::TextLineInfo maTextLineInfo
;
1597 ::basegfx::B2DSize maLinesOverallSize
;
1598 const ::basegfx::B2DRectangle maOutlineBounds
;
1599 uno::Reference
< rendering::XPolyPolygon2D
> mxTextLines
;
1600 const ::basegfx::B2DSize maReliefOffset
;
1601 const ::Color maReliefColor
;
1602 const ::basegfx::B2DSize maShadowOffset
;
1603 const ::Color maShadowColor
;
1606 double calcOutlineWidth( const OutDevState
& rState
,
1607 VirtualDevice
& rVDev
)
1609 const ::basegfx::B2DSize
aFontSize( 0,
1610 rVDev
.GetFont().GetHeight() / 64.0 );
1612 const double nOutlineWidth(
1613 (rState
.mapModeTransform
* aFontSize
).getY() );
1615 return nOutlineWidth
< 1.0 ? 1.0 : nOutlineWidth
;
1618 OutlineAction::OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1619 const ::basegfx::B2DSize
& rReliefOffset
,
1620 const ::Color
& rReliefColor
,
1621 const ::basegfx::B2DSize
& rShadowOffset
,
1622 const ::Color
& rShadowColor
,
1623 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1624 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1625 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1626 const uno::Sequence
< double >& rOffsets
,
1627 VirtualDevice
& rVDev
,
1628 const CanvasSharedPtr
& rCanvas
,
1629 const OutDevState
& rState
) :
1630 mxTextPoly( rTextPoly
),
1631 maPolygonGlyphMap( rPolygonGlyphMap
),
1632 maOffsets( rOffsets
),
1633 mpCanvas( rCanvas
),
1635 mnOutlineWidth( calcOutlineWidth(rState
,rVDev
) ),
1637 ::vcl::unotools::colorToDoubleSequence(
1638 ::Color( COL_WHITE
),
1639 rCanvas
->getUNOCanvas()->getDevice()->getDeviceColorSpace() )),
1640 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1641 maLinesOverallSize(),
1642 maOutlineBounds( rOutlineBounds
),
1644 maReliefOffset( rReliefOffset
),
1645 maReliefColor( rReliefColor
),
1646 maShadowOffset( rShadowOffset
),
1647 maShadowColor( rShadowColor
)
1649 initEffectLinePolyPolygon( maLinesOverallSize
,
1661 OutlineAction::OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1662 const ::basegfx::B2DSize
& rReliefOffset
,
1663 const ::Color
& rReliefColor
,
1664 const ::basegfx::B2DSize
& rShadowOffset
,
1665 const ::Color
& rShadowColor
,
1666 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1667 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1668 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1669 const uno::Sequence
< double >& rOffsets
,
1670 VirtualDevice
& rVDev
,
1671 const CanvasSharedPtr
& rCanvas
,
1672 const OutDevState
& rState
,
1673 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
1674 mxTextPoly( rTextPoly
),
1675 maPolygonGlyphMap( rPolygonGlyphMap
),
1676 maOffsets( rOffsets
),
1677 mpCanvas( rCanvas
),
1679 mnOutlineWidth( calcOutlineWidth(rState
,rVDev
) ),
1681 ::vcl::unotools::colorToDoubleSequence(
1682 ::Color( COL_WHITE
),
1683 rCanvas
->getUNOCanvas()->getDevice()->getDeviceColorSpace() )),
1684 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1685 maLinesOverallSize(),
1686 maOutlineBounds( rOutlineBounds
),
1688 maReliefOffset( rReliefOffset
),
1689 maReliefColor( rReliefColor
),
1690 maShadowOffset( rShadowOffset
),
1691 maShadowColor( rShadowColor
)
1693 initEffectLinePolyPolygon( maLinesOverallSize
,
1706 bool OutlineAction::operator()( const rendering::RenderState
& rRenderState
) const
1708 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
1709 const uno::Reference
< rendering::XCanvas
>& rCanvas( mpCanvas
->getUNOCanvas() );
1711 rendering::StrokeAttributes aStrokeAttributes
;
1713 aStrokeAttributes
.StrokeWidth
= mnOutlineWidth
;
1714 aStrokeAttributes
.MiterLimit
= 1.0;
1715 aStrokeAttributes
.StartCapType
= rendering::PathCapType::BUTT
;
1716 aStrokeAttributes
.EndCapType
= rendering::PathCapType::BUTT
;
1717 aStrokeAttributes
.JoinType
= rendering::PathJoinType::MITER
;
1719 rendering::RenderState
aLocalState( rRenderState
);
1720 aLocalState
.DeviceColor
= maFillColor
;
1722 // TODO(P1): implement caching
1724 // background of text
1725 rCanvas
->fillPolyPolygon( mxTextPoly
,
1729 // border line of text
1730 rCanvas
->strokePolyPolygon( mxTextPoly
,
1733 aStrokeAttributes
);
1735 // underlines/strikethrough - background
1736 rCanvas
->fillPolyPolygon( mxTextLines
,
1739 // underlines/strikethrough - border
1740 rCanvas
->strokePolyPolygon( mxTextLines
,
1743 aStrokeAttributes
);
1748 bool OutlineAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1750 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction::render()" );
1751 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction: 0x" << std::hex
<< this );
1753 rendering::RenderState
aLocalState( maState
);
1754 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1756 return renderEffectText( *this,
1758 mpCanvas
->getViewState(),
1759 mpCanvas
->getUNOCanvas(),
1766 #if 0 // see #if'ed out use in OutlineAction::renderSubset below:
1767 class OutlineTextArrayRenderHelper
: public TextRenderer
1770 OutlineTextArrayRenderHelper( const uno::Reference
< rendering::XCanvas
>& rCanvas
,
1771 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPolygon
,
1772 const uno::Reference
< rendering::XPolyPolygon2D
>& rLinePolygon
,
1773 const rendering::ViewState
& rViewState
,
1774 double nOutlineWidth
) :
1776 ::vcl::unotools::colorToDoubleSequence(
1777 ::Color( COL_WHITE
),
1778 rCanvas
->getDevice()->getDeviceColorSpace() )),
1779 mnOutlineWidth( nOutlineWidth
),
1780 mrCanvas( rCanvas
),
1781 mrTextPolygon( rTextPolygon
),
1782 mrLinePolygon( rLinePolygon
),
1783 mrViewState( rViewState
)
1787 // TextRenderer interface
1788 virtual bool operator()( const rendering::RenderState
& rRenderState
) const
1790 rendering::StrokeAttributes aStrokeAttributes
;
1792 aStrokeAttributes
.StrokeWidth
= mnOutlineWidth
;
1793 aStrokeAttributes
.MiterLimit
= 1.0;
1794 aStrokeAttributes
.StartCapType
= rendering::PathCapType::BUTT
;
1795 aStrokeAttributes
.EndCapType
= rendering::PathCapType::BUTT
;
1796 aStrokeAttributes
.JoinType
= rendering::PathJoinType::MITER
;
1798 rendering::RenderState
aLocalState( rRenderState
);
1799 aLocalState
.DeviceColor
= maFillColor
;
1801 // TODO(P1): implement caching
1803 // background of text
1804 mrCanvas
->fillPolyPolygon( mrTextPolygon
,
1808 // border line of text
1809 mrCanvas
->strokePolyPolygon( mrTextPolygon
,
1812 aStrokeAttributes
);
1814 // underlines/strikethrough - background
1815 mrCanvas
->fillPolyPolygon( mrLinePolygon
,
1818 // underlines/strikethrough - border
1819 mrCanvas
->strokePolyPolygon( mrLinePolygon
,
1822 aStrokeAttributes
);
1828 const uno::Sequence
< double > maFillColor
;
1829 double mnOutlineWidth
;
1830 const uno::Reference
< rendering::XCanvas
>& mrCanvas
;
1831 const uno::Reference
< rendering::XPolyPolygon2D
>& mrTextPolygon
;
1832 const uno::Reference
< rendering::XPolyPolygon2D
>& mrLinePolygon
;
1833 const rendering::ViewState
& mrViewState
;
1837 bool OutlineAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1838 const Subset
& rSubset
) const
1840 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::OutlineAction::renderSubset()" );
1841 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::OutlineAction: 0x" << std::hex
<< this );
1843 if( rSubset
.mnSubsetBegin
== rSubset
.mnSubsetEnd
)
1844 return true; // empty range, render nothing
1847 // TODO(F3): Subsetting NYI for outline text!
1848 return render( rTransformation
);
1850 const rendering::StringContext
rOrigContext( mxTextLayout
->getText() );
1852 if( rSubset
.mnSubsetBegin
== 0 &&
1853 rSubset
.mnSubsetEnd
== rOrigContext
.Length
)
1855 // full range, no need for subsetting
1856 return render( rTransformation
);
1859 rendering::RenderState
aLocalState( maState
);
1860 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1863 // create and setup local Text polygon
1864 // ===================================
1866 uno::Reference
< rendering::XPolyPolygon2D
> xTextPolygon();
1868 // TODO(P3): Provide an API method for that!
1870 if( !xTextLayout
.is() )
1873 // render everything
1874 // =================
1876 return renderEffectText(
1877 OutlineTextArrayRenderHelper(
1893 ::basegfx::B2DRange
OutlineAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1895 rendering::RenderState
aLocalState( maState
);
1896 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1898 return calcEffectTextBounds( maOutlineBounds
,
1899 ::basegfx::B2DRange( 0,0,
1900 maLinesOverallSize
.getX(),
1901 maLinesOverallSize
.getY() ),
1905 mpCanvas
->getViewState() );
1908 ::basegfx::B2DRange
OutlineAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1909 const Subset
& /*rSubset*/ ) const
1911 SAL_WARN( "cppcanvas.emf", "OutlineAction::getBounds(): Subset not yet supported by this object" );
1913 return getBounds( rTransformation
);
1916 sal_Int32
OutlineAction::getActionCount() const
1918 // TODO(F3): Subsetting NYI for outline text!
1919 return maOffsets
.getLength();
1923 // ======================================================================
1925 // Action factory methods
1927 // ======================================================================
1929 /** Create an outline action
1931 This method extracts the polygonal outline from the
1932 text, and creates a properly setup OutlineAction from
1935 ActionSharedPtr
createOutline( const ::basegfx::B2DPoint
& rStartPoint
,
1936 const ::basegfx::B2DSize
& rReliefOffset
,
1937 const ::Color
& rReliefColor
,
1938 const ::basegfx::B2DSize
& rShadowOffset
,
1939 const ::Color
& rShadowColor
,
1940 const OUString
& rText
,
1941 sal_Int32 nStartPos
,
1943 const sal_Int32
* pDXArray
,
1944 VirtualDevice
& rVDev
,
1945 const CanvasSharedPtr
& rCanvas
,
1946 const OutDevState
& rState
,
1947 const Renderer::Parameters
& rParms
)
1949 // operate on raw DX array here (in logical coordinate
1950 // system), to have a higher resolution
1951 // PolyPolygon. That polygon is then converted to
1952 // device coordinate system.
1954 // #i68512# Temporarily switch off font rotation
1955 // (which is already contained in the render state
1956 // transformation matrix - otherwise, glyph polygons
1957 // will be rotated twice)
1958 const ::Font
aOrigFont( rVDev
.GetFont() );
1959 ::Font
aUnrotatedFont( aOrigFont
);
1960 aUnrotatedFont
.SetOrientation(0);
1961 rVDev
.SetFont( aUnrotatedFont
);
1963 // TODO(F3): Don't understand parameter semantics of
1964 // GetTextOutlines()
1965 ::basegfx::B2DPolyPolygon aResultingPolyPolygon
;
1966 PolyPolyVector aVCLPolyPolyVector
;
1967 const bool bHaveOutlines( rVDev
.GetTextOutlines( aVCLPolyPolyVector
, rText
,
1968 static_cast<sal_uInt16
>(nStartPos
),
1969 static_cast<sal_uInt16
>(nStartPos
),
1970 static_cast<sal_uInt16
>(nLen
),
1971 sal_True
, 0, pDXArray
) );
1972 rVDev
.SetFont(aOrigFont
);
1974 if( !bHaveOutlines
)
1975 return ActionSharedPtr();
1977 ::std::vector
< sal_Int32
> aPolygonGlyphMap
;
1979 // first glyph starts at polygon index 0
1980 aPolygonGlyphMap
.push_back( 0 );
1982 // remove offsetting from mapmode transformation
1983 // (outline polygons must stay at origin, only need to
1985 ::basegfx::B2DHomMatrix
aMapModeTransform(
1986 rState
.mapModeTransform
);
1987 aMapModeTransform
.set(0,2, 0.0);
1988 aMapModeTransform
.set(1,2, 0.0);
1990 PolyPolyVector::const_iterator
aIter( aVCLPolyPolyVector
.begin() );
1991 const PolyPolyVector::const_iterator
aEnd( aVCLPolyPolyVector
.end() );
1992 for( ; aIter
!= aEnd
; ++aIter
)
1994 ::basegfx::B2DPolyPolygon aPolyPolygon
;
1996 aPolyPolygon
= aIter
->getB2DPolyPolygon();
1997 aPolyPolygon
.transform( aMapModeTransform
);
1999 // append result to collecting polypoly
2000 for( sal_uInt32 i
=0; i
<aPolyPolygon
.count(); ++i
)
2002 // #i47795# Ensure closed polygons (since
2003 // FreeType returns the glyph outlines
2005 const ::basegfx::B2DPolygon
& rPoly( aPolyPolygon
.getB2DPolygon( i
) );
2006 const sal_uInt32
nCount( rPoly
.count() );
2010 // polygon either degenerate, or
2012 aResultingPolyPolygon
.append( rPoly
);
2016 ::basegfx::B2DPolygon
aPoly(rPoly
);
2017 aPoly
.setClosed(true);
2019 aResultingPolyPolygon
.append( aPoly
);
2023 // TODO(F3): Depending on the semantics of
2024 // GetTextOutlines(), this here is wrong!
2026 // calc next glyph index
2027 aPolygonGlyphMap
.push_back( aResultingPolyPolygon
.count() );
2030 const uno::Sequence
< double > aCharWidthSeq(
2032 setupDXArray( pDXArray
, nLen
, rState
) :
2033 setupDXArray( rText
,
2038 const uno::Reference
< rendering::XPolyPolygon2D
> xTextPoly(
2039 ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
2040 rCanvas
->getUNOCanvas()->getDevice(),
2041 aResultingPolyPolygon
) );
2043 if( rParms
.maTextTransformation
.is_initialized() )
2045 return ActionSharedPtr(
2052 ::basegfx::tools::getRange(aResultingPolyPolygon
),
2059 *rParms
.maTextTransformation
) );
2063 return ActionSharedPtr(
2070 ::basegfx::tools::getRange(aResultingPolyPolygon
),
2083 // ---------------------------------------------------------------------------------
2085 ActionSharedPtr
TextActionFactory::createTextAction( const ::Point
& rStartPoint
,
2086 const ::Size
& rReliefOffset
,
2087 const ::Color
& rReliefColor
,
2088 const ::Size
& rShadowOffset
,
2089 const ::Color
& rShadowColor
,
2090 const OUString
& rText
,
2091 sal_Int32 nStartPos
,
2093 const sal_Int32
* pDXArray
,
2094 VirtualDevice
& rVDev
,
2095 const CanvasSharedPtr
& rCanvas
,
2096 const OutDevState
& rState
,
2097 const Renderer::Parameters
& rParms
,
2100 const ::Size
aBaselineOffset( tools::getBaselineOffset( rState
,
2102 // #143885# maintain (nearly) full precision positioning,
2103 // by circumventing integer-based OutDev-mapping
2104 const ::basegfx::B2DPoint
aStartPoint(
2105 rState
.mapModeTransform
*
2106 ::basegfx::B2DPoint(rStartPoint
.X() + aBaselineOffset
.Width(),
2107 rStartPoint
.Y() + aBaselineOffset
.Height()) );
2109 const ::basegfx::B2DSize
aReliefOffset(
2110 rState
.mapModeTransform
* ::vcl::unotools::b2DSizeFromSize( rReliefOffset
) );
2111 const ::basegfx::B2DSize
aShadowOffset(
2112 rState
.mapModeTransform
* ::vcl::unotools::b2DSizeFromSize( rShadowOffset
) );
2114 if( rState
.isTextOutlineModeSet
)
2116 return createOutline(
2132 // convert DX array to device coordinate system (and
2133 // create it in the first place, if pDXArray is NULL)
2134 const uno::Sequence
< double > aCharWidths(
2136 setupDXArray( pDXArray
, nLen
, rState
) :
2137 setupDXArray( rText
,
2143 // determine type of text action to create
2144 // =======================================
2146 const ::Color
aEmptyColor( COL_AUTO
);
2148 // no DX array, and no need to subset - no need to store
2150 if( !pDXArray
&& !bSubsettable
)
2153 if( !rState
.textOverlineStyle
&&
2154 !rState
.textUnderlineStyle
&&
2155 !rState
.textStrikeoutStyle
&&
2156 rReliefColor
== aEmptyColor
&&
2157 rShadowColor
== aEmptyColor
)
2160 if( rParms
.maTextTransformation
.is_initialized() )
2162 return ActionSharedPtr( new TextAction(
2169 *rParms
.maTextTransformation
) );
2173 return ActionSharedPtr( new TextAction(
2184 // at least one of the effects requested
2185 if( rParms
.maTextTransformation
.is_initialized() )
2186 return ActionSharedPtr( new EffectTextAction(
2198 *rParms
.maTextTransformation
) );
2200 return ActionSharedPtr( new EffectTextAction(
2216 // DX array necessary - any effects?
2217 if( !rState
.textOverlineStyle
&&
2218 !rState
.textUnderlineStyle
&&
2219 !rState
.textStrikeoutStyle
&&
2220 rReliefColor
== aEmptyColor
&&
2221 rShadowColor
== aEmptyColor
)
2224 if( rParms
.maTextTransformation
.is_initialized() )
2225 return ActionSharedPtr( new TextArrayAction(
2233 *rParms
.maTextTransformation
) );
2235 return ActionSharedPtr( new TextArrayAction(
2246 // at least one of the effects requested
2247 if( rParms
.maTextTransformation
.is_initialized() )
2248 return ActionSharedPtr( new EffectTextArrayAction(
2261 *rParms
.maTextTransformation
) );
2263 return ActionSharedPtr( new EffectTextArrayAction(
2278 #if defined(__GNUC__)
2279 return ActionSharedPtr();
2285 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */