Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "headless/svpgdi.hxx"
21 : #include "headless/svpbmp.hxx"
22 :
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>
30 :
31 : #include <tools/debug.hxx>
32 :
33 : #if OSL_DEBUG_LEVEL > 2
34 : #include <basebmp/debug.hxx>
35 : #include <fstream>
36 : #include <rtl/strbuf.hxx>
37 : #include <sys/stat.h>
38 : #endif
39 :
40 : #include <stdio.h>
41 :
42 3263234 : inline void dbgOut( const basebmp::BitmapDeviceSharedPtr&
43 : #if OSL_DEBUG_LEVEL > 2
44 : rDevice
45 : #endif
46 : )
47 : {
48 : #if OSL_DEBUG_LEVEL > 2
49 : static int dbgStreamNum = 0;
50 : OStringBuffer aBuf( 256 );
51 : aBuf.append( "debug" );
52 : mkdir( aBuf.getStr(), 0777 );
53 : aBuf.append( "/" );
54 : aBuf.append( sal_Int64(reinterpret_cast<sal_IntPtr>(rDevice.get())), 16 );
55 : mkdir( aBuf.getStr(), 0777 );
56 : aBuf.append( "/bmp" );
57 : aBuf.append( sal_Int32(dbgStreamNum++) );
58 : std::fstream bmpstream( aBuf.getStr(), std::ios::out );
59 : debugDump( rDevice, bmpstream );
60 : #endif
61 3263234 : }
62 :
63 : // ===========================================================================
64 :
65 91410 : bool SvpSalGraphics::drawAlphaBitmap( const SalTwoRect&, const SalBitmap& /*rSourceBitmap*/, const SalBitmap& /*rAlphaBitmap*/ )
66 : {
67 : // TODO(P3) implement alpha blending
68 91410 : return false;
69 : }
70 :
71 34 : bool SvpSalGraphics::drawTransformedBitmap(
72 : const basegfx::B2DPoint& rNull,
73 : const basegfx::B2DPoint& rX,
74 : const basegfx::B2DPoint& rY,
75 : const SalBitmap& rSourceBitmap,
76 : const SalBitmap* pAlphaBitmap)
77 : {
78 : // here direct support for transformed bitmaps can be impemented
79 : (void)rNull; (void)rX; (void)rY; (void)rSourceBitmap; (void)pAlphaBitmap;
80 34 : return false;
81 : }
82 :
83 0 : bool SvpSalGraphics::drawAlphaRect( long /*nX*/, long /*nY*/, long /*nWidth*/, long /*nHeight*/, sal_uInt8 /*nTransparency*/ )
84 : {
85 : // TODO(P3) implement alpha blending
86 0 : return false;
87 : }
88 :
89 : #ifndef IOS
90 :
91 147385 : SvpSalGraphics::SvpSalGraphics() :
92 : m_bUseLineColor( true ),
93 : m_aLineColor( COL_BLACK ),
94 : m_bUseFillColor( false ),
95 : m_aFillColor( COL_WHITE ),
96 : m_aDrawMode( basebmp::DrawMode_PAINT ),
97 : m_aTextColor( COL_BLACK ),
98 : m_eTextFmt( basebmp::Format::EIGHT_BIT_GREY ),
99 147385 : m_bClipSetup( false )
100 : {
101 2505545 : for( int i = 0; i < MAX_FALLBACK; ++i )
102 2358160 : m_pServerFont[i] = NULL;
103 147385 : }
104 :
105 293940 : SvpSalGraphics::~SvpSalGraphics()
106 : {
107 293940 : }
108 :
109 : #endif
110 :
111 183847 : void SvpSalGraphics::setDevice( basebmp::BitmapDeviceSharedPtr& rDevice )
112 : {
113 183847 : m_aOrigDevice = rDevice;
114 183847 : ResetClipRegion();
115 :
116 : #ifndef IOS
117 : // determine matching bitmap format for masks
118 183847 : sal_uInt32 nDeviceFmt = m_aDevice->getScanlineFormat();
119 : DBG_ASSERT( (nDeviceFmt <= (sal_uInt32)basebmp::Format::MAX), "SVP::setDevice() with invalid bitmap format" );
120 183847 : switch( nDeviceFmt )
121 : {
122 : case basebmp::Format::EIGHT_BIT_GREY:
123 : case basebmp::Format::SIXTEEN_BIT_LSB_TC_MASK:
124 : case basebmp::Format::SIXTEEN_BIT_MSB_TC_MASK:
125 : case basebmp::Format::TWENTYFOUR_BIT_TC_MASK:
126 : case basebmp::Format::THIRTYTWO_BIT_TC_MASK_BGRA:
127 : case basebmp::Format::THIRTYTWO_BIT_TC_MASK_ARGB:
128 : case basebmp::Format::THIRTYTWO_BIT_TC_MASK_ABGR:
129 : case basebmp::Format::THIRTYTWO_BIT_TC_MASK_RGBA:
130 176660 : m_eTextFmt = basebmp::Format::EIGHT_BIT_GREY;
131 176660 : break;
132 : default:
133 7187 : m_eTextFmt = basebmp::Format::ONE_BIT_LSB_GREY;
134 7187 : break;
135 : }
136 : #endif
137 183847 : }
138 :
139 1313 : void SvpSalGraphics::GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY )
140 : {
141 1313 : rDPIX = rDPIY = 96;
142 1313 : }
143 :
144 129378 : sal_uInt16 SvpSalGraphics::GetBitCount() const
145 : {
146 129378 : return SvpSalBitmap::getBitCountFromScanlineFormat( m_aDevice->getScanlineFormat() );
147 : }
148 :
149 318 : long SvpSalGraphics::GetGraphicsWidth() const
150 : {
151 318 : if( m_aDevice.get() )
152 : {
153 318 : basegfx::B2IVector aSize = m_aOrigDevice->getSize();
154 318 : return aSize.getX();
155 : }
156 0 : return 0;
157 : }
158 :
159 188216 : void SvpSalGraphics::ResetClipRegion()
160 : {
161 188216 : m_aDevice = m_aOrigDevice;
162 188216 : m_aClipMap.reset();
163 188216 : m_bClipSetup = true;
164 188216 : m_aClipRegion.SetNull();
165 188216 : }
166 :
167 :
168 : // verify clip for the whole area is setup
169 3082788 : void SvpSalGraphics::ensureClip()
170 : {
171 3082788 : if (m_bClipSetup)
172 6151625 : return;
173 :
174 13951 : m_aDevice = m_aOrigDevice;
175 13951 : basegfx::B2IVector aSize = m_aDevice->getSize();
176 13951 : m_aClipMap = basebmp::createBitmapDevice( aSize, false, basebmp::Format::ONE_BIT_MSB_GREY );
177 13951 : m_aClipMap->clear( basebmp::Color(0xFFFFFFFF) );
178 :
179 27902 : RectangleVector aRectangles;
180 13951 : m_aClipRegion.GetRegionRectangles(aRectangles);
181 :
182 75994 : for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
183 : {
184 62043 : const long nW(aRectIter->GetWidth());
185 62043 : if(nW)
186 : {
187 62043 : const long nH(aRectIter->GetHeight());
188 :
189 62043 : if(nH)
190 : {
191 62043 : basegfx::B2DPolyPolygon aFull;
192 :
193 : aFull.append(
194 : basegfx::tools::createPolygonFromRect(
195 : basegfx::B2DRectangle(
196 62043 : aRectIter->Left(),
197 62043 : aRectIter->Top(),
198 62043 : aRectIter->Left() + nW,
199 248172 : aRectIter->Top() + nH)));
200 62043 : m_aClipMap->fillPolyPolygon(aFull, basebmp::Color(0), basebmp::DrawMode_PAINT);
201 : }
202 : }
203 : }
204 27902 : m_bClipSetup = true;
205 : }
206 :
207 2251364 : SvpSalGraphics::ClipUndoHandle::~ClipUndoHandle()
208 : {
209 1125682 : if( m_aDevice.get() )
210 916 : m_rGfx.m_aDevice = m_aDevice;
211 1125682 : }
212 :
213 : // setup a clip rectangle -only- iff we have to; if aRange
214 : // is entirely contained inside an existing clip frame, we
215 : // will avoid setting up the clip bitmap. Similarly if the
216 : // range doesn't appear at all we return true to avoid
217 : // rendering
218 1125682 : bool SvpSalGraphics::isClippedSetup( const basegfx::B2IBox &aRange, SvpSalGraphics::ClipUndoHandle &rUndo )
219 : {
220 1125682 : if( m_bClipSetup )
221 1091857 : return false;
222 :
223 33825 : if( m_aClipRegion.IsEmpty() ) // no clipping
224 0 : return false;
225 :
226 : // fprintf( stderr, "ensureClipFor: %d, %d %dx%d\n",
227 : // aRange.getMinX(), aRange.getMinY(),
228 : // (int)aRange.getWidth(), (int)aRange.getHeight() );
229 :
230 : // first see if aRange is purely internal to one of the clip regions
231 : Rectangle aRect( Point( aRange.getMinX(), aRange.getMinY() ),
232 33825 : Size( aRange.getWidth(), aRange.getHeight() ) );
233 :
234 : // then see if we are overlapping with just one
235 33825 : int nHit = 0;
236 33825 : Rectangle aHitRect;
237 33825 : RectangleVector aRectangles;
238 33825 : m_aClipRegion.GetRegionRectangles(aRectangles);
239 183315 : for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter)
240 : {
241 149490 : if( aRectIter->IsOver( aRect ) )
242 : {
243 10564 : aHitRect = *aRectIter;
244 10564 : nHit++;
245 : }
246 : }
247 :
248 33825 : if( nHit == 0 ) // rendering outside any clipping region
249 : {
250 : // fprintf (stderr, "denegerate case detected ...\n");
251 23638 : return true;
252 : }
253 10187 : else if( nHit == 1 ) // common path: rendering against just one clipping region
254 : {
255 9979 : if( aHitRect.IsInside( aRect ) )
256 : {
257 : // fprintf (stderr, " is inside ! avoid deeper clip ...\n");
258 9063 : return false;
259 : }
260 : // fprintf (stderr, " operation only overlaps with a single clip zone\n" );
261 916 : rUndo.m_aDevice = m_aDevice;
262 4580 : m_aDevice = basebmp::subsetBitmapDevice( m_aOrigDevice,
263 916 : basegfx::B2IBox (aHitRect.Left(),
264 916 : aHitRect.Top(),
265 916 : aHitRect.Right(),
266 1832 : aHitRect.Bottom()) );
267 916 : return false;
268 : }
269 : // fprintf (stderr, "URK: complex & slow clipping case\n" );
270 : // horribly slow & complicated case ...
271 :
272 208 : ensureClip();
273 208 : return false;
274 : }
275 :
276 :
277 : // Clipping by creating unconditional mask bitmaps is horribly
278 : // slow so defer it, as much as possible. It is common to get
279 : // 3 rectangles pushed, and have to create a vast off-screen
280 : // mask only to destroy it shortly afterwards. That is
281 : // particularly galling if we render only to a small,
282 : // well defined rectangular area inside one of these clip
283 : // rectangles.
284 : //
285 : // ensureClipFor() or ensureClip() need to be called before
286 : // real rendering. FIXME: we should prolly push this down to
287 : // bitmapdevice instead.
288 247495 : bool SvpSalGraphics::setClipRegion( const Region& i_rClip )
289 : {
290 247495 : m_aClipRegion = i_rClip;
291 247495 : m_aClipMap.reset();
292 247495 : if( i_rClip.IsEmpty() )
293 : {
294 0 : m_bClipSetup = true;
295 0 : return true;
296 : }
297 :
298 247495 : RectangleVector aRectangles;
299 247495 : i_rClip.GetRegionRectangles(aRectangles);
300 :
301 247495 : if(1 == aRectangles.size())
302 : {
303 221565 : m_aClipMap.reset();
304 :
305 221565 : const Rectangle& aBoundRect = aRectangles[0];
306 443130 : m_aDevice = basebmp::subsetBitmapDevice(
307 : m_aOrigDevice,
308 221565 : basegfx::B2IBox(aBoundRect.Left(),aBoundRect.Top(),aBoundRect.Right(),aBoundRect.Bottom()) );
309 :
310 221565 : m_bClipSetup = true;
311 : }
312 : else
313 25930 : m_bClipSetup = false;
314 :
315 247495 : return true;
316 : }
317 :
318 290963 : void SvpSalGraphics::SetLineColor()
319 : {
320 290963 : m_bUseLineColor = false;
321 290963 : }
322 :
323 195778 : void SvpSalGraphics::SetLineColor( SalColor nSalColor )
324 : {
325 195778 : m_bUseLineColor = true;
326 195778 : m_aLineColor = basebmp::Color( nSalColor );
327 195778 : }
328 :
329 4192 : void SvpSalGraphics::SetFillColor()
330 : {
331 4192 : m_bUseFillColor = false;
332 4192 : }
333 :
334 1867176 : void SvpSalGraphics::SetFillColor( SalColor nSalColor )
335 : {
336 1867176 : m_bUseFillColor = true;
337 1867176 : m_aFillColor = basebmp::Color( nSalColor );
338 1867176 : }
339 :
340 152128 : void SvpSalGraphics::SetXORMode( bool bSet, bool )
341 : {
342 152128 : m_aDrawMode = bSet ? basebmp::DrawMode_XOR : basebmp::DrawMode_PAINT;
343 152128 : }
344 :
345 0 : void SvpSalGraphics::SetROPLineColor( SalROPColor nROPColor )
346 : {
347 0 : m_bUseLineColor = true;
348 0 : switch( nROPColor )
349 : {
350 : case SAL_ROP_0:
351 0 : m_aLineColor = basebmp::Color( 0 );
352 0 : break;
353 : case SAL_ROP_1:
354 0 : m_aLineColor = basebmp::Color( 0xffffff );
355 0 : break;
356 : case SAL_ROP_INVERT:
357 0 : m_aLineColor = basebmp::Color( 0xffffff );
358 0 : break;
359 : }
360 0 : }
361 :
362 0 : void SvpSalGraphics::SetROPFillColor( SalROPColor nROPColor )
363 : {
364 0 : m_bUseFillColor = true;
365 0 : switch( nROPColor )
366 : {
367 : case SAL_ROP_0:
368 0 : m_aFillColor = basebmp::Color( 0 );
369 0 : break;
370 : case SAL_ROP_1:
371 0 : m_aFillColor = basebmp::Color( 0xffffff );
372 0 : break;
373 : case SAL_ROP_INVERT:
374 0 : m_aFillColor = basebmp::Color( 0xffffff );
375 0 : break;
376 : }
377 0 : }
378 :
379 116154 : void SvpSalGraphics::drawPixel( long nX, long nY )
380 : {
381 116154 : if( m_bUseLineColor )
382 : {
383 116154 : ensureClip();
384 : m_aDevice->setPixel( basegfx::B2IPoint( nX, nY ),
385 : m_aLineColor,
386 : m_aDrawMode,
387 : m_aClipMap
388 116154 : );
389 : }
390 116154 : dbgOut( m_aDevice );
391 116154 : }
392 :
393 179645 : void SvpSalGraphics::drawPixel( long nX, long nY, SalColor nSalColor )
394 : {
395 179645 : basebmp::Color aColor( nSalColor );
396 179645 : ensureClip();
397 : m_aDevice->setPixel( basegfx::B2IPoint( nX, nY ),
398 : aColor,
399 : m_aDrawMode,
400 : m_aClipMap
401 179645 : );
402 179645 : dbgOut( m_aDevice );
403 179645 : }
404 :
405 572560 : void SvpSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
406 : {
407 572560 : if( m_bUseLineColor )
408 : {
409 572560 : ensureClip(); // FIXME: for ...
410 : m_aDevice->drawLine( basegfx::B2IPoint( nX1, nY1 ),
411 : basegfx::B2IPoint( nX2, nY2 ),
412 : m_aLineColor,
413 : m_aDrawMode,
414 572560 : m_aClipMap );
415 : }
416 572560 : dbgOut( m_aDevice );
417 572560 : }
418 :
419 424015 : void SvpSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight )
420 : {
421 424015 : if( m_bUseLineColor || m_bUseFillColor )
422 : {
423 424015 : basegfx::B2DPolygon aRect = basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( nX, nY, nX+nWidth, nY+nHeight ) );
424 424015 : ensureClip(); // FIXME: for ...
425 424015 : if( m_bUseFillColor )
426 : {
427 422651 : basegfx::B2DPolyPolygon aPolyPoly( aRect );
428 422651 : m_aDevice->fillPolyPolygon( aPolyPoly, m_aFillColor, m_aDrawMode, m_aClipMap );
429 : }
430 424015 : if( m_bUseLineColor )
431 6185 : m_aDevice->drawPolygon( aRect, m_aLineColor, m_aDrawMode, m_aClipMap );
432 : }
433 424015 : dbgOut( m_aDevice );
434 424015 : }
435 :
436 149443 : void SvpSalGraphics::drawPolyLine( sal_uLong nPoints, const SalPoint* pPtAry )
437 : {
438 149443 : if( m_bUseLineColor && nPoints )
439 : {
440 149443 : basegfx::B2DPolygon aPoly;
441 149443 : aPoly.append( basegfx::B2DPoint( pPtAry->mnX, pPtAry->mnY ), nPoints );
442 817777 : for( sal_uLong i = 1; i < nPoints; i++ )
443 668334 : aPoly.setB2DPoint( i, basegfx::B2DPoint( pPtAry[i].mnX, pPtAry[i].mnY ) );
444 149443 : aPoly.setClosed( false );
445 149443 : ensureClip(); // FIXME: for ...
446 149443 : m_aDevice->drawPolygon( aPoly, m_aLineColor, m_aDrawMode, m_aClipMap );
447 : }
448 149443 : dbgOut( m_aDevice );
449 149443 : }
450 :
451 1638965 : void SvpSalGraphics::drawPolygon( sal_uLong nPoints, const SalPoint* pPtAry )
452 : {
453 1638965 : if( ( m_bUseLineColor || m_bUseFillColor ) && nPoints )
454 : {
455 1638965 : basegfx::B2DPolygon aPoly;
456 1638965 : aPoly.append( basegfx::B2DPoint( pPtAry->mnX, pPtAry->mnY ), nPoints );
457 7699140 : for( sal_uLong i = 1; i < nPoints; i++ )
458 6060175 : aPoly.setB2DPoint( i, basegfx::B2DPoint( pPtAry[i].mnX, pPtAry[i].mnY ) );
459 1638965 : ensureClip(); // FIXME: for ...
460 1638965 : if( m_bUseFillColor )
461 : {
462 1635997 : aPoly.setClosed( true );
463 1635997 : m_aDevice->fillPolyPolygon( basegfx::B2DPolyPolygon(aPoly), m_aFillColor, m_aDrawMode, m_aClipMap );
464 : }
465 1638965 : if( m_bUseLineColor )
466 : {
467 7679 : aPoly.setClosed( false );
468 7679 : m_aDevice->drawPolygon( aPoly, m_aLineColor, m_aDrawMode, m_aClipMap );
469 1638965 : }
470 : }
471 1638965 : dbgOut( m_aDevice );
472 1638965 : }
473 :
474 1798 : void SvpSalGraphics::drawPolyPolygon( sal_uInt32 nPoly,
475 : const sal_uInt32* pPointCounts,
476 : PCONSTSALPOINT* pPtAry )
477 : {
478 1798 : if( ( m_bUseLineColor || m_bUseFillColor ) && nPoly )
479 : {
480 1798 : basegfx::B2DPolyPolygon aPolyPoly;
481 7906 : for( sal_uInt32 nPolygon = 0; nPolygon < nPoly; nPolygon++ )
482 : {
483 6108 : sal_uInt32 nPoints = pPointCounts[nPolygon];
484 6108 : if( nPoints )
485 : {
486 6108 : PCONSTSALPOINT pPoints = pPtAry[nPolygon];
487 6108 : basegfx::B2DPolygon aPoly;
488 6108 : aPoly.append( basegfx::B2DPoint( pPoints->mnX, pPoints->mnY ), nPoints );
489 89799 : for( sal_uInt32 i = 1; i < nPoints; i++ )
490 83691 : aPoly.setB2DPoint( i, basegfx::B2DPoint( pPoints[i].mnX, pPoints[i].mnY ) );
491 :
492 6108 : aPolyPoly.append( aPoly );
493 : }
494 : }
495 1798 : ensureClip(); // FIXME: for ...
496 1798 : if( m_bUseFillColor )
497 : {
498 1798 : aPolyPoly.setClosed( true );
499 1798 : m_aDevice->fillPolyPolygon( aPolyPoly, m_aFillColor, m_aDrawMode, m_aClipMap );
500 : }
501 1798 : if( m_bUseLineColor )
502 : {
503 86 : aPolyPoly.setClosed( false );
504 86 : nPoly = aPolyPoly.count();
505 1872 : for( sal_uInt32 i = 0; i < nPoly; i++ )
506 1786 : m_aDevice->drawPolygon( aPolyPoly.getB2DPolygon(i), m_aLineColor, m_aDrawMode, m_aClipMap );
507 1798 : }
508 : }
509 1798 : dbgOut( m_aDevice );
510 1798 : }
511 :
512 0 : bool SvpSalGraphics::drawPolyLine(
513 : const ::basegfx::B2DPolygon&,
514 : double /*fTransparency*/,
515 : const ::basegfx::B2DVector& /*rLineWidths*/,
516 : basegfx::B2DLineJoin /*eJoin*/,
517 : com::sun::star::drawing::LineCap /*eLineCap*/)
518 : {
519 : // TODO: implement and advertise OutDevSupport_B2DDraw support
520 0 : return false;
521 : }
522 :
523 0 : sal_Bool SvpSalGraphics::drawPolyLineBezier( sal_uLong,
524 : const SalPoint*,
525 : const sal_uInt8* )
526 : {
527 0 : return sal_False;
528 : }
529 :
530 9280 : sal_Bool SvpSalGraphics::drawPolygonBezier( sal_uLong,
531 : const SalPoint*,
532 : const sal_uInt8* )
533 : {
534 9280 : return sal_False;
535 : }
536 :
537 1610 : sal_Bool SvpSalGraphics::drawPolyPolygonBezier( sal_uInt32,
538 : const sal_uInt32*,
539 : const SalPoint* const*,
540 : const sal_uInt8* const* )
541 : {
542 1610 : return sal_False;
543 : }
544 :
545 0 : bool SvpSalGraphics::drawPolyPolygon( const basegfx::B2DPolyPolygon&, double /*fTransparency*/ )
546 : {
547 : // TODO: maybe BaseBmp can draw B2DPolyPolygons directly
548 0 : return false;
549 : }
550 :
551 248 : void SvpSalGraphics::copyArea( long nDestX,
552 : long nDestY,
553 : long nSrcX,
554 : long nSrcY,
555 : long nSrcWidth,
556 : long nSrcHeight,
557 : sal_uInt16 /*nFlags*/ )
558 : {
559 248 : basegfx::B2IBox aSrcRect( nSrcX, nSrcY, nSrcX+nSrcWidth, nSrcY+nSrcHeight );
560 248 : basegfx::B2IBox aDestRect( nDestX, nDestY, nDestX+nSrcWidth, nDestY+nSrcHeight );
561 : // fprintf( stderr, "copyArea %ld pixels - clip region %d\n",
562 : // (long)(nSrcWidth * nSrcHeight), m_aClipMap.get() != NULL );
563 248 : SvpSalGraphics::ClipUndoHandle aUndo( this );
564 248 : if( !isClippedSetup( aDestRect, aUndo ) )
565 248 : m_aDevice->drawBitmap( m_aOrigDevice, aSrcRect, aDestRect, basebmp::DrawMode_PAINT, m_aClipMap );
566 248 : dbgOut( m_aDevice );
567 248 : }
568 :
569 31588 : void SvpSalGraphics::copyBits( const SalTwoRect& rPosAry,
570 : SalGraphics* pSrcGraphics )
571 : {
572 31588 : if( !m_aDevice.get() )
573 31588 : return;
574 :
575 : SvpSalGraphics* pSrc = pSrcGraphics ?
576 31588 : static_cast<SvpSalGraphics*>(pSrcGraphics) : this;
577 : basegfx::B2IBox aSrcRect( rPosAry.mnSrcX, rPosAry.mnSrcY,
578 : rPosAry.mnSrcX+rPosAry.mnSrcWidth,
579 31588 : rPosAry.mnSrcY+rPosAry.mnSrcHeight );
580 : basegfx::B2IBox aDestRect( rPosAry.mnDestX, rPosAry.mnDestY,
581 : rPosAry.mnDestX+rPosAry.mnDestWidth,
582 31588 : rPosAry.mnDestY+rPosAry.mnDestHeight );
583 :
584 31588 : SvpSalGraphics::ClipUndoHandle aUndo( this );
585 31588 : if( !isClippedSetup( aDestRect, aUndo ) )
586 31586 : m_aDevice->drawBitmap( pSrc->m_aOrigDevice, aSrcRect, aDestRect, basebmp::DrawMode_PAINT, m_aClipMap );
587 31588 : dbgOut( m_aDevice );
588 : }
589 :
590 110268 : void SvpSalGraphics::drawBitmap( const SalTwoRect& rPosAry,
591 : const SalBitmap& rSalBitmap )
592 : {
593 110268 : const SvpSalBitmap& rSrc = static_cast<const SvpSalBitmap&>(rSalBitmap);
594 : basegfx::B2IBox aSrcRect( rPosAry.mnSrcX, rPosAry.mnSrcY,
595 : rPosAry.mnSrcX+rPosAry.mnSrcWidth,
596 110268 : rPosAry.mnSrcY+rPosAry.mnSrcHeight );
597 : basegfx::B2IBox aDestRect( rPosAry.mnDestX, rPosAry.mnDestY,
598 : rPosAry.mnDestX+rPosAry.mnDestWidth,
599 110268 : rPosAry.mnDestY+rPosAry.mnDestHeight );
600 :
601 110268 : SvpSalGraphics::ClipUndoHandle aUndo( this );
602 110268 : if( !isClippedSetup( aDestRect, aUndo ) )
603 101833 : m_aDevice->drawBitmap( rSrc.getBitmap(), aSrcRect, aDestRect, basebmp::DrawMode_PAINT, m_aClipMap );
604 110268 : dbgOut( m_aDevice );
605 110268 : }
606 :
607 0 : void SvpSalGraphics::drawBitmap( const SalTwoRect&,
608 : const SalBitmap&,
609 : SalColor )
610 : {
611 : // SNI, as in X11 plugin
612 0 : }
613 :
614 5180 : void SvpSalGraphics::drawBitmap( const SalTwoRect& rPosAry,
615 : const SalBitmap& rSalBitmap,
616 : const SalBitmap& rTransparentBitmap )
617 : {
618 5180 : const SvpSalBitmap& rSrc = static_cast<const SvpSalBitmap&>(rSalBitmap);
619 5180 : const SvpSalBitmap& rSrcTrans = static_cast<const SvpSalBitmap&>(rTransparentBitmap);
620 : basegfx::B2IBox aSrcRect( rPosAry.mnSrcX, rPosAry.mnSrcY,
621 : rPosAry.mnSrcX+rPosAry.mnSrcWidth,
622 5180 : rPosAry.mnSrcY+rPosAry.mnSrcHeight );
623 : basegfx::B2IBox aDestRect( rPosAry.mnDestX, rPosAry.mnDestY,
624 : rPosAry.mnDestX+rPosAry.mnDestWidth,
625 5180 : rPosAry.mnDestY+rPosAry.mnDestHeight );
626 5180 : SvpSalGraphics::ClipUndoHandle aUndo( this );
627 5180 : if( !isClippedSetup( aDestRect, aUndo ) )
628 5180 : m_aDevice->drawMaskedBitmap( rSrc.getBitmap(), rSrcTrans.getBitmap(),
629 10360 : aSrcRect, aDestRect, basebmp::DrawMode_PAINT, m_aClipMap );
630 5180 : dbgOut( m_aDevice );
631 5180 : }
632 :
633 0 : void SvpSalGraphics::drawMask( const SalTwoRect& rPosAry,
634 : const SalBitmap& rSalBitmap,
635 : SalColor nMaskColor )
636 : {
637 0 : const SvpSalBitmap& rSrc = static_cast<const SvpSalBitmap&>(rSalBitmap);
638 : basegfx::B2IBox aSrcRect( rPosAry.mnSrcX, rPosAry.mnSrcY,
639 : rPosAry.mnSrcX+rPosAry.mnSrcWidth,
640 0 : rPosAry.mnSrcY+rPosAry.mnSrcHeight );
641 0 : basegfx::B2IPoint aDestPoint( rPosAry.mnDestX, rPosAry.mnDestY );
642 :
643 : // BitmapDevice::drawMaskedColor works with 0==transparent,
644 : // 255==opaque. drawMask() semantic is the other way
645 : // around. Therefore, invert mask.
646 : basebmp::BitmapDeviceSharedPtr aCopy =
647 : cloneBitmapDevice( basegfx::B2IVector( rPosAry.mnSrcWidth, rPosAry.mnSrcHeight ),
648 0 : rSrc.getBitmap() );
649 0 : basebmp::Color aBgColor( COL_WHITE );
650 0 : aCopy->clear(aBgColor);
651 0 : basebmp::Color aFgColor( COL_BLACK );
652 0 : aCopy->drawMaskedColor( aFgColor, rSrc.getBitmap(), aSrcRect, basegfx::B2IPoint() );
653 :
654 0 : basebmp::Color aColor( nMaskColor );
655 0 : basegfx::B2IBox aSrcRect2( 0, 0, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight );
656 0 : const basegfx::B2IBox aClipRect( aDestPoint, basegfx::B2ITuple( aSrcRect.getWidth(), aSrcRect.getHeight() ) );
657 :
658 0 : SvpSalGraphics::ClipUndoHandle aUndo( this );
659 0 : if( !isClippedSetup( aClipRect, aUndo ) )
660 0 : m_aDevice->drawMaskedColor( aColor, aCopy, aSrcRect, aDestPoint, m_aClipMap );
661 0 : dbgOut( m_aDevice );
662 0 : }
663 :
664 119210 : SalBitmap* SvpSalGraphics::getBitmap( long nX, long nY, long nWidth, long nHeight )
665 : {
666 : basebmp::BitmapDeviceSharedPtr aCopy =
667 : cloneBitmapDevice( basegfx::B2IVector( nWidth, nHeight ),
668 119210 : m_aDevice );
669 119210 : basegfx::B2IBox aSrcRect( nX, nY, nX+nWidth, nY+nHeight );
670 119210 : basegfx::B2IBox aDestRect( 0, 0, nWidth, nHeight );
671 :
672 238420 : SvpSalGraphics::ClipUndoHandle aUndo( this );
673 119210 : if( !isClippedSetup( aDestRect, aUndo ) )
674 104009 : aCopy->drawBitmap( m_aOrigDevice, aSrcRect, aDestRect, basebmp::DrawMode_PAINT );
675 :
676 119210 : SvpSalBitmap* pBitmap = new SvpSalBitmap();
677 119210 : pBitmap->setBitmap( aCopy );
678 238420 : return pBitmap;
679 : }
680 :
681 0 : SalColor SvpSalGraphics::getPixel( long nX, long nY )
682 : {
683 0 : basebmp::Color aColor( m_aOrigDevice->getPixel( basegfx::B2IPoint( nX, nY ) ) );
684 0 : return aColor.toInt32();
685 : }
686 :
687 33370 : void SvpSalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert /*nFlags*/ )
688 : {
689 : // FIXME: handle SAL_INVERT_50 and SAL_INVERT_TRACKFRAME
690 33370 : basegfx::B2DPolygon aRect = basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( nX, nY, nX+nWidth, nY+nHeight ) );
691 66740 : basegfx::B2DPolyPolygon aPolyPoly( aRect );
692 33370 : basegfx::B2IBox aDestRange( nX, nY, nX + nWidth, nY + nHeight );
693 :
694 66740 : SvpSalGraphics::ClipUndoHandle aUndo( this );
695 33370 : if( !isClippedSetup( aDestRange, aUndo ) )
696 33370 : m_aDevice->fillPolyPolygon( aPolyPoly, basebmp::Color( 0xffffff ), basebmp::DrawMode_XOR, m_aClipMap );
697 66740 : dbgOut( m_aDevice );
698 33370 : }
699 :
700 0 : void SvpSalGraphics::invert( sal_uLong nPoints, const SalPoint* pPtAry, SalInvert /*nFlags*/ )
701 : {
702 : // FIXME: handle SAL_INVERT_50 and SAL_INVERT_TRACKFRAME
703 0 : basegfx::B2DPolygon aPoly;
704 0 : aPoly.append( basegfx::B2DPoint( pPtAry->mnX, pPtAry->mnY ), nPoints );
705 0 : for( sal_uLong i = 1; i < nPoints; i++ )
706 0 : aPoly.setB2DPoint( i, basegfx::B2DPoint( pPtAry[i].mnX, pPtAry[i].mnY ) );
707 0 : aPoly.setClosed( true );
708 0 : ensureClip(); // FIXME for ...
709 0 : m_aDevice->fillPolyPolygon( basegfx::B2DPolyPolygon(aPoly), basebmp::Color( 0xffffff ), basebmp::DrawMode_XOR, m_aClipMap );
710 0 : dbgOut( m_aDevice );
711 0 : }
712 :
713 0 : sal_Bool SvpSalGraphics::drawEPS( long, long, long, long, void*, sal_uLong )
714 : {
715 0 : return sal_False;
716 : }
717 :
718 2 : SystemGraphicsData SvpSalGraphics::GetGraphicsData() const
719 : {
720 2 : return SystemGraphicsData();
721 : }
722 :
723 11025 : bool SvpSalGraphics::supportsOperation( OutDevSupportType ) const
724 : {
725 11025 : return false;
726 453 : }
727 :
728 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|