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