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 53060 : 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 : lhs[0] ^ rhs[0],
82 : lhs[1] ^ rhs[1],
83 53060 : lhs[2] ^ rhs[2]);
84 53060 : 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 28248 : 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 33214 : BitmapRenderer( const basegfx::B2IBox& rBounds,
286 : sal_Int32 nScanlineFormat,
287 : sal_Int32 nScanlineStride,
288 : sal_uInt8* pFirstScanline,
289 : dest_iterator_type begin,
290 : raw_accessor_type rawAccessor,
291 : dest_accessor_type accessor,
292 : const RawMemorySharedArray& rMem,
293 : const PaletteMemorySharedVector& rPalette,
294 : const IBitmapDeviceDamageTrackerSharedPtr& rDamage ) :
295 : BitmapDevice( rBounds, nScanlineFormat,
296 : nScanlineStride, pFirstScanline, rMem, rPalette ),
297 : maBegin( begin ),
298 : maColorLookup(),
299 : mpDamage(rDamage),
300 : maToUInt32Converter(),
301 : maAccessor( accessor ),
302 : maColorBlendAccessor( accessor ),
303 : maGenericColorBlendAccessor( accessor ),
304 : maRawAccessor( rawAccessor ),
305 : maXorAccessor( accessor ),
306 : maRawXorAccessor( rawAccessor ),
307 : maMaskedAccessor( accessor ),
308 : maMaskedColorBlendAccessor( maColorBlendAccessor ),
309 : maGenericMaskedColorBlendAccessor( maGenericColorBlendAccessor ),
310 : maMaskedXorAccessor( accessor ),
311 : maRawMaskedAccessor( rawAccessor ),
312 : maRawMaskedXorAccessor( rawAccessor ),
313 33214 : maRawMaskedMaskAccessor( rawAccessor )
314 33214 : {}
315 :
316 : private:
317 :
318 120166 : void damaged( const basegfx::B2IBox& rDamageRect ) const
319 : {
320 120166 : if( mpDamage )
321 0 : mpDamage->damaged( rDamageRect );
322 120166 : }
323 :
324 14993 : void damagedPointSize( const basegfx::B2IPoint& rPoint,
325 : const basegfx::B2IBox& rSize ) const
326 : {
327 14993 : if( mpDamage ) {
328 : basegfx::B2IPoint aLower( rPoint.getX() + rSize.getWidth(),
329 0 : rPoint.getY() + rSize.getHeight() );
330 0 : damaged( basegfx::B2IBox( rPoint, aLower ) );
331 : }
332 14993 : }
333 :
334 24915 : void damagedPixel( const basegfx::B2IPoint& rDamagePoint ) const
335 : {
336 24915 : if( !mpDamage )
337 24915 : return;
338 : basegfx::B2IPoint aEnd( rDamagePoint.getX() + 1,
339 0 : rDamagePoint.getY() + 1 );
340 0 : damaged( basegfx::B2IBox( rDamagePoint, aEnd ) );
341 : }
342 :
343 3886 : boost::shared_ptr<BitmapRenderer> getCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const
344 : {
345 3886 : return boost::dynamic_pointer_cast< BitmapRenderer >( bmp );
346 : }
347 :
348 1943 : virtual bool isCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const
349 : {
350 : // TODO(P1): dynamic_cast usually called twice for
351 : // compatible formats
352 1943 : return getCompatibleBitmap(bmp).get() != NULL;
353 : }
354 :
355 15105 : boost::shared_ptr<mask_bitmap_type> getCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const
356 : {
357 15105 : boost::shared_ptr<mask_bitmap_type> pMask( boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ));
358 :
359 15105 : if( !pMask )
360 14992 : return pMask;
361 :
362 113 : if( pMask->getSize() != getSize() )
363 1 : pMask.reset();
364 :
365 113 : return pMask;
366 : }
367 :
368 116 : virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const
369 : {
370 : // TODO(P1): dynamic_cast usually called twice for
371 : // compatible formats
372 116 : return boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ).get() != NULL;
373 : }
374 :
375 14993 : boost::shared_ptr<alphamask_bitmap_type> getCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const
376 : {
377 14993 : return boost::dynamic_pointer_cast<alphamask_bitmap_type>( bmp );
378 : }
379 :
380 0 : virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const
381 : {
382 : // TODO(P1): dynamic_cast usually called twice for
383 : // compatible formats
384 0 : return getCompatibleAlphaMask( bmp ).get() != NULL;
385 : }
386 :
387 84 : virtual void clear_i( Color fillColor,
388 : const basegfx::B2IBox& rBounds )
389 : {
390 84 : fillImage(destIterRange(maBegin,
391 : maRawAccessor,
392 : rBounds),
393 : maColorLookup(
394 : maAccessor,
395 : fillColor) );
396 84 : damaged( rBounds );
397 84 : }
398 :
399 24907 : virtual void setPixel_i( const basegfx::B2IPoint& rPt,
400 : Color pixelColor,
401 : DrawMode drawMode )
402 : {
403 : const DestIterator pixel( maBegin +
404 : vigra::Diff2D(rPt.getX(),
405 24907 : rPt.getY()) );
406 24907 : if( drawMode == DrawMode_XOR )
407 0 : maXorAccessor.set( pixelColor,
408 : pixel );
409 : else
410 24907 : maAccessor.set( pixelColor,
411 : pixel );
412 24907 : damagedPixel(rPt);
413 24907 : }
414 :
415 8 : virtual void setPixel_i( const basegfx::B2IPoint& rPt,
416 : Color pixelColor,
417 : DrawMode drawMode,
418 : const BitmapDeviceSharedPtr& rClip )
419 : {
420 8 : boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
421 : OSL_ASSERT( pMask );
422 :
423 : const vigra::Diff2D offset(rPt.getX(),
424 8 : rPt.getY());
425 :
426 : const composite_iterator_type aIter(
427 : maBegin + offset,
428 8 : pMask->maBegin + offset );
429 :
430 8 : if( drawMode == DrawMode_XOR )
431 0 : maMaskedXorAccessor.set( pixelColor,
432 : aIter );
433 : else
434 8 : maMaskedAccessor.set( pixelColor,
435 : aIter );
436 8 : damagedPixel(rPt);
437 8 : }
438 :
439 280731 : virtual Color getPixel_i(const basegfx::B2IPoint& rPt )
440 : {
441 : const DestIterator pixel( maBegin +
442 : vigra::Diff2D(rPt.getX(),
443 280731 : rPt.getY()) );
444 280731 : return maAccessor(pixel);
445 : }
446 :
447 4 : virtual sal_uInt32 getPixelData_i( const basegfx::B2IPoint& rPt )
448 : {
449 : const DestIterator pixel( maBegin +
450 : vigra::Diff2D(rPt.getX(),
451 4 : rPt.getY()) );
452 4 : return maToUInt32Converter(maRawAccessor(pixel));
453 : }
454 :
455 : template< typename Iterator, typename Col, typename RawAcc >
456 116188 : void implRenderLine2( const basegfx::B2IPoint& rPt1,
457 : const basegfx::B2IPoint& rPt2,
458 : const basegfx::B2IBox& rBounds,
459 : Col col,
460 : const Iterator& begin,
461 : const RawAcc& rawAcc )
462 : {
463 116188 : renderClippedLine( rPt1,
464 : rPt2,
465 : rBounds,
466 : col,
467 : begin,
468 : rawAcc );
469 : // TODO(P2): perhaps this needs pushing up the stack a bit
470 : // to make more complex polygons more efficient ...
471 116188 : damaged( basegfx::B2IBox( rPt1, rPt2 ) );
472 116188 : }
473 :
474 : template< typename Iterator, typename Accessor, typename RawAcc >
475 101180 : void implRenderLine( const basegfx::B2IPoint& rPt1,
476 : const basegfx::B2IPoint& rPt2,
477 : const basegfx::B2IBox& rBounds,
478 : Color col,
479 : const Iterator& begin,
480 : const Accessor& acc,
481 : const RawAcc& rawAcc )
482 : {
483 101180 : implRenderLine2( rPt1,rPt2,rBounds,
484 : maColorLookup( acc,
485 : col ),
486 : begin,
487 : rawAcc );
488 101180 : }
489 :
490 : template< typename Iterator, typename RawAcc, typename XorAcc >
491 101180 : void implDrawLine( const basegfx::B2IPoint& rPt1,
492 : const basegfx::B2IPoint& rPt2,
493 : const basegfx::B2IBox& rBounds,
494 : Color col,
495 : const Iterator& begin,
496 : const RawAcc& rawAcc,
497 : const XorAcc& xorAcc,
498 : DrawMode drawMode )
499 : {
500 101180 : if( drawMode == DrawMode_XOR )
501 8 : implRenderLine( rPt1, rPt2, rBounds, col,
502 : begin, maAccessor, xorAcc );
503 : else
504 101172 : implRenderLine( rPt1, rPt2, rBounds, col,
505 : begin, maAccessor, rawAcc );
506 101180 : }
507 :
508 101176 : virtual void drawLine_i(const basegfx::B2IPoint& rPt1,
509 : const basegfx::B2IPoint& rPt2,
510 : const basegfx::B2IBox& rBounds,
511 : Color lineColor,
512 : DrawMode drawMode )
513 : {
514 101176 : implDrawLine(rPt1,rPt2,rBounds,lineColor,
515 : maBegin,
516 : maRawAccessor,maRawXorAccessor,drawMode);
517 101176 : }
518 :
519 100 : composite_iterator_type getMaskedIter( const BitmapDeviceSharedPtr& rClip ) const
520 : {
521 100 : boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
522 : OSL_ASSERT( pMask );
523 :
524 : return composite_iterator_type( maBegin,
525 100 : pMask->maBegin );
526 : }
527 :
528 4 : virtual void drawLine_i(const basegfx::B2IPoint& rPt1,
529 : const basegfx::B2IPoint& rPt2,
530 : const basegfx::B2IBox& rBounds,
531 : Color lineColor,
532 : DrawMode drawMode,
533 : const BitmapDeviceSharedPtr& rClip )
534 : {
535 4 : implDrawLine(rPt1,rPt2,rBounds,lineColor,
536 : getMaskedIter(rClip),
537 : maRawMaskedAccessor,
538 : maRawMaskedXorAccessor,drawMode);
539 4 : }
540 :
541 : template< typename Iterator, typename RawAcc >
542 2941 : void implDrawPolygon( const basegfx::B2DPolygon& rPoly,
543 : const basegfx::B2IBox& rBounds,
544 : Color col,
545 : const Iterator& begin,
546 : const RawAcc& acc )
547 : {
548 2941 : basegfx::B2DPolygon aPoly( rPoly );
549 2941 : if( rPoly.areControlPointsUsed() )
550 0 : aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
551 :
552 : const typename dest_iterator_type::value_type colorIndex( maColorLookup(
553 : maAccessor,
554 2941 : col));
555 2941 : const sal_uInt32 nVertices( aPoly.count() );
556 17941 : for( sal_uInt32 i=1; i<nVertices; ++i )
557 15000 : implRenderLine2( basegfx::fround(aPoly.getB2DPoint(i-1)),
558 : basegfx::fround(aPoly.getB2DPoint(i)),
559 : rBounds,
560 : colorIndex,
561 : begin,
562 : acc );
563 :
564 2941 : if( nVertices > 1 && aPoly.isClosed() )
565 8 : implRenderLine2( basegfx::fround(aPoly.getB2DPoint(nVertices-1)),
566 : basegfx::fround(aPoly.getB2DPoint(0)),
567 : rBounds,
568 : colorIndex,
569 : begin,
570 : acc );
571 2941 : }
572 :
573 2941 : virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
574 : const basegfx::B2IBox& rBounds,
575 : Color lineColor,
576 : DrawMode drawMode )
577 : {
578 2941 : if( drawMode == DrawMode_XOR )
579 0 : implDrawPolygon( rPoly, rBounds, lineColor,
580 : maBegin,
581 : maRawXorAccessor );
582 : else
583 2941 : implDrawPolygon( rPoly, rBounds, lineColor,
584 : maBegin,
585 : maRawAccessor );
586 2941 : }
587 :
588 0 : virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
589 : const basegfx::B2IBox& rBounds,
590 : Color lineColor,
591 : DrawMode drawMode,
592 : const BitmapDeviceSharedPtr& rClip )
593 : {
594 0 : if( drawMode == DrawMode_XOR )
595 0 : implDrawPolygon( rPoly, rBounds, lineColor,
596 : getMaskedIter(rClip),
597 : maRawMaskedXorAccessor );
598 : else
599 0 : implDrawPolygon( rPoly, rBounds, lineColor,
600 : getMaskedIter(rClip),
601 : maRawMaskedAccessor );
602 0 : }
603 :
604 : template< typename Iterator, typename RawAcc >
605 78985 : void implFillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
606 : Color col,
607 : const Iterator& begin,
608 : const RawAcc& acc,
609 : const basegfx::B2IBox& rBounds )
610 : {
611 78985 : basegfx::B2DPolyPolygon aPoly( rPoly );
612 78985 : if( rPoly.areControlPointsUsed() )
613 0 : aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
614 :
615 78985 : renderClippedPolyPolygon( begin,
616 : acc,
617 : maColorLookup( maAccessor,
618 : col),
619 : rBounds,
620 : aPoly,
621 : basegfx::FillRule_EVEN_ODD );
622 :
623 78985 : if( mpDamage )
624 : {
625 0 : basegfx::B2DRange const aPolyBounds( basegfx::tools::getRange(aPoly) );
626 0 : damaged( basegfx::unotools::b2ISurroundingBoxFromB2DRange( aPolyBounds ) );
627 : }
628 78985 : }
629 :
630 78900 : virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
631 : Color fillColor,
632 : DrawMode drawMode,
633 : const basegfx::B2IBox& rBounds )
634 : {
635 78900 : if( drawMode == DrawMode_XOR )
636 1132 : implFillPolyPolygon( rPoly, fillColor,
637 : maBegin,
638 : maRawXorAccessor,
639 : rBounds );
640 : else
641 77768 : implFillPolyPolygon( rPoly, fillColor,
642 : maBegin,
643 : maRawAccessor,
644 : rBounds );
645 78900 : }
646 :
647 85 : virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
648 : Color fillColor,
649 : DrawMode drawMode,
650 : const basegfx::B2IBox& rBounds,
651 : const BitmapDeviceSharedPtr& rClip )
652 : {
653 85 : if( drawMode == DrawMode_XOR )
654 2 : implFillPolyPolygon( rPoly, fillColor,
655 : getMaskedIter(rClip),
656 : maRawMaskedXorAccessor,
657 : rBounds );
658 : else
659 83 : implFillPolyPolygon( rPoly, fillColor,
660 : getMaskedIter(rClip),
661 : maRawMaskedAccessor,
662 : rBounds );
663 85 : }
664 :
665 : template< typename Iterator, typename RawAcc >
666 1939 : void implDrawBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
667 : const basegfx::B2IBox& rSrcRect,
668 : const basegfx::B2IBox& rDstRect,
669 : const Iterator& begin,
670 : const RawAcc& acc)
671 : {
672 1939 : boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
673 : OSL_ASSERT( pSrcBmp );
674 :
675 1939 : scaleImage(
676 : srcIterRange(pSrcBmp->maBegin,
677 : pSrcBmp->maRawAccessor,
678 : rSrcRect),
679 : destIterRange(begin,
680 : acc,
681 : rDstRect),
682 : rSrcBitmap.get() == this );
683 1939 : damaged( rDstRect );
684 1939 : }
685 :
686 : template< typename Iterator, typename Acc >
687 0 : void implDrawBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
688 : const basegfx::B2IBox& rSrcRect,
689 : const basegfx::B2IBox& rDstRect,
690 : const Iterator& begin,
691 : const Acc& acc)
692 : {
693 0 : GenericColorImageAccessor aSrcAcc( rSrcBitmap );
694 :
695 0 : scaleImage(
696 : srcIterRange(vigra::Diff2D(),
697 : aSrcAcc,
698 : rSrcRect),
699 : destIterRange(begin,
700 : acc,
701 : rDstRect));
702 0 : damaged( rDstRect );
703 0 : }
704 :
705 1930 : virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
706 : const basegfx::B2IBox& rSrcRect,
707 : const basegfx::B2IBox& rDstRect,
708 : DrawMode drawMode )
709 : {
710 1930 : if( isCompatibleBitmap( rSrcBitmap ) )
711 : {
712 1930 : if( drawMode == DrawMode_XOR )
713 0 : implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
714 : maBegin,
715 : maRawXorAccessor);
716 : else
717 1930 : implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
718 : maBegin,
719 : maRawAccessor);
720 : }
721 : else
722 : {
723 0 : if( drawMode == DrawMode_XOR )
724 0 : implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
725 : maBegin,
726 : maXorAccessor);
727 : else
728 0 : implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
729 : maBegin,
730 : maAccessor);
731 : }
732 1930 : damaged( rDstRect );
733 1930 : }
734 :
735 9 : virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
736 : const basegfx::B2IBox& rSrcRect,
737 : const basegfx::B2IBox& rDstRect,
738 : DrawMode drawMode,
739 : const BitmapDeviceSharedPtr& rClip )
740 : {
741 9 : if( isCompatibleBitmap( rSrcBitmap ) )
742 : {
743 9 : if( drawMode == DrawMode_XOR )
744 0 : implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
745 : getMaskedIter(rClip),
746 : maRawMaskedXorAccessor);
747 : else
748 9 : implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
749 : getMaskedIter(rClip),
750 : maRawMaskedAccessor);
751 : }
752 : else
753 : {
754 0 : if( drawMode == DrawMode_XOR )
755 0 : implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
756 : getMaskedIter(rClip),
757 : maMaskedXorAccessor);
758 : else
759 0 : implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
760 : getMaskedIter(rClip),
761 : maMaskedAccessor);
762 : }
763 9 : damaged( rDstRect );
764 9 : }
765 :
766 14991 : virtual void drawMaskedColor_i(Color aSrcColor,
767 : const BitmapDeviceSharedPtr& rAlphaMask,
768 : const basegfx::B2IBox& rSrcRect,
769 : const basegfx::B2IPoint& rDstPoint )
770 : {
771 14991 : boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) );
772 14991 : boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
773 :
774 14991 : if( pAlpha )
775 : {
776 14990 : maColorBlendAccessor.setColor( aSrcColor );
777 :
778 14990 : vigra::copyImage( srcIterRange(pAlpha->maBegin,
779 : pAlpha->maRawAccessor,
780 : rSrcRect),
781 : destIter(maBegin,
782 : maColorBlendAccessor,
783 : rDstPoint) );
784 : }
785 1 : else if( pMask )
786 : {
787 : const composite_iterator_type aBegin(
788 : maBegin + vigra::Diff2D(rDstPoint.getX(),
789 : rDstPoint.getY()),
790 0 : pMask->maBegin + topLeft(rSrcRect) );
791 :
792 0 : fillImage(aBegin,
793 : aBegin + vigra::Diff2D(rSrcRect.getWidth(),
794 : rSrcRect.getHeight()),
795 : maRawMaskedAccessor,
796 : maColorLookup(
797 : maAccessor,
798 : aSrcColor) );
799 : }
800 : else
801 : {
802 1 : GenericColorImageAccessor aSrcAcc( rAlphaMask );
803 1 : maGenericColorBlendAccessor.setColor( aSrcColor );
804 :
805 1 : vigra::copyImage( srcIterRange(vigra::Diff2D(),
806 : aSrcAcc,
807 : rSrcRect),
808 : destIter(maBegin,
809 : maGenericColorBlendAccessor,
810 : rDstPoint) );
811 : }
812 14991 : damagedPointSize( rDstPoint, rSrcRect );
813 14991 : }
814 :
815 2 : virtual void drawMaskedColor_i(Color aSrcColor,
816 : const BitmapDeviceSharedPtr& rAlphaMask,
817 : const basegfx::B2IBox& rSrcRect,
818 : const basegfx::B2IPoint& rDstPoint,
819 : const BitmapDeviceSharedPtr& rClip )
820 : {
821 2 : boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) );
822 2 : boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
823 :
824 2 : if( pAlpha )
825 : {
826 2 : const composite_iterator_type aBegin( getMaskedIter(rClip) );
827 2 : maMaskedColorBlendAccessor.get1stWrappedAccessor().setColor(
828 : aSrcColor );
829 :
830 2 : vigra::copyImage( srcIterRange(pAlpha->maBegin,
831 : pAlpha->maRawAccessor,
832 : rSrcRect),
833 : destIter(aBegin,
834 : maMaskedColorBlendAccessor,
835 : rDstPoint) );
836 : }
837 0 : else if( pMask )
838 : {
839 0 : boost::shared_ptr<mask_bitmap_type> pClipMask( getCompatibleClipMask(rClip) );
840 : OSL_ASSERT( pClipMask );
841 :
842 : // setup a ((iter,mask),clipMask) composite composite
843 : // iterator, to pass both masks (clip and alpha mask)
844 : // to the algorithm
845 : const composite_composite_mask_iterator_type aBegin(
846 : composite_iterator_type(
847 : maBegin + vigra::Diff2D(rDstPoint.getX(),
848 : rDstPoint.getY()),
849 : pMask->maBegin + topLeft(rSrcRect)),
850 : pClipMask->maBegin + vigra::Diff2D(rDstPoint.getX(),
851 0 : rDstPoint.getY()) );
852 :
853 0 : fillImage(aBegin,
854 : aBegin + vigra::Diff2D(rSrcRect.getWidth(),
855 : rSrcRect.getHeight()),
856 : maRawMaskedMaskAccessor,
857 : maColorLookup(
858 : maAccessor,
859 : aSrcColor) );
860 : }
861 : else
862 : {
863 0 : GenericColorImageAccessor aSrcAcc( rAlphaMask );
864 0 : const composite_iterator_type aBegin( getMaskedIter(rClip) );
865 0 : maGenericMaskedColorBlendAccessor.get1stWrappedAccessor().setColor(
866 : aSrcColor );
867 :
868 0 : vigra::copyImage( srcIterRange(vigra::Diff2D(),
869 : aSrcAcc,
870 : rSrcRect),
871 : destIter(aBegin,
872 : maGenericMaskedColorBlendAccessor,
873 : rDstPoint) );
874 : }
875 2 : damagedPointSize( rDstPoint, rSrcRect );
876 2 : }
877 :
878 : template< typename Iterator, typename Acc >
879 4 : void implDrawMaskedBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
880 : const BitmapDeviceSharedPtr& rMask,
881 : const basegfx::B2IBox& rSrcRect,
882 : const basegfx::B2IBox& rDstRect,
883 : const Iterator& begin,
884 : const Acc& acc)
885 : {
886 4 : boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
887 4 : boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rMask) );
888 : OSL_ASSERT( pMask && pSrcBmp );
889 :
890 4 : scaleImage(
891 : srcIterRange(composite_iterator_type(
892 : pSrcBmp->maBegin,
893 : pMask->maBegin),
894 : joined_image_accessor_type(
895 : pSrcBmp->maAccessor,
896 : pMask->maRawAccessor),
897 : rSrcRect),
898 : destIterRange(begin,
899 : typename masked_input_splitting_accessor<
900 : Acc,
901 : joined_image_accessor_type,
902 : Masks::clipmask_polarity,
903 : FastMask >::type(acc),
904 : rDstRect),
905 : rSrcBitmap.get() == this);
906 4 : damaged( rDstRect );
907 4 : }
908 :
909 : template< typename Iterator, typename Acc >
910 4 : void implDrawMaskedBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
911 : const BitmapDeviceSharedPtr& rMask,
912 : const basegfx::B2IBox& rSrcRect,
913 : const basegfx::B2IBox& rDstRect,
914 : const Iterator& begin,
915 : const Acc& acc)
916 : {
917 4 : GenericColorImageAccessor aSrcAcc( rSrcBitmap );
918 4 : GenericColorImageAccessor aMaskAcc( rMask );
919 :
920 : const vigra::Diff2D aTopLeft(rSrcRect.getMinX(),
921 4 : rSrcRect.getMinY());
922 : const vigra::Diff2D aBottomRight(rSrcRect.getMaxX(),
923 4 : rSrcRect.getMaxY());
924 4 : scaleImage(
925 : vigra::make_triple(
926 : generic_composite_iterator_type(
927 : aTopLeft,aTopLeft),
928 : generic_composite_iterator_type(
929 : aBottomRight,aBottomRight),
930 : joined_generic_image_accessor_type(
931 : aSrcAcc,
932 : aMaskAcc)),
933 : destIterRange(begin,
934 : typename masked_input_splitting_accessor<
935 : Acc,
936 : joined_generic_image_accessor_type,
937 : Masks::clipmask_polarity,
938 : NoFastMask >::type(acc),
939 : rDstRect));
940 4 : damaged( rDstRect );
941 4 : }
942 :
943 8 : virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
944 : const BitmapDeviceSharedPtr& rMask,
945 : const basegfx::B2IBox& rSrcRect,
946 : const basegfx::B2IBox& rDstRect,
947 : DrawMode drawMode )
948 : {
949 8 : if( isCompatibleClipMask(rMask) &&
950 : isCompatibleBitmap(rSrcBitmap) )
951 : {
952 4 : if( drawMode == DrawMode_XOR )
953 0 : implDrawMaskedBitmap(rSrcBitmap, rMask,
954 : rSrcRect, rDstRect,
955 : maBegin,
956 : maXorAccessor);
957 : else
958 4 : implDrawMaskedBitmap(rSrcBitmap, rMask,
959 : rSrcRect, rDstRect,
960 : maBegin,
961 : maAccessor);
962 : }
963 : else
964 : {
965 4 : if( drawMode == DrawMode_XOR )
966 0 : implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
967 : rSrcRect, rDstRect,
968 : maBegin,
969 : maXorAccessor);
970 : else
971 4 : implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
972 : rSrcRect, rDstRect,
973 : maBegin,
974 : maAccessor);
975 : }
976 8 : damaged( rDstRect );
977 8 : }
978 :
979 0 : virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
980 : const BitmapDeviceSharedPtr& rMask,
981 : const basegfx::B2IBox& rSrcRect,
982 : const basegfx::B2IBox& rDstRect,
983 : DrawMode drawMode,
984 : const BitmapDeviceSharedPtr& rClip )
985 : {
986 0 : if( isCompatibleClipMask(rMask) &&
987 : isCompatibleBitmap(rSrcBitmap) )
988 : {
989 0 : if( drawMode == DrawMode_XOR )
990 0 : implDrawMaskedBitmap(rSrcBitmap, rMask,
991 : rSrcRect, rDstRect,
992 : getMaskedIter(rClip),
993 : maMaskedXorAccessor);
994 : else
995 0 : implDrawMaskedBitmap(rSrcBitmap, rMask,
996 : rSrcRect, rDstRect,
997 : getMaskedIter(rClip),
998 : maMaskedAccessor);
999 : }
1000 : else
1001 : {
1002 0 : if( drawMode == DrawMode_XOR )
1003 0 : implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
1004 : rSrcRect, rDstRect,
1005 : getMaskedIter(rClip),
1006 : maMaskedXorAccessor);
1007 : else
1008 0 : implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
1009 : rSrcRect, rDstRect,
1010 : getMaskedIter(rClip),
1011 : maMaskedAccessor);
1012 : }
1013 0 : damaged( rDstRect );
1014 0 : }
1015 :
1016 8922 : IBitmapDeviceDamageTrackerSharedPtr getDamageTracker_i() const
1017 : {
1018 8922 : return mpDamage;
1019 : }
1020 0 : void setDamageTracker_i( const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
1021 : {
1022 0 : mpDamage = rDamage;
1023 0 : }
1024 : };
1025 : } // namespace
1026 :
1027 47338 : struct ImplBitmapDevice
1028 : {
1029 : /** Bitmap memory plus deleter.
1030 :
1031 : Always points to the start of the mem
1032 : */
1033 : RawMemorySharedArray mpMem;
1034 :
1035 : /// Palette memory plus deleter (might be NULL)
1036 : PaletteMemorySharedVector mpPalette;
1037 :
1038 : /** Bounds of the device.
1039 :
1040 : maBounds.getWidth()/getHeight() yield the true size of the
1041 : device (i.e. the rectangle given by maBounds covers the device
1042 : area under the including-the-bottommost-and-rightmost-pixels
1043 : fill rule)
1044 : */
1045 : basegfx::B2IBox maBounds;
1046 :
1047 : /// Scanline format, as provided at the constructor
1048 : sal_Int32 mnScanlineFormat;
1049 :
1050 : /// Scanline stride. Negative for bottom-to-top formats
1051 : sal_Int32 mnScanlineStride;
1052 :
1053 : /// raw ptr to 0th scanline. used for cloning a generic renderer
1054 : sal_uInt8* mpFirstScanline;
1055 :
1056 : /** (Optional) device sharing the same memory, and used for input
1057 : clip masks/alpha masks/bitmaps that don't match our exact
1058 : bitmap format.
1059 :
1060 : This is to avoid the combinatorical explosion when dealing
1061 : with n bitmap formats, which could be combined with n clip
1062 : masks, alpha masks and bitmap masks (yielding a total of n^4
1063 : combinations). Since each BitmapRenderer is specialized for
1064 : one specific combination of said formats, a lot of duplicate
1065 : code would be generated, most of which probably never
1066 : used. Therefore, only the most common combinations are
1067 : specialized templates, the remainder gets handled by this
1068 : generic renderer (via runtime polymorphism).
1069 : */
1070 : BitmapDeviceSharedPtr mpGenericRenderer;
1071 : };
1072 :
1073 :
1074 33214 : BitmapDevice::BitmapDevice( const basegfx::B2IBox& rBounds,
1075 : sal_Int32 nScanlineFormat,
1076 : sal_Int32 nScanlineStride,
1077 : sal_uInt8* pFirstScanline,
1078 : const RawMemorySharedArray& rMem,
1079 : const PaletteMemorySharedVector& rPalette ) :
1080 33214 : mpImpl( new ImplBitmapDevice )
1081 : {
1082 33214 : mpImpl->mpMem = rMem;
1083 33214 : mpImpl->mpPalette = rPalette;
1084 33214 : mpImpl->maBounds = rBounds;
1085 33214 : mpImpl->mnScanlineFormat = nScanlineFormat;
1086 33214 : mpImpl->mnScanlineStride = nScanlineStride;
1087 33214 : mpImpl->mpFirstScanline = pFirstScanline;
1088 33214 : }
1089 :
1090 14124 : BitmapDevice::~BitmapDevice()
1091 : {
1092 : // outline, because of internal ImplBitmapDevice
1093 14124 : }
1094 :
1095 60513 : basegfx::B2IVector BitmapDevice::getSize() const
1096 : {
1097 : return basegfx::B2IVector(
1098 60513 : mpImpl->maBounds.getMaxX() - mpImpl->maBounds.getMinX(),
1099 121026 : mpImpl->maBounds.getMaxY() - mpImpl->maBounds.getMinY() );
1100 : }
1101 :
1102 9533 : bool BitmapDevice::isTopDown() const
1103 : {
1104 9533 : return mpImpl->mnScanlineStride >= 0;
1105 : }
1106 :
1107 38130 : sal_Int32 BitmapDevice::getScanlineFormat() const
1108 : {
1109 38130 : return mpImpl->mnScanlineFormat;
1110 : }
1111 :
1112 390 : sal_Int32 BitmapDevice::getScanlineStride() const
1113 : {
1114 390 : return mpImpl->mnScanlineStride < 0 ?
1115 390 : -mpImpl->mnScanlineStride : mpImpl->mnScanlineStride;
1116 : }
1117 :
1118 9463 : RawMemorySharedArray BitmapDevice::getBuffer() const
1119 : {
1120 9463 : return mpImpl->mpMem;
1121 : }
1122 :
1123 8922 : IBitmapDeviceDamageTrackerSharedPtr BitmapDevice::getDamageTracker() const
1124 : {
1125 8922 : return getDamageTracker_i();
1126 : }
1127 :
1128 0 : void BitmapDevice::setDamageTracker( const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
1129 : {
1130 0 : setDamageTracker_i(rDamage);
1131 0 : }
1132 :
1133 9223 : PaletteMemorySharedVector BitmapDevice::getPalette() const
1134 : {
1135 9223 : return mpImpl->mpPalette;
1136 : }
1137 :
1138 84 : void BitmapDevice::clear( Color fillColor )
1139 : {
1140 84 : clear_i( fillColor, mpImpl->maBounds );
1141 84 : }
1142 :
1143 25376 : void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt,
1144 : Color lineColor,
1145 : DrawMode drawMode )
1146 : {
1147 25376 : if( mpImpl->maBounds.isInside(rPt) )
1148 24907 : setPixel_i(rPt,lineColor,drawMode);
1149 25376 : }
1150 :
1151 25354 : void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt,
1152 : Color lineColor,
1153 : DrawMode drawMode,
1154 : const BitmapDeviceSharedPtr& rClip )
1155 : {
1156 25354 : if( !rClip )
1157 : {
1158 25346 : setPixel(rPt,lineColor,drawMode);
1159 50700 : return;
1160 : }
1161 :
1162 8 : if( mpImpl->maBounds.isInside(rPt) )
1163 : {
1164 8 : if( isCompatibleClipMask( rClip ) )
1165 8 : setPixel_i(rPt,lineColor,drawMode,rClip);
1166 : else
1167 0 : getGenericRenderer()->setPixel( rPt, lineColor, drawMode, rClip );
1168 : }
1169 : }
1170 :
1171 280731 : Color BitmapDevice::getPixel( const basegfx::B2IPoint& rPt )
1172 : {
1173 280731 : if( mpImpl->maBounds.isInside(rPt) )
1174 280731 : return getPixel_i(rPt);
1175 :
1176 0 : return Color();
1177 : }
1178 :
1179 6 : sal_uInt32 BitmapDevice::getPixelData( const basegfx::B2IPoint& rPt )
1180 : {
1181 6 : if( mpImpl->maBounds.isInside(rPt) )
1182 4 : return getPixelData_i(rPt);
1183 :
1184 2 : return 0;
1185 : }
1186 :
1187 101176 : void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1,
1188 : const basegfx::B2IPoint& rPt2,
1189 : Color lineColor,
1190 : DrawMode drawMode )
1191 : {
1192 : drawLine_i( rPt1,
1193 : rPt2,
1194 101176 : mpImpl->maBounds,
1195 : lineColor,
1196 202352 : drawMode );
1197 101176 : }
1198 :
1199 101154 : void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1,
1200 : const basegfx::B2IPoint& rPt2,
1201 : Color lineColor,
1202 : DrawMode drawMode,
1203 : const BitmapDeviceSharedPtr& rClip )
1204 : {
1205 101154 : if( !rClip )
1206 : {
1207 101150 : drawLine(rPt1,rPt2,lineColor,drawMode);
1208 202304 : return;
1209 : }
1210 :
1211 4 : if( isCompatibleClipMask( rClip ) )
1212 : drawLine_i( rPt1,
1213 : rPt2,
1214 4 : mpImpl->maBounds,
1215 : lineColor,
1216 : drawMode,
1217 8 : rClip );
1218 : else
1219 : getGenericRenderer()->drawLine( rPt1, rPt2, lineColor,
1220 0 : drawMode, rClip );
1221 : }
1222 :
1223 2941 : void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly,
1224 : Color lineColor,
1225 : DrawMode drawMode )
1226 : {
1227 2941 : const sal_uInt32 numVertices( rPoly.count() );
1228 2941 : if( numVertices )
1229 : drawPolygon_i( rPoly,
1230 2941 : mpImpl->maBounds,
1231 5882 : lineColor, drawMode );
1232 2941 : }
1233 :
1234 2924 : void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly,
1235 : Color lineColor,
1236 : DrawMode drawMode,
1237 : const BitmapDeviceSharedPtr& rClip )
1238 : {
1239 2924 : if( !rClip )
1240 : {
1241 2924 : drawPolygon(rPoly,lineColor,drawMode);
1242 5848 : return;
1243 : }
1244 :
1245 0 : const sal_uInt32 numVertices( rPoly.count() );
1246 0 : if( numVertices )
1247 : {
1248 0 : if( isCompatibleClipMask( rClip ) )
1249 : drawPolygon_i( rPoly,
1250 0 : mpImpl->maBounds,
1251 0 : lineColor, drawMode, rClip );
1252 : else
1253 : getGenericRenderer()->drawPolygon( rPoly, lineColor,
1254 0 : drawMode, rClip );
1255 : }
1256 : }
1257 :
1258 78900 : void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
1259 : Color fillColor,
1260 : DrawMode drawMode )
1261 : {
1262 78900 : fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds );
1263 78900 : }
1264 :
1265 78904 : void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
1266 : Color fillColor,
1267 : DrawMode drawMode,
1268 : const BitmapDeviceSharedPtr& rClip )
1269 : {
1270 78904 : if( !rClip )
1271 : {
1272 78819 : fillPolyPolygon(rPoly,fillColor,drawMode);
1273 157723 : return;
1274 : }
1275 :
1276 85 : if( isCompatibleClipMask( rClip ) )
1277 85 : fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds, rClip );
1278 : else
1279 : getGenericRenderer()->fillPolyPolygon( rPoly, fillColor,
1280 0 : drawMode, rClip );
1281 : }
1282 :
1283 :
1284 : namespace
1285 : {
1286 14993 : void assertImagePoint( const basegfx::B2IPoint& rPt,
1287 : const basegfx::B2IBox& rPermittedRange )
1288 : {
1289 : (void)rPt; (void)rPermittedRange;
1290 : OSL_ASSERT( rPermittedRange.isInside(rPt) );
1291 14993 : }
1292 :
1293 18887 : void assertImageRange( const basegfx::B2IBox& rRange,
1294 : const basegfx::B2IBox& rPermittedRange )
1295 : {
1296 : #if OSL_DEBUG_LEVEL > 0
1297 : basegfx::B2IBox aRange( rRange );
1298 : aRange.intersect( rPermittedRange );
1299 :
1300 : OSL_ASSERT( aRange == rRange );
1301 : #else
1302 : (void)rRange; (void)rPermittedRange;
1303 : #endif
1304 18887 : }
1305 :
1306 : // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
1307 : // to basegfx, and use here!
1308 15801 : bool clipAreaImpl( ::basegfx::B2IBox& io_rSourceArea,
1309 : ::basegfx::B2IPoint& io_rDestPoint,
1310 : const ::basegfx::B2IBox& rSourceBounds,
1311 : const ::basegfx::B2IBox& rDestBounds )
1312 : {
1313 : const ::basegfx::B2IPoint aSourceTopLeft(
1314 15801 : io_rSourceArea.getMinimum() );
1315 :
1316 15801 : ::basegfx::B2IBox aLocalSourceArea( io_rSourceArea );
1317 :
1318 : // clip source area (which must be inside rSourceBounds)
1319 15801 : aLocalSourceArea.intersect( rSourceBounds );
1320 :
1321 15801 : if( aLocalSourceArea.isEmpty() )
1322 0 : return false;
1323 :
1324 : // calc relative new source area points (relative to orig
1325 : // source area)
1326 : const ::basegfx::B2IVector aUpperLeftOffset(
1327 15801 : aLocalSourceArea.getMinimum()-aSourceTopLeft );
1328 : const ::basegfx::B2IVector aLowerRightOffset(
1329 15801 : aLocalSourceArea.getMaximum()-aSourceTopLeft );
1330 :
1331 : ::basegfx::B2IBox aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
1332 15801 : io_rDestPoint + aLowerRightOffset );
1333 :
1334 : // clip dest area (which must be inside rDestBounds)
1335 15801 : aLocalDestArea.intersect( rDestBounds );
1336 :
1337 15801 : if( aLocalDestArea.isEmpty() )
1338 808 : return false;
1339 :
1340 : // calc relative new dest area points (relative to orig
1341 : // source area)
1342 : const ::basegfx::B2IVector aDestUpperLeftOffset(
1343 14993 : aLocalDestArea.getMinimum()-io_rDestPoint );
1344 : const ::basegfx::B2IVector aDestLowerRightOffset(
1345 14993 : aLocalDestArea.getMaximum()-io_rDestPoint );
1346 :
1347 : io_rSourceArea = ::basegfx::B2IBox( aSourceTopLeft + aDestUpperLeftOffset,
1348 14993 : aSourceTopLeft + aDestLowerRightOffset );
1349 14993 : io_rDestPoint = aLocalDestArea.getMinimum();
1350 :
1351 14993 : return true;
1352 : }
1353 :
1354 : // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
1355 : // to basegfx, and use here!
1356 1950 : bool clipAreaImpl( ::basegfx::B2IBox& io_rDestArea,
1357 : ::basegfx::B2IBox& io_rSourceArea,
1358 : const ::basegfx::B2IBox& rDestBounds,
1359 : const ::basegfx::B2IBox& rSourceBounds )
1360 : {
1361 : // extract inherent scale
1362 1950 : const double nScaleX( io_rDestArea.getWidth() / (double)io_rSourceArea.getWidth() );
1363 1950 : const double nScaleY( io_rDestArea.getHeight() / (double)io_rSourceArea.getHeight() );
1364 :
1365 : // extract range origins
1366 : const basegfx::B2IPoint aDestTopLeft(
1367 1950 : io_rDestArea.getMinimum() );
1368 : const ::basegfx::B2IPoint aSourceTopLeft(
1369 1950 : io_rSourceArea.getMinimum() );
1370 :
1371 1950 : ::basegfx::B2IBox aLocalSourceArea( io_rSourceArea );
1372 :
1373 : // clip source area (which must be inside rSourceBounds)
1374 1950 : aLocalSourceArea.intersect( rSourceBounds );
1375 :
1376 1950 : if( aLocalSourceArea.isEmpty() )
1377 0 : return false;
1378 :
1379 : // calc relative new source area points (relative to orig
1380 : // source area)
1381 : const ::basegfx::B2IVector aUpperLeftOffset(
1382 1950 : aLocalSourceArea.getMinimum()-aSourceTopLeft );
1383 : const ::basegfx::B2IVector aLowerRightOffset(
1384 1950 : aLocalSourceArea.getMaximum()-aSourceTopLeft );
1385 :
1386 3900 : ::basegfx::B2IBox aLocalDestArea( basegfx::fround(aDestTopLeft.getX() + nScaleX*aUpperLeftOffset.getX()),
1387 3900 : basegfx::fround(aDestTopLeft.getY() + nScaleY*aUpperLeftOffset.getY()),
1388 3900 : basegfx::fround(aDestTopLeft.getX() + nScaleX*aLowerRightOffset.getX()),
1389 13650 : basegfx::fround(aDestTopLeft.getY() + nScaleY*aLowerRightOffset.getY()) );
1390 :
1391 : // clip dest area (which must be inside rDestBounds)
1392 1950 : aLocalDestArea.intersect( rDestBounds );
1393 :
1394 1950 : if( aLocalDestArea.isEmpty() )
1395 3 : return false;
1396 :
1397 : // calc relative new dest area points (relative to orig
1398 : // source area)
1399 : const ::basegfx::B2IVector aDestUpperLeftOffset(
1400 1947 : aLocalDestArea.getMinimum()-aDestTopLeft );
1401 : const ::basegfx::B2IVector aDestLowerRightOffset(
1402 1947 : aLocalDestArea.getMaximum()-aDestTopLeft );
1403 :
1404 3894 : io_rSourceArea = ::basegfx::B2IBox( basegfx::fround(aSourceTopLeft.getX() + aDestUpperLeftOffset.getX()/nScaleX),
1405 3894 : basegfx::fround(aSourceTopLeft.getY() + aDestUpperLeftOffset.getY()/nScaleY),
1406 3894 : basegfx::fround(aSourceTopLeft.getX() + aDestLowerRightOffset.getX()/nScaleX),
1407 13629 : basegfx::fround(aSourceTopLeft.getY() + aDestLowerRightOffset.getY()/nScaleY) );
1408 1947 : io_rDestArea = aLocalDestArea;
1409 :
1410 : // final source area clip (chopping round-offs)
1411 1947 : io_rSourceArea.intersect( rSourceBounds );
1412 :
1413 1947 : if( io_rSourceArea.isEmpty() )
1414 0 : return false;
1415 :
1416 :
1417 1947 : return true;
1418 : }
1419 : }
1420 :
1421 1933 : void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1422 : const basegfx::B2IBox& rSrcRect,
1423 : const basegfx::B2IBox& rDstRect,
1424 : DrawMode drawMode )
1425 : {
1426 1933 : const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1427 1933 : const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1428 1933 : basegfx::B2IBox aSrcRange( rSrcRect );
1429 1933 : basegfx::B2IBox aDestRange( rDstRect );
1430 :
1431 1933 : if( clipAreaImpl( aDestRange,
1432 : aSrcRange,
1433 1933 : mpImpl->maBounds,
1434 1933 : aSrcBounds ))
1435 : {
1436 1930 : assertImageRange(aDestRange,mpImpl->maBounds);
1437 1930 : assertImageRange(aSrcRange,aSrcBounds);
1438 :
1439 1930 : drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode );
1440 1933 : }
1441 1933 : }
1442 :
1443 1856 : void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1444 : const basegfx::B2IBox& rSrcRect,
1445 : const basegfx::B2IBox& rDstRect,
1446 : DrawMode drawMode,
1447 : const BitmapDeviceSharedPtr& rClip )
1448 : {
1449 1856 : if( !rClip )
1450 : {
1451 1847 : drawBitmap(rSrcBitmap,rSrcRect,rDstRect,drawMode);
1452 1856 : return;
1453 : }
1454 :
1455 9 : const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1456 9 : const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1457 9 : basegfx::B2IBox aSrcRange( rSrcRect );
1458 9 : basegfx::B2IBox aDestRange( rDstRect );
1459 :
1460 9 : if( clipAreaImpl( aDestRange,
1461 : aSrcRange,
1462 9 : mpImpl->maBounds,
1463 9 : aSrcBounds ))
1464 : {
1465 9 : assertImageRange(aDestRange,mpImpl->maBounds);
1466 9 : assertImageRange(aSrcRange,aSrcBounds);
1467 :
1468 9 : if( isCompatibleClipMask( rClip ) )
1469 : {
1470 9 : drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode, rClip );
1471 : }
1472 : else
1473 : {
1474 : getGenericRenderer()->drawBitmap( rSrcBitmap, rSrcRect,
1475 0 : rDstRect, drawMode, rClip );
1476 : }
1477 9 : }
1478 : }
1479 :
1480 15799 : void BitmapDevice::drawMaskedColor( Color aSrcColor,
1481 : const BitmapDeviceSharedPtr& rAlphaMask,
1482 : const basegfx::B2IBox& rSrcRect,
1483 : const basegfx::B2IPoint& rDstPoint )
1484 : {
1485 15799 : const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
1486 15799 : const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1487 15799 : basegfx::B2IBox aSrcRange( rSrcRect );
1488 15799 : basegfx::B2IPoint aDestPoint( rDstPoint );
1489 :
1490 15799 : if( clipAreaImpl( aSrcRange,
1491 : aDestPoint,
1492 : aSrcBounds,
1493 15799 : mpImpl->maBounds ))
1494 : {
1495 14991 : assertImagePoint(aDestPoint,mpImpl->maBounds);
1496 14991 : assertImageRange(aSrcRange,aSrcBounds);
1497 :
1498 14991 : if( rAlphaMask.get() == this )
1499 : {
1500 : // src == dest, copy rAlphaMask beforehand
1501 : // ---------------------------------------------------
1502 :
1503 0 : const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
1504 0 : aSrcRange.getHeight() );
1505 : BitmapDeviceSharedPtr pAlphaCopy(
1506 : cloneBitmapDevice( aSize,
1507 0 : shared_from_this()) );
1508 0 : basegfx::B2ITuple aGcc3WorkaroundTemporary;
1509 : const basegfx::B2IBox aAlphaRange( aGcc3WorkaroundTemporary,
1510 0 : aSize );
1511 : pAlphaCopy->drawBitmap(rAlphaMask,
1512 : aSrcRange,
1513 : aAlphaRange,
1514 0 : DrawMode_PAINT);
1515 0 : drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint );
1516 : }
1517 : else
1518 : {
1519 14991 : drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint );
1520 : }
1521 15799 : }
1522 15799 : }
1523 :
1524 15793 : void BitmapDevice::drawMaskedColor( Color aSrcColor,
1525 : const BitmapDeviceSharedPtr& rAlphaMask,
1526 : const basegfx::B2IBox& rSrcRect,
1527 : const basegfx::B2IPoint& rDstPoint,
1528 : const BitmapDeviceSharedPtr& rClip )
1529 : {
1530 15793 : if( !rClip )
1531 : {
1532 15791 : drawMaskedColor(aSrcColor,rAlphaMask,rSrcRect,rDstPoint);
1533 15793 : return;
1534 : }
1535 :
1536 2 : const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
1537 2 : const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1538 2 : basegfx::B2IBox aSrcRange( rSrcRect );
1539 2 : basegfx::B2IPoint aDestPoint( rDstPoint );
1540 :
1541 2 : if( clipAreaImpl( aSrcRange,
1542 : aDestPoint,
1543 : aSrcBounds,
1544 2 : mpImpl->maBounds ))
1545 : {
1546 2 : assertImagePoint(aDestPoint,mpImpl->maBounds);
1547 2 : assertImageRange(aSrcRange,aSrcBounds);
1548 :
1549 2 : if( isCompatibleClipMask( rClip ) )
1550 : {
1551 2 : if( rAlphaMask.get() == this )
1552 : {
1553 : // src == dest, copy rAlphaMask beforehand
1554 : // ---------------------------------------------------
1555 :
1556 0 : const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
1557 0 : aSrcRange.getHeight() );
1558 : BitmapDeviceSharedPtr pAlphaCopy(
1559 : cloneBitmapDevice( aSize,
1560 0 : shared_from_this()) );
1561 0 : basegfx::B2ITuple aGcc3WorkaroundTemporary;
1562 : const basegfx::B2IBox aAlphaRange( aGcc3WorkaroundTemporary,
1563 0 : aSize );
1564 : pAlphaCopy->drawBitmap(rAlphaMask,
1565 : aSrcRange,
1566 : aAlphaRange,
1567 0 : DrawMode_PAINT);
1568 0 : drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint, rClip );
1569 : }
1570 : else
1571 : {
1572 2 : drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint, rClip );
1573 : }
1574 : }
1575 : else
1576 : {
1577 : getGenericRenderer()->drawMaskedColor( aSrcColor, rAlphaMask,
1578 0 : rSrcRect, rDstPoint, rClip );
1579 : }
1580 2 : }
1581 : }
1582 :
1583 8 : void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1584 : const BitmapDeviceSharedPtr& rMask,
1585 : const basegfx::B2IBox& rSrcRect,
1586 : const basegfx::B2IBox& rDstRect,
1587 : DrawMode drawMode )
1588 : {
1589 : OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
1590 :
1591 8 : const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1592 8 : const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1593 8 : basegfx::B2IBox aSrcRange( rSrcRect );
1594 8 : basegfx::B2IBox aDestRange( rDstRect );
1595 :
1596 8 : if( clipAreaImpl( aDestRange,
1597 : aSrcRange,
1598 8 : mpImpl->maBounds,
1599 8 : aSrcBounds ))
1600 : {
1601 8 : assertImageRange(aDestRange,mpImpl->maBounds);
1602 8 : assertImageRange(aSrcRange,aSrcBounds);
1603 :
1604 8 : drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode );
1605 8 : }
1606 8 : }
1607 :
1608 4 : void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1609 : const BitmapDeviceSharedPtr& rMask,
1610 : const basegfx::B2IBox& rSrcRect,
1611 : const basegfx::B2IBox& rDstRect,
1612 : DrawMode drawMode,
1613 : const BitmapDeviceSharedPtr& rClip )
1614 : {
1615 4 : if( !rClip )
1616 : {
1617 4 : drawMaskedBitmap(rSrcBitmap,rMask,rSrcRect,rDstRect,drawMode);
1618 4 : return;
1619 : }
1620 :
1621 : OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
1622 :
1623 0 : const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1624 0 : const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1625 0 : basegfx::B2IBox aSrcRange( rSrcRect );
1626 0 : basegfx::B2IBox aDestRange( rDstRect );
1627 :
1628 0 : if( clipAreaImpl( aDestRange,
1629 : aSrcRange,
1630 0 : mpImpl->maBounds,
1631 0 : aSrcBounds ))
1632 : {
1633 0 : assertImageRange(aDestRange,mpImpl->maBounds);
1634 0 : assertImageRange(aSrcRange,aSrcBounds);
1635 :
1636 0 : if( isCompatibleClipMask( rClip ) )
1637 : {
1638 0 : drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode, rClip );
1639 : }
1640 : else
1641 : {
1642 : getGenericRenderer()->drawMaskedBitmap( rSrcBitmap, rMask, rSrcRect,
1643 0 : rDstRect, drawMode, rClip );
1644 : }
1645 0 : }
1646 : }
1647 :
1648 :
1649 : //----------------------------------------------------------------------------------
1650 :
1651 : /** Standard clip and alpha masks
1652 : */
1653 : struct StdMasks
1654 : {
1655 : typedef PixelFormatTraits_GREY1_MSB clipmask_format_traits;
1656 : typedef PixelFormatTraits_GREY8 alphamask_format_traits;
1657 :
1658 : /// Clipmask: 0 means opaque
1659 : static const bool clipmask_polarity = false;
1660 :
1661 : /// Alpha mask: 0 means fully transparent
1662 : static const bool alphamask_polarity = true;
1663 : };
1664 :
1665 : //----------------------------------------------------------------------------------
1666 :
1667 : // Some compilers don't like the nested template wrap_accessor
1668 : // reference in the parameter list - being slightly less type safe,
1669 : // then.
1670 : #ifndef BASEBMP_NO_NESTED_TEMPLATE_PARAMETER
1671 :
1672 : /// Produces a specialized renderer for the given pixel format
1673 : template< class FormatTraits, class MaskTraits >
1674 33214 : BitmapDeviceSharedPtr createRenderer(
1675 : const basegfx::B2IBox& rBounds,
1676 : sal_Int32 nScanlineFormat,
1677 : sal_Int32 nScanlineStride,
1678 : sal_uInt8* pFirstScanline,
1679 : typename FormatTraits::raw_accessor_type const& rRawAccessor,
1680 : typename FormatTraits::accessor_selector::template wrap_accessor<
1681 : typename FormatTraits::raw_accessor_type>::type const& rAccessor,
1682 : boost::shared_array< sal_uInt8 > pMem,
1683 : const PaletteMemorySharedVector& pPal,
1684 : const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1685 : #else
1686 :
1687 : template< class FormatTraits, class MaskTraits, class Accessor >
1688 : BitmapDeviceSharedPtr createRenderer(
1689 : const basegfx::B2IBox& rBounds,
1690 : sal_Int32 nScanlineFormat,
1691 : sal_Int32 nScanlineStride,
1692 : sal_uInt8* pFirstScanline,
1693 : typename FormatTraits::raw_accessor_type const& rRawAccessor,
1694 : Accessor const& rAccessor,
1695 : boost::shared_array< sal_uInt8 > pMem,
1696 : const PaletteMemorySharedVector& pPal,
1697 : const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1698 :
1699 : #endif
1700 : {
1701 : typedef typename FormatTraits::iterator_type Iterator;
1702 : typedef BitmapRenderer< Iterator,
1703 : typename FormatTraits::raw_accessor_type,
1704 : typename FormatTraits::accessor_selector,
1705 : MaskTraits > Renderer;
1706 :
1707 : return BitmapDeviceSharedPtr(
1708 : new Renderer( rBounds,
1709 : nScanlineFormat,
1710 : nScanlineStride,
1711 : pFirstScanline,
1712 : Iterator(
1713 : reinterpret_cast<typename Iterator::value_type*>(
1714 : pFirstScanline),
1715 : nScanlineStride),
1716 : rRawAccessor,
1717 : rAccessor,
1718 : pMem,
1719 : pPal,
1720 33214 : pDamage ));
1721 : }
1722 :
1723 : /// Create standard grey level palette
1724 882 : PaletteMemorySharedVector createStandardPalette(
1725 : const PaletteMemorySharedVector& pPal,
1726 : sal_Int32 nNumEntries )
1727 : {
1728 882 : if( pPal || nNumEntries <= 0 )
1729 846 : return pPal;
1730 :
1731 : boost::shared_ptr< std::vector<Color> > pLocalPal(
1732 36 : new std::vector<Color>(nNumEntries) );
1733 :
1734 36 : const sal_Int32 nIncrement( 0x00FFFFFF/nNumEntries );
1735 36 : --nNumEntries;
1736 72 : for( sal_Int32 i=0, c=0; i<nNumEntries; ++i,c+=nIncrement )
1737 36 : pLocalPal->at(i) = Color(0xFF000000 | c);
1738 :
1739 36 : pLocalPal->at(nNumEntries) = Color(0xFFFFFFFF);
1740 :
1741 36 : return pLocalPal;
1742 : }
1743 :
1744 : template< class FormatTraits, class MaskTraits >
1745 32332 : BitmapDeviceSharedPtr createRenderer(
1746 : const basegfx::B2IBox& rBounds,
1747 : sal_Int32 nScanlineFormat,
1748 : sal_Int32 nScanlineStride,
1749 : sal_uInt8* pFirstScanline,
1750 : boost::shared_array< sal_uInt8 > pMem,
1751 : const PaletteMemorySharedVector& pPal,
1752 : const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1753 : {
1754 : return createRenderer<FormatTraits,
1755 : MaskTraits>(rBounds,
1756 : nScanlineFormat,
1757 : nScanlineStride,
1758 : pFirstScanline,
1759 : typename FormatTraits::raw_accessor_type(),
1760 : typename FormatTraits::accessor_selector::template
1761 : wrap_accessor<
1762 : typename FormatTraits::raw_accessor_type>::type(),
1763 : pMem,
1764 : pPal,
1765 32332 : pDamage);
1766 : }
1767 :
1768 : template< class FormatTraits, class MaskTraits >
1769 882 : BitmapDeviceSharedPtr createRenderer(
1770 : const basegfx::B2IBox& rBounds,
1771 : sal_Int32 nScanlineFormat,
1772 : sal_Int32 nScanlineStride,
1773 : sal_uInt8* pFirstScanline,
1774 : boost::shared_array< sal_uInt8 > pMem,
1775 : PaletteMemorySharedVector pPal,
1776 : int nBitsPerPixel,
1777 : const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1778 : {
1779 882 : pPal = createStandardPalette(pPal,
1780 : 1UL << nBitsPerPixel);
1781 :
1782 : OSL_ASSERT(pPal);
1783 : return createRenderer<FormatTraits,
1784 : MaskTraits>(rBounds,
1785 : nScanlineFormat,
1786 : nScanlineStride,
1787 : pFirstScanline,
1788 : typename FormatTraits::raw_accessor_type(),
1789 : typename FormatTraits::accessor_selector::template
1790 : wrap_accessor<
1791 : typename FormatTraits::raw_accessor_type>::type(
1792 : &pPal->at(0),
1793 : pPal->size()),
1794 : pMem,
1795 : pPal,
1796 882 : pDamage);
1797 : }
1798 :
1799 : //----------------------------------------------------------------------------------
1800 :
1801 : // TODO(Q3): consolidate with canvas/canvastools.hxx! Best move this
1802 : // to o3tl or sal/bithacks.hxx ...
1803 :
1804 : /** Compute the next highest power of 2 of a 32-bit value
1805 :
1806 : Code devised by Sean Anderson, in good ole HAKMEM
1807 : tradition.
1808 :
1809 : @return 1 << (lg(x - 1) + 1)
1810 : */
1811 33216 : inline sal_uInt32 nextPow2( sal_uInt32 x )
1812 : {
1813 33216 : --x;
1814 33216 : x |= x >> 1;
1815 33216 : x |= x >> 2;
1816 33216 : x |= x >> 4;
1817 33216 : x |= x >> 8;
1818 33216 : x |= x >> 16;
1819 :
1820 33216 : return ++x;
1821 : }
1822 :
1823 : //----------------------------------------------------------------------------------
1824 :
1825 : namespace
1826 : {
1827 33216 : BitmapDeviceSharedPtr createBitmapDeviceImpl( const basegfx::B2IVector& rSize,
1828 : bool bTopDown,
1829 : sal_Int32 nScanlineFormat,
1830 : boost::shared_array< sal_uInt8 > pMem,
1831 : PaletteMemorySharedVector pPal,
1832 : const basegfx::B2IBox* pSubset,
1833 : const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
1834 : {
1835 : OSL_ASSERT(rSize.getX() > 0 && rSize.getY() > 0);
1836 :
1837 33216 : if( nScanlineFormat <= Format::NONE ||
1838 : nScanlineFormat > Format::MAX )
1839 0 : return BitmapDeviceSharedPtr();
1840 :
1841 : static const sal_uInt8 bitsPerPixel[] =
1842 : {
1843 : 0, // NONE
1844 : 1, // ONE_BIT_MSB_GREY
1845 : 1, // ONE_BIT_LSB_GREY
1846 : 1, // ONE_BIT_MSB_PAL
1847 : 1, // ONE_BIT_LSB_PAL
1848 : 4, // FOUR_BIT_MSB_GREY
1849 : 4, // FOUR_BIT_LSB_GREY
1850 : 4, // FOUR_BIT_MSB_PAL
1851 : 4, // FOUR_BIT_LSB_PAL
1852 : 8, // EIGHT_BIT_PAL
1853 : 8, // EIGHT_BIT_GREY
1854 : 16, // SIXTEEN_BIT_LSB_TC_MASK
1855 : 16, // SIXTEEN_BIT_MSB_TC_MASK
1856 : 24, // TWENTYFOUR_BIT_TC_MASK
1857 : 32, // THIRTYTWO_BIT_TC_MASK_BGRA
1858 : 32, // THIRTYTWO_BIT_TC_MASK_ARGB
1859 : 32, // THIRTYTWO_BIT_TC_MASK_ABGR
1860 : 32, // THIRTYTWO_BIT_TC_MASK_RGBA
1861 : };
1862 :
1863 33216 : sal_Int32 nScanlineStride(0);
1864 :
1865 : // round up to full 8 bit, divide by 8
1866 33216 : nScanlineStride = (rSize.getX()*bitsPerPixel[nScanlineFormat] + 7) >> 3;
1867 :
1868 : // rounded up to next full power-of-two number of bytes
1869 : const sal_uInt32 bytesPerPixel = nextPow2(
1870 33216 : (bitsPerPixel[nScanlineFormat] + 7) >> 3);
1871 :
1872 : // now make nScanlineStride a multiple of bytesPerPixel
1873 33216 : nScanlineStride = (nScanlineStride + bytesPerPixel - 1) / bytesPerPixel * bytesPerPixel;
1874 :
1875 : // factor in bottom-up scanline order case
1876 33216 : nScanlineStride *= bTopDown ? 1 : -1;
1877 :
1878 33216 : const sal_uInt32 nWidth(nScanlineStride < 0 ? -nScanlineStride : nScanlineStride);
1879 33216 : const sal_uInt32 nHeight(rSize.getY());
1880 :
1881 33216 : if (nHeight && nWidth && nWidth > SAL_MAX_INT32 / nHeight)
1882 : {
1883 : SAL_WARN( "basebmp", "suspicious massive alloc " << nWidth << " * " << nHeight);
1884 2 : return BitmapDeviceSharedPtr();
1885 : }
1886 :
1887 33214 : const std::size_t nMemSize(nWidth * nHeight);
1888 :
1889 33214 : if( !pMem )
1890 : {
1891 : pMem.reset(
1892 8355 : reinterpret_cast<sal_uInt8*>(rtl_allocateMemory( nMemSize )),
1893 8355 : &rtl_freeMemory );
1894 8355 : if (pMem.get() == 0 && nMemSize != 0)
1895 0 : return BitmapDeviceSharedPtr();
1896 8355 : memset(pMem.get(), 0, nMemSize);
1897 : }
1898 :
1899 : sal_uInt8* pFirstScanline = nScanlineStride < 0 ?
1900 33214 : pMem.get() + nMemSize + nScanlineStride : pMem.get();
1901 :
1902 : // shrink render area to given subset, if given
1903 33214 : basegfx::B2IBox aBounds(0,0,rSize.getX(),rSize.getY());
1904 33214 : if( pSubset )
1905 8847 : aBounds.intersect( *pSubset );
1906 :
1907 33214 : switch( nScanlineFormat )
1908 : {
1909 : // ----------------------------------------------------------------------
1910 : // one bit formats
1911 :
1912 : case Format::ONE_BIT_MSB_GREY:
1913 : return createRenderer<PixelFormatTraits_GREY1_MSB,StdMasks>(
1914 : aBounds, nScanlineFormat, nScanlineStride,
1915 17 : pFirstScanline, pMem, pPal, rDamage );
1916 :
1917 : case Format::ONE_BIT_LSB_GREY:
1918 : return createRenderer<PixelFormatTraits_GREY1_LSB,StdMasks>(
1919 : aBounds, nScanlineFormat, nScanlineStride,
1920 1 : pFirstScanline, pMem, pPal, rDamage );
1921 :
1922 : case Format::ONE_BIT_MSB_PAL:
1923 : return createRenderer<PixelFormatTraits_PAL1_MSB,StdMasks>(
1924 : aBounds, nScanlineFormat, nScanlineStride,
1925 : pFirstScanline, pMem, pPal,
1926 639 : bitsPerPixel[nScanlineFormat], rDamage );
1927 :
1928 : case Format::ONE_BIT_LSB_PAL:
1929 : return createRenderer<PixelFormatTraits_PAL1_LSB,StdMasks>(
1930 : aBounds, nScanlineFormat, nScanlineStride,
1931 : pFirstScanline, pMem, pPal,
1932 1 : bitsPerPixel[nScanlineFormat], rDamage );
1933 :
1934 :
1935 : // ----------------------------------------------------------------------
1936 : // four bit formats
1937 :
1938 : case Format::FOUR_BIT_MSB_GREY:
1939 : return createRenderer<PixelFormatTraits_GREY4_MSB,StdMasks>(
1940 : aBounds, nScanlineFormat, nScanlineStride,
1941 0 : pFirstScanline, pMem, pPal, rDamage );
1942 :
1943 : case Format::FOUR_BIT_LSB_GREY:
1944 : return createRenderer<PixelFormatTraits_GREY4_LSB,StdMasks>(
1945 : aBounds, nScanlineFormat, nScanlineStride,
1946 0 : pFirstScanline, pMem, pPal, rDamage );
1947 :
1948 : case Format::FOUR_BIT_MSB_PAL:
1949 : return createRenderer<PixelFormatTraits_PAL4_MSB,StdMasks>(
1950 : aBounds, nScanlineFormat, nScanlineStride,
1951 : pFirstScanline, pMem, pPal,
1952 4 : bitsPerPixel[nScanlineFormat], rDamage );
1953 :
1954 : case Format::FOUR_BIT_LSB_PAL:
1955 : return createRenderer<PixelFormatTraits_PAL4_LSB,StdMasks>(
1956 : aBounds, nScanlineFormat, nScanlineStride,
1957 : pFirstScanline, pMem, pPal,
1958 0 : bitsPerPixel[nScanlineFormat], rDamage );
1959 :
1960 :
1961 : // ----------------------------------------------------------------------
1962 : // eight bit formats
1963 :
1964 : case Format::EIGHT_BIT_GREY:
1965 : return createRenderer<PixelFormatTraits_GREY8,StdMasks>(
1966 : aBounds, nScanlineFormat, nScanlineStride,
1967 15795 : pFirstScanline, pMem, pPal, rDamage );
1968 :
1969 : case Format::EIGHT_BIT_PAL:
1970 : return createRenderer<PixelFormatTraits_PAL8,StdMasks>(
1971 : aBounds, nScanlineFormat, nScanlineStride,
1972 : pFirstScanline, pMem, pPal,
1973 238 : bitsPerPixel[nScanlineFormat], rDamage );
1974 :
1975 :
1976 : // ----------------------------------------------------------------------
1977 : // sixteen bit formats
1978 :
1979 : case Format::SIXTEEN_BIT_LSB_TC_MASK:
1980 : return createRenderer<PixelFormatTraits_RGB16_565_LSB,StdMasks>(
1981 : aBounds, nScanlineFormat, nScanlineStride,
1982 1 : pFirstScanline, pMem, pPal, rDamage );
1983 :
1984 : case Format::SIXTEEN_BIT_MSB_TC_MASK:
1985 : return createRenderer<PixelFormatTraits_RGB16_565_MSB,StdMasks>(
1986 : aBounds, nScanlineFormat, nScanlineStride,
1987 0 : pFirstScanline, pMem, pPal, rDamage );
1988 :
1989 :
1990 : // ----------------------------------------------------------------------
1991 : // twentyfour bit formats
1992 : case Format::TWENTYFOUR_BIT_TC_MASK:
1993 : return createRenderer<PixelFormatTraits_BGR24,StdMasks>(
1994 : aBounds, nScanlineFormat, nScanlineStride,
1995 16483 : pFirstScanline, pMem, pPal, rDamage );
1996 :
1997 :
1998 : // ----------------------------------------------------------------------
1999 : // thirtytwo bit formats
2000 :
2001 : case Format::THIRTYTWO_BIT_TC_MASK_BGRA:
2002 : return createRenderer<PixelFormatTraits_BGRX32_8888,StdMasks>(
2003 : aBounds, nScanlineFormat, nScanlineStride,
2004 35 : pFirstScanline, pMem, pPal, rDamage );
2005 :
2006 : case Format::THIRTYTWO_BIT_TC_MASK_ARGB:
2007 : return createRenderer<PixelFormatTraits_XRGB32_8888,StdMasks>(
2008 : aBounds, nScanlineFormat, nScanlineStride,
2009 0 : pFirstScanline, pMem, pPal, rDamage );
2010 :
2011 : case Format::THIRTYTWO_BIT_TC_MASK_ABGR:
2012 : return createRenderer<PixelFormatTraits_XBGR32_8888,StdMasks>(
2013 : aBounds, nScanlineFormat, nScanlineStride,
2014 0 : pFirstScanline, pMem, pPal, rDamage );
2015 :
2016 : case Format::THIRTYTWO_BIT_TC_MASK_RGBA:
2017 : return createRenderer<PixelFormatTraits_RGBX32_8888,StdMasks>(
2018 : aBounds, nScanlineFormat, nScanlineStride,
2019 0 : pFirstScanline, pMem, pPal, rDamage );
2020 : }
2021 :
2022 : // TODO(F3): other formats not yet implemented
2023 0 : return BitmapDeviceSharedPtr();
2024 : }
2025 : } // namespace
2026 :
2027 :
2028 7696 : BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2029 : bool bTopDown,
2030 : sal_Int32 nScanlineFormat )
2031 : {
2032 : return createBitmapDeviceImpl( rSize,
2033 : bTopDown,
2034 : nScanlineFormat,
2035 : boost::shared_array< sal_uInt8 >(),
2036 : PaletteMemorySharedVector(),
2037 : NULL,
2038 7696 : IBitmapDeviceDamageTrackerSharedPtr() );
2039 : }
2040 :
2041 430 : BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2042 : bool bTopDown,
2043 : sal_Int32 nScanlineFormat,
2044 : const PaletteMemorySharedVector& rPalette )
2045 : {
2046 : return createBitmapDeviceImpl( rSize,
2047 : bTopDown,
2048 : nScanlineFormat,
2049 : boost::shared_array< sal_uInt8 >(),
2050 : rPalette,
2051 : NULL,
2052 430 : IBitmapDeviceDamageTrackerSharedPtr() );
2053 : }
2054 :
2055 16168 : BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2056 : bool bTopDown,
2057 : sal_Int32 nScanlineFormat,
2058 : const RawMemorySharedArray& rMem,
2059 : const PaletteMemorySharedVector& rPalette )
2060 : {
2061 : return createBitmapDeviceImpl( rSize,
2062 : bTopDown,
2063 : nScanlineFormat,
2064 : rMem,
2065 : rPalette,
2066 : NULL,
2067 16168 : IBitmapDeviceDamageTrackerSharedPtr() );
2068 : }
2069 :
2070 8847 : BitmapDeviceSharedPtr subsetBitmapDevice( const BitmapDeviceSharedPtr& rProto,
2071 : const basegfx::B2IBox& rSubset )
2072 : {
2073 : return createBitmapDeviceImpl( rProto->getSize(),
2074 8847 : rProto->isTopDown(),
2075 : rProto->getScanlineFormat(),
2076 : rProto->getBuffer(),
2077 : rProto->getPalette(),
2078 : &rSubset,
2079 17694 : rProto->getDamageTracker() );
2080 : }
2081 :
2082 75 : BitmapDeviceSharedPtr cloneBitmapDevice( const basegfx::B2IVector& rSize,
2083 : const BitmapDeviceSharedPtr& rProto )
2084 : {
2085 : return createBitmapDeviceImpl( rSize,
2086 75 : rProto->isTopDown(),
2087 : rProto->getScanlineFormat(),
2088 : boost::shared_array< sal_uInt8 >(),
2089 : rProto->getPalette(),
2090 : NULL,
2091 150 : rProto->getDamageTracker() );
2092 : }
2093 :
2094 : //----------------------------------------------------------------------------------
2095 :
2096 : /// Clone our device, with GenericImageAccessor to handle all formats
2097 0 : BitmapDeviceSharedPtr BitmapDevice::getGenericRenderer() const
2098 : {
2099 0 : return mpImpl->mpGenericRenderer;
2100 : }
2101 :
2102 : } // namespace basebmp
2103 :
2104 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|