diff options
Diffstat (limited to 'canvas/source/directx/dx_canvashelper.cxx')
-rw-r--r-- | canvas/source/directx/dx_canvashelper.cxx | 816 |
1 files changed, 0 insertions, 816 deletions
diff --git a/canvas/source/directx/dx_canvashelper.cxx b/canvas/source/directx/dx_canvashelper.cxx deleted file mode 100644 index ba6720d289..0000000000 --- a/canvas/source/directx/dx_canvashelper.cxx +++ /dev/null @@ -1,816 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_canvas.hxx" - -#include <canvas/debug.hxx> -#include <tools/diagnose_ex.h> - -#include <rtl/logfile.hxx> -#include <rtl/math.hxx> - -#include <com/sun/star/rendering/TexturingMode.hpp> -#include <com/sun/star/rendering/CompositeOperation.hpp> -#include <com/sun/star/rendering/RepaintResult.hpp> -#include <com/sun/star/rendering/PathCapType.hpp> -#include <com/sun/star/rendering/PathJoinType.hpp> - -#include <basegfx/matrix/b2dhommatrix.hxx> -#include <basegfx/point/b2dpoint.hxx> -#include <basegfx/tools/canvastools.hxx> -#include <basegfx/matrix/b2dhommatrixtools.hxx> - -#include <comphelper/sequence.hxx> -#include <canvas/canvastools.hxx> - -#include "dx_spritecanvas.hxx" -#include "dx_impltools.hxx" -#include "dx_vcltools.hxx" -#include "dx_canvasfont.hxx" -#include "dx_textlayout.hxx" -#include "dx_canvashelper.hxx" - -#include <algorithm> - - -using namespace ::com::sun::star; - -namespace dxcanvas -{ - namespace - { - Gdiplus::LineCap gdiCapFromCap( sal_Int8 nCapType ) - { - switch( nCapType ) - { - case rendering::PathCapType::BUTT: - return Gdiplus::LineCapFlat; - - case rendering::PathCapType::ROUND: - return Gdiplus::LineCapRound; - - case rendering::PathCapType::SQUARE: - return Gdiplus::LineCapSquare; - - default: - ENSURE_OR_THROW( false, - "gdiCapFromCap(): Unexpected cap type" ); - } - - return Gdiplus::LineCapFlat; - } - - Gdiplus::LineJoin gdiJoinFromJoin( sal_Int8 nJoinType ) - { - switch( nJoinType ) - { - case rendering::PathJoinType::NONE: - OSL_FAIL( "gdiJoinFromJoin(): Join NONE not possible, mapping to MITER" ); - // FALLTHROUGH intended - case rendering::PathJoinType::MITER: - return Gdiplus::LineJoinMiter; - - case rendering::PathJoinType::ROUND: - return Gdiplus::LineJoinRound; - - case rendering::PathJoinType::BEVEL: - return Gdiplus::LineJoinBevel; - - default: - ENSURE_OR_THROW( false, - "gdiJoinFromJoin(): Unexpected join type" ); - } - - return Gdiplus::LineJoinMiter; - } - } - - CanvasHelper::CanvasHelper() : - mpGdiPlusUser( GDIPlusUser::createInstance() ), - mpDevice( NULL ), - mpGraphicsProvider(), - maOutputOffset() - { - } - - void CanvasHelper::disposing() - { - mpGraphicsProvider.reset(); - mpDevice = NULL; - mpGdiPlusUser.reset(); - } - - void CanvasHelper::setDevice( rendering::XGraphicDevice& rDevice ) - { - mpDevice = &rDevice; - } - - void CanvasHelper::setTarget( const GraphicsProviderSharedPtr& rTarget ) - { - ENSURE_OR_THROW( rTarget, - "CanvasHelper::setTarget(): Invalid target" ); - ENSURE_OR_THROW( !mpGraphicsProvider.get(), - "CanvasHelper::setTarget(): target set, old target would be overwritten" ); - - mpGraphicsProvider = rTarget; - } - - void CanvasHelper::setTarget( const GraphicsProviderSharedPtr& rTarget, - const ::basegfx::B2ISize& rOutputOffset ) - { - ENSURE_OR_THROW( rTarget, - "CanvasHelper::setTarget(): invalid target" ); - ENSURE_OR_THROW( !mpGraphicsProvider.get(), - "CanvasHelper::setTarget(): target set, old target would be overwritten" ); - - mpGraphicsProvider = rTarget; - maOutputOffset = rOutputOffset; - } - - void CanvasHelper::clear() - { - if( needOutput() ) - { - GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() ); - Gdiplus::Color aClearColor = Gdiplus::Color((Gdiplus::ARGB)Gdiplus::Color::White); - - ENSURE_OR_THROW( - Gdiplus::Ok == pGraphics->SetCompositingMode( - Gdiplus::CompositingModeSourceCopy ), // force set, don't blend - "CanvasHelper::clear(): GDI+ SetCompositingMode call failed" ); - ENSURE_OR_THROW( - Gdiplus::Ok == pGraphics->Clear( aClearColor ), - "CanvasHelper::clear(): GDI+ Clear call failed" ); - } - } - - void CanvasHelper::drawPoint( const rendering::XCanvas* /*pCanvas*/, - const geometry::RealPoint2D& aPoint, - const rendering::ViewState& viewState, - const rendering::RenderState& renderState ) - { - if( needOutput() ) - { - GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() ); - - setupGraphicsState( pGraphics, viewState, renderState ); - - Gdiplus::SolidBrush aBrush( - Gdiplus::Color( - tools::sequenceToArgb(renderState.DeviceColor)) ); - - // determine size of one-by-one device pixel ellipse - Gdiplus::Matrix aMatrix; - pGraphics->GetTransform(&aMatrix); - aMatrix.Invert(); - Gdiplus::PointF vector(1, 1); - aMatrix.TransformVectors(&vector); - - // paint a one-by-one circle, with the given point - // in the middle (rounded to float) - ENSURE_OR_THROW( - Gdiplus::Ok == pGraphics->FillEllipse( &aBrush, - // disambiguate call - Gdiplus::REAL(aPoint.X), - Gdiplus::REAL(aPoint.Y), - Gdiplus::REAL(vector.X), - Gdiplus::REAL(vector.Y) ), - "CanvasHelper::drawPoint(): GDI+ call failed" ); - } - } - - void CanvasHelper::drawLine( const rendering::XCanvas* /*pCanvas*/, - const geometry::RealPoint2D& aStartPoint, - const geometry::RealPoint2D& aEndPoint, - const rendering::ViewState& viewState, - const rendering::RenderState& renderState ) - { - if( needOutput() ) - { - GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() ); - - setupGraphicsState( pGraphics, viewState, renderState ); - - Gdiplus::Pen aPen( - Gdiplus::Color( - tools::sequenceToArgb(renderState.DeviceColor)), - Gdiplus::REAL(0.0) ); - - // #122683# Switched precedence of pixel offset - // mode. Seemingly, polygon stroking needs - // PixelOffsetModeNone to achieve visually pleasing - // results, whereas all other operations (e.g. polygon - // fills, bitmaps) look better with PixelOffsetModeHalf. - const Gdiplus::PixelOffsetMode aOldMode( - pGraphics->GetPixelOffsetMode() ); - pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone ); - - Gdiplus::Status hr = pGraphics->DrawLine( &aPen, - Gdiplus::REAL(aStartPoint.X), // disambiguate call - Gdiplus::REAL(aStartPoint.Y), - Gdiplus::REAL(aEndPoint.X), - Gdiplus::REAL(aEndPoint.Y) ); - pGraphics->SetPixelOffsetMode( aOldMode ); - - ENSURE_OR_THROW( - Gdiplus::Ok == hr, - "CanvasHelper::drawLine(): GDI+ call failed" ); - } - } - - void CanvasHelper::drawBezier( const rendering::XCanvas* /*pCanvas*/, - const geometry::RealBezierSegment2D& aBezierSegment, - const geometry::RealPoint2D& aEndPoint, - const rendering::ViewState& viewState, - const rendering::RenderState& renderState ) - { - if( needOutput() ) - { - GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() ); - - setupGraphicsState( pGraphics, viewState, renderState ); - - Gdiplus::Pen aPen( - Gdiplus::Color( - tools::sequenceToArgb(renderState.DeviceColor)), - Gdiplus::REAL(0.0) ); - - // #122683# Switched precedence of pixel offset - // mode. Seemingly, polygon stroking needs - // PixelOffsetModeNone to achieve visually pleasing - // results, whereas all other operations (e.g. polygon - // fills, bitmaps) look better with PixelOffsetModeHalf. - const Gdiplus::PixelOffsetMode aOldMode( - pGraphics->GetPixelOffsetMode() ); - pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone ); - - Gdiplus::Status hr = pGraphics->DrawBezier( &aPen, - Gdiplus::REAL(aBezierSegment.Px), // disambiguate call - Gdiplus::REAL(aBezierSegment.Py), - Gdiplus::REAL(aBezierSegment.C1x), - Gdiplus::REAL(aBezierSegment.C1y), - Gdiplus::REAL(aEndPoint.X), - Gdiplus::REAL(aEndPoint.Y), - Gdiplus::REAL(aBezierSegment.C2x), - Gdiplus::REAL(aBezierSegment.C2y) ); - - pGraphics->SetPixelOffsetMode( aOldMode ); - - ENSURE_OR_THROW( - Gdiplus::Ok == hr, - "CanvasHelper::drawBezier(): GDI+ call failed" ); - } - } - - uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* /*pCanvas*/, - const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon, - const rendering::ViewState& viewState, - const rendering::RenderState& renderState ) - { - ENSURE_OR_THROW( xPolyPolygon.is(), - "CanvasHelper::drawPolyPolygon: polygon is NULL"); - - if( needOutput() ) - { - GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() ); - - setupGraphicsState( pGraphics, viewState, renderState ); - - Gdiplus::Pen aPen( - Gdiplus::Color( - tools::sequenceToArgb(renderState.DeviceColor)), - Gdiplus::REAL(0.0) ); - - // #122683# Switched precedence of pixel offset - // mode. Seemingly, polygon stroking needs - // PixelOffsetModeNone to achieve visually pleasing - // results, whereas all other operations (e.g. polygon - // fills, bitmaps) look better with PixelOffsetModeHalf. - const Gdiplus::PixelOffsetMode aOldMode( - pGraphics->GetPixelOffsetMode() ); - pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone ); - - GraphicsPathSharedPtr pPath( tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ) ); - - // TODO(E1): Return value - Gdiplus::Status hr = pGraphics->DrawPath( &aPen, pPath.get() ); - - pGraphics->SetPixelOffsetMode( aOldMode ); - - ENSURE_OR_THROW( - Gdiplus::Ok == hr, - "CanvasHelper::drawPolyPolygon(): GDI+ call failed" ); - } - - // TODO(P1): Provide caching here. - return uno::Reference< rendering::XCachedPrimitive >(NULL); - } - - uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokePolyPolygon( const rendering::XCanvas* /*pCanvas*/, - const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon, - const rendering::ViewState& viewState, - const rendering::RenderState& renderState, - const rendering::StrokeAttributes& strokeAttributes ) - { - ENSURE_OR_THROW( xPolyPolygon.is(), - "CanvasHelper::drawPolyPolygon: polygon is NULL"); - - if( needOutput() ) - { - GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() ); - - setupGraphicsState( pGraphics, viewState, renderState ); - - - // Setup stroke pen - // ---------------- - - Gdiplus::Pen aPen( - Gdiplus::Color( - tools::sequenceToArgb(renderState.DeviceColor)), - static_cast< Gdiplus::REAL >(strokeAttributes.StrokeWidth) ); - - // #122683# Switched precedence of pixel offset - // mode. Seemingly, polygon stroking needs - // PixelOffsetModeNone to achieve visually pleasing - // results, whereas all other operations (e.g. polygon - // fills, bitmaps) look better with PixelOffsetModeHalf. - const Gdiplus::PixelOffsetMode aOldMode( - pGraphics->GetPixelOffsetMode() ); - pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone ); - - const bool bIsMiter(rendering::PathJoinType::MITER == strokeAttributes.JoinType); - const bool bIsNone(rendering::PathJoinType::NONE == strokeAttributes.JoinType); - - if(bIsMiter) - aPen.SetMiterLimit( static_cast< Gdiplus::REAL >(strokeAttributes.MiterLimit) ); - - const ::std::vector< Gdiplus::REAL >& rDashArray( - ::comphelper::sequenceToContainer< ::std::vector< Gdiplus::REAL > >( - strokeAttributes.DashArray ) ); - if( !rDashArray.empty() ) - { - aPen.SetDashPattern( &rDashArray[0], - rDashArray.size() ); - } - aPen.SetLineCap( gdiCapFromCap(strokeAttributes.StartCapType), - gdiCapFromCap(strokeAttributes.EndCapType), - Gdiplus::DashCapFlat ); - if(!bIsNone) - aPen.SetLineJoin( gdiJoinFromJoin(strokeAttributes.JoinType) ); - - GraphicsPathSharedPtr pPath( tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon, bIsNone ) ); - - // TODO(E1): Return value - Gdiplus::Status hr = pGraphics->DrawPath( &aPen, pPath.get() ); - - pGraphics->SetPixelOffsetMode( aOldMode ); - - ENSURE_OR_THROW( - Gdiplus::Ok == hr, - "CanvasHelper::strokePolyPolygon(): GDI+ call failed" ); - } - - // TODO(P1): Provide caching here. - return uno::Reference< rendering::XCachedPrimitive >(NULL); - } - - uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas* /*pCanvas*/, - const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/, - const rendering::ViewState& /*viewState*/, - const rendering::RenderState& /*renderState*/, - const uno::Sequence< rendering::Texture >& /*textures*/, - const rendering::StrokeAttributes& /*strokeAttributes*/ ) - { - // TODO - return uno::Reference< rendering::XCachedPrimitive >(NULL); - } - - uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas* /*pCanvas*/, - const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/, - const rendering::ViewState& /*viewState*/, - const rendering::RenderState& /*renderState*/, - const uno::Sequence< rendering::Texture >& /*textures*/, - const uno::Reference< geometry::XMapping2D >& /*xMapping*/, - const rendering::StrokeAttributes& /*strokeAttributes*/ ) - { - // TODO - return uno::Reference< rendering::XCachedPrimitive >(NULL); - } - - uno::Reference< rendering::XPolyPolygon2D > CanvasHelper::queryStrokeShapes( const rendering::XCanvas* /*pCanvas*/, - const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/, - const rendering::ViewState& /*viewState*/, - const rendering::RenderState& /*renderState*/, - const rendering::StrokeAttributes& /*strokeAttributes*/ ) - { - // TODO - return uno::Reference< rendering::XPolyPolygon2D >(NULL); - } - - uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillPolyPolygon( const rendering::XCanvas* /*pCanvas*/, - const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon, - const rendering::ViewState& viewState, - const rendering::RenderState& renderState ) - { - ENSURE_OR_THROW( xPolyPolygon.is(), - "CanvasHelper::fillPolyPolygon: polygon is NULL"); - - if( needOutput() ) - { - GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() ); - - setupGraphicsState( pGraphics, viewState, renderState ); - - Gdiplus::SolidBrush aBrush( - tools::sequenceToArgb(renderState.DeviceColor)); - - GraphicsPathSharedPtr pPath( tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ) ); - - // TODO(F1): FillRule - ENSURE_OR_THROW( Gdiplus::Ok == pGraphics->FillPath( &aBrush, pPath.get() ), - "CanvasHelper::fillPolyPolygon(): GDI+ call failed " ); - } - - // TODO(P1): Provide caching here. - return uno::Reference< rendering::XCachedPrimitive >(NULL); - } - - uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas* /*pCanvas*/, - const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/, - const rendering::ViewState& /*viewState*/, - const rendering::RenderState& /*renderState*/, - const uno::Sequence< rendering::Texture >& /*textures*/, - const uno::Reference< geometry::XMapping2D >& /*xMapping*/ ) - { - // TODO - return uno::Reference< rendering::XCachedPrimitive >(NULL); - } - - uno::Reference< rendering::XCanvasFont > CanvasHelper::createFont( const rendering::XCanvas* /*pCanvas*/, - const rendering::FontRequest& fontRequest, - const uno::Sequence< beans::PropertyValue >& extraFontProperties, - const geometry::Matrix2D& fontMatrix ) - { - if( needOutput() ) - { - return uno::Reference< rendering::XCanvasFont >( - new CanvasFont(fontRequest, extraFontProperties, fontMatrix ) ); - } - - return uno::Reference< rendering::XCanvasFont >(); - } - - uno::Sequence< rendering::FontInfo > CanvasHelper::queryAvailableFonts( const rendering::XCanvas* /*pCanvas*/, - const rendering::FontInfo& /*aFilter*/, - const uno::Sequence< beans::PropertyValue >& /*aFontProperties*/ ) - { - // TODO - return uno::Sequence< rendering::FontInfo >(); - } - - uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawText( const rendering::XCanvas* /*pCanvas*/, - const rendering::StringContext& text, - const uno::Reference< rendering::XCanvasFont >& xFont, - const rendering::ViewState& viewState, - const rendering::RenderState& renderState, - sal_Int8 /*textDirection*/ ) - { - ENSURE_OR_THROW( xFont.is(), - "CanvasHelper::drawText: font is NULL"); - - if( needOutput() ) - { - GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() ); - - setupGraphicsState( pGraphics, viewState, renderState ); - - Gdiplus::SolidBrush aBrush( - Gdiplus::Color( - tools::sequenceToArgb(renderState.DeviceColor))); - - CanvasFont::ImplRef pFont( - tools::canvasFontFromXFont(xFont) ); - - // Move glyphs up, such that output happens at the font - // baseline. - Gdiplus::PointF aPoint( 0.0, - static_cast<Gdiplus::REAL>(-(pFont->getFont()->GetSize()* - pFont->getCellAscent() / - pFont->getEmHeight())) ); - - // TODO(F1): According to - // http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q307208, - // we might have to revert to GDI and ExTextOut here, - // since GDI+ takes the scalability a little bit too - // far... - - // TODO(F2): Proper layout (BiDi, CTL)! IMHO must use - // DrawDriverString here, and perform layouting myself... - ENSURE_OR_THROW( - Gdiplus::Ok == pGraphics->DrawString( reinterpret_cast<LPCWSTR>( - text.Text.copy( text.StartPosition, - text.Length ).getStr()), - text.Length, - pFont->getFont().get(), - aPoint, - &aBrush ), - "CanvasHelper::drawText(): GDI+ call failed" ); - } - - return uno::Reference< rendering::XCachedPrimitive >(NULL); - } - - uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawTextLayout( const rendering::XCanvas* /*pCanvas*/, - const uno::Reference< rendering::XTextLayout >& xLayoutetText, - const rendering::ViewState& viewState, - const rendering::RenderState& renderState ) - { - ENSURE_OR_THROW( xLayoutetText.is(), - "CanvasHelper::drawTextLayout: layout is NULL"); - - if( needOutput() ) - { - TextLayout* pTextLayout = - dynamic_cast< TextLayout* >( xLayoutetText.get() ); - - ENSURE_OR_THROW( pTextLayout, - "CanvasHelper::drawTextLayout(): TextLayout not compatible with this canvas" ); - - pTextLayout->draw( mpGraphicsProvider->getGraphics(), - viewState, - renderState, - maOutputOffset, - mpDevice, - false ); - } - - return uno::Reference< rendering::XCachedPrimitive >(NULL); - } - - uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmap( const rendering::XCanvas* /*pCanvas*/, - const uno::Reference< rendering::XBitmap >& xBitmap, - const rendering::ViewState& viewState, - const rendering::RenderState& renderState ) - { - ENSURE_OR_THROW( xBitmap.is(), - "CanvasHelper::drawBitmap: bitmap is NULL"); - - if( needOutput() ) - { - // check whether one of our own objects - need to retrieve - // bitmap _before_ calling - // GraphicsProvider::getGraphics(), to avoid locking our - // own surface. - BitmapSharedPtr pGdiBitmap; - BitmapProvider* pBitmap = dynamic_cast< BitmapProvider* >(xBitmap.get()); - if( pBitmap ) - { - IBitmapSharedPtr pDXBitmap( pBitmap->getBitmap() ); - if( pDXBitmap ) - pGdiBitmap = pDXBitmap->getBitmap(); - } - - GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() ); - setupGraphicsState( pGraphics, viewState, renderState ); - - if( pGdiBitmap ) - tools::drawGdiPlusBitmap(pGraphics,pGdiBitmap); - else - tools::drawVCLBitmapFromXBitmap(pGraphics, - xBitmap); - } - - // TODO(P1): Provide caching here. - return uno::Reference< rendering::XCachedPrimitive >(NULL); - } - - uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* pCanvas, - const uno::Reference< rendering::XBitmap >& xBitmap, - const rendering::ViewState& viewState, - const rendering::RenderState& renderState ) - { - ENSURE_OR_THROW( xBitmap.is(), - "CanvasHelper::drawBitmap: bitmap is NULL"); - - // no color set -> this is equivalent to a plain drawBitmap(), then - if( renderState.DeviceColor.getLength() < 3 ) - return drawBitmap( pCanvas, xBitmap, viewState, renderState ); - - if( needOutput() ) - { - GraphicsSharedPtr pGraphics( mpGraphicsProvider->getGraphics() ); - - setupGraphicsState( pGraphics, viewState, renderState ); - - BitmapSharedPtr pBitmap( tools::bitmapFromXBitmap( xBitmap ) ); - Gdiplus::Rect aRect( 0, 0, - pBitmap->GetWidth(), - pBitmap->GetHeight() ); - - // Setup an ImageAttributes with an alpha-modulating - // color matrix. - const rendering::ARGBColor& rARGBColor( - mpDevice->getDeviceColorSpace()->convertToARGB(renderState.DeviceColor)[0]); - - Gdiplus::ImageAttributes aImgAttr; - tools::setModulateImageAttributes( aImgAttr, - rARGBColor.Red, - rARGBColor.Green, - rARGBColor.Blue, - rARGBColor.Alpha ); - - ENSURE_OR_THROW( - Gdiplus::Ok == pGraphics->DrawImage( pBitmap.get(), - aRect, - 0, 0, - pBitmap->GetWidth(), - pBitmap->GetHeight(), - Gdiplus::UnitPixel, - &aImgAttr, - NULL, - NULL ), - "CanvasHelper::drawBitmapModulated(): GDI+ call failed" ); - } - - // TODO(P1): Provide caching here. - return uno::Reference< rendering::XCachedPrimitive >(NULL); - } - - uno::Reference< rendering::XGraphicDevice > CanvasHelper::getDevice() - { - return uno::Reference< rendering::XGraphicDevice >(mpDevice); - } - - // private helper - // -------------------------------------------------- - - Gdiplus::CompositingMode CanvasHelper::calcCompositingMode( sal_Int8 nMode ) - { - Gdiplus::CompositingMode aRet( Gdiplus::CompositingModeSourceOver ); - - switch( nMode ) - { - case rendering::CompositeOperation::OVER: - // FALLTHROUGH intended - case rendering::CompositeOperation::CLEAR: - aRet = Gdiplus::CompositingModeSourceOver; - break; - - case rendering::CompositeOperation::SOURCE: - aRet = Gdiplus::CompositingModeSourceCopy; - break; - - case rendering::CompositeOperation::DESTINATION: - // FALLTHROUGH intended - case rendering::CompositeOperation::UNDER: - // FALLTHROUGH intended - case rendering::CompositeOperation::INSIDE: - // FALLTHROUGH intended - case rendering::CompositeOperation::INSIDE_REVERSE: - // FALLTHROUGH intended - case rendering::CompositeOperation::OUTSIDE: - // FALLTHROUGH intended - case rendering::CompositeOperation::OUTSIDE_REVERSE: - // FALLTHROUGH intended - case rendering::CompositeOperation::ATOP: - // FALLTHROUGH intended - case rendering::CompositeOperation::ATOP_REVERSE: - // FALLTHROUGH intended - case rendering::CompositeOperation::XOR: - // FALLTHROUGH intended - case rendering::CompositeOperation::ADD: - // FALLTHROUGH intended - case rendering::CompositeOperation::SATURATE: - // TODO(F2): Problem, because GDI+ only knows about two compositing modes - aRet = Gdiplus::CompositingModeSourceOver; - break; - - default: - ENSURE_OR_THROW( false, "CanvasHelper::calcCompositingMode: unexpected mode" ); - break; - } - - return aRet; - } - - void CanvasHelper::setupGraphicsState( GraphicsSharedPtr& rGraphics, - const rendering::ViewState& viewState, - const rendering::RenderState& renderState ) - { - ENSURE_OR_THROW( needOutput(), - "CanvasHelper::setupGraphicsState: primary graphics invalid" ); - ENSURE_OR_THROW( mpDevice, - "CanvasHelper::setupGraphicsState: reference device invalid" ); - - // setup view transform first. Clipping e.g. depends on it - ::basegfx::B2DHomMatrix aTransform; - ::canvas::tools::getViewStateTransform(aTransform, viewState); - - // add output offset - if( !maOutputOffset.equalZero() ) - { - const basegfx::B2DHomMatrix aOutputOffset(basegfx::tools::createTranslateB2DHomMatrix( - maOutputOffset.getX(), maOutputOffset.getY())); - aTransform = aOutputOffset * aTransform; - } - - Gdiplus::Matrix aMatrix; - tools::gdiPlusMatrixFromB2DHomMatrix( aMatrix, aTransform ); - - ENSURE_OR_THROW( - Gdiplus::Ok == rGraphics->SetTransform( &aMatrix ), - "CanvasHelper::setupGraphicsState(): Failed to set GDI+ transformation" ); - - // setup view and render state clipping - ENSURE_OR_THROW( - Gdiplus::Ok == rGraphics->ResetClip(), - "CanvasHelper::setupGraphicsState(): Failed to reset GDI+ clip" ); - - if( viewState.Clip.is() ) - { - GraphicsPathSharedPtr aClipPath( tools::graphicsPathFromXPolyPolygon2D( viewState.Clip ) ); - - // TODO(P3): Cache clip. SetClip( GraphicsPath ) performs abyssmally on GDI+. - // Try SetClip( Rect ) or similar for simple clip paths (need some support in - // LinePolyPolygon, then) - ENSURE_OR_THROW( - Gdiplus::Ok == rGraphics->SetClip( aClipPath.get(), - Gdiplus::CombineModeIntersect ), - "CanvasHelper::setupGraphicsState(): Cannot set GDI+ clip" ); - } - - // setup overall transform only now. View clip above was relative to - // view transform - ::canvas::tools::mergeViewAndRenderTransform(aTransform, - viewState, - renderState); - - // add output offset - if( !maOutputOffset.equalZero() ) - { - const basegfx::B2DHomMatrix aOutputOffset(basegfx::tools::createTranslateB2DHomMatrix( - maOutputOffset.getX(), maOutputOffset.getY())); - aTransform = aOutputOffset * aTransform; - } - - tools::gdiPlusMatrixFromB2DHomMatrix( aMatrix, aTransform ); - - ENSURE_OR_THROW( - Gdiplus::Ok == rGraphics->SetTransform( &aMatrix ), - "CanvasHelper::setupGraphicsState(): Cannot set GDI+ transformation" ); - - if( renderState.Clip.is() ) - { - GraphicsPathSharedPtr aClipPath( tools::graphicsPathFromXPolyPolygon2D( renderState.Clip ) ); - - // TODO(P3): Cache clip. SetClip( GraphicsPath ) performs abyssmally on GDI+. - // Try SetClip( Rect ) or similar for simple clip paths (need some support in - // LinePolyPolygon, then) - ENSURE_OR_THROW( - Gdiplus::Ok == rGraphics->SetClip( aClipPath.get(), - Gdiplus::CombineModeIntersect ), - "CanvasHelper::setupGraphicsState(): Cannot set GDI+ clip" ); - } - - // setup compositing - const Gdiplus::CompositingMode eCompositing( calcCompositingMode( renderState.CompositeOperation ) ); - ENSURE_OR_THROW( - Gdiplus::Ok == rGraphics->SetCompositingMode( eCompositing ), - "CanvasHelper::setupGraphicsState(): Cannot set GDI* compositing mode)" ); - } - - void CanvasHelper::flush() const - { - if( needOutput() ) - mpGraphicsProvider->getGraphics()->Flush( Gdiplus::FlushIntentionSync ); - } -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |