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 OS2 28 /************************************************************************ 29 * OS/2 surface backend for Apache OpenOffice Cairo Canvas * 30 ************************************************************************/ 31 32 #define INCL_WIN 33 #include <os2.h> 34 35 #include <osl/diagnose.h> 36 #include <vcl/bitmap.hxx> 37 #include <vcl/virdev.hxx> 38 #include <vcl/sysdata.hxx> 39 40 #include "cairo_os2_cairo.hxx" 41 42 namespace cairo 43 { 44 45 #include <cairo/cairo-os2.h> 46 47 // workaround for svpm.h definitions 48 #define sal_Bool BOOL 49 #define PM_FIXED FIXED 50 #define LPGLYPHMETRICS void* 51 #define MAT2 void 52 #include <ft2lib.h> 53 IsCairoWorking(OutputDevice *)54 bool IsCairoWorking( OutputDevice* ) 55 { 56 // trivially true for OS/2 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 **/ Os2Surface(const CairoSurfaceSharedPtr & pSurface)71 Os2Surface::Os2Surface( 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 **/ Os2Surface(HWND hwnd,int x,int y,int w,int h)86 Os2Surface::Os2Surface( HWND hwnd, int x, int y, int w, int h) : 87 mpSurface( 88 cairo_os2_surface_create_for_window( hwnd, w + x, h + y), 89 &cairo_surface_destroy) 90 { 91 OSL_TRACE( "Os2Surface::Os2Surface hwnd:%x offset: %d,%d size %d x %d", 92 hwnd, x, y, w, h); 93 cairo_surface_set_device_offset( mpSurface.get(), 0, 0); 94 } 95 96 /** 97 * Surface::Surface: Create platform native Canvas surface from BitmapSystemData 98 * @param pBmpData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx) 99 * 100 * Create a surface based on image data on pBmpData 101 * 102 * Set the mpSurface to the new surface or NULL 103 **/ Os2Surface(const BitmapSystemData & rBmpData)104 Os2Surface::Os2Surface( const BitmapSystemData& rBmpData ) : 105 mpSurface() 106 { 107 OSL_TRACE( "Os2Surface::Os2Surface bitmap"); 108 #if 0 109 OSL_ASSERT(rBmpData.pDIB == NULL); 110 111 if(rBmpData.pDIB != NULL) { 112 // So just leave mpSurface to NULL, little else we can do at 113 // this stage. Hopefully the Win32 patch to 114 // cairocanvas::DeviceHelper::getSurface(BitmapSystemData&, 115 // const Size&) will catch the cases where this 116 // constructor would be called with a DIB bitmap, and we 117 // will never get here. At least it worked for Ballmer.ppt. 118 } 119 else 120 { 121 HDC hDC = CreateCompatibleDC(NULL); 122 void* hOrigBitmap; 123 OSL_TRACE ("Surface::Surface(): Selecting bitmap %p into DC %p", rBmpData.pDDB, hDC); 124 hOrigBitmap = SelectObject( hDC, (HANDLE)rBmpData.pDDB ); 125 if(hOrigBitmap == NULL) 126 OSL_TRACE ("SelectObject failed: %d", GetLastError ()); 127 mpSurface.reset( 128 cairo_win32_surface_create(hDC), 129 &cairo_surface_destroy); 130 } 131 #endif 132 } 133 134 /** 135 * Surface::getCairo: Create Cairo (drawing object) for the Canvas surface 136 * 137 * @return new Cairo or NULL 138 **/ getCairo() const139 CairoSharedPtr Os2Surface::getCairo() const 140 { 141 return CairoSharedPtr( cairo_create(mpSurface.get()), 142 &cairo_destroy ); 143 } 144 145 /** 146 * Surface::getSimilar: Create new similar Canvas surface 147 * @param aContent format of the new surface (cairo_content_t from cairo/src/cairo.h) 148 * @param width width of the new surface 149 * @param height height of the new surface 150 * 151 * Creates a new Canvas surface. This normally creates platform native surface, even though 152 * generic function is used. 153 * 154 * Cairo surface from aContent (cairo_content_t) 155 * 156 * @return new surface or NULL 157 **/ getSimilar(Content aContent,int width,int height) const158 SurfaceSharedPtr Os2Surface::getSimilar( Content aContent, int width, int height ) const 159 { 160 OSL_TRACE( "Os2Surface::getSimilar size: %d x %d", width, height); 161 // cairo hits assertion in cairo-surface.c#535 if size is 0x0 162 int w = (width == 0 ? 1 : width); 163 int h = (height == 0 ? 1 : height); 164 return SurfaceSharedPtr( 165 new Os2Surface( 166 CairoSurfaceSharedPtr( 167 cairo_surface_create_similar( mpSurface.get(), aContent, w, h), 168 &cairo_surface_destroy ))); 169 } 170 171 /** 172 * Surface::Resize: Resizes the Canvas surface. 173 * @param width new width of the surface 174 * @param height new height of the surface 175 * 176 * Only used on X11. 177 * 178 * @return The new surface or NULL 179 **/ Resize(int width,int height)180 void Os2Surface::Resize( int width, int height) 181 { 182 cairo_os2_surface_set_size( mpSurface.get(), width, height, false); 183 } 184 flush() const185 void Os2Surface::flush() const 186 { 187 OSL_TRACE( "Os2Surface::flush"); 188 cairo_os2_surface_paint_window( mpSurface.get(), NULL, NULL, 0); 189 } 190 191 /** 192 * Surface::getDepth: Get the color depth of the Canvas surface. 193 * 194 * @return color depth 195 **/ getDepth() const196 int Os2Surface::getDepth() const 197 { 198 OSL_TRACE( "Os2Surface::getDepth"); 199 if (mpSurface) { 200 switch (cairo_surface_get_content (mpSurface.get())) { 201 case CAIRO_CONTENT_ALPHA: return 8; break; 202 case CAIRO_CONTENT_COLOR: return 24; break; 203 case CAIRO_CONTENT_COLOR_ALPHA: return 32; break; 204 } 205 } 206 OSL_TRACE("Canvas::cairo::Surface::getDepth(): ERROR - depth unspecified!"); 207 return -1; 208 } 209 210 211 /** 212 * cairo::createVirtualDevice: Create a VCL virtual device for the CGContext in the cairo Surface 213 * 214 * @return The new virtual device 215 **/ createVirtualDevice() const216 boost::shared_ptr<VirtualDevice> Os2Surface::createVirtualDevice() const 217 { 218 SystemGraphicsData aSystemGraphicsData; 219 aSystemGraphicsData.nSize = sizeof(SystemGraphicsData); 220 //aSystemGraphicsData.hDC = cairo_win32_surface_get_dc( mpSurface.get() ); 221 OSL_TRACE( "Os2Surface::createVirtualDevice"); 222 223 return boost::shared_ptr<VirtualDevice>( 224 new VirtualDevice( &aSystemGraphicsData, sal::static_int_cast<USHORT>(getDepth()) )); 225 } 226 227 228 /** 229 * cairo::createSurface: Create generic Canvas surface using given Cairo Surface 230 * 231 * @param rSurface Cairo Surface 232 * 233 * @return new Surface 234 */ createSurface(const CairoSurfaceSharedPtr & rSurface)235 SurfaceSharedPtr createSurface( const CairoSurfaceSharedPtr& rSurface ) 236 { 237 OSL_TRACE( "Os2Surface createSurface from surface"); 238 return SurfaceSharedPtr(new Os2Surface(rSurface)); 239 } 240 241 242 /** 243 * cairo::createSurface: Create Canvas surface using given VCL Window or Virtualdevice 244 * 245 * @param rSurface Cairo Surface 246 * 247 * For VCL Window, use platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx) 248 * For VCL Virtualdevice, use platform native system graphics data (struct SystemGraphicsData in vcl/inc/sysdata.hxx) 249 * 250 * @return new Surface 251 */ createSurface(const OutputDevice & rRefDevice,int x,int y,int width,int height)252 SurfaceSharedPtr createSurface( const OutputDevice& rRefDevice, 253 int x, int y, int width, int height) 254 { 255 SurfaceSharedPtr surf; 256 // cairo hits assertion in cairo-surface.c#535 if size is 0x0 257 int w = (width == 0 ? 1 : width); 258 int h = (height == 0 ? 1 : height); 259 OSL_TRACE( "createSurface refDev:%x, offset: %d x %d", &rRefDevice, x, y); 260 261 if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW ) 262 { 263 OSL_TRACE( "Os2Surface createSurface for WINDOW"); 264 const Window &rWindow = (const Window &) rRefDevice; 265 const SystemEnvData* pSysData = GetSysData(&rWindow); 266 if (pSysData && pSysData->hWnd) 267 surf = SurfaceSharedPtr(new Os2Surface( 268 pSysData->hWnd, x, y, w, h)); 269 } 270 else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV ) 271 { 272 OSL_TRACE( "Os2Surface createSurface for VIRDEV"); 273 //SystemGraphicsData aSysData = ((const VirtualDevice&) rRefDevice).GetSystemGfxData(); 274 //if (aSysData.hDC) 275 // surf = SurfaceSharedPtr(new Os2Surface((HDC) aSysData.hDC, x, y)); 276 } 277 return surf; 278 } 279 280 281 /** 282 * cairo::createBitmapSurface: Create platform native Canvas surface from BitmapSystemData 283 * @param OutputDevice (not used) 284 * @param rData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx) 285 * @param rSize width and height of the new surface 286 * 287 * Create a surface based on image data on rData 288 * 289 * @return new surface or empty surface 290 **/ createBitmapSurface(const OutputDevice &,const BitmapSystemData & rData,const Size & rSize)291 SurfaceSharedPtr createBitmapSurface( const OutputDevice& /* rRefDevice */, 292 const BitmapSystemData& rData, 293 const Size& rSize ) 294 { 295 OSL_TRACE( "createBitmapSurface requested size: %d x %d available size: %d x %d", 296 rSize.Width(), rSize.Height(), rData.mnWidth, rData.mnHeight ); 297 298 if ( rData.mnWidth == rSize.Width() && rData.mnHeight == rSize.Height() ) 299 return SurfaceSharedPtr(new Os2Surface( rData )); 300 else 301 return SurfaceSharedPtr(); 302 } 303 304 typedef USHORT WCHAR; 305 extern "C" ULONG APIENTRY Ft2GetGlyphIndices( HPS, WCHAR *, int, USHORT *, ULONG ); 306 307 /** 308 * cairo::ucs4toindex: Convert ucs4 char to glyph index 309 * @param ucs4 an ucs4 char 310 * @param hfont current font 311 * 312 * @return true if successful 313 **/ ucs4toindex(unsigned int ucs4,const char * font)314 unsigned long ucs4toindex(unsigned int ucs4, const char* font) 315 { 316 WCHAR unicode[2]; 317 USHORT glyph_index; 318 HPS hps = NULL; 319 FATTRS fontAttrs; 320 APIRET rc; 321 322 hps = WinGetPS( HWND_DESKTOP); 323 if (!hps) return 0; 324 325 memset( &fontAttrs, 0, sizeof( fontAttrs)); 326 fontAttrs.usRecordLength = sizeof( FATTRS); 327 fontAttrs.usCodePage = 850; 328 fontAttrs.fsType = FATTR_TYPE_MBCS; 329 fontAttrs.fsFontUse = FATTR_FONTUSE_NOMIX; 330 // map StarSymbol to OpenSymbol 331 if (strcmp( font, "StarSymbol") == 0) 332 strcpy( fontAttrs.szFacename, "OpenSymbol"); 333 else 334 strcpy( fontAttrs.szFacename, font); 335 rc = Ft2CreateLogFont( hps, NULL, 1L, &fontAttrs); 336 rc = Ft2SetCharSet( hps, 1L); 337 338 unicode[0] = ucs4; 339 unicode[1] = 0; 340 if (Ft2GetGlyphIndices( hps, unicode, 1, &glyph_index, 0) == -1) { 341 glyph_index = 0; 342 } 343 344 WinReleasePS( hps); 345 346 return glyph_index; 347 } 348 349 350 } // namespace cairo 351 352 #endif // OS2 353