LibreOffice Module canvas (master) 1
canvashelper.cxx
Go to the documentation of this file.
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#include <sal/config.h>
21
31#include <com/sun/star/drawing/LineCap.hpp>
32#include <com/sun/star/rendering/CompositeOperation.hpp>
33#include <com/sun/star/rendering/PathCapType.hpp>
34#include <com/sun/star/rendering/PathJoinType.hpp>
35#include <com/sun/star/rendering/TextDirection.hpp>
37#include <rtl/math.hxx>
38#include <tools/diagnose_ex.h>
39#include <tools/poly.hxx>
40#include <vcl/bitmapex.hxx>
42#include <vcl/canvastools.hxx>
45
47
48#include "canvasbitmap.hxx"
49#include "canvasfont.hxx"
50#include "canvashelper.hxx"
51#include "impltools.hxx"
52#include "textlayout.hxx"
53
54
55using namespace ::com::sun::star;
56
57namespace vclcanvas
58{
59 namespace
60 {
61 basegfx::B2DLineJoin b2DJoineFromJoin( sal_Int8 nJoinType )
62 {
63 switch( nJoinType )
64 {
65 case rendering::PathJoinType::NONE:
67
68 case rendering::PathJoinType::MITER:
70
71 case rendering::PathJoinType::ROUND:
73
74 case rendering::PathJoinType::BEVEL:
76
77 default:
78 ENSURE_OR_THROW( false,
79 "b2DJoineFromJoin(): Unexpected join type" );
80 }
81
83 }
84
85 drawing::LineCap unoCapeFromCap( sal_Int8 nCapType)
86 {
87 switch ( nCapType)
88 {
89 case rendering::PathCapType::BUTT:
90 return drawing::LineCap_BUTT;
91
92 case rendering::PathCapType::ROUND:
93 return drawing::LineCap_ROUND;
94
95 case rendering::PathCapType::SQUARE:
96 return drawing::LineCap_SQUARE;
97
98 default:
99 ENSURE_OR_THROW( false,
100 "unoCapeFromCap(): Unexpected cap type" );
101 }
102 return drawing::LineCap_BUTT;
103 }
104 }
105
107 mpDevice(),
108 mbHaveAlpha( false )
109 {
110 }
111
113 {
114 mpDevice = nullptr;
116 mpOutDevProvider.reset();
117 mp2ndOutDevProvider.reset();
118 }
119
120 void CanvasHelper::init( rendering::XGraphicDevice& rDevice,
121 const OutDevProviderSharedPtr& rOutDev,
122 bool bProtect,
123 bool bHaveAlpha )
124 {
125 // cast away const, need to change refcount (as this is
126 // ~invisible to client code, still logically const)
127 mpDevice = &rDevice;
128 mbHaveAlpha = bHaveAlpha;
129
130 setOutDev( rOutDev, bProtect );
131 }
132
134 bool bProtect )
135 {
136 if( bProtect )
138 else
140
141 mpOutDevProvider = rOutDev;
142 }
143
145 {
146 mp2ndOutDevProvider = rOutDev;
147 mp2ndOutDevProvider->getOutDev().EnableMapMode( false );
148 mp2ndOutDevProvider->getOutDev().SetAntialiasing( AntialiasingFlags::Enable );
149 }
150
152 {
153 // are we disposed?
154 if( !mpOutDevProvider )
155 return;
156
157 OutputDevice& rOutDev( mpOutDevProvider->getOutDev() );
159
160 rOutDev.EnableMapMode( false );
161 rOutDev.SetAntialiasing( AntialiasingFlags::Enable );
162 rOutDev.SetLineColor( COL_WHITE );
163 rOutDev.SetFillColor( COL_WHITE );
164 rOutDev.SetClipRegion();
166 rOutDev.GetOutputSizePixel()) );
167
169 return;
170
171 OutputDevice& rOutDev2( mp2ndOutDevProvider->getOutDev() );
172
173 rOutDev2.SetDrawMode( DrawModeFlags::Default );
174 rOutDev2.EnableMapMode( false );
175 rOutDev2.SetAntialiasing( AntialiasingFlags::Enable );
176 rOutDev2.SetLineColor( COL_WHITE );
177 rOutDev2.SetFillColor( COL_WHITE );
178 rOutDev2.SetClipRegion();
179 rOutDev2.DrawRect( ::tools::Rectangle( Point(),
180 rOutDev2.GetOutputSizePixel()) );
181 rOutDev2.SetDrawMode( DrawModeFlags::BlackLine | DrawModeFlags::BlackFill | DrawModeFlags::BlackText |
182 DrawModeFlags::BlackGradient | DrawModeFlags::BlackBitmap );
183 }
184
185 void CanvasHelper::drawLine( const rendering::XCanvas* ,
186 const geometry::RealPoint2D& aStartRealPoint2D,
187 const geometry::RealPoint2D& aEndRealPoint2D,
188 const rendering::ViewState& viewState,
189 const rendering::RenderState& renderState )
190 {
191 // are we disposed?
192 if( !mpOutDevProvider )
193 return;
194
195 // nope, render
197 setupOutDevState( viewState, renderState, LINE_COLOR );
198
199 const Point aStartPoint( tools::mapRealPoint2D( aStartRealPoint2D,
200 viewState, renderState ) );
201 const Point aEndPoint( tools::mapRealPoint2D( aEndRealPoint2D,
202 viewState, renderState ) );
203 // TODO(F2): alpha
204 mpOutDevProvider->getOutDev().DrawLine( aStartPoint, aEndPoint );
205
207 mp2ndOutDevProvider->getOutDev().DrawLine( aStartPoint, aEndPoint );
208 }
209
210 void CanvasHelper::drawBezier( const rendering::XCanvas* ,
211 const geometry::RealBezierSegment2D& aBezierSegment,
212 const geometry::RealPoint2D& _aEndPoint,
213 const rendering::ViewState& viewState,
214 const rendering::RenderState& renderState )
215 {
216 if( !mpOutDevProvider )
217 return;
218
219 tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDevProvider );
220 setupOutDevState( viewState, renderState, LINE_COLOR );
221
222 const Point& rStartPoint( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.Px,
223 aBezierSegment.Py),
224 viewState, renderState ) );
225 const Point& rCtrlPoint1( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.C1x,
226 aBezierSegment.C1y),
227 viewState, renderState ) );
228 const Point& rCtrlPoint2( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.C2x,
229 aBezierSegment.C2y),
230 viewState, renderState ) );
231 const Point& rEndPoint( tools::mapRealPoint2D( _aEndPoint,
232 viewState, renderState ) );
233
234 ::tools::Polygon aPoly(4);
235 aPoly.SetPoint( rStartPoint, 0 );
236 aPoly.SetFlags( 0, PolyFlags::Normal );
237 aPoly.SetPoint( rCtrlPoint1, 1 );
238 aPoly.SetFlags( 1, PolyFlags::Control );
239 aPoly.SetPoint( rCtrlPoint2, 2 );
240 aPoly.SetFlags( 2, PolyFlags::Control );
241 aPoly.SetPoint( rEndPoint, 3 );
242 aPoly.SetFlags( 3, PolyFlags::Normal );
243
244 // TODO(F2): alpha
245 mpOutDevProvider->getOutDev().DrawPolygon( aPoly );
247 mp2ndOutDevProvider->getOutDev().DrawPolygon( aPoly );
248 }
249
250 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* ,
251 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
252 const rendering::ViewState& viewState,
253 const rendering::RenderState& renderState )
254 {
255 ENSURE_ARG_OR_THROW( xPolyPolygon.is(),
256 "polygon is NULL");
257
258 if( mpOutDevProvider )
259 {
260 tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDevProvider );
261 setupOutDevState( viewState, renderState, LINE_COLOR );
262
263 const ::basegfx::B2DPolyPolygon& rPolyPoly(
264 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon) );
265 const ::tools::PolyPolygon aPolyPoly( tools::mapPolyPolygon( rPolyPoly, viewState, renderState ) );
266
267 if( rPolyPoly.isClosed() )
268 {
269 mpOutDevProvider->getOutDev().DrawPolyPolygon( aPolyPoly );
270
272 mp2ndOutDevProvider->getOutDev().DrawPolyPolygon( aPolyPoly );
273 }
274 else
275 {
276 // mixed open/closed state. Cannot render open polygon
277 // via DrawPolyPolygon(), since that implicitly
278 // closed every polygon. OTOH, no need to distinguish
279 // further and render closed polygons via
280 // DrawPolygon(), and open ones via DrawPolyLine():
281 // closed polygons will simply already contain the
282 // closing segment.
283 sal_uInt16 nSize( aPolyPoly.Count() );
284
285 for( sal_uInt16 i=0; i<nSize; ++i )
286 {
287 mpOutDevProvider->getOutDev().DrawPolyLine( aPolyPoly[i] );
288
290 mp2ndOutDevProvider->getOutDev().DrawPolyLine( aPolyPoly[i] );
291 }
292 }
293 }
294
295 // TODO(P1): Provide caching here.
296 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
297 }
298
299 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokePolyPolygon( const rendering::XCanvas* ,
300 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
301 const rendering::ViewState& viewState,
302 const rendering::RenderState& renderState,
303 const rendering::StrokeAttributes& strokeAttributes )
304 {
305 ENSURE_ARG_OR_THROW( xPolyPolygon.is(),
306 "polygon is NULL");
307
308 if( mpOutDevProvider )
309 {
310 tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDevProvider );
311
313 ::canvas::tools::mergeViewAndRenderTransform(aMatrix, viewState, renderState);
314
316 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon) );
317
318 std::vector<double> aDashArray;
319 if( strokeAttributes.DashArray.hasElements() )
320 aDashArray = ::comphelper::sequenceToContainer< std::vector<double> >(strokeAttributes.DashArray);
321
322 // First try to draw directly using VCL.
323 bool directFailed = false;
324 setupOutDevState( viewState, renderState, LINE_COLOR );
325 for( sal_uInt32 i=0; i<aPolyPoly.count(); ++i )
326 {
327 if( !mpOutDevProvider->getOutDev().DrawPolyLineDirect( aMatrix, aPolyPoly.getB2DPolygon(i),
328 strokeAttributes.StrokeWidth, 0, !aDashArray.empty() ? &aDashArray : nullptr,
329 b2DJoineFromJoin(strokeAttributes.JoinType), unoCapeFromCap(strokeAttributes.StartCapType)))
330 {
331 directFailed = true;
332 break;
333 }
334 }
335 if(!directFailed)
336 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
337
338 // Do it all manually.
339
340 // apply dashing, if any
341 if( strokeAttributes.DashArray.hasElements() )
342 {
343 ::basegfx::B2DPolyPolygon aDashedPolyPoly;
344
345 for( sal_uInt32 i=0; i<aPolyPoly.count(); ++i )
346 {
347 // AW: new interface; You may also get gaps in the same run now
348 basegfx::utils::applyLineDashing(aPolyPoly.getB2DPolygon(i), aDashArray, &aDashedPolyPoly);
349 //aDashedPolyPoly.append(
350 // ::basegfx::utils::applyLineDashing( aPolyPoly.getB2DPolygon(i),
351 // aDashArray ) );
352 }
353
354 aPolyPoly = aDashedPolyPoly;
355 }
356
357 ::basegfx::B2DSize aLinePixelSize(strokeAttributes.StrokeWidth,
358 strokeAttributes.StrokeWidth);
359 aLinePixelSize *= aMatrix;
360 ::basegfx::B2DPolyPolygon aStrokedPolyPoly;
361 if( aLinePixelSize.getLength() < 1.42 )
362 {
363 // line width < 1.0 in device pixel, thus, output as a
364 // simple hairline poly-polygon
365 setupOutDevState( viewState, renderState, LINE_COLOR );
366
367 aStrokedPolyPoly = aPolyPoly;
368 }
369 else
370 {
371 // render as a 'thick' line
372 setupOutDevState( viewState, renderState, FILL_COLOR );
373
374 for( sal_uInt32 i=0; i<aPolyPoly.count(); ++i )
375 {
376 double fMiterMinimumAngle;
377 if (strokeAttributes.MiterLimit <= 1.0)
378 {
379 fMiterMinimumAngle = M_PI_2;
380 }
381 else
382 {
383 fMiterMinimumAngle = 2.0 * asin(1.0/strokeAttributes.MiterLimit);
384 }
385
386 // TODO(F2): Also use Cap settings from
387 // StrokeAttributes, the
388 // createAreaGeometryForLineStartEnd() method does not
389 // seem to fit very well here
390
391 // AW: New interface, will create bezier polygons now
393 aPolyPoly.getB2DPolygon(i),
394 strokeAttributes.StrokeWidth*0.5,
395 b2DJoineFromJoin(strokeAttributes.JoinType),
396 unoCapeFromCap(strokeAttributes.StartCapType),
397 basegfx::deg2rad(12.5) /* default fMaxAllowedAngle*/ ,
398 0.4 /* default fMaxPartOfEdge*/ ,
399 fMiterMinimumAngle
400 ));
401 //aStrokedPolyPoly.append(
402 // ::basegfx::utils::createAreaGeometryForPolygon( aPolyPoly.getB2DPolygon(i),
403 // strokeAttributes.StrokeWidth*0.5,
404 // b2DJoineFromJoin(strokeAttributes.JoinType) ) );
405 }
406 }
407
408 // transform only _now_, all the StrokeAttributes are in
409 // user coordinates.
410 aStrokedPolyPoly.transform( aMatrix );
411
412 // TODO(F2): When using alpha here, must handle that via
413 // temporary surface or somesuch.
414
415 // Note: the generated stroke poly-polygon is NOT free of
416 // self-intersections. Therefore, if we would render it
417 // via OutDev::DrawPolyPolygon(), on/off fill would
418 // generate off areas on those self-intersections.
419 for( sal_uInt32 i=0; i<aStrokedPolyPoly.count(); ++i )
420 {
421 const basegfx::B2DPolygon& polygon = aStrokedPolyPoly.getB2DPolygon( i );
422 if( polygon.isClosed()) {
423 mpOutDevProvider->getOutDev().DrawPolygon( polygon );
425 mp2ndOutDevProvider->getOutDev().DrawPolygon( polygon );
426 } else {
427 mpOutDevProvider->getOutDev().DrawPolyLine( polygon );
429 mp2ndOutDevProvider->getOutDev().DrawPolyLine( polygon );
430 }
431 }
432 }
433
434 // TODO(P1): Provide caching here.
435 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
436 }
437
438 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas* ,
439 const uno::Reference< rendering::XPolyPolygon2D >& ,
440 const rendering::ViewState& ,
441 const rendering::RenderState& ,
442 const uno::Sequence< rendering::Texture >& ,
443 const rendering::StrokeAttributes& )
444 {
445 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
446 }
447
448 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas* ,
449 const uno::Reference< rendering::XPolyPolygon2D >& ,
450 const rendering::ViewState& ,
451 const rendering::RenderState& ,
452 const uno::Sequence< rendering::Texture >& ,
453 const uno::Reference< geometry::XMapping2D >& ,
454 const rendering::StrokeAttributes& )
455 {
456 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
457 }
458
459 uno::Reference< rendering::XPolyPolygon2D > CanvasHelper::queryStrokeShapes( const rendering::XCanvas* ,
460 const uno::Reference< rendering::XPolyPolygon2D >& ,
461 const rendering::ViewState& ,
462 const rendering::RenderState& ,
463 const rendering::StrokeAttributes& )
464 {
465 return uno::Reference< rendering::XPolyPolygon2D >(nullptr);
466 }
467
468 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillPolyPolygon( const rendering::XCanvas* ,
469 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
470 const rendering::ViewState& viewState,
471 const rendering::RenderState& renderState )
472 {
473 ENSURE_ARG_OR_THROW( xPolyPolygon.is(),
474 "polygon is NULL");
475
476 if( mpOutDevProvider )
477 {
478 tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDevProvider );
479
480 const int nAlpha( setupOutDevState( viewState, renderState, FILL_COLOR ) );
481 ::basegfx::B2DPolyPolygon aB2DPolyPoly(
482 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon));
483 aB2DPolyPoly.setClosed(true); // ensure closed poly, otherwise VCL does not fill
484 const ::tools::PolyPolygon aPolyPoly( tools::mapPolyPolygon(
485 aB2DPolyPoly,
486 viewState, renderState ) );
487 const bool bSourceAlpha( renderState.CompositeOperation == rendering::CompositeOperation::SOURCE );
488 if( nAlpha == 255 || bSourceAlpha )
489 {
490 mpOutDevProvider->getOutDev().DrawPolyPolygon( aPolyPoly );
491 }
492 else
493 {
494 const int nTransPercent( ((255 - nAlpha) * 100 + 128) / 255 ); // normal rounding, no truncation here
495 mpOutDevProvider->getOutDev().DrawTransparent( aPolyPoly, static_cast<sal_uInt16>(nTransPercent) );
496 }
497
499 {
500 // HACK. Normally, CanvasHelper does not care about
501 // actually what mp2ndOutDev is... well, here we do &
502 // assume a 1bpp target - everything beyond 97%
503 // transparency is fully transparent
504 if( nAlpha > 2 )
505 {
506 mp2ndOutDevProvider->getOutDev().SetFillColor( COL_BLACK );
507 mp2ndOutDevProvider->getOutDev().DrawPolyPolygon( aPolyPoly );
508 }
509 }
510 }
511
512 // TODO(P1): Provide caching here.
513 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
514 }
515
516 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas* ,
517 const uno::Reference< rendering::XPolyPolygon2D >& ,
518 const rendering::ViewState& ,
519 const rendering::RenderState& ,
520 const uno::Sequence< rendering::Texture >& ,
521 const uno::Reference< geometry::XMapping2D >& )
522 {
523 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
524 }
525
526 uno::Reference< rendering::XCanvasFont > CanvasHelper::createFont( const rendering::XCanvas* ,
527 const rendering::FontRequest& fontRequest,
528 const uno::Sequence< beans::PropertyValue >& extraFontProperties,
529 const geometry::Matrix2D& fontMatrix )
530 {
532 {
533 // TODO(F2): font properties and font matrix
534 return uno::Reference< rendering::XCanvasFont >(
535 new CanvasFont(fontRequest, extraFontProperties, fontMatrix,
537 }
538
539 return uno::Reference< rendering::XCanvasFont >();
540 }
541
542 uno::Sequence< rendering::FontInfo > CanvasHelper::queryAvailableFonts( const rendering::XCanvas* ,
543 const rendering::FontInfo& ,
544 const uno::Sequence< beans::PropertyValue >& )
545 {
546 // TODO(F2)
547 return uno::Sequence< rendering::FontInfo >();
548 }
549
550 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawText( const rendering::XCanvas* ,
551 const rendering::StringContext& text,
552 const uno::Reference< rendering::XCanvasFont >& xFont,
553 const rendering::ViewState& viewState,
554 const rendering::RenderState& renderState,
555 sal_Int8 textDirection )
556 {
557 ENSURE_ARG_OR_THROW( xFont.is(),
558 "font is NULL");
559
560 if( mpOutDevProvider )
561 {
562 tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDevProvider );
563
564 ::Point aOutpos;
565 if( !setupTextOutput( aOutpos, viewState, renderState, xFont ) )
566 return uno::Reference< rendering::XCachedPrimitive >(nullptr); // no output necessary
567
568 // change text direction and layout mode
570 switch( textDirection )
571 {
572 case rendering::TextDirection::WEAK_LEFT_TO_RIGHT:
573 case rendering::TextDirection::STRONG_LEFT_TO_RIGHT:
576 break;
577
578 case rendering::TextDirection::WEAK_RIGHT_TO_LEFT:
580 [[fallthrough]];
581 case rendering::TextDirection::STRONG_RIGHT_TO_LEFT:
584 break;
585 }
586
587 // TODO(F2): alpha
588 mpOutDevProvider->getOutDev().SetLayoutMode( nLayoutMode );
589 mpOutDevProvider->getOutDev().DrawText( aOutpos,
590 text.Text,
591 ::canvas::tools::numeric_cast<sal_uInt16>(text.StartPosition),
592 ::canvas::tools::numeric_cast<sal_uInt16>(text.Length) );
593
595 {
596 mp2ndOutDevProvider->getOutDev().SetLayoutMode( nLayoutMode );
597 mp2ndOutDevProvider->getOutDev().DrawText( aOutpos,
598 text.Text,
599 ::canvas::tools::numeric_cast<sal_uInt16>(text.StartPosition),
600 ::canvas::tools::numeric_cast<sal_uInt16>(text.Length) );
601 }
602 }
603
604 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
605 }
606
607 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawTextLayout( const rendering::XCanvas* ,
608 const uno::Reference< rendering::XTextLayout >& xLayoutedText,
609 const rendering::ViewState& viewState,
610 const rendering::RenderState& renderState )
611 {
612 ENSURE_ARG_OR_THROW( xLayoutedText.is(),
613 "layout is NULL");
614
615 TextLayout* pTextLayout = dynamic_cast< TextLayout* >( xLayoutedText.get() );
616
617 if( pTextLayout )
618 {
619 if( mpOutDevProvider )
620 {
621 tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDevProvider );
622
623 // TODO(T3): Race condition. We're taking the font
624 // from xLayoutedText, and then calling draw() at it,
625 // without exclusive access. Move setupTextOutput(),
626 // e.g. to impltools?
627
628 ::Point aOutpos;
629 if( !setupTextOutput( aOutpos, viewState, renderState, xLayoutedText->getFont() ) )
630 return uno::Reference< rendering::XCachedPrimitive >(nullptr); // no output necessary
631
632 // TODO(F2): What about the offset scalings?
633 // TODO(F2): alpha
634 pTextLayout->draw( mpOutDevProvider->getOutDev(), aOutpos, viewState, renderState );
635
637 pTextLayout->draw( mp2ndOutDevProvider->getOutDev(), aOutpos, viewState, renderState );
638 }
639 }
640 else
641 {
642 ENSURE_ARG_OR_THROW( false,
643 "TextLayout not compatible with this canvas" );
644 }
645
646 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
647 }
648
649 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::implDrawBitmap( const rendering::XCanvas* pCanvas,
650 const uno::Reference< rendering::XBitmap >& xBitmap,
651 const rendering::ViewState& viewState,
652 const rendering::RenderState& renderState,
653 bool bModulateColors )
654 {
655 ENSURE_ARG_OR_THROW( xBitmap.is(),
656 "bitmap is NULL");
657
658 ::canvas::tools::verifyInput( renderState,
659 __func__,
660 mpDevice,
661 4,
662 bModulateColors ? 3 : 0 );
663
664 if( mpOutDevProvider )
665 {
667 setupOutDevState( viewState, renderState, IGNORE_COLOR );
668
670 ::canvas::tools::mergeViewAndRenderTransform(aMatrix, viewState, renderState);
671
672 ::basegfx::B2DPoint aOutputPos( 0.0, 0.0 );
673 aOutputPos *= aMatrix;
674
675 BitmapEx aBmpEx( tools::bitmapExFromXBitmap(xBitmap) );
676
677 // TODO(F2): Implement modulation again for other color
678 // channels (currently, works only for alpha). Note: this
679 // is already implemented in transformBitmap()
680 if( bModulateColors &&
681 renderState.DeviceColor.getLength() > 3 )
682 {
683 // optimize away the case where alpha modulation value
684 // is 1.0 - we then simply switch off modulation at all
685 bModulateColors = !::rtl::math::approxEqual(
686 renderState.DeviceColor[3], 1.0);
687 }
688
689 // check whether we can render bitmap as-is: must not
690 // modulate colors, matrix must either be the identity
691 // transform (that's clear), _or_ contain only
692 // translational components.
693 if( !bModulateColors &&
694 (aMatrix.isIdentity() ||
695 (::basegfx::fTools::equalZero( aMatrix.get(0,1) ) &&
696 ::basegfx::fTools::equalZero( aMatrix.get(1,0) ) &&
697 ::rtl::math::approxEqual(aMatrix.get(0,0), 1.0) &&
698 ::rtl::math::approxEqual(aMatrix.get(1,1), 1.0)) ) )
699 {
700 // optimized case: identity matrix, or only
701 // translational components.
702 mpOutDevProvider->getOutDev().DrawBitmapEx( vcl::unotools::pointFromB2DPoint( aOutputPos ),
703 aBmpEx );
704
706 {
707 // HACK. Normally, CanvasHelper does not care about
708 // actually what mp2ndOutDev is... well, here we do &
709 // assume a 1bpp target - everything beyond 97%
710 // transparency is fully transparent
711 if( aBmpEx.IsAlpha() && !SkiaHelper::isVCLSkiaEnabled())
712 {
714 }
715
716 mp2ndOutDevProvider->getOutDev().DrawBitmapEx( vcl::unotools::pointFromB2DPoint( aOutputPos ),
717 aBmpEx );
718 }
719
720 // Returning a cache object is not useful, the XBitmap
721 // itself serves this purpose
722 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
723 }
724 else if( mpOutDevProvider->getOutDev().HasFastDrawTransformedBitmap())
725 {
726 ::basegfx::B2DHomMatrix aSizeTransform;
727 aSizeTransform.scale( aBmpEx.GetSizePixel().Width(), aBmpEx.GetSizePixel().Height() );
728 aMatrix = aMatrix * aSizeTransform;
729 const double fAlpha = bModulateColors ? renderState.DeviceColor[3] : 1.0;
730
731 mpOutDevProvider->getOutDev().DrawTransformedBitmapEx( aMatrix, aBmpEx, fAlpha );
733 {
734 // HACK. Normally, CanvasHelper does not care about
735 // actually what mp2ndOutDev is... well, here we do &
736 // assume a 1bpp target - everything beyond 97%
737 // transparency is fully transparent
738 if( aBmpEx.IsAlpha() && !SkiaHelper::isVCLSkiaEnabled())
739 {
741 }
742
743 mp2ndOutDevProvider->getOutDev().DrawTransformedBitmapEx( aMatrix, aBmpEx );
744 }
745 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
746 }
747 else
748 {
749 // Matrix contains non-trivial transformation (or
750 // color modulation is requested), decompose to check
751 // whether GraphicObject suffices
753 double nRotate;
754 double nShearX;
755 aMatrix.decompose( aScale, aOutputPos, nRotate, nShearX );
756
757 GraphicAttr aGrfAttr;
759
760 ::Size aBmpSize( aBmpEx.GetSizePixel() );
761
762 // setup alpha modulation
763 if( bModulateColors )
764 {
765 const double nAlphaModulation( renderState.DeviceColor[3] );
766
767 // TODO(F1): Note that the GraphicManager has a
768 // subtle difference in how it calculates the
769 // resulting alpha value: it's using the inverse
770 // alpha values (i.e. 'transparency'), and
771 // calculates transOrig + transModulate, instead
772 // of transOrig + transModulate -
773 // transOrig*transModulate (which would be
774 // equivalent to the origAlpha*modulateAlpha the
775 // DX canvas performs)
776 aGrfAttr.SetAlpha(
777 static_cast< sal_uInt8 >(
778 ::basegfx::fround( 255.0 * nAlphaModulation ) ) );
779 }
780
781 if( ::basegfx::fTools::equalZero( nShearX ) )
782 {
783 // no shear, GraphicObject is enough (the
784 // GraphicObject only supports scaling, rotation
785 // and translation)
786
787 // #i75339# don't apply mirror flags, having
788 // negative size values is enough to make
789 // GraphicObject flip the bitmap
790
791 // The angle has to be mapped from radian to tenths of
792 // degrees with the orientation reversed: [0,2Pi) ->
793 // (3600,0]. Note that the original angle may have
794 // values outside the [0,2Pi) interval.
795 const double nAngleInTenthOfDegrees (3600.0 - basegfx::rad2deg<10>(nRotate));
796 aGrfAttr.SetRotation( Degree10(::basegfx::fround(nAngleInTenthOfDegrees)) );
797
798 pGrfObj = std::make_shared<GraphicObject>( aBmpEx );
799 }
800 else
801 {
802 // modify output position, to account for the fact
803 // that transformBitmap() always normalizes its output
804 // bitmap into the smallest enclosing box.
805 ::basegfx::B2DRectangle aDestRect;
808 0,
809 aBmpSize.Width(),
810 aBmpSize.Height()),
811 aMatrix );
812
813 aOutputPos.setX( aDestRect.getMinX() );
814 aOutputPos.setY( aDestRect.getMinY() );
815
816 // complex transformation, use generic affine bitmap
817 // transformation
818 aBmpEx = tools::transformBitmap( aBmpEx,
819 aMatrix );
820
821 pGrfObj = std::make_shared<GraphicObject>( aBmpEx );
822
823 // clear scale values, generated bitmap already
824 // contains scaling
825 aScale.setX( 1.0 ); aScale.setY( 1.0 );
826
827 // update bitmap size, bitmap has changed above.
828 aBmpSize = aBmpEx.GetSizePixel();
829 }
830
831 // output GraphicObject
832 const ::Point aPt( vcl::unotools::pointFromB2DPoint( aOutputPos ) );
833 const ::Size aSz( ::basegfx::fround( aScale.getX() * aBmpSize.Width() ),
834 ::basegfx::fround( aScale.getY() * aBmpSize.Height() ) );
835
836 pGrfObj->Draw(mpOutDevProvider->getOutDev(),
837 aPt,
838 aSz,
839 &aGrfAttr);
840
842 pGrfObj->Draw(mp2ndOutDevProvider->getOutDev(),
843 aPt,
844 aSz,
845 &aGrfAttr);
846
847 // created GraphicObject, which possibly cached
848 // display bitmap - return cache object, to retain
849 // that information.
850 return uno::Reference< rendering::XCachedPrimitive >(
851 new CachedBitmap( pGrfObj,
852 aPt,
853 aSz,
854 aGrfAttr,
855 viewState,
856 renderState,
857 // cast away const, need to
858 // change refcount (as this is
859 // ~invisible to client code,
860 // still logically const)
861 const_cast< rendering::XCanvas* >(pCanvas)) );
862 }
863 }
864
865 // Nothing rendered
866 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
867 }
868
869 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmap( const rendering::XCanvas* pCanvas,
870 const uno::Reference< rendering::XBitmap >& xBitmap,
871 const rendering::ViewState& viewState,
872 const rendering::RenderState& renderState )
873 {
874 return implDrawBitmap( pCanvas,
875 xBitmap,
876 viewState,
877 renderState,
878 false );
879 }
880
881 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* pCanvas,
882 const uno::Reference< rendering::XBitmap >& xBitmap,
883 const rendering::ViewState& viewState,
884 const rendering::RenderState& renderState )
885 {
886 return implDrawBitmap( pCanvas,
887 xBitmap,
888 viewState,
889 renderState,
890 true );
891 }
892
893 geometry::IntegerSize2D CanvasHelper::getSize()
894 {
895 if( !mpOutDevProvider )
896 return geometry::IntegerSize2D(); // we're disposed
897
898 return vcl::unotools::integerSize2DFromSize( mpOutDevProvider->getOutDev().GetOutputSizePixel() );
899 }
900
901 uno::Reference< rendering::XBitmap > CanvasHelper::getScaledBitmap( const geometry::RealSize2D& newSize,
902 bool beFast )
903 {
904 if( !mpOutDevProvider || !mpDevice )
905 return uno::Reference< rendering::XBitmap >(); // we're disposed
906
907 OutputDevice& rOutDev( mpOutDevProvider->getOutDev() );
908
910 rOutDev.EnableMapMode( false );
911 rOutDev.SetAntialiasing( AntialiasingFlags::Enable );
912
913 // TODO(F2): Support alpha vdev canvas here
914 const Point aEmptyPoint(0,0);
915 const Size aBmpSize( rOutDev.GetOutputSizePixel() );
916
917 BitmapEx aBitmap( rOutDev.GetBitmapEx(aEmptyPoint, aBmpSize) );
918
919 aBitmap.Scale( vcl::unotools::sizeFromRealSize2D(newSize),
920 beFast ? BmpScaleFlag::Default : BmpScaleFlag::BestQuality );
921
922 return uno::Reference< rendering::XBitmap >(
923 new CanvasBitmap( aBitmap, *mpDevice, mpOutDevProvider ) );
924 }
925
926 uno::Sequence< sal_Int8 > CanvasHelper::getData( rendering::IntegerBitmapLayout& rLayout,
927 const geometry::IntegerRectangle2D& rect )
928 {
929 if( !mpOutDevProvider )
930 return uno::Sequence< sal_Int8 >(); // we're disposed
931
932 rLayout = getMemoryLayout();
933
934 // TODO(F2): Support alpha canvas here
935 const ::tools::Rectangle aRect( vcl::unotools::rectangleFromIntegerRectangle2D(rect) );
936
937 OutputDevice& rOutDev( mpOutDevProvider->getOutDev() );
938
939 tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDevProvider );
940 rOutDev.EnableMapMode( false );
941 rOutDev.SetAntialiasing( AntialiasingFlags::Enable );
942
943 Bitmap aBitmap( rOutDev.GetBitmapEx(aRect.TopLeft(),
944 aRect.GetSize()).GetBitmap() );
945
946 Bitmap::ScopedReadAccess pReadAccess( aBitmap );
947
948 ENSURE_OR_THROW( pReadAccess.get() != nullptr,
949 "Could not acquire read access to OutDev bitmap" );
950
951 const sal_Int32 nWidth( rect.X2 - rect.X1 );
952 const sal_Int32 nHeight( rect.Y2 - rect.Y1 );
953
954 rLayout.ScanLines = nHeight;
955 rLayout.ScanLineBytes = nWidth*4;
956 rLayout.ScanLineStride = rLayout.ScanLineBytes;
957
958 uno::Sequence< sal_Int8 > aRes( 4*nWidth*nHeight );
959 sal_Int8* pRes = aRes.getArray();
960
961 int nCurrPos(0);
962 for( int y=0; y<nHeight; ++y )
963 {
964 for( int x=0; x<nWidth; ++x )
965 {
966 pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetRed();
967 pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetGreen();
968 pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetBlue();
969 pRes[ nCurrPos++ ] = -1;
970 }
971 }
972
973 return aRes;
974 }
975
976 uno::Sequence< sal_Int8 > CanvasHelper::getPixel( rendering::IntegerBitmapLayout& rLayout,
977 const geometry::IntegerPoint2D& pos )
978 {
979 if( !mpOutDevProvider )
980 return uno::Sequence< sal_Int8 >(); // we're disposed
981
982 rLayout = getMemoryLayout();
983 rLayout.ScanLines = 1;
984 rLayout.ScanLineBytes = 4;
985 rLayout.ScanLineStride = rLayout.ScanLineBytes;
986
987 OutputDevice& rOutDev( mpOutDevProvider->getOutDev() );
988
989 tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDevProvider );
990 rOutDev.EnableMapMode( false );
991 rOutDev.SetAntialiasing( AntialiasingFlags::Enable );
992
993 const Size aBmpSize( rOutDev.GetOutputSizePixel() );
994
995 ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aBmpSize.Width(),
996 "X coordinate out of bounds" );
997 ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aBmpSize.Height(),
998 "Y coordinate out of bounds" );
999
1000 // TODO(F2): Support alpha canvas here
1002 rOutDev.GetPixel(
1004 }
1005
1006 rendering::IntegerBitmapLayout CanvasHelper::getMemoryLayout()
1007 {
1008 if( !mpOutDevProvider )
1009 return rendering::IntegerBitmapLayout(); // we're disposed
1010
1011 rendering::IntegerBitmapLayout aBitmapLayout( ::canvas::tools::getStdMemoryLayout(getSize()) );
1012 if ( !mbHaveAlpha )
1013 aBitmapLayout.ColorSpace = canvas::tools::getStdColorSpaceWithoutAlpha();
1014
1015 return aBitmapLayout;
1016 }
1017
1018 int CanvasHelper::setupOutDevState( const rendering::ViewState& viewState,
1019 const rendering::RenderState& renderState,
1020 ColorType eColorType ) const
1021 {
1023 "outdev null. Are we disposed?" );
1024
1025 ::canvas::tools::verifyInput( renderState,
1026 __func__,
1027 mpDevice,
1028 2,
1029 eColorType == IGNORE_COLOR ? 0 : 3 );
1030
1031 OutputDevice& rOutDev( mpOutDevProvider->getOutDev() );
1032 OutputDevice* p2ndOutDev = nullptr;
1033
1034 rOutDev.EnableMapMode( false );
1035 rOutDev.SetAntialiasing( AntialiasingFlags::Enable );
1036
1038 p2ndOutDev = &mp2ndOutDevProvider->getOutDev();
1039
1040 int nAlpha(255);
1041
1042 // TODO(P2): Don't change clipping all the time, maintain current clip
1043 // state and change only when update is necessary
1044 ::canvas::tools::clipOutDev(viewState, renderState, rOutDev, p2ndOutDev);
1045
1046 Color aColor( COL_WHITE );
1047
1048 if( renderState.DeviceColor.getLength() > 2 )
1049 {
1051 renderState.DeviceColor );
1052 }
1053
1054 // extract alpha, and make color opaque
1055 // afterwards. Otherwise, OutputDevice won't draw anything
1056 nAlpha = aColor.GetAlpha();
1057 aColor.SetAlpha(255);
1058
1059 if( eColorType != IGNORE_COLOR )
1060 {
1061 switch( eColorType )
1062 {
1063 case LINE_COLOR:
1064 rOutDev.SetLineColor( aColor );
1065 rOutDev.SetFillColor();
1066
1067 if( p2ndOutDev )
1068 {
1069 p2ndOutDev->SetLineColor( aColor );
1070 p2ndOutDev->SetFillColor();
1071 }
1072 break;
1073
1074 case FILL_COLOR:
1075 rOutDev.SetFillColor( aColor );
1076 rOutDev.SetLineColor();
1077
1078 if( p2ndOutDev )
1079 {
1080 p2ndOutDev->SetFillColor( aColor );
1081 p2ndOutDev->SetLineColor();
1082 }
1083 break;
1084
1085 case TEXT_COLOR:
1086 rOutDev.SetTextColor( aColor );
1087
1088 if( p2ndOutDev )
1089 p2ndOutDev->SetTextColor( aColor );
1090 break;
1091
1092 default:
1093 ENSURE_OR_THROW( false,
1094 "Unexpected color type");
1095 break;
1096 }
1097 }
1098
1099 return nAlpha;
1100 }
1101
1102 bool CanvasHelper::setupTextOutput( ::Point& o_rOutPos,
1103 const rendering::ViewState& viewState,
1104 const rendering::RenderState& renderState,
1105 const uno::Reference< rendering::XCanvasFont >& xFont ) const
1106 {
1108 "outdev null. Are we disposed?" );
1109
1110 OutputDevice& rOutDev( mpOutDevProvider->getOutDev() );
1111
1112 setupOutDevState( viewState, renderState, TEXT_COLOR );
1113
1114 CanvasFont* pFont = dynamic_cast< CanvasFont* >( xFont.get() );
1115
1116 ENSURE_ARG_OR_THROW( pFont,
1117 "Font not compatible with this canvas" );
1118
1119 vcl::Font aVCLFont = pFont->getVCLFont();
1120
1121 Color aColor( COL_BLACK );
1122
1123 if( renderState.DeviceColor.getLength() > 2 )
1124 {
1126 renderState.DeviceColor );
1127 }
1128
1129 // setup font color
1130 aVCLFont.SetColor( aColor );
1131 aVCLFont.SetFillColor( aColor );
1132
1133 // no need to replicate this for mp2ndOutDev, we're modifying only aVCLFont here.
1134 if( !tools::setupFontTransform( o_rOutPos, aVCLFont, viewState, renderState, rOutDev ) )
1135 return false;
1136
1137 rOutDev.SetFont( aVCLFont );
1138
1140 mp2ndOutDevProvider->getOutDev().SetFont( aVCLFont );
1141
1142 return true;
1143 }
1144
1146 const rendering::ViewState& viewState,
1147 const rendering::RenderState& renderState,
1148 const ::Point& rPt,
1149 const ::Size& rSz,
1150 const GraphicAttr& rAttr ) const
1151 {
1153 "Invalid Graphic" );
1154
1155 if( !mpOutDevProvider )
1156 return false; // disposed
1157 else
1158 {
1160 setupOutDevState( viewState, renderState, IGNORE_COLOR );
1161
1162 if (!rGrf->Draw(mpOutDevProvider->getOutDev(), rPt, rSz, &rAttr))
1163 return false;
1164
1165 // #i80779# Redraw also into mask outdev
1167 return rGrf->Draw(mp2ndOutDevProvider->getOutDev(), rPt, rSz, &rAttr);
1168
1169 return true;
1170 }
1171 }
1172
1174 {
1175 if (mpOutDevProvider)
1176 mpOutDevProvider->getOutDev().Flush();
1177
1179 mp2ndOutDevProvider->getOutDev().Flush();
1180 }
1181
1182}
1183
1184/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsAlpha() const
const Size & GetSizePixel() const
static bool Filter(BitmapEx &rBmpEx, BitmapFilter const &rFilter)
sal_uInt8 GetAlpha() const
void SetAlpha(sal_uInt8 nAlpha)
void SetRotation(Degree10 nRotate10)
void SetAlpha(sal_uInt8 cAlpha)
void EnableMapMode(bool bEnable=true)
void SetAntialiasing(AntialiasingFlags nMode)
void SetFont(const vcl::Font &rNewFont)
Size GetOutputSizePixel() const
void DrawRect(const tools::Rectangle &rRect)
void SetLineColor()
void SetTextColor(const Color &rColor)
void SetClipRegion()
void SetFillColor()
void SetDrawMode(DrawModeFlags nDrawMode)
constexpr tools::Long Height() const
constexpr tools::Long Width() const
bool decompose(B2DTuple &rScale, B2DTuple &rTranslate, double &rRotate, double &rShearX) const
double get(sal_uInt16 nRow, sal_uInt16 nColumn) const
void scale(double fX, double fY)
bool isIdentity() const
B2DPolygon const & getB2DPolygon(sal_uInt32 nIndex) const
void append(const B2DPolygon &rPolygon, sal_uInt32 nCount=1)
void transform(const basegfx::B2DHomMatrix &rMatrix)
sal_uInt32 count() const
bool isClosed() const
TYPE getMinX() const
TYPE getMinY() const
TYPE getX() const
void setY(TYPE fY)
TYPE getY() const
void setX(TYPE fX)
void SetFillColor(const Color &)
void SetColor(const Color &)
vcl::Font const & getVCLFont() const
Definition: canvasfont.cxx:171
css::uno::Reference< css::rendering::XCachedPrimitive > strokeTextureMappedPolyPolygon(const css::rendering::XCanvas *rCanvas, const css::uno::Reference< css::rendering::XPolyPolygon2D > &xPolyPolygon, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, const css::uno::Sequence< css::rendering::Texture > &textures, const css::uno::Reference< css::geometry::XMapping2D > &xMapping, const css::rendering::StrokeAttributes &strokeAttributes)
CanvasHelper()
Create canvas helper.
css::geometry::IntegerSize2D getSize()
css::rendering::XGraphicDevice * mpDevice
Phyical output device.
css::uno::Reference< css::rendering::XCachedPrimitive > drawTextLayout(const css::rendering::XCanvas *rCanvas, const css::uno::Reference< css::rendering::XTextLayout > &laidOutText, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
void flush() const
Flush drawing queue.
OutDevProviderSharedPtr mpProtectedOutDevProvider
Rendering to this outdev preserves its state.
void disposing()
Release all references.
bool repaint(const GraphicObjectSharedPtr &rGrf, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, const ::Point &rPt, const ::Size &rSz, const GraphicAttr &rAttr) const
Repaint a cached bitmap.
css::uno::Sequence< css::rendering::FontInfo > queryAvailableFonts(const css::rendering::XCanvas *rCanvas, const css::rendering::FontInfo &aFilter, const css::uno::Sequence< css::beans::PropertyValue > &aFontProperties)
int setupOutDevState(const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, ColorType eColorType) const
css::uno::Reference< css::rendering::XCachedPrimitive > drawPolyPolygon(const css::rendering::XCanvas *rCanvas, const css::uno::Reference< css::rendering::XPolyPolygon2D > &xPolyPolygon, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
css::uno::Reference< css::rendering::XCachedPrimitive > strokeTexturedPolyPolygon(const css::rendering::XCanvas *rCanvas, const css::uno::Reference< css::rendering::XPolyPolygon2D > &xPolyPolygon, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, const css::uno::Sequence< css::rendering::Texture > &textures, const css::rendering::StrokeAttributes &strokeAttributes)
css::uno::Reference< css::rendering::XPolyPolygon2D > queryStrokeShapes(const css::rendering::XCanvas *rCanvas, const css::uno::Reference< css::rendering::XPolyPolygon2D > &xPolyPolygon, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, const css::rendering::StrokeAttributes &strokeAttributes)
css::rendering::IntegerBitmapLayout getMemoryLayout()
css::uno::Reference< css::rendering::XCachedPrimitive > fillTextureMappedPolyPolygon(const css::rendering::XCanvas *rCanvas, const css::uno::Reference< css::rendering::XPolyPolygon2D > &xPolyPolygon, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, const css::uno::Sequence< css::rendering::Texture > &textures, const css::uno::Reference< css::geometry::XMapping2D > &xMapping)
css::uno::Reference< css::rendering::XCachedPrimitive > strokePolyPolygon(const css::rendering::XCanvas *rCanvas, const css::uno::Reference< css::rendering::XPolyPolygon2D > &xPolyPolygon, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, const css::rendering::StrokeAttributes &strokeAttributes)
void setOutDev(const OutDevProviderSharedPtr &rOutDev, bool bProtect)
Set primary output device.
void init(css::rendering::XGraphicDevice &rDevice, const OutDevProviderSharedPtr &rOutDev, bool bProtect, bool bHaveAlpha)
Initialize canvas helper.
css::uno::Reference< css::rendering::XCachedPrimitive > drawBitmap(const css::rendering::XCanvas *rCanvas, const css::uno::Reference< css::rendering::XBitmap > &xBitmap, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
bool setupTextOutput(::Point &o_rOutPos, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, const css::uno::Reference< css::rendering::XCanvasFont > &xFont) const
css::uno::Reference< css::rendering::XCachedPrimitive > implDrawBitmap(const css::rendering::XCanvas *rCanvas, const css::uno::Reference< css::rendering::XBitmap > &xBitmap, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, bool bModulateColors)
void drawLine(const css::rendering::XCanvas *rCanvas, const css::geometry::RealPoint2D &aStartPoint, const css::geometry::RealPoint2D &aEndPoint, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
css::uno::Sequence< sal_Int8 > getPixel(css::rendering::IntegerBitmapLayout &bitmapLayout, const css::geometry::IntegerPoint2D &pos)
css::uno::Reference< css::rendering::XCachedPrimitive > drawBitmapModulated(const css::rendering::XCanvas *rCanvas, const css::uno::Reference< css::rendering::XBitmap > &xBitmap, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
OutDevProviderSharedPtr mpOutDevProvider
Rendering to this outdev does not preserve its state.
OutDevProviderSharedPtr mp2ndOutDevProvider
Rendering to this outdev does not preserve its state.
css::uno::Reference< css::rendering::XCanvasFont > createFont(const css::rendering::XCanvas *rCanvas, const css::rendering::FontRequest &fontRequest, const css::uno::Sequence< css::beans::PropertyValue > &extraFontProperties, const css::geometry::Matrix2D &fontMatrix)
void setBackgroundOutDev(const OutDevProviderSharedPtr &rOutDev)
Set secondary output device.
void drawBezier(const css::rendering::XCanvas *rCanvas, const css::geometry::RealBezierSegment2D &aBezierSegment, const css::geometry::RealPoint2D &aEndPoint, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
css::uno::Reference< css::rendering::XCachedPrimitive > drawText(const css::rendering::XCanvas *rCanvas, const css::rendering::StringContext &text, const css::uno::Reference< css::rendering::XCanvasFont > &xFont, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, sal_Int8 textDirection)
css::uno::Sequence< sal_Int8 > getData(css::rendering::IntegerBitmapLayout &bitmapLayout, const css::geometry::IntegerRectangle2D &rect)
css::uno::Reference< css::rendering::XBitmap > getScaledBitmap(const css::geometry::RealSize2D &newSize, bool beFast)
css::uno::Reference< css::rendering::XCachedPrimitive > fillPolyPolygon(const css::rendering::XCanvas *rCanvas, const css::uno::Reference< css::rendering::XPolyPolygon2D > &xPolyPolygon, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
bool mbHaveAlpha
When true, content is able to represent alpha.
constexpr ::Color COL_WHITE(0xFF, 0xFF, 0xFF)
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
#define ENSURE_OR_RETURN_FALSE(c, m)
#define ENSURE_OR_THROW(c, m)
#define ENSURE_ARG_OR_THROW(c, m)
sal::systools::COMReference< IDirect3DDevice9 > mpDevice
Definition: dx_9rm.cxx:169
float y
Definition: dx_9rm.cxx:190
float x
Definition: dx_9rm.cxx:190
def text(shape, orig_st)
VCL_DLLPUBLIC bool isVCLSkiaEnabled()
void applyLineDashing(const B2DPolygon &rCandidate, const std::vector< double > &rDotDashArray, B2DPolyPolygon *pLineTarget, B2DPolyPolygon *pGapTarget, double fDotDashLength)
B2DPolyPolygon createAreaGeometry(const B2DPolygon &rCandidate, double fHalfLineWidth, B2DLineJoin eJoin, css::drawing::LineCap eCap, double fMaxAllowedAngle=basegfx::deg2rad(12.5), double fMaxPartOfEdge=0.4, double fMiterMinimumAngle=basegfx::deg2rad(15.0), basegfx::triangulator::B2DTriangleVector *pTriangles=nullptr)
constexpr double deg2rad(double v)
uno::Reference< rendering::XIntegerBitmapColorSpace > const & getStdColorSpaceWithoutAlpha()
Return a color space for a default RGB integer format.
::basegfx::B2DHomMatrix & mergeViewAndRenderTransform(::basegfx::B2DHomMatrix &combinedTransform, const rendering::ViewState &viewState, const rendering::RenderState &renderState)
rendering::IntegerBitmapLayout getStdMemoryLayout(const geometry::IntegerSize2D &rBmpSize)
uno::Sequence< sal_Int8 > colorToStdIntSequence(const ::Color &rColor)
Convert standard 8888 RGBA color to vcl color.
::basegfx::B2DRange & calcTransformedRectBounds(::basegfx::B2DRange &outRect, const ::basegfx::B2DRange &inRect, const ::basegfx::B2DHomMatrix &transformation)
Calc the bounding rectangle of a transformed rectangle.
void verifyInput(const geometry::RealPoint2D &rPoint, const char *pStr, const uno::Reference< uno::XInterface > &xIf, ::sal_Int16 nArgPos)
Definition: verifyinput.cxx:51
void clipOutDev(const rendering::ViewState &viewState, const rendering::RenderState &renderState, OutputDevice &rOutDev, OutputDevice *p2ndOutDev)
int i
ComplexTextLayoutFlags
Size sizeFromRealSize2D(const geometry::RealSize2D &rSize)
Color stdColorSpaceSequenceToColor(const uno::Sequence< double > &rColor)
Point pointFromIntegerPoint2D(const geometry::IntegerPoint2D &rPoint)
geometry::IntegerSize2D integerSize2DFromSize(const Size &rSize)
::Point pointFromB2DPoint(const basegfx::B2DPoint &rPoint)
tools::Rectangle rectangleFromIntegerRectangle2D(const geometry::IntegerRectangle2D &rRectangle)
::tools::PolyPolygon mapPolyPolygon(const ::basegfx::B2DPolyPolygon &rPoly, const rendering::ViewState &rViewState, const rendering::RenderState &rRenderState)
Definition: impltools.cxx:172
bool setupFontTransform(::Point &o_rPoint, vcl::Font &io_rVCLFont, const rendering::ViewState &rViewState, const rendering::RenderState &rRenderState, ::OutputDevice const &rOutDev)
Definition: impltools.cxx:87
::BitmapEx transformBitmap(const BitmapEx &rBitmap, const ::basegfx::B2DHomMatrix &rTransform)
Definition: impltools.cxx:188
::Point mapRealPoint2D(const geometry::RealPoint2D &rPoint, const rendering::ViewState &rViewState, const rendering::RenderState &rRenderState)
Definition: impltools.cxx:158
::BitmapEx bitmapExFromXBitmap(const uno::Reference< rendering::XBitmap > &xBitmap)
Definition: impltools.cxx:49
std::shared_ptr< OutDevProvider > OutDevProviderSharedPtr
std::shared_ptr< GraphicObject > GraphicObjectSharedPtr
unsigned char sal_uInt8
signed char sal_Int8
size_t pos