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 long* 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
< long > pCharWidths( new long[nLen
] );
202 rVDev
.GetTextArray( rText
, pCharWidths
.get(),
205 return setupDXArray( pCharWidths
.get(), nLen
, rState
);
208 ::basegfx::B2DPoint
adaptStartPoint( const ::basegfx::B2DPoint
& rStartPoint
,
209 const OutDevState
& rState
,
210 const uno::Sequence
< double >& rOffsets
)
212 ::basegfx::B2DPoint
aLocalPoint( rStartPoint
);
214 if( rState
.textAlignment
)
216 // text origin is right, not left. Modify start point
217 // accordingly, because XCanvas::drawTextLayout()
218 // always aligns left!
220 const double nOffset( rOffsets
[ rOffsets
.getLength()-1 ] );
222 // correct start point for rotated text: rotate around
223 // former start point
224 aLocalPoint
.setX( aLocalPoint
.getX() + cos( rState
.fontRotation
)*nOffset
);
225 aLocalPoint
.setY( aLocalPoint
.getY() + sin( rState
.fontRotation
)*nOffset
);
231 /** Perform common setup for array text actions
233 This method creates the XTextLayout object and
234 initializes it, e.g. with the logical advancements.
236 void initArrayAction( rendering::RenderState
& o_rRenderState
,
237 uno::Reference
< rendering::XTextLayout
>& o_rTextLayout
,
238 const ::basegfx::B2DPoint
& rStartPoint
,
239 const OUString
& rText
,
242 const uno::Sequence
< double >& rOffsets
,
243 const CanvasSharedPtr
& rCanvas
,
244 const OutDevState
& rState
,
245 const ::basegfx::B2DHomMatrix
* pTextTransform
)
247 ENSURE_OR_THROW( rOffsets
.getLength(),
248 "::cppcanvas::internal::initArrayAction(): zero-length DX array" );
250 const ::basegfx::B2DPoint
aLocalStartPoint(
251 adaptStartPoint( rStartPoint
, rState
, rOffsets
) );
253 uno::Reference
< rendering::XCanvasFont
> xFont( rState
.xFont
);
256 init( o_rRenderState
, xFont
, aLocalStartPoint
, rState
, rCanvas
, *pTextTransform
);
258 init( o_rRenderState
, xFont
, aLocalStartPoint
, rState
, rCanvas
);
260 o_rTextLayout
= xFont
->createTextLayout(
261 rendering::StringContext( rText
, nStartPos
, nLen
),
262 rState
.textDirection
,
265 ENSURE_OR_THROW( o_rTextLayout
.is(),
266 "::cppcanvas::internal::initArrayAction(): Invalid font" );
268 o_rTextLayout
->applyLogicalAdvancements( rOffsets
);
271 double getLineWidth( ::VirtualDevice
& rVDev
,
272 const OutDevState
& rState
,
273 const rendering::StringContext
& rStringContext
)
275 // TODO(F2): use correct scale direction
276 const ::basegfx::B2DSize
aSize( rVDev
.GetTextWidth( rStringContext
.Text
,
277 static_cast<sal_uInt16
>(rStringContext
.StartPosition
),
278 static_cast<sal_uInt16
>(rStringContext
.Length
) ),
281 return (rState
.mapModeTransform
* aSize
).getX();
284 uno::Sequence
< double >
285 calcSubsetOffsets( rendering::RenderState
& io_rRenderState
,
288 const uno::Reference
< rendering::XTextLayout
>& rOrigTextLayout
,
289 const ::cppcanvas::internal::Action::Subset
& rSubset
)
291 ENSURE_OR_THROW( rSubset
.mnSubsetEnd
> rSubset
.mnSubsetBegin
,
292 "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );
294 uno::Sequence
< double > aOrigOffsets( rOrigTextLayout
->queryLogicalAdvancements() );
295 const double* pOffsets( aOrigOffsets
.getConstArray() );
297 ENSURE_OR_THROW( aOrigOffsets
.getLength() >= rSubset
.mnSubsetEnd
,
298 "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );
300 // TODO(F3): It currently seems that for RTL text, the
301 // DX offsets are nevertheless increasing in logical
302 // text order (I'd expect they are decreasing,
303 // mimicking the fact that the text is output
304 // right-to-left). This breaks text effects for ALL
307 // determine leftmost position in given subset range -
308 // as the DX array contains the output positions
309 // starting with the second character (the first is
310 // assumed to have output position 0), correct begin
312 const double nMinPos( rSubset
.mnSubsetBegin
<= 0 ? 0 :
313 *(::std::min_element( pOffsets
+rSubset
.mnSubsetBegin
-1,
314 pOffsets
+rSubset
.mnSubsetEnd
)) );
316 // determine rightmost position in given subset range
317 // - as the DX array contains the output positions
318 // starting with the second character (the first is
319 // assumed to have output position 0), correct begin
321 const double nMaxPos(
322 *(::std::max_element( pOffsets
+ (rSubset
.mnSubsetBegin
<= 0 ?
323 0 : rSubset
.mnSubsetBegin
-1),
324 pOffsets
+ rSubset
.mnSubsetEnd
)) );
327 // adapt render state, to move text output to given offset
330 // TODO(F1): Strictly speaking, we also have to adapt
331 // the clip here, which normally should _not_ move
332 // with the output offset. Neglected for now, as it
333 // does not matter for drawing layer output
335 if( rSubset
.mnSubsetBegin
> 0 )
337 ::basegfx::B2DHomMatrix aTranslation
;
338 if( rOrigTextLayout
->getFont()->getFontRequest().FontDescription
.IsVertical
)
340 // vertical text -> offset in y direction
341 aTranslation
.translate( 0.0, nMinPos
);
345 // horizontal text -> offset in x direction
346 aTranslation
.translate( nMinPos
, 0.0 );
349 ::canvas::tools::appendToRenderState( io_rRenderState
,
354 // reduce DX array to given substring
357 const sal_Int32
nNewElements( rSubset
.mnSubsetEnd
- rSubset
.mnSubsetBegin
);
358 uno::Sequence
< double > aAdaptedOffsets( nNewElements
);
359 double* pAdaptedOffsets( aAdaptedOffsets
.getArray() );
361 // move to new output position (subtract nMinPos,
362 // which is the new '0' position), copy only the range
363 // as given by rSubset.
364 ::std::transform( pOffsets
+ rSubset
.mnSubsetBegin
,
365 pOffsets
+ rSubset
.mnSubsetEnd
,
367 ::boost::bind( ::std::minus
<double>(),
374 return aAdaptedOffsets
;
377 uno::Reference
< rendering::XTextLayout
>
378 createSubsetLayout( const rendering::StringContext
& rOrigContext
,
379 const ::cppcanvas::internal::Action::Subset
& rSubset
,
380 const uno::Reference
< rendering::XTextLayout
>& rOrigTextLayout
)
382 // create temporary new text layout with subset string
385 const sal_Int32
nNewStartPos( rOrigContext
.StartPosition
+ ::std::min(
386 rSubset
.mnSubsetBegin
, rOrigContext
.Length
-1 ) );
387 const sal_Int32
nNewLength( ::std::max(
389 rSubset
.mnSubsetEnd
- rSubset
.mnSubsetBegin
,
390 rOrigContext
.Length
),
393 const rendering::StringContext
aContext( rOrigContext
.Text
,
397 uno::Reference
< rendering::XTextLayout
> xTextLayout(
398 rOrigTextLayout
->getFont()->createTextLayout( aContext
,
399 rOrigTextLayout
->getMainTextDirection(),
401 uno::UNO_QUERY_THROW
);
406 /** Setup subset text layout
408 @param io_rTextLayout
409 Must contain original (full set) text layout on input,
410 will contain subsetted text layout (or empty
411 reference, for empty subsets) on output.
413 @param io_rRenderState
414 Must contain original render state on input, will
415 contain shifted render state concatenated with
416 rTransformation on output.
418 @param rTransformation
419 Additional transformation, to be prepended to render
425 void createSubsetLayout( uno::Reference
< rendering::XTextLayout
>& io_rTextLayout
,
426 rendering::RenderState
& io_rRenderState
,
429 const ::basegfx::B2DHomMatrix
& rTransformation
,
430 const Action::Subset
& rSubset
)
432 ::canvas::tools::prependToRenderState(io_rRenderState
, rTransformation
);
434 if( rSubset
.mnSubsetBegin
== rSubset
.mnSubsetEnd
)
436 // empty range, empty layout
437 io_rTextLayout
.clear();
442 ENSURE_OR_THROW( io_rTextLayout
.is(),
443 "createSubsetLayout(): Invalid input layout" );
445 const rendering::StringContext
& rOrigContext( io_rTextLayout
->getText() );
447 if( rSubset
.mnSubsetBegin
== 0 &&
448 rSubset
.mnSubsetEnd
== rOrigContext
.Length
)
450 // full range, no need for subsetting
454 uno::Reference
< rendering::XTextLayout
> xTextLayout(
455 createSubsetLayout( rOrigContext
, rSubset
, io_rTextLayout
) );
457 if( xTextLayout
.is() )
459 xTextLayout
->applyLogicalAdvancements(
460 calcSubsetOffsets( io_rRenderState
,
467 io_rTextLayout
= xTextLayout
;
471 /** Interface for renderEffectText functor below.
473 This is interface is used from the renderEffectText()
474 method below, to call the client implementation.
479 virtual ~TextRenderer() {}
481 /// Render text with given RenderState
482 virtual bool operator()( const rendering::RenderState
& rRenderState
) const = 0;
485 /** Render effect text.
488 Functor object, will be called to render the actual
489 part of the text effect (the text itself and the means
490 to render it are unknown to this method)
492 bool renderEffectText( const TextRenderer
& rRenderer
,
493 const rendering::RenderState
& rRenderState
,
494 const rendering::ViewState
& /*rViewState*/,
495 const uno::Reference
< rendering::XCanvas
>& xCanvas
,
496 const ::Color
& rShadowColor
,
497 const ::basegfx::B2DSize
& rShadowOffset
,
498 const ::Color
& rReliefColor
,
499 const ::basegfx::B2DSize
& rReliefOffset
)
501 ::Color
aEmptyColor( COL_AUTO
);
502 uno::Reference
<rendering::XColorSpace
> xColorSpace(
503 xCanvas
->getDevice()->getDeviceColorSpace() );
505 // draw shadow text, if enabled
506 if( rShadowColor
!= aEmptyColor
)
508 rendering::RenderState
aShadowState( rRenderState
);
509 ::basegfx::B2DHomMatrix aTranslate
;
511 aTranslate
.translate( rShadowOffset
.getX(),
512 rShadowOffset
.getY() );
514 ::canvas::tools::appendToRenderState(aShadowState
, aTranslate
);
516 aShadowState
.DeviceColor
=
517 vcl::unotools::colorToDoubleSequence( rShadowColor
,
520 rRenderer( aShadowState
);
523 // draw relief text, if enabled
524 if( rReliefColor
!= aEmptyColor
)
526 rendering::RenderState
aReliefState( rRenderState
);
527 ::basegfx::B2DHomMatrix aTranslate
;
529 aTranslate
.translate( rReliefOffset
.getX(),
530 rReliefOffset
.getY() );
532 ::canvas::tools::appendToRenderState(aReliefState
, aTranslate
);
534 aReliefState
.DeviceColor
=
535 vcl::unotools::colorToDoubleSequence( rReliefColor
,
538 rRenderer( aReliefState
);
542 rRenderer( rRenderState
);
548 ::basegfx::B2DRange
calcEffectTextBounds( const ::basegfx::B2DRange
& rTextBounds
,
549 const ::basegfx::B2DRange
& rLineBounds
,
550 const ::basegfx::B2DSize
& rReliefOffset
,
551 const ::basegfx::B2DSize
& rShadowOffset
,
552 const rendering::RenderState
& rRenderState
,
553 const rendering::ViewState
& rViewState
)
555 ::basegfx::B2DRange
aBounds( rTextBounds
);
557 // add extends of text lines
558 aBounds
.expand( rLineBounds
);
560 // TODO(Q3): Provide this functionality at the B2DRange
561 ::basegfx::B2DRange
aTotalBounds( aBounds
);
563 ::basegfx::B2DRange( aBounds
.getMinX() + rReliefOffset
.getX(),
564 aBounds
.getMinY() + rReliefOffset
.getY(),
565 aBounds
.getMaxX() + rReliefOffset
.getX(),
566 aBounds
.getMaxY() + rReliefOffset
.getY() ) );
568 ::basegfx::B2DRange( aBounds
.getMinX() + rShadowOffset
.getX(),
569 aBounds
.getMinY() + rShadowOffset
.getY(),
570 aBounds
.getMaxX() + rShadowOffset
.getX(),
571 aBounds
.getMaxY() + rShadowOffset
.getY() ) );
573 return tools::calcDevicePixelBounds( aTotalBounds
,
578 void initEffectLinePolyPolygon( ::basegfx::B2DSize
& o_rOverallSize
,
579 uno::Reference
< rendering::XPolyPolygon2D
>& o_rTextLines
,
580 const CanvasSharedPtr
& rCanvas
,
581 const uno::Sequence
< double >& rOffsets
,
582 const tools::TextLineInfo
& rLineInfo
)
584 const ::basegfx::B2DPolyPolygon
aPoly(
585 textLinesFromLogicalOffsets(
589 o_rOverallSize
= ::basegfx::tools::getRange( aPoly
).getRange();
591 o_rTextLines
= ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
592 rCanvas
->getUNOCanvas()->getDevice(),
596 void initEffectLinePolyPolygon( ::basegfx::B2DSize
& o_rOverallSize
,
597 uno::Reference
< rendering::XPolyPolygon2D
>& o_rTextLines
,
598 const CanvasSharedPtr
& rCanvas
,
600 const tools::TextLineInfo
& rLineInfo
)
602 const ::basegfx::B2DPolyPolygon
aPoly(
603 tools::createTextLinesPolyPolygon( 0.0, nLineWidth
,
606 o_rOverallSize
= ::basegfx::tools::getRange( aPoly
).getRange();
608 o_rTextLines
= ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
609 rCanvas
->getUNOCanvas()->getDevice(),
616 class TextAction
: public Action
, private ::boost::noncopyable
619 TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
620 const OUString
& rString
,
623 const CanvasSharedPtr
& rCanvas
,
624 const OutDevState
& rState
);
626 TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
627 const OUString
& rString
,
630 const CanvasSharedPtr
& rCanvas
,
631 const OutDevState
& rState
,
632 const ::basegfx::B2DHomMatrix
& rTextTransform
);
634 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const SAL_OVERRIDE
;
635 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
636 const Subset
& rSubset
) const SAL_OVERRIDE
;
638 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const SAL_OVERRIDE
;
639 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
640 const Subset
& rSubset
) const SAL_OVERRIDE
;
642 virtual sal_Int32
getActionCount() const SAL_OVERRIDE
;
645 // TODO(P2): This is potentially a real mass object
646 // (every character might be a separate TextAction),
647 // thus, make it as lightweight as possible. For
648 // example, share common RenderState among several
649 // TextActions, maybe using maOffsets for the
652 uno::Reference
< rendering::XCanvasFont
> mxFont
;
653 const rendering::StringContext maStringContext
;
654 const CanvasSharedPtr mpCanvas
;
655 rendering::RenderState maState
;
656 const sal_Int8 maTextDirection
;
659 TextAction::TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
660 const OUString
& rString
,
663 const CanvasSharedPtr
& rCanvas
,
664 const OutDevState
& rState
) :
665 mxFont( rState
.xFont
),
666 maStringContext( rString
, nStartPos
, nLen
),
669 maTextDirection( rState
.textDirection
)
671 init( maState
, mxFont
,
675 ENSURE_OR_THROW( mxFont
.is(),
676 "::cppcanvas::internal::TextAction(): Invalid font" );
679 TextAction::TextAction( const ::basegfx::B2DPoint
& rStartPoint
,
680 const OUString
& rString
,
683 const CanvasSharedPtr
& rCanvas
,
684 const OutDevState
& rState
,
685 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
686 mxFont( rState
.xFont
),
687 maStringContext( rString
, nStartPos
, nLen
),
690 maTextDirection( rState
.textDirection
)
692 init( maState
, mxFont
,
694 rState
, rCanvas
, rTextTransform
);
696 ENSURE_OR_THROW( mxFont
.is(),
697 "::cppcanvas::internal::TextAction(): Invalid font" );
700 bool TextAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
702 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextAction::render()" );
703 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextAction: 0x" << std::hex
<< this );
705 rendering::RenderState
aLocalState( maState
);
706 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
708 mpCanvas
->getUNOCanvas()->drawText( maStringContext
, mxFont
,
709 mpCanvas
->getViewState(), aLocalState
, maTextDirection
);
714 bool TextAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
715 const Subset
& /*rSubset*/ ) const
717 SAL_WARN( "cppcanvas.emf", "TextAction::renderSubset(): Subset not supported by this object" );
719 // TODO(P1): Retrieve necessary font metric info for
720 // TextAction from XCanvas. Currently, the
721 // TextActionFactory does not generate this object for
722 // _subsettable_ text
723 return render( rTransformation
);
726 ::basegfx::B2DRange
TextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
728 // create XTextLayout, to have the
729 // XTextLayout::queryTextBounds() method available
730 uno::Reference
< rendering::XTextLayout
> xTextLayout(
731 mxFont
->createTextLayout(
736 rendering::RenderState
aLocalState( maState
);
737 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
739 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
740 xTextLayout
->queryTextBounds() ),
741 mpCanvas
->getViewState(),
745 ::basegfx::B2DRange
TextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
746 const Subset
& /*rSubset*/ ) const
748 SAL_WARN( "cppcanvas.emf", "TextAction::getBounds(): Subset not supported by this object" );
750 // TODO(P1): Retrieve necessary font metric info for
751 // TextAction from XCanvas. Currently, the
752 // TextActionFactory does not generate this object for
753 // _subsettable_ text
754 return getBounds( rTransformation
);
757 sal_Int32
TextAction::getActionCount() const
759 // TODO(P1): Retrieve necessary font metric info for
760 // TextAction from XCanvas. Currently, the
761 // TextActionFactory does not generate this object for
762 // _subsettable_ text
769 class EffectTextAction
:
772 private ::boost::noncopyable
775 EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
776 const ::basegfx::B2DSize
& rReliefOffset
,
777 const ::Color
& rReliefColor
,
778 const ::basegfx::B2DSize
& rShadowOffset
,
779 const ::Color
& rShadowColor
,
780 const OUString
& rText
,
783 VirtualDevice
& rVDev
,
784 const CanvasSharedPtr
& rCanvas
,
785 const OutDevState
& rState
);
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 OUString
& rText
,
795 VirtualDevice
& rVDev
,
796 const CanvasSharedPtr
& rCanvas
,
797 const OutDevState
& rState
,
798 const ::basegfx::B2DHomMatrix
& rTextTransform
);
800 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const SAL_OVERRIDE
;
801 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
802 const Subset
& rSubset
) const SAL_OVERRIDE
;
804 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const SAL_OVERRIDE
;
805 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
806 const Subset
& rSubset
) const SAL_OVERRIDE
;
808 virtual sal_Int32
getActionCount() const SAL_OVERRIDE
;
811 /// Interface TextRenderer
812 virtual bool operator()( const rendering::RenderState
& rRenderState
) const SAL_OVERRIDE
;
814 // TODO(P2): This is potentially a real mass object
815 // (every character might be a separate TextAction),
816 // thus, make it as lightweight as possible. For
817 // example, share common RenderState among several
818 // TextActions, maybe using maOffsets for the
821 uno::Reference
< rendering::XCanvasFont
> mxFont
;
822 const rendering::StringContext maStringContext
;
823 const CanvasSharedPtr mpCanvas
;
824 rendering::RenderState maState
;
825 const tools::TextLineInfo maTextLineInfo
;
826 ::basegfx::B2DSize maLinesOverallSize
;
827 const double mnLineWidth
;
828 uno::Reference
< rendering::XPolyPolygon2D
> mxTextLines
;
829 const ::basegfx::B2DSize maReliefOffset
;
830 const ::Color maReliefColor
;
831 const ::basegfx::B2DSize maShadowOffset
;
832 const ::Color maShadowColor
;
833 const sal_Int8 maTextDirection
;
836 EffectTextAction::EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
837 const ::basegfx::B2DSize
& rReliefOffset
,
838 const ::Color
& rReliefColor
,
839 const ::basegfx::B2DSize
& rShadowOffset
,
840 const ::Color
& rShadowColor
,
841 const OUString
& rText
,
844 VirtualDevice
& rVDev
,
845 const CanvasSharedPtr
& rCanvas
,
846 const OutDevState
& rState
) :
847 mxFont( rState
.xFont
),
848 maStringContext( rText
, nStartPos
, nLen
),
851 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
852 maLinesOverallSize(),
853 mnLineWidth( getLineWidth( rVDev
, rState
, maStringContext
) ),
855 maReliefOffset( rReliefOffset
),
856 maReliefColor( rReliefColor
),
857 maShadowOffset( rShadowOffset
),
858 maShadowColor( rShadowColor
),
859 maTextDirection( rState
.textDirection
)
861 initEffectLinePolyPolygon( maLinesOverallSize
,
867 init( maState
, mxFont
,
871 ENSURE_OR_THROW( mxFont
.is() && mxTextLines
.is(),
872 "::cppcanvas::internal::EffectTextAction(): Invalid font or lines" );
875 EffectTextAction::EffectTextAction( const ::basegfx::B2DPoint
& rStartPoint
,
876 const ::basegfx::B2DSize
& rReliefOffset
,
877 const ::Color
& rReliefColor
,
878 const ::basegfx::B2DSize
& rShadowOffset
,
879 const ::Color
& rShadowColor
,
880 const OUString
& rText
,
883 VirtualDevice
& rVDev
,
884 const CanvasSharedPtr
& rCanvas
,
885 const OutDevState
& rState
,
886 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
887 mxFont( rState
.xFont
),
888 maStringContext( rText
, nStartPos
, nLen
),
891 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
892 maLinesOverallSize(),
893 mnLineWidth( getLineWidth( rVDev
, rState
, maStringContext
) ),
895 maReliefOffset( rReliefOffset
),
896 maReliefColor( rReliefColor
),
897 maShadowOffset( rShadowOffset
),
898 maShadowColor( rShadowColor
),
899 maTextDirection( rState
.textDirection
)
901 initEffectLinePolyPolygon( maLinesOverallSize
,
907 init( maState
, mxFont
,
909 rState
, rCanvas
, rTextTransform
);
911 ENSURE_OR_THROW( mxFont
.is() && mxTextLines
.is(),
912 "::cppcanvas::internal::EffectTextAction(): Invalid font or lines" );
915 bool EffectTextAction::operator()( const rendering::RenderState
& rRenderState
) const
917 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
918 const uno::Reference
< rendering::XCanvas
>& rCanvas( mpCanvas
->getUNOCanvas() );
920 rCanvas
->fillPolyPolygon( mxTextLines
,
924 rCanvas
->drawText( maStringContext
, mxFont
,
932 bool EffectTextAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
934 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextAction::render()" );
935 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextAction: 0x" << std::hex
<< this );
937 rendering::RenderState
aLocalState( maState
);
938 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
940 return renderEffectText( *this,
942 mpCanvas
->getViewState(),
943 mpCanvas
->getUNOCanvas(),
950 bool EffectTextAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
951 const Subset
& /*rSubset*/ ) const
953 SAL_WARN( "cppcanvas.emf", "EffectTextAction::renderSubset(): Subset not supported by this object" );
955 // TODO(P1): Retrieve necessary font metric info for
956 // TextAction from XCanvas. Currently, the
957 // TextActionFactory does not generate this object for
959 return render( rTransformation
);
962 ::basegfx::B2DRange
EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
964 // create XTextLayout, to have the
965 // XTextLayout::queryTextBounds() method available
966 uno::Reference
< rendering::XTextLayout
> xTextLayout(
967 mxFont
->createTextLayout(
972 rendering::RenderState
aLocalState( maState
);
973 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
975 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
976 xTextLayout
->queryTextBounds() ),
977 ::basegfx::B2DRange( 0,0,
978 maLinesOverallSize
.getX(),
979 maLinesOverallSize
.getY() ),
983 mpCanvas
->getViewState() );
986 ::basegfx::B2DRange
EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
987 const Subset
& /*rSubset*/ ) const
989 SAL_WARN( "cppcanvas.emf", "EffectTextAction::getBounds(): Subset not supported by this object" );
991 // TODO(P1): Retrieve necessary font metric info for
992 // TextAction from XCanvas. Currently, the
993 // TextActionFactory does not generate this object for
994 // _subsettable_ text
995 return getBounds( rTransformation
);
998 sal_Int32
EffectTextAction::getActionCount() const
1000 // TODO(P1): Retrieve necessary font metric info for
1001 // TextAction from XCanvas. Currently, the
1002 // TextActionFactory does not generate this object for
1010 class TextArrayAction
: public Action
, private ::boost::noncopyable
1013 TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1014 const OUString
& rString
,
1015 sal_Int32 nStartPos
,
1017 const uno::Sequence
< double >& rOffsets
,
1018 const CanvasSharedPtr
& rCanvas
,
1019 const OutDevState
& rState
);
1021 TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1022 const OUString
& rString
,
1023 sal_Int32 nStartPos
,
1025 const uno::Sequence
< double >& rOffsets
,
1026 const CanvasSharedPtr
& rCanvas
,
1027 const OutDevState
& rState
,
1028 const ::basegfx::B2DHomMatrix
& rTextTransform
);
1030 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const SAL_OVERRIDE
;
1031 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1032 const Subset
& rSubset
) const SAL_OVERRIDE
;
1034 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const SAL_OVERRIDE
;
1035 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1036 const Subset
& rSubset
) const SAL_OVERRIDE
;
1038 virtual sal_Int32
getActionCount() const SAL_OVERRIDE
;
1041 // TODO(P2): This is potentially a real mass object
1042 // (every character might be a separate TextAction),
1043 // thus, make it as lightweight as possible. For
1044 // example, share common RenderState among several
1045 // TextActions, maybe using maOffsets for the
1048 uno::Reference
< rendering::XTextLayout
> mxTextLayout
;
1049 const CanvasSharedPtr mpCanvas
;
1050 rendering::RenderState maState
;
1053 TextArrayAction::TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1054 const OUString
& rString
,
1055 sal_Int32 nStartPos
,
1057 const uno::Sequence
< double >& rOffsets
,
1058 const CanvasSharedPtr
& rCanvas
,
1059 const OutDevState
& rState
) :
1061 mpCanvas( rCanvas
),
1064 initArrayAction( maState
,
1075 TextArrayAction::TextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1076 const OUString
& rString
,
1077 sal_Int32 nStartPos
,
1079 const uno::Sequence
< double >& rOffsets
,
1080 const CanvasSharedPtr
& rCanvas
,
1081 const OutDevState
& rState
,
1082 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
1084 mpCanvas( rCanvas
),
1087 initArrayAction( maState
,
1099 bool TextArrayAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1101 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextArrayAction::render()" );
1102 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextArrayAction: 0x" << std::hex
<< this );
1104 rendering::RenderState
aLocalState( maState
);
1105 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1107 mpCanvas
->getUNOCanvas()->drawTextLayout( mxTextLayout
,
1108 mpCanvas
->getViewState(),
1114 bool TextArrayAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1115 const Subset
& rSubset
) const
1117 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextArrayAction::renderSubset()" );
1118 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextArrayAction: 0x" << std::hex
<< this );
1120 rendering::RenderState
aLocalState( maState
);
1121 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1123 double nDummy0
, nDummy1
;
1124 createSubsetLayout( xTextLayout
,
1131 if( !xTextLayout
.is() )
1132 return true; // empty layout, render nothing
1134 mpCanvas
->getUNOCanvas()->drawTextLayout( xTextLayout
,
1135 mpCanvas
->getViewState(),
1141 ::basegfx::B2DRange
TextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1143 rendering::RenderState
aLocalState( maState
);
1144 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1146 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1147 mxTextLayout
->queryTextBounds() ),
1148 mpCanvas
->getViewState(),
1152 ::basegfx::B2DRange
TextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1153 const Subset
& rSubset
) const
1155 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextArrayAction::getBounds( subset )" );
1156 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::TextArrayAction: 0x" << std::hex
<< this );
1158 rendering::RenderState
aLocalState( maState
);
1159 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1161 double nDummy0
, nDummy1
;
1162 createSubsetLayout( xTextLayout
,
1169 if( !xTextLayout
.is() )
1170 return ::basegfx::B2DRange(); // empty layout, empty bounds
1172 return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1173 xTextLayout
->queryTextBounds() ),
1174 mpCanvas
->getViewState(),
1178 sal_Int32
TextArrayAction::getActionCount() const
1180 const rendering::StringContext
& rOrigContext( mxTextLayout
->getText() );
1182 return rOrigContext
.Length
;
1188 class EffectTextArrayAction
:
1190 public TextRenderer
,
1191 private ::boost::noncopyable
1194 EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1195 const ::basegfx::B2DSize
& rReliefOffset
,
1196 const ::Color
& rReliefColor
,
1197 const ::basegfx::B2DSize
& rShadowOffset
,
1198 const ::Color
& rShadowColor
,
1199 const OUString
& rText
,
1200 sal_Int32 nStartPos
,
1202 const uno::Sequence
< double >& rOffsets
,
1203 VirtualDevice
& rVDev
,
1204 const CanvasSharedPtr
& rCanvas
,
1205 const OutDevState
& rState
);
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 OUString
& rText
,
1212 sal_Int32 nStartPos
,
1214 const uno::Sequence
< double >& rOffsets
,
1215 VirtualDevice
& rVDev
,
1216 const CanvasSharedPtr
& rCanvas
,
1217 const OutDevState
& rState
,
1218 const ::basegfx::B2DHomMatrix
& rTextTransform
);
1220 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const SAL_OVERRIDE
;
1221 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1222 const Subset
& rSubset
) const SAL_OVERRIDE
;
1224 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const SAL_OVERRIDE
;
1225 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1226 const Subset
& rSubset
) const SAL_OVERRIDE
;
1228 virtual sal_Int32
getActionCount() const SAL_OVERRIDE
;
1231 // TextRenderer interface
1232 virtual bool operator()( const rendering::RenderState
& rRenderState
) const SAL_OVERRIDE
;
1234 // TODO(P2): This is potentially a real mass object
1235 // (every character might be a separate TextAction),
1236 // thus, make it as lightweight as possible. For
1237 // example, share common RenderState among several
1238 // TextActions, maybe using maOffsets for the
1241 uno::Reference
< rendering::XTextLayout
> mxTextLayout
;
1242 const CanvasSharedPtr mpCanvas
;
1243 rendering::RenderState maState
;
1244 const tools::TextLineInfo maTextLineInfo
;
1245 ::basegfx::B2DSize maLinesOverallSize
;
1246 uno::Reference
< rendering::XPolyPolygon2D
> mxTextLines
;
1247 const ::basegfx::B2DSize maReliefOffset
;
1248 const ::Color maReliefColor
;
1249 const ::basegfx::B2DSize maShadowOffset
;
1250 const ::Color maShadowColor
;
1253 EffectTextArrayAction::EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1254 const ::basegfx::B2DSize
& rReliefOffset
,
1255 const ::Color
& rReliefColor
,
1256 const ::basegfx::B2DSize
& rShadowOffset
,
1257 const ::Color
& rShadowColor
,
1258 const OUString
& rText
,
1259 sal_Int32 nStartPos
,
1261 const uno::Sequence
< double >& rOffsets
,
1262 VirtualDevice
& rVDev
,
1263 const CanvasSharedPtr
& rCanvas
,
1264 const OutDevState
& rState
) :
1266 mpCanvas( rCanvas
),
1268 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1269 maLinesOverallSize(),
1271 maReliefOffset( rReliefOffset
),
1272 maReliefColor( rReliefColor
),
1273 maShadowOffset( rShadowOffset
),
1274 maShadowColor( rShadowColor
)
1276 initEffectLinePolyPolygon( maLinesOverallSize
,
1282 initArrayAction( maState
,
1293 EffectTextArrayAction::EffectTextArrayAction( const ::basegfx::B2DPoint
& rStartPoint
,
1294 const ::basegfx::B2DSize
& rReliefOffset
,
1295 const ::Color
& rReliefColor
,
1296 const ::basegfx::B2DSize
& rShadowOffset
,
1297 const ::Color
& rShadowColor
,
1298 const OUString
& rText
,
1299 sal_Int32 nStartPos
,
1301 const uno::Sequence
< double >& rOffsets
,
1302 VirtualDevice
& rVDev
,
1303 const CanvasSharedPtr
& rCanvas
,
1304 const OutDevState
& rState
,
1305 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
1307 mpCanvas( rCanvas
),
1309 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1310 maLinesOverallSize(),
1312 maReliefOffset( rReliefOffset
),
1313 maReliefColor( rReliefColor
),
1314 maShadowOffset( rShadowOffset
),
1315 maShadowColor( rShadowColor
)
1317 initEffectLinePolyPolygon( maLinesOverallSize
,
1323 initArrayAction( maState
,
1335 bool EffectTextArrayAction::operator()( const rendering::RenderState
& rRenderState
) const
1337 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
1338 const uno::Reference
< rendering::XCanvas
>& rCanvas( mpCanvas
->getUNOCanvas() );
1340 rCanvas
->fillPolyPolygon( mxTextLines
,
1344 rCanvas
->drawTextLayout( mxTextLayout
,
1351 bool EffectTextArrayAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1353 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction::render()" );
1354 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction: 0x" << std::hex
<< this );
1356 rendering::RenderState
aLocalState( maState
);
1357 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1359 return renderEffectText( *this,
1361 mpCanvas
->getViewState(),
1362 mpCanvas
->getUNOCanvas(),
1369 class EffectTextArrayRenderHelper
: public TextRenderer
1372 EffectTextArrayRenderHelper( const uno::Reference
< rendering::XCanvas
>& rCanvas
,
1373 const uno::Reference
< rendering::XTextLayout
>& rTextLayout
,
1374 const uno::Reference
< rendering::XPolyPolygon2D
>& rLinePolygon
,
1375 const rendering::ViewState
& rViewState
) :
1376 mrCanvas( rCanvas
),
1377 mrTextLayout( rTextLayout
),
1378 mrLinePolygon( rLinePolygon
),
1379 mrViewState( rViewState
)
1383 // TextRenderer interface
1384 virtual bool operator()( const rendering::RenderState
& rRenderState
) const SAL_OVERRIDE
1386 mrCanvas
->fillPolyPolygon( mrLinePolygon
,
1390 mrCanvas
->drawTextLayout( mrTextLayout
,
1398 const uno::Reference
< rendering::XCanvas
>& mrCanvas
;
1399 const uno::Reference
< rendering::XTextLayout
>& mrTextLayout
;
1400 const uno::Reference
< rendering::XPolyPolygon2D
>& mrLinePolygon
;
1401 const rendering::ViewState
& mrViewState
;
1404 bool EffectTextArrayAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1405 const Subset
& rSubset
) const
1407 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction::renderSubset()" );
1408 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction: 0x" << std::hex
<< this );
1410 rendering::RenderState
aLocalState( maState
);
1411 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1412 const geometry::RealRectangle2D
aTextBounds( mxTextLayout
->queryTextBounds() );
1414 double nMinPos(0.0);
1415 double nMaxPos(aTextBounds
.X2
- aTextBounds
.X1
);
1417 createSubsetLayout( xTextLayout
,
1424 if( !xTextLayout
.is() )
1425 return true; // empty layout, render nothing
1428 // create and setup local line polygon
1429 // ===================================
1431 uno::Reference
< rendering::XCanvas
> xCanvas( mpCanvas
->getUNOCanvas() );
1432 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
1434 uno::Reference
< rendering::XPolyPolygon2D
> xTextLines(
1435 ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
1436 xCanvas
->getDevice(),
1437 tools::createTextLinesPolyPolygon(
1438 0.0, nMaxPos
- nMinPos
,
1439 maTextLineInfo
) ) );
1442 // render everything
1443 // =================
1445 return renderEffectText(
1446 EffectTextArrayRenderHelper( xCanvas
,
1459 ::basegfx::B2DRange
EffectTextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1461 rendering::RenderState
aLocalState( maState
);
1462 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1464 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1465 mxTextLayout
->queryTextBounds() ),
1466 ::basegfx::B2DRange( 0,0,
1467 maLinesOverallSize
.getX(),
1468 maLinesOverallSize
.getY() ),
1472 mpCanvas
->getViewState() );
1475 ::basegfx::B2DRange
EffectTextArrayAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1476 const Subset
& rSubset
) const
1478 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction::getBounds( subset )" );
1479 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction: 0x" << std::hex
<< this );
1481 rendering::RenderState
aLocalState( maState
);
1482 uno::Reference
< rendering::XTextLayout
> xTextLayout( mxTextLayout
);
1483 const geometry::RealRectangle2D
aTextBounds( mxTextLayout
->queryTextBounds() );
1485 double nMinPos(0.0);
1486 double nMaxPos(aTextBounds
.X2
- aTextBounds
.X1
);
1488 createSubsetLayout( xTextLayout
,
1495 if( !xTextLayout
.is() )
1496 return ::basegfx::B2DRange(); // empty layout, empty bounds
1499 // create and setup local line polygon
1500 // ===================================
1502 const ::basegfx::B2DPolyPolygon
aPoly(
1503 tools::createTextLinesPolyPolygon(
1504 0.0, nMaxPos
- nMinPos
,
1507 return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
1508 xTextLayout
->queryTextBounds() ),
1509 ::basegfx::tools::getRange( aPoly
),
1513 mpCanvas
->getViewState() );
1516 sal_Int32
EffectTextArrayAction::getActionCount() const
1518 const rendering::StringContext
& rOrigContext( mxTextLayout
->getText() );
1520 return rOrigContext
.Length
;
1526 class OutlineAction
:
1528 public TextRenderer
,
1529 private ::boost::noncopyable
1532 OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1533 const ::basegfx::B2DSize
& rReliefOffset
,
1534 const ::Color
& rReliefColor
,
1535 const ::basegfx::B2DSize
& rShadowOffset
,
1536 const ::Color
& rShadowColor
,
1537 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1538 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1539 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1540 const uno::Sequence
< double >& rOffsets
,
1541 VirtualDevice
& rVDev
,
1542 const CanvasSharedPtr
& rCanvas
,
1543 const OutDevState
& rState
);
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 const ::basegfx::B2DHomMatrix
& rTextTransform
);
1558 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
) const SAL_OVERRIDE
;
1559 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1560 const Subset
& rSubset
) const SAL_OVERRIDE
;
1562 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const SAL_OVERRIDE
;
1563 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1564 const Subset
& rSubset
) const SAL_OVERRIDE
;
1566 virtual sal_Int32
getActionCount() const SAL_OVERRIDE
;
1569 // TextRenderer interface
1570 virtual bool operator()( const rendering::RenderState
& rRenderState
) const SAL_OVERRIDE
;
1572 // TODO(P2): This is potentially a real mass object
1573 // (every character might be a separate TextAction),
1574 // thus, make it as lightweight as possible. For
1575 // example, share common RenderState among several
1576 // TextActions, maybe using maOffsets for the
1579 uno::Reference
< rendering::XPolyPolygon2D
> mxTextPoly
;
1581 /** This vector denotes the index of the start polygon
1582 for the respective glyph sequence.
1584 To get a polygon index range for a given character
1585 index i, take [ maPolygonGlyphMap[i],
1586 maPolygonGlyphMap[i+1] ). Note that this is wrong
1589 const ::std::vector
< sal_Int32
> maPolygonGlyphMap
;
1590 const uno::Sequence
< double > maOffsets
;
1591 const CanvasSharedPtr mpCanvas
;
1592 rendering::RenderState maState
;
1593 double mnOutlineWidth
;
1594 const uno::Sequence
< double > maFillColor
;
1595 const tools::TextLineInfo maTextLineInfo
;
1596 ::basegfx::B2DSize maLinesOverallSize
;
1597 const ::basegfx::B2DRectangle maOutlineBounds
;
1598 uno::Reference
< rendering::XPolyPolygon2D
> mxTextLines
;
1599 const ::basegfx::B2DSize maReliefOffset
;
1600 const ::Color maReliefColor
;
1601 const ::basegfx::B2DSize maShadowOffset
;
1602 const ::Color maShadowColor
;
1605 double calcOutlineWidth( const OutDevState
& rState
,
1606 VirtualDevice
& rVDev
)
1608 const ::basegfx::B2DSize
aFontSize( 0,
1609 rVDev
.GetFont().GetHeight() / 64.0 );
1611 const double nOutlineWidth(
1612 (rState
.mapModeTransform
* aFontSize
).getY() );
1614 return nOutlineWidth
< 1.0 ? 1.0 : nOutlineWidth
;
1617 OutlineAction::OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1618 const ::basegfx::B2DSize
& rReliefOffset
,
1619 const ::Color
& rReliefColor
,
1620 const ::basegfx::B2DSize
& rShadowOffset
,
1621 const ::Color
& rShadowColor
,
1622 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1623 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1624 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1625 const uno::Sequence
< double >& rOffsets
,
1626 VirtualDevice
& rVDev
,
1627 const CanvasSharedPtr
& rCanvas
,
1628 const OutDevState
& rState
) :
1629 mxTextPoly( rTextPoly
),
1630 maPolygonGlyphMap( rPolygonGlyphMap
),
1631 maOffsets( rOffsets
),
1632 mpCanvas( rCanvas
),
1634 mnOutlineWidth( calcOutlineWidth(rState
,rVDev
) ),
1636 vcl::unotools::colorToDoubleSequence(
1637 ::Color( COL_WHITE
),
1638 rCanvas
->getUNOCanvas()->getDevice()->getDeviceColorSpace() )),
1639 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1640 maLinesOverallSize(),
1641 maOutlineBounds( rOutlineBounds
),
1643 maReliefOffset( rReliefOffset
),
1644 maReliefColor( rReliefColor
),
1645 maShadowOffset( rShadowOffset
),
1646 maShadowColor( rShadowColor
)
1648 initEffectLinePolyPolygon( maLinesOverallSize
,
1660 OutlineAction::OutlineAction( const ::basegfx::B2DPoint
& rStartPoint
,
1661 const ::basegfx::B2DSize
& rReliefOffset
,
1662 const ::Color
& rReliefColor
,
1663 const ::basegfx::B2DSize
& rShadowOffset
,
1664 const ::Color
& rShadowColor
,
1665 const ::basegfx::B2DRectangle
& rOutlineBounds
,
1666 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPoly
,
1667 const ::std::vector
< sal_Int32
>& rPolygonGlyphMap
,
1668 const uno::Sequence
< double >& rOffsets
,
1669 VirtualDevice
& rVDev
,
1670 const CanvasSharedPtr
& rCanvas
,
1671 const OutDevState
& rState
,
1672 const ::basegfx::B2DHomMatrix
& rTextTransform
) :
1673 mxTextPoly( rTextPoly
),
1674 maPolygonGlyphMap( rPolygonGlyphMap
),
1675 maOffsets( rOffsets
),
1676 mpCanvas( rCanvas
),
1678 mnOutlineWidth( calcOutlineWidth(rState
,rVDev
) ),
1680 vcl::unotools::colorToDoubleSequence(
1681 ::Color( COL_WHITE
),
1682 rCanvas
->getUNOCanvas()->getDevice()->getDeviceColorSpace() )),
1683 maTextLineInfo( tools::createTextLineInfo( rVDev
, rState
) ),
1684 maLinesOverallSize(),
1685 maOutlineBounds( rOutlineBounds
),
1687 maReliefOffset( rReliefOffset
),
1688 maReliefColor( rReliefColor
),
1689 maShadowOffset( rShadowOffset
),
1690 maShadowColor( rShadowColor
)
1692 initEffectLinePolyPolygon( maLinesOverallSize
,
1705 bool OutlineAction::operator()( const rendering::RenderState
& rRenderState
) const
1707 const rendering::ViewState
& rViewState( mpCanvas
->getViewState() );
1708 const uno::Reference
< rendering::XCanvas
>& rCanvas( mpCanvas
->getUNOCanvas() );
1710 rendering::StrokeAttributes aStrokeAttributes
;
1712 aStrokeAttributes
.StrokeWidth
= mnOutlineWidth
;
1713 aStrokeAttributes
.MiterLimit
= 1.0;
1714 aStrokeAttributes
.StartCapType
= rendering::PathCapType::BUTT
;
1715 aStrokeAttributes
.EndCapType
= rendering::PathCapType::BUTT
;
1716 aStrokeAttributes
.JoinType
= rendering::PathJoinType::MITER
;
1718 rendering::RenderState
aLocalState( rRenderState
);
1719 aLocalState
.DeviceColor
= maFillColor
;
1721 // TODO(P1): implement caching
1723 // background of text
1724 rCanvas
->fillPolyPolygon( mxTextPoly
,
1728 // border line of text
1729 rCanvas
->strokePolyPolygon( mxTextPoly
,
1732 aStrokeAttributes
);
1734 // underlines/strikethrough - background
1735 rCanvas
->fillPolyPolygon( mxTextLines
,
1738 // underlines/strikethrough - border
1739 rCanvas
->strokePolyPolygon( mxTextLines
,
1742 aStrokeAttributes
);
1747 bool OutlineAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1749 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction::render()" );
1750 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::EffectTextArrayAction: 0x" << std::hex
<< this );
1752 rendering::RenderState
aLocalState( maState
);
1753 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1755 return renderEffectText( *this,
1757 mpCanvas
->getViewState(),
1758 mpCanvas
->getUNOCanvas(),
1765 #if 0 // see #if'ed out use in OutlineAction::renderSubset below:
1766 class OutlineTextArrayRenderHelper
: public TextRenderer
1769 OutlineTextArrayRenderHelper( const uno::Reference
< rendering::XCanvas
>& rCanvas
,
1770 const uno::Reference
< rendering::XPolyPolygon2D
>& rTextPolygon
,
1771 const uno::Reference
< rendering::XPolyPolygon2D
>& rLinePolygon
,
1772 const rendering::ViewState
& rViewState
,
1773 double nOutlineWidth
) :
1775 vcl::unotools::colorToDoubleSequence(
1776 ::Color( COL_WHITE
),
1777 rCanvas
->getDevice()->getDeviceColorSpace() )),
1778 mnOutlineWidth( nOutlineWidth
),
1779 mrCanvas( rCanvas
),
1780 mrTextPolygon( rTextPolygon
),
1781 mrLinePolygon( rLinePolygon
),
1782 mrViewState( rViewState
)
1786 // TextRenderer interface
1787 virtual bool operator()( const rendering::RenderState
& rRenderState
) const
1789 rendering::StrokeAttributes aStrokeAttributes
;
1791 aStrokeAttributes
.StrokeWidth
= mnOutlineWidth
;
1792 aStrokeAttributes
.MiterLimit
= 1.0;
1793 aStrokeAttributes
.StartCapType
= rendering::PathCapType::BUTT
;
1794 aStrokeAttributes
.EndCapType
= rendering::PathCapType::BUTT
;
1795 aStrokeAttributes
.JoinType
= rendering::PathJoinType::MITER
;
1797 rendering::RenderState
aLocalState( rRenderState
);
1798 aLocalState
.DeviceColor
= maFillColor
;
1800 // TODO(P1): implement caching
1802 // background of text
1803 mrCanvas
->fillPolyPolygon( mrTextPolygon
,
1807 // border line of text
1808 mrCanvas
->strokePolyPolygon( mrTextPolygon
,
1811 aStrokeAttributes
);
1813 // underlines/strikethrough - background
1814 mrCanvas
->fillPolyPolygon( mrLinePolygon
,
1817 // underlines/strikethrough - border
1818 mrCanvas
->strokePolyPolygon( mrLinePolygon
,
1821 aStrokeAttributes
);
1827 const uno::Sequence
< double > maFillColor
;
1828 double mnOutlineWidth
;
1829 const uno::Reference
< rendering::XCanvas
>& mrCanvas
;
1830 const uno::Reference
< rendering::XPolyPolygon2D
>& mrTextPolygon
;
1831 const uno::Reference
< rendering::XPolyPolygon2D
>& mrLinePolygon
;
1832 const rendering::ViewState
& mrViewState
;
1836 bool OutlineAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
1837 const Subset
& rSubset
) const
1839 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::OutlineAction::renderSubset()" );
1840 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::OutlineAction: 0x" << std::hex
<< this );
1842 if( rSubset
.mnSubsetBegin
== rSubset
.mnSubsetEnd
)
1843 return true; // empty range, render nothing
1846 // TODO(F3): Subsetting NYI for outline text!
1847 return render( rTransformation
);
1849 const rendering::StringContext
rOrigContext( mxTextLayout
->getText() );
1851 if( rSubset
.mnSubsetBegin
== 0 &&
1852 rSubset
.mnSubsetEnd
== rOrigContext
.Length
)
1854 // full range, no need for subsetting
1855 return render( rTransformation
);
1858 rendering::RenderState
aLocalState( maState
);
1859 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1862 // create and setup local Text polygon
1863 // ===================================
1865 uno::Reference
< rendering::XPolyPolygon2D
> xTextPolygon();
1867 // TODO(P3): Provide an API method for that!
1869 if( !xTextLayout
.is() )
1872 // render everything
1873 // =================
1875 return renderEffectText(
1876 OutlineTextArrayRenderHelper(
1892 ::basegfx::B2DRange
OutlineAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
1894 rendering::RenderState
aLocalState( maState
);
1895 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
1897 return calcEffectTextBounds( maOutlineBounds
,
1898 ::basegfx::B2DRange( 0,0,
1899 maLinesOverallSize
.getX(),
1900 maLinesOverallSize
.getY() ),
1904 mpCanvas
->getViewState() );
1907 ::basegfx::B2DRange
OutlineAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
1908 const Subset
& /*rSubset*/ ) const
1910 SAL_WARN( "cppcanvas.emf", "OutlineAction::getBounds(): Subset not yet supported by this object" );
1912 return getBounds( rTransformation
);
1915 sal_Int32
OutlineAction::getActionCount() const
1917 // TODO(F3): Subsetting NYI for outline text!
1918 return maOffsets
.getLength();
1924 // Action factory methods
1928 /** Create an outline action
1930 This method extracts the polygonal outline from the
1931 text, and creates a properly setup OutlineAction from
1934 ActionSharedPtr
createOutline( const ::basegfx::B2DPoint
& rStartPoint
,
1935 const ::basegfx::B2DSize
& rReliefOffset
,
1936 const ::Color
& rReliefColor
,
1937 const ::basegfx::B2DSize
& rShadowOffset
,
1938 const ::Color
& rShadowColor
,
1939 const OUString
& rText
,
1940 sal_Int32 nStartPos
,
1942 const long* pDXArray
,
1943 VirtualDevice
& rVDev
,
1944 const CanvasSharedPtr
& rCanvas
,
1945 const OutDevState
& rState
,
1946 const Renderer::Parameters
& rParms
)
1948 // operate on raw DX array here (in logical coordinate
1949 // system), to have a higher resolution
1950 // PolyPolygon. That polygon is then converted to
1951 // device coordinate system.
1953 // #i68512# Temporarily switch off font rotation
1954 // (which is already contained in the render state
1955 // transformation matrix - otherwise, glyph polygons
1956 // will be rotated twice)
1957 const vcl::Font
aOrigFont( rVDev
.GetFont() );
1958 vcl::Font
aUnrotatedFont( aOrigFont
);
1959 aUnrotatedFont
.SetOrientation(0);
1960 rVDev
.SetFont( aUnrotatedFont
);
1962 // TODO(F3): Don't understand parameter semantics of
1963 // GetTextOutlines()
1964 ::basegfx::B2DPolyPolygon aResultingPolyPolygon
;
1965 PolyPolyVector aVCLPolyPolyVector
;
1966 const bool bHaveOutlines( rVDev
.GetTextOutlines( aVCLPolyPolyVector
, rText
,
1967 static_cast<sal_uInt16
>(nStartPos
),
1968 static_cast<sal_uInt16
>(nStartPos
),
1969 static_cast<sal_uInt16
>(nLen
),
1970 true, 0, pDXArray
) );
1971 rVDev
.SetFont(aOrigFont
);
1973 if( !bHaveOutlines
)
1974 return ActionSharedPtr();
1976 ::std::vector
< sal_Int32
> aPolygonGlyphMap
;
1978 // first glyph starts at polygon index 0
1979 aPolygonGlyphMap
.push_back( 0 );
1981 // remove offsetting from mapmode transformation
1982 // (outline polygons must stay at origin, only need to
1984 ::basegfx::B2DHomMatrix
aMapModeTransform(
1985 rState
.mapModeTransform
);
1986 aMapModeTransform
.set(0,2, 0.0);
1987 aMapModeTransform
.set(1,2, 0.0);
1989 PolyPolyVector::const_iterator
aIter( aVCLPolyPolyVector
.begin() );
1990 const PolyPolyVector::const_iterator
aEnd( aVCLPolyPolyVector
.end() );
1991 for( ; aIter
!= aEnd
; ++aIter
)
1993 ::basegfx::B2DPolyPolygon aPolyPolygon
;
1995 aPolyPolygon
= aIter
->getB2DPolyPolygon();
1996 aPolyPolygon
.transform( aMapModeTransform
);
1998 // append result to collecting polypoly
1999 for( sal_uInt32 i
=0; i
<aPolyPolygon
.count(); ++i
)
2001 // #i47795# Ensure closed polygons (since
2002 // FreeType returns the glyph outlines
2004 const ::basegfx::B2DPolygon
& rPoly( aPolyPolygon
.getB2DPolygon( i
) );
2005 const sal_uInt32
nCount( rPoly
.count() );
2009 // polygon either degenerate, or
2011 aResultingPolyPolygon
.append( rPoly
);
2015 ::basegfx::B2DPolygon
aPoly(rPoly
);
2016 aPoly
.setClosed(true);
2018 aResultingPolyPolygon
.append( aPoly
);
2022 // TODO(F3): Depending on the semantics of
2023 // GetTextOutlines(), this here is wrong!
2025 // calc next glyph index
2026 aPolygonGlyphMap
.push_back( aResultingPolyPolygon
.count() );
2029 const uno::Sequence
< double > aCharWidthSeq(
2031 setupDXArray( pDXArray
, nLen
, rState
) :
2032 setupDXArray( rText
,
2037 const uno::Reference
< rendering::XPolyPolygon2D
> xTextPoly(
2038 ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
2039 rCanvas
->getUNOCanvas()->getDevice(),
2040 aResultingPolyPolygon
) );
2042 if( rParms
.maTextTransformation
.is_initialized() )
2044 return ActionSharedPtr(
2051 ::basegfx::tools::getRange(aResultingPolyPolygon
),
2058 *rParms
.maTextTransformation
) );
2062 return ActionSharedPtr(
2069 ::basegfx::tools::getRange(aResultingPolyPolygon
),
2084 ActionSharedPtr
TextActionFactory::createTextAction( const ::Point
& rStartPoint
,
2085 const ::Size
& rReliefOffset
,
2086 const ::Color
& rReliefColor
,
2087 const ::Size
& rShadowOffset
,
2088 const ::Color
& rShadowColor
,
2089 const OUString
& rText
,
2090 sal_Int32 nStartPos
,
2092 const long* pDXArray
,
2093 VirtualDevice
& rVDev
,
2094 const CanvasSharedPtr
& rCanvas
,
2095 const OutDevState
& rState
,
2096 const Renderer::Parameters
& rParms
,
2099 const ::Size
aBaselineOffset( tools::getBaselineOffset( rState
,
2101 // #143885# maintain (nearly) full precision positioning,
2102 // by circumventing integer-based OutDev-mapping
2103 const ::basegfx::B2DPoint
aStartPoint(
2104 rState
.mapModeTransform
*
2105 ::basegfx::B2DPoint(rStartPoint
.X() + aBaselineOffset
.Width(),
2106 rStartPoint
.Y() + aBaselineOffset
.Height()) );
2108 const ::basegfx::B2DSize
aReliefOffset(
2109 rState
.mapModeTransform
* vcl::unotools::b2DSizeFromSize( rReliefOffset
) );
2110 const ::basegfx::B2DSize
aShadowOffset(
2111 rState
.mapModeTransform
* vcl::unotools::b2DSizeFromSize( rShadowOffset
) );
2113 if( rState
.isTextOutlineModeSet
)
2115 return createOutline(
2131 // convert DX array to device coordinate system (and
2132 // create it in the first place, if pDXArray is NULL)
2133 const uno::Sequence
< double > aCharWidths(
2135 setupDXArray( pDXArray
, nLen
, rState
) :
2136 setupDXArray( rText
,
2142 // determine type of text action to create
2143 // =======================================
2145 const ::Color
aEmptyColor( COL_AUTO
);
2147 ActionSharedPtr ret
;
2149 // no DX array, and no need to subset - no need to store
2151 if( !pDXArray
&& !bSubsettable
)
2154 if( !rState
.textOverlineStyle
&&
2155 !rState
.textUnderlineStyle
&&
2156 !rState
.textStrikeoutStyle
&&
2157 rReliefColor
== aEmptyColor
&&
2158 rShadowColor
== aEmptyColor
)
2161 if( rParms
.maTextTransformation
.is_initialized() )
2163 ret
= ActionSharedPtr( new TextAction(
2170 *rParms
.maTextTransformation
) );
2174 ret
= ActionSharedPtr( new TextAction(
2185 // at least one of the effects requested
2186 if( rParms
.maTextTransformation
.is_initialized() )
2187 ret
= ActionSharedPtr( new EffectTextAction(
2199 *rParms
.maTextTransformation
) );
2201 ret
= ActionSharedPtr( new EffectTextAction(
2217 // DX array necessary - any effects?
2218 if( !rState
.textOverlineStyle
&&
2219 !rState
.textUnderlineStyle
&&
2220 !rState
.textStrikeoutStyle
&&
2221 rReliefColor
== aEmptyColor
&&
2222 rShadowColor
== aEmptyColor
)
2225 if( rParms
.maTextTransformation
.is_initialized() )
2226 ret
= ActionSharedPtr( new TextArrayAction(
2234 *rParms
.maTextTransformation
) );
2236 ret
= ActionSharedPtr( new TextArrayAction(
2247 // at least one of the effects requested
2248 if( rParms
.maTextTransformation
.is_initialized() )
2249 ret
= ActionSharedPtr( new EffectTextArrayAction(
2262 *rParms
.maTextTransformation
) );
2264 ret
= ActionSharedPtr( new EffectTextArrayAction(
2284 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */