Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : #include <canvas/debug.hxx>
22 : #include <tools/diagnose_ex.h>
23 : #include <canvas/verbosetrace.hxx>
24 : #include <com/sun/star/rendering/RenderState.hpp>
25 : #include <com/sun/star/rendering/XCanvas.hpp>
26 : #include <basegfx/numeric/ftools.hxx>
27 : #include <basegfx/tools/canvastools.hxx>
28 : #include <basegfx/polygon/b2dpolygontools.hxx>
29 : #include <basegfx/polygon/b2dpolygon.hxx>
30 : #include <basegfx/range/b2drectangle.hxx>
31 : #include <basegfx/vector/b2dvector.hxx>
32 : #include <canvas/canvastools.hxx>
33 : #include <vcl/gdimtf.hxx>
34 : #include <vcl/metaact.hxx>
35 : #include <vcl/virdev.hxx>
36 : #include <vcl/metric.hxx>
37 : #include <tools/poly.hxx>
38 : #include "mtftools.hxx"
39 : #include "outdevstate.hxx"
40 : #include "polypolyaction.hxx"
41 : #include <basegfx/matrix/b2dhommatrixtools.hxx>
42 :
43 :
44 :
45 : using namespace ::com::sun::star;
46 :
47 : namespace cppcanvas
48 : {
49 : namespace tools
50 : {
51 0 : void initRenderState( rendering::RenderState& renderState,
52 : const ::cppcanvas::internal::OutDevState& outdevState )
53 : {
54 0 : ::canvas::tools::initRenderState( renderState );
55 : ::canvas::tools::setRenderStateTransform( renderState,
56 0 : outdevState.transform );
57 0 : renderState.Clip = outdevState.xClipPoly;
58 0 : }
59 :
60 0 : ::Size getBaselineOffset( const ::cppcanvas::internal::OutDevState& outdevState,
61 : const VirtualDevice& rVDev )
62 : {
63 0 : const ::FontMetric& aMetric = rVDev.GetFontMetric();
64 :
65 : // calc offset for text output, the XCanvas always renders
66 : // baseline offset.
67 0 : switch( outdevState.textReferencePoint )
68 : {
69 : case ALIGN_TOP:
70 : return ::Size( 0,
71 0 : aMetric.GetIntLeading() + aMetric.GetAscent() );
72 :
73 : default:
74 0 : ENSURE_OR_THROW( false,
75 : "tools::getBaselineOffset(): Unexpected TextAlign value" );
76 : // FALLTHROUGH intended (to calm compiler warning - case won't happen)
77 : case ALIGN_BASELINE:
78 0 : return ::Size( 0, 0 );
79 :
80 : case ALIGN_BOTTOM:
81 : return ::Size( 0,
82 0 : -aMetric.GetDescent() );
83 :
84 0 : }
85 : }
86 :
87 0 : ::basegfx::B2DHomMatrix& calcLogic2PixelLinearTransform( ::basegfx::B2DHomMatrix& o_rMatrix,
88 : const VirtualDevice& rVDev )
89 : {
90 : // select size value in the middle of the available range,
91 : // to have headroom both when map mode scales up, and when
92 : // it scales down.
93 : const ::Size aSizeLogic( 0x00010000L,
94 0 : 0x00010000L );
95 :
96 0 : const ::Size aSizePixel( rVDev.LogicToPixel( aSizeLogic ) );
97 :
98 : o_rMatrix = basegfx::tools::createScaleB2DHomMatrix(
99 0 : aSizePixel.Width() / (double)aSizeLogic.Width(),
100 0 : aSizePixel.Height() / (double)aSizeLogic.Height() );
101 :
102 0 : return o_rMatrix;
103 : }
104 :
105 0 : ::basegfx::B2DHomMatrix& calcLogic2PixelAffineTransform( ::basegfx::B2DHomMatrix& o_rMatrix,
106 : const VirtualDevice& rVDev )
107 : {
108 : // retrieves scale
109 0 : calcLogic2PixelLinearTransform(o_rMatrix, rVDev);
110 :
111 : // translate according to curr map mode/pref map mode offset
112 0 : const ::Point aEmptyPoint;
113 : const ::Point& rTranslatedPoint(
114 0 : rVDev.LogicToPixel( aEmptyPoint ));
115 :
116 0 : o_rMatrix.translate(rTranslatedPoint.X(),
117 0 : rTranslatedPoint.Y());
118 :
119 0 : return o_rMatrix;
120 : }
121 :
122 0 : bool modifyClip( rendering::RenderState& o_rRenderState,
123 : const struct ::cppcanvas::internal::OutDevState& rOutdevState,
124 : const CanvasSharedPtr& rCanvas,
125 : const ::basegfx::B2DPoint& rOffset,
126 : const ::basegfx::B2DVector* pScaling,
127 : const double* pRotation )
128 : {
129 0 : const ::Point aEmptyPoint;
130 :
131 0 : const bool bOffsetting( !rOffset.equalZero() );
132 : const bool bScaling( pScaling &&
133 0 : pScaling->getX() != 1.0 &&
134 0 : pScaling->getY() != 1.0 );
135 : const bool bRotation( pRotation &&
136 0 : *pRotation != 0.0 );
137 :
138 0 : if( !bOffsetting && !bScaling && !bRotation )
139 0 : return false; // nothing to do
140 :
141 0 : if( rOutdevState.clip.count() )
142 : {
143 : // general polygon case
144 :
145 0 : ::basegfx::B2DPolyPolygon aLocalClip( rOutdevState.clip );
146 0 : ::basegfx::B2DHomMatrix aTransform;
147 :
148 0 : if( bOffsetting )
149 0 : aTransform.translate( -rOffset.getX(),
150 0 : -rOffset.getY() );
151 0 : if( bScaling )
152 0 : aTransform.scale( 1.0/pScaling->getX(), 1.0/pScaling->getY() );
153 :
154 0 : if( bRotation )
155 0 : aTransform.rotate( - *pRotation );
156 :
157 0 : aLocalClip.transform( aTransform );
158 :
159 : o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
160 0 : rCanvas->getUNOCanvas()->getDevice(),
161 0 : aLocalClip );
162 :
163 0 : return true;
164 : }
165 0 : else if( !rOutdevState.clipRect.IsEmpty() )
166 : {
167 : // simple rect case
168 :
169 0 : const ::Rectangle aLocalClipRect( rOutdevState.clipRect );
170 :
171 0 : if( bRotation )
172 : {
173 : // rotation involved - convert to polygon first,
174 : // then transform that
175 : ::basegfx::B2DPolygon aLocalClip(
176 : ::basegfx::tools::createPolygonFromRect(
177 : ::basegfx::B2DRectangle(
178 0 : (double)(aLocalClipRect.Left()),
179 0 : (double)(aLocalClipRect.Top()),
180 0 : (double)(aLocalClipRect.Right()),
181 0 : (double)(aLocalClipRect.Bottom()) ) ) );
182 0 : ::basegfx::B2DHomMatrix aTransform;
183 :
184 0 : if( bOffsetting )
185 0 : aTransform.translate( -rOffset.getX(),
186 0 : -rOffset.getY() );
187 0 : if( bScaling )
188 0 : aTransform.scale( 1.0/pScaling->getX(), 1.0/pScaling->getY() );
189 :
190 0 : aTransform.rotate( - *pRotation );
191 :
192 0 : aLocalClip.transform( aTransform );
193 :
194 : o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
195 0 : rCanvas->getUNOCanvas()->getDevice(),
196 0 : ::basegfx::B2DPolyPolygon( aLocalClip ) );
197 : }
198 0 : else if( bScaling )
199 : {
200 : // scale and offset - do it on the fly, have to
201 : // convert to float anyway.
202 : o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
203 0 : rCanvas->getUNOCanvas()->getDevice(),
204 : ::basegfx::B2DPolyPolygon(
205 : ::basegfx::tools::createPolygonFromRect(
206 : ::basegfx::B2DRectangle(
207 0 : (double)(aLocalClipRect.Left() - rOffset.getX())/pScaling->getX(),
208 0 : (double)(aLocalClipRect.Top() - rOffset.getY())/pScaling->getY(),
209 0 : (double)(aLocalClipRect.Right() - rOffset.getX())/pScaling->getX(),
210 0 : (double)(aLocalClipRect.Bottom() - rOffset.getY())/pScaling->getY() ) ) ) );
211 : }
212 : else
213 : {
214 : // offset only - do it on the fly, have to convert
215 : // to float anyway.
216 : o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
217 0 : rCanvas->getUNOCanvas()->getDevice(),
218 : ::basegfx::B2DPolyPolygon(
219 : ::basegfx::tools::createPolygonFromRect(
220 0 : ::basegfx::B2DRectangle( aLocalClipRect.Left() - rOffset.getX(),
221 0 : aLocalClipRect.Top() - rOffset.getY(),
222 0 : aLocalClipRect.Right() - rOffset.getX(),
223 0 : aLocalClipRect.Bottom() - rOffset.getY() ) ) ) );
224 : }
225 :
226 0 : return true;
227 : }
228 :
229 : // empty clip, nothing to do
230 0 : return false;
231 : }
232 :
233 : // create overline/underline/strikeout line info struct
234 0 : TextLineInfo createTextLineInfo( const ::VirtualDevice& rVDev,
235 : const ::cppcanvas::internal::OutDevState& rState )
236 : {
237 0 : const sal_Bool bOldMode( rVDev.IsMapModeEnabled() );
238 :
239 : // #i68512# Force metric regeneration with mapmode enabled
240 : // (prolly OutDev bug)
241 0 : rVDev.GetFontMetric();
242 :
243 : // will restore map mode below
244 0 : const_cast< ::VirtualDevice& >(rVDev).EnableMapMode( sal_False );
245 :
246 0 : const ::FontMetric aMetric = rVDev.GetFontMetric();
247 :
248 : TextLineInfo aTextInfo(
249 0 : (aMetric.GetDescent() + 2) / 4.0,
250 0 : ((aMetric.GetIntLeading() + 1.5) / 3.0),
251 0 : (aMetric.GetIntLeading() / 2.0) - aMetric.GetAscent(),
252 0 : aMetric.GetDescent() / 2.0,
253 0 : (aMetric.GetIntLeading() - aMetric.GetAscent()) / 3.0,
254 : rState.textOverlineStyle,
255 : rState.textUnderlineStyle,
256 0 : rState.textStrikeoutStyle );
257 :
258 0 : const_cast< ::VirtualDevice& >(rVDev).EnableMapMode( bOldMode );
259 :
260 0 : return aTextInfo;
261 : }
262 :
263 : namespace
264 : {
265 0 : void appendRect( ::basegfx::B2DPolyPolygon& o_rPoly,
266 : const ::basegfx::B2DPoint& rStartPos,
267 : const double nX1,
268 : const double nY1,
269 : const double nX2,
270 : const double nY2 )
271 : {
272 0 : const double x( rStartPos.getX() );
273 0 : const double y( rStartPos.getY() );
274 :
275 : o_rPoly.append(
276 : ::basegfx::tools::createPolygonFromRect(
277 0 : ::basegfx::B2DRectangle( x + nX1, y + nY1, x + nX2, y + nY2 ) ) );
278 0 : }
279 :
280 0 : void appendRect( ::basegfx::B2DPolyPolygon& o_rPoly,
281 : const double nX1,
282 : const double nY1,
283 : const double nX2,
284 : const double nY2 )
285 : {
286 : o_rPoly.append(
287 : ::basegfx::tools::createPolygonFromRect(
288 0 : ::basegfx::B2DRectangle( nX1, nY1, nX2, nY2 ) ) );
289 0 : }
290 :
291 0 : void appendDashes( ::basegfx::B2DPolyPolygon& o_rPoly,
292 : const double nX,
293 : const double nY,
294 : const double nLineWidth,
295 : const double nLineHeight,
296 : const double nDashWidth,
297 : const double nDashSkip )
298 : {
299 : const sal_Int32 nNumLoops(
300 : static_cast< sal_Int32 >(
301 : ::std::max( 1.0,
302 0 : nLineWidth / nDashSkip ) + .5) );
303 :
304 0 : double x = nX;
305 0 : for( sal_Int32 i=0; i<nNumLoops; ++i )
306 : {
307 : appendRect( o_rPoly,
308 : x, nY,
309 0 : x + nDashWidth, nY + nLineHeight );
310 :
311 0 : x += nDashSkip;
312 : }
313 0 : }
314 : }
315 :
316 : // create line actions for text such as underline and
317 : // strikeout
318 0 : ::basegfx::B2DPolyPolygon createTextLinesPolyPolygon( const ::basegfx::B2DPoint rStartPos,
319 : const double& rLineWidth,
320 : const TextLineInfo& rTextLineInfo )
321 : {
322 : // fill the polypolygon with all text lines
323 0 : ::basegfx::B2DPolyPolygon aTextLinesPolyPoly;
324 :
325 0 : switch( rTextLineInfo.mnOverlineStyle )
326 : {
327 : case UNDERLINE_NONE: // nothing to do
328 : // FALLTHROUGH intended
329 : case UNDERLINE_DONTKNOW:
330 0 : break;
331 :
332 : case UNDERLINE_SMALLWAVE: // TODO(F3): NYI
333 : // FALLTHROUGH intended
334 : case UNDERLINE_WAVE: // TODO(F3): NYI
335 : // FALLTHROUGH intended
336 : case UNDERLINE_SINGLE:
337 : appendRect(
338 : aTextLinesPolyPoly,
339 : rStartPos,
340 : 0,
341 : rTextLineInfo.mnOverlineOffset,
342 : rLineWidth,
343 0 : rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight );
344 0 : break;
345 :
346 : case UNDERLINE_BOLDDOTTED: // TODO(F3): NYI
347 : // FALLTHROUGH intended
348 : case UNDERLINE_BOLDDASH: // TODO(F3): NYI
349 : // FALLTHROUGH intended
350 : case UNDERLINE_BOLDLONGDASH: // TODO(F3): NYI
351 : // FALLTHROUGH intended
352 : case UNDERLINE_BOLDDASHDOT: // TODO(F3): NYI
353 : // FALLTHROUGH intended
354 : case UNDERLINE_BOLDDASHDOTDOT:// TODO(F3): NYI
355 : // FALLTHROUGH intended
356 : case UNDERLINE_BOLDWAVE: // TODO(F3): NYI
357 : // FALLTHROUGH intended
358 : case UNDERLINE_BOLD:
359 : appendRect(
360 : aTextLinesPolyPoly,
361 : rStartPos,
362 : 0,
363 : rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight,
364 : rLineWidth,
365 0 : rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight );
366 0 : break;
367 :
368 : case UNDERLINE_DOUBLEWAVE: // TODO(F3): NYI
369 : // FALLTHROUGH intended
370 : case UNDERLINE_DOUBLE:
371 : appendRect(
372 : aTextLinesPolyPoly,
373 : rStartPos,
374 : 0,
375 : rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight * 2.0 ,
376 : rLineWidth,
377 0 : rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight );
378 :
379 : appendRect(
380 : aTextLinesPolyPoly,
381 : rStartPos,
382 : 0,
383 : rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight,
384 : rLineWidth,
385 0 : rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight * 2.0 );
386 0 : break;
387 :
388 : case UNDERLINE_DASHDOTDOT: // TODO(F3): NYI
389 : // FALLTHROUGH intended
390 : case UNDERLINE_DOTTED:
391 : appendDashes(
392 : aTextLinesPolyPoly,
393 : rStartPos.getX(),
394 0 : rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
395 : rLineWidth,
396 : rTextLineInfo.mnOverlineHeight,
397 : rTextLineInfo.mnOverlineHeight,
398 0 : 2*rTextLineInfo.mnOverlineHeight );
399 0 : break;
400 :
401 : case UNDERLINE_DASHDOT: // TODO(F3): NYI
402 : // FALLTHROUGH intended
403 : case UNDERLINE_DASH:
404 : appendDashes(
405 : aTextLinesPolyPoly,
406 : rStartPos.getX(),
407 0 : rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
408 : rLineWidth,
409 : rTextLineInfo.mnOverlineHeight,
410 : 3*rTextLineInfo.mnOverlineHeight,
411 0 : 6*rTextLineInfo.mnOverlineHeight );
412 0 : break;
413 :
414 : case UNDERLINE_LONGDASH:
415 : appendDashes(
416 : aTextLinesPolyPoly,
417 : rStartPos.getX(),
418 0 : rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
419 : rLineWidth,
420 : rTextLineInfo.mnOverlineHeight,
421 : 6*rTextLineInfo.mnOverlineHeight,
422 0 : 12*rTextLineInfo.mnOverlineHeight );
423 0 : break;
424 :
425 : default:
426 0 : ENSURE_OR_THROW( false,
427 : "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected overline case" );
428 : }
429 :
430 0 : switch( rTextLineInfo.mnUnderlineStyle )
431 : {
432 : case UNDERLINE_NONE: // nothing to do
433 : // FALLTHROUGH intended
434 : case UNDERLINE_DONTKNOW:
435 0 : break;
436 :
437 : case UNDERLINE_SMALLWAVE: // TODO(F3): NYI
438 : // FALLTHROUGH intended
439 : case UNDERLINE_WAVE: // TODO(F3): NYI
440 : // FALLTHROUGH intended
441 : case UNDERLINE_SINGLE:
442 : appendRect(
443 : aTextLinesPolyPoly,
444 : rStartPos,
445 : 0,
446 : rTextLineInfo.mnUnderlineOffset,
447 : rLineWidth,
448 0 : rTextLineInfo.mnUnderlineOffset + rTextLineInfo.mnLineHeight );
449 0 : break;
450 :
451 : case UNDERLINE_BOLDDOTTED: // TODO(F3): NYI
452 : // FALLTHROUGH intended
453 : case UNDERLINE_BOLDDASH: // TODO(F3): NYI
454 : // FALLTHROUGH intended
455 : case UNDERLINE_BOLDLONGDASH: // TODO(F3): NYI
456 : // FALLTHROUGH intended
457 : case UNDERLINE_BOLDDASHDOT: // TODO(F3): NYI
458 : // FALLTHROUGH intended
459 : case UNDERLINE_BOLDDASHDOTDOT:// TODO(F3): NYI
460 : // FALLTHROUGH intended
461 : case UNDERLINE_BOLDWAVE: // TODO(F3): NYI
462 : // FALLTHROUGH intended
463 : case UNDERLINE_BOLD:
464 : appendRect(
465 : aTextLinesPolyPoly,
466 : rStartPos,
467 : 0,
468 : rTextLineInfo.mnUnderlineOffset,
469 : rLineWidth,
470 0 : rTextLineInfo.mnUnderlineOffset + 2*rTextLineInfo.mnLineHeight );
471 0 : break;
472 :
473 : case UNDERLINE_DOUBLEWAVE: // TODO(F3): NYI
474 : // FALLTHROUGH intended
475 : case UNDERLINE_DOUBLE:
476 : appendRect(
477 : aTextLinesPolyPoly,
478 : rStartPos,
479 : 0,
480 : rTextLineInfo.mnUnderlineOffset - rTextLineInfo.mnLineHeight,
481 : rLineWidth,
482 0 : rTextLineInfo.mnUnderlineOffset );
483 :
484 : appendRect(
485 : aTextLinesPolyPoly,
486 : rStartPos,
487 : 0,
488 : rTextLineInfo.mnUnderlineOffset + 2*rTextLineInfo.mnLineHeight,
489 : rLineWidth,
490 0 : rTextLineInfo.mnUnderlineOffset + 3*rTextLineInfo.mnLineHeight );
491 0 : break;
492 :
493 : case UNDERLINE_DASHDOTDOT: // TODO(F3): NYI
494 : // FALLTHROUGH intended
495 : case UNDERLINE_DOTTED:
496 : appendDashes(
497 : aTextLinesPolyPoly,
498 : rStartPos.getX(),
499 0 : rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
500 : rLineWidth,
501 : rTextLineInfo.mnLineHeight,
502 : rTextLineInfo.mnLineHeight,
503 0 : 2*rTextLineInfo.mnLineHeight );
504 0 : break;
505 :
506 : case UNDERLINE_DASHDOT: // TODO(F3): NYI
507 : // FALLTHROUGH intended
508 : case UNDERLINE_DASH:
509 : appendDashes(
510 : aTextLinesPolyPoly,
511 : rStartPos.getX(),
512 0 : rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
513 : rLineWidth,
514 : rTextLineInfo.mnLineHeight,
515 : 3*rTextLineInfo.mnLineHeight,
516 0 : 6*rTextLineInfo.mnLineHeight );
517 0 : break;
518 :
519 : case UNDERLINE_LONGDASH:
520 : appendDashes(
521 : aTextLinesPolyPoly,
522 : rStartPos.getX(),
523 0 : rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
524 : rLineWidth,
525 : rTextLineInfo.mnLineHeight,
526 : 6*rTextLineInfo.mnLineHeight,
527 0 : 12*rTextLineInfo.mnLineHeight );
528 0 : break;
529 :
530 : default:
531 0 : ENSURE_OR_THROW( false,
532 : "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected underline case" );
533 : }
534 :
535 0 : switch( rTextLineInfo.mnStrikeoutStyle )
536 : {
537 : case STRIKEOUT_NONE: // nothing to do
538 : // FALLTHROUGH intended
539 : case STRIKEOUT_DONTKNOW:
540 0 : break;
541 :
542 : case STRIKEOUT_SLASH: // TODO(Q1): we should handle this in the text layer
543 : // FALLTHROUGH intended
544 : case STRIKEOUT_X:
545 0 : break;
546 :
547 : case STRIKEOUT_SINGLE:
548 : appendRect(
549 : aTextLinesPolyPoly,
550 : rStartPos,
551 : 0,
552 : rTextLineInfo.mnStrikeoutOffset,
553 : rLineWidth,
554 0 : rTextLineInfo.mnStrikeoutOffset + rTextLineInfo.mnLineHeight );
555 0 : break;
556 :
557 : case STRIKEOUT_BOLD:
558 : appendRect(
559 : aTextLinesPolyPoly,
560 : rStartPos,
561 : 0,
562 : rTextLineInfo.mnStrikeoutOffset,
563 : rLineWidth,
564 0 : rTextLineInfo.mnStrikeoutOffset + 2*rTextLineInfo.mnLineHeight );
565 0 : break;
566 :
567 : case STRIKEOUT_DOUBLE:
568 : appendRect(
569 : aTextLinesPolyPoly,
570 : rStartPos,
571 : 0,
572 : rTextLineInfo.mnStrikeoutOffset - rTextLineInfo.mnLineHeight,
573 : rLineWidth,
574 0 : rTextLineInfo.mnStrikeoutOffset );
575 :
576 : appendRect(
577 : aTextLinesPolyPoly,
578 : rStartPos,
579 : 0,
580 : rTextLineInfo.mnStrikeoutOffset + 2*rTextLineInfo.mnLineHeight,
581 : rLineWidth,
582 0 : rTextLineInfo.mnStrikeoutOffset + 3*rTextLineInfo.mnLineHeight );
583 0 : break;
584 :
585 : default:
586 0 : ENSURE_OR_THROW( false,
587 : "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected strikeout case" );
588 : }
589 :
590 0 : return aTextLinesPolyPoly;
591 : }
592 :
593 0 : ::basegfx::B2DRange calcDevicePixelBounds( const ::basegfx::B2DRange& rBounds,
594 : const rendering::ViewState& viewState,
595 : const rendering::RenderState& renderState )
596 : {
597 0 : ::basegfx::B2DHomMatrix aTransform;
598 : ::canvas::tools::mergeViewAndRenderTransform( aTransform,
599 : viewState,
600 0 : renderState );
601 :
602 0 : ::basegfx::B2DRange aTransformedBounds;
603 : return ::canvas::tools::calcTransformedRectBounds( aTransformedBounds,
604 : rBounds,
605 0 : aTransform );
606 : }
607 :
608 : // create line actions for text such as underline and
609 : // strikeout
610 0 : ::basegfx::B2DPolyPolygon createTextLinesPolyPolygon( const double& rStartOffset,
611 : const double& rLineWidth,
612 : const TextLineInfo& rTextLineInfo )
613 : {
614 : return createTextLinesPolyPolygon(
615 : ::basegfx::B2DPoint( rStartOffset,
616 : 0.0 ),
617 : rLineWidth,
618 0 : rTextLineInfo );
619 : }
620 : }
621 : }
622 :
623 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|