xref: /trunk/main/canvas/source/cairo/cairo_os2_cairo.cxx (revision 906a4e93d5b4ffdb4ad3f13b8caa67184206760c)
1*906a4e93SYuri Dario /**************************************************************
2*906a4e93SYuri Dario  *
3*906a4e93SYuri Dario  * Licensed to the Apache Software Foundation (ASF) under one
4*906a4e93SYuri Dario  * or more contributor license agreements.  See the NOTICE file
5*906a4e93SYuri Dario  * distributed with this work for additional information
6*906a4e93SYuri Dario  * regarding copyright ownership.  The ASF licenses this file
7*906a4e93SYuri Dario  * to you under the Apache License, Version 2.0 (the
8*906a4e93SYuri Dario  * "License"); you may not use this file except in compliance
9*906a4e93SYuri Dario  * with the License.  You may obtain a copy of the License at
10*906a4e93SYuri Dario  *
11*906a4e93SYuri Dario  *   http://www.apache.org/licenses/LICENSE-2.0
12*906a4e93SYuri Dario  *
13*906a4e93SYuri Dario  * Unless required by applicable law or agreed to in writing,
14*906a4e93SYuri Dario  * software distributed under the License is distributed on an
15*906a4e93SYuri Dario  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*906a4e93SYuri Dario  * KIND, either express or implied.  See the License for the
17*906a4e93SYuri Dario  * specific language governing permissions and limitations
18*906a4e93SYuri Dario  * under the License.
19*906a4e93SYuri Dario  *
20*906a4e93SYuri Dario  *************************************************************/
21*906a4e93SYuri Dario 
22*906a4e93SYuri Dario 
23*906a4e93SYuri Dario 
24*906a4e93SYuri Dario // MARKER(update_precomp.py): autogen include statement, do not remove
25*906a4e93SYuri Dario #include "precompiled_canvas.hxx"
26*906a4e93SYuri Dario 
27*906a4e93SYuri Dario #ifdef OS2
28*906a4e93SYuri Dario /************************************************************************
29*906a4e93SYuri Dario  * OS/2 surface backend for Apache OpenOffice Cairo Canvas              *
30*906a4e93SYuri Dario  ************************************************************************/
31*906a4e93SYuri Dario 
32*906a4e93SYuri Dario #define INCL_WIN
33*906a4e93SYuri Dario #include <os2.h>
34*906a4e93SYuri Dario 
35*906a4e93SYuri Dario #include <osl/diagnose.h>
36*906a4e93SYuri Dario #include <vcl/bitmap.hxx>
37*906a4e93SYuri Dario #include <vcl/virdev.hxx>
38*906a4e93SYuri Dario #include <vcl/sysdata.hxx>
39*906a4e93SYuri Dario 
40*906a4e93SYuri Dario #include "cairo_os2_cairo.hxx"
41*906a4e93SYuri Dario 
42*906a4e93SYuri Dario namespace cairo
43*906a4e93SYuri Dario {
44*906a4e93SYuri Dario 
45*906a4e93SYuri Dario #include <cairo/cairo-os2.h>
46*906a4e93SYuri Dario 
47*906a4e93SYuri Dario // workaround for svpm.h definitions
48*906a4e93SYuri Dario #define sal_Bool BOOL
49*906a4e93SYuri Dario #define PM_FIXED FIXED
50*906a4e93SYuri Dario #define LPGLYPHMETRICS void*
51*906a4e93SYuri Dario #define MAT2 void
52*906a4e93SYuri Dario #include <ft2lib.h>
53*906a4e93SYuri Dario 
54*906a4e93SYuri Dario     bool IsCairoWorking( OutputDevice* )
55*906a4e93SYuri Dario     {
56*906a4e93SYuri Dario         // trivially true for OS/2
57*906a4e93SYuri Dario         return true;
58*906a4e93SYuri Dario     }
59*906a4e93SYuri Dario 
60*906a4e93SYuri Dario     /**
61*906a4e93SYuri Dario      * Surface::Surface:     Create generic Canvas surface using given Cairo Surface
62*906a4e93SYuri Dario      *
63*906a4e93SYuri Dario      * @param pSurface Cairo Surface
64*906a4e93SYuri Dario      *
65*906a4e93SYuri Dario      * This constructor only stores data, it does no processing.
66*906a4e93SYuri Dario      * It is used with e.g. cairo_image_surface_create_for_data()
67*906a4e93SYuri Dario      * and Surface::getSimilar()
68*906a4e93SYuri Dario      *
69*906a4e93SYuri Dario      * Set the mpSurface to the new surface or NULL
70*906a4e93SYuri Dario      **/
71*906a4e93SYuri Dario     Os2Surface::Os2Surface( const CairoSurfaceSharedPtr& pSurface ) :
72*906a4e93SYuri Dario         mpSurface( pSurface )
73*906a4e93SYuri Dario     {}
74*906a4e93SYuri Dario 
75*906a4e93SYuri Dario     /**
76*906a4e93SYuri Dario      * Surface::Surface:   Create Canvas surface from Window reference.
77*906a4e93SYuri Dario      * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx)
78*906a4e93SYuri Dario      * @param x horizontal location of the new surface
79*906a4e93SYuri Dario      * @param y vertical location of the new surface
80*906a4e93SYuri Dario      *
81*906a4e93SYuri Dario      * pSysData contains the platform native Window reference.
82*906a4e93SYuri Dario      * pSysData is used to create a surface on the Window
83*906a4e93SYuri Dario      *
84*906a4e93SYuri Dario      * Set the mpSurface to the new surface or NULL
85*906a4e93SYuri Dario      **/
86*906a4e93SYuri Dario     Os2Surface::Os2Surface( HWND hwnd, int x, int y, int w, int h) :
87*906a4e93SYuri Dario         mpSurface(
88*906a4e93SYuri Dario             cairo_os2_surface_create_for_window( hwnd, w + x, h + y),
89*906a4e93SYuri Dario             &cairo_surface_destroy)
90*906a4e93SYuri Dario     {
91*906a4e93SYuri Dario         OSL_TRACE( "Os2Surface::Os2Surface hwnd:%x offset: %d,%d size %d x %d",
92*906a4e93SYuri Dario                    hwnd, x, y, w, h);
93*906a4e93SYuri Dario         cairo_surface_set_device_offset( mpSurface.get(), 0, 0);
94*906a4e93SYuri Dario     }
95*906a4e93SYuri Dario 
96*906a4e93SYuri Dario     /**
97*906a4e93SYuri Dario      * Surface::Surface:   Create platform native Canvas surface from BitmapSystemData
98*906a4e93SYuri Dario      * @param pBmpData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx)
99*906a4e93SYuri Dario      *
100*906a4e93SYuri Dario      * Create a surface based on image data on pBmpData
101*906a4e93SYuri Dario      *
102*906a4e93SYuri Dario      * Set the mpSurface to the new surface or NULL
103*906a4e93SYuri Dario      **/
104*906a4e93SYuri Dario     Os2Surface::Os2Surface( const BitmapSystemData& rBmpData ) :
105*906a4e93SYuri Dario         mpSurface()
106*906a4e93SYuri Dario     {
107*906a4e93SYuri Dario         OSL_TRACE( "Os2Surface::Os2Surface bitmap");
108*906a4e93SYuri Dario #if 0
109*906a4e93SYuri Dario         OSL_ASSERT(rBmpData.pDIB == NULL);
110*906a4e93SYuri Dario 
111*906a4e93SYuri Dario         if(rBmpData.pDIB != NULL) {
112*906a4e93SYuri Dario             // So just leave mpSurface to NULL, little else we can do at
113*906a4e93SYuri Dario             // this stage. Hopefully the Win32 patch to
114*906a4e93SYuri Dario             // cairocanvas::DeviceHelper::getSurface(BitmapSystemData&,
115*906a4e93SYuri Dario             // const Size&) will catch the cases where this
116*906a4e93SYuri Dario             // constructor would be called with a DIB bitmap, and we
117*906a4e93SYuri Dario             // will never get here. At least it worked for Ballmer.ppt.
118*906a4e93SYuri Dario         }
119*906a4e93SYuri Dario         else
120*906a4e93SYuri Dario         {
121*906a4e93SYuri Dario             HDC hDC = CreateCompatibleDC(NULL);
122*906a4e93SYuri Dario             void* hOrigBitmap;
123*906a4e93SYuri Dario             OSL_TRACE ("Surface::Surface(): Selecting bitmap %p into DC %p", rBmpData.pDDB, hDC);
124*906a4e93SYuri Dario             hOrigBitmap = SelectObject( hDC, (HANDLE)rBmpData.pDDB );
125*906a4e93SYuri Dario             if(hOrigBitmap == NULL)
126*906a4e93SYuri Dario                 OSL_TRACE ("SelectObject failed: %d", GetLastError ());
127*906a4e93SYuri Dario             mpSurface.reset(
128*906a4e93SYuri Dario                 cairo_win32_surface_create(hDC),
129*906a4e93SYuri Dario                 &cairo_surface_destroy);
130*906a4e93SYuri Dario         }
131*906a4e93SYuri Dario #endif
132*906a4e93SYuri Dario     }
133*906a4e93SYuri Dario 
134*906a4e93SYuri Dario     /**
135*906a4e93SYuri Dario      * Surface::getCairo:  Create Cairo (drawing object) for the Canvas surface
136*906a4e93SYuri Dario      *
137*906a4e93SYuri Dario      * @return new Cairo or NULL
138*906a4e93SYuri Dario      **/
139*906a4e93SYuri Dario     CairoSharedPtr Os2Surface::getCairo() const
140*906a4e93SYuri Dario     {
141*906a4e93SYuri Dario         return CairoSharedPtr( cairo_create(mpSurface.get()),
142*906a4e93SYuri Dario                                &cairo_destroy );
143*906a4e93SYuri Dario     }
144*906a4e93SYuri Dario 
145*906a4e93SYuri Dario     /**
146*906a4e93SYuri Dario      * Surface::getSimilar:  Create new similar Canvas surface
147*906a4e93SYuri Dario      * @param aContent format of the new surface (cairo_content_t from cairo/src/cairo.h)
148*906a4e93SYuri Dario      * @param width width of the new surface
149*906a4e93SYuri Dario      * @param height height of the new surface
150*906a4e93SYuri Dario      *
151*906a4e93SYuri Dario      * Creates a new Canvas surface. This normally creates platform native surface, even though
152*906a4e93SYuri Dario      * generic function is used.
153*906a4e93SYuri Dario      *
154*906a4e93SYuri Dario      * Cairo surface from aContent (cairo_content_t)
155*906a4e93SYuri Dario      *
156*906a4e93SYuri Dario      * @return new surface or NULL
157*906a4e93SYuri Dario      **/
158*906a4e93SYuri Dario     SurfaceSharedPtr Os2Surface::getSimilar( Content aContent, int width, int height ) const
159*906a4e93SYuri Dario     {
160*906a4e93SYuri Dario         OSL_TRACE( "Os2Surface::getSimilar size: %d x %d", width, height);
161*906a4e93SYuri Dario         // cairo hits assertion in cairo-surface.c#535 if size is 0x0
162*906a4e93SYuri Dario         int w = (width == 0 ? 1 : width);
163*906a4e93SYuri Dario         int h = (height == 0 ? 1 : height);
164*906a4e93SYuri Dario         return SurfaceSharedPtr(
165*906a4e93SYuri Dario             new Os2Surface(
166*906a4e93SYuri Dario                 CairoSurfaceSharedPtr(
167*906a4e93SYuri Dario                     cairo_surface_create_similar( mpSurface.get(), aContent, w, h),
168*906a4e93SYuri Dario                     &cairo_surface_destroy )));
169*906a4e93SYuri Dario     }
170*906a4e93SYuri Dario 
171*906a4e93SYuri Dario     /**
172*906a4e93SYuri Dario      * Surface::Resize:  Resizes the Canvas surface.
173*906a4e93SYuri Dario      * @param width new width of the surface
174*906a4e93SYuri Dario      * @param height new height of the surface
175*906a4e93SYuri Dario      *
176*906a4e93SYuri Dario      * Only used on X11.
177*906a4e93SYuri Dario      *
178*906a4e93SYuri Dario      * @return The new surface or NULL
179*906a4e93SYuri Dario      **/
180*906a4e93SYuri Dario     void Os2Surface::Resize( int width, int height)
181*906a4e93SYuri Dario     {
182*906a4e93SYuri Dario         cairo_os2_surface_set_size( mpSurface.get(), width, height, false);
183*906a4e93SYuri Dario     }
184*906a4e93SYuri Dario 
185*906a4e93SYuri Dario     void Os2Surface::flush() const
186*906a4e93SYuri Dario     {
187*906a4e93SYuri Dario         OSL_TRACE( "Os2Surface::flush");
188*906a4e93SYuri Dario         cairo_os2_surface_paint_window( mpSurface.get(), NULL, NULL, 0);
189*906a4e93SYuri Dario     }
190*906a4e93SYuri Dario 
191*906a4e93SYuri Dario     /**
192*906a4e93SYuri Dario      * Surface::getDepth:  Get the color depth of the Canvas surface.
193*906a4e93SYuri Dario      *
194*906a4e93SYuri Dario      * @return color depth
195*906a4e93SYuri Dario      **/
196*906a4e93SYuri Dario     int Os2Surface::getDepth() const
197*906a4e93SYuri Dario     {
198*906a4e93SYuri Dario         OSL_TRACE( "Os2Surface::getDepth");
199*906a4e93SYuri Dario         if (mpSurface) {
200*906a4e93SYuri Dario             switch (cairo_surface_get_content (mpSurface.get())) {
201*906a4e93SYuri Dario                 case CAIRO_CONTENT_ALPHA:       return 8;  break;
202*906a4e93SYuri Dario                 case CAIRO_CONTENT_COLOR:       return 24; break;
203*906a4e93SYuri Dario                 case CAIRO_CONTENT_COLOR_ALPHA: return 32; break;
204*906a4e93SYuri Dario             }
205*906a4e93SYuri Dario         }
206*906a4e93SYuri Dario         OSL_TRACE("Canvas::cairo::Surface::getDepth(): ERROR - depth unspecified!");
207*906a4e93SYuri Dario         return -1;
208*906a4e93SYuri Dario     }
209*906a4e93SYuri Dario 
210*906a4e93SYuri Dario 
211*906a4e93SYuri Dario     /**
212*906a4e93SYuri Dario      * cairo::createVirtualDevice:  Create a VCL virtual device for the CGContext in the cairo Surface
213*906a4e93SYuri Dario      *
214*906a4e93SYuri Dario      * @return The new virtual device
215*906a4e93SYuri Dario      **/
216*906a4e93SYuri Dario     boost::shared_ptr<VirtualDevice> Os2Surface::createVirtualDevice() const
217*906a4e93SYuri Dario     {
218*906a4e93SYuri Dario         SystemGraphicsData aSystemGraphicsData;
219*906a4e93SYuri Dario         aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
220*906a4e93SYuri Dario         //aSystemGraphicsData.hDC = cairo_win32_surface_get_dc( mpSurface.get() );
221*906a4e93SYuri Dario         OSL_TRACE( "Os2Surface::createVirtualDevice");
222*906a4e93SYuri Dario 
223*906a4e93SYuri Dario         return boost::shared_ptr<VirtualDevice>(
224*906a4e93SYuri Dario                     new VirtualDevice( &aSystemGraphicsData, sal::static_int_cast<USHORT>(getDepth()) ));
225*906a4e93SYuri Dario     }
226*906a4e93SYuri Dario 
227*906a4e93SYuri Dario 
228*906a4e93SYuri Dario     /**
229*906a4e93SYuri Dario      * cairo::createSurface:     Create generic Canvas surface using given Cairo Surface
230*906a4e93SYuri Dario      *
231*906a4e93SYuri Dario      * @param rSurface Cairo Surface
232*906a4e93SYuri Dario      *
233*906a4e93SYuri Dario      * @return new Surface
234*906a4e93SYuri Dario      */
235*906a4e93SYuri Dario     SurfaceSharedPtr createSurface( const CairoSurfaceSharedPtr& rSurface )
236*906a4e93SYuri Dario     {
237*906a4e93SYuri Dario         OSL_TRACE( "Os2Surface createSurface from surface");
238*906a4e93SYuri Dario         return SurfaceSharedPtr(new Os2Surface(rSurface));
239*906a4e93SYuri Dario     }
240*906a4e93SYuri Dario 
241*906a4e93SYuri Dario 
242*906a4e93SYuri Dario     /**
243*906a4e93SYuri Dario      * cairo::createSurface:     Create Canvas surface using given VCL Window or Virtualdevice
244*906a4e93SYuri Dario      *
245*906a4e93SYuri Dario      * @param rSurface Cairo Surface
246*906a4e93SYuri Dario      *
247*906a4e93SYuri Dario      *  For VCL Window, use platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx)
248*906a4e93SYuri Dario      *  For VCL Virtualdevice, use platform native system graphics data (struct SystemGraphicsData in vcl/inc/sysdata.hxx)
249*906a4e93SYuri Dario      *
250*906a4e93SYuri Dario      * @return new Surface
251*906a4e93SYuri Dario      */
252*906a4e93SYuri Dario     SurfaceSharedPtr createSurface( const OutputDevice& rRefDevice,
253*906a4e93SYuri Dario                                     int x, int y, int width, int height)
254*906a4e93SYuri Dario     {
255*906a4e93SYuri Dario         SurfaceSharedPtr surf;
256*906a4e93SYuri Dario         // cairo hits assertion in cairo-surface.c#535 if size is 0x0
257*906a4e93SYuri Dario         int w = (width == 0 ? 1 : width);
258*906a4e93SYuri Dario         int h = (height == 0 ? 1 : height);
259*906a4e93SYuri Dario         OSL_TRACE( "createSurface refDev:%x, offset: %d x %d", &rRefDevice, x, y);
260*906a4e93SYuri Dario 
261*906a4e93SYuri Dario         if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW )
262*906a4e93SYuri Dario         {
263*906a4e93SYuri Dario             OSL_TRACE( "Os2Surface createSurface for WINDOW");
264*906a4e93SYuri Dario             const Window &rWindow = (const Window &) rRefDevice;
265*906a4e93SYuri Dario             const SystemEnvData* pSysData = GetSysData(&rWindow);
266*906a4e93SYuri Dario             if (pSysData && pSysData->hWnd)
267*906a4e93SYuri Dario                 surf = SurfaceSharedPtr(new Os2Surface(
268*906a4e93SYuri Dario                                             pSysData->hWnd, x, y, w, h));
269*906a4e93SYuri Dario         }
270*906a4e93SYuri Dario         else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV )
271*906a4e93SYuri Dario         {
272*906a4e93SYuri Dario             OSL_TRACE( "Os2Surface createSurface for VIRDEV");
273*906a4e93SYuri Dario             //SystemGraphicsData aSysData = ((const VirtualDevice&) rRefDevice).GetSystemGfxData();
274*906a4e93SYuri Dario             //if (aSysData.hDC)
275*906a4e93SYuri Dario             //    surf = SurfaceSharedPtr(new Os2Surface((HDC) aSysData.hDC, x, y));
276*906a4e93SYuri Dario         }
277*906a4e93SYuri Dario         return surf;
278*906a4e93SYuri Dario     }
279*906a4e93SYuri Dario 
280*906a4e93SYuri Dario 
281*906a4e93SYuri Dario     /**
282*906a4e93SYuri Dario      * cairo::createBitmapSurface:   Create platform native Canvas surface from BitmapSystemData
283*906a4e93SYuri Dario      * @param OutputDevice (not used)
284*906a4e93SYuri Dario      * @param rData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx)
285*906a4e93SYuri Dario      * @param rSize width and height of the new surface
286*906a4e93SYuri Dario      *
287*906a4e93SYuri Dario      * Create a surface based on image data on rData
288*906a4e93SYuri Dario      *
289*906a4e93SYuri Dario      * @return new surface or empty surface
290*906a4e93SYuri Dario      **/
291*906a4e93SYuri Dario     SurfaceSharedPtr createBitmapSurface( const OutputDevice&     /* rRefDevice */,
292*906a4e93SYuri Dario                                           const BitmapSystemData& rData,
293*906a4e93SYuri Dario                                           const Size&             rSize )
294*906a4e93SYuri Dario     {
295*906a4e93SYuri Dario         OSL_TRACE( "createBitmapSurface requested size: %d x %d available size: %d x %d",
296*906a4e93SYuri Dario                    rSize.Width(), rSize.Height(), rData.mnWidth, rData.mnHeight );
297*906a4e93SYuri Dario 
298*906a4e93SYuri Dario         if ( rData.mnWidth == rSize.Width() && rData.mnHeight == rSize.Height() )
299*906a4e93SYuri Dario             return SurfaceSharedPtr(new Os2Surface( rData ));
300*906a4e93SYuri Dario         else
301*906a4e93SYuri Dario             return SurfaceSharedPtr();
302*906a4e93SYuri Dario     }
303*906a4e93SYuri Dario 
304*906a4e93SYuri Dario     typedef USHORT WCHAR;
305*906a4e93SYuri Dario     extern "C" ULONG APIENTRY Ft2GetGlyphIndices( HPS, WCHAR *, int, USHORT *, ULONG );
306*906a4e93SYuri Dario 
307*906a4e93SYuri Dario     /**
308*906a4e93SYuri Dario      * cairo::ucs4toindex: Convert ucs4 char to glyph index
309*906a4e93SYuri Dario      * @param ucs4 an ucs4 char
310*906a4e93SYuri Dario      * @param hfont current font
311*906a4e93SYuri Dario      *
312*906a4e93SYuri Dario      * @return true if successful
313*906a4e93SYuri Dario      **/
314*906a4e93SYuri Dario     unsigned long ucs4toindex(unsigned int ucs4, const char* font)
315*906a4e93SYuri Dario     {
316*906a4e93SYuri Dario         WCHAR unicode[2];
317*906a4e93SYuri Dario         USHORT glyph_index;
318*906a4e93SYuri Dario         HPS hps = NULL;
319*906a4e93SYuri Dario         FATTRS fontAttrs;
320*906a4e93SYuri Dario         APIRET rc;
321*906a4e93SYuri Dario 
322*906a4e93SYuri Dario         hps = WinGetPS( HWND_DESKTOP);
323*906a4e93SYuri Dario         if (!hps) return 0;
324*906a4e93SYuri Dario 
325*906a4e93SYuri Dario         memset( &fontAttrs, 0, sizeof( fontAttrs));
326*906a4e93SYuri Dario         fontAttrs.usRecordLength = sizeof( FATTRS);
327*906a4e93SYuri Dario         fontAttrs.usCodePage = 850;
328*906a4e93SYuri Dario         fontAttrs.fsType = FATTR_TYPE_MBCS;
329*906a4e93SYuri Dario         fontAttrs.fsFontUse = FATTR_FONTUSE_NOMIX;
330*906a4e93SYuri Dario         strcpy( fontAttrs.szFacename, font);
331*906a4e93SYuri Dario         rc = Ft2CreateLogFont( hps, NULL, 1L, &fontAttrs);
332*906a4e93SYuri Dario         rc = Ft2SetCharSet( hps, 1L);
333*906a4e93SYuri Dario 
334*906a4e93SYuri Dario         unicode[0] = ucs4;
335*906a4e93SYuri Dario         unicode[1] = 0;
336*906a4e93SYuri Dario         if (Ft2GetGlyphIndices( hps, unicode, 1, &glyph_index, 0) == -1) {
337*906a4e93SYuri Dario             glyph_index = 0;
338*906a4e93SYuri Dario         }
339*906a4e93SYuri Dario 
340*906a4e93SYuri Dario         WinReleasePS( hps);
341*906a4e93SYuri Dario 
342*906a4e93SYuri Dario         return glyph_index;
343*906a4e93SYuri Dario     }
344*906a4e93SYuri Dario 
345*906a4e93SYuri Dario 
346*906a4e93SYuri Dario }  // namespace cairo
347*906a4e93SYuri Dario 
348*906a4e93SYuri Dario #endif   // OS2
349