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 0 : 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 bool bOffsetting( !rOffset.equalZero() );
130 0 : const bool bScaling( pScaling &&
131 0 : pScaling->getX() != 1.0 &&
132 0 : pScaling->getY() != 1.0 );
133 0 : const bool bRotation( pRotation &&
134 0 : *pRotation != 0.0 );
135 :
136 0 : if( !bOffsetting && !bScaling && !bRotation )
137 0 : return false; // nothing to do
138 :
139 0 : if( rOutdevState.clip.count() )
140 : {
141 : // general polygon case
142 :
143 0 : ::basegfx::B2DPolyPolygon aLocalClip( rOutdevState.clip );
144 0 : ::basegfx::B2DHomMatrix aTransform;
145 :
146 0 : if( bOffsetting )
147 0 : aTransform.translate( -rOffset.getX(),
148 0 : -rOffset.getY() );
149 0 : if( bScaling )
150 0 : aTransform.scale( 1.0/pScaling->getX(), 1.0/pScaling->getY() );
151 :
152 0 : if( bRotation )
153 0 : aTransform.rotate( - *pRotation );
154 :
155 0 : aLocalClip.transform( aTransform );
156 :
157 0 : o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
158 0 : rCanvas->getUNOCanvas()->getDevice(),
159 0 : aLocalClip );
160 :
161 0 : return true;
162 : }
163 0 : else if( !rOutdevState.clipRect.IsEmpty() )
164 : {
165 : // simple rect case
166 :
167 0 : const ::Rectangle aLocalClipRect( rOutdevState.clipRect );
168 :
169 0 : if( bRotation )
170 : {
171 : // rotation involved - convert to polygon first,
172 : // then transform that
173 : ::basegfx::B2DPolygon aLocalClip(
174 : ::basegfx::tools::createPolygonFromRect(
175 : ::basegfx::B2DRectangle(
176 0 : (double)(aLocalClipRect.Left()),
177 0 : (double)(aLocalClipRect.Top()),
178 0 : (double)(aLocalClipRect.Right()),
179 0 : (double)(aLocalClipRect.Bottom()) ) ) );
180 0 : ::basegfx::B2DHomMatrix aTransform;
181 :
182 0 : if( bOffsetting )
183 0 : aTransform.translate( -rOffset.getX(),
184 0 : -rOffset.getY() );
185 0 : if( bScaling )
186 0 : aTransform.scale( 1.0/pScaling->getX(), 1.0/pScaling->getY() );
187 :
188 0 : aTransform.rotate( - *pRotation );
189 :
190 0 : aLocalClip.transform( aTransform );
191 :
192 0 : o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
193 0 : rCanvas->getUNOCanvas()->getDevice(),
194 0 : ::basegfx::B2DPolyPolygon( aLocalClip ) );
195 : }
196 0 : else if( bScaling )
197 : {
198 : // scale and offset - do it on the fly, have to
199 : // convert to float anyway.
200 0 : o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
201 0 : rCanvas->getUNOCanvas()->getDevice(),
202 : ::basegfx::B2DPolyPolygon(
203 : ::basegfx::tools::createPolygonFromRect(
204 : ::basegfx::B2DRectangle(
205 0 : (double)(aLocalClipRect.Left() - rOffset.getX())/pScaling->getX(),
206 0 : (double)(aLocalClipRect.Top() - rOffset.getY())/pScaling->getY(),
207 0 : (double)(aLocalClipRect.Right() - rOffset.getX())/pScaling->getX(),
208 0 : (double)(aLocalClipRect.Bottom() - rOffset.getY())/pScaling->getY() ) ) ) );
209 : }
210 : else
211 : {
212 : // offset only - do it on the fly, have to convert
213 : // to float anyway.
214 0 : o_rRenderState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
215 0 : rCanvas->getUNOCanvas()->getDevice(),
216 : ::basegfx::B2DPolyPolygon(
217 : ::basegfx::tools::createPolygonFromRect(
218 0 : ::basegfx::B2DRectangle( aLocalClipRect.Left() - rOffset.getX(),
219 0 : aLocalClipRect.Top() - rOffset.getY(),
220 0 : aLocalClipRect.Right() - rOffset.getX(),
221 0 : aLocalClipRect.Bottom() - rOffset.getY() ) ) ) );
222 : }
223 :
224 0 : return true;
225 : }
226 :
227 : // empty clip, nothing to do
228 0 : return false;
229 : }
230 :
231 : // create overline/underline/strikeout line info struct
232 0 : TextLineInfo createTextLineInfo( const ::VirtualDevice& rVDev,
233 : const ::cppcanvas::internal::OutDevState& rState )
234 : {
235 0 : const bool bOldMode( rVDev.IsMapModeEnabled() );
236 :
237 : // #i68512# Force metric regeneration with mapmode enabled
238 : // (prolly OutDev bug)
239 0 : rVDev.GetFontMetric();
240 :
241 : // will restore map mode below
242 0 : const_cast< ::VirtualDevice& >(rVDev).EnableMapMode( false );
243 :
244 0 : const ::FontMetric aMetric = rVDev.GetFontMetric();
245 :
246 : TextLineInfo aTextInfo(
247 0 : (aMetric.GetDescent() + 2) / 4.0,
248 0 : ((aMetric.GetIntLeading() + 1.5) / 3.0),
249 0 : (aMetric.GetIntLeading() / 2.0) - aMetric.GetAscent(),
250 0 : aMetric.GetDescent() / 2.0,
251 0 : (aMetric.GetIntLeading() - aMetric.GetAscent()) / 3.0,
252 : rState.textOverlineStyle,
253 : rState.textUnderlineStyle,
254 0 : rState.textStrikeoutStyle );
255 :
256 0 : const_cast< ::VirtualDevice& >(rVDev).EnableMapMode( bOldMode );
257 :
258 0 : return aTextInfo;
259 : }
260 :
261 : namespace
262 : {
263 0 : void appendRect( ::basegfx::B2DPolyPolygon& o_rPoly,
264 : const ::basegfx::B2DPoint& rStartPos,
265 : const double nX1,
266 : const double nY1,
267 : const double nX2,
268 : const double nY2 )
269 : {
270 0 : const double x( rStartPos.getX() );
271 0 : const double y( rStartPos.getY() );
272 :
273 : o_rPoly.append(
274 : ::basegfx::tools::createPolygonFromRect(
275 0 : ::basegfx::B2DRectangle( x + nX1, y + nY1, x + nX2, y + nY2 ) ) );
276 0 : }
277 :
278 0 : void appendRect( ::basegfx::B2DPolyPolygon& o_rPoly,
279 : const double nX1,
280 : const double nY1,
281 : const double nX2,
282 : const double nY2 )
283 : {
284 : o_rPoly.append(
285 : ::basegfx::tools::createPolygonFromRect(
286 0 : ::basegfx::B2DRectangle( nX1, nY1, nX2, nY2 ) ) );
287 0 : }
288 :
289 0 : void appendDashes( ::basegfx::B2DPolyPolygon& o_rPoly,
290 : const double nX,
291 : const double nY,
292 : const double nLineWidth,
293 : const double nLineHeight,
294 : const double nDashWidth,
295 : const double nDashSkip )
296 : {
297 : const sal_Int32 nNumLoops(
298 : static_cast< sal_Int32 >(
299 : ::std::max( 1.0,
300 0 : nLineWidth / nDashSkip ) + .5) );
301 :
302 0 : double x = nX;
303 0 : for( sal_Int32 i=0; i<nNumLoops; ++i )
304 : {
305 : appendRect( o_rPoly,
306 : x, nY,
307 0 : x + nDashWidth, nY + nLineHeight );
308 :
309 0 : x += nDashSkip;
310 : }
311 0 : }
312 : }
313 :
314 : // create line actions for text such as underline and
315 : // strikeout
316 0 : ::basegfx::B2DPolyPolygon createTextLinesPolyPolygon( const ::basegfx::B2DPoint& rStartPos,
317 : const double& rLineWidth,
318 : const TextLineInfo& rTextLineInfo )
319 : {
320 : // fill the polypolygon with all text lines
321 0 : ::basegfx::B2DPolyPolygon aTextLinesPolyPoly;
322 :
323 0 : switch( rTextLineInfo.mnOverlineStyle )
324 : {
325 : case UNDERLINE_NONE: // nothing to do
326 : // FALLTHROUGH intended
327 : case UNDERLINE_DONTKNOW:
328 0 : break;
329 :
330 : case UNDERLINE_SMALLWAVE: // TODO(F3): NYI
331 : // FALLTHROUGH intended
332 : case UNDERLINE_WAVE: // TODO(F3): NYI
333 : // FALLTHROUGH intended
334 : case UNDERLINE_SINGLE:
335 : appendRect(
336 : aTextLinesPolyPoly,
337 : rStartPos,
338 : 0,
339 : rTextLineInfo.mnOverlineOffset,
340 : rLineWidth,
341 0 : rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight );
342 0 : break;
343 :
344 : case UNDERLINE_BOLDDOTTED: // TODO(F3): NYI
345 : // FALLTHROUGH intended
346 : case UNDERLINE_BOLDDASH: // TODO(F3): NYI
347 : // FALLTHROUGH intended
348 : case UNDERLINE_BOLDLONGDASH: // TODO(F3): NYI
349 : // FALLTHROUGH intended
350 : case UNDERLINE_BOLDDASHDOT: // TODO(F3): NYI
351 : // FALLTHROUGH intended
352 : case UNDERLINE_BOLDDASHDOTDOT:// TODO(F3): NYI
353 : // FALLTHROUGH intended
354 : case UNDERLINE_BOLDWAVE: // TODO(F3): NYI
355 : // FALLTHROUGH intended
356 : case UNDERLINE_BOLD:
357 : appendRect(
358 : aTextLinesPolyPoly,
359 : rStartPos,
360 : 0,
361 : rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight,
362 : rLineWidth,
363 0 : rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight );
364 0 : break;
365 :
366 : case UNDERLINE_DOUBLEWAVE: // TODO(F3): NYI
367 : // FALLTHROUGH intended
368 : case UNDERLINE_DOUBLE:
369 : appendRect(
370 : aTextLinesPolyPoly,
371 : rStartPos,
372 : 0,
373 0 : rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight * 2.0 ,
374 : rLineWidth,
375 0 : rTextLineInfo.mnOverlineOffset - rTextLineInfo.mnOverlineHeight );
376 :
377 : appendRect(
378 : aTextLinesPolyPoly,
379 : rStartPos,
380 : 0,
381 : rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight,
382 : rLineWidth,
383 0 : rTextLineInfo.mnOverlineOffset + rTextLineInfo.mnOverlineHeight * 2.0 );
384 0 : break;
385 :
386 : case UNDERLINE_DASHDOTDOT: // TODO(F3): NYI
387 : // FALLTHROUGH intended
388 : case UNDERLINE_DOTTED:
389 : appendDashes(
390 : aTextLinesPolyPoly,
391 : rStartPos.getX(),
392 0 : rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
393 : rLineWidth,
394 : rTextLineInfo.mnOverlineHeight,
395 : rTextLineInfo.mnOverlineHeight,
396 0 : 2*rTextLineInfo.mnOverlineHeight );
397 0 : break;
398 :
399 : case UNDERLINE_DASHDOT: // TODO(F3): NYI
400 : // FALLTHROUGH intended
401 : case UNDERLINE_DASH:
402 : appendDashes(
403 : aTextLinesPolyPoly,
404 : rStartPos.getX(),
405 0 : rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
406 : rLineWidth,
407 : rTextLineInfo.mnOverlineHeight,
408 : 3*rTextLineInfo.mnOverlineHeight,
409 0 : 6*rTextLineInfo.mnOverlineHeight );
410 0 : break;
411 :
412 : case UNDERLINE_LONGDASH:
413 : appendDashes(
414 : aTextLinesPolyPoly,
415 : rStartPos.getX(),
416 0 : rStartPos.getY() + rTextLineInfo.mnOverlineOffset,
417 : rLineWidth,
418 : rTextLineInfo.mnOverlineHeight,
419 : 6*rTextLineInfo.mnOverlineHeight,
420 0 : 12*rTextLineInfo.mnOverlineHeight );
421 0 : break;
422 :
423 : default:
424 0 : ENSURE_OR_THROW( false,
425 : "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected overline case" );
426 : }
427 :
428 0 : switch( rTextLineInfo.mnUnderlineStyle )
429 : {
430 : case UNDERLINE_NONE: // nothing to do
431 : // FALLTHROUGH intended
432 : case UNDERLINE_DONTKNOW:
433 0 : break;
434 :
435 : case UNDERLINE_SMALLWAVE: // TODO(F3): NYI
436 : // FALLTHROUGH intended
437 : case UNDERLINE_WAVE: // TODO(F3): NYI
438 : // FALLTHROUGH intended
439 : case UNDERLINE_SINGLE:
440 : appendRect(
441 : aTextLinesPolyPoly,
442 : rStartPos,
443 : 0,
444 : rTextLineInfo.mnUnderlineOffset,
445 : rLineWidth,
446 0 : rTextLineInfo.mnUnderlineOffset + rTextLineInfo.mnLineHeight );
447 0 : break;
448 :
449 : case UNDERLINE_BOLDDOTTED: // TODO(F3): NYI
450 : // FALLTHROUGH intended
451 : case UNDERLINE_BOLDDASH: // TODO(F3): NYI
452 : // FALLTHROUGH intended
453 : case UNDERLINE_BOLDLONGDASH: // TODO(F3): NYI
454 : // FALLTHROUGH intended
455 : case UNDERLINE_BOLDDASHDOT: // TODO(F3): NYI
456 : // FALLTHROUGH intended
457 : case UNDERLINE_BOLDDASHDOTDOT:// TODO(F3): NYI
458 : // FALLTHROUGH intended
459 : case UNDERLINE_BOLDWAVE: // TODO(F3): NYI
460 : // FALLTHROUGH intended
461 : case UNDERLINE_BOLD:
462 : appendRect(
463 : aTextLinesPolyPoly,
464 : rStartPos,
465 : 0,
466 : rTextLineInfo.mnUnderlineOffset,
467 : rLineWidth,
468 0 : rTextLineInfo.mnUnderlineOffset + 2*rTextLineInfo.mnLineHeight );
469 0 : break;
470 :
471 : case UNDERLINE_DOUBLEWAVE: // TODO(F3): NYI
472 : // FALLTHROUGH intended
473 : case UNDERLINE_DOUBLE:
474 : appendRect(
475 : aTextLinesPolyPoly,
476 : rStartPos,
477 : 0,
478 : rTextLineInfo.mnUnderlineOffset - rTextLineInfo.mnLineHeight,
479 : rLineWidth,
480 0 : rTextLineInfo.mnUnderlineOffset );
481 :
482 : appendRect(
483 : aTextLinesPolyPoly,
484 : rStartPos,
485 : 0,
486 0 : rTextLineInfo.mnUnderlineOffset + 2*rTextLineInfo.mnLineHeight,
487 : rLineWidth,
488 0 : rTextLineInfo.mnUnderlineOffset + 3*rTextLineInfo.mnLineHeight );
489 0 : break;
490 :
491 : case UNDERLINE_DASHDOTDOT: // TODO(F3): NYI
492 : // FALLTHROUGH intended
493 : case UNDERLINE_DOTTED:
494 : appendDashes(
495 : aTextLinesPolyPoly,
496 : rStartPos.getX(),
497 0 : rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
498 : rLineWidth,
499 : rTextLineInfo.mnLineHeight,
500 : rTextLineInfo.mnLineHeight,
501 0 : 2*rTextLineInfo.mnLineHeight );
502 0 : break;
503 :
504 : case UNDERLINE_DASHDOT: // TODO(F3): NYI
505 : // FALLTHROUGH intended
506 : case UNDERLINE_DASH:
507 : appendDashes(
508 : aTextLinesPolyPoly,
509 : rStartPos.getX(),
510 0 : rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
511 : rLineWidth,
512 : rTextLineInfo.mnLineHeight,
513 : 3*rTextLineInfo.mnLineHeight,
514 0 : 6*rTextLineInfo.mnLineHeight );
515 0 : break;
516 :
517 : case UNDERLINE_LONGDASH:
518 : appendDashes(
519 : aTextLinesPolyPoly,
520 : rStartPos.getX(),
521 0 : rStartPos.getY() + rTextLineInfo.mnUnderlineOffset,
522 : rLineWidth,
523 : rTextLineInfo.mnLineHeight,
524 : 6*rTextLineInfo.mnLineHeight,
525 0 : 12*rTextLineInfo.mnLineHeight );
526 0 : break;
527 :
528 : default:
529 0 : ENSURE_OR_THROW( false,
530 : "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected underline case" );
531 : }
532 :
533 0 : switch( rTextLineInfo.mnStrikeoutStyle )
534 : {
535 : case STRIKEOUT_NONE: // nothing to do
536 : // FALLTHROUGH intended
537 : case STRIKEOUT_DONTKNOW:
538 0 : break;
539 :
540 : case STRIKEOUT_SLASH: // TODO(Q1): we should handle this in the text layer
541 : // FALLTHROUGH intended
542 : case STRIKEOUT_X:
543 0 : break;
544 :
545 : case STRIKEOUT_SINGLE:
546 : appendRect(
547 : aTextLinesPolyPoly,
548 : rStartPos,
549 : 0,
550 : rTextLineInfo.mnStrikeoutOffset,
551 : rLineWidth,
552 0 : rTextLineInfo.mnStrikeoutOffset + rTextLineInfo.mnLineHeight );
553 0 : break;
554 :
555 : case STRIKEOUT_BOLD:
556 : appendRect(
557 : aTextLinesPolyPoly,
558 : rStartPos,
559 : 0,
560 : rTextLineInfo.mnStrikeoutOffset,
561 : rLineWidth,
562 0 : rTextLineInfo.mnStrikeoutOffset + 2*rTextLineInfo.mnLineHeight );
563 0 : break;
564 :
565 : case STRIKEOUT_DOUBLE:
566 : appendRect(
567 : aTextLinesPolyPoly,
568 : rStartPos,
569 : 0,
570 : rTextLineInfo.mnStrikeoutOffset - rTextLineInfo.mnLineHeight,
571 : rLineWidth,
572 0 : rTextLineInfo.mnStrikeoutOffset );
573 :
574 : appendRect(
575 : aTextLinesPolyPoly,
576 : rStartPos,
577 : 0,
578 0 : rTextLineInfo.mnStrikeoutOffset + 2*rTextLineInfo.mnLineHeight,
579 : rLineWidth,
580 0 : rTextLineInfo.mnStrikeoutOffset + 3*rTextLineInfo.mnLineHeight );
581 0 : break;
582 :
583 : default:
584 0 : ENSURE_OR_THROW( false,
585 : "::cppcanvas::internal::createTextLinesPolyPolygon(): Unexpected strikeout case" );
586 : }
587 :
588 0 : return aTextLinesPolyPoly;
589 : }
590 :
591 0 : ::basegfx::B2DRange calcDevicePixelBounds( const ::basegfx::B2DRange& rBounds,
592 : const rendering::ViewState& viewState,
593 : const rendering::RenderState& renderState )
594 : {
595 0 : ::basegfx::B2DHomMatrix aTransform;
596 : ::canvas::tools::mergeViewAndRenderTransform( aTransform,
597 : viewState,
598 0 : renderState );
599 :
600 0 : ::basegfx::B2DRange aTransformedBounds;
601 : return ::canvas::tools::calcTransformedRectBounds( aTransformedBounds,
602 : rBounds,
603 0 : aTransform );
604 : }
605 :
606 : // create line actions for text such as underline and
607 : // strikeout
608 0 : ::basegfx::B2DPolyPolygon createTextLinesPolyPolygon( const double& rStartOffset,
609 : const double& rLineWidth,
610 : const TextLineInfo& rTextLineInfo )
611 : {
612 : return createTextLinesPolyPolygon(
613 : ::basegfx::B2DPoint( rStartOffset,
614 : 0.0 ),
615 : rLineWidth,
616 0 : rTextLineInfo );
617 : }
618 : }
619 1143 : }
620 :
621 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|