/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_canvas.hxx" #ifdef OS2 /************************************************************************ * OS/2 surface backend for Apache OpenOffice Cairo Canvas * ************************************************************************/ #define INCL_WIN #include #include #include #include #include #include "cairo_os2_cairo.hxx" namespace cairo { #include // workaround for svpm.h definitions #define sal_Bool BOOL #define PM_FIXED FIXED #define LPGLYPHMETRICS void* #define MAT2 void #include bool IsCairoWorking( OutputDevice* ) { // trivially true for OS/2 return true; } /** * Surface::Surface: Create generic Canvas surface using given Cairo Surface * * @param pSurface Cairo Surface * * This constructor only stores data, it does no processing. * It is used with e.g. cairo_image_surface_create_for_data() * and Surface::getSimilar() * * Set the mpSurface to the new surface or NULL **/ Os2Surface::Os2Surface( const CairoSurfaceSharedPtr& pSurface ) : mpSurface( pSurface ) {} /** * Surface::Surface: Create Canvas surface from Window reference. * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx) * @param x horizontal location of the new surface * @param y vertical location of the new surface * * pSysData contains the platform native Window reference. * pSysData is used to create a surface on the Window * * Set the mpSurface to the new surface or NULL **/ Os2Surface::Os2Surface( HWND hwnd, int x, int y, int w, int h) : mpSurface( cairo_os2_surface_create_for_window( hwnd, w + x, h + y), &cairo_surface_destroy) { OSL_TRACE( "Os2Surface::Os2Surface hwnd:%x offset: %d,%d size %d x %d", hwnd, x, y, w, h); cairo_surface_set_device_offset( mpSurface.get(), 0, 0); } /** * Surface::Surface: Create platform native Canvas surface from BitmapSystemData * @param pBmpData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx) * * Create a surface based on image data on pBmpData * * Set the mpSurface to the new surface or NULL **/ Os2Surface::Os2Surface( const BitmapSystemData& rBmpData ) : mpSurface() { OSL_TRACE( "Os2Surface::Os2Surface bitmap"); #if 0 OSL_ASSERT(rBmpData.pDIB == NULL); if(rBmpData.pDIB != NULL) { // So just leave mpSurface to NULL, little else we can do at // this stage. Hopefully the Win32 patch to // cairocanvas::DeviceHelper::getSurface(BitmapSystemData&, // const Size&) will catch the cases where this // constructor would be called with a DIB bitmap, and we // will never get here. At least it worked for Ballmer.ppt. } else { HDC hDC = CreateCompatibleDC(NULL); void* hOrigBitmap; OSL_TRACE ("Surface::Surface(): Selecting bitmap %p into DC %p", rBmpData.pDDB, hDC); hOrigBitmap = SelectObject( hDC, (HANDLE)rBmpData.pDDB ); if(hOrigBitmap == NULL) OSL_TRACE ("SelectObject failed: %d", GetLastError ()); mpSurface.reset( cairo_win32_surface_create(hDC), &cairo_surface_destroy); } #endif } /** * Surface::getCairo: Create Cairo (drawing object) for the Canvas surface * * @return new Cairo or NULL **/ CairoSharedPtr Os2Surface::getCairo() const { return CairoSharedPtr( cairo_create(mpSurface.get()), &cairo_destroy ); } /** * Surface::getSimilar: Create new similar Canvas surface * @param aContent format of the new surface (cairo_content_t from cairo/src/cairo.h) * @param width width of the new surface * @param height height of the new surface * * Creates a new Canvas surface. This normally creates platform native surface, even though * generic function is used. * * Cairo surface from aContent (cairo_content_t) * * @return new surface or NULL **/ SurfaceSharedPtr Os2Surface::getSimilar( Content aContent, int width, int height ) const { OSL_TRACE( "Os2Surface::getSimilar size: %d x %d", width, height); // cairo hits assertion in cairo-surface.c#535 if size is 0x0 int w = (width == 0 ? 1 : width); int h = (height == 0 ? 1 : height); return SurfaceSharedPtr( new Os2Surface( CairoSurfaceSharedPtr( cairo_surface_create_similar( mpSurface.get(), aContent, w, h), &cairo_surface_destroy ))); } /** * Surface::Resize: Resizes the Canvas surface. * @param width new width of the surface * @param height new height of the surface * * Only used on X11. * * @return The new surface or NULL **/ void Os2Surface::Resize( int width, int height) { cairo_os2_surface_set_size( mpSurface.get(), width, height, false); } void Os2Surface::flush() const { OSL_TRACE( "Os2Surface::flush"); cairo_os2_surface_paint_window( mpSurface.get(), NULL, NULL, 0); } /** * Surface::getDepth: Get the color depth of the Canvas surface. * * @return color depth **/ int Os2Surface::getDepth() const { OSL_TRACE( "Os2Surface::getDepth"); if (mpSurface) { switch (cairo_surface_get_content (mpSurface.get())) { case CAIRO_CONTENT_ALPHA: return 8; break; case CAIRO_CONTENT_COLOR: return 24; break; case CAIRO_CONTENT_COLOR_ALPHA: return 32; break; } } OSL_TRACE("Canvas::cairo::Surface::getDepth(): ERROR - depth unspecified!"); return -1; } /** * cairo::createVirtualDevice: Create a VCL virtual device for the CGContext in the cairo Surface * * @return The new virtual device **/ boost::shared_ptr Os2Surface::createVirtualDevice() const { SystemGraphicsData aSystemGraphicsData; aSystemGraphicsData.nSize = sizeof(SystemGraphicsData); //aSystemGraphicsData.hDC = cairo_win32_surface_get_dc( mpSurface.get() ); OSL_TRACE( "Os2Surface::createVirtualDevice"); return boost::shared_ptr( new VirtualDevice( &aSystemGraphicsData, sal::static_int_cast(getDepth()) )); } /** * cairo::createSurface: Create generic Canvas surface using given Cairo Surface * * @param rSurface Cairo Surface * * @return new Surface */ SurfaceSharedPtr createSurface( const CairoSurfaceSharedPtr& rSurface ) { OSL_TRACE( "Os2Surface createSurface from surface"); return SurfaceSharedPtr(new Os2Surface(rSurface)); } /** * cairo::createSurface: Create Canvas surface using given VCL Window or Virtualdevice * * @param rSurface Cairo Surface * * For VCL Window, use platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx) * For VCL Virtualdevice, use platform native system graphics data (struct SystemGraphicsData in vcl/inc/sysdata.hxx) * * @return new Surface */ SurfaceSharedPtr createSurface( const OutputDevice& rRefDevice, int x, int y, int width, int height) { SurfaceSharedPtr surf; // cairo hits assertion in cairo-surface.c#535 if size is 0x0 int w = (width == 0 ? 1 : width); int h = (height == 0 ? 1 : height); OSL_TRACE( "createSurface refDev:%x, offset: %d x %d", &rRefDevice, x, y); if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW ) { OSL_TRACE( "Os2Surface createSurface for WINDOW"); const Window &rWindow = (const Window &) rRefDevice; const SystemEnvData* pSysData = GetSysData(&rWindow); if (pSysData && pSysData->hWnd) surf = SurfaceSharedPtr(new Os2Surface( pSysData->hWnd, x, y, w, h)); } else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV ) { OSL_TRACE( "Os2Surface createSurface for VIRDEV"); //SystemGraphicsData aSysData = ((const VirtualDevice&) rRefDevice).GetSystemGfxData(); //if (aSysData.hDC) // surf = SurfaceSharedPtr(new Os2Surface((HDC) aSysData.hDC, x, y)); } return surf; } /** * cairo::createBitmapSurface: Create platform native Canvas surface from BitmapSystemData * @param OutputDevice (not used) * @param rData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx) * @param rSize width and height of the new surface * * Create a surface based on image data on rData * * @return new surface or empty surface **/ SurfaceSharedPtr createBitmapSurface( const OutputDevice& /* rRefDevice */, const BitmapSystemData& rData, const Size& rSize ) { OSL_TRACE( "createBitmapSurface requested size: %d x %d available size: %d x %d", rSize.Width(), rSize.Height(), rData.mnWidth, rData.mnHeight ); if ( rData.mnWidth == rSize.Width() && rData.mnHeight == rSize.Height() ) return SurfaceSharedPtr(new Os2Surface( rData )); else return SurfaceSharedPtr(); } typedef USHORT WCHAR; extern "C" ULONG APIENTRY Ft2GetGlyphIndices( HPS, WCHAR *, int, USHORT *, ULONG ); /** * cairo::ucs4toindex: Convert ucs4 char to glyph index * @param ucs4 an ucs4 char * @param hfont current font * * @return true if successful **/ unsigned long ucs4toindex(unsigned int ucs4, const char* font) { WCHAR unicode[2]; USHORT glyph_index; HPS hps = NULL; FATTRS fontAttrs; APIRET rc; hps = WinGetPS( HWND_DESKTOP); if (!hps) return 0; memset( &fontAttrs, 0, sizeof( fontAttrs)); fontAttrs.usRecordLength = sizeof( FATTRS); fontAttrs.usCodePage = 850; fontAttrs.fsType = FATTR_TYPE_MBCS; fontAttrs.fsFontUse = FATTR_FONTUSE_NOMIX; // map StarSymbol to OpenSymbol if (strcmp( font, "StarSymbol") == 0) strcpy( fontAttrs.szFacename, "OpenSymbol"); else strcpy( fontAttrs.szFacename, font); rc = Ft2CreateLogFont( hps, NULL, 1L, &fontAttrs); rc = Ft2SetCharSet( hps, 1L); unicode[0] = ucs4; unicode[1] = 0; if (Ft2GetGlyphIndices( hps, unicode, 1, &glyph_index, 0) == -1) { glyph_index = 0; } WinReleasePS( hps); return glyph_index; } } // namespace cairo #endif // OS2