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.
101bool 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(std::move(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
275bool GraphicObject::ImplDrawTiled(OutputDevice& rOut, const tools::Rectangle& rArea, const Size& rSizePixel,
276 const Size& rOffset, const GraphicAttr* pAttr, int nTileCacheSize1D)
277{
278 const MapMode aOutMapMode(rOut.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(BitmapEx(GetGraphic().GetBitmapEx().GetAlphaMask().GetBitmap()));
312 else
313 aAlphaGraphic.SetGraphic(BitmapEx(Bitmap()));
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(rOut, rArea,
331 aTileBitmap.GetSizePixel(),
332 rOffset, pAttr, nTileCacheSize1D);
333 }
334 }
335 else
336 {
337 const Size aOutOffset( rOut.LogicToPixel( rOffset, aOutMapMode ) );
338 const tools::Rectangle aOutArea( rOut.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( rOut.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
364 rOut.IntersectClipRegion( rArea );
365
366 // Paint all tiles
367
368
369 bRet = ImplDrawTiled(rOut, 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 rOut.Pop();
375 }
376
377 return bRet;
378}
379
380bool GraphicObject::ImplDrawTiled( OutputDevice& rOut, const Point& rPosPixel,
381 int nNumTilesX, int nNumTilesY,
382 const Size& rTileSizePixel, const GraphicAttr* pAttr ) const
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.IsAlpha() )
459 {
460 aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), rBmpEx.GetAlphaMask() );
461 }
462 else
463 {
464 // #104115# Generate mask bitmap and init to zero
465 AlphaMask aMask(aBmpSize);
466 aMask.Erase(255);
467
468 // #104115# Always generate transparent bitmap, we need the border transparent
469 aBmpEx2 = BitmapEx( rBmpEx.GetBitmap(), aMask );
470
471 // #104115# Add opaque mask to source bitmap, otherwise the destination remains transparent
472 rBmpEx = aBmpEx2;
473 }
474
475 aBmpEx2.Scale(Size(nPadTotalWidth, nPadTotalHeight));
476 aBmpEx2.Erase( Color(ColorAlpha,0,0,0,0) );
477 aBmpEx2.CopyPixel( tools::Rectangle( Point(nPadLeft, nPadTop), aBmpSize ), tools::Rectangle( Point(0, 0), aBmpSize ), &rBmpEx );
478 rBmpEx = aBmpEx2;
479 }
480 }
481
482 const Size aSizePixel( rBmpEx.GetSizePixel() );
483
484 if( rAttr.GetRotation() == 0_deg10 || IsAnimated() )
485 return;
486
487 if( !(aSizePixel.Width() && aSizePixel.Height() && rDstSize.Width() && rDstSize.Height()) )
488 return;
489
490 double fSrcWH = static_cast<double>(aSizePixel.Width()) / aSizePixel.Height();
491 double fDstWH = static_cast<double>(rDstSize.Width()) / rDstSize.Height();
492 double fScaleX = 1.0, fScaleY = 1.0;
493
494 // always choose scaling to shrink bitmap
495 if( fSrcWH < fDstWH )
496 fScaleY = aSizePixel.Width() / ( fDstWH * aSizePixel.Height() );
497 else
498 fScaleX = fDstWH * aSizePixel.Height() / aSizePixel.Width();
499
500 rBmpEx.Scale( fScaleX, fScaleY );
501}
502
503/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void Erase(sal_uInt8 cTransparency)
Definition: alpha.cxx:82
const AlphaMask & GetAlphaMask() const
Definition: bitmapex.hxx:71
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: BitmapEx.cxx:305
bool Erase(const Color &rFillColor)
Fill the entire bitmap with the given color.
Definition: BitmapEx.cxx:461
bool IsAlpha() const
Definition: BitmapEx.cxx:207
bool CopyPixel(const tools::Rectangle &rRectDst, const tools::Rectangle &rRectSrc, const BitmapEx *pBmpExSrc)
Copy a rectangular area from another bitmap.
Definition: BitmapEx.cxx:409
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:217
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
Definition: BitmapEx.cxx:363
const Size & GetSizePixel() const
Definition: bitmapex.hxx:73
bool IsCropped() const
Degree10 GetRotation() const
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
void SetGraphic(const Graphic &rGraphic)
const Graphic & GetGraphic() const
GraphicType GetType() const
bool VCL_DLLPRIVATE ImplDrawTiled(OutputDevice &rOut, const tools::Rectangle &rArea, const Size &rSizePixel, const Size &rOffset, const GraphicAttr *pAttr, int nTileCacheSize1D)
bool IsAnimated() 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()
bool IsTransparent() const
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.
bool Draw(OutputDevice &rOut, const Point &rPt, const Size &rSz, const GraphicAttr *pAttr=nullptr) const
const Fraction & GetScaleX() const
Definition: mapmod.cxx:185
MapUnit GetMapUnit() const
Definition: mapmod.cxx:181
const Fraction & GetScaleY() const
Definition: mapmod.cxx:187
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:170
GDIMetaFile * GetConnectMetaFile() const
Definition: outdev.hxx:285
void EnableMapMode(bool bEnable=true)
Definition: map.cxx:589
void DrawEllipse(const tools::Rectangle &rRect)
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1110
void DrawRect(const tools::Rectangle &rRect)
Definition: rect.cxx:50
void SetLineColor()
Definition: line.cxx:37
void SetFillColor()
Definition: fill.cxx:29
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:879
virtual Bitmap GetBitmap(const Point &rSrcPt, const Size &rSize) const
const MapMode & GetMapMode() const
Definition: outdev.hxx:1557
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
Definition: stack.cxx:32
void Pop()
Definition: stack.cxx:91
void IntersectClipRegion(const tools::Rectangle &rRect)
bool IsMapModeEnabled() const
Definition: outdev.hxx:1551
constexpr tools::Long Y() const
void setX(tools::Long nX)
void setY(tools::Long nY)
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
constexpr tools::Long X() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
constexpr tools::Long GetWidth() const
constexpr tools::Long Top() const
constexpr tools::Long GetHeight() const
constexpr tools::Long Left() const
ColorAlpha
constexpr ::Color COL_WHITE(0xFF, 0xFF, 0xFF)
BitmapEx GetBitmapEx(BitmapEx const &rBitmapEx, DrawModeFlags nDrawMode)
Definition: drawmode.cxx:242
Point aNextTileTopLeft