1*b1cdbd2cSJim Jagielski /************************************************************** 2*b1cdbd2cSJim Jagielski * 3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski * distributed with this work for additional information 6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski * 11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski * 13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski * under the License. 19*b1cdbd2cSJim Jagielski * 20*b1cdbd2cSJim Jagielski *************************************************************/ 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski 23*b1cdbd2cSJim Jagielski 24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove 25*b1cdbd2cSJim Jagielski #include "precompiled_canvas.hxx" 26*b1cdbd2cSJim Jagielski 27*b1cdbd2cSJim Jagielski #include <ctype.h> // don't ask. msdev breaks otherwise... 28*b1cdbd2cSJim Jagielski #include <canvas/debug.hxx> 29*b1cdbd2cSJim Jagielski #include <canvas/canvastools.hxx> 30*b1cdbd2cSJim Jagielski #include <tools/diagnose_ex.h> 31*b1cdbd2cSJim Jagielski 32*b1cdbd2cSJim Jagielski #include <vcl/bitmapex.hxx> 33*b1cdbd2cSJim Jagielski 34*b1cdbd2cSJim Jagielski #include <boost/preprocessor/repetition.hpp> 35*b1cdbd2cSJim Jagielski #include <boost/preprocessor/iteration/local.hpp> 36*b1cdbd2cSJim Jagielski #include <boost/scoped_array.hpp> 37*b1cdbd2cSJim Jagielski 38*b1cdbd2cSJim Jagielski #include "dx_canvasbitmap.hxx" 39*b1cdbd2cSJim Jagielski #include "dx_impltools.hxx" 40*b1cdbd2cSJim Jagielski 41*b1cdbd2cSJim Jagielski 42*b1cdbd2cSJim Jagielski using namespace ::com::sun::star; 43*b1cdbd2cSJim Jagielski 44*b1cdbd2cSJim Jagielski namespace dxcanvas 45*b1cdbd2cSJim Jagielski { CanvasBitmap(const IBitmapSharedPtr & rBitmap,const DeviceRef & rDevice)46*b1cdbd2cSJim Jagielski CanvasBitmap::CanvasBitmap( const IBitmapSharedPtr& rBitmap, 47*b1cdbd2cSJim Jagielski const DeviceRef& rDevice ) : 48*b1cdbd2cSJim Jagielski mpDevice( rDevice ), 49*b1cdbd2cSJim Jagielski mpBitmap( rBitmap ) 50*b1cdbd2cSJim Jagielski { 51*b1cdbd2cSJim Jagielski ENSURE_OR_THROW( mpDevice.is() && mpBitmap, 52*b1cdbd2cSJim Jagielski "CanvasBitmap::CanvasBitmap(): Invalid surface or device" ); 53*b1cdbd2cSJim Jagielski 54*b1cdbd2cSJim Jagielski maCanvasHelper.setDevice( *mpDevice.get() ); 55*b1cdbd2cSJim Jagielski maCanvasHelper.setTarget( mpBitmap ); 56*b1cdbd2cSJim Jagielski } 57*b1cdbd2cSJim Jagielski disposing()58*b1cdbd2cSJim Jagielski void SAL_CALL CanvasBitmap::disposing() 59*b1cdbd2cSJim Jagielski { 60*b1cdbd2cSJim Jagielski mpBitmap.reset(); 61*b1cdbd2cSJim Jagielski mpDevice.clear(); 62*b1cdbd2cSJim Jagielski 63*b1cdbd2cSJim Jagielski // forward to parent 64*b1cdbd2cSJim Jagielski CanvasBitmap_Base::disposing(); 65*b1cdbd2cSJim Jagielski } 66*b1cdbd2cSJim Jagielski 67*b1cdbd2cSJim Jagielski struct AlphaDIB 68*b1cdbd2cSJim Jagielski { 69*b1cdbd2cSJim Jagielski BITMAPINFOHEADER bmiHeader; 70*b1cdbd2cSJim Jagielski RGBQUAD bmiColors[256]; 71*b1cdbd2cSJim Jagielski }; 72*b1cdbd2cSJim Jagielski getFastPropertyValue(sal_Int32 nHandle)73*b1cdbd2cSJim Jagielski uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle ) throw (uno::RuntimeException) 74*b1cdbd2cSJim Jagielski { 75*b1cdbd2cSJim Jagielski uno::Any aRes; 76*b1cdbd2cSJim Jagielski // 0 ... get BitmapEx 77*b1cdbd2cSJim Jagielski // 1 ... get Pixbuf with bitmap RGB content 78*b1cdbd2cSJim Jagielski // 2 ... get Pixbuf with bitmap alpha mask 79*b1cdbd2cSJim Jagielski switch( nHandle ) 80*b1cdbd2cSJim Jagielski { 81*b1cdbd2cSJim Jagielski // sorry, no BitmapEx here... 82*b1cdbd2cSJim Jagielski case 0: 83*b1cdbd2cSJim Jagielski aRes = ::com::sun::star::uno::Any( reinterpret_cast<sal_Int64>( (BitmapEx*) NULL ) ); 84*b1cdbd2cSJim Jagielski break; 85*b1cdbd2cSJim Jagielski 86*b1cdbd2cSJim Jagielski case 1: 87*b1cdbd2cSJim Jagielski { 88*b1cdbd2cSJim Jagielski if(!mpBitmap->hasAlpha()) 89*b1cdbd2cSJim Jagielski { 90*b1cdbd2cSJim Jagielski HBITMAP aHBmp; 91*b1cdbd2cSJim Jagielski mpBitmap->getBitmap()->GetHBITMAP(Gdiplus::Color(), &aHBmp ); 92*b1cdbd2cSJim Jagielski 93*b1cdbd2cSJim Jagielski uno::Sequence< uno::Any > args(1); 94*b1cdbd2cSJim Jagielski args[0] = uno::Any( sal_Int64(aHBmp) ); 95*b1cdbd2cSJim Jagielski 96*b1cdbd2cSJim Jagielski aRes <<= args; 97*b1cdbd2cSJim Jagielski } 98*b1cdbd2cSJim Jagielski else 99*b1cdbd2cSJim Jagielski { 100*b1cdbd2cSJim Jagielski // need to copy&convert the bitmap, since dx 101*b1cdbd2cSJim Jagielski // canvas uses inline alpha channel 102*b1cdbd2cSJim Jagielski HDC hScreenDC=GetDC(NULL); 103*b1cdbd2cSJim Jagielski const basegfx::B2IVector aSize(mpBitmap->getSize()); 104*b1cdbd2cSJim Jagielski HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC, 105*b1cdbd2cSJim Jagielski aSize.getX(), 106*b1cdbd2cSJim Jagielski aSize.getY() ); 107*b1cdbd2cSJim Jagielski if( !hBmpBitmap ) 108*b1cdbd2cSJim Jagielski return aRes; 109*b1cdbd2cSJim Jagielski 110*b1cdbd2cSJim Jagielski BITMAPINFOHEADER aBIH; 111*b1cdbd2cSJim Jagielski 112*b1cdbd2cSJim Jagielski aBIH.biSize = sizeof( BITMAPINFOHEADER ); 113*b1cdbd2cSJim Jagielski aBIH.biWidth = aSize.getX(); 114*b1cdbd2cSJim Jagielski aBIH.biHeight = -aSize.getY(); 115*b1cdbd2cSJim Jagielski aBIH.biPlanes = 1; 116*b1cdbd2cSJim Jagielski aBIH.biBitCount = 32; 117*b1cdbd2cSJim Jagielski aBIH.biCompression = BI_RGB; // expects pixel in 118*b1cdbd2cSJim Jagielski // bbggrrxx format 119*b1cdbd2cSJim Jagielski // (little endian) 120*b1cdbd2cSJim Jagielski aBIH.biSizeImage = 0; 121*b1cdbd2cSJim Jagielski aBIH.biXPelsPerMeter = 0; 122*b1cdbd2cSJim Jagielski aBIH.biYPelsPerMeter = 0; 123*b1cdbd2cSJim Jagielski aBIH.biClrUsed = 0; 124*b1cdbd2cSJim Jagielski aBIH.biClrImportant = 0; 125*b1cdbd2cSJim Jagielski 126*b1cdbd2cSJim Jagielski Gdiplus::BitmapData aBmpData; 127*b1cdbd2cSJim Jagielski aBmpData.Width = aSize.getX(); 128*b1cdbd2cSJim Jagielski aBmpData.Height = aSize.getY(); 129*b1cdbd2cSJim Jagielski aBmpData.Stride = 4*aBmpData.Width; 130*b1cdbd2cSJim Jagielski aBmpData.PixelFormat = PixelFormat32bppARGB; 131*b1cdbd2cSJim Jagielski aBmpData.Scan0 = NULL; 132*b1cdbd2cSJim Jagielski const Gdiplus::Rect aRect( 0,0,aSize.getX(),aSize.getY() ); 133*b1cdbd2cSJim Jagielski BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap(); 134*b1cdbd2cSJim Jagielski if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect, 135*b1cdbd2cSJim Jagielski Gdiplus::ImageLockModeRead, 136*b1cdbd2cSJim Jagielski PixelFormat32bppARGB, // outputs ARGB (big endian) 137*b1cdbd2cSJim Jagielski &aBmpData ) ) 138*b1cdbd2cSJim Jagielski { 139*b1cdbd2cSJim Jagielski // failed to lock, bail out 140*b1cdbd2cSJim Jagielski return aRes; 141*b1cdbd2cSJim Jagielski } 142*b1cdbd2cSJim Jagielski 143*b1cdbd2cSJim Jagielski // now aBmpData.Scan0 contains our bits - push 144*b1cdbd2cSJim Jagielski // them into HBITMAP, ignoring alpha 145*b1cdbd2cSJim Jagielski SetDIBits( hScreenDC, hBmpBitmap, 0, aSize.getY(), aBmpData.Scan0, (PBITMAPINFO)&aBIH, DIB_RGB_COLORS ); 146*b1cdbd2cSJim Jagielski 147*b1cdbd2cSJim Jagielski pGDIPlusBitmap->UnlockBits( &aBmpData ); 148*b1cdbd2cSJim Jagielski 149*b1cdbd2cSJim Jagielski uno::Sequence< uno::Any > args(1); 150*b1cdbd2cSJim Jagielski args[0] = uno::Any( sal_Int64(hBmpBitmap) ); 151*b1cdbd2cSJim Jagielski 152*b1cdbd2cSJim Jagielski aRes <<= args; 153*b1cdbd2cSJim Jagielski } 154*b1cdbd2cSJim Jagielski } 155*b1cdbd2cSJim Jagielski break; 156*b1cdbd2cSJim Jagielski 157*b1cdbd2cSJim Jagielski case 2: 158*b1cdbd2cSJim Jagielski { 159*b1cdbd2cSJim Jagielski if(!mpBitmap->hasAlpha()) 160*b1cdbd2cSJim Jagielski { 161*b1cdbd2cSJim Jagielski return aRes; 162*b1cdbd2cSJim Jagielski } 163*b1cdbd2cSJim Jagielski else 164*b1cdbd2cSJim Jagielski { 165*b1cdbd2cSJim Jagielski static AlphaDIB aDIB= 166*b1cdbd2cSJim Jagielski { 167*b1cdbd2cSJim Jagielski {0,0,0,1,8,BI_RGB,0,0,0,0,0}, 168*b1cdbd2cSJim Jagielski { 169*b1cdbd2cSJim Jagielski // this here fills palette with grey 170*b1cdbd2cSJim Jagielski // level colors, starting from 0,0,0 171*b1cdbd2cSJim Jagielski // up to 255,255,255 172*b1cdbd2cSJim Jagielski #define BOOST_PP_LOCAL_MACRO(n_) \ 173*b1cdbd2cSJim Jagielski BOOST_PP_COMMA_IF(n_) \ 174*b1cdbd2cSJim Jagielski {n_,n_,n_,n_} 175*b1cdbd2cSJim Jagielski #define BOOST_PP_LOCAL_LIMITS (0, 255) 176*b1cdbd2cSJim Jagielski #include BOOST_PP_LOCAL_ITERATE() 177*b1cdbd2cSJim Jagielski } 178*b1cdbd2cSJim Jagielski }; 179*b1cdbd2cSJim Jagielski 180*b1cdbd2cSJim Jagielski // need to copy&convert the bitmap, since dx 181*b1cdbd2cSJim Jagielski // canvas uses inline alpha channel 182*b1cdbd2cSJim Jagielski HDC hScreenDC=GetDC(NULL); 183*b1cdbd2cSJim Jagielski const basegfx::B2IVector aSize(mpBitmap->getSize()); 184*b1cdbd2cSJim Jagielski HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC, aSize.getX(), aSize.getY() ); 185*b1cdbd2cSJim Jagielski if( !hBmpBitmap ) 186*b1cdbd2cSJim Jagielski return aRes; 187*b1cdbd2cSJim Jagielski 188*b1cdbd2cSJim Jagielski aDIB.bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); 189*b1cdbd2cSJim Jagielski aDIB.bmiHeader.biWidth = aSize.getX(); 190*b1cdbd2cSJim Jagielski aDIB.bmiHeader.biHeight = -aSize.getY(); 191*b1cdbd2cSJim Jagielski aDIB.bmiHeader.biPlanes = 1; 192*b1cdbd2cSJim Jagielski aDIB.bmiHeader.biBitCount = 8; 193*b1cdbd2cSJim Jagielski aDIB.bmiHeader.biCompression = BI_RGB; 194*b1cdbd2cSJim Jagielski aDIB.bmiHeader.biSizeImage = 0; 195*b1cdbd2cSJim Jagielski aDIB.bmiHeader.biXPelsPerMeter = 0; 196*b1cdbd2cSJim Jagielski aDIB.bmiHeader.biYPelsPerMeter = 0; 197*b1cdbd2cSJim Jagielski aDIB.bmiHeader.biClrUsed = 0; 198*b1cdbd2cSJim Jagielski aDIB.bmiHeader.biClrImportant = 0; 199*b1cdbd2cSJim Jagielski 200*b1cdbd2cSJim Jagielski Gdiplus::BitmapData aBmpData; 201*b1cdbd2cSJim Jagielski aBmpData.Width = aSize.getX(); 202*b1cdbd2cSJim Jagielski aBmpData.Height = aSize.getY(); 203*b1cdbd2cSJim Jagielski aBmpData.Stride = 4*aBmpData.Width; 204*b1cdbd2cSJim Jagielski aBmpData.PixelFormat = PixelFormat32bppARGB; 205*b1cdbd2cSJim Jagielski aBmpData.Scan0 = NULL; 206*b1cdbd2cSJim Jagielski const Gdiplus::Rect aRect( 0,0,aSize.getX(),aSize.getY() ); 207*b1cdbd2cSJim Jagielski BitmapSharedPtr pGDIPlusBitmap=mpBitmap->getBitmap(); 208*b1cdbd2cSJim Jagielski if( Gdiplus::Ok != pGDIPlusBitmap->LockBits( &aRect, 209*b1cdbd2cSJim Jagielski Gdiplus::ImageLockModeRead, 210*b1cdbd2cSJim Jagielski PixelFormat32bppARGB, // outputs ARGB (big endian) 211*b1cdbd2cSJim Jagielski &aBmpData ) ) 212*b1cdbd2cSJim Jagielski { 213*b1cdbd2cSJim Jagielski // failed to lock, bail out 214*b1cdbd2cSJim Jagielski return aRes; 215*b1cdbd2cSJim Jagielski } 216*b1cdbd2cSJim Jagielski 217*b1cdbd2cSJim Jagielski // copy only alpha channel to pAlphaBits 218*b1cdbd2cSJim Jagielski const sal_Int32 nScanWidth((aSize.getX() + 3) & ~3); 219*b1cdbd2cSJim Jagielski boost::scoped_array<sal_uInt8> pAlphaBits( new sal_uInt8[nScanWidth*aSize.getY()] ); 220*b1cdbd2cSJim Jagielski const sal_uInt8* pInBits=(sal_uInt8*)aBmpData.Scan0; 221*b1cdbd2cSJim Jagielski pInBits+=3; 222*b1cdbd2cSJim Jagielski sal_uInt8* pOutBits; 223*b1cdbd2cSJim Jagielski for( sal_Int32 y=0; y<aSize.getY(); ++y ) 224*b1cdbd2cSJim Jagielski { 225*b1cdbd2cSJim Jagielski pOutBits=pAlphaBits.get()+y*nScanWidth; 226*b1cdbd2cSJim Jagielski for( sal_Int32 x=0; x<aSize.getX(); ++x ) 227*b1cdbd2cSJim Jagielski { 228*b1cdbd2cSJim Jagielski *pOutBits++ = 255-*pInBits; 229*b1cdbd2cSJim Jagielski pInBits += 4; 230*b1cdbd2cSJim Jagielski } 231*b1cdbd2cSJim Jagielski } 232*b1cdbd2cSJim Jagielski 233*b1cdbd2cSJim Jagielski pGDIPlusBitmap->UnlockBits( &aBmpData ); 234*b1cdbd2cSJim Jagielski 235*b1cdbd2cSJim Jagielski // set bits to newly create HBITMAP 236*b1cdbd2cSJim Jagielski SetDIBits( hScreenDC, hBmpBitmap, 0, 237*b1cdbd2cSJim Jagielski aSize.getY(), pAlphaBits.get(), 238*b1cdbd2cSJim Jagielski (PBITMAPINFO)&aDIB, DIB_RGB_COLORS ); 239*b1cdbd2cSJim Jagielski 240*b1cdbd2cSJim Jagielski uno::Sequence< uno::Any > args(1); 241*b1cdbd2cSJim Jagielski args[0] = uno::Any( sal_Int64(hBmpBitmap) ); 242*b1cdbd2cSJim Jagielski 243*b1cdbd2cSJim Jagielski aRes <<= args; 244*b1cdbd2cSJim Jagielski } 245*b1cdbd2cSJim Jagielski } 246*b1cdbd2cSJim Jagielski break; 247*b1cdbd2cSJim Jagielski } 248*b1cdbd2cSJim Jagielski 249*b1cdbd2cSJim Jagielski return aRes; 250*b1cdbd2cSJim Jagielski } 251*b1cdbd2cSJim Jagielski 252*b1cdbd2cSJim Jagielski #define IMPLEMENTATION_NAME "DXCanvas.CanvasBitmap" 253*b1cdbd2cSJim Jagielski #define SERVICE_NAME "com.sun.star.rendering.CanvasBitmap" 254*b1cdbd2cSJim Jagielski getImplementationName()255*b1cdbd2cSJim Jagielski ::rtl::OUString SAL_CALL CanvasBitmap::getImplementationName( ) throw (uno::RuntimeException) 256*b1cdbd2cSJim Jagielski { 257*b1cdbd2cSJim Jagielski return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) ); 258*b1cdbd2cSJim Jagielski } 259*b1cdbd2cSJim Jagielski supportsService(const::rtl::OUString & ServiceName)260*b1cdbd2cSJim Jagielski sal_Bool SAL_CALL CanvasBitmap::supportsService( const ::rtl::OUString& ServiceName ) throw (uno::RuntimeException) 261*b1cdbd2cSJim Jagielski { 262*b1cdbd2cSJim Jagielski return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) ); 263*b1cdbd2cSJim Jagielski } 264*b1cdbd2cSJim Jagielski getSupportedServiceNames()265*b1cdbd2cSJim Jagielski uno::Sequence< ::rtl::OUString > SAL_CALL CanvasBitmap::getSupportedServiceNames( ) throw (uno::RuntimeException) 266*b1cdbd2cSJim Jagielski { 267*b1cdbd2cSJim Jagielski uno::Sequence< ::rtl::OUString > aRet(1); 268*b1cdbd2cSJim Jagielski aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) ); 269*b1cdbd2cSJim Jagielski 270*b1cdbd2cSJim Jagielski return aRet; 271*b1cdbd2cSJim Jagielski } 272*b1cdbd2cSJim Jagielski 273*b1cdbd2cSJim Jagielski } 274