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