From 642b86aa541aa977143ac5a084550f3390423926 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Thu, 22 Nov 2012 09:41:19 +0100 Subject: fix 3D 'fade' transitions * canvas bitmaps created without transparency get an appropriate color space * implement a color space for OpenGL RGBA to use instead of canvas::tools::getStdColorSpace(), which apparently uses VCL's interpretation of alpha (alpha == 0xff means full transparency, alpha == 0 full opacity). Change-Id: I97f30533206b75132abd0bb0d290a279f15ae8a9 --- canvas/inc/canvas/canvastools.hxx | 8 + canvas/source/cairo/cairo_canvashelper.cxx | 327 +++++++++++++++++- canvas/source/cairo/cairo_canvashelper.hxx | 2 + canvas/source/tools/canvastools.cxx | 348 +++++++++++++++++++ canvas/source/vcl/canvasbitmaphelper.cxx | 6 +- canvas/source/vcl/canvashelper.cxx | 6 +- canvas/source/vcl/devicehelper.cxx | 4 +- .../OGLTrans/unx/OGLTrans_TransitionerImpl.cxx | 367 ++++++++++++++++++++- 8 files changed, 1054 insertions(+), 14 deletions(-) diff --git a/canvas/inc/canvas/canvastools.hxx b/canvas/inc/canvas/canvastools.hxx index 4f38c0b07527..b2627d49c357 100644 --- a/canvas/inc/canvas/canvastools.hxx +++ b/canvas/inc/canvas/canvastools.hxx @@ -359,6 +359,14 @@ namespace canvas */ CANVASTOOLS_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XIntegerBitmapColorSpace> getStdColorSpace(); + /** Return a color space for a default RGB integer format + + Use this method for dead-simple bitmap implementations, + that map all their formats to 8888 RGB color (the last byte + is unused). + */ + CANVASTOOLS_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XIntegerBitmapColorSpace> getStdColorSpaceWithoutAlpha(); + /** Return a memory layout for a default RGBA integer format Use this method for dead-simple bitmap implementations, diff --git a/canvas/source/cairo/cairo_canvashelper.cxx b/canvas/source/cairo/cairo_canvashelper.cxx index f18d2dce0492..cbda60a0bc95 100644 --- a/canvas/source/cairo/cairo_canvashelper.cxx +++ b/canvas/source/cairo/cairo_canvashelper.cxx @@ -1583,14 +1583,13 @@ namespace cairocanvas { if( mpCairo ) { - aLayout = getMemoryLayout(); - const sal_Int32 nWidth( rect.X2 - rect.X1 ); const sal_Int32 nHeight( rect.Y2 - rect.Y1 ); + const Format eFormat( mbHaveAlpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24 ); uno::Sequence< sal_Int8 > aRes( 4*nWidth*nHeight ); sal_Int8* pData = aRes.getArray(); cairo_surface_t* pImageSurface = cairo_image_surface_create_for_data( (unsigned char *) pData, - CAIRO_FORMAT_ARGB32, + eFormat, nWidth, nHeight, 4*nWidth ); cairo_t* pCairo = cairo_create( pImageSurface ); cairo_set_source_surface( pCairo, mpSurface->getCairoSurface().get(), -rect.X1, -rect.Y1); @@ -1598,9 +1597,7 @@ namespace cairocanvas cairo_destroy( pCairo ); cairo_surface_destroy( pImageSurface ); - aLayout.ScanLines = nHeight; - aLayout.ScanLineBytes = nWidth*4; - aLayout.ScanLineStride = aLayout.ScanLineBytes; + aLayout = impl_getMemoryLayout( nWidth, nHeight ); return aRes; } @@ -1985,6 +1982,310 @@ namespace cairocanvas } }; + class CairoNoAlphaColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XIntegerBitmapColorSpace > + { + private: + uno::Sequence< sal_Int8 > maComponentTags; + uno::Sequence< sal_Int32 > maBitCounts; + + virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException) + { + return rendering::ColorSpaceType::RGB; + } + virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException) + { + return maComponentTags; + } + virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException) + { + return rendering::RenderingIntent::PERCEPTUAL; + } + virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException) + { + return uno::Sequence< beans::PropertyValue >(); + } + virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor, + const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, + uno::RuntimeException) + { + // TODO(P3): if we know anything about target + // colorspace, this can be greatly sped up + uno::Sequence aIntermediate( + convertToARGB(deviceColor)); + return targetColorSpace->convertFromARGB(aIntermediate); + } + virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const double* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::RGBColor > aRes(nLen/4); + rendering::RGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i impl_convertToARGB( const uno::Sequence< double >& deviceColor ) + { + const double* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + return impl_convertToARGB( deviceColor ); + } + virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + return impl_convertToARGB( deviceColor ); + } + virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::RGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< double > aRes(nLen*4); + double* pColors=aRes.getArray(); + for( sal_Size i=0; iBlue; + *pColors++ = pIn->Green; + *pColors++ = pIn->Red; + *pColors++ = 1.0; // the value does not matter + ++pIn; + } + return aRes; + } + uno::Sequence< double > impl_convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< double > aRes(nLen*4); + double* pColors=aRes.getArray(); + for( sal_Size i=0; iBlue; + *pColors++ = pIn->Green; + *pColors++ = pIn->Red; + *pColors++ = 1.0; // the value does not matter + ++pIn; + } + return aRes; + } + virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + return impl_convertFromARGB( rgbColor ); + } + virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + return impl_convertFromARGB( rgbColor ); + } + + // XIntegerBitmapColorSpace + virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException) + { + return 32; + } + virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException) + { + return maBitCounts; + } + virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException) + { + return util::Endianness::LITTLE; + } + virtual uno::Sequence SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor, + const uno::Reference< rendering::XColorSpace >& targetColorSpace ) + throw (lang::IllegalArgumentException, uno::RuntimeException) + { + if( dynamic_cast(targetColorSpace.get()) ) + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence aRes(nLen); + double* pOut( aRes.getArray() ); + for( sal_Size i=0; i aIntermediate( + convertIntegerToARGB(deviceColor)); + return targetColorSpace->convertFromARGB(aIntermediate); + } + } + virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor, + const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) + throw (lang::IllegalArgumentException, uno::RuntimeException) + { + if( dynamic_cast(targetColorSpace.get()) ) + { + // it's us, so simply pass-through the data + return deviceColor; + } + else + { + // TODO(P3): if we know anything about target + // colorspace, this can be greatly sped up + uno::Sequence aIntermediate( + convertIntegerToARGB(deviceColor)); + return targetColorSpace->convertIntegerFromARGB(aIntermediate); + } + } + virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) + throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::RGBColor > aRes(nLen/4); + rendering::RGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) + throw (lang::IllegalArgumentException, uno::RuntimeException) + { + return impl_convertIntegerToARGB( deviceColor ); + } + virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) + throw (lang::IllegalArgumentException, uno::RuntimeException) + { + return impl_convertIntegerToARGB( deviceColor ); + } + uno::Sequence< rendering::ARGBColor > impl_convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) + throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::RGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< sal_Int8 > aRes(nLen*4); + sal_Int8* pColors=aRes.getArray(); + for( sal_Size i=0; iBlue); + *pColors++ = vcl::unotools::toByteColor(pIn->Green); + *pColors++ = vcl::unotools::toByteColor(pIn->Red); + *pColors++ = -1; // the value does not matter + ++pIn; + } + return aRes; + } + + virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) + throw (lang::IllegalArgumentException, uno::RuntimeException) + { + return impl_convertIntegerFromARGB( rgbColor ); + } + virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) + throw (lang::IllegalArgumentException, uno::RuntimeException) + { + return impl_convertIntegerFromARGB( rgbColor ); + } + uno::Sequence< ::sal_Int8 > impl_convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< sal_Int8 > aRes(nLen*4); + sal_Int8* pColors=aRes.getArray(); + for( sal_Size i=0; iBlue); + *pColors++ = vcl::unotools::toByteColor(pIn->Green); + *pColors++ = vcl::unotools::toByteColor(pIn->Red); + *pColors++ = -1; // the value does not matter + ++pIn; + } + return aRes; + } + + public: + CairoNoAlphaColorSpace() : + maComponentTags(3), + maBitCounts(3) + { + sal_Int8* pTags = maComponentTags.getArray(); + sal_Int32* pBitCounts = maBitCounts.getArray(); + pTags[0] = rendering::ColorComponentTag::RGB_BLUE; + pTags[1] = rendering::ColorComponentTag::RGB_GREEN; + pTags[2] = rendering::ColorComponentTag::RGB_RED; + + pBitCounts[0] = + pBitCounts[1] = + pBitCounts[2] = 8; + } + }; + + struct CairoNoAlphaColorSpaceHolder : public rtl::StaticWithInit, + CairoNoAlphaColorSpaceHolder> + { + uno::Reference operator()() + { + return new CairoNoAlphaColorSpace(); + } + }; + struct CairoColorSpaceHolder : public rtl::StaticWithInit, CairoColorSpaceHolder> { @@ -1993,6 +2294,7 @@ namespace cairocanvas return new CairoColorSpace(); } }; + } rendering::IntegerBitmapLayout CanvasHelper::getMemoryLayout() @@ -2001,13 +2303,20 @@ namespace cairocanvas return rendering::IntegerBitmapLayout(); // we're disposed const geometry::IntegerSize2D aSize(getSize()); + + return impl_getMemoryLayout( aSize.Width, aSize.Height ); + } + + rendering::IntegerBitmapLayout + CanvasHelper::impl_getMemoryLayout( const sal_Int32 nWidth, const sal_Int32 nHeight ) + { rendering::IntegerBitmapLayout aLayout; - aLayout.ScanLines = aSize.Height; - aLayout.ScanLineBytes = aSize.Width*4; + aLayout.ScanLines = nHeight; + aLayout.ScanLineBytes = nWidth*4; aLayout.ScanLineStride = aLayout.ScanLineBytes; aLayout.PlaneStride = 0; - aLayout.ColorSpace = CairoColorSpaceHolder::get(); + aLayout.ColorSpace = mbHaveAlpha ? CairoColorSpaceHolder::get() : CairoNoAlphaColorSpaceHolder::get(); aLayout.Palette.clear(); aLayout.IsMsbFirst = sal_False; diff --git a/canvas/source/cairo/cairo_canvashelper.hxx b/canvas/source/cairo/cairo_canvashelper.hxx index 3ae1de714463..8dc7fdbb8991 100644 --- a/canvas/source/cairo/cairo_canvashelper.hxx +++ b/canvas/source/cairo/cairo_canvashelper.hxx @@ -301,6 +301,8 @@ namespace cairocanvas const ::com::sun::star::rendering::RenderState& renderState, bool setColor ); + com::sun::star::rendering::IntegerBitmapLayout impl_getMemoryLayout( sal_Int32 nWidth, sal_Int32 nHeight ); + /// When true, content is able to represent alpha bool mbHaveAlpha; diff --git a/canvas/source/tools/canvastools.cxx b/canvas/source/tools/canvastools.cxx index a3dcfa6c5223..25977f6527a9 100644 --- a/canvas/source/tools/canvastools.cxx +++ b/canvas/source/tools/canvastools.cxx @@ -557,6 +557,340 @@ namespace canvas } }; + class StandardNoAlphaColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XIntegerBitmapColorSpace > + { + private: + uno::Sequence< sal_Int8 > maComponentTags; + uno::Sequence< sal_Int32 > maBitCounts; + + virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException) + { + return rendering::ColorSpaceType::RGB; + } + virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException) + { + return maComponentTags; + } + virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException) + { + return rendering::RenderingIntent::PERCEPTUAL; + } + virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException) + { + return uno::Sequence< beans::PropertyValue >(); + } + virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor, + const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, + uno::RuntimeException) + { + // TODO(P3): if we know anything about target + // colorspace, this can be greatly sped up + uno::Sequence aIntermediate( + convertToARGB(deviceColor)); + return targetColorSpace->convertFromARGB(aIntermediate); + } + virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const double* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::RGBColor > aRes(nLen/4); + rendering::RGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const double* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const double* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::RGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< double > aRes(nLen*4); + double* pColors=aRes.getArray(); + for( sal_Size i=0; iRed; + *pColors++ = pIn->Green; + *pColors++ = pIn->Blue; + *pColors++ = 1.0; // the value does not matter + ++pIn; + } + return aRes; + } + virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< double > aRes(nLen*4); + double* pColors=aRes.getArray(); + for( sal_Size i=0; iRed; + *pColors++ = pIn->Green; + *pColors++ = pIn->Blue; + *pColors++ = 1.0; // the value does not matter + ++pIn; + } + return aRes; + } + virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< double > aRes(nLen*4); + double* pColors=aRes.getArray(); + for( sal_Size i=0; iRed/pIn->Alpha; + *pColors++ = pIn->Green/pIn->Alpha; + *pColors++ = pIn->Blue/pIn->Alpha; + *pColors++ = 1.0; // the value does not matter + ++pIn; + } + return aRes; + } + + // XIntegerBitmapColorSpace + virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException) + { + return 32; + } + virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException) + { + return maBitCounts; + } + virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException) + { + return util::Endianness::LITTLE; + } + virtual uno::Sequence SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor, + const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, + uno::RuntimeException) + { + if( dynamic_cast(targetColorSpace.get()) ) + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence aRes(nLen); + double* pOut( aRes.getArray() ); + for( sal_Size i=0; i aIntermediate( + convertIntegerToARGB(deviceColor)); + return targetColorSpace->convertFromARGB(aIntermediate); + } + } + virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor, + const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, + uno::RuntimeException) + { + if( dynamic_cast(targetColorSpace.get()) ) + { + // it's us, so simply pass-through the data + return deviceColor; + } + else + { + // TODO(P3): if we know anything about target + // colorspace, this can be greatly sped up + uno::Sequence aIntermediate( + convertIntegerToARGB(deviceColor)); + return targetColorSpace->convertIntegerFromARGB(aIntermediate); + } + } + virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::RGBColor > aRes(nLen/4); + rendering::RGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::RGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< sal_Int8 > aRes(nLen*4); + sal_Int8* pColors=aRes.getArray(); + for( sal_Size i=0; iRed); + *pColors++ = vcl::unotools::toByteColor(pIn->Green); + *pColors++ = vcl::unotools::toByteColor(pIn->Blue); + *pColors++ = 1.0; + ++pIn; + } + return aRes; + } + + virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< sal_Int8 > aRes(nLen*4); + sal_Int8* pColors=aRes.getArray(); + for( sal_Size i=0; iRed); + *pColors++ = vcl::unotools::toByteColor(pIn->Green); + *pColors++ = vcl::unotools::toByteColor(pIn->Blue); + *pColors++ = 255; + ++pIn; + } + return aRes; + } + + virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< sal_Int8 > aRes(nLen*4); + sal_Int8* pColors=aRes.getArray(); + for( sal_Size i=0; iRed/pIn->Alpha); + *pColors++ = vcl::unotools::toByteColor(pIn->Green/pIn->Alpha); + *pColors++ = vcl::unotools::toByteColor(pIn->Blue/pIn->Alpha); + *pColors++ = 255; + ++pIn; + } + return aRes; + } + + public: + StandardNoAlphaColorSpace() : + maComponentTags(3), + maBitCounts(3) + { + sal_Int8* pTags = maComponentTags.getArray(); + sal_Int32* pBitCounts = maBitCounts.getArray(); + pTags[0] = rendering::ColorComponentTag::RGB_RED; + pTags[1] = rendering::ColorComponentTag::RGB_GREEN; + pTags[2] = rendering::ColorComponentTag::RGB_BLUE; + + pBitCounts[0] = + pBitCounts[1] = + pBitCounts[2] = 8; + } + }; + struct StandardColorSpaceHolder : public rtl::StaticWithInit, StandardColorSpaceHolder> { @@ -565,6 +899,15 @@ namespace canvas return new StandardColorSpace(); } }; + + struct StandardNoAlphaColorSpaceHolder : public rtl::StaticWithInit, + StandardNoAlphaColorSpaceHolder> + { + uno::Reference operator()() + { + return new StandardNoAlphaColorSpace(); + } + }; } uno::Reference getStdColorSpace() @@ -572,6 +915,11 @@ namespace canvas return StandardColorSpaceHolder::get(); } + uno::Reference getStdColorSpaceWithoutAlpha() + { + return StandardNoAlphaColorSpaceHolder::get(); + } + rendering::IntegerBitmapLayout getStdMemoryLayout( const geometry::IntegerSize2D& rBmpSize ) { rendering::IntegerBitmapLayout aLayout; diff --git a/canvas/source/vcl/canvasbitmaphelper.cxx b/canvas/source/vcl/canvasbitmaphelper.cxx index 12e57ec57440..7b604101950c 100644 --- a/canvas/source/vcl/canvasbitmaphelper.cxx +++ b/canvas/source/vcl/canvasbitmaphelper.cxx @@ -539,7 +539,11 @@ namespace vclcanvas if( !mpOutDev.get() ) return rendering::IntegerBitmapLayout(); // we're disposed - return ::canvas::tools::getStdMemoryLayout(getSize()); + rendering::IntegerBitmapLayout xBitmapLayout( ::canvas::tools::getStdMemoryLayout(getSize()) ); + if ( !hasAlpha() ) + xBitmapLayout.ColorSpace = canvas::tools::getStdColorSpaceWithoutAlpha(); + + return xBitmapLayout; } BitmapEx CanvasBitmapHelper::getBitmap() const diff --git a/canvas/source/vcl/canvashelper.cxx b/canvas/source/vcl/canvashelper.cxx index 2454dded1d67..8c393fd59e6d 100644 --- a/canvas/source/vcl/canvashelper.cxx +++ b/canvas/source/vcl/canvashelper.cxx @@ -1195,7 +1195,11 @@ namespace vclcanvas if( !mpOutDev.get() ) return rendering::IntegerBitmapLayout(); // we're disposed - return ::canvas::tools::getStdMemoryLayout(getSize()); + rendering::IntegerBitmapLayout xBitmapLayout( ::canvas::tools::getStdMemoryLayout(getSize()) ); + if ( !mbHaveAlpha ) + xBitmapLayout.ColorSpace = canvas::tools::getStdColorSpaceWithoutAlpha(); + + return xBitmapLayout; } int CanvasHelper::setupOutDevState( const rendering::ViewState& viewState, diff --git a/canvas/source/vcl/devicehelper.cxx b/canvas/source/vcl/devicehelper.cxx index 2d5af8ed72fb..c9f7139487e7 100644 --- a/canvas/source/vcl/devicehelper.cxx +++ b/canvas/source/vcl/devicehelper.cxx @@ -194,7 +194,9 @@ namespace vclcanvas { uno::Reference operator()() { - return vcl::unotools::createStandardColorSpace(); + uno::Reference< rendering::XColorSpace > xColorSpace( canvas::tools::getStdColorSpace(), uno::UNO_QUERY ); + assert( xColorSpace.is() ); + return xColorSpace; } }; } diff --git a/slideshow/source/engine/OGLTrans/unx/OGLTrans_TransitionerImpl.cxx b/slideshow/source/engine/OGLTrans/unx/OGLTrans_TransitionerImpl.cxx index 67db2632c10c..03e7c4c26407 100644 --- a/slideshow/source/engine/OGLTrans/unx/OGLTrans_TransitionerImpl.cxx +++ b/slideshow/source/engine/OGLTrans/unx/OGLTrans_TransitionerImpl.cxx @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include #include @@ -50,7 +52,11 @@ #include #include + +#include #include + +#include #include #include @@ -915,6 +921,360 @@ void OGLTransitionerImpl::createTexture( unsigned int* texID, SAL_WARN_IF(!glIsTexture(*texID), "slideshow.opengl", "Can't generate Leaving slide textures in OpenGL"); } +namespace +{ + class OGLColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XIntegerBitmapColorSpace > + { + private: + uno::Sequence< sal_Int8 > maComponentTags; + uno::Sequence< sal_Int32 > maBitCounts; + + virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException) + { + return rendering::ColorSpaceType::RGB; + } + virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException) + { + return maComponentTags; + } + virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException) + { + return rendering::RenderingIntent::PERCEPTUAL; + } + virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException) + { + return uno::Sequence< beans::PropertyValue >(); + } + virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor, + const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, + uno::RuntimeException) + { + // TODO(P3): if we know anything about target + // colorspace, this can be greatly sped up + uno::Sequence aIntermediate( + convertToARGB(deviceColor)); + return targetColorSpace->convertFromARGB(aIntermediate); + } + virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const double* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::RGBColor > aRes(nLen/4); + rendering::RGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const double* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const double* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::RGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< double > aRes(nLen*4); + double* pColors=aRes.getArray(); + for( sal_Size i=0; iRed; + *pColors++ = pIn->Green; + *pColors++ = pIn->Blue; + *pColors++ = 1.0; + ++pIn; + } + return aRes; + } + virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< double > aRes(nLen*4); + double* pColors=aRes.getArray(); + for( sal_Size i=0; iRed; + *pColors++ = pIn->Green; + *pColors++ = pIn->Blue; + *pColors++ = pIn->Alpha; + ++pIn; + } + return aRes; + } + virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< double > aRes(nLen*4); + double* pColors=aRes.getArray(); + for( sal_Size i=0; iRed/pIn->Alpha; + *pColors++ = pIn->Green/pIn->Alpha; + *pColors++ = pIn->Blue/pIn->Alpha; + *pColors++ = pIn->Alpha; + ++pIn; + } + return aRes; + } + + // XIntegerBitmapColorSpace + virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException) + { + return 32; + } + virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException) + { + return maBitCounts; + } + virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException) + { + return util::Endianness::LITTLE; + } + virtual uno::Sequence SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor, + const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, + uno::RuntimeException) + { + if( dynamic_cast(targetColorSpace.get()) ) + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence aRes(nLen); + double* pOut( aRes.getArray() ); + for( sal_Size i=0; i aIntermediate( + convertIntegerToARGB(deviceColor)); + return targetColorSpace->convertFromARGB(aIntermediate); + } + } + virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor, + const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException, + uno::RuntimeException) + { + if( dynamic_cast(targetColorSpace.get()) ) + { + // it's us, so simply pass-through the data + return deviceColor; + } + else + { + // TODO(P3): if we know anything about target + // colorspace, this can be greatly sped up + uno::Sequence aIntermediate( + convertIntegerToARGB(deviceColor)); + return targetColorSpace->convertIntegerFromARGB(aIntermediate); + } + } + virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::RGBColor > aRes(nLen/4); + rendering::RGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const sal_Int8* pIn( deviceColor.getConstArray() ); + const sal_Size nLen( deviceColor.getLength() ); + ENSURE_ARG_OR_THROW2(nLen%4==0, + "number of channels no multiple of 4", + static_cast(this), 0); + + uno::Sequence< rendering::ARGBColor > aRes(nLen/4); + rendering::ARGBColor* pOut( aRes.getArray() ); + for( sal_Size i=0; i SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::RGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< sal_Int8 > aRes(nLen*4); + sal_Int8* pColors=aRes.getArray(); + for( sal_Size i=0; iRed); + *pColors++ = vcl::unotools::toByteColor(pIn->Green); + *pColors++ = vcl::unotools::toByteColor(pIn->Blue); + *pColors++ = 255; + ++pIn; + } + return aRes; + } + + virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< sal_Int8 > aRes(nLen*4); + sal_Int8* pColors=aRes.getArray(); + for( sal_Size i=0; iRed); + *pColors++ = vcl::unotools::toByteColor(pIn->Green); + *pColors++ = vcl::unotools::toByteColor(pIn->Blue); + *pColors++ = vcl::unotools::toByteColor(pIn->Alpha); + ++pIn; + } + return aRes; + } + + virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException) + { + const rendering::ARGBColor* pIn( rgbColor.getConstArray() ); + const sal_Size nLen( rgbColor.getLength() ); + + uno::Sequence< sal_Int8 > aRes(nLen*4); + sal_Int8* pColors=aRes.getArray(); + for( sal_Size i=0; iRed/pIn->Alpha); + *pColors++ = vcl::unotools::toByteColor(pIn->Green/pIn->Alpha); + *pColors++ = vcl::unotools::toByteColor(pIn->Blue/pIn->Alpha); + *pColors++ = vcl::unotools::toByteColor(pIn->Alpha); + ++pIn; + } + return aRes; + } + + public: + OGLColorSpace() : + maComponentTags(4), + maBitCounts(4) + { + sal_Int8* pTags = maComponentTags.getArray(); + sal_Int32* pBitCounts = maBitCounts.getArray(); + pTags[0] = rendering::ColorComponentTag::RGB_RED; + pTags[1] = rendering::ColorComponentTag::RGB_GREEN; + pTags[2] = rendering::ColorComponentTag::RGB_BLUE; + pTags[3] = rendering::ColorComponentTag::ALPHA; + + pBitCounts[0] = + pBitCounts[1] = + pBitCounts[2] = + pBitCounts[3] = 8; + } + }; + + struct OGLColorSpaceHolder : public rtl::StaticWithInit, OGLColorSpaceHolder> + { + uno::Reference operator()() + { + return new OGLColorSpace(); + } + }; + + uno::Reference + getOGLColorSpace() + { + return OGLColorSpaceHolder::get(); + } +} + void OGLTransitionerImpl::impl_createTexture( bool useMipmap, uno::Sequence& data, @@ -926,7 +1286,7 @@ void OGLTransitionerImpl::impl_createTexture( uno::Sequence tempBytes( SlideBitmapLayout.ColorSpace->convertToIntegerColorSpace( data, - canvas::tools::getStdColorSpace())); + getOGLColorSpace())); gluBuild2DMipmaps(GL_TEXTURE_2D, 4, SlideSize.Width, @@ -1085,7 +1445,10 @@ const OGLFormat* OGLTransitionerImpl::chooseFormats() } break; case 32: - pDetectedFormat = &lcl_ARGB32[nComponentOrderIndex]; + if ( nNumComponents == 4 ) + { + pDetectedFormat = &lcl_ARGB32[nComponentOrderIndex]; + } break; } } -- cgit v1.2.3