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