/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
Point aTileTopLeft; // top, left position of the rendered tile
Point aNextTileTopLeft; // top, left position for next recursion // level's tile
Size aTileSizePixel; // size of the generated tile (might // differ from // aNextTileTopLeft-aTileTopLeft, because // this is nExponent*prevTileSize. The // generated tile is always nExponent // times the previous tile, such that it // can be used in the next stage. The // required area coverage is often // less. The extraneous area covered is // later overwritten by the next stage) int nTilesEmptyX; // number of original tiles empty right of // this tile. This counts from // aNextTileTopLeft, i.e. the additional // area covered by aTileSizePixel is not // considered here. This is for // unification purposes, as the iterative // calculation of the next level's empty // tiles has to be based on this value. int nTilesEmptyY; // as above, for Y
};
bool GraphicObject::ImplRenderTempTile( VirtualDevice& rVDev, int nNumTilesX, int nNumTilesY, const Size& rTileSizePixel, const GraphicAttr* pAttr )
{ // how many tiles to generate per recursion step constint nExponent = 2;
// one less if(nMSBFactor > 1)
{
nMSBFactor /= nExponent;
}
ImplTileInfo aTileInfo;
// #105229# Switch off mapping (converting to logic and back to // pixel might cause roundoff errors) bool bOldMap( rVDev.IsMapModeEnabled() );
rVDev.EnableMapMode( false );
// see header comment. this works similar to base conversion of a // number, i.e. if the exponent is 10, then the number for every tile // size is given by the decimal place of the corresponding decimal // representation. bool GraphicObject::ImplRenderTileRecursive( VirtualDevice& rVDev, int nExponent, int nMSBFactor, int nNumOrigTilesX, int nNumOrigTilesY, int nRemainderTilesX, int nRemainderTilesY, const Size& rTileSizePixel, const GraphicAttr* pAttr,
ImplTileInfo& rTileInfo )
{ // gets loaded with our tile bitmap
std::unique_ptr<GraphicObject> xTmpGraphic;
GraphicObject* pTileGraphic;
// stores a flag that renders the zero'th tile position // (i.e. (0,0)+rCurrPos) only if we're at the bottom of the // recursion stack. All other position already have that tile // rendered, because the lower levels painted their generated tile // there. bool bNoFirstTileDraw( false );
// what's left when we're done with our tile size constint nNewRemainderX( nRemainderTilesX % nMSBFactor ); constint nNewRemainderY( nRemainderTilesY % nMSBFactor );
// gets filled out from the recursive call with info of what's // been generated
ImplTileInfo aTileInfo;
// check for recursion's end condition: LSB place reached? if( nMSBFactor == 1 )
{
pTileGraphic = this;
// where x denotes the place filled by our recursive predecessors
// check whether we have to fill stripes here. Although not // obvious, there is one case where we can skip this step: if // the previous recursion level (the one who filled our // aTileInfo) had zero area to fill, then there are no white // stripes left, naturally. This happens if the digit // associated to that level has a zero, and can be checked via // aTileTopLeft==aNextTileTopLeft. if( aTileInfo.aTileTopLeft != aTileInfo.aNextTileTopLeft )
{ // now fill one row from aTileInfo.aNextTileTopLeft.X() all // the way to the right // current output position while drawing
Point aCurrPos(aTileInfo.aNextTileTopLeft.X(), aTileInfo.aTileTopLeft.Y()); for (int nX=0; nX < aTileInfo.nTilesEmptyX; nX += nMSBFactor)
{ if (!pTileGraphic->Draw(rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr)) returnfalse;
// now fill one column from aTileInfo.aNextTileTopLeft.Y() all // the way to the bottom
aCurrPos.setX( aTileInfo.aTileTopLeft.X() );
aCurrPos.setY( aTileInfo.aNextTileTopLeft.Y() ); for (int nY=0; nY < aTileInfo.nTilesEmptyY; nY += nMSBFactor)
{ if (!pTileGraphic->Draw(rVDev, aCurrPos, aTileInfo.aTileSizePixel, pAttr)) returnfalse;
#ifdef DBG_TEST
rVDev.DrawEllipse( tools::Rectangle(aTileInfo.aTileTopLeft.X(), aTileInfo.aNextTileTopLeft.Y(),
aTileInfo.aTileTopLeft.X() + aTileInfo.aTileSizePixel.Width() - 1,
aTileInfo.aNextTileTopLeft.Y() - 1 + (aTileInfo.nTilesEmptyY/nMSBFactor)*aTileInfo.aTileSizePixel.Height()) ); #endif
} else
{ // Thought that aTileInfo.aNextTileTopLeft tile has always // been drawn already, but that's wrong: typically, // _parts_ of that tile have been drawn, since the // previous level generated the tile there. But when // aTileInfo.aNextTileTopLeft!=aTileInfo.aTileTopLeft, the // difference between these two values is missing in the // lower right corner of this first tile. So, can do that // only here.
bNoFirstTileDraw = true;
}
} else
{ returnfalse;
}
// calc number of original tiles in our drawing area without // remainder
nRemainderTilesX -= nNewRemainderX;
nRemainderTilesY -= nNewRemainderY;
// init output position
Point aCurrPos = aTileInfo.aNextTileTopLeft;
// fill our drawing area. Fill possibly more, to create the next // bigger tile size -> see bitmap extraction above. This does no // harm, since everything right or below our actual area is // overdrawn by our caller. Just in case we're in the last level, // we don't draw beyond the right or bottom border. for (int nY=0; nY < aTileInfo.nTilesEmptyY && nY < nExponent*nMSBFactor; nY += nMSBFactor)
{
aCurrPos.setX( aTileInfo.aNextTileTopLeft.X() );
// #i42643# Casting to Int64, to avoid integer overflow for // huge-DPI output devices if( GetGraphic().GetType() == GraphicType::Bitmap && static_cast<sal_Int64>(rSizePixel.Width()) * rSizePixel.Height() < static_cast<sal_Int64>(nTileCacheSize1D)*nTileCacheSize1D )
{ // First combine very small bitmaps into a larger tile
// origin from where to 'virtually' start drawing in pixel const Point aOutOrigin( rOut.LogicToPixel( Point( rArea.Left() - rOffset.Width(),
rArea.Top() - rOffset.Height() ) ) ); // position in pixel from where to really start output const Point aOutStart( aOutOrigin.X() + nInvisibleTilesX*rSizePixel.Width(),
aOutOrigin.Y() + nInvisibleTilesY*rSizePixel.Height() );
for( nX=0; nX < nNumTilesX; ++nX )
{ // #105229# work with pixel coordinates here, mapping is disabled! // #104004# don't disable mapping for metafile recordings // #108412# don't quit the loop if one draw fails
// update return value. This method should return true, if // at least one of the looped Draws succeeded.
bRet |= Draw(rOut,
bDrawInPixel ? aCurrPos : rOut.PixelToLogic(aCurrPos),
bDrawInPixel ? rTileSizePixel : aTileSizeLogic,
pAttr);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.