1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "headless/svpgdi.hxx"
21 #include "headless/svpbmp.hxx"
23 #include <vcl/sysdata.hxx>
24 #include <basegfx/range/b2drange.hxx>
25 #include <basegfx/range/b2ibox.hxx>
26 #include <basegfx/polygon/b2dpolypolygon.hxx>
27 #include <basegfx/polygon/b2dpolygon.hxx>
28 #include <basegfx/polygon/b2dpolygontools.hxx>
29 #include <basebmp/scanlineformats.hxx>
31 #include <tools/debug.hxx>
33 #if OSL_DEBUG_LEVEL > 2
34 #include <basebmp/debug.hxx>
36 #include <rtl/strbuf.hxx>
43 inline void dbgOut( const basebmp::BitmapDeviceSharedPtr
&
44 #if OSL_DEBUG_LEVEL > 2
49 #if OSL_DEBUG_LEVEL > 2
50 static int dbgStreamNum
= 0;
51 OStringBuffer
aBuf( 256 );
52 aBuf
.append( "debug" );
53 mkdir( aBuf
.getStr(), 0777 );
55 aBuf
.append( sal_Int64(reinterpret_cast<sal_IntPtr
>(rDevice
.get())), 16 );
56 mkdir( aBuf
.getStr(), 0777 );
57 aBuf
.append( "/bmp" );
58 aBuf
.append( sal_Int32(dbgStreamNum
++) );
59 std::fstream
bmpstream( aBuf
.getStr(), std::ios::out
);
60 debugDump( rDevice
, bmpstream
);
64 // ===========================================================================
66 bool SvpSalGraphics::drawAlphaBitmap( const SalTwoRect
&, const SalBitmap
& /*rSourceBitmap*/, const SalBitmap
& /*rAlphaBitmap*/ )
68 // TODO(P3) implement alpha blending
72 bool SvpSalGraphics::drawAlphaRect( long /*nX*/, long /*nY*/, long /*nWidth*/, long /*nHeight*/, sal_uInt8
/*nTransparency*/ )
74 // TODO(P3) implement alpha blending
80 SvpSalGraphics::SvpSalGraphics() :
81 m_bUseLineColor( true ),
82 m_aLineColor( COL_BLACK
),
83 m_bUseFillColor( false ),
84 m_aFillColor( COL_WHITE
),
85 m_aDrawMode( basebmp::DrawMode_PAINT
),
86 m_aTextColor( COL_BLACK
),
87 m_eTextFmt( basebmp::Format::EIGHT_BIT_GREY
),
90 for( int i
= 0; i
< MAX_FALLBACK
; ++i
)
91 m_pServerFont
[i
] = NULL
;
94 SvpSalGraphics::~SvpSalGraphics()
100 void SvpSalGraphics::setDevice( basebmp::BitmapDeviceSharedPtr
& rDevice
)
102 m_aOrigDevice
= rDevice
;
106 // determine matching bitmap format for masks
107 sal_uInt32 nDeviceFmt
= m_aDevice
->getScanlineFormat();
108 DBG_ASSERT( (nDeviceFmt
<= (sal_uInt32
)basebmp::Format::MAX
), "SVP::setDevice() with invalid bitmap format" );
111 case basebmp::Format::EIGHT_BIT_GREY
:
112 case basebmp::Format::SIXTEEN_BIT_LSB_TC_MASK
:
113 case basebmp::Format::SIXTEEN_BIT_MSB_TC_MASK
:
114 case basebmp::Format::TWENTYFOUR_BIT_TC_MASK
:
115 case basebmp::Format::THIRTYTWO_BIT_TC_MASK_BGRA
:
116 case basebmp::Format::THIRTYTWO_BIT_TC_MASK_ARGB
:
117 case basebmp::Format::THIRTYTWO_BIT_TC_MASK_ABGR
:
118 case basebmp::Format::THIRTYTWO_BIT_TC_MASK_RGBA
:
119 m_eTextFmt
= basebmp::Format::EIGHT_BIT_GREY
;
122 m_eTextFmt
= basebmp::Format::ONE_BIT_LSB_GREY
;
128 void SvpSalGraphics::GetResolution( sal_Int32
& rDPIX
, sal_Int32
& rDPIY
)
133 sal_uInt16
SvpSalGraphics::GetBitCount() const
135 return SvpElement::getBitCountFromScanlineFormat( m_aDevice
->getScanlineFormat() );
138 long SvpSalGraphics::GetGraphicsWidth() const
140 if( m_aDevice
.get() )
142 basegfx::B2IVector aSize
= m_aOrigDevice
->getSize();
148 void SvpSalGraphics::ResetClipRegion()
150 m_aDevice
= m_aOrigDevice
;
153 m_aClipRegion
.SetNull();
157 // verify clip for the whole area is setup
158 void SvpSalGraphics::ensureClip()
163 m_aDevice
= m_aOrigDevice
;
164 basegfx::B2IVector aSize
= m_aDevice
->getSize();
165 m_aClipMap
= basebmp::createBitmapDevice( aSize
, false, basebmp::Format::ONE_BIT_MSB_GREY
);
166 m_aClipMap
->clear( basebmp::Color(0xFFFFFFFF) );
168 // fprintf( stderr, "non rect clip region set with %d rects:\n",
169 // (int)m_aClipRegion.GetRectCount() );
170 ImplRegionInfo aInfo
;
172 bool bRegionRect
= m_aClipRegion
.ImplGetFirstRect(aInfo
, nX
, nY
, nW
, nH
);
177 basegfx::B2DPolyPolygon aFull
;
178 aFull
.append( basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( nX
, nY
, nX
+nW
, nY
+nH
) ) );
179 m_aClipMap
->fillPolyPolygon( aFull
, basebmp::Color(0), basebmp::DrawMode_PAINT
);
181 // fprintf( stderr, "\t %ld,%ld %ldx%ld\n", nX, nY, nW, nH );
182 bRegionRect
= m_aClipRegion
.ImplGetNextRect( aInfo
, nX
, nY
, nW
, nH
);
187 SvpSalGraphics::ClipUndoHandle::~ClipUndoHandle()
189 if( m_aDevice
.get() )
190 m_rGfx
.m_aDevice
= m_aDevice
;
193 // setup a clip rectangle -only- iff we have to; if aRange
194 // is entirely contained inside an existing clip frame, we
195 // will avoid setting up the clip bitmap. Similarly if the
196 // range doesn't appear at all we return true to avoid
198 bool SvpSalGraphics::isClippedSetup( const basegfx::B2IBox
&aRange
, SvpSalGraphics::ClipUndoHandle
&rUndo
)
203 if( m_aClipRegion
.IsEmpty() ) // no clipping
206 // fprintf( stderr, "ensureClipFor: %d, %d %dx%d\n",
207 // aRange.getMinX(), aRange.getMinY(),
208 // (int)aRange.getWidth(), (int)aRange.getHeight() );
210 // first see if aRange is purely internal to one of the clip regions
211 Rectangle
aRect( Point( aRange
.getMinX(), aRange
.getMinY() ),
212 Size( aRange
.getWidth(), aRange
.getHeight() ) );
214 // then see if we are overlapping with just one
216 Rectangle aIterRect
, aHitRect
;
217 RegionHandle aHnd
= m_aClipRegion
.BeginEnumRects();
218 while( m_aClipRegion
.GetNextEnumRect( aHnd
, aIterRect
) )
220 if( aIterRect
.IsOver( aRect
) )
222 aHitRect
= aIterRect
;
226 m_aClipRegion
.EndEnumRects (aHnd
);
228 if( nHit
== 0 ) // rendering outside any clipping region
230 // fprintf (stderr, "denegerate case detected ...\n");
233 else if( nHit
== 1 ) // common path: rendering against just one clipping region
235 if( aHitRect
.IsInside( aRect
) )
237 // fprintf (stderr, " is inside ! avoid deeper clip ...\n");
240 // fprintf (stderr, " operation only overlaps with a single clip zone\n" );
241 rUndo
.m_aDevice
= m_aDevice
;
242 m_aDevice
= basebmp::subsetBitmapDevice( m_aOrigDevice
,
243 basegfx::B2IBox (aHitRect
.Left(),
246 aHitRect
.Bottom()) );
249 // fprintf (stderr, "URK: complex & slow clipping case\n" );
250 // horribly slow & complicated case ...
257 // Clipping by creating unconditional mask bitmaps is horribly
258 // slow so defer it, as much as possible. It is common to get
259 // 3 rectangles pushed, and have to create a vast off-screen
260 // mask only to destroy it shortly afterwards. That is
261 // particularly galling if we render only to a small,
262 // well defined rectangular area inside one of these clip
265 // ensureClipFor() or ensureClip() need to be called before
266 // real rendering. FIXME: we should prolly push this down to
267 // bitmapdevice instead.
268 bool SvpSalGraphics::setClipRegion( const Region
& i_rClip
)
270 m_aClipRegion
= i_rClip
;
272 if( i_rClip
.IsEmpty() )
275 else if( i_rClip
.GetRectCount() == 1 )
278 Rectangle
aBoundRect( i_rClip
.GetBoundRect() );
279 m_aDevice
= basebmp::subsetBitmapDevice( m_aOrigDevice
,
280 basegfx::B2IBox(aBoundRect
.Left(),aBoundRect
.Top(),aBoundRect
.Right(),aBoundRect
.Bottom()) );
284 m_bClipSetup
= false;
289 void SvpSalGraphics::SetLineColor()
291 m_bUseLineColor
= false;
294 void SvpSalGraphics::SetLineColor( SalColor nSalColor
)
296 m_bUseLineColor
= true;
297 m_aLineColor
= basebmp::Color( nSalColor
);
300 void SvpSalGraphics::SetFillColor()
302 m_bUseFillColor
= false;
305 void SvpSalGraphics::SetFillColor( SalColor nSalColor
)
307 m_bUseFillColor
= true;
308 m_aFillColor
= basebmp::Color( nSalColor
);
311 void SvpSalGraphics::SetXORMode( bool bSet
, bool )
313 m_aDrawMode
= bSet
? basebmp::DrawMode_XOR
: basebmp::DrawMode_PAINT
;
316 void SvpSalGraphics::SetROPLineColor( SalROPColor nROPColor
)
318 m_bUseLineColor
= true;
322 m_aLineColor
= basebmp::Color( 0 );
325 m_aLineColor
= basebmp::Color( 0xffffff );
328 m_aLineColor
= basebmp::Color( 0xffffff );
333 void SvpSalGraphics::SetROPFillColor( SalROPColor nROPColor
)
335 m_bUseFillColor
= true;
339 m_aFillColor
= basebmp::Color( 0 );
342 m_aFillColor
= basebmp::Color( 0xffffff );
345 m_aFillColor
= basebmp::Color( 0xffffff );
350 void SvpSalGraphics::drawPixel( long nX
, long nY
)
352 if( m_bUseLineColor
)
355 m_aDevice
->setPixel( basegfx::B2IPoint( nX
, nY
),
364 void SvpSalGraphics::drawPixel( long nX
, long nY
, SalColor nSalColor
)
366 basebmp::Color
aColor( nSalColor
);
368 m_aDevice
->setPixel( basegfx::B2IPoint( nX
, nY
),
376 void SvpSalGraphics::drawLine( long nX1
, long nY1
, long nX2
, long nY2
)
378 if( m_bUseLineColor
)
380 ensureClip(); // FIXME: for ...
381 m_aDevice
->drawLine( basegfx::B2IPoint( nX1
, nY1
),
382 basegfx::B2IPoint( nX2
, nY2
),
390 void SvpSalGraphics::drawRect( long nX
, long nY
, long nWidth
, long nHeight
)
392 if( m_bUseLineColor
|| m_bUseFillColor
)
394 basegfx::B2DPolygon aRect
= basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( nX
, nY
, nX
+nWidth
, nY
+nHeight
) );
395 ensureClip(); // FIXME: for ...
396 if( m_bUseFillColor
)
398 basegfx::B2DPolyPolygon
aPolyPoly( aRect
);
399 m_aDevice
->fillPolyPolygon( aPolyPoly
, m_aFillColor
, m_aDrawMode
, m_aClipMap
);
401 if( m_bUseLineColor
)
402 m_aDevice
->drawPolygon( aRect
, m_aLineColor
, m_aDrawMode
, m_aClipMap
);
407 void SvpSalGraphics::drawPolyLine( sal_uLong nPoints
, const SalPoint
* pPtAry
)
409 if( m_bUseLineColor
&& nPoints
)
411 basegfx::B2DPolygon aPoly
;
412 aPoly
.append( basegfx::B2DPoint( pPtAry
->mnX
, pPtAry
->mnY
), nPoints
);
413 for( sal_uLong i
= 1; i
< nPoints
; i
++ )
414 aPoly
.setB2DPoint( i
, basegfx::B2DPoint( pPtAry
[i
].mnX
, pPtAry
[i
].mnY
) );
415 aPoly
.setClosed( false );
416 ensureClip(); // FIXME: for ...
417 m_aDevice
->drawPolygon( aPoly
, m_aLineColor
, m_aDrawMode
, m_aClipMap
);
422 void SvpSalGraphics::drawPolygon( sal_uLong nPoints
, const SalPoint
* pPtAry
)
424 if( ( m_bUseLineColor
|| m_bUseFillColor
) && nPoints
)
426 basegfx::B2DPolygon aPoly
;
427 aPoly
.append( basegfx::B2DPoint( pPtAry
->mnX
, pPtAry
->mnY
), nPoints
);
428 for( sal_uLong i
= 1; i
< nPoints
; i
++ )
429 aPoly
.setB2DPoint( i
, basegfx::B2DPoint( pPtAry
[i
].mnX
, pPtAry
[i
].mnY
) );
430 ensureClip(); // FIXME: for ...
431 if( m_bUseFillColor
)
433 aPoly
.setClosed( true );
434 m_aDevice
->fillPolyPolygon( basegfx::B2DPolyPolygon(aPoly
), m_aFillColor
, m_aDrawMode
, m_aClipMap
);
436 if( m_bUseLineColor
)
438 aPoly
.setClosed( false );
439 m_aDevice
->drawPolygon( aPoly
, m_aLineColor
, m_aDrawMode
, m_aClipMap
);
445 void SvpSalGraphics::drawPolyPolygon( sal_uInt32 nPoly
,
446 const sal_uInt32
* pPointCounts
,
447 PCONSTSALPOINT
* pPtAry
)
449 if( ( m_bUseLineColor
|| m_bUseFillColor
) && nPoly
)
451 basegfx::B2DPolyPolygon aPolyPoly
;
452 for( sal_uInt32 nPolygon
= 0; nPolygon
< nPoly
; nPolygon
++ )
454 sal_uInt32 nPoints
= pPointCounts
[nPolygon
];
457 PCONSTSALPOINT pPoints
= pPtAry
[nPolygon
];
458 basegfx::B2DPolygon aPoly
;
459 aPoly
.append( basegfx::B2DPoint( pPoints
->mnX
, pPoints
->mnY
), nPoints
);
460 for( sal_uInt32 i
= 1; i
< nPoints
; i
++ )
461 aPoly
.setB2DPoint( i
, basegfx::B2DPoint( pPoints
[i
].mnX
, pPoints
[i
].mnY
) );
463 aPolyPoly
.append( aPoly
);
466 ensureClip(); // FIXME: for ...
467 if( m_bUseFillColor
)
469 aPolyPoly
.setClosed( true );
470 m_aDevice
->fillPolyPolygon( aPolyPoly
, m_aFillColor
, m_aDrawMode
, m_aClipMap
);
472 if( m_bUseLineColor
)
474 aPolyPoly
.setClosed( false );
475 nPoly
= aPolyPoly
.count();
476 for( sal_uInt32 i
= 0; i
< nPoly
; i
++ )
477 m_aDevice
->drawPolygon( aPolyPoly
.getB2DPolygon(i
), m_aLineColor
, m_aDrawMode
, m_aClipMap
);
483 bool SvpSalGraphics::drawPolyLine(
484 const ::basegfx::B2DPolygon
&,
485 double /*fTransparency*/,
486 const ::basegfx::B2DVector
& /*rLineWidths*/,
487 basegfx::B2DLineJoin
/*eJoin*/,
488 com::sun::star::drawing::LineCap
/*eLineCap*/)
490 // TODO: implement and advertise OutDevSupport_B2DDraw support
494 sal_Bool
SvpSalGraphics::drawPolyLineBezier( sal_uLong
,
501 sal_Bool
SvpSalGraphics::drawPolygonBezier( sal_uLong
,
508 sal_Bool
SvpSalGraphics::drawPolyPolygonBezier( sal_uInt32
,
510 const SalPoint
* const*,
511 const sal_uInt8
* const* )
516 bool SvpSalGraphics::drawPolyPolygon( const basegfx::B2DPolyPolygon
&, double /*fTransparency*/ )
518 // TODO: maybe BaseBmp can draw B2DPolyPolygons directly
522 void SvpSalGraphics::copyArea( long nDestX
,
528 sal_uInt16
/*nFlags*/ )
530 basegfx::B2IBox
aSrcRect( nSrcX
, nSrcY
, nSrcX
+nSrcWidth
, nSrcY
+nSrcHeight
);
531 basegfx::B2IBox
aDestRect( nDestX
, nDestY
, nDestX
+nSrcWidth
, nDestY
+nSrcHeight
);
532 // fprintf( stderr, "copyArea %ld pixels - clip region %d\n",
533 // (long)(nSrcWidth * nSrcHeight), m_aClipMap.get() != NULL );
534 SvpSalGraphics::ClipUndoHandle
aUndo( this );
535 if( !isClippedSetup( aDestRect
, aUndo
) )
536 m_aDevice
->drawBitmap( m_aOrigDevice
, aSrcRect
, aDestRect
, basebmp::DrawMode_PAINT
, m_aClipMap
);
540 void SvpSalGraphics::copyBits( const SalTwoRect
* pPosAry
,
541 SalGraphics
* pSrcGraphics
)
543 if( !m_aDevice
.get() )
546 SvpSalGraphics
* pSrc
= pSrcGraphics
?
547 static_cast<SvpSalGraphics
*>(pSrcGraphics
) : this;
548 basegfx::B2IBox
aSrcRect( pPosAry
->mnSrcX
, pPosAry
->mnSrcY
,
549 pPosAry
->mnSrcX
+pPosAry
->mnSrcWidth
,
550 pPosAry
->mnSrcY
+pPosAry
->mnSrcHeight
);
551 basegfx::B2IBox
aDestRect( pPosAry
->mnDestX
, pPosAry
->mnDestY
,
552 pPosAry
->mnDestX
+pPosAry
->mnDestWidth
,
553 pPosAry
->mnDestY
+pPosAry
->mnDestHeight
);
555 SvpSalGraphics::ClipUndoHandle
aUndo( this );
556 if( !isClippedSetup( aDestRect
, aUndo
) )
557 m_aDevice
->drawBitmap( pSrc
->m_aOrigDevice
, aSrcRect
, aDestRect
, basebmp::DrawMode_PAINT
, m_aClipMap
);
561 void SvpSalGraphics::drawBitmap( const SalTwoRect
* pPosAry
,
562 const SalBitmap
& rSalBitmap
)
564 const SvpSalBitmap
& rSrc
= static_cast<const SvpSalBitmap
&>(rSalBitmap
);
565 basegfx::B2IBox
aSrcRect( pPosAry
->mnSrcX
, pPosAry
->mnSrcY
,
566 pPosAry
->mnSrcX
+pPosAry
->mnSrcWidth
,
567 pPosAry
->mnSrcY
+pPosAry
->mnSrcHeight
);
568 basegfx::B2IBox
aDestRect( pPosAry
->mnDestX
, pPosAry
->mnDestY
,
569 pPosAry
->mnDestX
+pPosAry
->mnDestWidth
,
570 pPosAry
->mnDestY
+pPosAry
->mnDestHeight
);
572 SvpSalGraphics::ClipUndoHandle
aUndo( this );
573 if( !isClippedSetup( aDestRect
, aUndo
) )
574 m_aDevice
->drawBitmap( rSrc
.getBitmap(), aSrcRect
, aDestRect
, basebmp::DrawMode_PAINT
, m_aClipMap
);
578 void SvpSalGraphics::drawBitmap( const SalTwoRect
*,
582 // SNI, as in X11 plugin
585 void SvpSalGraphics::drawBitmap( const SalTwoRect
* pPosAry
,
586 const SalBitmap
& rSalBitmap
,
587 const SalBitmap
& rTransparentBitmap
)
589 const SvpSalBitmap
& rSrc
= static_cast<const SvpSalBitmap
&>(rSalBitmap
);
590 const SvpSalBitmap
& rSrcTrans
= static_cast<const SvpSalBitmap
&>(rTransparentBitmap
);
591 basegfx::B2IBox
aSrcRect( pPosAry
->mnSrcX
, pPosAry
->mnSrcY
,
592 pPosAry
->mnSrcX
+pPosAry
->mnSrcWidth
,
593 pPosAry
->mnSrcY
+pPosAry
->mnSrcHeight
);
594 basegfx::B2IBox
aDestRect( pPosAry
->mnDestX
, pPosAry
->mnDestY
,
595 pPosAry
->mnDestX
+pPosAry
->mnDestWidth
,
596 pPosAry
->mnDestY
+pPosAry
->mnDestHeight
);
597 SvpSalGraphics::ClipUndoHandle
aUndo( this );
598 if( !isClippedSetup( aDestRect
, aUndo
) )
599 m_aDevice
->drawMaskedBitmap( rSrc
.getBitmap(), rSrcTrans
.getBitmap(),
600 aSrcRect
, aDestRect
, basebmp::DrawMode_PAINT
, m_aClipMap
);
604 void SvpSalGraphics::drawMask( const SalTwoRect
* pPosAry
,
605 const SalBitmap
& rSalBitmap
,
606 SalColor nMaskColor
)
608 const SvpSalBitmap
& rSrc
= static_cast<const SvpSalBitmap
&>(rSalBitmap
);
609 basegfx::B2IBox
aSrcRect( pPosAry
->mnSrcX
, pPosAry
->mnSrcY
,
610 pPosAry
->mnSrcX
+pPosAry
->mnSrcWidth
,
611 pPosAry
->mnSrcY
+pPosAry
->mnSrcHeight
);
612 basegfx::B2IPoint
aDestPoint( pPosAry
->mnDestX
, pPosAry
->mnDestY
);
614 // BitmapDevice::drawMaskedColor works with 0==transparent,
615 // 255==opaque. drawMask() semantic is the other way
616 // around. Therefore, invert mask.
617 basebmp::BitmapDeviceSharedPtr aCopy
=
618 cloneBitmapDevice( basegfx::B2IVector( pPosAry
->mnSrcWidth
, pPosAry
->mnSrcHeight
),
620 basebmp::Color
aBgColor( COL_WHITE
);
621 aCopy
->clear(aBgColor
);
622 basebmp::Color
aFgColor( COL_BLACK
);
623 aCopy
->drawMaskedColor( aFgColor
, rSrc
.getBitmap(), aSrcRect
, basegfx::B2IPoint() );
625 basebmp::Color
aColor( nMaskColor
);
626 basegfx::B2IBox
aSrcRect2( 0, 0, pPosAry
->mnSrcWidth
, pPosAry
->mnSrcHeight
);
627 const basegfx::B2IBox
aClipRect( aDestPoint
, basegfx::B2ITuple( aSrcRect
.getWidth(), aSrcRect
.getHeight() ) );
629 SvpSalGraphics::ClipUndoHandle
aUndo( this );
630 if( !isClippedSetup( aClipRect
, aUndo
) )
631 m_aDevice
->drawMaskedColor( aColor
, aCopy
, aSrcRect
, aDestPoint
, m_aClipMap
);
635 SalBitmap
* SvpSalGraphics::getBitmap( long nX
, long nY
, long nWidth
, long nHeight
)
637 basebmp::BitmapDeviceSharedPtr aCopy
=
638 cloneBitmapDevice( basegfx::B2IVector( nWidth
, nHeight
),
640 basegfx::B2IBox
aSrcRect( nX
, nY
, nX
+nWidth
, nY
+nHeight
);
641 basegfx::B2IBox
aDestRect( 0, 0, nWidth
, nHeight
);
643 SvpSalGraphics::ClipUndoHandle
aUndo( this );
644 if( !isClippedSetup( aDestRect
, aUndo
) )
645 aCopy
->drawBitmap( m_aOrigDevice
, aSrcRect
, aDestRect
, basebmp::DrawMode_PAINT
);
647 SvpSalBitmap
* pBitmap
= new SvpSalBitmap();
648 pBitmap
->setBitmap( aCopy
);
652 SalColor
SvpSalGraphics::getPixel( long nX
, long nY
)
654 basebmp::Color
aColor( m_aOrigDevice
->getPixel( basegfx::B2IPoint( nX
, nY
) ) );
655 return aColor
.toInt32();
658 void SvpSalGraphics::invert( long nX
, long nY
, long nWidth
, long nHeight
, SalInvert
/*nFlags*/ )
660 // FIXME: handle SAL_INVERT_50 and SAL_INVERT_TRACKFRAME
661 basegfx::B2DPolygon aRect
= basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( nX
, nY
, nX
+nWidth
, nY
+nHeight
) );
662 basegfx::B2DPolyPolygon
aPolyPoly( aRect
);
663 basegfx::B2IBox
aDestRange( nX
, nY
, nX
+ nWidth
, nY
+ nHeight
);
665 SvpSalGraphics::ClipUndoHandle
aUndo( this );
666 if( !isClippedSetup( aDestRange
, aUndo
) )
667 m_aDevice
->fillPolyPolygon( aPolyPoly
, basebmp::Color( 0xffffff ), basebmp::DrawMode_XOR
, m_aClipMap
);
671 void SvpSalGraphics::invert( sal_uLong nPoints
, const SalPoint
* pPtAry
, SalInvert
/*nFlags*/ )
673 // FIXME: handle SAL_INVERT_50 and SAL_INVERT_TRACKFRAME
674 basegfx::B2DPolygon aPoly
;
675 aPoly
.append( basegfx::B2DPoint( pPtAry
->mnX
, pPtAry
->mnY
), nPoints
);
676 for( sal_uLong i
= 1; i
< nPoints
; i
++ )
677 aPoly
.setB2DPoint( i
, basegfx::B2DPoint( pPtAry
[i
].mnX
, pPtAry
[i
].mnY
) );
678 aPoly
.setClosed( true );
679 ensureClip(); // FIXME for ...
680 m_aDevice
->fillPolyPolygon( basegfx::B2DPolyPolygon(aPoly
), basebmp::Color( 0xffffff ), basebmp::DrawMode_XOR
, m_aClipMap
);
684 sal_Bool
SvpSalGraphics::drawEPS( long, long, long, long, void*, sal_uLong
)
689 SystemGraphicsData
SvpSalGraphics::GetGraphicsData() const
691 return SystemGraphicsData();
694 bool SvpSalGraphics::supportsOperation( OutDevSupportType
) const
699 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */