125ea7f45SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 325ea7f45SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 425ea7f45SAndrew Rist * or more contributor license agreements. See the NOTICE file 525ea7f45SAndrew Rist * distributed with this work for additional information 625ea7f45SAndrew Rist * regarding copyright ownership. The ASF licenses this file 725ea7f45SAndrew Rist * to you under the Apache License, Version 2.0 (the 825ea7f45SAndrew Rist * "License"); you may not use this file except in compliance 925ea7f45SAndrew Rist * with the License. You may obtain a copy of the License at 1025ea7f45SAndrew Rist * 1125ea7f45SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 1225ea7f45SAndrew Rist * 1325ea7f45SAndrew Rist * Unless required by applicable law or agreed to in writing, 1425ea7f45SAndrew Rist * software distributed under the License is distributed on an 1525ea7f45SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1625ea7f45SAndrew Rist * KIND, either express or implied. See the License for the 1725ea7f45SAndrew Rist * specific language governing permissions and limitations 1825ea7f45SAndrew Rist * under the License. 1925ea7f45SAndrew Rist * 2025ea7f45SAndrew Rist *************************************************************/ 2125ea7f45SAndrew Rist 2225ea7f45SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_canvas.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <canvas/debug.hxx> 28cdf0e10cSrcweir #include <tools/diagnose_ex.h> 29cdf0e10cSrcweir 30cdf0e10cSrcweir #include <rtl/math.hxx> 31cdf0e10cSrcweir 32cdf0e10cSrcweir #include <com/sun/star/rendering/CompositeOperation.hpp> 33cdf0e10cSrcweir #include <com/sun/star/util/Endianness.hpp> 34cdf0e10cSrcweir #include <com/sun/star/rendering/TextDirection.hpp> 35cdf0e10cSrcweir #include <com/sun/star/rendering/TexturingMode.hpp> 36cdf0e10cSrcweir #include <com/sun/star/rendering/PathCapType.hpp> 37cdf0e10cSrcweir #include <com/sun/star/rendering/PathJoinType.hpp> 385aaf853bSArmin Le Grand #include <com/sun/star/drawing/LineCap.hpp> 39cdf0e10cSrcweir 40cdf0e10cSrcweir #include <tools/poly.hxx> 41cdf0e10cSrcweir #include <vcl/window.hxx> 42cdf0e10cSrcweir #include <vcl/bitmapex.hxx> 43cdf0e10cSrcweir #include <vcl/bmpacc.hxx> 44cdf0e10cSrcweir #include <vcl/canvastools.hxx> 45cdf0e10cSrcweir 46cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx> 47cdf0e10cSrcweir #include <basegfx/range/b2drectangle.hxx> 48cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx> 49cdf0e10cSrcweir #include <basegfx/vector/b2dsize.hxx> 50cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx> 51cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx> 52cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx> 53cdf0e10cSrcweir #include <basegfx/polygon/b2dlinegeometry.hxx> 54cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx> 55cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx> 56cdf0e10cSrcweir 57cdf0e10cSrcweir #include <utility> 58cdf0e10cSrcweir 59cdf0e10cSrcweir #include <comphelper/sequence.hxx> 60cdf0e10cSrcweir #include <canvas/canvastools.hxx> 61cdf0e10cSrcweir 62cdf0e10cSrcweir #include "textlayout.hxx" 63cdf0e10cSrcweir #include "canvashelper.hxx" 64cdf0e10cSrcweir #include "canvasbitmap.hxx" 65cdf0e10cSrcweir #include "impltools.hxx" 66cdf0e10cSrcweir #include "canvasfont.hxx" 67cdf0e10cSrcweir 68cdf0e10cSrcweir 69cdf0e10cSrcweir using namespace ::com::sun::star; 70cdf0e10cSrcweir 71cdf0e10cSrcweir namespace vclcanvas 72cdf0e10cSrcweir { 73cdf0e10cSrcweir namespace 74cdf0e10cSrcweir { b2DJoineFromJoin(sal_Int8 nJoinType)75cdf0e10cSrcweir basegfx::B2DLineJoin b2DJoineFromJoin( sal_Int8 nJoinType ) 76cdf0e10cSrcweir { 77cdf0e10cSrcweir switch( nJoinType ) 78cdf0e10cSrcweir { 79cdf0e10cSrcweir case rendering::PathJoinType::NONE: 80cdf0e10cSrcweir return basegfx::B2DLINEJOIN_NONE; 81cdf0e10cSrcweir 82cdf0e10cSrcweir case rendering::PathJoinType::MITER: 83cdf0e10cSrcweir return basegfx::B2DLINEJOIN_MITER; 84cdf0e10cSrcweir 85cdf0e10cSrcweir case rendering::PathJoinType::ROUND: 86cdf0e10cSrcweir return basegfx::B2DLINEJOIN_ROUND; 87cdf0e10cSrcweir 88cdf0e10cSrcweir case rendering::PathJoinType::BEVEL: 89cdf0e10cSrcweir return basegfx::B2DLINEJOIN_BEVEL; 90cdf0e10cSrcweir 91cdf0e10cSrcweir default: 92cdf0e10cSrcweir ENSURE_OR_THROW( false, 93cdf0e10cSrcweir "b2DJoineFromJoin(): Unexpected join type" ); 94cdf0e10cSrcweir } 95cdf0e10cSrcweir 96cdf0e10cSrcweir return basegfx::B2DLINEJOIN_NONE; 97cdf0e10cSrcweir } 985aaf853bSArmin Le Grand unoCapeFromCap(sal_Int8 nCapType)995aaf853bSArmin Le Grand drawing::LineCap unoCapeFromCap( sal_Int8 nCapType) 1005aaf853bSArmin Le Grand { 1015aaf853bSArmin Le Grand switch ( nCapType) 1025aaf853bSArmin Le Grand { 1035aaf853bSArmin Le Grand case rendering::PathCapType::BUTT: 1045aaf853bSArmin Le Grand return drawing::LineCap_BUTT; 1055aaf853bSArmin Le Grand 1065aaf853bSArmin Le Grand case rendering::PathCapType::ROUND: 1075aaf853bSArmin Le Grand return drawing::LineCap_ROUND; 1085aaf853bSArmin Le Grand 1095aaf853bSArmin Le Grand case rendering::PathCapType::SQUARE: 1105aaf853bSArmin Le Grand return drawing::LineCap_SQUARE; 1115aaf853bSArmin Le Grand 1125aaf853bSArmin Le Grand default: 1135aaf853bSArmin Le Grand ENSURE_OR_THROW( false, 1145aaf853bSArmin Le Grand "unoCapeFromCap(): Unexpected cap type" ); 1155aaf853bSArmin Le Grand } 1165aaf853bSArmin Le Grand return drawing::LineCap_BUTT; 1175aaf853bSArmin Le Grand } 118cdf0e10cSrcweir } 119cdf0e10cSrcweir CanvasHelper()120cdf0e10cSrcweir CanvasHelper::CanvasHelper() : 121cdf0e10cSrcweir mpDevice(), 122cdf0e10cSrcweir mpProtectedOutDev(), 123cdf0e10cSrcweir mpOutDev(), 124cdf0e10cSrcweir mp2ndOutDev(), 125cdf0e10cSrcweir mbHaveAlpha( false ) 126cdf0e10cSrcweir { 127cdf0e10cSrcweir } 128cdf0e10cSrcweir disposing()129cdf0e10cSrcweir void CanvasHelper::disposing() 130cdf0e10cSrcweir { 131cdf0e10cSrcweir mpDevice = NULL; 132cdf0e10cSrcweir mpProtectedOutDev.reset(); 133cdf0e10cSrcweir mpOutDev.reset(); 134cdf0e10cSrcweir mp2ndOutDev.reset(); 135cdf0e10cSrcweir } 136cdf0e10cSrcweir init(rendering::XGraphicDevice & rDevice,const OutDevProviderSharedPtr & rOutDev,bool bProtect,bool bHaveAlpha)137cdf0e10cSrcweir void CanvasHelper::init( rendering::XGraphicDevice& rDevice, 138cdf0e10cSrcweir const OutDevProviderSharedPtr& rOutDev, 139cdf0e10cSrcweir bool bProtect, 140cdf0e10cSrcweir bool bHaveAlpha ) 141cdf0e10cSrcweir { 142cdf0e10cSrcweir // cast away const, need to change refcount (as this is 143cdf0e10cSrcweir // ~invisible to client code, still logically const) 144cdf0e10cSrcweir mpDevice = &rDevice; 145cdf0e10cSrcweir mbHaveAlpha = bHaveAlpha; 146cdf0e10cSrcweir 147cdf0e10cSrcweir setOutDev( rOutDev, bProtect ); 148cdf0e10cSrcweir } 149cdf0e10cSrcweir setOutDev(const OutDevProviderSharedPtr & rOutDev,bool bProtect)150cdf0e10cSrcweir void CanvasHelper::setOutDev( const OutDevProviderSharedPtr& rOutDev, 151cdf0e10cSrcweir bool bProtect ) 152cdf0e10cSrcweir { 153cdf0e10cSrcweir if( bProtect ) 154cdf0e10cSrcweir mpProtectedOutDev = rOutDev; 155cdf0e10cSrcweir else 156cdf0e10cSrcweir mpProtectedOutDev.reset(); 157cdf0e10cSrcweir 158cdf0e10cSrcweir mpOutDev = rOutDev; 159cdf0e10cSrcweir } 160cdf0e10cSrcweir setBackgroundOutDev(const OutDevProviderSharedPtr & rOutDev)161cdf0e10cSrcweir void CanvasHelper::setBackgroundOutDev( const OutDevProviderSharedPtr& rOutDev ) 162cdf0e10cSrcweir { 163cdf0e10cSrcweir mp2ndOutDev = rOutDev; 164cdf0e10cSrcweir mp2ndOutDev->getOutDev().EnableMapMode( sal_False ); 165*5f27b83cSArmin Le Grand mp2ndOutDev->getOutDev().SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW ); 166cdf0e10cSrcweir } 167cdf0e10cSrcweir clear()168cdf0e10cSrcweir void CanvasHelper::clear() 169cdf0e10cSrcweir { 170cdf0e10cSrcweir // are we disposed? 171cdf0e10cSrcweir if( mpOutDev ) 172cdf0e10cSrcweir { 173cdf0e10cSrcweir OutputDevice& rOutDev( mpOutDev->getOutDev() ); 174cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 175cdf0e10cSrcweir 176cdf0e10cSrcweir rOutDev.EnableMapMode( sal_False ); 177*5f27b83cSArmin Le Grand rOutDev.SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW ); 178cdf0e10cSrcweir rOutDev.SetLineColor( COL_WHITE ); 179cdf0e10cSrcweir rOutDev.SetFillColor( COL_WHITE ); 180cdf0e10cSrcweir rOutDev.DrawRect( Rectangle( Point(), 181cdf0e10cSrcweir rOutDev.GetOutputSizePixel()) ); 182cdf0e10cSrcweir 183cdf0e10cSrcweir if( mp2ndOutDev ) 184cdf0e10cSrcweir { 185cdf0e10cSrcweir OutputDevice& rOutDev2( mp2ndOutDev->getOutDev() ); 186cdf0e10cSrcweir 187cdf0e10cSrcweir rOutDev2.SetDrawMode( DRAWMODE_DEFAULT ); 188cdf0e10cSrcweir rOutDev2.EnableMapMode( sal_False ); 189*5f27b83cSArmin Le Grand rOutDev2.SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW ); 190cdf0e10cSrcweir rOutDev2.SetLineColor( COL_WHITE ); 191cdf0e10cSrcweir rOutDev2.SetFillColor( COL_WHITE ); 192cdf0e10cSrcweir rOutDev2.DrawRect( Rectangle( Point(), 193cdf0e10cSrcweir rOutDev2.GetOutputSizePixel()) ); 194cdf0e10cSrcweir rOutDev2.SetDrawMode( DRAWMODE_BLACKLINE | DRAWMODE_BLACKFILL | DRAWMODE_BLACKTEXT | 195cdf0e10cSrcweir DRAWMODE_BLACKGRADIENT | DRAWMODE_BLACKBITMAP ); 196cdf0e10cSrcweir } 197cdf0e10cSrcweir } 198cdf0e10cSrcweir } 199cdf0e10cSrcweir drawPoint(const rendering::XCanvas *,const geometry::RealPoint2D & aPoint,const rendering::ViewState & viewState,const rendering::RenderState & renderState)200cdf0e10cSrcweir void CanvasHelper::drawPoint( const rendering::XCanvas* , 201cdf0e10cSrcweir const geometry::RealPoint2D& aPoint, 202cdf0e10cSrcweir const rendering::ViewState& viewState, 203cdf0e10cSrcweir const rendering::RenderState& renderState ) 204cdf0e10cSrcweir { 205cdf0e10cSrcweir // are we disposed? 206cdf0e10cSrcweir if( mpOutDev ) 207cdf0e10cSrcweir { 208cdf0e10cSrcweir // nope, render 209cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 210cdf0e10cSrcweir setupOutDevState( viewState, renderState, LINE_COLOR ); 211cdf0e10cSrcweir 212cdf0e10cSrcweir const Point aOutPoint( tools::mapRealPoint2D( aPoint, 213cdf0e10cSrcweir viewState, renderState ) ); 214cdf0e10cSrcweir // TODO(F1): alpha 215cdf0e10cSrcweir mpOutDev->getOutDev().DrawPixel( aOutPoint ); 216cdf0e10cSrcweir 217cdf0e10cSrcweir if( mp2ndOutDev ) 218cdf0e10cSrcweir mp2ndOutDev->getOutDev().DrawPixel( aOutPoint ); 219cdf0e10cSrcweir } 220cdf0e10cSrcweir } 221cdf0e10cSrcweir drawLine(const rendering::XCanvas *,const geometry::RealPoint2D & aStartRealPoint2D,const geometry::RealPoint2D & aEndRealPoint2D,const rendering::ViewState & viewState,const rendering::RenderState & renderState)222cdf0e10cSrcweir void CanvasHelper::drawLine( const rendering::XCanvas* , 223cdf0e10cSrcweir const geometry::RealPoint2D& aStartRealPoint2D, 224cdf0e10cSrcweir const geometry::RealPoint2D& aEndRealPoint2D, 225cdf0e10cSrcweir const rendering::ViewState& viewState, 226cdf0e10cSrcweir const rendering::RenderState& renderState ) 227cdf0e10cSrcweir { 228cdf0e10cSrcweir // are we disposed? 229cdf0e10cSrcweir if( mpOutDev ) 230cdf0e10cSrcweir { 231cdf0e10cSrcweir // nope, render 232cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 233cdf0e10cSrcweir setupOutDevState( viewState, renderState, LINE_COLOR ); 234cdf0e10cSrcweir 235cdf0e10cSrcweir const Point aStartPoint( tools::mapRealPoint2D( aStartRealPoint2D, 236cdf0e10cSrcweir viewState, renderState ) ); 237cdf0e10cSrcweir const Point aEndPoint( tools::mapRealPoint2D( aEndRealPoint2D, 238cdf0e10cSrcweir viewState, renderState ) ); 239cdf0e10cSrcweir // TODO(F2): alpha 240cdf0e10cSrcweir mpOutDev->getOutDev().DrawLine( aStartPoint, aEndPoint ); 241cdf0e10cSrcweir 242cdf0e10cSrcweir if( mp2ndOutDev ) 243cdf0e10cSrcweir mp2ndOutDev->getOutDev().DrawLine( aStartPoint, aEndPoint ); 244cdf0e10cSrcweir } 245cdf0e10cSrcweir } 246cdf0e10cSrcweir drawBezier(const rendering::XCanvas *,const geometry::RealBezierSegment2D & aBezierSegment,const geometry::RealPoint2D & _aEndPoint,const rendering::ViewState & viewState,const rendering::RenderState & renderState)247cdf0e10cSrcweir void CanvasHelper::drawBezier( const rendering::XCanvas* , 248cdf0e10cSrcweir const geometry::RealBezierSegment2D& aBezierSegment, 249cdf0e10cSrcweir const geometry::RealPoint2D& _aEndPoint, 250cdf0e10cSrcweir const rendering::ViewState& viewState, 251cdf0e10cSrcweir const rendering::RenderState& renderState ) 252cdf0e10cSrcweir { 253cdf0e10cSrcweir if( mpOutDev ) 254cdf0e10cSrcweir { 255cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 256cdf0e10cSrcweir setupOutDevState( viewState, renderState, LINE_COLOR ); 257cdf0e10cSrcweir 258cdf0e10cSrcweir const Point& rStartPoint( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.Px, 259cdf0e10cSrcweir aBezierSegment.Py), 260cdf0e10cSrcweir viewState, renderState ) ); 261cdf0e10cSrcweir const Point& rCtrlPoint1( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.C1x, 262cdf0e10cSrcweir aBezierSegment.C1y), 263cdf0e10cSrcweir viewState, renderState ) ); 264cdf0e10cSrcweir const Point& rCtrlPoint2( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.C2x, 265cdf0e10cSrcweir aBezierSegment.C2y), 266cdf0e10cSrcweir viewState, renderState ) ); 267cdf0e10cSrcweir const Point& rEndPoint( tools::mapRealPoint2D( _aEndPoint, 268cdf0e10cSrcweir viewState, renderState ) ); 269cdf0e10cSrcweir 270cdf0e10cSrcweir ::Polygon aPoly(4); 271cdf0e10cSrcweir aPoly.SetPoint( rStartPoint, 0 ); 272cdf0e10cSrcweir aPoly.SetFlags( 0, POLY_NORMAL ); 273cdf0e10cSrcweir aPoly.SetPoint( rCtrlPoint1, 1 ); 274cdf0e10cSrcweir aPoly.SetFlags( 1, POLY_CONTROL ); 275cdf0e10cSrcweir aPoly.SetPoint( rCtrlPoint2, 2 ); 276cdf0e10cSrcweir aPoly.SetFlags( 2, POLY_CONTROL ); 277cdf0e10cSrcweir aPoly.SetPoint( rEndPoint, 3 ); 278cdf0e10cSrcweir aPoly.SetFlags( 3, POLY_NORMAL ); 279cdf0e10cSrcweir 280cdf0e10cSrcweir // TODO(F2): alpha 281cdf0e10cSrcweir mpOutDev->getOutDev().DrawPolygon( aPoly ); 282cdf0e10cSrcweir if( mp2ndOutDev ) 283cdf0e10cSrcweir mp2ndOutDev->getOutDev().DrawPolygon( aPoly ); 284cdf0e10cSrcweir } 285cdf0e10cSrcweir } 286cdf0e10cSrcweir drawPolyPolygon(const rendering::XCanvas *,const uno::Reference<rendering::XPolyPolygon2D> & xPolyPolygon,const rendering::ViewState & viewState,const rendering::RenderState & renderState)287cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* , 288cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon, 289cdf0e10cSrcweir const rendering::ViewState& viewState, 290cdf0e10cSrcweir const rendering::RenderState& renderState ) 291cdf0e10cSrcweir { 292cdf0e10cSrcweir ENSURE_ARG_OR_THROW( xPolyPolygon.is(), 293cdf0e10cSrcweir "polygon is NULL"); 294cdf0e10cSrcweir 295cdf0e10cSrcweir if( mpOutDev ) 296cdf0e10cSrcweir { 297cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 298cdf0e10cSrcweir setupOutDevState( viewState, renderState, LINE_COLOR ); 299cdf0e10cSrcweir 300cdf0e10cSrcweir const ::basegfx::B2DPolyPolygon& rPolyPoly( 301cdf0e10cSrcweir ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon) ); 302cdf0e10cSrcweir const PolyPolygon aPolyPoly( tools::mapPolyPolygon( rPolyPoly, viewState, renderState ) ); 303cdf0e10cSrcweir 304cdf0e10cSrcweir if( rPolyPoly.isClosed() ) 305cdf0e10cSrcweir { 306cdf0e10cSrcweir mpOutDev->getOutDev().DrawPolyPolygon( aPolyPoly ); 307cdf0e10cSrcweir 308cdf0e10cSrcweir if( mp2ndOutDev ) 309cdf0e10cSrcweir mp2ndOutDev->getOutDev().DrawPolyPolygon( aPolyPoly ); 310cdf0e10cSrcweir } 311cdf0e10cSrcweir else 312cdf0e10cSrcweir { 313cdf0e10cSrcweir // mixed open/closed state. Cannot render open polygon 314cdf0e10cSrcweir // via DrawPolyPolygon(), since that implicitley 315cdf0e10cSrcweir // closed every polygon. OTOH, no need to distinguish 316cdf0e10cSrcweir // further and render closed polygons via 317cdf0e10cSrcweir // DrawPolygon(), and open ones via DrawPolyLine(): 318cdf0e10cSrcweir // closed polygons will simply already contain the 319cdf0e10cSrcweir // closing segment. 320cdf0e10cSrcweir sal_uInt16 nSize( aPolyPoly.Count() ); 321cdf0e10cSrcweir 322cdf0e10cSrcweir for( sal_uInt16 i=0; i<nSize; ++i ) 323cdf0e10cSrcweir { 324cdf0e10cSrcweir mpOutDev->getOutDev().DrawPolyLine( aPolyPoly[i] ); 325cdf0e10cSrcweir 326cdf0e10cSrcweir if( mp2ndOutDev ) 327cdf0e10cSrcweir mp2ndOutDev->getOutDev().DrawPolyLine( aPolyPoly[i] ); 328cdf0e10cSrcweir } 329cdf0e10cSrcweir } 330cdf0e10cSrcweir } 331cdf0e10cSrcweir 332cdf0e10cSrcweir // TODO(P1): Provide caching here. 333cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 334cdf0e10cSrcweir } 335cdf0e10cSrcweir strokePolyPolygon(const rendering::XCanvas *,const uno::Reference<rendering::XPolyPolygon2D> & xPolyPolygon,const rendering::ViewState & viewState,const rendering::RenderState & renderState,const rendering::StrokeAttributes & strokeAttributes)336cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokePolyPolygon( const rendering::XCanvas* , 337cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon, 338cdf0e10cSrcweir const rendering::ViewState& viewState, 339cdf0e10cSrcweir const rendering::RenderState& renderState, 340cdf0e10cSrcweir const rendering::StrokeAttributes& strokeAttributes ) 341cdf0e10cSrcweir { 342cdf0e10cSrcweir ENSURE_ARG_OR_THROW( xPolyPolygon.is(), 343cdf0e10cSrcweir "polygon is NULL"); 344cdf0e10cSrcweir 345cdf0e10cSrcweir if( mpOutDev ) 346cdf0e10cSrcweir { 347cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 348cdf0e10cSrcweir 349cdf0e10cSrcweir ::basegfx::B2DHomMatrix aMatrix; 350cdf0e10cSrcweir ::canvas::tools::mergeViewAndRenderTransform(aMatrix, viewState, renderState); 351cdf0e10cSrcweir 352cdf0e10cSrcweir ::basegfx::B2DSize aLinePixelSize(strokeAttributes.StrokeWidth, 353cdf0e10cSrcweir strokeAttributes.StrokeWidth); 354cdf0e10cSrcweir aLinePixelSize *= aMatrix; 355cdf0e10cSrcweir 356cdf0e10cSrcweir ::basegfx::B2DPolyPolygon aPolyPoly( 357cdf0e10cSrcweir ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon) ); 358cdf0e10cSrcweir 359cdf0e10cSrcweir if( aPolyPoly.areControlPointsUsed() ) 360cdf0e10cSrcweir { 361cdf0e10cSrcweir // AW: Not needed for ApplyLineDashing anymore; should be removed 362cdf0e10cSrcweir aPolyPoly = ::basegfx::tools::adaptiveSubdivideByAngle(aPolyPoly); 363cdf0e10cSrcweir } 364cdf0e10cSrcweir 365cdf0e10cSrcweir // apply dashing, if any 366cdf0e10cSrcweir if( strokeAttributes.DashArray.getLength() ) 367cdf0e10cSrcweir { 368cdf0e10cSrcweir const ::std::vector<double>& aDashArray( 369cdf0e10cSrcweir ::comphelper::sequenceToContainer< ::std::vector<double> >(strokeAttributes.DashArray) ); 370cdf0e10cSrcweir 371cdf0e10cSrcweir ::basegfx::B2DPolyPolygon aDashedPolyPoly; 372cdf0e10cSrcweir 373cdf0e10cSrcweir for( sal_uInt32 i=0; i<aPolyPoly.count(); ++i ) 374cdf0e10cSrcweir { 375cdf0e10cSrcweir // AW: new interface; You may also get gaps in the same run now 376cdf0e10cSrcweir basegfx::tools::applyLineDashing(aPolyPoly.getB2DPolygon(i), aDashArray, &aDashedPolyPoly); 377cdf0e10cSrcweir //aDashedPolyPoly.append( 378cdf0e10cSrcweir // ::basegfx::tools::applyLineDashing( aPolyPoly.getB2DPolygon(i), 379cdf0e10cSrcweir // aDashArray ) ); 380cdf0e10cSrcweir } 381cdf0e10cSrcweir 382cdf0e10cSrcweir aPolyPoly = aDashedPolyPoly; 383cdf0e10cSrcweir } 384cdf0e10cSrcweir 385cdf0e10cSrcweir ::basegfx::B2DPolyPolygon aStrokedPolyPoly; 386cdf0e10cSrcweir if( aLinePixelSize.getLength() < 1.42 ) 387cdf0e10cSrcweir { 388cdf0e10cSrcweir // line width < 1.0 in device pixel, thus, output as a 389cdf0e10cSrcweir // simple hairline poly-polygon 390cdf0e10cSrcweir setupOutDevState( viewState, renderState, LINE_COLOR ); 391cdf0e10cSrcweir 392cdf0e10cSrcweir aStrokedPolyPoly = aPolyPoly; 393cdf0e10cSrcweir } 394cdf0e10cSrcweir else 395cdf0e10cSrcweir { 396cdf0e10cSrcweir // render as a 'thick' line 397cdf0e10cSrcweir setupOutDevState( viewState, renderState, FILL_COLOR ); 398cdf0e10cSrcweir 399cdf0e10cSrcweir for( sal_uInt32 i=0; i<aPolyPoly.count(); ++i ) 400cdf0e10cSrcweir { 401cdf0e10cSrcweir // TODO(F2): Use MiterLimit from StrokeAttributes, 402cdf0e10cSrcweir // need to convert it here to angle. 403cdf0e10cSrcweir 404cdf0e10cSrcweir // TODO(F2): Also use Cap settings from 405cdf0e10cSrcweir // StrokeAttributes, the 406cdf0e10cSrcweir // createAreaGeometryForLineStartEnd() method does not 407cdf0e10cSrcweir // seem to fit very well here 408cdf0e10cSrcweir 409cdf0e10cSrcweir // AW: New interface, will create bezier polygons now 410cdf0e10cSrcweir aStrokedPolyPoly.append(basegfx::tools::createAreaGeometry( 4115aaf853bSArmin Le Grand aPolyPoly.getB2DPolygon(i), 4125aaf853bSArmin Le Grand strokeAttributes.StrokeWidth*0.5, 4135aaf853bSArmin Le Grand b2DJoineFromJoin(strokeAttributes.JoinType), 4145aaf853bSArmin Le Grand unoCapeFromCap(strokeAttributes.StartCapType))); 415cdf0e10cSrcweir //aStrokedPolyPoly.append( 416cdf0e10cSrcweir // ::basegfx::tools::createAreaGeometryForPolygon( aPolyPoly.getB2DPolygon(i), 417cdf0e10cSrcweir // strokeAttributes.StrokeWidth*0.5, 418cdf0e10cSrcweir // b2DJoineFromJoin(strokeAttributes.JoinType) ) ); 419cdf0e10cSrcweir } 420cdf0e10cSrcweir } 421cdf0e10cSrcweir 422cdf0e10cSrcweir // transform only _now_, all the StrokeAttributes are in 423cdf0e10cSrcweir // user coordinates. 424cdf0e10cSrcweir aStrokedPolyPoly.transform( aMatrix ); 425cdf0e10cSrcweir 426cdf0e10cSrcweir const PolyPolygon aVCLPolyPoly( aStrokedPolyPoly ); 427cdf0e10cSrcweir 428cdf0e10cSrcweir // TODO(F2): When using alpha here, must handle that via 429cdf0e10cSrcweir // temporary surface or somesuch. 430cdf0e10cSrcweir 431cdf0e10cSrcweir // Note: the generated stroke poly-polygon is NOT free of 432cdf0e10cSrcweir // self-intersections. Therefore, if we would render it 433cdf0e10cSrcweir // via OutDev::DrawPolyPolygon(), on/off fill would 434cdf0e10cSrcweir // generate off areas on those self-intersections. 435cdf0e10cSrcweir sal_uInt16 nSize( aVCLPolyPoly.Count() ); 436cdf0e10cSrcweir 437cdf0e10cSrcweir for( sal_uInt16 i=0; i<nSize; ++i ) 438cdf0e10cSrcweir { 439cdf0e10cSrcweir if( aStrokedPolyPoly.getB2DPolygon( i ).isClosed() ) { 440cdf0e10cSrcweir mpOutDev->getOutDev().DrawPolygon( aVCLPolyPoly[i] ); 441cdf0e10cSrcweir if( mp2ndOutDev ) 442cdf0e10cSrcweir mp2ndOutDev->getOutDev().DrawPolygon( aVCLPolyPoly[i] ); 443cdf0e10cSrcweir } else { 444cdf0e10cSrcweir const sal_uInt16 nPolySize = aVCLPolyPoly[i].GetSize(); 445cdf0e10cSrcweir if( nPolySize ) { 446cdf0e10cSrcweir Point rPrevPoint = aVCLPolyPoly[i].GetPoint( 0 ); 447cdf0e10cSrcweir Point rPoint; 448cdf0e10cSrcweir 449cdf0e10cSrcweir for( sal_uInt16 j=1; j<nPolySize; j++ ) { 450cdf0e10cSrcweir rPoint = aVCLPolyPoly[i].GetPoint( j ); 451cdf0e10cSrcweir mpOutDev->getOutDev().DrawLine( rPrevPoint, rPoint ); 452cdf0e10cSrcweir if( mp2ndOutDev ) 453cdf0e10cSrcweir mp2ndOutDev->getOutDev().DrawLine( rPrevPoint, rPoint ); 454cdf0e10cSrcweir rPrevPoint = rPoint; 455cdf0e10cSrcweir } 456cdf0e10cSrcweir } 457cdf0e10cSrcweir } 458cdf0e10cSrcweir } 459cdf0e10cSrcweir } 460cdf0e10cSrcweir 461cdf0e10cSrcweir // TODO(P1): Provide caching here. 462cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 463cdf0e10cSrcweir } 464cdf0e10cSrcweir strokeTexturedPolyPolygon(const rendering::XCanvas *,const uno::Reference<rendering::XPolyPolygon2D> &,const rendering::ViewState &,const rendering::RenderState &,const uno::Sequence<rendering::Texture> &,const rendering::StrokeAttributes &)465cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas* , 466cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& , 467cdf0e10cSrcweir const rendering::ViewState& , 468cdf0e10cSrcweir const rendering::RenderState& , 469cdf0e10cSrcweir const uno::Sequence< rendering::Texture >& , 470cdf0e10cSrcweir const rendering::StrokeAttributes& ) 471cdf0e10cSrcweir { 472cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 473cdf0e10cSrcweir } 474cdf0e10cSrcweir strokeTextureMappedPolyPolygon(const rendering::XCanvas *,const uno::Reference<rendering::XPolyPolygon2D> &,const rendering::ViewState &,const rendering::RenderState &,const uno::Sequence<rendering::Texture> &,const uno::Reference<geometry::XMapping2D> &,const rendering::StrokeAttributes &)475cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas* , 476cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& , 477cdf0e10cSrcweir const rendering::ViewState& , 478cdf0e10cSrcweir const rendering::RenderState& , 479cdf0e10cSrcweir const uno::Sequence< rendering::Texture >& , 480cdf0e10cSrcweir const uno::Reference< geometry::XMapping2D >& , 481cdf0e10cSrcweir const rendering::StrokeAttributes& ) 482cdf0e10cSrcweir { 483cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 484cdf0e10cSrcweir } 485cdf0e10cSrcweir queryStrokeShapes(const rendering::XCanvas *,const uno::Reference<rendering::XPolyPolygon2D> &,const rendering::ViewState &,const rendering::RenderState &,const rendering::StrokeAttributes &)486cdf0e10cSrcweir uno::Reference< rendering::XPolyPolygon2D > CanvasHelper::queryStrokeShapes( const rendering::XCanvas* , 487cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& , 488cdf0e10cSrcweir const rendering::ViewState& , 489cdf0e10cSrcweir const rendering::RenderState& , 490cdf0e10cSrcweir const rendering::StrokeAttributes& ) 491cdf0e10cSrcweir { 492cdf0e10cSrcweir return uno::Reference< rendering::XPolyPolygon2D >(NULL); 493cdf0e10cSrcweir } 494cdf0e10cSrcweir fillPolyPolygon(const rendering::XCanvas *,const uno::Reference<rendering::XPolyPolygon2D> & xPolyPolygon,const rendering::ViewState & viewState,const rendering::RenderState & renderState)495cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillPolyPolygon( const rendering::XCanvas* , 496cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon, 497cdf0e10cSrcweir const rendering::ViewState& viewState, 498cdf0e10cSrcweir const rendering::RenderState& renderState ) 499cdf0e10cSrcweir { 500cdf0e10cSrcweir ENSURE_ARG_OR_THROW( xPolyPolygon.is(), 501cdf0e10cSrcweir "polygon is NULL"); 502cdf0e10cSrcweir 503cdf0e10cSrcweir if( mpOutDev ) 504cdf0e10cSrcweir { 505cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 506cdf0e10cSrcweir 507cdf0e10cSrcweir const int nTransparency( setupOutDevState( viewState, renderState, FILL_COLOR ) ); 508cdf0e10cSrcweir const int nTransPercent( (nTransparency * 100 + 128) / 255 ); // normal rounding, no truncation here 509cdf0e10cSrcweir ::basegfx::B2DPolyPolygon aB2DPolyPoly( 510cdf0e10cSrcweir ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon)); 511cdf0e10cSrcweir aB2DPolyPoly.setClosed(true); // ensure closed poly, otherwise VCL does not fill 512cdf0e10cSrcweir const PolyPolygon aPolyPoly( tools::mapPolyPolygon( 513cdf0e10cSrcweir aB2DPolyPoly, 514cdf0e10cSrcweir viewState, renderState ) ); 515cdf0e10cSrcweir const bool bSourceAlpha( renderState.CompositeOperation == rendering::CompositeOperation::SOURCE ); 516cdf0e10cSrcweir if( !nTransparency || bSourceAlpha ) 517cdf0e10cSrcweir { 518cdf0e10cSrcweir mpOutDev->getOutDev().DrawPolyPolygon( aPolyPoly ); 519cdf0e10cSrcweir } 520cdf0e10cSrcweir else 521cdf0e10cSrcweir { 522cdf0e10cSrcweir mpOutDev->getOutDev().DrawTransparent( aPolyPoly, (sal_uInt16)nTransPercent ); 523cdf0e10cSrcweir } 524cdf0e10cSrcweir 525cdf0e10cSrcweir if( mp2ndOutDev ) 526cdf0e10cSrcweir { 527cdf0e10cSrcweir if( !nTransparency || bSourceAlpha ) 528cdf0e10cSrcweir { 529cdf0e10cSrcweir // HACK. Normally, CanvasHelper does not care 530cdf0e10cSrcweir // about actually what mp2ndOutDev is... 531cdf0e10cSrcweir if( bSourceAlpha && nTransparency == 255 ) 532cdf0e10cSrcweir { 533cdf0e10cSrcweir mp2ndOutDev->getOutDev().SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT | 534cdf0e10cSrcweir DRAWMODE_WHITEGRADIENT | DRAWMODE_WHITEBITMAP ); 535cdf0e10cSrcweir mp2ndOutDev->getOutDev().SetFillColor( COL_WHITE ); 536cdf0e10cSrcweir mp2ndOutDev->getOutDev().DrawPolyPolygon( aPolyPoly ); 537cdf0e10cSrcweir mp2ndOutDev->getOutDev().SetDrawMode( DRAWMODE_BLACKLINE | DRAWMODE_BLACKFILL | DRAWMODE_BLACKTEXT | 538cdf0e10cSrcweir DRAWMODE_BLACKGRADIENT | DRAWMODE_BLACKBITMAP ); 539cdf0e10cSrcweir } 540cdf0e10cSrcweir else 541cdf0e10cSrcweir { 542cdf0e10cSrcweir mp2ndOutDev->getOutDev().DrawPolyPolygon( aPolyPoly ); 543cdf0e10cSrcweir } 544cdf0e10cSrcweir } 545cdf0e10cSrcweir else 546cdf0e10cSrcweir { 547cdf0e10cSrcweir mp2ndOutDev->getOutDev().DrawTransparent( aPolyPoly, (sal_uInt16)nTransPercent ); 548cdf0e10cSrcweir } 549cdf0e10cSrcweir } 550cdf0e10cSrcweir } 551cdf0e10cSrcweir 552cdf0e10cSrcweir // TODO(P1): Provide caching here. 553cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 554cdf0e10cSrcweir } 555cdf0e10cSrcweir fillTextureMappedPolyPolygon(const rendering::XCanvas *,const uno::Reference<rendering::XPolyPolygon2D> &,const rendering::ViewState &,const rendering::RenderState &,const uno::Sequence<rendering::Texture> &,const uno::Reference<geometry::XMapping2D> &)556cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas* , 557cdf0e10cSrcweir const uno::Reference< rendering::XPolyPolygon2D >& , 558cdf0e10cSrcweir const rendering::ViewState& , 559cdf0e10cSrcweir const rendering::RenderState& , 560cdf0e10cSrcweir const uno::Sequence< rendering::Texture >& , 561cdf0e10cSrcweir const uno::Reference< geometry::XMapping2D >& ) 562cdf0e10cSrcweir { 563cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 564cdf0e10cSrcweir } 565cdf0e10cSrcweir createFont(const rendering::XCanvas *,const rendering::FontRequest & fontRequest,const uno::Sequence<beans::PropertyValue> & extraFontProperties,const geometry::Matrix2D & fontMatrix)566cdf0e10cSrcweir uno::Reference< rendering::XCanvasFont > CanvasHelper::createFont( const rendering::XCanvas* , 567cdf0e10cSrcweir const rendering::FontRequest& fontRequest, 568cdf0e10cSrcweir const uno::Sequence< beans::PropertyValue >& extraFontProperties, 569cdf0e10cSrcweir const geometry::Matrix2D& fontMatrix ) 570cdf0e10cSrcweir { 571cdf0e10cSrcweir if( mpOutDev && mpDevice ) 572cdf0e10cSrcweir { 573cdf0e10cSrcweir // TODO(F2): font properties and font matrix 574cdf0e10cSrcweir return uno::Reference< rendering::XCanvasFont >( 575cdf0e10cSrcweir new CanvasFont(fontRequest, extraFontProperties, fontMatrix, 576cdf0e10cSrcweir *mpDevice, mpOutDev) ); 577cdf0e10cSrcweir } 578cdf0e10cSrcweir 579cdf0e10cSrcweir return uno::Reference< rendering::XCanvasFont >(); 580cdf0e10cSrcweir } 581cdf0e10cSrcweir queryAvailableFonts(const rendering::XCanvas *,const rendering::FontInfo &,const uno::Sequence<beans::PropertyValue> &)582cdf0e10cSrcweir uno::Sequence< rendering::FontInfo > CanvasHelper::queryAvailableFonts( const rendering::XCanvas* , 583cdf0e10cSrcweir const rendering::FontInfo& , 584cdf0e10cSrcweir const uno::Sequence< beans::PropertyValue >& ) 585cdf0e10cSrcweir { 586cdf0e10cSrcweir // TODO(F2) 587cdf0e10cSrcweir return uno::Sequence< rendering::FontInfo >(); 588cdf0e10cSrcweir } 589cdf0e10cSrcweir drawText(const rendering::XCanvas *,const rendering::StringContext & text,const uno::Reference<rendering::XCanvasFont> & xFont,const rendering::ViewState & viewState,const rendering::RenderState & renderState,sal_Int8 textDirection)590cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawText( const rendering::XCanvas* , 591cdf0e10cSrcweir const rendering::StringContext& text, 592cdf0e10cSrcweir const uno::Reference< rendering::XCanvasFont >& xFont, 593cdf0e10cSrcweir const rendering::ViewState& viewState, 594cdf0e10cSrcweir const rendering::RenderState& renderState, 595cdf0e10cSrcweir sal_Int8 textDirection ) 596cdf0e10cSrcweir { 597cdf0e10cSrcweir ENSURE_ARG_OR_THROW( xFont.is(), 598cdf0e10cSrcweir "font is NULL"); 599cdf0e10cSrcweir 600cdf0e10cSrcweir if( mpOutDev ) 601cdf0e10cSrcweir { 602cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 603cdf0e10cSrcweir 604cdf0e10cSrcweir ::Point aOutpos; 605cdf0e10cSrcweir if( !setupTextOutput( aOutpos, viewState, renderState, xFont ) ) 606cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); // no output necessary 607cdf0e10cSrcweir 608cdf0e10cSrcweir // change text direction and layout mode 609cdf0e10cSrcweir sal_uIntPtr nLayoutMode(0); 610cdf0e10cSrcweir switch( textDirection ) 611cdf0e10cSrcweir { 612cdf0e10cSrcweir case rendering::TextDirection::WEAK_LEFT_TO_RIGHT: 613cdf0e10cSrcweir nLayoutMode |= TEXT_LAYOUT_BIDI_LTR; 614cdf0e10cSrcweir // FALLTHROUGH intended 615cdf0e10cSrcweir case rendering::TextDirection::STRONG_LEFT_TO_RIGHT: 616cdf0e10cSrcweir nLayoutMode |= TEXT_LAYOUT_BIDI_LTR | TEXT_LAYOUT_BIDI_STRONG; 617cdf0e10cSrcweir nLayoutMode |= TEXT_LAYOUT_TEXTORIGIN_LEFT; 618cdf0e10cSrcweir break; 619cdf0e10cSrcweir 620cdf0e10cSrcweir case rendering::TextDirection::WEAK_RIGHT_TO_LEFT: 621cdf0e10cSrcweir nLayoutMode |= TEXT_LAYOUT_BIDI_RTL; 622cdf0e10cSrcweir // FALLTHROUGH intended 623cdf0e10cSrcweir case rendering::TextDirection::STRONG_RIGHT_TO_LEFT: 624cdf0e10cSrcweir nLayoutMode |= TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_BIDI_STRONG; 625cdf0e10cSrcweir nLayoutMode |= TEXT_LAYOUT_TEXTORIGIN_RIGHT; 626cdf0e10cSrcweir break; 627cdf0e10cSrcweir } 628cdf0e10cSrcweir 629cdf0e10cSrcweir // TODO(F2): alpha 630cdf0e10cSrcweir mpOutDev->getOutDev().SetLayoutMode( nLayoutMode ); 631cdf0e10cSrcweir mpOutDev->getOutDev().DrawText( aOutpos, 632cdf0e10cSrcweir text.Text, 633cdf0e10cSrcweir ::canvas::tools::numeric_cast<sal_uInt16>(text.StartPosition), 634cdf0e10cSrcweir ::canvas::tools::numeric_cast<sal_uInt16>(text.Length) ); 635cdf0e10cSrcweir 636cdf0e10cSrcweir if( mp2ndOutDev ) 637cdf0e10cSrcweir { 638cdf0e10cSrcweir mp2ndOutDev->getOutDev().SetLayoutMode( nLayoutMode ); 639cdf0e10cSrcweir mp2ndOutDev->getOutDev().DrawText( aOutpos, 640cdf0e10cSrcweir text.Text, 641cdf0e10cSrcweir ::canvas::tools::numeric_cast<sal_uInt16>(text.StartPosition), 642cdf0e10cSrcweir ::canvas::tools::numeric_cast<sal_uInt16>(text.Length) ); 643cdf0e10cSrcweir } 644cdf0e10cSrcweir } 645cdf0e10cSrcweir 646cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 647cdf0e10cSrcweir } 648cdf0e10cSrcweir drawTextLayout(const rendering::XCanvas *,const uno::Reference<rendering::XTextLayout> & xLayoutedText,const rendering::ViewState & viewState,const rendering::RenderState & renderState)649cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawTextLayout( const rendering::XCanvas* , 650cdf0e10cSrcweir const uno::Reference< rendering::XTextLayout >& xLayoutedText, 651cdf0e10cSrcweir const rendering::ViewState& viewState, 652cdf0e10cSrcweir const rendering::RenderState& renderState ) 653cdf0e10cSrcweir { 654cdf0e10cSrcweir ENSURE_ARG_OR_THROW( xLayoutedText.is(), 655cdf0e10cSrcweir "layout is NULL"); 656cdf0e10cSrcweir 657cdf0e10cSrcweir TextLayout* pTextLayout = dynamic_cast< TextLayout* >( xLayoutedText.get() ); 658cdf0e10cSrcweir 659cdf0e10cSrcweir if( pTextLayout ) 660cdf0e10cSrcweir { 661cdf0e10cSrcweir if( mpOutDev ) 662cdf0e10cSrcweir { 663cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 664cdf0e10cSrcweir 665cdf0e10cSrcweir // TODO(T3): Race condition. We're taking the font 666cdf0e10cSrcweir // from xLayoutedText, and then calling draw() at it, 667cdf0e10cSrcweir // without exclusive access. Move setupTextOutput(), 668cdf0e10cSrcweir // e.g. to impltools? 669cdf0e10cSrcweir 670cdf0e10cSrcweir ::Point aOutpos; 671cdf0e10cSrcweir if( !setupTextOutput( aOutpos, viewState, renderState, xLayoutedText->getFont() ) ) 672cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); // no output necessary 673cdf0e10cSrcweir 674cdf0e10cSrcweir // TODO(F2): What about the offset scalings? 675cdf0e10cSrcweir // TODO(F2): alpha 676cdf0e10cSrcweir pTextLayout->draw( mpOutDev->getOutDev(), aOutpos, viewState, renderState ); 677cdf0e10cSrcweir 678cdf0e10cSrcweir if( mp2ndOutDev ) 679cdf0e10cSrcweir pTextLayout->draw( mp2ndOutDev->getOutDev(), aOutpos, viewState, renderState ); 680cdf0e10cSrcweir } 681cdf0e10cSrcweir } 682cdf0e10cSrcweir else 683cdf0e10cSrcweir { 684cdf0e10cSrcweir ENSURE_ARG_OR_THROW( false, 685cdf0e10cSrcweir "TextLayout not compatible with this canvas" ); 686cdf0e10cSrcweir } 687cdf0e10cSrcweir 688cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 689cdf0e10cSrcweir } 690cdf0e10cSrcweir implDrawBitmap(const rendering::XCanvas * pCanvas,const uno::Reference<rendering::XBitmap> & xBitmap,const rendering::ViewState & viewState,const rendering::RenderState & renderState,bool bModulateColors)691cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::implDrawBitmap( const rendering::XCanvas* pCanvas, 692cdf0e10cSrcweir const uno::Reference< rendering::XBitmap >& xBitmap, 693cdf0e10cSrcweir const rendering::ViewState& viewState, 694cdf0e10cSrcweir const rendering::RenderState& renderState, 695cdf0e10cSrcweir bool bModulateColors ) 696cdf0e10cSrcweir { 697cdf0e10cSrcweir ENSURE_ARG_OR_THROW( xBitmap.is(), 698cdf0e10cSrcweir "bitmap is NULL"); 699cdf0e10cSrcweir 700cdf0e10cSrcweir ::canvas::tools::verifyInput( renderState, 701cdf0e10cSrcweir BOOST_CURRENT_FUNCTION, 702cdf0e10cSrcweir mpDevice, 703cdf0e10cSrcweir 4, 704cdf0e10cSrcweir bModulateColors ? 3 : 0 ); 705cdf0e10cSrcweir 706cdf0e10cSrcweir if( mpOutDev ) 707cdf0e10cSrcweir { 708cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 709cdf0e10cSrcweir setupOutDevState( viewState, renderState, IGNORE_COLOR ); 710cdf0e10cSrcweir 711cdf0e10cSrcweir ::basegfx::B2DHomMatrix aMatrix; 712cdf0e10cSrcweir ::canvas::tools::mergeViewAndRenderTransform(aMatrix, viewState, renderState); 713cdf0e10cSrcweir 714cdf0e10cSrcweir ::basegfx::B2DPoint aOutputPos( 0.0, 0.0 ); 715cdf0e10cSrcweir aOutputPos *= aMatrix; 716cdf0e10cSrcweir 717cdf0e10cSrcweir BitmapEx aBmpEx( tools::bitmapExFromXBitmap(xBitmap) ); 718cdf0e10cSrcweir 719cdf0e10cSrcweir // TODO(F2): Implement modulation again for other color 720cdf0e10cSrcweir // channels (currently, works only for alpha). Note: this 721cdf0e10cSrcweir // is already implemented in transformBitmap() 722cdf0e10cSrcweir if( bModulateColors && 723cdf0e10cSrcweir renderState.DeviceColor.getLength() > 3 ) 724cdf0e10cSrcweir { 725cdf0e10cSrcweir // optimize away the case where alpha modulation value 726cdf0e10cSrcweir // is 1.0 - we then simply switch off modulation at all 727cdf0e10cSrcweir bModulateColors = !::rtl::math::approxEqual( 728cdf0e10cSrcweir renderState.DeviceColor[3], 1.0); 729cdf0e10cSrcweir } 730cdf0e10cSrcweir 731cdf0e10cSrcweir // check whether we can render bitmap as-is: must not 732cdf0e10cSrcweir // modulate colors, matrix must either be the identity 733cdf0e10cSrcweir // transform (that's clear), _or_ contain only 734cdf0e10cSrcweir // translational components. 735cdf0e10cSrcweir if( !bModulateColors && 736cdf0e10cSrcweir (aMatrix.isIdentity() || 737cdf0e10cSrcweir (::basegfx::fTools::equalZero( aMatrix.get(0,1) ) && 738cdf0e10cSrcweir ::basegfx::fTools::equalZero( aMatrix.get(1,0) ) && 739cdf0e10cSrcweir ::rtl::math::approxEqual(aMatrix.get(0,0), 1.0) && 740cdf0e10cSrcweir ::rtl::math::approxEqual(aMatrix.get(1,1), 1.0)) ) ) 741cdf0e10cSrcweir { 742cdf0e10cSrcweir // optimized case: identity matrix, or only 743cdf0e10cSrcweir // translational components. 744cdf0e10cSrcweir mpOutDev->getOutDev().DrawBitmapEx( ::vcl::unotools::pointFromB2DPoint( aOutputPos ), 745cdf0e10cSrcweir aBmpEx ); 746cdf0e10cSrcweir 747cdf0e10cSrcweir if( mp2ndOutDev ) 748cdf0e10cSrcweir mp2ndOutDev->getOutDev().DrawBitmapEx( ::vcl::unotools::pointFromB2DPoint( aOutputPos ), 749cdf0e10cSrcweir aBmpEx ); 750cdf0e10cSrcweir 751cdf0e10cSrcweir // Returning a cache object is not useful, the XBitmap 752cdf0e10cSrcweir // itself serves this purpose 753cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 754cdf0e10cSrcweir } 755cdf0e10cSrcweir else 756cdf0e10cSrcweir { 757cdf0e10cSrcweir // Matrix contains non-trivial transformation (or 758cdf0e10cSrcweir // color modulation is requested), decompose to check 759cdf0e10cSrcweir // whether GraphicObject suffices 760cdf0e10cSrcweir ::basegfx::B2DVector aScale; 761cdf0e10cSrcweir double nRotate; 762cdf0e10cSrcweir double nShearX; 763cdf0e10cSrcweir aMatrix.decompose( aScale, aOutputPos, nRotate, nShearX ); 764cdf0e10cSrcweir 765cdf0e10cSrcweir GraphicAttr aGrfAttr; 766cdf0e10cSrcweir GraphicObjectSharedPtr pGrfObj; 767cdf0e10cSrcweir 768cdf0e10cSrcweir ::Size aBmpSize( aBmpEx.GetSizePixel() ); 769cdf0e10cSrcweir 770cdf0e10cSrcweir // setup alpha modulation 771cdf0e10cSrcweir if( bModulateColors ) 772cdf0e10cSrcweir { 773cdf0e10cSrcweir const double nAlphaModulation( renderState.DeviceColor[3] ); 774cdf0e10cSrcweir 775cdf0e10cSrcweir // TODO(F1): Note that the GraphicManager has a 776cdf0e10cSrcweir // subtle difference in how it calculates the 777cdf0e10cSrcweir // resulting alpha value: it's using the inverse 778cdf0e10cSrcweir // alpha values (i.e. 'transparency'), and 779cdf0e10cSrcweir // calculates transOrig + transModulate, instead 780cdf0e10cSrcweir // of transOrig + transModulate - 781cdf0e10cSrcweir // transOrig*transModulate (which would be 782cdf0e10cSrcweir // equivalent to the origAlpha*modulateAlpha the 783cdf0e10cSrcweir // DX canvas performs) 784cdf0e10cSrcweir aGrfAttr.SetTransparency( 785cdf0e10cSrcweir static_cast< sal_uInt8 >( 786cdf0e10cSrcweir ::basegfx::fround( 255.0*( 1.0 - nAlphaModulation ) ) ) ); 787cdf0e10cSrcweir } 788cdf0e10cSrcweir 789cdf0e10cSrcweir if( ::basegfx::fTools::equalZero( nShearX ) ) 790cdf0e10cSrcweir { 791cdf0e10cSrcweir // no shear, GraphicObject is enough (the 792cdf0e10cSrcweir // GraphicObject only supports scaling, rotation 793cdf0e10cSrcweir // and translation) 794cdf0e10cSrcweir 795cdf0e10cSrcweir // #i75339# don't apply mirror flags, having 796cdf0e10cSrcweir // negative size values is enough to make 797cdf0e10cSrcweir // GraphicObject flip the bitmap 798cdf0e10cSrcweir 799cdf0e10cSrcweir // The angle has to be mapped from radian to tenths of 800cdf0e10cSrcweir // degress with the orientation reversed: [0,2Pi) -> 801cdf0e10cSrcweir // (3600,0]. Note that the original angle may have 802cdf0e10cSrcweir // values outside the [0,2Pi) interval. 803cdf0e10cSrcweir const double nAngleInTenthOfDegrees (3600.0 - nRotate * 3600.0 / (2*M_PI)); 804cdf0e10cSrcweir aGrfAttr.SetRotation( static_cast< sal_uInt16 >(::basegfx::fround(nAngleInTenthOfDegrees)) ); 805cdf0e10cSrcweir 806cdf0e10cSrcweir pGrfObj.reset( new GraphicObject( aBmpEx ) ); 807cdf0e10cSrcweir } 808cdf0e10cSrcweir else 809cdf0e10cSrcweir { 810cdf0e10cSrcweir // modify output position, to account for the fact 811cdf0e10cSrcweir // that transformBitmap() always normalizes its output 812cdf0e10cSrcweir // bitmap into the smallest enclosing box. 813cdf0e10cSrcweir ::basegfx::B2DRectangle aDestRect; 814cdf0e10cSrcweir ::canvas::tools::calcTransformedRectBounds( aDestRect, 815cdf0e10cSrcweir ::basegfx::B2DRectangle(0, 816cdf0e10cSrcweir 0, 817cdf0e10cSrcweir aBmpSize.Width(), 818cdf0e10cSrcweir aBmpSize.Height()), 819cdf0e10cSrcweir aMatrix ); 820cdf0e10cSrcweir 821cdf0e10cSrcweir aOutputPos.setX( aDestRect.getMinX() ); 822cdf0e10cSrcweir aOutputPos.setY( aDestRect.getMinY() ); 823cdf0e10cSrcweir 824cdf0e10cSrcweir // complex transformation, use generic affine bitmap 825cdf0e10cSrcweir // transformation 826cdf0e10cSrcweir aBmpEx = tools::transformBitmap( aBmpEx, 827cdf0e10cSrcweir aMatrix, 828cdf0e10cSrcweir renderState.DeviceColor, 829cdf0e10cSrcweir tools::MODULATE_NONE ); 830cdf0e10cSrcweir 831cdf0e10cSrcweir pGrfObj.reset( new GraphicObject( aBmpEx ) ); 832cdf0e10cSrcweir 833cdf0e10cSrcweir // clear scale values, generated bitmap already 834cdf0e10cSrcweir // contains scaling 835cdf0e10cSrcweir aScale.setX( 1.0 ); aScale.setY( 1.0 ); 836cdf0e10cSrcweir 837cdf0e10cSrcweir // update bitmap size, bitmap has changed above. 838cdf0e10cSrcweir aBmpSize = aBmpEx.GetSizePixel(); 839cdf0e10cSrcweir } 840cdf0e10cSrcweir 841cdf0e10cSrcweir // output GraphicObject 842cdf0e10cSrcweir const ::Point aPt( ::vcl::unotools::pointFromB2DPoint( aOutputPos ) ); 843cdf0e10cSrcweir const ::Size aSz( ::basegfx::fround( aScale.getX() * aBmpSize.Width() ), 844cdf0e10cSrcweir ::basegfx::fround( aScale.getY() * aBmpSize.Height() ) ); 845cdf0e10cSrcweir 846cdf0e10cSrcweir pGrfObj->Draw( &mpOutDev->getOutDev(), 847cdf0e10cSrcweir aPt, 848cdf0e10cSrcweir aSz, 849cdf0e10cSrcweir &aGrfAttr ); 850cdf0e10cSrcweir 851cdf0e10cSrcweir if( mp2ndOutDev ) 852cdf0e10cSrcweir pGrfObj->Draw( &mp2ndOutDev->getOutDev(), 853cdf0e10cSrcweir aPt, 854cdf0e10cSrcweir aSz, 855cdf0e10cSrcweir &aGrfAttr ); 856cdf0e10cSrcweir 857cdf0e10cSrcweir // created GraphicObject, which possibly cached 858cdf0e10cSrcweir // display bitmap - return cache object, to retain 859cdf0e10cSrcweir // that information. 860cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >( 861cdf0e10cSrcweir new CachedBitmap( pGrfObj, 862cdf0e10cSrcweir aPt, 863cdf0e10cSrcweir aSz, 864cdf0e10cSrcweir aGrfAttr, 865cdf0e10cSrcweir viewState, 866cdf0e10cSrcweir renderState, 867cdf0e10cSrcweir // cast away const, need to 868cdf0e10cSrcweir // change refcount (as this is 869cdf0e10cSrcweir // ~invisible to client code, 870cdf0e10cSrcweir // still logically const) 871cdf0e10cSrcweir const_cast< rendering::XCanvas* >(pCanvas)) ); 872cdf0e10cSrcweir } 873cdf0e10cSrcweir } 874cdf0e10cSrcweir 875cdf0e10cSrcweir // Nothing rendered 876cdf0e10cSrcweir return uno::Reference< rendering::XCachedPrimitive >(NULL); 877cdf0e10cSrcweir } 878cdf0e10cSrcweir drawBitmap(const rendering::XCanvas * pCanvas,const uno::Reference<rendering::XBitmap> & xBitmap,const rendering::ViewState & viewState,const rendering::RenderState & renderState)879cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmap( const rendering::XCanvas* pCanvas, 880cdf0e10cSrcweir const uno::Reference< rendering::XBitmap >& xBitmap, 881cdf0e10cSrcweir const rendering::ViewState& viewState, 882cdf0e10cSrcweir const rendering::RenderState& renderState ) 883cdf0e10cSrcweir { 884cdf0e10cSrcweir return implDrawBitmap( pCanvas, 885cdf0e10cSrcweir xBitmap, 886cdf0e10cSrcweir viewState, 887cdf0e10cSrcweir renderState, 888cdf0e10cSrcweir false ); 889cdf0e10cSrcweir } 890cdf0e10cSrcweir drawBitmapModulated(const rendering::XCanvas * pCanvas,const uno::Reference<rendering::XBitmap> & xBitmap,const rendering::ViewState & viewState,const rendering::RenderState & renderState)891cdf0e10cSrcweir uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* pCanvas, 892cdf0e10cSrcweir const uno::Reference< rendering::XBitmap >& xBitmap, 893cdf0e10cSrcweir const rendering::ViewState& viewState, 894cdf0e10cSrcweir const rendering::RenderState& renderState ) 895cdf0e10cSrcweir { 896cdf0e10cSrcweir return implDrawBitmap( pCanvas, 897cdf0e10cSrcweir xBitmap, 898cdf0e10cSrcweir viewState, 899cdf0e10cSrcweir renderState, 900cdf0e10cSrcweir true ); 901cdf0e10cSrcweir } 902cdf0e10cSrcweir getDevice()903cdf0e10cSrcweir uno::Reference< rendering::XGraphicDevice > CanvasHelper::getDevice() 904cdf0e10cSrcweir { 905cdf0e10cSrcweir // cast away const, need to change refcount (as this is 906cdf0e10cSrcweir // ~invisible to client code, still logically const) 907cdf0e10cSrcweir return uno::Reference< rendering::XGraphicDevice >(mpDevice); 908cdf0e10cSrcweir } 909cdf0e10cSrcweir copyRect(const rendering::XCanvas *,const uno::Reference<rendering::XBitmapCanvas> &,const geometry::RealRectangle2D &,const rendering::ViewState &,const rendering::RenderState &,const geometry::RealRectangle2D &,const rendering::ViewState &,const rendering::RenderState &)910cdf0e10cSrcweir void CanvasHelper::copyRect( const rendering::XCanvas* , 911cdf0e10cSrcweir const uno::Reference< rendering::XBitmapCanvas >& , 912cdf0e10cSrcweir const geometry::RealRectangle2D& , 913cdf0e10cSrcweir const rendering::ViewState& , 914cdf0e10cSrcweir const rendering::RenderState& , 915cdf0e10cSrcweir const geometry::RealRectangle2D& , 916cdf0e10cSrcweir const rendering::ViewState& , 917cdf0e10cSrcweir const rendering::RenderState& ) 918cdf0e10cSrcweir { 919cdf0e10cSrcweir // TODO(F1) 920cdf0e10cSrcweir } 921cdf0e10cSrcweir getSize()922cdf0e10cSrcweir geometry::IntegerSize2D CanvasHelper::getSize() 923cdf0e10cSrcweir { 924cdf0e10cSrcweir if( !mpOutDev.get() ) 925cdf0e10cSrcweir return geometry::IntegerSize2D(); // we're disposed 926cdf0e10cSrcweir 927cdf0e10cSrcweir return ::vcl::unotools::integerSize2DFromSize( mpOutDev->getOutDev().GetOutputSizePixel() ); 928cdf0e10cSrcweir } 929cdf0e10cSrcweir getScaledBitmap(const geometry::RealSize2D & newSize,sal_Bool beFast)930cdf0e10cSrcweir uno::Reference< rendering::XBitmap > CanvasHelper::getScaledBitmap( const geometry::RealSize2D& newSize, 931cdf0e10cSrcweir sal_Bool beFast ) 932cdf0e10cSrcweir { 933cdf0e10cSrcweir if( !mpOutDev.get() || !mpDevice ) 934cdf0e10cSrcweir return uno::Reference< rendering::XBitmap >(); // we're disposed 935cdf0e10cSrcweir 936cdf0e10cSrcweir OutputDevice& rOutDev( mpOutDev->getOutDev() ); 937cdf0e10cSrcweir 938cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 939cdf0e10cSrcweir rOutDev.EnableMapMode( sal_False ); 940*5f27b83cSArmin Le Grand rOutDev.SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW ); 941cdf0e10cSrcweir 942cdf0e10cSrcweir // TODO(F2): Support alpha vdev canvas here 943cdf0e10cSrcweir const Point aEmptyPoint(0,0); 944cdf0e10cSrcweir const Size aBmpSize( rOutDev.GetOutputSizePixel() ); 945cdf0e10cSrcweir 946cdf0e10cSrcweir Bitmap aBitmap( rOutDev.GetBitmap(aEmptyPoint, aBmpSize) ); 947cdf0e10cSrcweir 948cdf0e10cSrcweir aBitmap.Scale( ::vcl::unotools::sizeFromRealSize2D(newSize), 94937ab0f2dSArmin Le Grand beFast ? BMP_SCALE_FASTESTINTERPOLATE : BMP_SCALE_INTERPOLATE ); 950cdf0e10cSrcweir 951cdf0e10cSrcweir return uno::Reference< rendering::XBitmap >( 952cdf0e10cSrcweir new CanvasBitmap( aBitmap, *mpDevice, mpOutDev ) ); 953cdf0e10cSrcweir } 954cdf0e10cSrcweir getData(rendering::IntegerBitmapLayout & rLayout,const geometry::IntegerRectangle2D & rect)955cdf0e10cSrcweir uno::Sequence< sal_Int8 > CanvasHelper::getData( rendering::IntegerBitmapLayout& rLayout, 956cdf0e10cSrcweir const geometry::IntegerRectangle2D& rect ) 957cdf0e10cSrcweir { 958cdf0e10cSrcweir if( !mpOutDev.get() ) 959cdf0e10cSrcweir return uno::Sequence< sal_Int8 >(); // we're disposed 960cdf0e10cSrcweir 961cdf0e10cSrcweir rLayout = getMemoryLayout(); 962cdf0e10cSrcweir 963cdf0e10cSrcweir // TODO(F2): Support alpha canvas here 964cdf0e10cSrcweir const Rectangle aRect( ::vcl::unotools::rectangleFromIntegerRectangle2D(rect) ); 965cdf0e10cSrcweir 966cdf0e10cSrcweir OutputDevice& rOutDev( mpOutDev->getOutDev() ); 967cdf0e10cSrcweir 968cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 969cdf0e10cSrcweir rOutDev.EnableMapMode( sal_False ); 970*5f27b83cSArmin Le Grand rOutDev.SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW ); 971cdf0e10cSrcweir 972cdf0e10cSrcweir Bitmap aBitmap( rOutDev.GetBitmap(aRect.TopLeft(), 973cdf0e10cSrcweir aRect.GetSize()) ); 974cdf0e10cSrcweir 975cdf0e10cSrcweir ScopedBitmapReadAccess pReadAccess( aBitmap.AcquireReadAccess(), 976cdf0e10cSrcweir aBitmap ); 977cdf0e10cSrcweir 978cdf0e10cSrcweir ENSURE_OR_THROW( pReadAccess.get() != NULL, 979cdf0e10cSrcweir "Could not acquire read access to OutDev bitmap" ); 980cdf0e10cSrcweir 981cdf0e10cSrcweir const sal_Int32 nWidth( rect.X2 - rect.X1 ); 982cdf0e10cSrcweir const sal_Int32 nHeight( rect.Y2 - rect.Y1 ); 983cdf0e10cSrcweir 984cdf0e10cSrcweir rLayout.ScanLines = nHeight; 985cdf0e10cSrcweir rLayout.ScanLineBytes = nWidth*4; 986cdf0e10cSrcweir rLayout.ScanLineStride = rLayout.ScanLineBytes; 987cdf0e10cSrcweir 988cdf0e10cSrcweir uno::Sequence< sal_Int8 > aRes( 4*nWidth*nHeight ); 989cdf0e10cSrcweir sal_Int8* pRes = aRes.getArray(); 990cdf0e10cSrcweir 991cdf0e10cSrcweir int nCurrPos(0); 992cdf0e10cSrcweir for( int y=0; y<nHeight; ++y ) 993cdf0e10cSrcweir { 994cdf0e10cSrcweir for( int x=0; x<nWidth; ++x ) 995cdf0e10cSrcweir { 996cdf0e10cSrcweir pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetRed(); 997cdf0e10cSrcweir pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetGreen(); 998cdf0e10cSrcweir pRes[ nCurrPos++ ] = pReadAccess->GetColor( y, x ).GetBlue(); 999cdf0e10cSrcweir pRes[ nCurrPos++ ] = -1; 1000cdf0e10cSrcweir } 1001cdf0e10cSrcweir } 1002cdf0e10cSrcweir 1003cdf0e10cSrcweir return aRes; 1004cdf0e10cSrcweir } 1005cdf0e10cSrcweir setData(const uno::Sequence<sal_Int8> & data,const rendering::IntegerBitmapLayout & aLayout,const geometry::IntegerRectangle2D & rect)1006cdf0e10cSrcweir void CanvasHelper::setData( const uno::Sequence< sal_Int8 >& data, 1007cdf0e10cSrcweir const rendering::IntegerBitmapLayout& aLayout, 1008cdf0e10cSrcweir const geometry::IntegerRectangle2D& rect ) 1009cdf0e10cSrcweir { 1010cdf0e10cSrcweir if( !mpOutDev.get() ) 1011cdf0e10cSrcweir return; // we're disposed 1012cdf0e10cSrcweir 1013cdf0e10cSrcweir const rendering::IntegerBitmapLayout aRefLayout( getMemoryLayout() ); 1014cdf0e10cSrcweir ENSURE_ARG_OR_THROW( aRefLayout.PlaneStride != aLayout.PlaneStride || 1015cdf0e10cSrcweir aRefLayout.ColorSpace != aLayout.ColorSpace || 1016cdf0e10cSrcweir aRefLayout.Palette != aLayout.Palette || 1017cdf0e10cSrcweir aRefLayout.IsMsbFirst != aLayout.IsMsbFirst, 1018cdf0e10cSrcweir "Mismatching memory layout" ); 1019cdf0e10cSrcweir 1020cdf0e10cSrcweir OutputDevice& rOutDev( mpOutDev->getOutDev() ); 1021cdf0e10cSrcweir 1022cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 1023cdf0e10cSrcweir rOutDev.EnableMapMode( sal_False ); 1024*5f27b83cSArmin Le Grand rOutDev.SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW ); 1025cdf0e10cSrcweir 1026cdf0e10cSrcweir const Rectangle aRect( ::vcl::unotools::rectangleFromIntegerRectangle2D(rect) ); 1027cdf0e10cSrcweir const sal_uInt16 nBitCount( ::std::min( (sal_uInt16)24U, 1028cdf0e10cSrcweir (sal_uInt16)rOutDev.GetBitCount() ) ); 1029cdf0e10cSrcweir const BitmapPalette* pPalette = NULL; 1030cdf0e10cSrcweir 1031cdf0e10cSrcweir if( nBitCount <= 8 ) 1032cdf0e10cSrcweir { 1033cdf0e10cSrcweir // TODO(Q1): Extract this to a common place, e.g. GraphicDevice 1034cdf0e10cSrcweir 1035cdf0e10cSrcweir // try to determine palette from output device (by 1036cdf0e10cSrcweir // extracting a 1,1 bitmap, and querying it) 1037cdf0e10cSrcweir const Point aEmptyPoint; 1038cdf0e10cSrcweir const Size aSize(1,1); 1039cdf0e10cSrcweir Bitmap aTmpBitmap( rOutDev.GetBitmap( aEmptyPoint, 1040cdf0e10cSrcweir aSize ) ); 1041cdf0e10cSrcweir 1042cdf0e10cSrcweir ScopedBitmapReadAccess pReadAccess( aTmpBitmap.AcquireReadAccess(), 1043cdf0e10cSrcweir aTmpBitmap ); 1044cdf0e10cSrcweir 1045cdf0e10cSrcweir pPalette = &pReadAccess->GetPalette(); 1046cdf0e10cSrcweir } 1047cdf0e10cSrcweir 1048cdf0e10cSrcweir // TODO(F2): Support alpha canvas here 1049cdf0e10cSrcweir Bitmap aBitmap( aRect.GetSize(), nBitCount, pPalette ); 1050cdf0e10cSrcweir 1051cdf0e10cSrcweir bool bCopyBack( false ); // only copy something back, if we 1052cdf0e10cSrcweir // actually changed some pixel 1053cdf0e10cSrcweir { 1054cdf0e10cSrcweir ScopedBitmapWriteAccess pWriteAccess( aBitmap.AcquireWriteAccess(), 1055cdf0e10cSrcweir aBitmap ); 1056cdf0e10cSrcweir 1057cdf0e10cSrcweir ENSURE_OR_THROW( pWriteAccess.get() != NULL, 1058cdf0e10cSrcweir "Could not acquire write access to OutDev bitmap" ); 1059cdf0e10cSrcweir 1060cdf0e10cSrcweir // for the time being, always read as RGB 1061cdf0e10cSrcweir const sal_Int32 nWidth( rect.X2 - rect.X1 ); 1062cdf0e10cSrcweir const sal_Int32 nHeight( rect.Y2 - rect.Y1 ); 1063cdf0e10cSrcweir int x, y, nCurrPos(0); 1064cdf0e10cSrcweir for( y=0; y<nHeight; ++y ) 1065cdf0e10cSrcweir { 1066cdf0e10cSrcweir switch( pWriteAccess->GetScanlineFormat() ) 1067cdf0e10cSrcweir { 1068cdf0e10cSrcweir case BMP_FORMAT_8BIT_PAL: 1069cdf0e10cSrcweir { 1070cdf0e10cSrcweir Scanline pScan = pWriteAccess->GetScanline( y ); 1071cdf0e10cSrcweir 1072cdf0e10cSrcweir for( x=0; x<nWidth; ++x ) 1073cdf0e10cSrcweir { 1074cdf0e10cSrcweir *pScan++ = (sal_uInt8)pWriteAccess->GetBestPaletteIndex( 1075cdf0e10cSrcweir BitmapColor( data[ nCurrPos ], 1076cdf0e10cSrcweir data[ nCurrPos+1 ], 1077cdf0e10cSrcweir data[ nCurrPos+2 ] ) ); 1078cdf0e10cSrcweir 1079cdf0e10cSrcweir nCurrPos += 4; 1080cdf0e10cSrcweir } 1081cdf0e10cSrcweir } 1082cdf0e10cSrcweir break; 1083cdf0e10cSrcweir 1084cdf0e10cSrcweir case BMP_FORMAT_24BIT_TC_BGR: 1085cdf0e10cSrcweir { 1086cdf0e10cSrcweir Scanline pScan = pWriteAccess->GetScanline( y ); 1087cdf0e10cSrcweir 1088cdf0e10cSrcweir for( x=0; x<nWidth; ++x ) 1089cdf0e10cSrcweir { 1090cdf0e10cSrcweir *pScan++ = data[ nCurrPos+2 ]; 1091cdf0e10cSrcweir *pScan++ = data[ nCurrPos+1 ]; 1092cdf0e10cSrcweir *pScan++ = data[ nCurrPos ]; 1093cdf0e10cSrcweir 1094cdf0e10cSrcweir nCurrPos += 4; 1095cdf0e10cSrcweir } 1096cdf0e10cSrcweir } 1097cdf0e10cSrcweir break; 1098cdf0e10cSrcweir 1099cdf0e10cSrcweir case BMP_FORMAT_24BIT_TC_RGB: 1100cdf0e10cSrcweir { 1101cdf0e10cSrcweir Scanline pScan = pWriteAccess->GetScanline( y ); 1102cdf0e10cSrcweir 1103cdf0e10cSrcweir for( x=0; x<nWidth; ++x ) 1104cdf0e10cSrcweir { 1105cdf0e10cSrcweir *pScan++ = data[ nCurrPos ]; 1106cdf0e10cSrcweir *pScan++ = data[ nCurrPos+1 ]; 1107cdf0e10cSrcweir *pScan++ = data[ nCurrPos+2 ]; 1108cdf0e10cSrcweir 1109cdf0e10cSrcweir nCurrPos += 4; 1110cdf0e10cSrcweir } 1111cdf0e10cSrcweir } 1112cdf0e10cSrcweir break; 1113cdf0e10cSrcweir 1114cdf0e10cSrcweir default: 1115cdf0e10cSrcweir { 1116cdf0e10cSrcweir for( x=0; x<nWidth; ++x ) 1117cdf0e10cSrcweir { 1118cdf0e10cSrcweir pWriteAccess->SetPixel( y, x, BitmapColor( data[ nCurrPos ], 1119cdf0e10cSrcweir data[ nCurrPos+1 ], 1120cdf0e10cSrcweir data[ nCurrPos+2 ] ) ); 1121cdf0e10cSrcweir nCurrPos += 4; 1122cdf0e10cSrcweir } 1123cdf0e10cSrcweir } 1124cdf0e10cSrcweir break; 1125cdf0e10cSrcweir } 1126cdf0e10cSrcweir } 1127cdf0e10cSrcweir 1128cdf0e10cSrcweir bCopyBack = true; 1129cdf0e10cSrcweir } 1130cdf0e10cSrcweir 1131cdf0e10cSrcweir // copy back only here, since the BitmapAccessors must be 1132cdf0e10cSrcweir // destroyed beforehand 1133cdf0e10cSrcweir if( bCopyBack ) 1134cdf0e10cSrcweir { 1135cdf0e10cSrcweir // TODO(F2): Support alpha canvas here 1136cdf0e10cSrcweir rOutDev.DrawBitmap(aRect.TopLeft(), aBitmap); 1137cdf0e10cSrcweir } 1138cdf0e10cSrcweir } 1139cdf0e10cSrcweir setPixel(const uno::Sequence<sal_Int8> & color,const rendering::IntegerBitmapLayout & rLayout,const geometry::IntegerPoint2D & pos)1140cdf0e10cSrcweir void CanvasHelper::setPixel( const uno::Sequence< sal_Int8 >& color, 1141cdf0e10cSrcweir const rendering::IntegerBitmapLayout& rLayout, 1142cdf0e10cSrcweir const geometry::IntegerPoint2D& pos ) 1143cdf0e10cSrcweir { 1144cdf0e10cSrcweir if( !mpOutDev.get() ) 1145cdf0e10cSrcweir return; // we're disposed 1146cdf0e10cSrcweir 1147cdf0e10cSrcweir OutputDevice& rOutDev( mpOutDev->getOutDev() ); 1148cdf0e10cSrcweir 1149cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 1150cdf0e10cSrcweir rOutDev.EnableMapMode( sal_False ); 1151*5f27b83cSArmin Le Grand rOutDev.SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW ); 1152cdf0e10cSrcweir 1153cdf0e10cSrcweir const Size aBmpSize( rOutDev.GetOutputSizePixel() ); 1154cdf0e10cSrcweir 1155cdf0e10cSrcweir ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aBmpSize.Width(), 1156cdf0e10cSrcweir "X coordinate out of bounds" ); 1157cdf0e10cSrcweir ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aBmpSize.Height(), 1158cdf0e10cSrcweir "Y coordinate out of bounds" ); 1159cdf0e10cSrcweir ENSURE_ARG_OR_THROW( color.getLength() > 3, 1160cdf0e10cSrcweir "not enough color components" ); 1161cdf0e10cSrcweir 1162cdf0e10cSrcweir const rendering::IntegerBitmapLayout aRefLayout( getMemoryLayout() ); 1163cdf0e10cSrcweir ENSURE_ARG_OR_THROW( aRefLayout.PlaneStride != rLayout.PlaneStride || 1164cdf0e10cSrcweir aRefLayout.ColorSpace != rLayout.ColorSpace || 1165cdf0e10cSrcweir aRefLayout.Palette != rLayout.Palette || 1166cdf0e10cSrcweir aRefLayout.IsMsbFirst != rLayout.IsMsbFirst, 1167cdf0e10cSrcweir "Mismatching memory layout" ); 1168cdf0e10cSrcweir 1169cdf0e10cSrcweir // TODO(F2): Support alpha canvas here 1170cdf0e10cSrcweir rOutDev.DrawPixel( ::vcl::unotools::pointFromIntegerPoint2D( pos ), 1171cdf0e10cSrcweir ::canvas::tools::stdIntSequenceToColor( color )); 1172cdf0e10cSrcweir } 1173cdf0e10cSrcweir getPixel(rendering::IntegerBitmapLayout & rLayout,const geometry::IntegerPoint2D & pos)1174cdf0e10cSrcweir uno::Sequence< sal_Int8 > CanvasHelper::getPixel( rendering::IntegerBitmapLayout& rLayout, 1175cdf0e10cSrcweir const geometry::IntegerPoint2D& pos ) 1176cdf0e10cSrcweir { 1177cdf0e10cSrcweir if( !mpOutDev.get() ) 1178cdf0e10cSrcweir return uno::Sequence< sal_Int8 >(); // we're disposed 1179cdf0e10cSrcweir 1180cdf0e10cSrcweir rLayout = getMemoryLayout(); 1181cdf0e10cSrcweir rLayout.ScanLines = 1; 1182cdf0e10cSrcweir rLayout.ScanLineBytes = 4; 1183cdf0e10cSrcweir rLayout.ScanLineStride = rLayout.ScanLineBytes; 1184cdf0e10cSrcweir 1185cdf0e10cSrcweir OutputDevice& rOutDev( mpOutDev->getOutDev() ); 1186cdf0e10cSrcweir 1187cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 1188cdf0e10cSrcweir rOutDev.EnableMapMode( sal_False ); 1189*5f27b83cSArmin Le Grand rOutDev.SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW ); 1190cdf0e10cSrcweir 1191cdf0e10cSrcweir const Size aBmpSize( rOutDev.GetOutputSizePixel() ); 1192cdf0e10cSrcweir 1193cdf0e10cSrcweir ENSURE_ARG_OR_THROW( pos.X >= 0 && pos.X < aBmpSize.Width(), 1194cdf0e10cSrcweir "X coordinate out of bounds" ); 1195cdf0e10cSrcweir ENSURE_ARG_OR_THROW( pos.Y >= 0 && pos.Y < aBmpSize.Height(), 1196cdf0e10cSrcweir "Y coordinate out of bounds" ); 1197cdf0e10cSrcweir 1198cdf0e10cSrcweir // TODO(F2): Support alpha canvas here 1199cdf0e10cSrcweir return ::canvas::tools::colorToStdIntSequence( 1200cdf0e10cSrcweir rOutDev.GetPixel( 1201cdf0e10cSrcweir ::vcl::unotools::pointFromIntegerPoint2D( pos ))); 1202cdf0e10cSrcweir } 1203cdf0e10cSrcweir getMemoryLayout()1204cdf0e10cSrcweir rendering::IntegerBitmapLayout CanvasHelper::getMemoryLayout() 1205cdf0e10cSrcweir { 1206cdf0e10cSrcweir if( !mpOutDev.get() ) 1207cdf0e10cSrcweir return rendering::IntegerBitmapLayout(); // we're disposed 1208cdf0e10cSrcweir 1209cdf0e10cSrcweir return ::canvas::tools::getStdMemoryLayout(getSize()); 1210cdf0e10cSrcweir } 1211cdf0e10cSrcweir setupOutDevState(const rendering::ViewState & viewState,const rendering::RenderState & renderState,ColorType eColorType) const1212cdf0e10cSrcweir int CanvasHelper::setupOutDevState( const rendering::ViewState& viewState, 1213cdf0e10cSrcweir const rendering::RenderState& renderState, 1214cdf0e10cSrcweir ColorType eColorType ) const 1215cdf0e10cSrcweir { 1216cdf0e10cSrcweir ENSURE_OR_THROW( mpOutDev.get(), 1217cdf0e10cSrcweir "outdev null. Are we disposed?" ); 1218cdf0e10cSrcweir 1219cdf0e10cSrcweir ::canvas::tools::verifyInput( renderState, 1220cdf0e10cSrcweir BOOST_CURRENT_FUNCTION, 1221cdf0e10cSrcweir mpDevice, 1222cdf0e10cSrcweir 2, 1223cdf0e10cSrcweir eColorType == IGNORE_COLOR ? 0 : 3 ); 1224cdf0e10cSrcweir 1225cdf0e10cSrcweir OutputDevice& rOutDev( mpOutDev->getOutDev() ); 1226cdf0e10cSrcweir OutputDevice* p2ndOutDev = NULL; 1227cdf0e10cSrcweir 1228cdf0e10cSrcweir rOutDev.EnableMapMode( sal_False ); 1229*5f27b83cSArmin Le Grand rOutDev.SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW ); 1230cdf0e10cSrcweir 1231cdf0e10cSrcweir if( mp2ndOutDev ) 1232cdf0e10cSrcweir p2ndOutDev = &mp2ndOutDev->getOutDev(); 1233cdf0e10cSrcweir 1234cdf0e10cSrcweir int nTransparency(0); 1235cdf0e10cSrcweir 1236cdf0e10cSrcweir // TODO(P2): Don't change clipping all the time, maintain current clip 1237cdf0e10cSrcweir // state and change only when update is necessary 1238cdf0e10cSrcweir 1239cdf0e10cSrcweir // accumulate non-empty clips into one region 1240cdf0e10cSrcweir // ========================================== 1241cdf0e10cSrcweir 1242e6f63103SArmin Le Grand Region aClipRegion(true); 1243cdf0e10cSrcweir 1244cdf0e10cSrcweir if( viewState.Clip.is() ) 1245cdf0e10cSrcweir { 1246cdf0e10cSrcweir ::basegfx::B2DPolyPolygon aClipPoly( 1247cdf0e10cSrcweir ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(viewState.Clip) ); 1248cdf0e10cSrcweir 1249cdf0e10cSrcweir if( aClipPoly.count() ) 1250cdf0e10cSrcweir { 1251cdf0e10cSrcweir // setup non-empty clipping 1252cdf0e10cSrcweir ::basegfx::B2DHomMatrix aMatrix; 1253cdf0e10cSrcweir aClipPoly.transform( 1254cdf0e10cSrcweir ::basegfx::unotools::homMatrixFromAffineMatrix( aMatrix, 1255cdf0e10cSrcweir viewState.AffineTransform ) ); 1256cdf0e10cSrcweir 1257cdf0e10cSrcweir aClipRegion = Region::GetRegionFromPolyPolygon( ::PolyPolygon( aClipPoly ) ); 1258cdf0e10cSrcweir } 1259cdf0e10cSrcweir else 1260cdf0e10cSrcweir { 1261cdf0e10cSrcweir // clip polygon is empty 1262cdf0e10cSrcweir aClipRegion.SetEmpty(); 1263cdf0e10cSrcweir } 1264cdf0e10cSrcweir } 1265cdf0e10cSrcweir 1266cdf0e10cSrcweir if( renderState.Clip.is() ) 1267cdf0e10cSrcweir { 1268cdf0e10cSrcweir ::basegfx::B2DPolyPolygon aClipPoly( 1269cdf0e10cSrcweir ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(renderState.Clip) ); 1270cdf0e10cSrcweir 1271cdf0e10cSrcweir ::basegfx::B2DHomMatrix aMatrix; 1272cdf0e10cSrcweir aClipPoly.transform( 1273cdf0e10cSrcweir ::canvas::tools::mergeViewAndRenderTransform( aMatrix, 1274cdf0e10cSrcweir viewState, 1275cdf0e10cSrcweir renderState ) ); 1276cdf0e10cSrcweir 1277cdf0e10cSrcweir if( aClipPoly.count() ) 1278cdf0e10cSrcweir { 1279cdf0e10cSrcweir // setup non-empty clipping 1280cdf0e10cSrcweir Region aRegion = Region::GetRegionFromPolyPolygon( ::PolyPolygon( aClipPoly ) ); 1281cdf0e10cSrcweir aClipRegion.Intersect( aRegion ); 1282cdf0e10cSrcweir } 1283cdf0e10cSrcweir else 1284cdf0e10cSrcweir { 1285cdf0e10cSrcweir // clip polygon is empty 1286cdf0e10cSrcweir aClipRegion.SetEmpty(); 1287cdf0e10cSrcweir } 1288cdf0e10cSrcweir } 1289cdf0e10cSrcweir 1290cdf0e10cSrcweir // setup accumulated clip region. Note that setting an 1291cdf0e10cSrcweir // empty clip region denotes "clip everything" on the 1292cdf0e10cSrcweir // OutputDevice (which is why we translate that into 1293cdf0e10cSrcweir // SetClipRegion() here). When both view and render clip 1294cdf0e10cSrcweir // are empty, aClipRegion remains default-constructed, 1295cdf0e10cSrcweir // i.e. empty, too. 1296cdf0e10cSrcweir if( aClipRegion.IsNull() ) 1297cdf0e10cSrcweir { 1298cdf0e10cSrcweir rOutDev.SetClipRegion(); 1299cdf0e10cSrcweir 1300cdf0e10cSrcweir if( p2ndOutDev ) 1301cdf0e10cSrcweir p2ndOutDev->SetClipRegion(); 1302cdf0e10cSrcweir } 1303cdf0e10cSrcweir else 1304cdf0e10cSrcweir { 1305cdf0e10cSrcweir rOutDev.SetClipRegion( aClipRegion ); 1306cdf0e10cSrcweir 1307cdf0e10cSrcweir if( p2ndOutDev ) 1308cdf0e10cSrcweir p2ndOutDev->SetClipRegion( aClipRegion ); 1309cdf0e10cSrcweir } 1310cdf0e10cSrcweir 1311cdf0e10cSrcweir if( eColorType != IGNORE_COLOR ) 1312cdf0e10cSrcweir { 1313cdf0e10cSrcweir Color aColor( COL_WHITE ); 1314cdf0e10cSrcweir 1315cdf0e10cSrcweir if( renderState.DeviceColor.getLength() > 2 ) 1316cdf0e10cSrcweir { 1317cdf0e10cSrcweir aColor = ::vcl::unotools::stdColorSpaceSequenceToColor( 1318cdf0e10cSrcweir renderState.DeviceColor ); 1319cdf0e10cSrcweir } 1320cdf0e10cSrcweir 1321cdf0e10cSrcweir // extract alpha, and make color opaque 1322cdf0e10cSrcweir // afterwards. Otherwise, OutputDevice won't draw anything 1323cdf0e10cSrcweir nTransparency = aColor.GetTransparency(); 1324cdf0e10cSrcweir aColor.SetTransparency(0); 1325cdf0e10cSrcweir 1326cdf0e10cSrcweir switch( eColorType ) 1327cdf0e10cSrcweir { 1328cdf0e10cSrcweir case LINE_COLOR: 1329cdf0e10cSrcweir rOutDev.SetLineColor( aColor ); 1330cdf0e10cSrcweir rOutDev.SetFillColor(); 1331cdf0e10cSrcweir 1332cdf0e10cSrcweir if( p2ndOutDev ) 1333cdf0e10cSrcweir { 1334cdf0e10cSrcweir p2ndOutDev->SetLineColor( aColor ); 1335cdf0e10cSrcweir p2ndOutDev->SetFillColor(); 1336cdf0e10cSrcweir } 1337cdf0e10cSrcweir break; 1338cdf0e10cSrcweir 1339cdf0e10cSrcweir case FILL_COLOR: 1340cdf0e10cSrcweir rOutDev.SetFillColor( aColor ); 1341cdf0e10cSrcweir rOutDev.SetLineColor(); 1342cdf0e10cSrcweir 1343cdf0e10cSrcweir if( p2ndOutDev ) 1344cdf0e10cSrcweir { 1345cdf0e10cSrcweir p2ndOutDev->SetFillColor( aColor ); 1346cdf0e10cSrcweir p2ndOutDev->SetLineColor(); 1347cdf0e10cSrcweir } 1348cdf0e10cSrcweir break; 1349cdf0e10cSrcweir 1350cdf0e10cSrcweir case TEXT_COLOR: 1351cdf0e10cSrcweir rOutDev.SetTextColor( aColor ); 1352cdf0e10cSrcweir 1353cdf0e10cSrcweir if( p2ndOutDev ) 1354cdf0e10cSrcweir p2ndOutDev->SetTextColor( aColor ); 1355cdf0e10cSrcweir break; 1356cdf0e10cSrcweir 1357cdf0e10cSrcweir default: 1358cdf0e10cSrcweir ENSURE_OR_THROW( false, 1359cdf0e10cSrcweir "Unexpected color type"); 1360cdf0e10cSrcweir break; 1361cdf0e10cSrcweir } 1362cdf0e10cSrcweir } 1363cdf0e10cSrcweir 1364cdf0e10cSrcweir return nTransparency; 1365cdf0e10cSrcweir } 1366cdf0e10cSrcweir setupTextOutput(::Point & o_rOutPos,const rendering::ViewState & viewState,const rendering::RenderState & renderState,const uno::Reference<rendering::XCanvasFont> & xFont) const1367cdf0e10cSrcweir bool CanvasHelper::setupTextOutput( ::Point& o_rOutPos, 1368cdf0e10cSrcweir const rendering::ViewState& viewState, 1369cdf0e10cSrcweir const rendering::RenderState& renderState, 1370cdf0e10cSrcweir const uno::Reference< rendering::XCanvasFont >& xFont ) const 1371cdf0e10cSrcweir { 1372cdf0e10cSrcweir ENSURE_OR_THROW( mpOutDev.get(), 1373cdf0e10cSrcweir "outdev null. Are we disposed?" ); 1374cdf0e10cSrcweir 1375cdf0e10cSrcweir setupOutDevState( viewState, renderState, TEXT_COLOR ); 1376cdf0e10cSrcweir 1377cdf0e10cSrcweir OutputDevice& rOutDev( mpOutDev->getOutDev() ); 1378cdf0e10cSrcweir 1379cdf0e10cSrcweir ::Font aVCLFont; 1380cdf0e10cSrcweir 1381cdf0e10cSrcweir CanvasFont* pFont = dynamic_cast< CanvasFont* >( xFont.get() ); 1382cdf0e10cSrcweir 1383cdf0e10cSrcweir ENSURE_ARG_OR_THROW( pFont, 1384cdf0e10cSrcweir "Font not compatible with this canvas" ); 1385cdf0e10cSrcweir 1386cdf0e10cSrcweir aVCLFont = pFont->getVCLFont(); 1387cdf0e10cSrcweir 1388cdf0e10cSrcweir Color aColor( COL_BLACK ); 1389cdf0e10cSrcweir 1390cdf0e10cSrcweir if( renderState.DeviceColor.getLength() > 2 ) 1391cdf0e10cSrcweir { 1392cdf0e10cSrcweir aColor = ::vcl::unotools::stdColorSpaceSequenceToColor( 1393cdf0e10cSrcweir renderState.DeviceColor ); 1394cdf0e10cSrcweir } 1395cdf0e10cSrcweir 1396cdf0e10cSrcweir // setup font color 1397cdf0e10cSrcweir aVCLFont.SetColor( aColor ); 1398cdf0e10cSrcweir aVCLFont.SetFillColor( aColor ); 1399cdf0e10cSrcweir 1400cdf0e10cSrcweir // no need to replicate this for mp2ndOutDev, we're modifying only aVCLFont here. 1401cdf0e10cSrcweir if( !tools::setupFontTransform( o_rOutPos, aVCLFont, viewState, renderState, rOutDev ) ) 1402cdf0e10cSrcweir return false; 1403cdf0e10cSrcweir 1404cdf0e10cSrcweir rOutDev.SetFont( aVCLFont ); 1405cdf0e10cSrcweir 1406cdf0e10cSrcweir if( mp2ndOutDev ) 1407cdf0e10cSrcweir mp2ndOutDev->getOutDev().SetFont( aVCLFont ); 1408cdf0e10cSrcweir 1409cdf0e10cSrcweir return true; 1410cdf0e10cSrcweir } 1411cdf0e10cSrcweir repaint(const GraphicObjectSharedPtr & rGrf,const rendering::ViewState & viewState,const rendering::RenderState & renderState,const::Point & rPt,const::Size & rSz,const GraphicAttr & rAttr) const1412cdf0e10cSrcweir bool CanvasHelper::repaint( const GraphicObjectSharedPtr& rGrf, 1413cdf0e10cSrcweir const rendering::ViewState& viewState, 1414cdf0e10cSrcweir const rendering::RenderState& renderState, 1415cdf0e10cSrcweir const ::Point& rPt, 1416cdf0e10cSrcweir const ::Size& rSz, 1417cdf0e10cSrcweir const GraphicAttr& rAttr ) const 1418cdf0e10cSrcweir { 1419cdf0e10cSrcweir ENSURE_OR_RETURN_FALSE( rGrf, 1420cdf0e10cSrcweir "Invalid Graphic" ); 1421cdf0e10cSrcweir 1422cdf0e10cSrcweir if( !mpOutDev ) 1423cdf0e10cSrcweir return false; // disposed 1424cdf0e10cSrcweir else 1425cdf0e10cSrcweir { 1426cdf0e10cSrcweir tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDev ); 1427cdf0e10cSrcweir setupOutDevState( viewState, renderState, IGNORE_COLOR ); 1428cdf0e10cSrcweir 1429cdf0e10cSrcweir if( !rGrf->Draw( &mpOutDev->getOutDev(), rPt, rSz, &rAttr ) ) 1430cdf0e10cSrcweir return false; 1431cdf0e10cSrcweir 1432cdf0e10cSrcweir // #i80779# Redraw also into mask outdev 1433cdf0e10cSrcweir if( mp2ndOutDev ) 1434cdf0e10cSrcweir return rGrf->Draw( &mp2ndOutDev->getOutDev(), rPt, rSz, &rAttr ); 1435cdf0e10cSrcweir 1436cdf0e10cSrcweir return true; 1437cdf0e10cSrcweir } 1438cdf0e10cSrcweir } 1439cdf0e10cSrcweir flush() const1440cdf0e10cSrcweir void CanvasHelper::flush() const 1441cdf0e10cSrcweir { 1442cdf0e10cSrcweir if( mpOutDev && mpOutDev->getOutDev().GetOutDevType() == OUTDEV_WINDOW ) 1443cdf0e10cSrcweir { 1444cdf0e10cSrcweir // TODO(Q3): Evil downcast. And what's more, Window::Flush is 1445cdf0e10cSrcweir // not even const. Wah. 1446cdf0e10cSrcweir static_cast<Window&>(mpOutDev->getOutDev()).Flush(); 1447cdf0e10cSrcweir } 1448cdf0e10cSrcweir 1449cdf0e10cSrcweir if( mp2ndOutDev && mp2ndOutDev->getOutDev().GetOutDevType() == OUTDEV_WINDOW ) 1450cdf0e10cSrcweir { 1451cdf0e10cSrcweir // TODO(Q3): Evil downcast. And what's more, Window::Flush is 1452cdf0e10cSrcweir // not even const. Wah. 1453cdf0e10cSrcweir static_cast<Window&>(mp2ndOutDev->getOutDev()).Flush(); 1454cdf0e10cSrcweir } 1455cdf0e10cSrcweir } 1456cdf0e10cSrcweir 1457cdf0e10cSrcweir } 1458