/* -*- 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 . */ #include #include #include #include #include #include #include #include "salgdi.hxx" void OutputDevice::DrawRect( const Rectangle& rRect ) { assert(!is_double_buffered_window()); if ( mpMetaFile ) mpMetaFile->AddAction( new MetaRectAction( rRect ) ); if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() ) return; Rectangle aRect( ImplLogicToDevicePixel( rRect ) ); if ( aRect.IsEmpty() ) return; aRect.Justify(); if ( !mpGraphics && !AcquireGraphics() ) return; if ( mbInitClipRegion ) InitClipRegion(); if ( mbOutputClipped ) return; if ( mbInitLineColor ) InitLineColor(); if ( mbInitFillColor ) InitFillColor(); mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), this ); if( mpAlphaVDev ) mpAlphaVDev->DrawRect( rRect ); } void OutputDevice::DrawRect( const Rectangle& rRect, sal_uLong nHorzRound, sal_uLong nVertRound ) { assert(!is_double_buffered_window()); if ( mpMetaFile ) mpMetaFile->AddAction( new MetaRoundRectAction( rRect, nHorzRound, nVertRound ) ); if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() ) return; const Rectangle aRect( ImplLogicToDevicePixel( rRect ) ); if ( aRect.IsEmpty() ) return; nHorzRound = ImplLogicWidthToDevicePixel( nHorzRound ); nVertRound = ImplLogicHeightToDevicePixel( nVertRound ); // we need a graphics if ( !mpGraphics ) { if ( !AcquireGraphics() ) return; } if ( mbInitClipRegion ) InitClipRegion(); if ( mbOutputClipped ) return; if ( mbInitLineColor ) InitLineColor(); if ( mbInitFillColor ) InitFillColor(); if ( !nHorzRound && !nVertRound ) { mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), this ); } else { const tools::Polygon aRoundRectPoly( aRect, nHorzRound, nVertRound ); if ( aRoundRectPoly.GetSize() >= 2 ) { const SalPoint* pPtAry = reinterpret_cast(aRoundRectPoly.GetConstPointAry()); if ( !mbFillColor ) mpGraphics->DrawPolyLine( aRoundRectPoly.GetSize(), pPtAry, this ); else mpGraphics->DrawPolygon( aRoundRectPoly.GetSize(), pPtAry, this ); } } if( mpAlphaVDev ) mpAlphaVDev->DrawRect( rRect, nHorzRound, nVertRound ); } void OutputDevice::Invert( const Rectangle& rRect, InvertFlags nFlags ) { assert(!is_double_buffered_window()); if ( !IsDeviceOutputNecessary() ) return; Rectangle aRect( ImplLogicToDevicePixel( rRect ) ); if ( aRect.IsEmpty() ) return; aRect.Justify(); // we need a graphics if ( !mpGraphics ) { if ( !AcquireGraphics() ) return; } if ( mbInitClipRegion ) InitClipRegion(); if ( mbOutputClipped ) return; SalInvert nSalFlags = 0; if ( nFlags & InvertFlags::Highlight ) nSalFlags |= SAL_INVERT_HIGHLIGHT; if ( nFlags & InvertFlags::N50 ) nSalFlags |= SAL_INVERT_50; mpGraphics->Invert( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), nSalFlags, this ); } void OutputDevice::Invert( const tools::Polygon& rPoly, InvertFlags nFlags ) { assert(!is_double_buffered_window()); if ( !IsDeviceOutputNecessary() ) return; sal_uInt16 nPoints = rPoly.GetSize(); if ( nPoints < 2 ) return; tools::Polygon aPoly( ImplLogicToDevicePixel( rPoly ) ); // we need a graphics if ( !mpGraphics ) { if ( !AcquireGraphics() ) return; } if ( mbInitClipRegion ) InitClipRegion(); if ( mbOutputClipped ) return; SalInvert nSalFlags = 0; if ( nFlags & InvertFlags::Highlight ) nSalFlags |= SAL_INVERT_HIGHLIGHT; if ( nFlags & InvertFlags::N50 ) nSalFlags |= SAL_INVERT_50; const SalPoint* pPtAry = reinterpret_cast(aPoly.GetConstPointAry()); mpGraphics->Invert( nPoints, pPtAry, nSalFlags, this ); } void OutputDevice::DrawCheckered(const Point& rPos, const Size& rSize, sal_uInt32 nLen, Color aStart, Color aEnd) { assert(!is_double_buffered_window()); const sal_uInt32 nMaxX(rPos.X() + rSize.Width()); const sal_uInt32 nMaxY(rPos.Y() + rSize.Height()); Push(PushFlags::LINECOLOR|PushFlags::FILLCOLOR); SetLineColor(); for(sal_uInt32 x(0), nX(rPos.X()); nX < nMaxX; x++, nX += nLen) { const sal_uInt32 nRight(std::min(nMaxX, nX + nLen)); for(sal_uInt32 y(0), nY(rPos.Y()); nY < nMaxY; y++, nY += nLen) { const sal_uInt32 nBottom(std::min(nMaxY, nY + nLen)); SetFillColor((x & 0x0001) ^ (y & 0x0001) ? aStart : aEnd); DrawRect(Rectangle(nX, nY, nRight, nBottom)); } } Pop(); } void OutputDevice::DrawGrid( const Rectangle& rRect, const Size& rDist, DrawGridFlags nFlags ) { assert(!is_double_buffered_window()); Rectangle aDstRect( PixelToLogic( Point() ), GetOutputSize() ); aDstRect.Intersection( rRect ); if( aDstRect.IsEmpty() || ImplIsRecordLayout() ) return; if( !mpGraphics && !AcquireGraphics() ) return; if( mbInitClipRegion ) InitClipRegion(); if( mbOutputClipped ) return; const long nDistX = std::max( rDist.Width(), 1L ); const long nDistY = std::max( rDist.Height(), 1L ); long nX = ( rRect.Left() >= aDstRect.Left() ) ? rRect.Left() : ( rRect.Left() + ( ( aDstRect.Left() - rRect.Left() ) / nDistX ) * nDistX ); long nY = ( rRect.Top() >= aDstRect.Top() ) ? rRect.Top() : ( rRect.Top() + ( ( aDstRect.Top() - rRect.Top() ) / nDistY ) * nDistY ); const long nRight = aDstRect.Right(); const long nBottom = aDstRect.Bottom(); const long nStartX = ImplLogicXToDevicePixel( nX ); const long nEndX = ImplLogicXToDevicePixel( nRight ); const long nStartY = ImplLogicYToDevicePixel( nY ); const long nEndY = ImplLogicYToDevicePixel( nBottom ); long nHorzCount = 0L; long nVertCount = 0L; css::uno::Sequence< sal_Int32 > aVertBuf; css::uno::Sequence< sal_Int32 > aHorzBuf; if( ( nFlags & DrawGridFlags::Dots ) || ( nFlags & DrawGridFlags::HorzLines ) ) { aVertBuf.realloc( aDstRect.GetHeight() / nDistY + 2L ); aVertBuf[ nVertCount++ ] = nStartY; while( ( nY += nDistY ) <= nBottom ) { aVertBuf[ nVertCount++ ] = ImplLogicYToDevicePixel( nY ); } } if( ( nFlags & DrawGridFlags::Dots ) || ( nFlags & DrawGridFlags::VertLines ) ) { aHorzBuf.realloc( aDstRect.GetWidth() / nDistX + 2L ); aHorzBuf[ nHorzCount++ ] = nStartX; while( ( nX += nDistX ) <= nRight ) { aHorzBuf[ nHorzCount++ ] = ImplLogicXToDevicePixel( nX ); } } if( mbInitLineColor ) InitLineColor(); if( mbInitFillColor ) InitFillColor(); const bool bOldMap = mbMap; EnableMapMode( false ); if( nFlags & DrawGridFlags::Dots ) { for( long i = 0L; i < nVertCount; i++ ) { for( long j = 0L, Y = aVertBuf[ i ]; j < nHorzCount; j++ ) { mpGraphics->DrawPixel( aHorzBuf[ j ], Y, this ); } } } else { if( nFlags & DrawGridFlags::HorzLines ) { for( long i = 0L; i < nVertCount; i++ ) { nY = aVertBuf[ i ]; mpGraphics->DrawLine( nStartX, nY, nEndX, nY, this ); } } if( nFlags & DrawGridFlags::VertLines ) { for( long i = 0L; i < nHorzCount; i++ ) { nX = aHorzBuf[ i ]; mpGraphics->DrawLine( nX, nStartY, nX, nEndY, this ); } } } EnableMapMode( bOldMap ); if( mpAlphaVDev ) mpAlphaVDev->DrawGrid( rRect, rDist, nFlags ); } BmpMirrorFlags AdjustTwoRect( SalTwoRect& rTwoRect, const Size& rSizePix ) { BmpMirrorFlags nMirrFlags = BmpMirrorFlags::NONE; if ( rTwoRect.mnDestWidth < 0 ) { rTwoRect.mnSrcX = rSizePix.Width() - rTwoRect.mnSrcX - rTwoRect.mnSrcWidth; rTwoRect.mnDestWidth = -rTwoRect.mnDestWidth; rTwoRect.mnDestX -= rTwoRect.mnDestWidth-1; nMirrFlags |= BmpMirrorFlags::Horizontal; } if ( rTwoRect.mnDestHeight < 0 ) { rTwoRect.mnSrcY = rSizePix.Height() - rTwoRect.mnSrcY - rTwoRect.mnSrcHeight; rTwoRect.mnDestHeight = -rTwoRect.mnDestHeight; rTwoRect.mnDestY -= rTwoRect.mnDestHeight-1; nMirrFlags |= BmpMirrorFlags::Vertical; } if( ( rTwoRect.mnSrcX < 0 ) || ( rTwoRect.mnSrcX >= rSizePix.Width() ) || ( rTwoRect.mnSrcY < 0 ) || ( rTwoRect.mnSrcY >= rSizePix.Height() ) || ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rSizePix.Width() ) || ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rSizePix.Height() ) ) { const Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ), Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) ); Rectangle aCropRect( aSourceRect ); aCropRect.Intersection( Rectangle( Point(), rSizePix ) ); if( aCropRect.IsEmpty() ) { rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0; } else { const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? (double) ( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0; const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? (double) ( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0; const long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) ); const long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) ); const long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) ); const long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) ); rTwoRect.mnSrcX = aCropRect.Left(); rTwoRect.mnSrcY = aCropRect.Top(); rTwoRect.mnSrcWidth = aCropRect.GetWidth(); rTwoRect.mnSrcHeight = aCropRect.GetHeight(); rTwoRect.mnDestX = nDstX1; rTwoRect.mnDestY = nDstY1; rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1; rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1; } } return nMirrFlags; } void AdjustTwoRect( SalTwoRect& rTwoRect, const Rectangle& rValidSrcRect ) { if( ( rTwoRect.mnSrcX < rValidSrcRect.Left() ) || ( rTwoRect.mnSrcX >= rValidSrcRect.Right() ) || ( rTwoRect.mnSrcY < rValidSrcRect.Top() ) || ( rTwoRect.mnSrcY >= rValidSrcRect.Bottom() ) || ( ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) > rValidSrcRect.Right() ) || ( ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) > rValidSrcRect.Bottom() ) ) { const Rectangle aSourceRect( Point( rTwoRect.mnSrcX, rTwoRect.mnSrcY ), Size( rTwoRect.mnSrcWidth, rTwoRect.mnSrcHeight ) ); Rectangle aCropRect( aSourceRect ); aCropRect.Intersection( rValidSrcRect ); if( aCropRect.IsEmpty() ) { rTwoRect.mnSrcWidth = rTwoRect.mnSrcHeight = rTwoRect.mnDestWidth = rTwoRect.mnDestHeight = 0; } else { const double fFactorX = ( rTwoRect.mnSrcWidth > 1 ) ? (double) ( rTwoRect.mnDestWidth - 1 ) / ( rTwoRect.mnSrcWidth - 1 ) : 0.0; const double fFactorY = ( rTwoRect.mnSrcHeight > 1 ) ? (double) ( rTwoRect.mnDestHeight - 1 ) / ( rTwoRect.mnSrcHeight - 1 ) : 0.0; const long nDstX1 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Left() - rTwoRect.mnSrcX ) ); const long nDstY1 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Top() - rTwoRect.mnSrcY ) ); const long nDstX2 = rTwoRect.mnDestX + FRound( fFactorX * ( aCropRect.Right() - rTwoRect.mnSrcX ) ); const long nDstY2 = rTwoRect.mnDestY + FRound( fFactorY * ( aCropRect.Bottom() - rTwoRect.mnSrcY ) ); rTwoRect.mnSrcX = aCropRect.Left(); rTwoRect.mnSrcY = aCropRect.Top(); rTwoRect.mnSrcWidth = aCropRect.GetWidth(); rTwoRect.mnSrcHeight = aCropRect.GetHeight(); rTwoRect.mnDestX = nDstX1; rTwoRect.mnDestY = nDstY1; rTwoRect.mnDestWidth = nDstX2 - nDstX1 + 1; rTwoRect.mnDestHeight = nDstY2 - nDstY1 + 1; } } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */