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