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 <string.h>
21 :
22 : #include "basebmp/bitmapdevice.hxx"
23 :
24 : #include "basebmp/compositeiterator.hxx"
25 : #include "basebmp/iteratortraits.hxx"
26 :
27 : #include "basebmp/accessor.hxx"
28 : #include "basebmp/accessortraits.hxx"
29 : #include "basebmp/accessoradapters.hxx"
30 : #include "basebmp/colorblendaccessoradapter.hxx"
31 :
32 : #include "basebmp/color.hxx"
33 : #include "basebmp/colormisc.hxx"
34 : #include "basebmp/colortraits.hxx"
35 :
36 : #include "basebmp/greylevelformats.hxx"
37 : #include "basebmp/paletteformats.hxx"
38 : #include "basebmp/rgbmaskpixelformats.hxx"
39 : #include "basebmp/rgb24pixelformats.hxx"
40 :
41 : #include "basebmp/scanlineformats.hxx"
42 : #include "basebmp/fillimage.hxx"
43 : #include "basebmp/scaleimage.hxx"
44 : #include "basebmp/clippedlinerenderer.hxx"
45 : #include "basebmp/polypolygonrenderer.hxx"
46 : #include "basebmp/genericcolorimageaccessor.hxx"
47 :
48 : #include "basebmp/tools.hxx"
49 : #include "intconversion.hxx"
50 :
51 : #include <rtl/alloc.h>
52 : #include <osl/diagnose.h>
53 :
54 : #include <basegfx/tools/tools.hxx>
55 : #include <basegfx/tools/canvastools.hxx>
56 : #include <basegfx/range/b2ibox.hxx>
57 : #include <basegfx/range/b2irange.hxx>
58 : #include <basegfx/range/b2drange.hxx>
59 : #include <basegfx/polygon/b2dpolygon.hxx>
60 : #include <basegfx/polygon/b2dpolygontools.hxx>
61 : #include <basegfx/polygon/b2dpolypolygontools.hxx>
62 : #include <basegfx/point/b2ipoint.hxx>
63 : #include <basegfx/vector/b2ivector.hxx>
64 :
65 : #include <vigra/iteratortraits.hxx>
66 : #include <vigra/rgbvalue.hxx>
67 : #include <vigra/copyimage.hxx>
68 : #include <vigra/tuple.hxx>
69 :
70 :
71 : namespace vigra
72 : {
73 :
74 : /// componentwise xor of an RGBValue (missing from rgbvalue.hxx)
75 : template< class Value, unsigned int RedIndex, unsigned int BlueIndex, unsigned int GreenIndex >
76 : inline RGBValue<Value, RedIndex, GreenIndex, BlueIndex>
77 10251452 : operator^( RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& lhs,
78 : RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& rhs )
79 : {
80 : RGBValue<Value, RedIndex, GreenIndex, BlueIndex> res(
81 20502904 : lhs[0] ^ rhs[0],
82 20502904 : lhs[1] ^ rhs[1],
83 51257260 : lhs[2] ^ rhs[2]);
84 10251452 : return res;
85 : }
86 : }
87 :
88 : namespace basebmp
89 : {
90 :
91 : namespace
92 : {
93 : /** Create the type for an accessor that takes the (mask,bitmap)
94 : input value generated from a JoinImageAccessorAdapter, and
95 : pipe that through a mask functor.
96 :
97 : @tpl DestAccessor
98 : Destination bitmap accessor
99 :
100 : @tpl JoinedAccessor
101 : Input accessor, is expected to generate a std::pair as the
102 : value type
103 :
104 : @tpl MaskFunctorMode
105 : Either FastMask or NoFastMask, depending on whether the mask
106 : is guaranteed to contain only 0s and 1s.
107 : */
108 : template< class DestAccessor,
109 : class JoinedAccessor,
110 : bool polarity,
111 : typename MaskFunctorMode > struct masked_input_splitting_accessor
112 : {
113 : typedef BinarySetterFunctionAccessorAdapter<
114 : DestAccessor,
115 : BinaryFunctorSplittingWrapper<
116 : typename outputMaskFunctorSelector<
117 : typename JoinedAccessor::value_type::first_type,
118 : typename JoinedAccessor::value_type::second_type,
119 : polarity,
120 : MaskFunctorMode >::type > > type;
121 : };
122 :
123 :
124 :
125 : // Actual BitmapDevice implementation (templatized by accessor and iterator)
126 : //--------------------------------------------------------------------------
127 :
128 : /** Implementation of the BitmapDevice interface
129 :
130 : @tpl DestIterator
131 : Iterator to access bitmap memory
132 :
133 : @tpl RawAccessor
134 : Raw accessor, to access pixel values directly
135 :
136 : @tpl AccessorSelector
137 : Accessor adapter selector, which, when applying the nested
138 : template metafunction wrap_accessor to one of the raw bitmap
139 : accessors, yields a member type named 'type', which is a
140 : wrapped accessor that map color values.
141 :
142 : @tpl Masks
143 : Traits template, containing nested traits
144 : clipmask_format_traits and alphamask_format_traits, which
145 : determine what specialized formats are to be used for clip and
146 : alpha masks. With those mask formats, clipping and alpha
147 : blending is handled natively.
148 : */
149 : template< class DestIterator,
150 : class RawAccessor,
151 : class AccessorSelector,
152 1415186 : class Masks > class BitmapRenderer :
153 : public BitmapDevice
154 : {
155 : public:
156 : typedef DestIterator dest_iterator_type;
157 : typedef RawAccessor raw_accessor_type;
158 : typedef AccessorSelector accessor_selector;
159 :
160 : typedef typename Masks::clipmask_format_traits::iterator_type mask_iterator_type;
161 : typedef typename Masks::clipmask_format_traits::raw_accessor_type mask_rawaccessor_type;
162 : typedef typename Masks::clipmask_format_traits::accessor_selector mask_accessorselector_type;
163 :
164 : typedef typename Masks::alphamask_format_traits::iterator_type alphamask_iterator_type;
165 : typedef typename Masks::alphamask_format_traits::raw_accessor_type alphamask_rawaccessor_type;
166 : typedef typename Masks::alphamask_format_traits::accessor_selector alphamask_accessorselector_type;
167 :
168 : typedef typename AccessorSelector::template wrap_accessor<
169 : raw_accessor_type >::type dest_accessor_type;
170 :
171 : typedef AccessorTraits< dest_accessor_type > accessor_traits;
172 : typedef CompositeIterator2D< dest_iterator_type,
173 : mask_iterator_type > composite_iterator_type;
174 : typedef CompositeIterator2D< vigra::Diff2D,
175 : vigra::Diff2D > generic_composite_iterator_type;
176 :
177 : typedef BitmapRenderer<mask_iterator_type,
178 : mask_rawaccessor_type,
179 : mask_accessorselector_type,
180 : Masks> mask_bitmap_type;
181 : typedef BitmapRenderer<alphamask_iterator_type,
182 : alphamask_rawaccessor_type,
183 : alphamask_accessorselector_type,
184 : Masks> alphamask_bitmap_type;
185 :
186 : // -------------------------------------------------------
187 :
188 : typedef AccessorTraits< raw_accessor_type > raw_accessor_traits;
189 : typedef typename uInt32Converter<
190 : typename raw_accessor_type::value_type>::to to_uint32_functor;
191 :
192 : // -------------------------------------------------------
193 :
194 : typedef typename raw_accessor_traits::xor_accessor raw_xor_accessor_type;
195 : typedef AccessorTraits<raw_xor_accessor_type> raw_xor_accessor_traits;
196 : typedef typename accessor_selector::template wrap_accessor<
197 : raw_xor_accessor_type >::type xor_accessor_type;
198 : typedef AccessorTraits<xor_accessor_type> xor_accessor_traits;
199 :
200 : // -------------------------------------------------------
201 :
202 : typedef typename raw_accessor_traits::template masked_accessor<
203 : mask_rawaccessor_type,
204 : dest_iterator_type,
205 : mask_iterator_type,
206 : Masks::clipmask_polarity>::type raw_maskedaccessor_type;
207 : typedef typename accessor_selector::template wrap_accessor<
208 : raw_maskedaccessor_type >::type masked_accessor_type;
209 : typedef typename AccessorTraits<
210 : raw_maskedaccessor_type>::xor_accessor raw_maskedxor_accessor_type;
211 : typedef typename accessor_selector::template wrap_accessor<
212 : raw_maskedxor_accessor_type >::type masked_xoraccessor_type;
213 :
214 : // -------------------------------------------------------
215 :
216 : // ((iter,mask),mask) special case (e.g. for clipped
217 : // drawMaskedColor())
218 : typedef AccessorTraits< raw_maskedaccessor_type > raw_maskedaccessor_traits;
219 : typedef typename raw_maskedaccessor_traits::template masked_accessor<
220 : mask_rawaccessor_type,
221 : composite_iterator_type,
222 : mask_iterator_type,
223 : Masks::clipmask_polarity>::type raw_maskedmask_accessor_type;
224 :
225 : typedef CompositeIterator2D<
226 : composite_iterator_type,
227 : mask_iterator_type> composite_composite_mask_iterator_type;
228 :
229 : // -------------------------------------------------------
230 :
231 : typedef ConstantColorBlendSetterAccessorAdapter<
232 : dest_accessor_type,
233 : typename alphamask_rawaccessor_type::value_type,
234 : Masks::alphamask_polarity> colorblend_accessor_type;
235 : typedef AccessorTraits<colorblend_accessor_type> colorblend_accessor_traits;
236 : typedef typename colorblend_accessor_traits::template masked_accessor<
237 : mask_rawaccessor_type,
238 : dest_iterator_type,
239 : mask_iterator_type,
240 : Masks::clipmask_polarity>::type masked_colorblend_accessor_type;
241 :
242 : // -------------------------------------------------------
243 :
244 : typedef ConstantColorBlendSetterAccessorAdapter<
245 : dest_accessor_type,
246 : Color,
247 : Masks::alphamask_polarity> colorblend_generic_accessor_type;
248 : typedef AccessorTraits<colorblend_generic_accessor_type> colorblend_generic_accessor_traits;
249 : typedef typename colorblend_generic_accessor_traits::template masked_accessor<
250 : mask_rawaccessor_type,
251 : dest_iterator_type,
252 : mask_iterator_type,
253 : Masks::clipmask_polarity>::type masked_colorblend_generic_accessor_type;
254 :
255 : // -------------------------------------------------------
256 :
257 : typedef JoinImageAccessorAdapter< dest_accessor_type,
258 : mask_rawaccessor_type > joined_image_accessor_type;
259 : typedef JoinImageAccessorAdapter< GenericColorImageAccessor,
260 : GenericColorImageAccessor > joined_generic_image_accessor_type;
261 :
262 : // -------------------------------------------------------
263 :
264 : dest_iterator_type maBegin;
265 : typename accessor_traits::color_lookup maColorLookup;
266 : IBitmapDeviceDamageTrackerSharedPtr mpDamage;
267 : to_uint32_functor maToUInt32Converter;
268 : dest_accessor_type maAccessor;
269 : colorblend_accessor_type maColorBlendAccessor;
270 : colorblend_generic_accessor_type maGenericColorBlendAccessor;
271 : raw_accessor_type maRawAccessor;
272 : xor_accessor_type maXorAccessor;
273 : raw_xor_accessor_type maRawXorAccessor;
274 : masked_accessor_type maMaskedAccessor;
275 : masked_colorblend_accessor_type maMaskedColorBlendAccessor;
276 : masked_colorblend_generic_accessor_type maGenericMaskedColorBlendAccessor;
277 : masked_xoraccessor_type maMaskedXorAccessor;
278 : raw_maskedaccessor_type maRawMaskedAccessor;
279 : raw_maskedxor_accessor_type maRawMaskedXorAccessor;
280 : raw_maskedmask_accessor_type maRawMaskedMaskAccessor;
281 :
282 :
283 : // -------------------------------------------------------
284 :
285 1533564 : BitmapRenderer( const basegfx::B2IBox& rBounds,
286 : const basegfx::B2IVector& rBufferSize,
287 : sal_Int32 nScanlineFormat,
288 : sal_Int32 nScanlineStride,
289 : sal_uInt8* pFirstScanline,
290 : dest_iterator_type begin,
291 : raw_accessor_type rawAccessor,
292 : dest_accessor_type accessor,
293 : const RawMemorySharedArray& rMem,
294 : const PaletteMemorySharedVector& rPalette,
295 : const IBitmapDeviceDamageTrackerSharedPtr& rDamage ) :
296 : BitmapDevice( rBounds, rBufferSize, nScanlineFormat,
297 : nScanlineStride, pFirstScanline, rMem, rPalette ),
298 : maBegin( begin ),
299 : maColorLookup(),
300 : mpDamage(rDamage),
301 : maToUInt32Converter(),
302 : maAccessor( accessor ),
303 : maColorBlendAccessor( accessor ),
304 : maGenericColorBlendAccessor( accessor ),
305 : maRawAccessor( rawAccessor ),
306 : maXorAccessor( accessor ),
307 : maRawXorAccessor( rawAccessor ),
308 : maMaskedAccessor( accessor ),
309 : maMaskedColorBlendAccessor( maColorBlendAccessor ),
310 : maGenericMaskedColorBlendAccessor( maGenericColorBlendAccessor ),
311 : maMaskedXorAccessor( accessor ),
312 : maRawMaskedAccessor( rawAccessor ),
313 : maRawMaskedXorAccessor( rawAccessor ),
314 1533564 : maRawMaskedMaskAccessor( rawAccessor )
315 1533564 : {}
316 :
317 : private:
318 :
319 2156305 : void damaged( const basegfx::B2IBox& rDamageRect ) const
320 : {
321 2156305 : if( mpDamage )
322 0 : mpDamage->damaged( rDamageRect );
323 2156305 : }
324 :
325 717489 : void damagedPointSize( const basegfx::B2IPoint& rPoint,
326 : const basegfx::B2IBox& rSize ) const
327 : {
328 717489 : if( mpDamage ) {
329 0 : basegfx::B2IPoint aLower( rPoint.getX() + rSize.getWidth(),
330 0 : rPoint.getY() + rSize.getHeight() );
331 0 : damaged( basegfx::B2IBox( rPoint, aLower ) );
332 : }
333 717489 : }
334 :
335 275276 : void damagedPixel( const basegfx::B2IPoint& rDamagePoint ) const
336 : {
337 275276 : if( !mpDamage )
338 550552 : return;
339 0 : basegfx::B2IPoint aEnd( rDamagePoint.getX() + 1,
340 0 : rDamagePoint.getY() + 1 );
341 0 : damaged( basegfx::B2IBox( rDamagePoint, aEnd ) );
342 : }
343 :
344 691556 : boost::shared_ptr<BitmapRenderer> getCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const
345 : {
346 691556 : return boost::dynamic_pointer_cast< BitmapRenderer >( bmp );
347 : }
348 :
349 345779 : virtual bool isCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const
350 : {
351 : // TODO(P1): dynamic_cast usually called twice for
352 : // compatible formats
353 345779 : return getCompatibleBitmap(bmp).get() != NULL;
354 : }
355 :
356 835320 : boost::shared_ptr<mask_bitmap_type> getCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const
357 : {
358 835320 : boost::shared_ptr<mask_bitmap_type> pMask( boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ));
359 :
360 835320 : if( !pMask )
361 717486 : return pMask;
362 :
363 117834 : if( pMask->getSize() != getSize() )
364 3 : pMask.reset();
365 :
366 117834 : return pMask;
367 : }
368 :
369 123011 : virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const
370 : {
371 : // TODO(P1): dynamic_cast usually called twice for
372 : // compatible formats
373 123011 : return boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ).get() != NULL;
374 : }
375 :
376 717489 : boost::shared_ptr<alphamask_bitmap_type> getCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const
377 : {
378 717489 : return boost::dynamic_pointer_cast<alphamask_bitmap_type>( bmp );
379 : }
380 :
381 0 : virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const
382 : {
383 : // TODO(P1): dynamic_cast usually called twice for
384 : // compatible formats
385 0 : return getCompatibleAlphaMask( bmp ).get() != NULL;
386 : }
387 :
388 14025 : virtual void clear_i( Color fillColor,
389 : const basegfx::B2IBox& rBounds )
390 : {
391 14025 : fillImage(destIterRange(maBegin,
392 : maRawAccessor,
393 14025 : rBounds),
394 : maColorLookup(
395 : maAccessor,
396 42075 : fillColor) );
397 14025 : damaged( rBounds );
398 14025 : }
399 :
400 220258 : virtual void setPixel_i( const basegfx::B2IPoint& rPt,
401 : Color pixelColor,
402 : DrawMode drawMode )
403 : {
404 440516 : const DestIterator pixel( maBegin +
405 220258 : vigra::Diff2D(rPt.getX(),
406 440516 : rPt.getY()) );
407 220258 : if( drawMode == DrawMode_XOR )
408 0 : maXorAccessor.set( pixelColor,
409 : pixel );
410 : else
411 220258 : maAccessor.set( pixelColor,
412 : pixel );
413 220258 : damagedPixel(rPt);
414 220258 : }
415 :
416 55018 : virtual void setPixel_i( const basegfx::B2IPoint& rPt,
417 : Color pixelColor,
418 : DrawMode drawMode,
419 : const BitmapDeviceSharedPtr& rClip )
420 : {
421 55018 : boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
422 : OSL_ASSERT( pMask );
423 :
424 55018 : const vigra::Diff2D offset(rPt.getX(),
425 110036 : rPt.getY());
426 :
427 : const composite_iterator_type aIter(
428 55018 : maBegin + offset,
429 110036 : pMask->maBegin + offset );
430 :
431 55018 : if( drawMode == DrawMode_XOR )
432 0 : maMaskedXorAccessor.set( pixelColor,
433 : aIter );
434 : else
435 55018 : maMaskedAccessor.set( pixelColor,
436 : aIter );
437 55018 : damagedPixel(rPt);
438 55018 : }
439 :
440 82327657 : virtual Color getPixel_i(const basegfx::B2IPoint& rPt )
441 : {
442 164655314 : const DestIterator pixel( maBegin +
443 82327657 : vigra::Diff2D(rPt.getX(),
444 164655314 : rPt.getY()) );
445 82327657 : return maAccessor(pixel);
446 : }
447 :
448 4 : virtual sal_uInt32 getPixelData_i( const basegfx::B2IPoint& rPt )
449 : {
450 8 : const DestIterator pixel( maBegin +
451 4 : vigra::Diff2D(rPt.getX(),
452 8 : rPt.getY()) );
453 4 : return maToUInt32Converter(maRawAccessor(pixel));
454 : }
455 :
456 : template< typename Iterator, typename Col, typename RawAcc >
457 1440362 : void implRenderLine2( const basegfx::B2IPoint& rPt1,
458 : const basegfx::B2IPoint& rPt2,
459 : const basegfx::B2IBox& rBounds,
460 : Col col,
461 : const Iterator& begin,
462 : const RawAcc& rawAcc )
463 : {
464 1440362 : renderClippedLine( rPt1,
465 : rPt2,
466 : rBounds,
467 : col,
468 : begin,
469 2880724 : rawAcc );
470 : // TODO(P2): perhaps this needs pushing up the stack a bit
471 : // to make more complex polygons more efficient ...
472 1440362 : damaged( basegfx::B2IBox( rPt1, rPt2 ) );
473 1440362 : }
474 :
475 : template< typename Iterator, typename Accessor, typename RawAcc >
476 572590 : void implRenderLine( const basegfx::B2IPoint& rPt1,
477 : const basegfx::B2IPoint& rPt2,
478 : const basegfx::B2IBox& rBounds,
479 : Color col,
480 : const Iterator& begin,
481 : const Accessor& acc,
482 : const RawAcc& rawAcc )
483 : {
484 572590 : implRenderLine2( rPt1,rPt2,rBounds,
485 : maColorLookup( acc,
486 : col ),
487 : begin,
488 1145150 : rawAcc );
489 572590 : }
490 :
491 : template< typename Iterator, typename RawAcc, typename XorAcc >
492 572590 : void implDrawLine( const basegfx::B2IPoint& rPt1,
493 : const basegfx::B2IPoint& rPt2,
494 : const basegfx::B2IBox& rBounds,
495 : Color col,
496 : const Iterator& begin,
497 : const RawAcc& rawAcc,
498 : const XorAcc& xorAcc,
499 : DrawMode drawMode )
500 : {
501 572590 : if( drawMode == DrawMode_XOR )
502 8 : implRenderLine( rPt1, rPt2, rBounds, col,
503 8 : begin, maAccessor, xorAcc );
504 : else
505 572582 : implRenderLine( rPt1, rPt2, rBounds, col,
506 572582 : begin, maAccessor, rawAcc );
507 572590 : }
508 :
509 565369 : virtual void drawLine_i(const basegfx::B2IPoint& rPt1,
510 : const basegfx::B2IPoint& rPt2,
511 : const basegfx::B2IBox& rBounds,
512 : Color lineColor,
513 : DrawMode drawMode )
514 : {
515 565369 : implDrawLine(rPt1,rPt2,rBounds,lineColor,
516 : maBegin,
517 565369 : maRawAccessor,maRawXorAccessor,drawMode);
518 565369 : }
519 :
520 62809 : composite_iterator_type getMaskedIter( const BitmapDeviceSharedPtr& rClip ) const
521 : {
522 62809 : boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
523 : OSL_ASSERT( pMask );
524 :
525 : return composite_iterator_type( maBegin,
526 62809 : pMask->maBegin );
527 : }
528 :
529 7221 : virtual void drawLine_i(const basegfx::B2IPoint& rPt1,
530 : const basegfx::B2IPoint& rPt2,
531 : const basegfx::B2IBox& rBounds,
532 : Color lineColor,
533 : DrawMode drawMode,
534 : const BitmapDeviceSharedPtr& rClip )
535 : {
536 7221 : implDrawLine(rPt1,rPt2,rBounds,lineColor,
537 : getMaskedIter(rClip),
538 : maRawMaskedAccessor,
539 14442 : maRawMaskedXorAccessor,drawMode);
540 7221 : }
541 :
542 : template< typename Iterator, typename RawAcc >
543 165110 : void implDrawPolygon( const basegfx::B2DPolygon& rPoly,
544 : const basegfx::B2IBox& rBounds,
545 : Color col,
546 : const Iterator& begin,
547 : const RawAcc& acc )
548 : {
549 165110 : basegfx::B2DPolygon aPoly( rPoly );
550 165110 : if( rPoly.areControlPointsUsed() )
551 0 : aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
552 :
553 : const typename dest_iterator_type::value_type colorIndex( maColorLookup(
554 : maAccessor,
555 165110 : col));
556 165110 : const sal_uInt32 nVertices( aPoly.count() );
557 1026692 : for( sal_uInt32 i=1; i<nVertices; ++i )
558 861582 : implRenderLine2( basegfx::fround(aPoly.getB2DPoint(i-1)),
559 : basegfx::fround(aPoly.getB2DPoint(i)),
560 : rBounds,
561 : colorIndex,
562 : begin,
563 1723164 : acc );
564 :
565 165110 : if( nVertices > 1 && aPoly.isClosed() )
566 6190 : implRenderLine2( basegfx::fround(aPoly.getB2DPoint(nVertices-1)),
567 : basegfx::fround(aPoly.getB2DPoint(0)),
568 : rBounds,
569 : colorIndex,
570 : begin,
571 12380 : acc );
572 165110 : }
573 :
574 163834 : virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
575 : const basegfx::B2IBox& rBounds,
576 : Color lineColor,
577 : DrawMode drawMode )
578 : {
579 163834 : if( drawMode == DrawMode_XOR )
580 0 : implDrawPolygon( rPoly, rBounds, lineColor,
581 : maBegin,
582 0 : maRawXorAccessor );
583 : else
584 163834 : implDrawPolygon( rPoly, rBounds, lineColor,
585 : maBegin,
586 163834 : maRawAccessor );
587 163834 : }
588 :
589 1276 : virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
590 : const basegfx::B2IBox& rBounds,
591 : Color lineColor,
592 : DrawMode drawMode,
593 : const BitmapDeviceSharedPtr& rClip )
594 : {
595 1276 : if( drawMode == DrawMode_XOR )
596 0 : implDrawPolygon( rPoly, rBounds, lineColor,
597 : getMaskedIter(rClip),
598 0 : maRawMaskedXorAccessor );
599 : else
600 1276 : implDrawPolygon( rPoly, rBounds, lineColor,
601 : getMaskedIter(rClip),
602 2552 : maRawMaskedAccessor );
603 1276 : }
604 :
605 : template< typename Iterator, typename RawAcc >
606 2155923 : void implFillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
607 : Color col,
608 : const Iterator& begin,
609 : const RawAcc& acc,
610 : const basegfx::B2IBox& rBounds )
611 : {
612 2155923 : basegfx::B2DPolyPolygon aPoly( rPoly );
613 2155923 : if( rPoly.areControlPointsUsed() )
614 0 : aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
615 :
616 2155923 : renderClippedPolyPolygon( begin,
617 : acc,
618 : maColorLookup( maAccessor,
619 : col),
620 : rBounds,
621 : aPoly,
622 4232555 : basegfx::FillRule_EVEN_ODD );
623 :
624 2155923 : if( mpDamage )
625 : {
626 0 : basegfx::B2DRange const aPolyBounds( basegfx::tools::getRange(aPoly) );
627 0 : damaged( basegfx::unotools::b2ISurroundingBoxFromB2DRange( aPolyBounds ) );
628 2155923 : }
629 2155923 : }
630 :
631 2104082 : virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
632 : Color fillColor,
633 : DrawMode drawMode,
634 : const basegfx::B2IBox& rBounds )
635 : {
636 2104082 : if( drawMode == DrawMode_XOR )
637 40759 : implFillPolyPolygon( rPoly, fillColor,
638 : maBegin,
639 : maRawXorAccessor,
640 40759 : rBounds );
641 : else
642 2063323 : implFillPolyPolygon( rPoly, fillColor,
643 : maBegin,
644 : maRawAccessor,
645 2063323 : rBounds );
646 2104082 : }
647 :
648 51841 : virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
649 : Color fillColor,
650 : DrawMode drawMode,
651 : const basegfx::B2IBox& rBounds,
652 : const BitmapDeviceSharedPtr& rClip )
653 : {
654 51841 : if( drawMode == DrawMode_XOR )
655 102 : implFillPolyPolygon( rPoly, fillColor,
656 : getMaskedIter(rClip),
657 : maRawMaskedXorAccessor,
658 204 : rBounds );
659 : else
660 51739 : implFillPolyPolygon( rPoly, fillColor,
661 : getMaskedIter(rClip),
662 : maRawMaskedAccessor,
663 103478 : rBounds );
664 51841 : }
665 :
666 : template< typename Iterator, typename RawAcc >
667 345773 : void implDrawBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
668 : const basegfx::B2IBox& rSrcRect,
669 : const basegfx::B2IBox& rDstRect,
670 : const Iterator& begin,
671 : const RawAcc& acc)
672 : {
673 345773 : boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
674 : OSL_ASSERT( pSrcBmp );
675 :
676 345773 : scaleImage(
677 345773 : srcIterRange(pSrcBmp->maBegin,
678 345773 : pSrcBmp->maRawAccessor,
679 691546 : rSrcRect),
680 : destIterRange(begin,
681 : acc,
682 : rDstRect),
683 1037319 : isSharedBuffer(rSrcBitmap) );
684 345773 : damaged( rDstRect );
685 345773 : }
686 :
687 : template< typename Iterator, typename Acc >
688 2 : void implDrawBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
689 : const basegfx::B2IBox& rSrcRect,
690 : const basegfx::B2IBox& rDstRect,
691 : const Iterator& begin,
692 : const Acc& acc)
693 : {
694 2 : GenericColorImageAccessor aSrcAcc( rSrcBitmap );
695 :
696 2 : scaleImage(
697 : srcIterRange(vigra::Diff2D(),
698 : aSrcAcc,
699 : rSrcRect),
700 : destIterRange(begin,
701 : acc,
702 4 : rDstRect));
703 2 : damaged( rDstRect );
704 2 : }
705 :
706 344413 : virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
707 : const basegfx::B2IBox& rSrcRect,
708 : const basegfx::B2IBox& rDstRect,
709 : DrawMode drawMode )
710 : {
711 344413 : if( isCompatibleBitmap( rSrcBitmap ) )
712 : {
713 344411 : if( drawMode == DrawMode_XOR )
714 0 : implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
715 : maBegin,
716 0 : maRawXorAccessor);
717 : else
718 344411 : implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
719 : maBegin,
720 344411 : maRawAccessor);
721 : }
722 : else
723 : {
724 2 : if( drawMode == DrawMode_XOR )
725 0 : implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
726 : maBegin,
727 0 : maXorAccessor);
728 : else
729 2 : implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
730 : maBegin,
731 2 : maAccessor);
732 : }
733 344413 : damaged( rDstRect );
734 344413 : }
735 :
736 1362 : virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
737 : const basegfx::B2IBox& rSrcRect,
738 : const basegfx::B2IBox& rDstRect,
739 : DrawMode drawMode,
740 : const BitmapDeviceSharedPtr& rClip )
741 : {
742 1362 : if( isCompatibleBitmap( rSrcBitmap ) )
743 : {
744 1362 : if( drawMode == DrawMode_XOR )
745 0 : implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
746 : getMaskedIter(rClip),
747 0 : maRawMaskedXorAccessor);
748 : else
749 1362 : implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
750 : getMaskedIter(rClip),
751 2724 : maRawMaskedAccessor);
752 : }
753 : else
754 : {
755 0 : if( drawMode == DrawMode_XOR )
756 0 : implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
757 : getMaskedIter(rClip),
758 0 : maMaskedXorAccessor);
759 : else
760 0 : implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
761 : getMaskedIter(rClip),
762 0 : maMaskedAccessor);
763 : }
764 1362 : damaged( rDstRect );
765 1362 : }
766 :
767 716380 : virtual void drawMaskedColor_i(Color aSrcColor,
768 : const BitmapDeviceSharedPtr& rAlphaMask,
769 : const basegfx::B2IBox& rSrcRect,
770 : const basegfx::B2IPoint& rDstPoint )
771 : {
772 716380 : boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) );
773 1432760 : boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
774 :
775 716380 : if( pAlpha )
776 : {
777 716377 : maColorBlendAccessor.setColor( aSrcColor );
778 :
779 1432754 : vigra::copyImage( srcIterRange(pAlpha->maBegin,
780 716377 : pAlpha->maRawAccessor,
781 : rSrcRect),
782 : destIter(maBegin,
783 : maColorBlendAccessor,
784 2149131 : rDstPoint) );
785 : }
786 3 : else if( pMask )
787 : {
788 : const composite_iterator_type aBegin(
789 0 : maBegin + vigra::Diff2D(rDstPoint.getX(),
790 0 : rDstPoint.getY()),
791 0 : pMask->maBegin + topLeft(rSrcRect) );
792 :
793 0 : fillImage(aBegin,
794 0 : aBegin + vigra::Diff2D(rSrcRect.getWidth(),
795 0 : rSrcRect.getHeight()),
796 : maRawMaskedAccessor,
797 : maColorLookup(
798 : maAccessor,
799 0 : aSrcColor) );
800 : }
801 : else
802 : {
803 3 : GenericColorImageAccessor aSrcAcc( rAlphaMask );
804 3 : maGenericColorBlendAccessor.setColor( aSrcColor );
805 :
806 3 : vigra::copyImage( srcIterRange(vigra::Diff2D(),
807 : aSrcAcc,
808 : rSrcRect),
809 : destIter(maBegin,
810 : maGenericColorBlendAccessor,
811 6 : rDstPoint) );
812 : }
813 1432760 : damagedPointSize( rDstPoint, rSrcRect );
814 716380 : }
815 :
816 1109 : virtual void drawMaskedColor_i(Color aSrcColor,
817 : const BitmapDeviceSharedPtr& rAlphaMask,
818 : const basegfx::B2IBox& rSrcRect,
819 : const basegfx::B2IPoint& rDstPoint,
820 : const BitmapDeviceSharedPtr& rClip )
821 : {
822 1109 : boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) );
823 2218 : boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
824 :
825 1109 : if( pAlpha )
826 : {
827 1109 : const composite_iterator_type aBegin( getMaskedIter(rClip) );
828 1109 : maMaskedColorBlendAccessor.get1stWrappedAccessor().setColor(
829 : aSrcColor );
830 :
831 2218 : vigra::copyImage( srcIterRange(pAlpha->maBegin,
832 1109 : pAlpha->maRawAccessor,
833 : rSrcRect),
834 : destIter(aBegin,
835 : maMaskedColorBlendAccessor,
836 4436 : rDstPoint) );
837 : }
838 0 : else if( pMask )
839 : {
840 0 : boost::shared_ptr<mask_bitmap_type> pClipMask( getCompatibleClipMask(rClip) );
841 : OSL_ASSERT( pClipMask );
842 :
843 : // setup a ((iter,mask),clipMask) composite composite
844 : // iterator, to pass both masks (clip and alpha mask)
845 : // to the algorithm
846 : const composite_composite_mask_iterator_type aBegin(
847 : composite_iterator_type(
848 0 : maBegin + vigra::Diff2D(rDstPoint.getX(),
849 0 : rDstPoint.getY()),
850 0 : pMask->maBegin + topLeft(rSrcRect)),
851 0 : pClipMask->maBegin + vigra::Diff2D(rDstPoint.getX(),
852 0 : rDstPoint.getY()) );
853 :
854 0 : fillImage(aBegin,
855 0 : aBegin + vigra::Diff2D(rSrcRect.getWidth(),
856 0 : rSrcRect.getHeight()),
857 : maRawMaskedMaskAccessor,
858 : maColorLookup(
859 : maAccessor,
860 0 : aSrcColor) );
861 : }
862 : else
863 : {
864 0 : GenericColorImageAccessor aSrcAcc( rAlphaMask );
865 0 : const composite_iterator_type aBegin( getMaskedIter(rClip) );
866 0 : maGenericMaskedColorBlendAccessor.get1stWrappedAccessor().setColor(
867 : aSrcColor );
868 :
869 0 : vigra::copyImage( srcIterRange(vigra::Diff2D(),
870 : aSrcAcc,
871 : rSrcRect),
872 : destIter(aBegin,
873 : maGenericMaskedColorBlendAccessor,
874 0 : rDstPoint) );
875 : }
876 2218 : damagedPointSize( rDstPoint, rSrcRect );
877 1109 : }
878 :
879 : template< typename Iterator, typename Acc >
880 4 : void implDrawMaskedBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
881 : const BitmapDeviceSharedPtr& rMask,
882 : const basegfx::B2IBox& rSrcRect,
883 : const basegfx::B2IBox& rDstRect,
884 : const Iterator& begin,
885 : const Acc& acc)
886 : {
887 4 : boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
888 8 : boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rMask) );
889 : OSL_ASSERT( pMask && pSrcBmp );
890 :
891 4 : scaleImage(
892 : srcIterRange(composite_iterator_type(
893 4 : pSrcBmp->maBegin,
894 4 : pMask->maBegin),
895 : joined_image_accessor_type(
896 4 : pSrcBmp->maAccessor,
897 4 : pMask->maRawAccessor),
898 : rSrcRect),
899 : destIterRange(begin,
900 : typename masked_input_splitting_accessor<
901 : Acc,
902 : joined_image_accessor_type,
903 : Masks::clipmask_polarity,
904 : FastMask >::type(acc),
905 8 : rDstRect),
906 24 : isSharedBuffer(rSrcBitmap));
907 8 : damaged( rDstRect );
908 4 : }
909 :
910 : template< typename Iterator, typename Acc >
911 5180 : void implDrawMaskedBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
912 : const BitmapDeviceSharedPtr& rMask,
913 : const basegfx::B2IBox& rSrcRect,
914 : const basegfx::B2IBox& rDstRect,
915 : const Iterator& begin,
916 : const Acc& acc)
917 : {
918 5180 : GenericColorImageAccessor aSrcAcc( rSrcBitmap );
919 10360 : GenericColorImageAccessor aMaskAcc( rMask );
920 :
921 5180 : const vigra::Diff2D aTopLeft(rSrcRect.getMinX(),
922 10360 : rSrcRect.getMinY());
923 5180 : const vigra::Diff2D aBottomRight(rSrcRect.getMaxX(),
924 10360 : rSrcRect.getMaxY());
925 5180 : scaleImage(
926 : vigra::make_triple(
927 : generic_composite_iterator_type(
928 : aTopLeft,aTopLeft),
929 : generic_composite_iterator_type(
930 : aBottomRight,aBottomRight),
931 : joined_generic_image_accessor_type(
932 : aSrcAcc,
933 : aMaskAcc)),
934 : destIterRange(begin,
935 : typename masked_input_splitting_accessor<
936 : Acc,
937 : joined_generic_image_accessor_type,
938 : Masks::clipmask_polarity,
939 : NoFastMask >::type(acc),
940 10360 : rDstRect));
941 10360 : damaged( rDstRect );
942 5180 : }
943 :
944 5184 : virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
945 : const BitmapDeviceSharedPtr& rMask,
946 : const basegfx::B2IBox& rSrcRect,
947 : const basegfx::B2IBox& rDstRect,
948 : DrawMode drawMode )
949 : {
950 5188 : if( isCompatibleClipMask(rMask) &&
951 4 : isCompatibleBitmap(rSrcBitmap) )
952 : {
953 4 : if( drawMode == DrawMode_XOR )
954 0 : implDrawMaskedBitmap(rSrcBitmap, rMask,
955 : rSrcRect, rDstRect,
956 : maBegin,
957 0 : maXorAccessor);
958 : else
959 4 : implDrawMaskedBitmap(rSrcBitmap, rMask,
960 : rSrcRect, rDstRect,
961 : maBegin,
962 4 : maAccessor);
963 : }
964 : else
965 : {
966 5180 : if( drawMode == DrawMode_XOR )
967 0 : implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
968 : rSrcRect, rDstRect,
969 : maBegin,
970 0 : maXorAccessor);
971 : else
972 5180 : implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
973 : rSrcRect, rDstRect,
974 : maBegin,
975 5180 : maAccessor);
976 : }
977 5184 : damaged( rDstRect );
978 5184 : }
979 :
980 0 : virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
981 : const BitmapDeviceSharedPtr& rMask,
982 : const basegfx::B2IBox& rSrcRect,
983 : const basegfx::B2IBox& rDstRect,
984 : DrawMode drawMode,
985 : const BitmapDeviceSharedPtr& rClip )
986 : {
987 0 : if( isCompatibleClipMask(rMask) &&
988 0 : isCompatibleBitmap(rSrcBitmap) )
989 : {
990 0 : if( drawMode == DrawMode_XOR )
991 0 : implDrawMaskedBitmap(rSrcBitmap, rMask,
992 : rSrcRect, rDstRect,
993 : getMaskedIter(rClip),
994 0 : maMaskedXorAccessor);
995 : else
996 0 : implDrawMaskedBitmap(rSrcBitmap, rMask,
997 : rSrcRect, rDstRect,
998 : getMaskedIter(rClip),
999 0 : maMaskedAccessor);
1000 : }
1001 : else
1002 : {
1003 0 : if( drawMode == DrawMode_XOR )
1004 0 : implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
1005 : rSrcRect, rDstRect,
1006 : getMaskedIter(rClip),
1007 0 : maMaskedXorAccessor);
1008 : else
1009 0 : implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
1010 : rSrcRect, rDstRect,
1011 : getMaskedIter(rClip),
1012 0 : maMaskedAccessor);
1013 : }
1014 0 : damaged( rDstRect );
1015 0 : }
1016 :
1017 450488 : IBitmapDeviceDamageTrackerSharedPtr getDamageTracker_i() const
1018 : {
1019 450488 : return mpDamage;
1020 : }
1021 0 : void setDamageTracker_i( const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
1022 : {
1023 0 : mpDamage = rDamage;
1024 0 : }
1025 : };
1026 : } // namespace
1027 :
1028 2241157 : struct ImplBitmapDevice
1029 : {
1030 : /** Bitmap memory plus deleter.
1031 :
1032 : Always points to the start of the mem
1033 : */
1034 : RawMemorySharedArray mpMem;
1035 :
1036 : /// Palette memory plus deleter (might be NULL)
1037 : PaletteMemorySharedVector mpPalette;
1038 :
1039 : /** Bounds of the device.
1040 :
1041 : maBounds.getWidth()/getHeight() yield the true size of the
1042 : device (i.e. the rectangle given by maBounds covers the device
1043 : area under the including-the-bottommost-and-rightmost-pixels
1044 : fill rule)
1045 : */
1046 : basegfx::B2IBox maBounds;
1047 :
1048 : //// Size of the actual frame buffer
1049 : basegfx::B2IVector maBufferSize;
1050 :
1051 : /// Scanline format, as provided at the constructor
1052 : sal_Int32 mnScanlineFormat;
1053 :
1054 : /// Scanline stride. Negative for bottom-to-top formats
1055 : sal_Int32 mnScanlineStride;
1056 :
1057 : /// raw ptr to 0th scanline. used for cloning a generic renderer
1058 : sal_uInt8* mpFirstScanline;
1059 :
1060 : /** (Optional) device sharing the same memory, and used for input
1061 : clip masks/alpha masks/bitmaps that don't match our exact
1062 : bitmap format.
1063 :
1064 : This is to avoid the combinatorical explosion when dealing
1065 : with n bitmap formats, which could be combined with n clip
1066 : masks, alpha masks and bitmap masks (yielding a total of n^4
1067 : combinations). Since each BitmapRenderer is specialized for
1068 : one specific combination of said formats, a lot of duplicate
1069 : code would be generated, most of which probably never
1070 : used. Therefore, only the most common combinations are
1071 : specialized templates, the remainder gets handled by this
1072 : generic renderer (via runtime polymorphism).
1073 : */
1074 : BitmapDeviceSharedPtr mpGenericRenderer;
1075 : };
1076 :
1077 :
1078 1533564 : BitmapDevice::BitmapDevice( const basegfx::B2IBox& rBounds,
1079 : const basegfx::B2IVector& rBufferSize,
1080 : sal_Int32 nScanlineFormat,
1081 : sal_Int32 nScanlineStride,
1082 : sal_uInt8* pFirstScanline,
1083 : const RawMemorySharedArray& rMem,
1084 : const PaletteMemorySharedVector& rPalette ) :
1085 1533564 : mpImpl( new ImplBitmapDevice )
1086 : {
1087 1533564 : mpImpl->mpMem = rMem;
1088 1533564 : mpImpl->mpPalette = rPalette;
1089 1533564 : mpImpl->maBounds = rBounds;
1090 1533564 : mpImpl->maBufferSize = rBufferSize;
1091 1533564 : mpImpl->mnScanlineFormat = nScanlineFormat;
1092 1533564 : mpImpl->mnScanlineStride = nScanlineStride;
1093 1533564 : mpImpl->mpFirstScanline = pFirstScanline;
1094 1533564 : }
1095 :
1096 707593 : BitmapDevice::~BitmapDevice()
1097 : {
1098 : // outline, because of internal ImplBitmapDevice
1099 : SAL_INFO( "basebmp.bitmapdevice", "~BitmapDevice(" << this << ")" );
1100 707593 : }
1101 :
1102 4869648 : basegfx::B2IVector BitmapDevice::getSize() const
1103 : {
1104 : return basegfx::B2IVector(
1105 4869648 : mpImpl->maBounds.getMaxX() - mpImpl->maBounds.getMinX(),
1106 9739296 : mpImpl->maBounds.getMaxY() - mpImpl->maBounds.getMinY() );
1107 : }
1108 :
1109 1096281 : bool BitmapDevice::isTopDown() const
1110 : {
1111 1096281 : return mpImpl->mnScanlineStride >= 0;
1112 : }
1113 :
1114 0 : basegfx::B2IVector BitmapDevice::getBufferSize() const
1115 : {
1116 0 : return mpImpl->maBufferSize;
1117 : }
1118 :
1119 3397562 : sal_Int32 BitmapDevice::getScanlineFormat() const
1120 : {
1121 3397562 : return mpImpl->mnScanlineFormat;
1122 : }
1123 :
1124 581738 : sal_Int32 BitmapDevice::getScanlineStride() const
1125 : {
1126 581738 : return mpImpl->mnScanlineStride < 0 ?
1127 581738 : -mpImpl->mnScanlineStride : mpImpl->mnScanlineStride;
1128 : }
1129 :
1130 2994819 : RawMemorySharedArray BitmapDevice::getBuffer() const
1131 : {
1132 2994819 : return mpImpl->mpMem;
1133 : }
1134 :
1135 450488 : IBitmapDeviceDamageTrackerSharedPtr BitmapDevice::getDamageTracker() const
1136 : {
1137 450488 : return getDamageTracker_i();
1138 : }
1139 :
1140 0 : void BitmapDevice::setDamageTracker( const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
1141 : {
1142 0 : setDamageTracker_i(rDamage);
1143 0 : }
1144 :
1145 783655 : PaletteMemorySharedVector BitmapDevice::getPalette() const
1146 : {
1147 783655 : return mpImpl->mpPalette;
1148 : }
1149 :
1150 1063266 : bool BitmapDevice::isSharedBuffer( const BitmapDeviceSharedPtr& rOther ) const
1151 : {
1152 1063266 : return rOther.get()->getBuffer().get() == getBuffer().get();
1153 : }
1154 :
1155 14025 : void BitmapDevice::clear( Color fillColor )
1156 : {
1157 14025 : clear_i( fillColor, mpImpl->maBounds );
1158 14025 : }
1159 :
1160 240819 : void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt,
1161 : Color lineColor,
1162 : DrawMode drawMode )
1163 : {
1164 240819 : if( mpImpl->maBounds.isInside(rPt) )
1165 220258 : setPixel_i(rPt,lineColor,drawMode);
1166 240819 : }
1167 :
1168 295807 : void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt,
1169 : Color lineColor,
1170 : DrawMode drawMode,
1171 : const BitmapDeviceSharedPtr& rClip )
1172 : {
1173 295807 : if( !rClip )
1174 : {
1175 240789 : setPixel(rPt,lineColor,drawMode);
1176 536596 : return;
1177 : }
1178 :
1179 55018 : if( mpImpl->maBounds.isInside(rPt) )
1180 : {
1181 55018 : if( isCompatibleClipMask( rClip ) )
1182 55018 : setPixel_i(rPt,lineColor,drawMode,rClip);
1183 : else
1184 0 : getGenericRenderer()->setPixel( rPt, lineColor, drawMode, rClip );
1185 : }
1186 : }
1187 :
1188 82327657 : Color BitmapDevice::getPixel( const basegfx::B2IPoint& rPt )
1189 : {
1190 82327657 : if( mpImpl->maBounds.isInside(rPt) )
1191 82327657 : return getPixel_i(rPt);
1192 :
1193 0 : return Color();
1194 : }
1195 :
1196 6 : sal_uInt32 BitmapDevice::getPixelData( const basegfx::B2IPoint& rPt )
1197 : {
1198 6 : if( mpImpl->maBounds.isInside(rPt) )
1199 4 : return getPixelData_i(rPt);
1200 :
1201 2 : return 0;
1202 : }
1203 :
1204 565369 : void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1,
1205 : const basegfx::B2IPoint& rPt2,
1206 : Color lineColor,
1207 : DrawMode drawMode )
1208 : {
1209 : drawLine_i( rPt1,
1210 : rPt2,
1211 565369 : mpImpl->maBounds,
1212 : lineColor,
1213 1130738 : drawMode );
1214 565369 : }
1215 :
1216 572564 : void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1,
1217 : const basegfx::B2IPoint& rPt2,
1218 : Color lineColor,
1219 : DrawMode drawMode,
1220 : const BitmapDeviceSharedPtr& rClip )
1221 : {
1222 572564 : if( !rClip )
1223 : {
1224 565343 : drawLine(rPt1,rPt2,lineColor,drawMode);
1225 1137907 : return;
1226 : }
1227 :
1228 7221 : if( isCompatibleClipMask( rClip ) )
1229 : drawLine_i( rPt1,
1230 : rPt2,
1231 7221 : mpImpl->maBounds,
1232 : lineColor,
1233 : drawMode,
1234 14442 : rClip );
1235 : else
1236 : getGenericRenderer()->drawLine( rPt1, rPt2, lineColor,
1237 0 : drawMode, rClip );
1238 : }
1239 :
1240 163834 : void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly,
1241 : Color lineColor,
1242 : DrawMode drawMode )
1243 : {
1244 163834 : const sal_uInt32 numVertices( rPoly.count() );
1245 163834 : if( numVertices )
1246 : drawPolygon_i( rPoly,
1247 163834 : mpImpl->maBounds,
1248 327668 : lineColor, drawMode );
1249 163834 : }
1250 :
1251 165093 : void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly,
1252 : Color lineColor,
1253 : DrawMode drawMode,
1254 : const BitmapDeviceSharedPtr& rClip )
1255 : {
1256 165093 : if( !rClip )
1257 : {
1258 163817 : drawPolygon(rPoly,lineColor,drawMode);
1259 328910 : return;
1260 : }
1261 :
1262 1276 : const sal_uInt32 numVertices( rPoly.count() );
1263 1276 : if( numVertices )
1264 : {
1265 1276 : if( isCompatibleClipMask( rClip ) )
1266 : drawPolygon_i( rPoly,
1267 1276 : mpImpl->maBounds,
1268 2552 : lineColor, drawMode, rClip );
1269 : else
1270 : getGenericRenderer()->drawPolygon( rPoly, lineColor,
1271 0 : drawMode, rClip );
1272 : }
1273 : }
1274 :
1275 2104082 : void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
1276 : Color fillColor,
1277 : DrawMode drawMode )
1278 : {
1279 2104082 : fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds );
1280 2104082 : }
1281 :
1282 2093820 : void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
1283 : Color fillColor,
1284 : DrawMode drawMode,
1285 : const BitmapDeviceSharedPtr& rClip )
1286 : {
1287 2093820 : if( !rClip )
1288 : {
1289 2041979 : fillPolyPolygon(rPoly,fillColor,drawMode);
1290 4135799 : return;
1291 : }
1292 :
1293 51841 : if( isCompatibleClipMask( rClip ) )
1294 51841 : fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds, rClip );
1295 : else
1296 : getGenericRenderer()->fillPolyPolygon( rPoly, fillColor,
1297 0 : drawMode, rClip );
1298 : }
1299 :
1300 :
1301 : namespace
1302 : {
1303 717489 : void assertImagePoint( const basegfx::B2IPoint& rPt,
1304 : const basegfx::B2IBox& rPermittedRange )
1305 : {
1306 : (void)rPt; (void)rPermittedRange;
1307 : OSL_ASSERT( rPermittedRange.isInside(rPt) );
1308 717489 : }
1309 :
1310 1419407 : void assertImageRange( const basegfx::B2IBox& rRange,
1311 : const basegfx::B2IBox& rPermittedRange )
1312 : {
1313 : #if OSL_DEBUG_LEVEL > 0
1314 : basegfx::B2IBox aRange( rRange );
1315 : aRange.intersect( rPermittedRange );
1316 :
1317 : OSL_ASSERT( aRange == rRange );
1318 : #else
1319 : (void)rRange; (void)rPermittedRange;
1320 : #endif
1321 1419407 : }
1322 :
1323 : // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
1324 : // to basegfx, and use here!
1325 825828 : bool clipAreaImpl( ::basegfx::B2IBox& io_rSourceArea,
1326 : ::basegfx::B2IPoint& io_rDestPoint,
1327 : const ::basegfx::B2IBox& rSourceBounds,
1328 : const ::basegfx::B2IBox& rDestBounds )
1329 : {
1330 : const ::basegfx::B2IPoint aSourceTopLeft(
1331 825828 : io_rSourceArea.getMinimum() );
1332 :
1333 825828 : ::basegfx::B2IBox aLocalSourceArea( io_rSourceArea );
1334 :
1335 : // clip source area (which must be inside rSourceBounds)
1336 825828 : aLocalSourceArea.intersect( rSourceBounds );
1337 :
1338 825828 : if( aLocalSourceArea.isEmpty() )
1339 0 : return false;
1340 :
1341 : // calc relative new source area points (relative to orig
1342 : // source area)
1343 : const ::basegfx::B2IVector aUpperLeftOffset(
1344 1651656 : aLocalSourceArea.getMinimum()-aSourceTopLeft );
1345 : const ::basegfx::B2IVector aLowerRightOffset(
1346 1651656 : aLocalSourceArea.getMaximum()-aSourceTopLeft );
1347 :
1348 1651656 : ::basegfx::B2IBox aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
1349 2477484 : io_rDestPoint + aLowerRightOffset );
1350 :
1351 : // clip dest area (which must be inside rDestBounds)
1352 825828 : aLocalDestArea.intersect( rDestBounds );
1353 :
1354 825828 : if( aLocalDestArea.isEmpty() )
1355 108339 : return false;
1356 :
1357 : // calc relative new dest area points (relative to orig
1358 : // source area)
1359 : const ::basegfx::B2IVector aDestUpperLeftOffset(
1360 1434978 : aLocalDestArea.getMinimum()-io_rDestPoint );
1361 : const ::basegfx::B2IVector aDestLowerRightOffset(
1362 1434978 : aLocalDestArea.getMaximum()-io_rDestPoint );
1363 :
1364 1434978 : io_rSourceArea = ::basegfx::B2IBox( aSourceTopLeft + aDestUpperLeftOffset,
1365 2152467 : aSourceTopLeft + aDestLowerRightOffset );
1366 717489 : io_rDestPoint = aLocalDestArea.getMinimum();
1367 :
1368 1543317 : return true;
1369 : }
1370 :
1371 : // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
1372 : // to basegfx, and use here!
1373 351664 : bool clipAreaImpl( ::basegfx::B2IBox& io_rDestArea,
1374 : ::basegfx::B2IBox& io_rSourceArea,
1375 : const ::basegfx::B2IBox& rDestBounds,
1376 : const ::basegfx::B2IBox& rSourceBounds )
1377 : {
1378 : // extract inherent scale
1379 351664 : const double nScaleX( io_rDestArea.getWidth() / (double)io_rSourceArea.getWidth() );
1380 351664 : const double nScaleY( io_rDestArea.getHeight() / (double)io_rSourceArea.getHeight() );
1381 :
1382 : // extract range origins
1383 : const basegfx::B2IPoint aDestTopLeft(
1384 351664 : io_rDestArea.getMinimum() );
1385 : const ::basegfx::B2IPoint aSourceTopLeft(
1386 703328 : io_rSourceArea.getMinimum() );
1387 :
1388 351664 : ::basegfx::B2IBox aLocalSourceArea( io_rSourceArea );
1389 :
1390 : // clip source area (which must be inside rSourceBounds)
1391 351664 : aLocalSourceArea.intersect( rSourceBounds );
1392 :
1393 351664 : if( aLocalSourceArea.isEmpty() )
1394 8 : return false;
1395 :
1396 : // calc relative new source area points (relative to orig
1397 : // source area)
1398 : const ::basegfx::B2IVector aUpperLeftOffset(
1399 703312 : aLocalSourceArea.getMinimum()-aSourceTopLeft );
1400 : const ::basegfx::B2IVector aLowerRightOffset(
1401 703312 : aLocalSourceArea.getMaximum()-aSourceTopLeft );
1402 :
1403 703312 : ::basegfx::B2IBox aLocalDestArea( basegfx::fround(aDestTopLeft.getX() + nScaleX*aUpperLeftOffset.getX()),
1404 703312 : basegfx::fround(aDestTopLeft.getY() + nScaleY*aUpperLeftOffset.getY()),
1405 703312 : basegfx::fround(aDestTopLeft.getX() + nScaleX*aLowerRightOffset.getX()),
1406 2461592 : basegfx::fround(aDestTopLeft.getY() + nScaleY*aLowerRightOffset.getY()) );
1407 :
1408 : // clip dest area (which must be inside rDestBounds)
1409 351656 : aLocalDestArea.intersect( rDestBounds );
1410 :
1411 351656 : if( aLocalDestArea.isEmpty() )
1412 697 : return false;
1413 :
1414 : // calc relative new dest area points (relative to orig
1415 : // source area)
1416 : const ::basegfx::B2IVector aDestUpperLeftOffset(
1417 701918 : aLocalDestArea.getMinimum()-aDestTopLeft );
1418 : const ::basegfx::B2IVector aDestLowerRightOffset(
1419 701918 : aLocalDestArea.getMaximum()-aDestTopLeft );
1420 :
1421 701918 : io_rSourceArea = ::basegfx::B2IBox( basegfx::fround(aSourceTopLeft.getX() + aDestUpperLeftOffset.getX()/nScaleX),
1422 701918 : basegfx::fround(aSourceTopLeft.getY() + aDestUpperLeftOffset.getY()/nScaleY),
1423 701918 : basegfx::fround(aSourceTopLeft.getX() + aDestLowerRightOffset.getX()/nScaleX),
1424 2456713 : basegfx::fround(aSourceTopLeft.getY() + aDestLowerRightOffset.getY()/nScaleY) );
1425 350959 : io_rDestArea = aLocalDestArea;
1426 :
1427 : // final source area clip (chopping round-offs)
1428 350959 : io_rSourceArea.intersect( rSourceBounds );
1429 :
1430 350959 : if( io_rSourceArea.isEmpty() )
1431 0 : return false;
1432 :
1433 :
1434 702623 : return true;
1435 : }
1436 : }
1437 :
1438 345118 : void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1439 : const basegfx::B2IBox& rSrcRect,
1440 : const basegfx::B2IBox& rDstRect,
1441 : DrawMode drawMode )
1442 : {
1443 345118 : const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1444 345118 : const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1445 345118 : basegfx::B2IBox aSrcRange( rSrcRect );
1446 345118 : basegfx::B2IBox aDestRange( rDstRect );
1447 :
1448 345118 : if( clipAreaImpl( aDestRange,
1449 : aSrcRange,
1450 345118 : mpImpl->maBounds,
1451 345118 : aSrcBounds ))
1452 : {
1453 344413 : assertImageRange(aDestRange,mpImpl->maBounds);
1454 344413 : assertImageRange(aSrcRange,aSrcBounds);
1455 :
1456 344413 : drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode );
1457 345118 : }
1458 345118 : }
1459 :
1460 133669 : void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1461 : const basegfx::B2IBox& rSrcRect,
1462 : const basegfx::B2IBox& rDstRect,
1463 : DrawMode drawMode,
1464 : const BitmapDeviceSharedPtr& rClip )
1465 : {
1466 133669 : if( !rClip )
1467 : {
1468 132307 : drawBitmap(rSrcBitmap,rSrcRect,rDstRect,drawMode);
1469 265976 : return;
1470 : }
1471 :
1472 1362 : const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1473 1362 : const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1474 1362 : basegfx::B2IBox aSrcRange( rSrcRect );
1475 1362 : basegfx::B2IBox aDestRange( rDstRect );
1476 :
1477 1362 : if( clipAreaImpl( aDestRange,
1478 : aSrcRange,
1479 1362 : mpImpl->maBounds,
1480 1362 : aSrcBounds ))
1481 : {
1482 1362 : assertImageRange(aDestRange,mpImpl->maBounds);
1483 1362 : assertImageRange(aSrcRange,aSrcBounds);
1484 :
1485 1362 : if( isCompatibleClipMask( rClip ) )
1486 : {
1487 1362 : drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode, rClip );
1488 : }
1489 : else
1490 : {
1491 : getGenericRenderer()->drawBitmap( rSrcBitmap, rSrcRect,
1492 0 : rDstRect, drawMode, rClip );
1493 : }
1494 1362 : }
1495 : }
1496 :
1497 824719 : void BitmapDevice::drawMaskedColor( Color aSrcColor,
1498 : const BitmapDeviceSharedPtr& rAlphaMask,
1499 : const basegfx::B2IBox& rSrcRect,
1500 : const basegfx::B2IPoint& rDstPoint )
1501 : {
1502 824719 : const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
1503 824719 : const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1504 824719 : basegfx::B2IBox aSrcRange( rSrcRect );
1505 1649438 : basegfx::B2IPoint aDestPoint( rDstPoint );
1506 :
1507 824719 : if( clipAreaImpl( aSrcRange,
1508 : aDestPoint,
1509 : aSrcBounds,
1510 824719 : mpImpl->maBounds ))
1511 : {
1512 716380 : assertImagePoint(aDestPoint,mpImpl->maBounds);
1513 716380 : assertImageRange(aSrcRange,aSrcBounds);
1514 :
1515 716380 : if( isSharedBuffer(rAlphaMask) )
1516 : {
1517 : // src == dest, copy rAlphaMask beforehand
1518 : // ---------------------------------------------------
1519 :
1520 0 : const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
1521 0 : aSrcRange.getHeight() );
1522 : BitmapDeviceSharedPtr pAlphaCopy(
1523 : cloneBitmapDevice( aSize,
1524 0 : shared_from_this()) );
1525 0 : basegfx::B2ITuple aGcc3WorkaroundTemporary;
1526 : const basegfx::B2IBox aAlphaRange( aGcc3WorkaroundTemporary,
1527 0 : aSize );
1528 : pAlphaCopy->drawBitmap(rAlphaMask,
1529 : aSrcRange,
1530 : aAlphaRange,
1531 0 : DrawMode_PAINT);
1532 0 : drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint );
1533 : }
1534 : else
1535 : {
1536 716380 : drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint );
1537 : }
1538 824719 : }
1539 824719 : }
1540 :
1541 825820 : void BitmapDevice::drawMaskedColor( Color aSrcColor,
1542 : const BitmapDeviceSharedPtr& rAlphaMask,
1543 : const basegfx::B2IBox& rSrcRect,
1544 : const basegfx::B2IPoint& rDstPoint,
1545 : const BitmapDeviceSharedPtr& rClip )
1546 : {
1547 825820 : if( !rClip )
1548 : {
1549 824711 : drawMaskedColor(aSrcColor,rAlphaMask,rSrcRect,rDstPoint);
1550 1650531 : return;
1551 : }
1552 :
1553 1109 : const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
1554 1109 : const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1555 1109 : basegfx::B2IBox aSrcRange( rSrcRect );
1556 2218 : basegfx::B2IPoint aDestPoint( rDstPoint );
1557 :
1558 1109 : if( clipAreaImpl( aSrcRange,
1559 : aDestPoint,
1560 : aSrcBounds,
1561 1109 : mpImpl->maBounds ))
1562 : {
1563 1109 : assertImagePoint(aDestPoint,mpImpl->maBounds);
1564 1109 : assertImageRange(aSrcRange,aSrcBounds);
1565 :
1566 1109 : if( isCompatibleClipMask( rClip ) )
1567 : {
1568 1109 : if( isSharedBuffer(rAlphaMask) )
1569 : {
1570 : // src == dest, copy rAlphaMask beforehand
1571 : // ---------------------------------------------------
1572 :
1573 0 : const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
1574 0 : aSrcRange.getHeight() );
1575 : BitmapDeviceSharedPtr pAlphaCopy(
1576 : cloneBitmapDevice( aSize,
1577 0 : shared_from_this()) );
1578 0 : basegfx::B2ITuple aGcc3WorkaroundTemporary;
1579 : const basegfx::B2IBox aAlphaRange( aGcc3WorkaroundTemporary,
1580 0 : aSize );
1581 : pAlphaCopy->drawBitmap(rAlphaMask,
1582 : aSrcRange,
1583 : aAlphaRange,
1584 0 : DrawMode_PAINT);
1585 0 : drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint, rClip );
1586 : }
1587 : else
1588 : {
1589 1109 : drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint, rClip );
1590 : }
1591 : }
1592 : else
1593 : {
1594 : getGenericRenderer()->drawMaskedColor( aSrcColor, rAlphaMask,
1595 0 : rSrcRect, rDstPoint, rClip );
1596 : }
1597 1109 : }
1598 : }
1599 :
1600 5184 : void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1601 : const BitmapDeviceSharedPtr& rMask,
1602 : const basegfx::B2IBox& rSrcRect,
1603 : const basegfx::B2IBox& rDstRect,
1604 : DrawMode drawMode )
1605 : {
1606 : OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
1607 :
1608 5184 : const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1609 5184 : const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1610 5184 : basegfx::B2IBox aSrcRange( rSrcRect );
1611 5184 : basegfx::B2IBox aDestRange( rDstRect );
1612 :
1613 5184 : if( clipAreaImpl( aDestRange,
1614 : aSrcRange,
1615 5184 : mpImpl->maBounds,
1616 5184 : aSrcBounds ))
1617 : {
1618 5184 : assertImageRange(aDestRange,mpImpl->maBounds);
1619 5184 : assertImageRange(aSrcRange,aSrcBounds);
1620 :
1621 5184 : drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode );
1622 5184 : }
1623 5184 : }
1624 :
1625 5180 : void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1626 : const BitmapDeviceSharedPtr& rMask,
1627 : const basegfx::B2IBox& rSrcRect,
1628 : const basegfx::B2IBox& rDstRect,
1629 : DrawMode drawMode,
1630 : const BitmapDeviceSharedPtr& rClip )
1631 : {
1632 5180 : if( !rClip )
1633 : {
1634 5180 : drawMaskedBitmap(rSrcBitmap,rMask,rSrcRect,rDstRect,drawMode);
1635 10360 : return;
1636 : }
1637 :
1638 : OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
1639 :
1640 0 : const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1641 0 : const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1642 0 : basegfx::B2IBox aSrcRange( rSrcRect );
1643 0 : basegfx::B2IBox aDestRange( rDstRect );
1644 :
1645 0 : if( clipAreaImpl( aDestRange,
1646 : aSrcRange,
1647 0 : mpImpl->maBounds,
1648 0 : aSrcBounds ))
1649 : {
1650 0 : assertImageRange(aDestRange,mpImpl->maBounds);
1651 0 : assertImageRange(aSrcRange,aSrcBounds);
1652 :
1653 0 : if( isCompatibleClipMask( rClip ) )
1654 : {
1655 0 : drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode, rClip );
1656 : }
1657 : else
1658 : {
1659 : getGenericRenderer()->drawMaskedBitmap( rSrcBitmap, rMask, rSrcRect,
1660 0 : rDstRect, drawMode, rClip );
1661 : }
1662 0 : }
1663 : }
1664 :
1665 :
1666 : //----------------------------------------------------------------------------------
1667 :
1668 : /** Standard clip and alpha masks
1669 : */
1670 : struct StdMasks
1671 : {
1672 : typedef PixelFormatTraits_GREY1_MSB clipmask_format_traits;
1673 : typedef PixelFormatTraits_GREY8 alphamask_format_traits;
1674 :
1675 : /// Clipmask: 0 means opaque
1676 : static const bool clipmask_polarity = false;
1677 :
1678 : /// Alpha mask: 0 means fully transparent
1679 : static const bool alphamask_polarity = true;
1680 : };
1681 :
1682 : //----------------------------------------------------------------------------------
1683 :
1684 : // Some compilers don't like the nested template wrap_accessor
1685 : // reference in the parameter list - being slightly less type safe,
1686 : // then.
1687 : #ifndef BASEBMP_NO_NESTED_TEMPLATE_PARAMETER
1688 :
1689 : /// Produces a specialized renderer for the given pixel format
1690 : template< class FormatTraits, class MaskTraits >
1691 1533564 : BitmapDeviceSharedPtr createRenderer(
1692 : const basegfx::B2IBox& rBounds,
1693 : const basegfx::B2IVector& rBufferSize,
1694 : sal_Int32 nScanlineFormat,
1695 : sal_Int32 nScanlineStride,
1696 : sal_uInt8* pFirstScanline,
1697 : typename FormatTraits::raw_accessor_type const& rRawAccessor,
1698 : typename FormatTraits::accessor_selector::template wrap_accessor<
1699 : typename FormatTraits::raw_accessor_type>::type const& rAccessor,
1700 : boost::shared_array< sal_uInt8 > pMem,
1701 : const PaletteMemorySharedVector& pPal,
1702 : const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1703 : #else
1704 :
1705 : template< class FormatTraits, class MaskTraits, class Accessor >
1706 : BitmapDeviceSharedPtr createRenderer(
1707 : const basegfx::B2IBox& rBounds,
1708 : const basegfx::B2IVector& rBufferSize,
1709 : sal_Int32 nScanlineFormat,
1710 : sal_Int32 nScanlineStride,
1711 : sal_uInt8* pFirstScanline,
1712 : typename FormatTraits::raw_accessor_type const& rRawAccessor,
1713 : Accessor const& rAccessor,
1714 : boost::shared_array< sal_uInt8 > pMem,
1715 : const PaletteMemorySharedVector& pPal,
1716 : const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1717 :
1718 : #endif
1719 : {
1720 : typedef typename FormatTraits::iterator_type Iterator;
1721 : typedef BitmapRenderer< Iterator,
1722 : typename FormatTraits::raw_accessor_type,
1723 : typename FormatTraits::accessor_selector,
1724 : MaskTraits > Renderer;
1725 :
1726 : return BitmapDeviceSharedPtr(
1727 : new Renderer( rBounds,
1728 : rBufferSize,
1729 : nScanlineFormat,
1730 : nScanlineStride,
1731 : pFirstScanline,
1732 : Iterator(
1733 : reinterpret_cast<typename Iterator::value_type*>(
1734 : pFirstScanline),
1735 : nScanlineStride),
1736 : rRawAccessor,
1737 : rAccessor,
1738 : pMem,
1739 : pPal,
1740 1533564 : pDamage ));
1741 : }
1742 :
1743 : /// Create standard grey level palette
1744 144814 : PaletteMemorySharedVector createStandardPalette(
1745 : const PaletteMemorySharedVector& pPal,
1746 : sal_Int32 nNumEntries )
1747 : {
1748 144814 : if( pPal || nNumEntries <= 0 )
1749 144778 : return pPal;
1750 :
1751 : boost::shared_ptr< std::vector<Color> > pLocalPal(
1752 36 : new std::vector<Color>(nNumEntries) );
1753 :
1754 36 : const sal_Int32 nIncrement( 0x00FFFFFF/nNumEntries );
1755 36 : --nNumEntries;
1756 72 : for( sal_Int32 i=0, c=0; i<nNumEntries; ++i,c+=nIncrement )
1757 36 : pLocalPal->at(i) = Color(0xFF000000 | c);
1758 :
1759 36 : pLocalPal->at(nNumEntries) = Color(0xFFFFFFFF);
1760 :
1761 36 : return pLocalPal;
1762 : }
1763 :
1764 : template< class FormatTraits, class MaskTraits >
1765 1388750 : BitmapDeviceSharedPtr createRenderer(
1766 : const basegfx::B2IBox& rBounds,
1767 : const basegfx::B2IVector& rBufferSize,
1768 : sal_Int32 nScanlineFormat,
1769 : sal_Int32 nScanlineStride,
1770 : sal_uInt8* pFirstScanline,
1771 : boost::shared_array< sal_uInt8 > pMem,
1772 : const PaletteMemorySharedVector& pPal,
1773 : const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1774 : {
1775 : return createRenderer<FormatTraits,
1776 : MaskTraits>(rBounds,
1777 : rBufferSize,
1778 : nScanlineFormat,
1779 : nScanlineStride,
1780 : pFirstScanline,
1781 : typename FormatTraits::raw_accessor_type(),
1782 : typename FormatTraits::accessor_selector::template
1783 : wrap_accessor<
1784 : typename FormatTraits::raw_accessor_type>::type(),
1785 : pMem,
1786 : pPal,
1787 1388750 : pDamage);
1788 : }
1789 :
1790 : template< class FormatTraits, class MaskTraits >
1791 144814 : BitmapDeviceSharedPtr createRenderer(
1792 : const basegfx::B2IBox& rBounds,
1793 : const basegfx::B2IVector& rBufferSize,
1794 : sal_Int32 nScanlineFormat,
1795 : sal_Int32 nScanlineStride,
1796 : sal_uInt8* pFirstScanline,
1797 : boost::shared_array< sal_uInt8 > pMem,
1798 : PaletteMemorySharedVector pPal,
1799 : int nBitsPerPixel,
1800 : const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1801 : {
1802 144814 : pPal = createStandardPalette(pPal,
1803 : 1UL << nBitsPerPixel);
1804 :
1805 : OSL_ASSERT(pPal);
1806 : return createRenderer<FormatTraits,
1807 : MaskTraits>(rBounds,
1808 : rBufferSize,
1809 : nScanlineFormat,
1810 : nScanlineStride,
1811 : pFirstScanline,
1812 : typename FormatTraits::raw_accessor_type(),
1813 : typename FormatTraits::accessor_selector::template
1814 : wrap_accessor<
1815 : typename FormatTraits::raw_accessor_type>::type(
1816 144814 : &pPal->at(0),
1817 : pPal->size()),
1818 : pMem,
1819 : pPal,
1820 289628 : pDamage);
1821 : }
1822 :
1823 : //----------------------------------------------------------------------------------
1824 :
1825 : // TODO(Q3): consolidate with canvas/canvastools.hxx! Best move this
1826 : // to o3tl or sal/bithacks.hxx ...
1827 :
1828 : /** Compute the next highest power of 2 of a 32-bit value
1829 :
1830 : Code devised by Sean Anderson, in good ole HAKMEM
1831 : tradition.
1832 :
1833 : @return 1 << (lg(x - 1) + 1)
1834 : */
1835 1533567 : inline sal_uInt32 nextPow2( sal_uInt32 x )
1836 : {
1837 1533567 : --x;
1838 1533567 : x |= x >> 1;
1839 1533567 : x |= x >> 2;
1840 1533567 : x |= x >> 4;
1841 1533567 : x |= x >> 8;
1842 1533567 : x |= x >> 16;
1843 :
1844 1533567 : return ++x;
1845 : }
1846 :
1847 : //----------------------------------------------------------------------------------
1848 :
1849 : namespace
1850 : {
1851 1533567 : BitmapDeviceSharedPtr createBitmapDeviceImplInner( const basegfx::B2IVector& rSize,
1852 : bool bTopDown,
1853 : sal_Int32 nScanlineFormat,
1854 : boost::shared_array< sal_uInt8 > pMem,
1855 : PaletteMemorySharedVector pPal,
1856 : const basegfx::B2IBox* pSubset,
1857 : const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
1858 : {
1859 : OSL_ASSERT(rSize.getX() > 0 && rSize.getY() > 0);
1860 :
1861 1533567 : if( nScanlineFormat <= Format::NONE ||
1862 : nScanlineFormat > Format::MAX )
1863 0 : return BitmapDeviceSharedPtr();
1864 :
1865 : static const sal_uInt8 bitsPerPixel[] =
1866 : {
1867 : 0, // NONE
1868 : 1, // ONE_BIT_MSB_GREY
1869 : 1, // ONE_BIT_LSB_GREY
1870 : 1, // ONE_BIT_MSB_PAL
1871 : 1, // ONE_BIT_LSB_PAL
1872 : 4, // FOUR_BIT_MSB_GREY
1873 : 4, // FOUR_BIT_LSB_GREY
1874 : 4, // FOUR_BIT_MSB_PAL
1875 : 4, // FOUR_BIT_LSB_PAL
1876 : 8, // EIGHT_BIT_PAL
1877 : 8, // EIGHT_BIT_GREY
1878 : 16, // SIXTEEN_BIT_LSB_TC_MASK
1879 : 16, // SIXTEEN_BIT_MSB_TC_MASK
1880 : 24, // TWENTYFOUR_BIT_TC_MASK
1881 : 32, // THIRTYTWO_BIT_TC_MASK_BGRA
1882 : 32, // THIRTYTWO_BIT_TC_MASK_ARGB
1883 : 32, // THIRTYTWO_BIT_TC_MASK_ABGR
1884 : 32, // THIRTYTWO_BIT_TC_MASK_RGBA
1885 : };
1886 :
1887 1533567 : sal_Int32 nScanlineStride(0);
1888 :
1889 : // round up to full 8 bit, divide by 8
1890 1533567 : nScanlineStride = (rSize.getX()*bitsPerPixel[nScanlineFormat] + 7) >> 3;
1891 :
1892 : // rounded up to next full power-of-two number of bytes
1893 : const sal_uInt32 bytesPerPixel = nextPow2(
1894 1533567 : (bitsPerPixel[nScanlineFormat] + 7) >> 3);
1895 :
1896 : // now make nScanlineStride a multiple of bytesPerPixel
1897 1533567 : nScanlineStride = (nScanlineStride + bytesPerPixel - 1) / bytesPerPixel * bytesPerPixel;
1898 :
1899 : // factor in bottom-up scanline order case
1900 1533567 : nScanlineStride *= bTopDown ? 1 : -1;
1901 :
1902 1533567 : const sal_uInt32 nWidth(nScanlineStride < 0 ? -nScanlineStride : nScanlineStride);
1903 1533567 : const sal_uInt32 nHeight(rSize.getY());
1904 :
1905 1533567 : if (nHeight && nWidth && nWidth > SAL_MAX_INT32 / nHeight)
1906 : {
1907 : SAL_WARN( "basebmp", "suspicious massive alloc " << nWidth << " * " << nHeight);
1908 3 : return BitmapDeviceSharedPtr();
1909 : }
1910 :
1911 1533564 : const std::size_t nMemSize(nWidth * nHeight);
1912 :
1913 1533564 : if( !pMem )
1914 : {
1915 : pMem.reset(
1916 421202 : reinterpret_cast<sal_uInt8*>(rtl_allocateMemory( nMemSize )),
1917 421202 : &rtl_freeMemory );
1918 421202 : if (pMem.get() == 0 && nMemSize != 0)
1919 0 : return BitmapDeviceSharedPtr();
1920 421202 : memset(pMem.get(), 0, nMemSize);
1921 : }
1922 :
1923 : sal_uInt8* pFirstScanline = nScanlineStride < 0 ?
1924 1533564 : pMem.get() + nMemSize + nScanlineStride : pMem.get();
1925 :
1926 : // shrink render area to given subset, if given
1927 1533564 : basegfx::B2IBox aBounds(0,0,rSize.getX(),rSize.getY());
1928 1533564 : if( pSubset )
1929 222489 : aBounds.intersect( *pSubset );
1930 :
1931 1533564 : switch( nScanlineFormat )
1932 : {
1933 : // ----------------------------------------------------------------------
1934 : // one bit formats
1935 :
1936 : case Format::ONE_BIT_MSB_GREY:
1937 : return createRenderer<PixelFormatTraits_GREY1_MSB,StdMasks>(
1938 : aBounds, rSize, nScanlineFormat, nScanlineStride,
1939 13958 : pFirstScanline, pMem, pPal, rDamage );
1940 :
1941 : case Format::ONE_BIT_LSB_GREY:
1942 : return createRenderer<PixelFormatTraits_GREY1_LSB,StdMasks>(
1943 : aBounds, rSize, nScanlineFormat, nScanlineStride,
1944 3 : pFirstScanline, pMem, pPal, rDamage );
1945 :
1946 : case Format::ONE_BIT_MSB_PAL:
1947 : return createRenderer<PixelFormatTraits_PAL1_MSB,StdMasks>(
1948 : aBounds, rSize, nScanlineFormat, nScanlineStride,
1949 : pFirstScanline, pMem, pPal,
1950 15204 : bitsPerPixel[nScanlineFormat], rDamage );
1951 :
1952 : case Format::ONE_BIT_LSB_PAL:
1953 : return createRenderer<PixelFormatTraits_PAL1_LSB,StdMasks>(
1954 : aBounds, rSize, nScanlineFormat, nScanlineStride,
1955 : pFirstScanline, pMem, pPal,
1956 1 : bitsPerPixel[nScanlineFormat], rDamage );
1957 :
1958 :
1959 : // ----------------------------------------------------------------------
1960 : // four bit formats
1961 :
1962 : case Format::FOUR_BIT_MSB_GREY:
1963 : return createRenderer<PixelFormatTraits_GREY4_MSB,StdMasks>(
1964 : aBounds, rSize, nScanlineFormat, nScanlineStride,
1965 0 : pFirstScanline, pMem, pPal, rDamage );
1966 :
1967 : case Format::FOUR_BIT_LSB_GREY:
1968 : return createRenderer<PixelFormatTraits_GREY4_LSB,StdMasks>(
1969 : aBounds, rSize, nScanlineFormat, nScanlineStride,
1970 0 : pFirstScanline, pMem, pPal, rDamage );
1971 :
1972 : case Format::FOUR_BIT_MSB_PAL:
1973 : return createRenderer<PixelFormatTraits_PAL4_MSB,StdMasks>(
1974 : aBounds, rSize, nScanlineFormat, nScanlineStride,
1975 : pFirstScanline, pMem, pPal,
1976 350 : bitsPerPixel[nScanlineFormat], rDamage );
1977 :
1978 : case Format::FOUR_BIT_LSB_PAL:
1979 : return createRenderer<PixelFormatTraits_PAL4_LSB,StdMasks>(
1980 : aBounds, rSize, nScanlineFormat, nScanlineStride,
1981 : pFirstScanline, pMem, pPal,
1982 0 : bitsPerPixel[nScanlineFormat], rDamage );
1983 :
1984 :
1985 : // ----------------------------------------------------------------------
1986 : // eight bit formats
1987 :
1988 : case Format::EIGHT_BIT_GREY:
1989 : return createRenderer<PixelFormatTraits_GREY8,StdMasks>(
1990 : aBounds, rSize, nScanlineFormat, nScanlineStride,
1991 825820 : pFirstScanline, pMem, pPal, rDamage );
1992 :
1993 : case Format::EIGHT_BIT_PAL:
1994 : return createRenderer<PixelFormatTraits_PAL8,StdMasks>(
1995 : aBounds, rSize, nScanlineFormat, nScanlineStride,
1996 : pFirstScanline, pMem, pPal,
1997 129259 : bitsPerPixel[nScanlineFormat], rDamage );
1998 :
1999 :
2000 : // ----------------------------------------------------------------------
2001 : // sixteen bit formats
2002 :
2003 : case Format::SIXTEEN_BIT_LSB_TC_MASK:
2004 : return createRenderer<PixelFormatTraits_RGB16_565_LSB,StdMasks>(
2005 : aBounds, rSize, nScanlineFormat, nScanlineStride,
2006 1 : pFirstScanline, pMem, pPal, rDamage );
2007 :
2008 : case Format::SIXTEEN_BIT_MSB_TC_MASK:
2009 : return createRenderer<PixelFormatTraits_RGB16_565_MSB,StdMasks>(
2010 : aBounds, rSize, nScanlineFormat, nScanlineStride,
2011 0 : pFirstScanline, pMem, pPal, rDamage );
2012 :
2013 :
2014 : // ----------------------------------------------------------------------
2015 : // twentyfour bit formats
2016 : case Format::TWENTYFOUR_BIT_TC_MASK:
2017 : return createRenderer<PixelFormatTraits_BGR24,StdMasks>(
2018 : aBounds, rSize, nScanlineFormat, nScanlineStride,
2019 548932 : pFirstScanline, pMem, pPal, rDamage );
2020 :
2021 :
2022 : // ----------------------------------------------------------------------
2023 : // thirtytwo bit formats
2024 :
2025 : case Format::THIRTYTWO_BIT_TC_MASK_BGRA:
2026 : return createRenderer<PixelFormatTraits_BGRX32_8888,StdMasks>(
2027 : aBounds, rSize, nScanlineFormat, nScanlineStride,
2028 36 : pFirstScanline, pMem, pPal, rDamage );
2029 :
2030 : case Format::THIRTYTWO_BIT_TC_MASK_ARGB:
2031 : return createRenderer<PixelFormatTraits_XRGB32_8888,StdMasks>(
2032 : aBounds, rSize, nScanlineFormat, nScanlineStride,
2033 0 : pFirstScanline, pMem, pPal, rDamage );
2034 :
2035 : case Format::THIRTYTWO_BIT_TC_MASK_ABGR:
2036 : return createRenderer<PixelFormatTraits_XBGR32_8888,StdMasks>(
2037 : aBounds, rSize, nScanlineFormat, nScanlineStride,
2038 0 : pFirstScanline, pMem, pPal, rDamage );
2039 :
2040 : case Format::THIRTYTWO_BIT_TC_MASK_RGBA:
2041 : return createRenderer<PixelFormatTraits_RGBX32_8888,StdMasks>(
2042 : aBounds, rSize, nScanlineFormat, nScanlineStride,
2043 0 : pFirstScanline, pMem, pPal, rDamage );
2044 : }
2045 :
2046 : // TODO(F3): other formats not yet implemented
2047 0 : return BitmapDeviceSharedPtr();
2048 : }
2049 :
2050 1533567 : BitmapDeviceSharedPtr createBitmapDeviceImpl( const basegfx::B2IVector& rSize,
2051 : bool bTopDown,
2052 : sal_Int32 nScanlineFormat,
2053 : boost::shared_array< sal_uInt8 > pMem,
2054 : PaletteMemorySharedVector pPal,
2055 : const basegfx::B2IBox* pSubset,
2056 : const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
2057 : {
2058 1533567 : BitmapDeviceSharedPtr result( createBitmapDeviceImplInner( rSize, bTopDown, nScanlineFormat, pMem, pPal, pSubset, rDamage ) );
2059 :
2060 : #ifdef SAL_LOG_INFO
2061 : std::ostringstream subset;
2062 :
2063 : if (pSubset)
2064 : subset << " subset=" << pSubset->getWidth() << "x" << pSubset->getHeight() << "@(" << pSubset->getMinX() << "," << pSubset->getMinY() << ")";
2065 :
2066 : SAL_INFO( "basebmp.bitmapdevice",
2067 : "createBitmapDevice: "
2068 : << rSize.getX() << "x" << rSize.getY()
2069 : << (bTopDown ? " top-down " : " bottom-up ")
2070 : << Format::formatName(nScanlineFormat)
2071 : << subset.str()
2072 : << " = " << result.get() );
2073 : #endif
2074 1533567 : return result;
2075 : }
2076 : } // namespace
2077 :
2078 :
2079 133988 : BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2080 : bool bTopDown,
2081 : sal_Int32 nScanlineFormat )
2082 : {
2083 : return createBitmapDeviceImpl( rSize,
2084 : bTopDown,
2085 : nScanlineFormat,
2086 : boost::shared_array< sal_uInt8 >(),
2087 : PaletteMemorySharedVector(),
2088 : NULL,
2089 133988 : IBitmapDeviceDamageTrackerSharedPtr() );
2090 : }
2091 :
2092 7187 : BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2093 : bool bTopDown,
2094 : sal_Int32 nScanlineFormat,
2095 : const PaletteMemorySharedVector& rPalette )
2096 : {
2097 : return createBitmapDeviceImpl( rSize,
2098 : bTopDown,
2099 : nScanlineFormat,
2100 : boost::shared_array< sal_uInt8 >(),
2101 : rPalette,
2102 : NULL,
2103 7187 : IBitmapDeviceDamageTrackerSharedPtr() );
2104 : }
2105 :
2106 941904 : BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2107 : bool bTopDown,
2108 : sal_Int32 nScanlineFormat,
2109 : const RawMemorySharedArray& rMem,
2110 : const PaletteMemorySharedVector& rPalette )
2111 : {
2112 : return createBitmapDeviceImpl( rSize,
2113 : bTopDown,
2114 : nScanlineFormat,
2115 : rMem,
2116 : rPalette,
2117 : NULL,
2118 941904 : IBitmapDeviceDamageTrackerSharedPtr() );
2119 : }
2120 :
2121 222489 : BitmapDeviceSharedPtr subsetBitmapDevice( const BitmapDeviceSharedPtr& rProto,
2122 : const basegfx::B2IBox& rSubset )
2123 : {
2124 : SAL_INFO( "basebmp.bitmapdevice", "subsetBitmapDevice: proto=" << rProto.get() );
2125 : return createBitmapDeviceImpl( rProto->getSize(),
2126 222489 : rProto->isTopDown(),
2127 : rProto->getScanlineFormat(),
2128 : rProto->getBuffer(),
2129 : rProto->getPalette(),
2130 : &rSubset,
2131 444978 : rProto->getDamageTracker() );
2132 : }
2133 :
2134 227999 : BitmapDeviceSharedPtr cloneBitmapDevice( const basegfx::B2IVector& rSize,
2135 : const BitmapDeviceSharedPtr& rProto )
2136 : {
2137 : return createBitmapDeviceImpl( rSize,
2138 227999 : rProto->isTopDown(),
2139 : rProto->getScanlineFormat(),
2140 : boost::shared_array< sal_uInt8 >(),
2141 : rProto->getPalette(),
2142 : NULL,
2143 455998 : rProto->getDamageTracker() );
2144 : }
2145 :
2146 : //----------------------------------------------------------------------------------
2147 :
2148 : /// Clone our device, with GenericImageAccessor to handle all formats
2149 0 : BitmapDeviceSharedPtr BitmapDevice::getGenericRenderer() const
2150 : {
2151 0 : return mpImpl->mpGenericRenderer;
2152 : }
2153 :
2154 : } // namespace basebmp
2155 :
2156 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|