LibreOffice Module vcl (master)  1
GraphicObject2.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 
22 #include <tools/gen.hxx>
23 #include <vcl/outdev.hxx>
24 #include <vcl/alpha.hxx>
25 #include <vcl/virdev.hxx>
26 #include <vcl/GraphicObject.hxx>
27 #include <memory>
28 
30 {
32 
33  Point aTileTopLeft; // top, left position of the rendered tile
34  Point aNextTileTopLeft; // top, left position for next recursion
35  // level's tile
36  Size aTileSizePixel; // size of the generated tile (might
37  // differ from
38  // aNextTileTopLeft-aTileTopLeft, because
39  // this is nExponent*prevTileSize. The
40  // generated tile is always nExponent
41  // times the previous tile, such that it
42  // can be used in the next stage. The
43  // required area coverage is often
44  // less. The extraneous area covered is
45  // later overwritten by the next stage)
46  int nTilesEmptyX; // number of original tiles empty right of
47  // this tile. This counts from
48  // aNextTileTopLeft, i.e. the additional
49  // area covered by aTileSizePixel is not
50  // considered here. This is for
51  // unification purposes, as the iterative
52  // calculation of the next level's empty
53  // tiles has to be based on this value.
54  int nTilesEmptyY; // as above, for Y
55 };
56 
57 
59  int nNumTilesX, int nNumTilesY,
60  const Size& rTileSizePixel,
61  const GraphicAttr* pAttr )
62 {
63  // how many tiles to generate per recursion step
64  const int nExponent = 2;
65 
66  // determine MSB factor
67  int nMSBFactor( 1 );
68  while( nNumTilesX / nMSBFactor != 0 ||
69  nNumTilesY / nMSBFactor != 0 )
70  {
71  nMSBFactor *= nExponent;
72  }
73 
74  // one less
75  if(nMSBFactor > 1)
76  {
77  nMSBFactor /= nExponent;
78  }
79  ImplTileInfo aTileInfo;
80 
81  // #105229# Switch off mapping (converting to logic and back to
82  // pixel might cause roundoff errors)
83  bool bOldMap( rVDev.IsMapModeEnabled() );
84  rVDev.EnableMapMode( false );
85 
86  bool bRet( ImplRenderTileRecursive( rVDev, nExponent, nMSBFactor, nNumTilesX, nNumTilesY,
87  nNumTilesX, nNumTilesY, rTileSizePixel, pAttr, aTileInfo ) );
88 
89  rVDev.EnableMapMode( bOldMap );
90 
91  return bRet;
92 }
93 
94 // define for debug drawings
95 //#define DBG_TEST
96 
97 // see header comment. this works similar to base conversion of a
98 // number, i.e. if the exponent is 10, then the number for every tile
99 // size is given by the decimal place of the corresponding decimal
100 // representation.
101 bool GraphicObject::ImplRenderTileRecursive( VirtualDevice& rVDev, int nExponent, int nMSBFactor,
102  int nNumOrigTilesX, int nNumOrigTilesY,
103  int nRemainderTilesX, int nRemainderTilesY,
104  const Size& rTileSizePixel, const GraphicAttr* pAttr,
105  ImplTileInfo& rTileInfo )
106 {
107  // gets loaded with our tile bitmap
108  std::unique_ptr<GraphicObject> xTmpGraphic;
109  GraphicObject* pTileGraphic;
110 
111  // stores a flag that renders the zero'th tile position
112  // (i.e. (0,0)+rCurrPos) only if we're at the bottom of the
113  // recursion stack. All other position already have that tile
114  // rendered, because the lower levels painted their generated tile
115  // there.
116  bool bNoFirstTileDraw( false );
117 
118  // what's left when we're done with our tile size
119  const int nNewRemainderX( nRemainderTilesX % nMSBFactor );
120  const int nNewRemainderY( nRemainderTilesY % nMSBFactor );
121 
122  // gets filled out from the recursive call with info of what's
123  // been generated
124  ImplTileInfo aTileInfo;
125 
126  // check for recursion's end condition: LSB place reached?
127  if( nMSBFactor == 1 )
128  {
129  pTileGraphic = this;
130 
131  // set initial tile size -> orig size
132  aTileInfo.aTileSizePixel = rTileSizePixel;
133  aTileInfo.nTilesEmptyX = nNumOrigTilesX;
134  aTileInfo.nTilesEmptyY = nNumOrigTilesY;
135  }
136  else if( ImplRenderTileRecursive( rVDev, nExponent, nMSBFactor/nExponent,
137  nNumOrigTilesX, nNumOrigTilesY,
138  nNewRemainderX, nNewRemainderY,
139  rTileSizePixel, pAttr, aTileInfo ) )
140  {
141  // extract generated tile -> see comment on the first loop below
142  BitmapEx aTileBitmap( rVDev.GetBitmap( aTileInfo.aTileTopLeft, aTileInfo.aTileSizePixel ) );
143 
144  xTmpGraphic.reset(new GraphicObject(aTileBitmap));
145  pTileGraphic = xTmpGraphic.get();
146 
147  // fill stripes left over from upstream levels:
148 
149  // x0000
150  // 0
151  // 0
152  // 0
153  // 0
154 
155  // where x denotes the place filled by our recursive predecessors
156 
157  // check whether we have to fill stripes here. Although not
158  // obvious, there is one case where we can skip this step: if
159  // the previous recursion level (the one who filled our
160  // aTileInfo) had zero area to fill, then there are no white
161  // stripes left, naturally. This happens if the digit
162  // associated to that level has a zero, and can be checked via
163  // aTileTopLeft==aNextTileTopLeft.
164  if( aTileInfo.aTileTopLeft != aTileInfo.aNextTileTopLeft )
165  {
166  // now fill one row from aTileInfo.aNextTileTopLeft.X() all
167  // the way to the right
168  // current output position while drawing
169  Point aCurrPos(aTileInfo.aNextTileTopLeft.X(), aTileInfo.aTileTopLeft.Y());
170  for (int nX=0; nX < aTileInfo.nTilesEmptyX; nX += nMSBFactor)
171  {
172  if (!pTileGraphic->Draw(&rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr))
173  return false;
174 
175  aCurrPos.AdjustX(aTileInfo.aTileSizePixel.Width() );
176  }
177 
178 #ifdef DBG_TEST
179 // rVDev.SetFillCOL_WHITE );
180  rVDev.SetFillColor();
181  rVDev.SetLineColor( Color( 255 * nExponent / nMSBFactor, 255 - 255 * nExponent / nMSBFactor, 128 - 255 * nExponent / nMSBFactor ) );
182  rVDev.DrawEllipse( tools::Rectangle(aTileInfo.aNextTileTopLeft.X(), aTileInfo.aTileTopLeft.Y(),
183  aTileInfo.aNextTileTopLeft.X() - 1 + (aTileInfo.nTilesEmptyX/nMSBFactor)*aTileInfo.aTileSizePixel.Width(),
184  aTileInfo.aTileTopLeft.Y() + aTileInfo.aTileSizePixel.Height() - 1) );
185 #endif
186 
187  // now fill one column from aTileInfo.aNextTileTopLeft.Y() all
188  // the way to the bottom
189  aCurrPos.setX( aTileInfo.aTileTopLeft.X() );
190  aCurrPos.setY( aTileInfo.aNextTileTopLeft.Y() );
191  for (int nY=0; nY < aTileInfo.nTilesEmptyY; nY += nMSBFactor)
192  {
193  if (!pTileGraphic->Draw(&rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr))
194  return false;
195 
196  aCurrPos.AdjustY(aTileInfo.aTileSizePixel.Height() );
197  }
198 
199 #ifdef DBG_TEST
200  rVDev.DrawEllipse( tools::Rectangle(aTileInfo.aTileTopLeft.X(), aTileInfo.aNextTileTopLeft.Y(),
201  aTileInfo.aTileTopLeft.X() + aTileInfo.aTileSizePixel.Width() - 1,
202  aTileInfo.aNextTileTopLeft.Y() - 1 + (aTileInfo.nTilesEmptyY/nMSBFactor)*aTileInfo.aTileSizePixel.Height()) );
203 #endif
204  }
205  else
206  {
207  // Thought that aTileInfo.aNextTileTopLeft tile has always
208  // been drawn already, but that's wrong: typically,
209  // _parts_ of that tile have been drawn, since the
210  // previous level generated the tile there. But when
211  // aTileInfo.aNextTileTopLeft!=aTileInfo.aTileTopLeft, the
212  // difference between these two values is missing in the
213  // lower right corner of this first tile. So, can do that
214  // only here.
215  bNoFirstTileDraw = true;
216  }
217  }
218  else
219  {
220  return false;
221  }
222 
223  // calc number of original tiles in our drawing area without
224  // remainder
225  nRemainderTilesX -= nNewRemainderX;
226  nRemainderTilesY -= nNewRemainderY;
227 
228  // fill tile info for calling method
229  rTileInfo.aTileTopLeft = aTileInfo.aNextTileTopLeft;
230  rTileInfo.aNextTileTopLeft = Point( rTileInfo.aTileTopLeft.X() + rTileSizePixel.Width()*nRemainderTilesX,
231  rTileInfo.aTileTopLeft.Y() + rTileSizePixel.Height()*nRemainderTilesY );
232  rTileInfo.aTileSizePixel = Size( rTileSizePixel.Width()*nMSBFactor*nExponent,
233  rTileSizePixel.Height()*nMSBFactor*nExponent );
234  rTileInfo.nTilesEmptyX = aTileInfo.nTilesEmptyX - nRemainderTilesX;
235  rTileInfo.nTilesEmptyY = aTileInfo.nTilesEmptyY - nRemainderTilesY;
236 
237  // init output position
238  Point aCurrPos = aTileInfo.aNextTileTopLeft;
239 
240  // fill our drawing area. Fill possibly more, to create the next
241  // bigger tile size -> see bitmap extraction above. This does no
242  // harm, since everything right or below our actual area is
243  // overdrawn by our caller. Just in case we're in the last level,
244  // we don't draw beyond the right or bottom border.
245  for (int nY=0; nY < aTileInfo.nTilesEmptyY && nY < nExponent*nMSBFactor; nY += nMSBFactor)
246  {
247  aCurrPos.setX( aTileInfo.aNextTileTopLeft.X() );
248 
249  for (int nX=0; nX < aTileInfo.nTilesEmptyX && nX < nExponent*nMSBFactor; nX += nMSBFactor)
250  {
251  if( bNoFirstTileDraw )
252  bNoFirstTileDraw = false; // don't draw first tile position
253  else if (!pTileGraphic->Draw(&rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr))
254  return false;
255 
256  aCurrPos.AdjustX(aTileInfo.aTileSizePixel.Width() );
257  }
258 
259  aCurrPos.AdjustY(aTileInfo.aTileSizePixel.Height() );
260  }
261 
262 #ifdef DBG_TEST
263 // rVDev.SetFillCOL_WHITE );
264  rVDev.SetFillColor();
265  rVDev.SetLineColor( Color( 255 * nExponent / nMSBFactor, 255 - 255 * nExponent / nMSBFactor, 128 - 255 * nExponent / nMSBFactor ) );
266  rVDev.DrawRect( tools::Rectangle((rTileInfo.aTileTopLeft.X())*rTileSizePixel.Width(),
267  (rTileInfo.aTileTopLeft.Y())*rTileSizePixel.Height(),
268  (rTileInfo.aNextTileTopLeft.X())*rTileSizePixel.Width()-1,
269  (rTileInfo.aNextTileTopLeft.Y())*rTileSizePixel.Height()-1) );
270 #endif
271 
272  return true;
273 }
274 
275 bool GraphicObject::ImplDrawTiled( OutputDevice* pOut, const tools::Rectangle& rArea, const Size& rSizePixel,
276  const Size& rOffset, const GraphicAttr* pAttr, int nTileCacheSize1D )
277 {
278  const MapMode aOutMapMode( pOut->GetMapMode() );
279  const MapMode aMapMode( aOutMapMode.GetMapUnit(), Point(), aOutMapMode.GetScaleX(), aOutMapMode.GetScaleY() );
280  bool bRet( false );
281 
282  // #i42643# Casting to Int64, to avoid integer overflow for
283  // huge-DPI output devices
285  static_cast<sal_Int64>(rSizePixel.Width()) * rSizePixel.Height() <
286  static_cast<sal_Int64>(nTileCacheSize1D)*nTileCacheSize1D )
287  {
288  // First combine very small bitmaps into a larger tile
289 
290 
292  const int nNumTilesInCacheX( (nTileCacheSize1D + rSizePixel.Width()-1) / rSizePixel.Width() );
293  const int nNumTilesInCacheY( (nTileCacheSize1D + rSizePixel.Height()-1) / rSizePixel.Height() );
294 
295  aVDev->SetOutputSizePixel( Size( nNumTilesInCacheX*rSizePixel.Width(),
296  nNumTilesInCacheY*rSizePixel.Height() ) );
297  aVDev->SetMapMode( aMapMode );
298 
299  // draw bitmap content
300  if( ImplRenderTempTile( *aVDev, nNumTilesInCacheX,
301  nNumTilesInCacheY, rSizePixel, pAttr ) )
302  {
303  BitmapEx aTileBitmap( aVDev->GetBitmap( Point(0,0), aVDev->GetOutputSize() ) );
304 
305  // draw alpha content, if any
306  if( IsTransparent() )
307  {
308  GraphicObject aAlphaGraphic;
309 
310  if( GetGraphic().IsAlpha() )
311  aAlphaGraphic.SetGraphic( GetGraphic().GetBitmapEx().GetAlpha().GetBitmap() );
312  else
313  aAlphaGraphic.SetGraphic( GetGraphic().GetBitmapEx().GetMask() );
314 
315  if( aAlphaGraphic.ImplRenderTempTile( *aVDev, nNumTilesInCacheX,
316  nNumTilesInCacheY, rSizePixel, pAttr ) )
317  {
318  // Combine bitmap and alpha/mask
319  if( GetGraphic().IsAlpha() )
320  aTileBitmap = BitmapEx( aTileBitmap.GetBitmap(),
321  AlphaMask( aVDev->GetBitmap( Point(0,0), aVDev->GetOutputSize() ) ) );
322  else
323  aTileBitmap = BitmapEx( aTileBitmap.GetBitmap(),
324  aVDev->GetBitmap( Point(0,0), aVDev->GetOutputSize() ).CreateMask( COL_WHITE ) );
325  }
326  }
327 
328  // paint generated tile
329  GraphicObject aTmpGraphic( aTileBitmap );
330  bRet = aTmpGraphic.ImplDrawTiled( pOut, rArea,
331  aTileBitmap.GetSizePixel(),
332  rOffset, pAttr, nTileCacheSize1D );
333  }
334  }
335  else
336  {
337  const Size aOutOffset( pOut->LogicToPixel( rOffset, aOutMapMode ) );
338  const tools::Rectangle aOutArea( pOut->LogicToPixel( rArea, aOutMapMode ) );
339 
340  // number of invisible (because out-of-area) tiles
341  int nInvisibleTilesX;
342  int nInvisibleTilesY;
343 
344  // round towards -infty for negative offset
345  if( aOutOffset.Width() < 0 )
346  nInvisibleTilesX = (aOutOffset.Width() - rSizePixel.Width() + 1) / rSizePixel.Width();
347  else
348  nInvisibleTilesX = aOutOffset.Width() / rSizePixel.Width();
349 
350  // round towards -infty for negative offset
351  if( aOutOffset.Height() < 0 )
352  nInvisibleTilesY = (aOutOffset.Height() - rSizePixel.Height() + 1) / rSizePixel.Height();
353  else
354  nInvisibleTilesY = aOutOffset.Height() / rSizePixel.Height();
355 
356  // origin from where to 'virtually' start drawing in pixel
357  const Point aOutOrigin( pOut->LogicToPixel( Point( rArea.Left() - rOffset.Width(),
358  rArea.Top() - rOffset.Height() ) ) );
359  // position in pixel from where to really start output
360  const Point aOutStart( aOutOrigin.X() + nInvisibleTilesX*rSizePixel.Width(),
361  aOutOrigin.Y() + nInvisibleTilesY*rSizePixel.Height() );
362 
363  pOut->Push( PushFlags::CLIPREGION );
364  pOut->IntersectClipRegion( rArea );
365 
366  // Paint all tiles
367 
368 
369  bRet = ImplDrawTiled( *pOut, aOutStart,
370  (aOutArea.GetWidth() + aOutArea.Left() - aOutStart.X() + rSizePixel.Width() - 1) / rSizePixel.Width(),
371  (aOutArea.GetHeight() + aOutArea.Top() - aOutStart.Y() + rSizePixel.Height() - 1) / rSizePixel.Height(),
372  rSizePixel, pAttr );
373 
374  pOut->Pop();
375  }
376 
377  return bRet;
378 }
379 
380 bool GraphicObject::ImplDrawTiled( OutputDevice& rOut, const Point& rPosPixel,
381  int nNumTilesX, int nNumTilesY,
382  const Size& rTileSizePixel, const GraphicAttr* pAttr )
383 {
384  Point aCurrPos( rPosPixel );
385  Size aTileSizeLogic( rOut.PixelToLogic( rTileSizePixel ) );
386  int nX, nY;
387 
388  // #107607# Use logical coordinates for metafile playing, too
389  bool bDrawInPixel( rOut.GetConnectMetaFile() == nullptr && GraphicType::Bitmap == GetType() );
390  bool bRet = false;
391 
392  // #105229# Switch off mapping (converting to logic and back to
393  // pixel might cause roundoff errors)
394  bool bOldMap( rOut.IsMapModeEnabled() );
395 
396  if( bDrawInPixel )
397  rOut.EnableMapMode( false );
398 
399  for( nY=0; nY < nNumTilesY; ++nY )
400  {
401  aCurrPos.setX( rPosPixel.X() );
402 
403  for( nX=0; nX < nNumTilesX; ++nX )
404  {
405  // #105229# work with pixel coordinates here, mapping is disabled!
406  // #104004# don't disable mapping for metafile recordings
407  // #108412# don't quit the loop if one draw fails
408 
409  // update return value. This method should return true, if
410  // at least one of the looped Draws succeeded.
411  bRet |= Draw( &rOut,
412  bDrawInPixel ? aCurrPos : rOut.PixelToLogic( aCurrPos ),
413  bDrawInPixel ? rTileSizePixel : aTileSizeLogic,
414  pAttr );
415 
416  aCurrPos.AdjustX(rTileSizePixel.Width() );
417  }
418 
419  aCurrPos.AdjustY(rTileSizePixel.Height() );
420  }
421 
422  if( bDrawInPixel )
423  rOut.EnableMapMode( bOldMap );
424 
425  return bRet;
426 }
427 
429  const GraphicAttr& rAttr,
430  const Size& rCropLeftTop,
431  const Size& rCropRightBottom,
432  const tools::Rectangle& rCropRect,
433  const Size& rDstSize,
434  bool bEnlarge ) const
435 {
436  // #107947# Extracted from svdograf.cxx
437 
438  // #104115# Crop the bitmap
439  if( rAttr.IsCropped() )
440  {
441  rBmpEx.Crop( rCropRect );
442 
443  // #104115# Negative crop sizes mean: enlarge bitmap and pad
444  if( bEnlarge && (
445  rCropLeftTop.Width() < 0 ||
446  rCropLeftTop.Height() < 0 ||
447  rCropRightBottom.Width() < 0 ||
448  rCropRightBottom.Height() < 0 ) )
449  {
450  Size aBmpSize( rBmpEx.GetSizePixel() );
451  sal_Int32 nPadLeft( rCropLeftTop.Width() < 0 ? -rCropLeftTop.Width() : 0 );
452  sal_Int32 nPadTop( rCropLeftTop.Height() < 0 ? -rCropLeftTop.Height() : 0 );
453  sal_Int32 nPadTotalWidth( aBmpSize.Width() + nPadLeft + (rCropRightBottom.Width() < 0 ? -rCropRightBottom.Width() : 0) );
454  sal_Int32 nPadTotalHeight( aBmpSize.Height() + nPadTop + (rCropRightBottom.Height() < 0 ? -rCropRightBottom.Height() : 0) );
455 
456  BitmapEx aBmpEx2;
457 
458  if( rBmpEx.IsTransparent() )
459  {
460  if( rBmpEx.IsAlpha() )
461  aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), rBmpEx.GetAlpha() );
462  else
463  aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), rBmpEx.GetMask() );
464  }
465  else
466  {
467  // #104115# Generate mask bitmap and init to zero
468  Bitmap aMask( aBmpSize, 1 );
469  aMask.Erase( Color(0,0,0) );
470 
471  // #104115# Always generate transparent bitmap, we need the border transparent
472  aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), aMask );
473 
474  // #104115# Add opaque mask to source bitmap, otherwise the destination remains transparent
475  rBmpEx = aBmpEx2;
476  }
477 
478  aBmpEx2.Scale(Size(nPadTotalWidth, nPadTotalHeight));
479  aBmpEx2.Erase( Color(0xFF,0,0,0) );
480  aBmpEx2.CopyPixel( tools::Rectangle( Point(nPadLeft, nPadTop), aBmpSize ), tools::Rectangle( Point(0, 0), aBmpSize ), &rBmpEx );
481  rBmpEx = aBmpEx2;
482  }
483  }
484 
485  const Size aSizePixel( rBmpEx.GetSizePixel() );
486 
487  if( rAttr.GetRotation() == 0 || IsAnimated() )
488  return;
489 
490  if( !(aSizePixel.Width() && aSizePixel.Height() && rDstSize.Width() && rDstSize.Height()) )
491  return;
492 
493  double fSrcWH = static_cast<double>(aSizePixel.Width()) / aSizePixel.Height();
494  double fDstWH = static_cast<double>(rDstSize.Width()) / rDstSize.Height();
495  double fScaleX = 1.0, fScaleY = 1.0;
496 
497  // always choose scaling to shrink bitmap
498  if( fSrcWH < fDstWH )
499  fScaleY = aSizePixel.Width() / ( fDstWH * aSizePixel.Height() );
500  else
501  fScaleX = fDstWH * aSizePixel.Height() / aSizePixel.Width();
502 
503  rBmpEx.Scale( fScaleX, fScaleY );
504 }
505 
506 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
bool Erase(const Color &rFillColor)
Fill the entire bitmap with the given color.
Definition: bitmapex.cxx:569
Bitmap GetMask() const
Definition: bitmapex.cxx:258
bool Draw(OutputDevice *pOut, const Point &rPt, const Size &rSz, const GraphicAttr *pAttr=nullptr)
long AdjustX(long nHorzMove)
long Height() const
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: bitmapex.cxx:370
bool IsMapModeEnabled() const
Definition: outdev.hxx:1669
const MapMode & GetMapMode() const
Definition: outdev.hxx:1674
Point aNextTileTopLeft
void IntersectClipRegion(const tools::Rectangle &rRect)
GDIMetaFile * GetConnectMetaFile() const
Definition: outdev.hxx:417
void EnableMapMode(bool bEnable=true)
Definition: map.cxx:647
bool IsAlpha() const
Definition: bitmapex.cxx:226
void setX(long nX)
virtual Bitmap GetBitmap(const Point &rSrcPt, const Size &rSize) const
long Top() const
bool VCL_DLLPRIVATE ImplRenderTileRecursive(VirtualDevice &rVDev, int nExponent, int nMSBFactor, int nNumOrigTilesX, int nNumOrigTilesY, int nRemainderTilesX, int nRemainderTilesY, const Size &rTileSizePixel, const GraphicAttr *pAttr, ImplTileInfo &rTileInfo)
internally called by ImplRenderTempTile()
void DrawRect(const tools::Rectangle &rRect)
Definition: rect.cxx:32
Bitmap GetBitmap(const Color *pTransReplaceColor=nullptr) const
Definition: bitmapex.cxx:236
void SetLineColor()
bool IsCropped() const
long AdjustY(long nVertMove)
bool VCL_DLLPRIVATE ImplRenderTempTile(VirtualDevice &rVDev, int nNumTilesX, int nNumTilesY, const Size &rTileSizePixel, const GraphicAttr *pAttr)
Render a given number of tiles in an optimized way.
void SetFillColor()
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:304
bool CopyPixel(const tools::Rectangle &rRectDst, const tools::Rectangle &rRectSrc, const BitmapEx *pBmpExSrc)
Copy a rectangular area from another bitmap.
Definition: bitmapex.cxx:480
sal_uInt16 GetRotation() const
bool IsTransparent() const
Definition: bitmapex.cxx:221
bool IsAlpha() const
Definition: graph.cxx:334
long X() const
GraphicType GetType() const
void SetGraphic(const Graphic &rGraphic, const GraphicObject *pCopyObj=nullptr)
Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1185
Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:940
AlphaMask GetAlpha() const
Definition: bitmapex.cxx:268
const Graphic & GetGraphic() const
bool VCL_DLLPRIVATE ImplDrawTiled(OutputDevice *pOut, const tools::Rectangle &rArea, const Size &rSizePixel, const Size &rOffset, const GraphicAttr *pAttr, int nTileCacheSize1D)
constexpr::Color COL_WHITE(0xFF, 0xFF, 0xFF)
long Left() const
void DrawEllipse(const tools::Rectangle &rRect)
bool Erase(const Color &rFillColor)
Fill the entire bitmap with the given color.
Definition: bitmappaint.cxx:34
void VCL_DLLPRIVATE ImplTransformBitmap(BitmapEx &rBmpEx, const GraphicAttr &rAttr, const Size &rCropLeftTop, const Size &rCropRightBottom, const tools::Rectangle &rCropRect, const Size &rDstSize, bool bEnlarge) const
bool IsAnimated() const
const Size & GetSizePixel() const
Definition: bitmapex.hxx:83
void Push(PushFlags nFlags=PushFlags::ALL)
Definition: outdevstate.cxx:60
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
Definition: bitmapex.cxx:434
bool IsTransparent() const
long Y() const