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_canvas.hxx" 26 27 #ifdef WNT 28 /************************************************************************ 29 * Win32 surface backend for OpenOffice.org Cairo Canvas * 30 ************************************************************************/ 31 32 #include <tools/prewin.h> 33 #include <windows.h> 34 #include <tools/postwin.h> 35 36 #include <osl/diagnose.h> 37 #include <vcl/bitmap.hxx> 38 #include <vcl/virdev.hxx> 39 #include <vcl/sysdata.hxx> 40 41 #include "cairo_win32_cairo.hxx" 42 43 #ifdef CAIRO_HAS_WIN32_SURFACE 44 45 namespace cairo 46 { 47 48 #include <cairo-win32.h> 49 IsCairoWorking(OutputDevice *)50 bool IsCairoWorking( OutputDevice* ) 51 { 52 // trivially true for Windows 53 return true; 54 } 55 56 /** 57 * Surface::Surface: Create generic Canvas surface using given Cairo Surface 58 * 59 * @param pSurface Cairo Surface 60 * 61 * This constructor only stores data, it does no processing. 62 * It is used with e.g. cairo_image_surface_create_for_data() 63 * and Surface::getSimilar() 64 * 65 * Set the mpSurface to the new surface or NULL 66 **/ Win32Surface(const CairoSurfaceSharedPtr & pSurface)67 Win32Surface::Win32Surface( const CairoSurfaceSharedPtr& pSurface ) : 68 mpSurface( pSurface ) 69 {} 70 71 /** 72 * Surface::Surface: Create Canvas surface from Window reference. 73 * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx) 74 * @param x horizontal location of the new surface 75 * @param y vertical location of the new surface 76 * 77 * pSysData contains the platform native Window reference. 78 * pSysData is used to create a surface on the Window 79 * 80 * Set the mpSurface to the new surface or NULL 81 **/ Win32Surface(HDC hDC,int x,int y)82 Win32Surface::Win32Surface( HDC hDC, int x, int y) : 83 mpSurface( 84 cairo_win32_surface_create(hDC), 85 &cairo_surface_destroy) 86 { 87 cairo_surface_set_device_offset( mpSurface.get(), x, y ); 88 } 89 90 /** 91 * Surface::Surface: Create platform native Canvas surface from BitmapSystemData 92 * @param pBmpData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx) 93 * 94 * Create a surface based on image data on pBmpData 95 * 96 * Set the mpSurface to the new surface or NULL 97 **/ Win32Surface(const BitmapSystemData & rBmpData)98 Win32Surface::Win32Surface( const BitmapSystemData& rBmpData ) : 99 mpSurface() 100 { 101 OSL_ASSERT(rBmpData.pDIB == NULL); 102 103 if(rBmpData.pDIB != NULL) { 104 // So just leave mpSurface to NULL, little else we can do at 105 // this stage. Hopefully the Win32 patch to 106 // cairocanvas::DeviceHelper::getSurface(BitmapSystemData&, 107 // const Size&) will catch the cases where this 108 // constructor would be called with a DIB bitmap, and we 109 // will never get here. At least it worked for Ballmer.ppt. 110 } 111 else 112 { 113 HDC hDC = CreateCompatibleDC(NULL); 114 void* hOrigBitmap; 115 OSL_TRACE ("Surface::Surface(): Selecting bitmap %p into DC %p", rBmpData.pDDB, hDC); 116 hOrigBitmap = SelectObject( hDC, (HANDLE)rBmpData.pDDB ); 117 if(hOrigBitmap == NULL) 118 OSL_TRACE ("SelectObject failed: %d", GetLastError ()); 119 mpSurface.reset( 120 cairo_win32_surface_create(hDC), 121 &cairo_surface_destroy); 122 } 123 } 124 125 /** 126 * Surface::getCairo: Create Cairo (drawing object) for the Canvas surface 127 * 128 * @return new Cairo or NULL 129 **/ getCairo() const130 CairoSharedPtr Win32Surface::getCairo() const 131 { 132 return CairoSharedPtr( cairo_create(mpSurface.get()), 133 &cairo_destroy ); 134 } 135 136 /** 137 * Surface::getSimilar: Create new similar Canvas surface 138 * @param aContent format of the new surface (cairo_content_t from cairo/src/cairo.h) 139 * @param width width of the new surface 140 * @param height height of the new surface 141 * 142 * Creates a new Canvas surface. This normally creates platform native surface, even though 143 * generic function is used. 144 * 145 * Cairo surface from aContent (cairo_content_t) 146 * 147 * @return new surface or NULL 148 **/ getSimilar(Content aContent,int width,int height) const149 SurfaceSharedPtr Win32Surface::getSimilar( Content aContent, int width, int height ) const 150 { 151 return SurfaceSharedPtr( 152 new Win32Surface( 153 CairoSurfaceSharedPtr( 154 cairo_surface_create_similar( mpSurface.get(), aContent, width, height ), 155 &cairo_surface_destroy ))); 156 } 157 158 /** 159 * Surface::Resize: Resizes the Canvas surface. 160 * @param width new width of the surface 161 * @param height new height of the surface 162 * 163 * Only used on X11. 164 * 165 * @return The new surface or NULL 166 **/ Resize(int,int)167 void Win32Surface::Resize( int /*width*/, int /*height*/ ) 168 { 169 OSL_ENSURE(false,"not supposed to be called!"); 170 } 171 flush() const172 void Win32Surface::flush() const 173 { 174 GdiFlush(); 175 } 176 177 /** 178 * Surface::getDepth: Get the color depth of the Canvas surface. 179 * 180 * @return color depth 181 **/ getDepth() const182 int Win32Surface::getDepth() const 183 { 184 if (mpSurface) { 185 switch (cairo_surface_get_content (mpSurface.get())) { 186 case CAIRO_CONTENT_ALPHA: return 8; break; 187 case CAIRO_CONTENT_COLOR: return 24; break; 188 case CAIRO_CONTENT_COLOR_ALPHA: return 32; break; 189 } 190 } 191 OSL_TRACE("Canvas::cairo::Surface::getDepth(): ERROR - depth unspecified!"); 192 return -1; 193 } 194 195 196 /** 197 * cairo::createVirtualDevice: Create a VCL virtual device for the CGContext in the cairo Surface 198 * 199 * @return The new virtual device 200 **/ createVirtualDevice() const201 boost::shared_ptr<VirtualDevice> Win32Surface::createVirtualDevice() const 202 { 203 SystemGraphicsData aSystemGraphicsData; 204 aSystemGraphicsData.nSize = sizeof(SystemGraphicsData); 205 aSystemGraphicsData.hDC = cairo_win32_surface_get_dc( mpSurface.get() ); 206 207 return boost::shared_ptr<VirtualDevice>( 208 new VirtualDevice( &aSystemGraphicsData, sal::static_int_cast<USHORT>(getDepth()) )); 209 } 210 211 212 /** 213 * cairo::createSurface: Create generic Canvas surface using given Cairo Surface 214 * 215 * @param rSurface Cairo Surface 216 * 217 * @return new Surface 218 */ createSurface(const CairoSurfaceSharedPtr & rSurface)219 SurfaceSharedPtr createSurface( const CairoSurfaceSharedPtr& rSurface ) 220 { 221 return SurfaceSharedPtr(new Win32Surface(rSurface)); 222 } 223 224 225 /** 226 * cairo::createSurface: Create Canvas surface using given VCL Window or Virtualdevice 227 * 228 * @param rSurface Cairo Surface 229 * 230 * For VCL Window, use platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx) 231 * For VCL Virtualdevice, use platform native system graphics data (struct SystemGraphicsData in vcl/inc/sysdata.hxx) 232 * 233 * @return new Surface 234 */ createSurface(const OutputDevice & rRefDevice,int x,int y,int,int)235 SurfaceSharedPtr createSurface( const OutputDevice& rRefDevice, 236 int x, int y, int /* width */, int /* height */) 237 { 238 SurfaceSharedPtr surf; 239 240 if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW ) 241 { 242 const Window &rWindow = (const Window &) rRefDevice; 243 const SystemEnvData* pSysData = GetSysData(&rWindow); 244 if (pSysData && pSysData->hWnd) 245 surf = SurfaceSharedPtr(new Win32Surface(GetDC((HWND) pSysData->hWnd), x, y)); 246 } 247 else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV ) 248 { 249 SystemGraphicsData aSysData = ((const VirtualDevice&) rRefDevice).GetSystemGfxData(); 250 if (aSysData.hDC) 251 surf = SurfaceSharedPtr(new Win32Surface((HDC) aSysData.hDC, x, y)); 252 } 253 return surf; 254 } 255 256 257 /** 258 * cairo::createBitmapSurface: Create platform native Canvas surface from BitmapSystemData 259 * @param OutputDevice (not used) 260 * @param rData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx) 261 * @param rSize width and height of the new surface 262 * 263 * Create a surface based on image data on rData 264 * 265 * @return new surface or empty surface 266 **/ createBitmapSurface(const OutputDevice &,const BitmapSystemData & rData,const Size & rSize)267 SurfaceSharedPtr createBitmapSurface( const OutputDevice& /* rRefDevice */, 268 const BitmapSystemData& rData, 269 const Size& rSize ) 270 { 271 OSL_TRACE( "requested size: %d x %d available size: %d x %d", 272 rSize.Width(), rSize.Height(), rData.mnWidth, rData.mnHeight ); 273 274 if ( rData.mnWidth == rSize.Width() && rData.mnHeight == rSize.Height() ) 275 return SurfaceSharedPtr(new Win32Surface( rData )); 276 else 277 return SurfaceSharedPtr(); 278 } 279 280 281 /** 282 * cairo::ucs4toindex: Convert ucs4 char to glyph index 283 * @param ucs4 an ucs4 char 284 * @param hfont current font 285 * 286 * @return true if successful 287 **/ ucs4toindex(unsigned int ucs4,HFONT hfont)288 unsigned long ucs4toindex(unsigned int ucs4, HFONT hfont) 289 { 290 wchar_t unicode[2]; 291 WORD glyph_index; 292 HDC hdc = NULL; 293 int i = 0; 294 295 hdc = CreateCompatibleDC (NULL); 296 297 if (!hdc) return 0; 298 if (!SetGraphicsMode (hdc, GM_ADVANCED)) { 299 DeleteDC (hdc); 300 return 0; 301 } 302 303 SelectObject (hdc, hfont); 304 SetMapMode (hdc, MM_TEXT); 305 306 unicode[0] = ucs4; 307 unicode[1] = 0; 308 if (GetGlyphIndicesW (hdc, unicode, 1, &glyph_index, 0) == GDI_ERROR) { 309 glyph_index = 0; 310 } 311 312 DeleteDC (hdc); 313 return glyph_index; 314 } 315 316 317 } // namespace cairo 318 319 #endif // CAIRO_HAS_WIN32_SURFACE 320 321 #endif // WNT 322