1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_canvas.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #ifdef WNT
32*cdf0e10cSrcweir /************************************************************************
33*cdf0e10cSrcweir  * Win32 surface backend for OpenOffice.org Cairo Canvas                *
34*cdf0e10cSrcweir  ************************************************************************/
35*cdf0e10cSrcweir 
36*cdf0e10cSrcweir #include <tools/prewin.h>
37*cdf0e10cSrcweir #include <windows.h>
38*cdf0e10cSrcweir #include <tools/postwin.h>
39*cdf0e10cSrcweir 
40*cdf0e10cSrcweir #include <osl/diagnose.h>
41*cdf0e10cSrcweir #include <vcl/bitmap.hxx>
42*cdf0e10cSrcweir #include <vcl/virdev.hxx>
43*cdf0e10cSrcweir #include <vcl/sysdata.hxx>
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir #include "cairo_win32_cairo.hxx"
46*cdf0e10cSrcweir 
47*cdf0e10cSrcweir #ifdef CAIRO_HAS_WIN32_SURFACE
48*cdf0e10cSrcweir 
49*cdf0e10cSrcweir namespace cairo
50*cdf0e10cSrcweir {
51*cdf0e10cSrcweir 
52*cdf0e10cSrcweir #include <cairo-win32.h>
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir     bool IsCairoWorking( OutputDevice* )
55*cdf0e10cSrcweir     {
56*cdf0e10cSrcweir         // trivially true for Windows
57*cdf0e10cSrcweir         return true;
58*cdf0e10cSrcweir     }
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir     /**
61*cdf0e10cSrcweir      * Surface::Surface:     Create generic Canvas surface using given Cairo Surface
62*cdf0e10cSrcweir      *
63*cdf0e10cSrcweir      * @param pSurface Cairo Surface
64*cdf0e10cSrcweir      *
65*cdf0e10cSrcweir      * This constructor only stores data, it does no processing.
66*cdf0e10cSrcweir      * It is used with e.g. cairo_image_surface_create_for_data()
67*cdf0e10cSrcweir      * and Surface::getSimilar()
68*cdf0e10cSrcweir      *
69*cdf0e10cSrcweir      * Set the mpSurface to the new surface or NULL
70*cdf0e10cSrcweir      **/
71*cdf0e10cSrcweir     Win32Surface::Win32Surface( const CairoSurfaceSharedPtr& pSurface ) :
72*cdf0e10cSrcweir         mpSurface( pSurface )
73*cdf0e10cSrcweir     {}
74*cdf0e10cSrcweir 
75*cdf0e10cSrcweir     /**
76*cdf0e10cSrcweir      * Surface::Surface:   Create Canvas surface from Window reference.
77*cdf0e10cSrcweir      * @param pSysData Platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx)
78*cdf0e10cSrcweir      * @param x horizontal location of the new surface
79*cdf0e10cSrcweir      * @param y vertical location of the new surface
80*cdf0e10cSrcweir      *
81*cdf0e10cSrcweir      * pSysData contains the platform native Window reference.
82*cdf0e10cSrcweir      * pSysData is used to create a surface on the Window
83*cdf0e10cSrcweir      *
84*cdf0e10cSrcweir      * Set the mpSurface to the new surface or NULL
85*cdf0e10cSrcweir      **/
86*cdf0e10cSrcweir     Win32Surface::Win32Surface( HDC hDC, int x, int y) :
87*cdf0e10cSrcweir         mpSurface(
88*cdf0e10cSrcweir             cairo_win32_surface_create(hDC),
89*cdf0e10cSrcweir             &cairo_surface_destroy)
90*cdf0e10cSrcweir     {
91*cdf0e10cSrcweir         cairo_surface_set_device_offset( mpSurface.get(), x, y );
92*cdf0e10cSrcweir 	}
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir     /**
95*cdf0e10cSrcweir      * Surface::Surface:   Create platfrom native Canvas surface from BitmapSystemData
96*cdf0e10cSrcweir      * @param pBmpData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx)
97*cdf0e10cSrcweir      *
98*cdf0e10cSrcweir      * Create a surface based on image data on pBmpData
99*cdf0e10cSrcweir      *
100*cdf0e10cSrcweir      * Set the mpSurface to the new surface or NULL
101*cdf0e10cSrcweir      **/
102*cdf0e10cSrcweir     Win32Surface::Win32Surface( const BitmapSystemData& rBmpData ) :
103*cdf0e10cSrcweir         mpSurface()
104*cdf0e10cSrcweir 	{
105*cdf0e10cSrcweir         OSL_ASSERT(rBmpData.pDIB == NULL);
106*cdf0e10cSrcweir 
107*cdf0e10cSrcweir         if(rBmpData.pDIB != NULL) {
108*cdf0e10cSrcweir             // So just leave mpSurface to NULL, little else we can do at
109*cdf0e10cSrcweir             // this stage. Hopefully the Win32 patch to
110*cdf0e10cSrcweir             // cairocanvas::DeviceHelper::getSurface(BitmapSystemData&,
111*cdf0e10cSrcweir             // const Size&) will catch the cases where this
112*cdf0e10cSrcweir             // constructor would be called with a DIB bitmap, and we
113*cdf0e10cSrcweir             // will never get here. At least it worked for Ballmer.ppt.
114*cdf0e10cSrcweir         }
115*cdf0e10cSrcweir         else
116*cdf0e10cSrcweir         {
117*cdf0e10cSrcweir             HDC hDC = CreateCompatibleDC(NULL);
118*cdf0e10cSrcweir             void* hOrigBitmap;
119*cdf0e10cSrcweir             OSL_TRACE ("Surface::Surface(): Selecting bitmap %p into DC %p", rBmpData.pDDB, hDC);
120*cdf0e10cSrcweir             hOrigBitmap = SelectObject( hDC, (HANDLE)rBmpData.pDDB );
121*cdf0e10cSrcweir             if(hOrigBitmap == NULL)
122*cdf0e10cSrcweir                 OSL_TRACE ("SelectObject failed: %d", GetLastError ());
123*cdf0e10cSrcweir             mpSurface.reset(
124*cdf0e10cSrcweir                 cairo_win32_surface_create(hDC),
125*cdf0e10cSrcweir                 &cairo_surface_destroy);
126*cdf0e10cSrcweir         }
127*cdf0e10cSrcweir 	}
128*cdf0e10cSrcweir 
129*cdf0e10cSrcweir     /**
130*cdf0e10cSrcweir      * Surface::getCairo:  Create Cairo (drawing object) for the Canvas surface
131*cdf0e10cSrcweir      *
132*cdf0e10cSrcweir      * @return new Cairo or NULL
133*cdf0e10cSrcweir      **/
134*cdf0e10cSrcweir 	CairoSharedPtr Win32Surface::getCairo() const
135*cdf0e10cSrcweir     {
136*cdf0e10cSrcweir         return CairoSharedPtr( cairo_create(mpSurface.get()),
137*cdf0e10cSrcweir                                &cairo_destroy );
138*cdf0e10cSrcweir     }
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir     /**
141*cdf0e10cSrcweir      * Surface::getSimilar:  Create new similar Canvas surface
142*cdf0e10cSrcweir      * @param aContent format of the new surface (cairo_content_t from cairo/src/cairo.h)
143*cdf0e10cSrcweir      * @param width width of the new surface
144*cdf0e10cSrcweir      * @param height height of the new surface
145*cdf0e10cSrcweir      *
146*cdf0e10cSrcweir      * Creates a new Canvas surface. This normally creates platform native surface, even though
147*cdf0e10cSrcweir      * generic function is used.
148*cdf0e10cSrcweir      *
149*cdf0e10cSrcweir      * Cairo surface from aContent (cairo_content_t)
150*cdf0e10cSrcweir      *
151*cdf0e10cSrcweir      * @return new surface or NULL
152*cdf0e10cSrcweir      **/
153*cdf0e10cSrcweir 	SurfaceSharedPtr Win32Surface::getSimilar( Content aContent, int width, int height ) const
154*cdf0e10cSrcweir 	{
155*cdf0e10cSrcweir         return SurfaceSharedPtr(
156*cdf0e10cSrcweir             new Win32Surface(
157*cdf0e10cSrcweir                 CairoSurfaceSharedPtr(
158*cdf0e10cSrcweir                     cairo_surface_create_similar( mpSurface.get(), aContent, width, height ),
159*cdf0e10cSrcweir                     &cairo_surface_destroy )));
160*cdf0e10cSrcweir 	}
161*cdf0e10cSrcweir 
162*cdf0e10cSrcweir     /**
163*cdf0e10cSrcweir      * Surface::Resize:  Resizes the Canvas surface.
164*cdf0e10cSrcweir      * @param width new width of the surface
165*cdf0e10cSrcweir      * @param height new height of the surface
166*cdf0e10cSrcweir      *
167*cdf0e10cSrcweir      * Only used on X11.
168*cdf0e10cSrcweir      *
169*cdf0e10cSrcweir      * @return The new surface or NULL
170*cdf0e10cSrcweir      **/
171*cdf0e10cSrcweir 	void Win32Surface::Resize( int /*width*/, int /*height*/ )
172*cdf0e10cSrcweir 	{
173*cdf0e10cSrcweir         OSL_ENSURE(false,"not supposed to be called!");
174*cdf0e10cSrcweir 	}
175*cdf0e10cSrcweir 
176*cdf0e10cSrcweir     void Win32Surface::flush() const
177*cdf0e10cSrcweir     {
178*cdf0e10cSrcweir         GdiFlush();
179*cdf0e10cSrcweir     }
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir     /**
182*cdf0e10cSrcweir      * Surface::getDepth:  Get the color depth of the Canvas surface.
183*cdf0e10cSrcweir      *
184*cdf0e10cSrcweir      * @return color depth
185*cdf0e10cSrcweir      **/
186*cdf0e10cSrcweir 	int Win32Surface::getDepth() const
187*cdf0e10cSrcweir 	{
188*cdf0e10cSrcweir         if (mpSurface) {
189*cdf0e10cSrcweir             switch (cairo_surface_get_content (mpSurface.get())) {
190*cdf0e10cSrcweir                 case CAIRO_CONTENT_ALPHA:       return 8;  break;
191*cdf0e10cSrcweir                 case CAIRO_CONTENT_COLOR:       return 24; break;
192*cdf0e10cSrcweir                 case CAIRO_CONTENT_COLOR_ALPHA: return 32; break;
193*cdf0e10cSrcweir             }
194*cdf0e10cSrcweir         }
195*cdf0e10cSrcweir         OSL_TRACE("Canvas::cairo::Surface::getDepth(): ERROR - depth unspecified!");
196*cdf0e10cSrcweir 		return -1;
197*cdf0e10cSrcweir 	}
198*cdf0e10cSrcweir 
199*cdf0e10cSrcweir 
200*cdf0e10cSrcweir     /**
201*cdf0e10cSrcweir      * cairo::createVirtualDevice:  Create a VCL virtual device for the CGContext in the cairo Surface
202*cdf0e10cSrcweir      *
203*cdf0e10cSrcweir      * @return The new virtual device
204*cdf0e10cSrcweir      **/
205*cdf0e10cSrcweir     boost::shared_ptr<VirtualDevice> Win32Surface::createVirtualDevice() const
206*cdf0e10cSrcweir     {
207*cdf0e10cSrcweir 		SystemGraphicsData aSystemGraphicsData;
208*cdf0e10cSrcweir 		aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
209*cdf0e10cSrcweir         aSystemGraphicsData.hDC = cairo_win32_surface_get_dc( mpSurface.get() );
210*cdf0e10cSrcweir 
211*cdf0e10cSrcweir 		return boost::shared_ptr<VirtualDevice>(
212*cdf0e10cSrcweir             new VirtualDevice( &aSystemGraphicsData, sal::static_int_cast<USHORT>(getDepth()) ));
213*cdf0e10cSrcweir     }
214*cdf0e10cSrcweir 
215*cdf0e10cSrcweir 
216*cdf0e10cSrcweir     /**
217*cdf0e10cSrcweir      * cairo::createSurface:     Create generic Canvas surface using given Cairo Surface
218*cdf0e10cSrcweir      *
219*cdf0e10cSrcweir      * @param rSurface Cairo Surface
220*cdf0e10cSrcweir      *
221*cdf0e10cSrcweir      * @return new Surface
222*cdf0e10cSrcweir      */
223*cdf0e10cSrcweir     SurfaceSharedPtr createSurface( const CairoSurfaceSharedPtr& rSurface )
224*cdf0e10cSrcweir     {
225*cdf0e10cSrcweir         return SurfaceSharedPtr(new Win32Surface(rSurface));
226*cdf0e10cSrcweir     }
227*cdf0e10cSrcweir 
228*cdf0e10cSrcweir 
229*cdf0e10cSrcweir     /**
230*cdf0e10cSrcweir      * cairo::createSurface:     Create Canvas surface using given VCL Window or Virtualdevice
231*cdf0e10cSrcweir      *
232*cdf0e10cSrcweir      * @param rSurface Cairo Surface
233*cdf0e10cSrcweir      *
234*cdf0e10cSrcweir      *  For VCL Window, use platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx)
235*cdf0e10cSrcweir      *  For VCL Virtualdevice, use platform native system graphics data (struct SystemGraphicsData in vcl/inc/sysdata.hxx)
236*cdf0e10cSrcweir      *
237*cdf0e10cSrcweir      * @return new Surface
238*cdf0e10cSrcweir      */
239*cdf0e10cSrcweir     SurfaceSharedPtr createSurface( const OutputDevice& rRefDevice,
240*cdf0e10cSrcweir                                     int x, int y, int /* width */, int /* height */)
241*cdf0e10cSrcweir     {
242*cdf0e10cSrcweir         SurfaceSharedPtr surf;
243*cdf0e10cSrcweir 
244*cdf0e10cSrcweir         if( rRefDevice.GetOutDevType() == OUTDEV_WINDOW )
245*cdf0e10cSrcweir         {
246*cdf0e10cSrcweir             const Window &rWindow = (const Window &) rRefDevice;
247*cdf0e10cSrcweir             const SystemEnvData* pSysData = GetSysData(&rWindow);
248*cdf0e10cSrcweir             if (pSysData && pSysData->hWnd)
249*cdf0e10cSrcweir                 surf = SurfaceSharedPtr(new Win32Surface(GetDC((HWND) pSysData->hWnd), x, y));
250*cdf0e10cSrcweir         }
251*cdf0e10cSrcweir         else if( rRefDevice.GetOutDevType() == OUTDEV_VIRDEV )
252*cdf0e10cSrcweir         {
253*cdf0e10cSrcweir             SystemGraphicsData aSysData = ((const VirtualDevice&) rRefDevice).GetSystemGfxData();
254*cdf0e10cSrcweir             if (aSysData.hDC)
255*cdf0e10cSrcweir                 surf = SurfaceSharedPtr(new Win32Surface((HDC) aSysData.hDC, x, y));
256*cdf0e10cSrcweir         }
257*cdf0e10cSrcweir         return surf;
258*cdf0e10cSrcweir     }
259*cdf0e10cSrcweir 
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir     /**
262*cdf0e10cSrcweir      * cairo::createBitmapSurface:   Create platfrom native Canvas surface from BitmapSystemData
263*cdf0e10cSrcweir      * @param OutputDevice (not used)
264*cdf0e10cSrcweir      * @param rData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx)
265*cdf0e10cSrcweir      * @param rSize width and height of the new surface
266*cdf0e10cSrcweir      *
267*cdf0e10cSrcweir      * Create a surface based on image data on rData
268*cdf0e10cSrcweir      *
269*cdf0e10cSrcweir      * @return new surface or empty surface
270*cdf0e10cSrcweir      **/
271*cdf0e10cSrcweir     SurfaceSharedPtr createBitmapSurface( const OutputDevice&     /* rRefDevice */,
272*cdf0e10cSrcweir                                           const BitmapSystemData& rData,
273*cdf0e10cSrcweir                                           const Size&             rSize )
274*cdf0e10cSrcweir     {
275*cdf0e10cSrcweir         OSL_TRACE( "requested size: %d x %d available size: %d x %d",
276*cdf0e10cSrcweir                    rSize.Width(), rSize.Height(), rData.mnWidth, rData.mnHeight );
277*cdf0e10cSrcweir 
278*cdf0e10cSrcweir         if ( rData.mnWidth == rSize.Width() && rData.mnHeight == rSize.Height() )
279*cdf0e10cSrcweir             return SurfaceSharedPtr(new Win32Surface( rData ));
280*cdf0e10cSrcweir         else
281*cdf0e10cSrcweir             return SurfaceSharedPtr();
282*cdf0e10cSrcweir     }
283*cdf0e10cSrcweir 
284*cdf0e10cSrcweir 
285*cdf0e10cSrcweir     /**
286*cdf0e10cSrcweir      * cairo::ucs4toindex: Convert ucs4 char to glyph index
287*cdf0e10cSrcweir      * @param ucs4 an ucs4 char
288*cdf0e10cSrcweir      * @param hfont current font
289*cdf0e10cSrcweir      *
290*cdf0e10cSrcweir      * @return true if successful
291*cdf0e10cSrcweir      **/
292*cdf0e10cSrcweir     unsigned long ucs4toindex(unsigned int ucs4, HFONT hfont)
293*cdf0e10cSrcweir     {
294*cdf0e10cSrcweir         wchar_t unicode[2];
295*cdf0e10cSrcweir         WORD glyph_index;
296*cdf0e10cSrcweir         HDC hdc = NULL;
297*cdf0e10cSrcweir         int i = 0;
298*cdf0e10cSrcweir 
299*cdf0e10cSrcweir         hdc = CreateCompatibleDC (NULL);
300*cdf0e10cSrcweir 
301*cdf0e10cSrcweir         if (!hdc) return 0;
302*cdf0e10cSrcweir         if (!SetGraphicsMode (hdc, GM_ADVANCED)) {
303*cdf0e10cSrcweir             DeleteDC (hdc);
304*cdf0e10cSrcweir             return 0;
305*cdf0e10cSrcweir         }
306*cdf0e10cSrcweir 
307*cdf0e10cSrcweir         SelectObject (hdc, hfont);
308*cdf0e10cSrcweir         SetMapMode (hdc, MM_TEXT);
309*cdf0e10cSrcweir 
310*cdf0e10cSrcweir         unicode[0] = ucs4;
311*cdf0e10cSrcweir         unicode[1] = 0;
312*cdf0e10cSrcweir         if (GetGlyphIndicesW (hdc, unicode, 1, &glyph_index, 0) == GDI_ERROR) {
313*cdf0e10cSrcweir             glyph_index = 0;
314*cdf0e10cSrcweir         }
315*cdf0e10cSrcweir 
316*cdf0e10cSrcweir         DeleteDC (hdc);
317*cdf0e10cSrcweir         return glyph_index;
318*cdf0e10cSrcweir 	}
319*cdf0e10cSrcweir 
320*cdf0e10cSrcweir 
321*cdf0e10cSrcweir }  // namespace cairo
322*cdf0e10cSrcweir 
323*cdf0e10cSrcweir #endif   // CAIRO_HAS_WIN32_SURFACE
324*cdf0e10cSrcweir 
325*cdf0e10cSrcweir #endif   // WNT
326