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