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