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