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