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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26
27 // bootstrap stuff
28 #include <sal/main.h>
29 #include <rtl/bootstrap.hxx>
30 #include <rtl/ref.hxx>
31 #include <comphelper/processfactory.hxx>
32 #include <comphelper/regpathhelper.hxx>
33 #include <cppuhelper/servicefactory.hxx>
34 #include <cppuhelper/bootstrap.hxx>
35 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 #include <com/sun/star/lang/XInitialization.hpp>
37 #include <com/sun/star/registry/XSimpleRegistry.hpp>
38 #include <com/sun/star/util/Endianness.hpp>
39 #include <com/sun/star/rendering/ColorComponentTag.hpp>
40 #include <com/sun/star/rendering/ColorSpaceType.hpp>
41 #include <com/sun/star/rendering/RenderingIntent.hpp>
42 #include <com/sun/star/rendering/XIntegerReadOnlyBitmap.hpp>
43 #include <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp>
44 #include <com/sun/star/rendering/XBitmapPalette.hpp>
45
46 #include <ucbhelper/contentbroker.hxx>
47 #include <ucbhelper/configurationkeys.hxx>
48 #include <cppuhelper/compbase3.hxx>
49
50 #include <tools/diagnose_ex.h>
51 #include <tools/extendapplicationenvironment.hxx>
52
53 #include "vcl/svapp.hxx"
54 #include "vcl/canvastools.hxx"
55 #include "vcl/canvasbitmap.hxx"
56 #include "vcl/dialog.hxx"
57 #include "vcl/outdev.hxx"
58 #include "vcl/bmpacc.hxx"
59 #include "vcl/virdev.hxx"
60 #include "vcl/bitmapex.hxx"
61
62
63 using namespace ::com::sun::star;
64 using namespace ::vcl::unotools;
65
66 // -----------------------------------------------------------------------
67
68 void Main();
69
70 // -----------------------------------------------------------------------
71
SAL_IMPLEMENT_MAIN()72 SAL_IMPLEMENT_MAIN()
73 {
74 tools::extendApplicationEnvironment();
75
76 uno::Reference< lang::XMultiServiceFactory > xMS;
77 xMS = cppu::createRegistryServiceFactory(
78 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "applicat.rdb" ) ),
79 sal_True );
80
81 InitVCL( xMS );
82 ::Main();
83 DeInitVCL();
84
85 return 0;
86 }
87
88 // -----------------------------------------------------------------------
89
90 namespace com { namespace sun { namespace star { namespace rendering
91 {
92
operator ==(const RGBColor & rLHS,const ARGBColor & rRHS)93 bool operator==( const RGBColor& rLHS, const ARGBColor& rRHS )
94 {
95 return rLHS.Red == rRHS.Red && rLHS.Green == rRHS.Green && rLHS.Blue == rRHS.Blue;
96 }
operator ==(const ARGBColor & rLHS,const RGBColor & rRHS)97 bool operator==( const ARGBColor& rLHS, const RGBColor& rRHS )
98 {
99 return rLHS.Red == rRHS.Red && rLHS.Green == rRHS.Green && rLHS.Blue == rRHS.Blue;
100 }
101
102 } } } }
103
104 //----------------------------------------------------------------------------------
105
106 namespace
107 {
108
109 class TestApp : public Application
110 {
111 public:
112 virtual void Main();
113 virtual USHORT Exception( USHORT nError );
114 };
115
116 class TestWindow : public Dialog
117 {
118 public:
TestWindow()119 TestWindow() : Dialog( (Window *) NULL )
120 {
121 SetText( rtl::OUString::createFromAscii( "CanvasBitmap test harness" ) );
122 SetSizePixel( Size( 1024, 1024 ) );
123 EnablePaint( true );
124 Show();
125 }
126
~TestWindow()127 virtual ~TestWindow() {}
128 virtual void Paint( const Rectangle& rRect );
129 };
130
131 //----------------------------------------------------------------------------------
132
133 static bool g_failure=false;
134
test(bool bResult,const char * msg)135 void test( bool bResult, const char* msg )
136 {
137 if( bResult )
138 {
139 OSL_TRACE("Testing: %s - PASSED", msg);
140 }
141 else
142 {
143 g_failure = true;
144 OSL_TRACE("Testing: %s - FAILED", msg);
145 }
146 }
147
148 //----------------------------------------------------------------------------------
149
rangeCheck(const rendering::RGBColor & rColor)150 bool rangeCheck( const rendering::RGBColor& rColor )
151 {
152 return rColor.Red < 0.0 || rColor.Red > 1.0 ||
153 rColor.Green < 0.0 || rColor.Green > 1.0 ||
154 rColor.Blue < 0.0 || rColor.Blue > 1.0;
155 }
156
157 //----------------------------------------------------------------------------------
158
checkCanvasBitmap(const rtl::Reference<VclCanvasBitmap> & xBmp,const char * msg,int nOriginalDepth)159 void checkCanvasBitmap( const rtl::Reference<VclCanvasBitmap>& xBmp,
160 const char* msg,
161 int nOriginalDepth )
162 {
163 OSL_TRACE("-------------------------");
164 OSL_TRACE("Testing %s, with depth %d", msg, nOriginalDepth);
165
166 BitmapEx aContainedBmpEx( xBmp->getBitmapEx() );
167 Bitmap aContainedBmp( aContainedBmpEx.GetBitmap() );
168 int nDepth = nOriginalDepth;
169
170 {
171 ScopedBitmapReadAccess pAcc( aContainedBmp.AcquireReadAccess(),
172 aContainedBmp );
173 nDepth = pAcc->GetBitCount();
174 }
175
176 test( aContainedBmp.GetSizePixel() == Size(200,200),
177 "Original bitmap size" );
178
179 test( xBmp->getSize().Width == 200 && xBmp->getSize().Height == 200,
180 "Original bitmap size via API" );
181
182 test( xBmp->hasAlpha() == aContainedBmpEx.IsTransparent(),
183 "Correct alpha state" );
184
185 test( xBmp->getScaledBitmap( geometry::RealSize2D(500,500), sal_False ).is(),
186 "getScaledBitmap()" );
187
188 rendering::IntegerBitmapLayout aLayout;
189 uno::Sequence<sal_Int8> aPixelData = xBmp->getData(aLayout, geometry::IntegerRectangle2D(0,0,1,1));
190
191 const sal_Int32 nExpectedBitsPerPixel(
192 aContainedBmpEx.IsTransparent() ? std::max(8,nDepth)+8 : nDepth);
193 test( aLayout.ScanLines == 1,
194 "# scanlines" );
195 test( aLayout.ScanLineBytes == (nExpectedBitsPerPixel+7)/8,
196 "# scanline bytes" );
197 test( aLayout.ScanLineStride == (nExpectedBitsPerPixel+7)/8 ||
198 aLayout.ScanLineStride == -(nExpectedBitsPerPixel+7)/8,
199 "# scanline stride" );
200 test( aLayout.PlaneStride == 0,
201 "# plane stride" );
202
203 test( aLayout.ColorSpace.is(),
204 "Color space there" );
205
206 test( aLayout.Palette.is() == (nDepth <= 8),
207 "Palette existance conforms to bitmap" );
208
209 uno::Sequence<sal_Int8> aPixelData2 = xBmp->getPixel( aLayout, geometry::IntegerPoint2D(0,0) );
210
211 test( aPixelData2.getLength() == aPixelData.getLength(),
212 "getData and getPixel return same amount of data" );
213
214 aPixelData = xBmp->getData(aLayout, geometry::IntegerRectangle2D(0,0,200,1));
215 test( aLayout.ScanLines == 1,
216 "# scanlines" );
217 test( aLayout.ScanLineBytes == (200*nExpectedBitsPerPixel+7)/8,
218 "# scanline bytes" );
219 test( aLayout.ScanLineStride == (200*nExpectedBitsPerPixel+7)/8 ||
220 aLayout.ScanLineStride == -(200*nExpectedBitsPerPixel+7)/8,
221 "# scanline stride" );
222
223 uno::Sequence< rendering::RGBColor > aRGBColors = xBmp->convertIntegerToRGB( aPixelData );
224 uno::Sequence< rendering::ARGBColor > aARGBColors = xBmp->convertIntegerToARGB( aPixelData );
225
226 const rendering::RGBColor* pRGBStart ( aRGBColors.getConstArray() );
227 const rendering::RGBColor* pRGBEnd ( aRGBColors.getConstArray()+aRGBColors.getLength() );
228 const rendering::ARGBColor* pARGBStart( aARGBColors.getConstArray() );
229 std::pair<const rendering::RGBColor*,
230 const rendering::ARGBColor*> aRes = std::mismatch( pRGBStart, pRGBEnd, pARGBStart );
231 test( aRes.first == pRGBEnd,
232 "argb and rgb colors are equal" );
233
234 test( std::find_if(pRGBStart,pRGBEnd,&rangeCheck) == pRGBEnd,
235 "rgb colors are within [0,1] range" );
236
237 test( pRGBStart[0].Red == 1.0 && pRGBStart[0].Green == 1.0 && pRGBStart[0].Blue == 1.0,
238 "First pixel is white" );
239 test( pARGBStart[1].Alpha == 1.0,
240 "Second pixel is opaque" );
241 if( aContainedBmpEx.IsTransparent() )
242 {
243 test( pARGBStart[0].Alpha == 0.0,
244 "First pixel is fully transparent" );
245 }
246
247 test( pRGBStart[1].Red == 0.0 && pRGBStart[1].Green == 0.0 && pRGBStart[1].Blue == 0.0,
248 "Second pixel is black" );
249
250 if( nOriginalDepth > 8 )
251 {
252 const Color aCol(COL_GREEN);
253 test( pRGBStart[5].Red == vcl::unotools::toDoubleColor(aCol.GetRed()) &&
254 pRGBStart[5].Green == vcl::unotools::toDoubleColor(aCol.GetGreen()) &&
255 pRGBStart[5].Blue == vcl::unotools::toDoubleColor(aCol.GetBlue()),
256 "Sixth pixel is green" );
257 }
258 else if( nDepth <= 8 )
259 {
260 uno::Reference<rendering::XBitmapPalette> xPal = xBmp->getPalette();
261 test( xPal.is(),
262 "8bit or less: needs palette" );
263 test( xPal->getNumberOfEntries() == 1L << nOriginalDepth,
264 "Palette has correct entry count" );
265 uno::Sequence<double> aIndex;
266 test( xPal->setIndex(aIndex,sal_True,0) == sal_False,
267 "Palette is read-only" );
268 test( xPal->getIndex(aIndex,0),
269 "Palette entry 0 is opaque" );
270 test( xPal->getColorSpace().is(),
271 "Palette has a valid color space" );
272 }
273
274 test( pRGBStart[150].Red == 1.0 && pRGBStart[150].Green == 1.0 && pRGBStart[150].Blue == 1.0,
275 "150th pixel is white" );
276
277 if( nOriginalDepth > 8 )
278 {
279 const uno::Sequence<sal_Int8> aComponentTags( xBmp->getComponentTags() );
280 uno::Sequence<rendering::ARGBColor> aARGBColor(1);
281 uno::Sequence<rendering::RGBColor> aRGBColor(1);
282 uno::Sequence<sal_Int8> aPixel3, aPixel4;
283
284 const Color aCol(COL_GREEN);
285 aARGBColor[0].Red = vcl::unotools::toDoubleColor(aCol.GetRed());
286 aARGBColor[0].Green = vcl::unotools::toDoubleColor(aCol.GetGreen());
287 aARGBColor[0].Blue = vcl::unotools::toDoubleColor(aCol.GetBlue());
288 aARGBColor[0].Alpha = 1.0;
289
290 aRGBColor[0].Red = vcl::unotools::toDoubleColor(aCol.GetRed());
291 aRGBColor[0].Green = vcl::unotools::toDoubleColor(aCol.GetGreen());
292 aRGBColor[0].Blue = vcl::unotools::toDoubleColor(aCol.GetBlue());
293
294 aPixel3 = xBmp->convertIntegerFromARGB( aARGBColor );
295 aPixel4 = xBmp->getPixel( aLayout, geometry::IntegerPoint2D(5,0) );
296 test( aPixel3 == aPixel4,
297 "Green pixel from bitmap matches with manually converted green pixel" );
298
299 if( !aContainedBmpEx.IsTransparent() )
300 {
301 aPixel3 = xBmp->convertIntegerFromRGB( aRGBColor );
302 test( aPixel3 == aPixel4,
303 "Green pixel from bitmap matches with manually RGB-converted green pixel" );
304 }
305 }
306 }
307
308 //----------------------------------------------------------------------------------
309
checkBitmapImport(const rtl::Reference<VclCanvasBitmap> & xBmp,const char * msg,int nOriginalDepth)310 void checkBitmapImport( const rtl::Reference<VclCanvasBitmap>& xBmp,
311 const char* msg,
312 int nOriginalDepth )
313 {
314 OSL_TRACE("-------------------------");
315 OSL_TRACE("Testing %s, with depth %d", msg, nOriginalDepth);
316
317 BitmapEx aContainedBmpEx( xBmp->getBitmapEx() );
318 Bitmap aContainedBmp( aContainedBmpEx.GetBitmap() );
319 int nDepth = nOriginalDepth;
320
321 {
322 ScopedBitmapReadAccess pAcc( aContainedBmp.AcquireReadAccess(),
323 aContainedBmp );
324 nDepth = pAcc->GetBitCount();
325 }
326
327 test( aContainedBmp.GetSizePixel() == Size(200,200),
328 "Original bitmap size" );
329
330 test( xBmp->getSize().Width == 200 && xBmp->getSize().Height == 200,
331 "Original bitmap size via API" );
332
333 test( xBmp->hasAlpha() == aContainedBmpEx.IsTransparent(),
334 "Correct alpha state" );
335
336 test( xBmp->getScaledBitmap( geometry::RealSize2D(500,500), sal_False ).is(),
337 "getScaledBitmap()" );
338
339 rendering::IntegerBitmapLayout aLayout;
340 uno::Sequence<sal_Int8> aPixelData = xBmp->getData(aLayout, geometry::IntegerRectangle2D(0,0,1,1));
341
342 const sal_Int32 nExpectedBitsPerPixel(
343 aContainedBmpEx.IsTransparent() ? std::max(8,nDepth)+8 : nDepth);
344 test( aLayout.ScanLines == 1,
345 "# scanlines" );
346 test( aLayout.ScanLineBytes == (nExpectedBitsPerPixel+7)/8,
347 "# scanline bytes" );
348 test( aLayout.ScanLineStride == (nExpectedBitsPerPixel+7)/8 ||
349 aLayout.ScanLineStride == -(nExpectedBitsPerPixel+7)/8,
350 "# scanline stride" );
351 test( aLayout.PlaneStride == 0,
352 "# plane stride" );
353
354 test( aLayout.ColorSpace.is(),
355 "Color space there" );
356
357 test( aLayout.Palette.is() == (nDepth <= 8),
358 "Palette existance conforms to bitmap" );
359
360 uno::Sequence<sal_Int8> aPixelData2 = xBmp->getPixel( aLayout, geometry::IntegerPoint2D(0,0) );
361
362 test( aPixelData2.getLength() == aPixelData.getLength(),
363 "getData and getPixel return same amount of data" );
364
365 aPixelData = xBmp->getData(aLayout, geometry::IntegerRectangle2D(0,0,200,1));
366 test( aLayout.ScanLines == 1,
367 "# scanlines" );
368 test( aLayout.ScanLineBytes == (200*nExpectedBitsPerPixel+7)/8,
369 "# scanline bytes" );
370 test( aLayout.ScanLineStride == (200*nExpectedBitsPerPixel+7)/8 ||
371 aLayout.ScanLineStride == -(200*nExpectedBitsPerPixel+7)/8,
372 "# scanline stride" );
373
374 uno::Sequence< rendering::RGBColor > aRGBColors = xBmp->convertIntegerToRGB( aPixelData );
375 uno::Sequence< rendering::ARGBColor > aARGBColors = xBmp->convertIntegerToARGB( aPixelData );
376
377 const rendering::RGBColor* pRGBStart ( aRGBColors.getConstArray() );
378 const rendering::RGBColor* pRGBEnd ( aRGBColors.getConstArray()+aRGBColors.getLength() );
379 const rendering::ARGBColor* pARGBStart( aARGBColors.getConstArray() );
380 std::pair<const rendering::RGBColor*,
381 const rendering::ARGBColor*> aRes = std::mismatch( pRGBStart, pRGBEnd, pARGBStart );
382 test( aRes.first == pRGBEnd,
383 "argb and rgb colors are equal" );
384
385 test( std::find_if(pRGBStart,pRGBEnd,&rangeCheck) == pRGBEnd,
386 "rgb colors are within [0,1] range" );
387
388 test( pRGBStart[0].Red == 1.0 && pRGBStart[0].Green == 1.0 && pRGBStart[0].Blue == 1.0,
389 "First pixel is white" );
390 test( pARGBStart[1].Alpha == 1.0,
391 "Second pixel is opaque" );
392 if( aContainedBmpEx.IsTransparent() )
393 {
394 test( pARGBStart[0].Alpha == 0.0,
395 "First pixel is fully transparent" );
396 }
397
398 test( pRGBStart[1].Red == 0.0 && pRGBStart[1].Green == 0.0 && pRGBStart[1].Blue == 0.0,
399 "Second pixel is black" );
400
401 if( nOriginalDepth > 8 )
402 {
403 const Color aCol(COL_GREEN);
404 test( pRGBStart[5].Red == vcl::unotools::toDoubleColor(aCol.GetRed()) &&
405 pRGBStart[5].Green == vcl::unotools::toDoubleColor(aCol.GetGreen()) &&
406 pRGBStart[5].Blue == vcl::unotools::toDoubleColor(aCol.GetBlue()),
407 "Sixth pixel is green" );
408 }
409 else if( nDepth <= 8 )
410 {
411 uno::Reference<rendering::XBitmapPalette> xPal = xBmp->getPalette();
412 test( xPal.is(),
413 "8bit or less: needs palette" );
414 test( xPal->getNumberOfEntries() == 1L << nOriginalDepth,
415 "Palette has correct entry count" );
416 uno::Sequence<double> aIndex;
417 test( xPal->setIndex(aIndex,sal_True,0) == sal_False,
418 "Palette is read-only" );
419 test( xPal->getIndex(aIndex,0),
420 "Palette entry 0 is opaque" );
421 test( xPal->getColorSpace().is(),
422 "Palette has a valid color space" );
423 }
424
425 test( pRGBStart[150].Red == 1.0 && pRGBStart[150].Green == 1.0 && pRGBStart[150].Blue == 1.0,
426 "150th pixel is white" );
427
428 if( nOriginalDepth > 8 )
429 {
430 const uno::Sequence<sal_Int8> aComponentTags( xBmp->getComponentTags() );
431 uno::Sequence<rendering::ARGBColor> aARGBColor(1);
432 uno::Sequence<rendering::RGBColor> aRGBColor(1);
433 uno::Sequence<sal_Int8> aPixel3, aPixel4;
434
435 const Color aCol(COL_GREEN);
436 aARGBColor[0].Red = vcl::unotools::toDoubleColor(aCol.GetRed());
437 aARGBColor[0].Green = vcl::unotools::toDoubleColor(aCol.GetGreen());
438 aARGBColor[0].Blue = vcl::unotools::toDoubleColor(aCol.GetBlue());
439 aARGBColor[0].Alpha = 1.0;
440
441 aRGBColor[0].Red = vcl::unotools::toDoubleColor(aCol.GetRed());
442 aRGBColor[0].Green = vcl::unotools::toDoubleColor(aCol.GetGreen());
443 aRGBColor[0].Blue = vcl::unotools::toDoubleColor(aCol.GetBlue());
444
445 aPixel3 = xBmp->convertIntegerFromARGB( aARGBColor );
446 aPixel4 = xBmp->getPixel( aLayout, geometry::IntegerPoint2D(5,0) );
447 test( aPixel3 == aPixel4,
448 "Green pixel from bitmap matches with manually converted green pixel" );
449
450 if( !aContainedBmpEx.IsTransparent() )
451 {
452 aPixel3 = xBmp->convertIntegerFromRGB( aRGBColor );
453 test( aPixel3 == aPixel4,
454 "Green pixel from bitmap matches with manually RGB-converted green pixel" );
455 }
456 }
457 }
458
459 //----------------------------------------------------------------------------------
460
461 class TestBitmap : public cppu::WeakImplHelper3< rendering::XIntegerReadOnlyBitmap,
462 rendering::XBitmapPalette,
463 rendering::XIntegerBitmapColorSpace >
464 {
465 private:
466 geometry::IntegerSize2D maSize;
467 uno::Sequence<sal_Int8> maComponentTags;
468 uno::Sequence<sal_Int32> maComponentBitCounts;
469 rendering::IntegerBitmapLayout maLayout;
470 const sal_Int32 mnBitsPerPixel;
471
472 // XBitmap
getSize()473 virtual geometry::IntegerSize2D SAL_CALL getSize() throw (uno::RuntimeException) { return maSize; }
hasAlpha()474 virtual ::sal_Bool SAL_CALL hasAlpha( ) throw (uno::RuntimeException) { return mnBitsPerPixel != 8; }
getScaledBitmap(const geometry::RealSize2D &,sal_Bool)475 virtual uno::Reference< rendering::XBitmap > SAL_CALL getScaledBitmap( const geometry::RealSize2D&,
476 sal_Bool ) throw (uno::RuntimeException) { return this; }
477
478 // XIntegerReadOnlyBitmap
getData(rendering::IntegerBitmapLayout & bitmapLayout,const geometry::IntegerRectangle2D & rect)479 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getData( rendering::IntegerBitmapLayout& bitmapLayout,
480 const geometry::IntegerRectangle2D& rect ) throw (lang::IndexOutOfBoundsException,
481 rendering::VolatileContentDestroyedException, uno::RuntimeException)
482 {
483 test( rect.X1 >= 0, "X1 within bounds" );
484 test( rect.Y1 >= 0, "Y1 within bounds" );
485 test( rect.X2 <= maSize.Width, "X2 within bounds" );
486 test( rect.Y2 <= maSize.Height, "Y2 within bounds" );
487
488 bitmapLayout = getMemoryLayout();
489
490 const sal_Int32 nWidth = rect.X2-rect.X1;
491 const sal_Int32 nHeight = rect.Y2-rect.Y1;
492 const sal_Int32 nScanlineLen = (nWidth * mnBitsPerPixel + 7)/8;
493 uno::Sequence<sal_Int8> aRes( nScanlineLen * nHeight );
494 sal_Int8* pOut = aRes.getArray();
495
496 bitmapLayout.ScanLines = nHeight;
497 bitmapLayout.ScanLineBytes =
498 bitmapLayout.ScanLineStride= nScanlineLen;
499
500 if( mnBitsPerPixel == 8 )
501 {
502 for( sal_Int32 y=0; y<nHeight; ++y )
503 {
504 for( sal_Int32 x=0; x<nWidth; ++x )
505 pOut[ y*nScanlineLen + x ] = sal_Int8(x);
506 }
507 }
508 else
509 {
510 for( sal_Int32 y=0; y<nHeight; ++y )
511 {
512 for( sal_Int32 x=0; x<nWidth; ++x )
513 {
514 pOut[ y*nScanlineLen + 4*x ] = sal_Int8(rect.X1);
515 pOut[ y*nScanlineLen + 4*x + 1 ] = sal_Int8(rect.Y2);
516 pOut[ y*nScanlineLen + 4*x + 2 ] = sal_Int8(x);
517 pOut[ y*nScanlineLen + 4*x + 3 ] = sal_Int8(rect.Y1);
518 }
519 }
520 }
521
522 return aRes;
523 }
524
getPixel(rendering::IntegerBitmapLayout &,const geometry::IntegerPoint2D &)525 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getPixel( rendering::IntegerBitmapLayout&,
526 const geometry::IntegerPoint2D& ) throw (lang::IndexOutOfBoundsException,
527 rendering::VolatileContentDestroyedException, uno::RuntimeException)
528 {
529 test(false, "Method not implemented");
530 return uno::Sequence< sal_Int8 >();
531 }
532
getPalette()533 virtual uno::Reference< rendering::XBitmapPalette > SAL_CALL getPalette( ) throw (uno::RuntimeException)
534 {
535 uno::Reference< XBitmapPalette > aRet;
536 if( mnBitsPerPixel == 8 )
537 aRet.set(this);
538 return aRet;
539 }
540
getMemoryLayout()541 virtual rendering::IntegerBitmapLayout SAL_CALL getMemoryLayout( ) throw (uno::RuntimeException)
542 {
543 rendering::IntegerBitmapLayout aLayout( maLayout );
544
545 const sal_Int32 nScanlineLen = (maSize.Width * mnBitsPerPixel + 7)/8;
546
547 aLayout.ScanLines = maSize.Height;
548 aLayout.ScanLineBytes =
549 aLayout.ScanLineStride= nScanlineLen;
550 aLayout.Palette = getPalette();
551 aLayout.ColorSpace.set( this );
552
553 return aLayout;
554 }
555
556 // XBitmapPalette
getNumberOfEntries()557 virtual sal_Int32 SAL_CALL getNumberOfEntries() throw (uno::RuntimeException)
558 {
559 test( getPalette().is(),
560 "Got palette interface call without handing out palette?!" );
561
562 return 255;
563 }
564
getIndex(uno::Sequence<double> & entry,::sal_Int32 nIndex)565 virtual ::sal_Bool SAL_CALL getIndex( uno::Sequence< double >& entry,
566 ::sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException,
567 uno::RuntimeException)
568 {
569 test( getPalette().is(),
570 "Got palette interface call without handing out palette?!" );
571 test( nIndex >= 0 && nIndex < 256,
572 "Index out of range" );
573 entry = colorToStdColorSpaceSequence(
574 Color(UINT8(nIndex),
575 UINT8(nIndex),
576 UINT8(nIndex)) );
577
578 return sal_True; // no palette transparency here.
579 }
580
setIndex(const uno::Sequence<double> &,::sal_Bool,::sal_Int32 nIndex)581 virtual ::sal_Bool SAL_CALL setIndex( const uno::Sequence< double >&,
582 ::sal_Bool,
583 ::sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException,
584 lang::IllegalArgumentException,
585 uno::RuntimeException)
586 {
587 test( getPalette().is(),
588 "Got palette interface call without handing out palette?!" );
589 test( nIndex >= 0 && nIndex < 256,
590 "Index out of range" );
591 return sal_False;
592 }
593
594 struct PaletteColorSpaceHolder: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>,
595 PaletteColorSpaceHolder>
596 {
operator ()__anond1d47db40111::TestBitmap::PaletteColorSpaceHolder597 uno::Reference<rendering::XColorSpace> operator()()
598 {
599 return vcl::unotools::createStandardColorSpace();
600 }
601 };
602
getColorSpace()603 virtual uno::Reference< rendering::XColorSpace > SAL_CALL getColorSpace( ) throw (uno::RuntimeException)
604 {
605 // this is the method from XBitmapPalette. Return palette color
606 // space here
607 return PaletteColorSpaceHolder::get();
608 }
609
610 // XIntegerBitmapColorSpace
getType()611 virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException)
612 {
613 return rendering::ColorSpaceType::RGB;
614 }
615
getComponentTags()616 virtual uno::Sequence< sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException)
617 {
618 return maComponentTags;
619 }
620
getRenderingIntent()621 virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException)
622 {
623 return rendering::RenderingIntent::PERCEPTUAL;
624 }
625
getProperties()626 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException)
627 {
628 test(false, "Method not implemented");
629 return uno::Sequence< ::beans::PropertyValue >();
630 }
631
convertColorSpace(const uno::Sequence<double> &,const uno::Reference<rendering::XColorSpace> &)632 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >&,
633 const uno::Reference< rendering::XColorSpace >& ) throw (uno::RuntimeException)
634 {
635 test(false, "Method not implemented");
636 return uno::Sequence< double >();
637 }
638
convertToRGB(const uno::Sequence<double> &)639 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& ) throw (lang::IllegalArgumentException,
640 uno::RuntimeException)
641 {
642 test(false, "Method not implemented");
643 return uno::Sequence< rendering::RGBColor >();
644 }
645
convertToARGB(const uno::Sequence<double> &)646 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& ) throw (lang::IllegalArgumentException,
647 uno::RuntimeException)
648 {
649 test(false, "Method not implemented");
650 return uno::Sequence< rendering::ARGBColor >();
651 }
652
convertToPARGB(const uno::Sequence<double> &)653 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& ) throw (lang::IllegalArgumentException,
654 uno::RuntimeException)
655 {
656 test(false, "Method not implemented");
657 return uno::Sequence< rendering::ARGBColor >();
658 }
659
convertFromRGB(const uno::Sequence<rendering::RGBColor> &)660 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& ) throw (lang::IllegalArgumentException,
661 uno::RuntimeException)
662 {
663 test(false, "Method not implemented");
664 return uno::Sequence< double >();
665 }
666
convertFromARGB(const uno::Sequence<rendering::ARGBColor> &)667 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& ) throw (lang::IllegalArgumentException,
668 uno::RuntimeException)
669 {
670 test(false, "This method is not expected to be called!");
671 return uno::Sequence< double >();
672 }
673
convertFromPARGB(const uno::Sequence<rendering::ARGBColor> &)674 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& ) throw (lang::IllegalArgumentException,
675 uno::RuntimeException)
676 {
677 test(false, "This method is not expected to be called!");
678 return uno::Sequence< double >();
679 }
680
getBitsPerPixel()681 virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException)
682 {
683 return mnBitsPerPixel;
684 }
685
getComponentBitCounts()686 virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException)
687 {
688 return maComponentBitCounts;
689 }
690
getEndianness()691 virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException)
692 {
693 return util::Endianness::LITTLE;
694 }
695
convertFromIntegerColorSpace(const uno::Sequence<::sal_Int8> &,const uno::Reference<rendering::XColorSpace> &)696 virtual uno::Sequence< double > SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& ,
697 const uno::Reference< rendering::XColorSpace >& ) throw (lang::IllegalArgumentException,
698 uno::RuntimeException)
699 {
700 test(false, "Method not implemented");
701 return uno::Sequence< double >();
702 }
703
convertToIntegerColorSpace(const uno::Sequence<::sal_Int8> &,const uno::Reference<rendering::XIntegerBitmapColorSpace> &)704 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& ,
705 const uno::Reference< rendering::XIntegerBitmapColorSpace >& ) throw (lang::IllegalArgumentException,
706 uno::RuntimeException)
707 {
708 test(false, "Method not implemented");
709 return uno::Sequence< sal_Int8 >();
710 }
711
convertIntegerToRGB(const uno::Sequence<::sal_Int8> & deviceColor)712 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,
713 uno::RuntimeException)
714 {
715 const uno::Sequence< rendering::ARGBColor > aTemp( convertIntegerToARGB(deviceColor) );
716 const sal_Size nLen(aTemp.getLength());
717 uno::Sequence< rendering::RGBColor > aRes( nLen );
718 rendering::RGBColor* pOut = aRes.getArray();
719 for( sal_Size i=0; i<nLen; ++i )
720 {
721 *pOut++ = rendering::RGBColor(aTemp[i].Red,
722 aTemp[i].Green,
723 aTemp[i].Blue);
724 }
725
726 return aRes;
727 }
728
convertIntegerToARGB(const uno::Sequence<::sal_Int8> & deviceColor)729 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,
730 uno::RuntimeException)
731 {
732 const sal_Size nLen( deviceColor.getLength() );
733 const sal_Int32 nBytesPerPixel(mnBitsPerPixel == 8 ? 1 : 4);
734 test(nLen%nBytesPerPixel==0,
735 "number of channels no multiple of pixel element count");
736
737 uno::Sequence< rendering::ARGBColor > aRes( nLen / nBytesPerPixel );
738 rendering::ARGBColor* pOut( aRes.getArray() );
739
740 if( getPalette().is() )
741 {
742 for( sal_Size i=0; i<nLen; ++i )
743 {
744 *pOut++ = rendering::ARGBColor(
745 1.0,
746 vcl::unotools::toDoubleColor(deviceColor[i]),
747 vcl::unotools::toDoubleColor(deviceColor[i]),
748 vcl::unotools::toDoubleColor(deviceColor[i]));
749 }
750 }
751 else
752 {
753 for( sal_Size i=0; i<nLen; i+=4 )
754 {
755 *pOut++ = rendering::ARGBColor(
756 vcl::unotools::toDoubleColor(deviceColor[i+3]),
757 vcl::unotools::toDoubleColor(deviceColor[i+0]),
758 vcl::unotools::toDoubleColor(deviceColor[i+1]),
759 vcl::unotools::toDoubleColor(deviceColor[i+2]));
760 }
761 }
762
763 return aRes;
764 }
765
convertIntegerToPARGB(const uno::Sequence<::sal_Int8> & deviceColor)766 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException,
767 uno::RuntimeException)
768 {
769 const sal_Size nLen( deviceColor.getLength() );
770 const sal_Int32 nBytesPerPixel(mnBitsPerPixel == 8 ? 1 : 4);
771 test(nLen%nBytesPerPixel==0,
772 "number of channels no multiple of pixel element count");
773
774 uno::Sequence< rendering::ARGBColor > aRes( nLen / nBytesPerPixel );
775 rendering::ARGBColor* pOut( aRes.getArray() );
776
777 if( getPalette().is() )
778 {
779 for( sal_Size i=0; i<nLen; ++i )
780 {
781 *pOut++ = rendering::ARGBColor(
782 1.0,
783 vcl::unotools::toDoubleColor(deviceColor[i]),
784 vcl::unotools::toDoubleColor(deviceColor[i]),
785 vcl::unotools::toDoubleColor(deviceColor[i]));
786 }
787 }
788 else
789 {
790 for( sal_Size i=0; i<nLen; i+=4 )
791 {
792 const double fAlpha=vcl::unotools::toDoubleColor(deviceColor[i+3]);
793 *pOut++ = rendering::ARGBColor(
794 fAlpha,
795 fAlpha*vcl::unotools::toDoubleColor(deviceColor[i+0]),
796 fAlpha*vcl::unotools::toDoubleColor(deviceColor[i+1]),
797 fAlpha*vcl::unotools::toDoubleColor(deviceColor[i+2]));
798 }
799 }
800
801 return aRes;
802 }
803
convertIntegerFromRGB(const uno::Sequence<rendering::RGBColor> &)804 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& ) throw (lang::IllegalArgumentException,
805 uno::RuntimeException)
806 {
807 test(false, "Method not implemented");
808 return uno::Sequence< sal_Int8 >();
809 }
810
convertIntegerFromARGB(const uno::Sequence<rendering::ARGBColor> &)811 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& ) throw (lang::IllegalArgumentException,
812 uno::RuntimeException)
813 {
814 test(false, "Method not implemented");
815 return uno::Sequence< sal_Int8 >();
816 }
817
convertIntegerFromPARGB(const uno::Sequence<rendering::ARGBColor> &)818 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& ) throw (lang::IllegalArgumentException,
819 uno::RuntimeException)
820 {
821 test(false, "Method not implemented");
822 return uno::Sequence< sal_Int8 >();
823 }
824
825 public:
TestBitmap(const geometry::IntegerSize2D & rSize,bool bPalette)826 TestBitmap( const geometry::IntegerSize2D& rSize, bool bPalette ) :
827 maSize(rSize),
828 maComponentTags(),
829 maComponentBitCounts(),
830 maLayout(),
831 mnBitsPerPixel( bPalette ? 8 : 32 )
832 {
833 if( bPalette )
834 {
835 maComponentTags.realloc(1);
836 maComponentTags[0] = rendering::ColorComponentTag::INDEX;
837
838 maComponentBitCounts.realloc(1);
839 maComponentBitCounts[0] = 8;
840 }
841 else
842 {
843 maComponentTags.realloc(4);
844 sal_Int8* pTags = maComponentTags.getArray();
845 pTags[0] = rendering::ColorComponentTag::RGB_BLUE;
846 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
847 pTags[2] = rendering::ColorComponentTag::RGB_RED;
848 pTags[3] = rendering::ColorComponentTag::ALPHA;
849
850 maComponentBitCounts.realloc(4);
851 sal_Int32* pCounts = maComponentBitCounts.getArray();
852 pCounts[0] = 8;
853 pCounts[1] = 8;
854 pCounts[2] = 8;
855 pCounts[3] = 8;
856 }
857
858 maLayout.ScanLines = 0;
859 maLayout.ScanLineBytes = 0;
860 maLayout.ScanLineStride = 0;
861 maLayout.PlaneStride = 0;
862 maLayout.ColorSpace.clear();
863 maLayout.Palette.clear();
864 maLayout.IsMsbFirst = sal_False;
865 }
866 };
867
868
869 //----------------------------------------------------------------------------------
870
Paint(const Rectangle &)871 void TestWindow::Paint( const Rectangle& )
872 {
873 static sal_Int8 lcl_depths[]={1,4,8,16,24};
874
875 try
876 {
877 // Testing VclCanvasBitmap wrapper
878 // ===============================
879
880 for( unsigned int i=0; i<sizeof(lcl_depths)/sizeof(*lcl_depths); ++i )
881 {
882 const sal_Int8 nDepth( lcl_depths[i] );
883 Bitmap aBitmap(Size(200,200),nDepth);
884 aBitmap.Erase(COL_WHITE);
885 {
886 ScopedBitmapWriteAccess pAcc(aBitmap.AcquireWriteAccess(),
887 aBitmap);
888 if( pAcc.get() )
889 {
890 BitmapColor aBlack(0);
891 BitmapColor aWhite(0);
892 if( pAcc->HasPalette() )
893 {
894 aBlack.SetIndex( sal::static_int_cast<BYTE>(pAcc->GetBestPaletteIndex(BitmapColor(0,0,0))) );
895 aWhite.SetIndex( sal::static_int_cast<BYTE>(pAcc->GetBestPaletteIndex(BitmapColor(255,255,255))) );
896 }
897 else
898 {
899 aBlack = Color(COL_BLACK);
900 aWhite = Color(COL_WHITE);
901 }
902 pAcc->SetFillColor(COL_GREEN);
903 pAcc->FillRect(Rectangle(0,0,100,100));
904 pAcc->SetPixel(0,0,aWhite);
905 pAcc->SetPixel(0,1,aBlack);
906 pAcc->SetPixel(0,2,aWhite);
907 }
908 }
909
910 rtl::Reference<VclCanvasBitmap> xBmp( new VclCanvasBitmap(aBitmap) );
911
912 checkCanvasBitmap( xBmp, "single bitmap", nDepth );
913
914 Bitmap aMask(Size(200,200),1);
915 aMask.Erase(COL_WHITE);
916 {
917 ScopedBitmapWriteAccess pAcc(aMask.AcquireWriteAccess(),
918 aMask);
919 if( pAcc.get() )
920 {
921 pAcc->SetFillColor(COL_BLACK);
922 pAcc->FillRect(Rectangle(0,0,100,100));
923 pAcc->SetPixel(0,0,BitmapColor(1));
924 pAcc->SetPixel(0,1,BitmapColor(0));
925 pAcc->SetPixel(0,2,BitmapColor(1));
926 }
927 }
928
929 xBmp.set( new VclCanvasBitmap(BitmapEx(aBitmap,aMask)) );
930
931 checkCanvasBitmap( xBmp, "masked bitmap", nDepth );
932
933 AlphaMask aAlpha(Size(200,200));
934 aAlpha.Erase(255);
935 {
936 BitmapWriteAccess* pAcc = aAlpha.AcquireWriteAccess();
937 if( pAcc )
938 {
939 pAcc->SetFillColor(COL_BLACK);
940 pAcc->FillRect(Rectangle(0,0,100,100));
941 pAcc->SetPixel(0,0,BitmapColor(255));
942 pAcc->SetPixel(0,1,BitmapColor(0));
943 pAcc->SetPixel(0,2,BitmapColor(255));
944 aAlpha.ReleaseAccess(pAcc);
945 }
946 }
947
948 xBmp.set( new VclCanvasBitmap(BitmapEx(aBitmap,aAlpha)) );
949
950 checkCanvasBitmap( xBmp, "alpha bitmap", nDepth );
951 }
952
953 // Testing XBitmap import
954 // ======================
955 uno::Reference< rendering::XIntegerReadOnlyBitmap > xTestBmp(
956 new TestBitmap( geometry::IntegerSize2D(10,10), true ));
957
958 BitmapEx aBmp = vcl::unotools::bitmapExFromXBitmap(xTestBmp);
959 test( aBmp.IsTransparent() == false,
960 "Palette bitmap is not transparent" );
961 test( aBmp.GetSizePixel() == Size(10,10),
962 "Bitmap has size (10,10)" );
963 test( aBmp.GetBitCount() == 8,
964 "Bitmap has bitcount of 8" );
965 {
966 BitmapReadAccess* pBmpAcc = aBmp.GetBitmap().AcquireReadAccess();
967
968 test( pBmpAcc,
969 "Bitmap has valid BitmapReadAccess" );
970
971 test(pBmpAcc->GetPixel(0,0) == BitmapColor(0),
972 "(0,0) correct content");
973 test(pBmpAcc->GetPixel(2,2) == BitmapColor(2),
974 "(2,2) correct content");
975 test(pBmpAcc->GetPixel(2,9) == BitmapColor(9),
976 "(9,2) correct content");
977
978 aBmp.GetBitmap().ReleaseAccess(pBmpAcc);
979 }
980
981 xTestBmp.set( new TestBitmap( geometry::IntegerSize2D(10,10), false ));
982
983 aBmp = vcl::unotools::bitmapExFromXBitmap(xTestBmp);
984 test( aBmp.IsTransparent() == TRUE,
985 "Palette bitmap is transparent" );
986 test( aBmp.IsAlpha() == TRUE,
987 "Palette bitmap has alpha" );
988 test( aBmp.GetSizePixel() == Size(10,10),
989 "Bitmap has size (10,10)" );
990 test( aBmp.GetBitCount() == 24,
991 "Bitmap has bitcount of 24" );
992 {
993 BitmapReadAccess* pBmpAcc = aBmp.GetBitmap().AcquireReadAccess();
994 BitmapReadAccess* pAlphaAcc = aBmp.GetAlpha().AcquireReadAccess();
995
996 test( pBmpAcc,
997 "Bitmap has valid BitmapReadAccess" );
998 test( pAlphaAcc,
999 "Bitmap has valid alpha BitmapReadAccess" );
1000
1001 test(pBmpAcc->GetPixel(0,0) == BitmapColor(0,1,0),
1002 "(0,0) correct content");
1003 test(pAlphaAcc->GetPixel(0,0) == BitmapColor(255),
1004 "(0,0) correct alpha content");
1005 test(pBmpAcc->GetPixel(2,2) == BitmapColor(0,3,2),
1006 "(2,2) correct content");
1007 test(pAlphaAcc->GetPixel(2,2) == BitmapColor(253),
1008 "(2,2) correct alpha content");
1009 test(pBmpAcc->GetPixel(2,9) == BitmapColor(0,3,9),
1010 "(9,2) correct content");
1011 test(pAlphaAcc->GetPixel(2,9) == BitmapColor(253),
1012 "(9,2) correct alpha content");
1013
1014 aBmp.GetAlpha().ReleaseAccess(pAlphaAcc);
1015 aBmp.GetBitmap().ReleaseAccess(pBmpAcc);
1016 }
1017 }
1018 catch( uno::Exception& )
1019 {
1020 DBG_UNHANDLED_EXCEPTION();
1021 exit(2);
1022 }
1023 catch( std::exception& )
1024 {
1025 OSL_TRACE( "Caught std exception!" );
1026 }
1027
1028 if( g_failure )
1029 exit(2);
1030 }
1031
1032 } // namespace
1033
Main()1034 void Main()
1035 {
1036 TestWindow aWindow;
1037 aWindow.Execute();
1038 aWindow.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "VCL - canvasbitmaptest" ) ) );
1039
1040 Application::Execute();
1041 }
1042
1043