xref: /trunk/main/canvas/source/cairo/cairo_os2_cairo.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
1906a4e93SYuri Dario /**************************************************************
2906a4e93SYuri Dario  *
3906a4e93SYuri Dario  * Licensed to the Apache Software Foundation (ASF) under one
4906a4e93SYuri Dario  * or more contributor license agreements.  See the NOTICE file
5906a4e93SYuri Dario  * distributed with this work for additional information
6906a4e93SYuri Dario  * regarding copyright ownership.  The ASF licenses this file
7906a4e93SYuri Dario  * to you under the Apache License, Version 2.0 (the
8906a4e93SYuri Dario  * "License"); you may not use this file except in compliance
9906a4e93SYuri Dario  * with the License.  You may obtain a copy of the License at
10906a4e93SYuri Dario  *
11906a4e93SYuri Dario  *   http://www.apache.org/licenses/LICENSE-2.0
12906a4e93SYuri Dario  *
13906a4e93SYuri Dario  * Unless required by applicable law or agreed to in writing,
14906a4e93SYuri Dario  * software distributed under the License is distributed on an
15906a4e93SYuri Dario  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16906a4e93SYuri Dario  * KIND, either express or implied.  See the License for the
17906a4e93SYuri Dario  * specific language governing permissions and limitations
18906a4e93SYuri Dario  * under the License.
19906a4e93SYuri Dario  *
20906a4e93SYuri Dario  *************************************************************/
21906a4e93SYuri Dario 
22906a4e93SYuri Dario 
23906a4e93SYuri Dario 
24906a4e93SYuri Dario // MARKER(update_precomp.py): autogen include statement, do not remove
25906a4e93SYuri Dario #include "precompiled_canvas.hxx"
26906a4e93SYuri Dario 
27906a4e93SYuri Dario #ifdef OS2
28906a4e93SYuri Dario /************************************************************************
29906a4e93SYuri Dario  * OS/2 surface backend for Apache OpenOffice Cairo Canvas              *
30906a4e93SYuri Dario  ************************************************************************/
31906a4e93SYuri Dario 
32906a4e93SYuri Dario #define INCL_WIN
33906a4e93SYuri Dario #include <os2.h>
34906a4e93SYuri Dario 
35906a4e93SYuri Dario #include <osl/diagnose.h>
36906a4e93SYuri Dario #include <vcl/bitmap.hxx>
37906a4e93SYuri Dario #include <vcl/virdev.hxx>
38906a4e93SYuri Dario #include <vcl/sysdata.hxx>
39906a4e93SYuri Dario 
40906a4e93SYuri Dario #include "cairo_os2_cairo.hxx"
41906a4e93SYuri Dario 
42906a4e93SYuri Dario namespace cairo
43906a4e93SYuri Dario {
44906a4e93SYuri Dario 
45906a4e93SYuri Dario #include <cairo/cairo-os2.h>
46906a4e93SYuri Dario 
47906a4e93SYuri Dario // workaround for svpm.h definitions
48906a4e93SYuri Dario #define sal_Bool BOOL
49906a4e93SYuri Dario #define PM_FIXED FIXED
50906a4e93SYuri Dario #define LPGLYPHMETRICS void*
51906a4e93SYuri Dario #define MAT2 void
52906a4e93SYuri Dario #include <ft2lib.h>
53906a4e93SYuri Dario 
IsCairoWorking(OutputDevice *)54906a4e93SYuri Dario     bool IsCairoWorking( OutputDevice* )
55906a4e93SYuri Dario     {
56906a4e93SYuri Dario         // trivially true for OS/2
57906a4e93SYuri Dario         return true;
58906a4e93SYuri Dario     }
59906a4e93SYuri Dario 
60906a4e93SYuri Dario     /**
61906a4e93SYuri Dario      * Surface::Surface:     Create generic Canvas surface using given Cairo Surface
62906a4e93SYuri Dario      *
63906a4e93SYuri Dario      * @param pSurface Cairo Surface
64906a4e93SYuri Dario      *
65906a4e93SYuri Dario      * This constructor only stores data, it does no processing.
66906a4e93SYuri Dario      * It is used with e.g. cairo_image_surface_create_for_data()
67906a4e93SYuri Dario      * and Surface::getSimilar()
68906a4e93SYuri Dario      *
69906a4e93SYuri Dario      * Set the mpSurface to the new surface or NULL
70906a4e93SYuri Dario      **/
Os2Surface(const CairoSurfaceSharedPtr & pSurface)71906a4e93SYuri Dario     Os2Surface::Os2Surface( const CairoSurfaceSharedPtr& pSurface ) :
72906a4e93SYuri Dario         mpSurface( pSurface )
73906a4e93SYuri Dario     {}
74906a4e93SYuri Dario 
75906a4e93SYuri Dario     /**
76906a4e93SYuri Dario      * Surface::Surface:   Create Canvas surface from Window reference.
77906a4e93SYuri Dario      * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx)
78906a4e93SYuri Dario      * @param x horizontal location of the new surface
79906a4e93SYuri Dario      * @param y vertical location of the new surface
80906a4e93SYuri Dario      *
81906a4e93SYuri Dario      * pSysData contains the platform native Window reference.
82906a4e93SYuri Dario      * pSysData is used to create a surface on the Window
83906a4e93SYuri Dario      *
84906a4e93SYuri Dario      * Set the mpSurface to the new surface or NULL
85906a4e93SYuri Dario      **/
Os2Surface(HWND hwnd,int x,int y,int w,int h)86906a4e93SYuri Dario     Os2Surface::Os2Surface( HWND hwnd, int x, int y, int w, int h) :
87906a4e93SYuri Dario         mpSurface(
88906a4e93SYuri Dario             cairo_os2_surface_create_for_window( hwnd, w + x, h + y),
89906a4e93SYuri Dario             &cairo_surface_destroy)
90906a4e93SYuri Dario     {
91906a4e93SYuri Dario         OSL_TRACE( "Os2Surface::Os2Surface hwnd:%x offset: %d,%d size %d x %d",
92906a4e93SYuri Dario                    hwnd, x, y, w, h);
93906a4e93SYuri Dario         cairo_surface_set_device_offset( mpSurface.get(), 0, 0);
94906a4e93SYuri Dario     }
95906a4e93SYuri Dario 
96906a4e93SYuri Dario     /**
97906a4e93SYuri Dario      * Surface::Surface:   Create platform native Canvas surface from BitmapSystemData
98906a4e93SYuri Dario      * @param pBmpData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx)
99906a4e93SYuri Dario      *
100906a4e93SYuri Dario      * Create a surface based on image data on pBmpData
101906a4e93SYuri Dario      *
102906a4e93SYuri Dario      * Set the mpSurface to the new surface or NULL
103906a4e93SYuri Dario      **/
Os2Surface(const BitmapSystemData & rBmpData)104906a4e93SYuri Dario     Os2Surface::Os2Surface( const BitmapSystemData& rBmpData ) :
105906a4e93SYuri Dario         mpSurface()
106906a4e93SYuri Dario     {
107906a4e93SYuri Dario         OSL_TRACE( "Os2Surface::Os2Surface bitmap");
108906a4e93SYuri Dario #if 0
109906a4e93SYuri Dario         OSL_ASSERT(rBmpData.pDIB == NULL);
110906a4e93SYuri Dario 
111906a4e93SYuri Dario         if(rBmpData.pDIB != NULL) {
112906a4e93SYuri Dario             // So just leave mpSurface to NULL, little else we can do at
113906a4e93SYuri Dario             // this stage. Hopefully the Win32 patch to
114906a4e93SYuri Dario             // cairocanvas::DeviceHelper::getSurface(BitmapSystemData&,
115906a4e93SYuri Dario             // const Size&) will catch the cases where this
116906a4e93SYuri Dario             // constructor would be called with a DIB bitmap, and we
117906a4e93SYuri Dario             // will never get here. At least it worked for Ballmer.ppt.
118906a4e93SYuri Dario         }
119906a4e93SYuri Dario         else
120906a4e93SYuri Dario         {
121906a4e93SYuri Dario             HDC hDC = CreateCompatibleDC(NULL);
122906a4e93SYuri Dario             void* hOrigBitmap;
123906a4e93SYuri Dario             OSL_TRACE ("Surface::Surface(): Selecting bitmap %p into DC %p", rBmpData.pDDB, hDC);
124906a4e93SYuri Dario             hOrigBitmap = SelectObject( hDC, (HANDLE)rBmpData.pDDB );
125906a4e93SYuri Dario             if(hOrigBitmap == NULL)
126906a4e93SYuri Dario                 OSL_TRACE ("SelectObject failed: %d", GetLastError ());
127906a4e93SYuri Dario             mpSurface.reset(
128906a4e93SYuri Dario                 cairo_win32_surface_create(hDC),
129906a4e93SYuri Dario                 &cairo_surface_destroy);
130906a4e93SYuri Dario         }
131906a4e93SYuri Dario #endif
132906a4e93SYuri Dario     }
133906a4e93SYuri Dario 
134906a4e93SYuri Dario     /**
135906a4e93SYuri Dario      * Surface::getCairo:  Create Cairo (drawing object) for the Canvas surface
136906a4e93SYuri Dario      *
137906a4e93SYuri Dario      * @return new Cairo or NULL
138906a4e93SYuri Dario      **/
getCairo() const139906a4e93SYuri Dario     CairoSharedPtr Os2Surface::getCairo() const
140906a4e93SYuri Dario     {
141906a4e93SYuri Dario         return CairoSharedPtr( cairo_create(mpSurface.get()),
142906a4e93SYuri Dario                                &cairo_destroy );
143906a4e93SYuri Dario     }
144906a4e93SYuri Dario 
145906a4e93SYuri Dario     /**
146906a4e93SYuri Dario      * Surface::getSimilar:  Create new similar Canvas surface
147906a4e93SYuri Dario      * @param aContent format of the new surface (cairo_content_t from cairo/src/cairo.h)
148906a4e93SYuri Dario      * @param width width of the new surface
149906a4e93SYuri Dario      * @param height height of the new surface
150906a4e93SYuri Dario      *
151906a4e93SYuri Dario      * Creates a new Canvas surface. This normally creates platform native surface, even though
152906a4e93SYuri Dario      * generic function is used.
153906a4e93SYuri Dario      *
154906a4e93SYuri Dario      * Cairo surface from aContent (cairo_content_t)
155906a4e93SYuri Dario      *
156906a4e93SYuri Dario      * @return new surface or NULL
157906a4e93SYuri Dario      **/
getSimilar(Content aContent,int width,int height) const158906a4e93SYuri Dario     SurfaceSharedPtr Os2Surface::getSimilar( Content aContent, int width, int height ) const
159906a4e93SYuri Dario     {
160906a4e93SYuri Dario         OSL_TRACE( "Os2Surface::getSimilar size: %d x %d", width, height);
161906a4e93SYuri Dario         // cairo hits assertion in cairo-surface.c#535 if size is 0x0
162906a4e93SYuri Dario         int w = (width == 0 ? 1 : width);
163906a4e93SYuri Dario         int h = (height == 0 ? 1 : height);
164906a4e93SYuri Dario         return SurfaceSharedPtr(
165906a4e93SYuri Dario             new Os2Surface(
166906a4e93SYuri Dario                 CairoSurfaceSharedPtr(
167906a4e93SYuri Dario                     cairo_surface_create_similar( mpSurface.get(), aContent, w, h),
168906a4e93SYuri Dario                     &cairo_surface_destroy )));
169906a4e93SYuri Dario     }
170906a4e93SYuri Dario 
171906a4e93SYuri Dario     /**
172906a4e93SYuri Dario      * Surface::Resize:  Resizes the Canvas surface.
173906a4e93SYuri Dario      * @param width new width of the surface
174906a4e93SYuri Dario      * @param height new height of the surface
175906a4e93SYuri Dario      *
176906a4e93SYuri Dario      * Only used on X11.
177906a4e93SYuri Dario      *
178906a4e93SYuri Dario      * @return The new surface or NULL
179906a4e93SYuri Dario      **/
Resize(int width,int height)180906a4e93SYuri Dario     void Os2Surface::Resize( int width, int height)
181906a4e93SYuri Dario     {
182906a4e93SYuri Dario         cairo_os2_surface_set_size( mpSurface.get(), width, height, false);
183906a4e93SYuri Dario     }
184906a4e93SYuri Dario 
flush() const185906a4e93SYuri Dario     void Os2Surface::flush() const
186906a4e93SYuri Dario     {
187906a4e93SYuri Dario         OSL_TRACE( "Os2Surface::flush");
188906a4e93SYuri Dario         cairo_os2_surface_paint_window( mpSurface.get(), NULL, NULL, 0);
189906a4e93SYuri Dario     }
190906a4e93SYuri Dario 
191906a4e93SYuri Dario     /**
192906a4e93SYuri Dario      * Surface::getDepth:  Get the color depth of the Canvas surface.
193906a4e93SYuri Dario      *
194906a4e93SYuri Dario      * @return color depth
195906a4e93SYuri Dario      **/
getDepth() const196906a4e93SYuri Dario     int Os2Surface::getDepth() const
197906a4e93SYuri Dario     {
198906a4e93SYuri Dario         OSL_TRACE( "Os2Surface::getDepth");
199906a4e93SYuri Dario         if (mpSurface) {
200906a4e93SYuri Dario             switch (cairo_surface_get_content (mpSurface.get())) {
201906a4e93SYuri Dario                 case CAIRO_CONTENT_ALPHA:       return 8;  break;
202906a4e93SYuri Dario                 case CAIRO_CONTENT_COLOR:       return 24; break;
203906a4e93SYuri Dario                 case CAIRO_CONTENT_COLOR_ALPHA: return 32; break;
204906a4e93SYuri Dario             }
205906a4e93SYuri Dario         }
206906a4e93SYuri Dario         OSL_TRACE("Canvas::cairo::Surface::getDepth(): ERROR - depth unspecified!");
207906a4e93SYuri Dario         return -1;
208906a4e93SYuri Dario     }
209906a4e93SYuri Dario 
210906a4e93SYuri Dario 
211906a4e93SYuri Dario     /**
212906a4e93SYuri Dario      * cairo::createVirtualDevice:  Create a VCL virtual device for the CGContext in the cairo Surface
213906a4e93SYuri Dario      *
214906a4e93SYuri Dario      * @return The new virtual device
215906a4e93SYuri Dario      **/
createVirtualDevice() const216906a4e93SYuri Dario     boost::shared_ptr<VirtualDevice> Os2Surface::createVirtualDevice() const
217906a4e93SYuri Dario     {
218906a4e93SYuri Dario         SystemGraphicsData aSystemGraphicsData;
219906a4e93SYuri Dario         aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
220906a4e93SYuri Dario         //aSystemGraphicsData.hDC = cairo_win32_surface_get_dc( mpSurface.get() );
221906a4e93SYuri Dario         OSL_TRACE( "Os2Surface::createVirtualDevice");
222906a4e93SYuri Dario 
223906a4e93SYuri Dario         return boost::shared_ptr<VirtualDevice>(
224906a4e93SYuri Dario                     new VirtualDevice( &aSystemGraphicsData, sal::static_int_cast<USHORT>(getDepth()) ));
225906a4e93SYuri Dario     }
226906a4e93SYuri Dario 
227906a4e93SYuri Dario 
228906a4e93SYuri Dario     /**
229906a4e93SYuri Dario      * cairo::createSurface:     Create generic Canvas surface using given Cairo Surface
230906a4e93SYuri Dario      *
231906a4e93SYuri Dario      * @param rSurface Cairo Surface
232906a4e93SYuri Dario      *
233906a4e93SYuri Dario      * @return new Surface
234906a4e93SYuri Dario      */
createSurface(const CairoSurfaceSharedPtr & rSurface)235906a4e93SYuri Dario     SurfaceSharedPtr createSurface( const CairoSurfaceSharedPtr& rSurface )
236906a4e93SYuri Dario     {
237906a4e93SYuri Dario         OSL_TRACE( "Os2Surface createSurface from surface");
238906a4e93SYuri Dario         return SurfaceSharedPtr(new Os2Surface(rSurface));
239906a4e93SYuri Dario     }
240906a4e93SYuri Dario 
241906a4e93SYuri Dario 
242906a4e93SYuri Dario     /**
243906a4e93SYuri Dario      * cairo::createSurface:     Create Canvas surface using given VCL Window or Virtualdevice
244906a4e93SYuri Dario      *
245906a4e93SYuri Dario      * @param rSurface Cairo Surface
246906a4e93SYuri Dario      *
247906a4e93SYuri Dario      *  For VCL Window, use platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx)
248906a4e93SYuri Dario      *  For VCL Virtualdevice, use platform native system graphics data (struct SystemGraphicsData in vcl/inc/sysdata.hxx)
249906a4e93SYuri Dario      *
250906a4e93SYuri Dario      * @return new Surface
251906a4e93SYuri Dario      */
createSurface(const OutputDevice & rRefDevice,int x,int y,int width,int height)252906a4e93SYuri Dario     SurfaceSharedPtr createSurface( const OutputDevice& rRefDevice,
253906a4e93SYuri Dario                                     int x, int y, int width, int height)
254906a4e93SYuri Dario     {
255906a4e93SYuri Dario         SurfaceSharedPtr surf;
256906a4e93SYuri Dario         // cairo hits assertion in cairo-surface.c#535 if size is 0x0
257906a4e93SYuri Dario         int w = (width == 0 ? 1 : width);
258906a4e93SYuri Dario         int h = (height == 0 ? 1 : height);
259906a4e93SYuri Dario         OSL_TRACE( "createSurface refDev:%x, offset: %d x %d", &rRefDevice, x, y);
260906a4e93SYuri Dario 
261906a4e93SYuri Dario         if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW )
262906a4e93SYuri Dario         {
263906a4e93SYuri Dario             OSL_TRACE( "Os2Surface createSurface for WINDOW");
264906a4e93SYuri Dario             const Window &rWindow = (const Window &) rRefDevice;
265906a4e93SYuri Dario             const SystemEnvData* pSysData = GetSysData(&rWindow);
266906a4e93SYuri Dario             if (pSysData && pSysData->hWnd)
267906a4e93SYuri Dario                 surf = SurfaceSharedPtr(new Os2Surface(
268906a4e93SYuri Dario                                             pSysData->hWnd, x, y, w, h));
269906a4e93SYuri Dario         }
270906a4e93SYuri Dario         else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV )
271906a4e93SYuri Dario         {
272906a4e93SYuri Dario             OSL_TRACE( "Os2Surface createSurface for VIRDEV");
273906a4e93SYuri Dario             //SystemGraphicsData aSysData = ((const VirtualDevice&) rRefDevice).GetSystemGfxData();
274906a4e93SYuri Dario             //if (aSysData.hDC)
275906a4e93SYuri Dario             //    surf = SurfaceSharedPtr(new Os2Surface((HDC) aSysData.hDC, x, y));
276906a4e93SYuri Dario         }
277906a4e93SYuri Dario         return surf;
278906a4e93SYuri Dario     }
279906a4e93SYuri Dario 
280906a4e93SYuri Dario 
281906a4e93SYuri Dario     /**
282906a4e93SYuri Dario      * cairo::createBitmapSurface:   Create platform native Canvas surface from BitmapSystemData
283906a4e93SYuri Dario      * @param OutputDevice (not used)
284906a4e93SYuri Dario      * @param rData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx)
285906a4e93SYuri Dario      * @param rSize width and height of the new surface
286906a4e93SYuri Dario      *
287906a4e93SYuri Dario      * Create a surface based on image data on rData
288906a4e93SYuri Dario      *
289906a4e93SYuri Dario      * @return new surface or empty surface
290906a4e93SYuri Dario      **/
createBitmapSurface(const OutputDevice &,const BitmapSystemData & rData,const Size & rSize)291906a4e93SYuri Dario     SurfaceSharedPtr createBitmapSurface( const OutputDevice&     /* rRefDevice */,
292906a4e93SYuri Dario                                           const BitmapSystemData& rData,
293906a4e93SYuri Dario                                           const Size&             rSize )
294906a4e93SYuri Dario     {
295906a4e93SYuri Dario         OSL_TRACE( "createBitmapSurface requested size: %d x %d available size: %d x %d",
296906a4e93SYuri Dario                    rSize.Width(), rSize.Height(), rData.mnWidth, rData.mnHeight );
297906a4e93SYuri Dario 
298906a4e93SYuri Dario         if ( rData.mnWidth == rSize.Width() && rData.mnHeight == rSize.Height() )
299906a4e93SYuri Dario             return SurfaceSharedPtr(new Os2Surface( rData ));
300906a4e93SYuri Dario         else
301906a4e93SYuri Dario             return SurfaceSharedPtr();
302906a4e93SYuri Dario     }
303906a4e93SYuri Dario 
304906a4e93SYuri Dario     typedef USHORT WCHAR;
305906a4e93SYuri Dario     extern "C" ULONG APIENTRY Ft2GetGlyphIndices( HPS, WCHAR *, int, USHORT *, ULONG );
306906a4e93SYuri Dario 
307906a4e93SYuri Dario     /**
308906a4e93SYuri Dario      * cairo::ucs4toindex: Convert ucs4 char to glyph index
309906a4e93SYuri Dario      * @param ucs4 an ucs4 char
310906a4e93SYuri Dario      * @param hfont current font
311906a4e93SYuri Dario      *
312906a4e93SYuri Dario      * @return true if successful
313906a4e93SYuri Dario      **/
ucs4toindex(unsigned int ucs4,const char * font)314906a4e93SYuri Dario     unsigned long ucs4toindex(unsigned int ucs4, const char* font)
315906a4e93SYuri Dario     {
316906a4e93SYuri Dario         WCHAR unicode[2];
317906a4e93SYuri Dario         USHORT glyph_index;
318906a4e93SYuri Dario         HPS hps = NULL;
319906a4e93SYuri Dario         FATTRS fontAttrs;
320906a4e93SYuri Dario         APIRET rc;
321906a4e93SYuri Dario 
322906a4e93SYuri Dario         hps = WinGetPS( HWND_DESKTOP);
323906a4e93SYuri Dario         if (!hps) return 0;
324906a4e93SYuri Dario 
325906a4e93SYuri Dario         memset( &fontAttrs, 0, sizeof( fontAttrs));
326906a4e93SYuri Dario         fontAttrs.usRecordLength = sizeof( FATTRS);
327906a4e93SYuri Dario         fontAttrs.usCodePage = 850;
328906a4e93SYuri Dario         fontAttrs.fsType = FATTR_TYPE_MBCS;
329906a4e93SYuri Dario         fontAttrs.fsFontUse = FATTR_FONTUSE_NOMIX;
330*1919b60fSYuri Dario         // map StarSymbol to OpenSymbol
331*1919b60fSYuri Dario         if (strcmp( font, "StarSymbol") == 0)
332*1919b60fSYuri Dario             strcpy( fontAttrs.szFacename, "OpenSymbol");
333*1919b60fSYuri Dario         else
334906a4e93SYuri Dario             strcpy( fontAttrs.szFacename, font);
335906a4e93SYuri Dario         rc = Ft2CreateLogFont( hps, NULL, 1L, &fontAttrs);
336906a4e93SYuri Dario         rc = Ft2SetCharSet( hps, 1L);
337906a4e93SYuri Dario 
338906a4e93SYuri Dario         unicode[0] = ucs4;
339906a4e93SYuri Dario         unicode[1] = 0;
340906a4e93SYuri Dario         if (Ft2GetGlyphIndices( hps, unicode, 1, &glyph_index, 0) == -1) {
341906a4e93SYuri Dario             glyph_index = 0;
342906a4e93SYuri Dario         }
343906a4e93SYuri Dario 
344906a4e93SYuri Dario         WinReleasePS( hps);
345906a4e93SYuri Dario 
346906a4e93SYuri Dario         return glyph_index;
347906a4e93SYuri Dario     }
348906a4e93SYuri Dario 
349906a4e93SYuri Dario 
350906a4e93SYuri Dario }  // namespace cairo
351906a4e93SYuri Dario 
352906a4e93SYuri Dario #endif   // OS2
353