blob: 6586e5e6ee341d4277188ff0401f19dec21a75cf [file]
/**************************************************************
*
* 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 <os2.h>
#include <osl/diagnose.h>
#include <vcl/bitmap.hxx>
#include <vcl/virdev.hxx>
#include <vcl/sysdata.hxx>
#include "cairo_os2_cairo.hxx"
namespace cairo
{
#include <cairo/cairo-os2.h>
// workaround for svpm.h definitions
#define sal_Bool BOOL
#define PM_FIXED FIXED
#define LPGLYPHMETRICS void*
#define MAT2 void
#include <ft2lib.h>
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<VirtualDevice> 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<VirtualDevice>(
new VirtualDevice( &aSystemGraphicsData, sal::static_int_cast<USHORT>(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