1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cairo_quartz_cairo.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_canvas.hxx"
35 /************************************************************************
36 * Mac OS X/Quartz surface backend for OpenOffice.org Cairo Canvas *
37 ************************************************************************/
39 #include <osl/diagnose.h>
40 #include <vcl/sysdata.hxx>
41 #include <vcl/bitmap.hxx>
42 #include <vcl/virdev.hxx>
44 #include "cairo_cairo.hxx"
46 #if defined CAIRO_HAS_QUARTZ_SURFACE
48 #include "cairo_quartz_cairo.hxx"
52 bool IsCairoWorking( OutputDevice
* )
54 // trivially true for Mac
59 * QuartzSurface::Surface: Create generic Canvas surface using given Cairo Surface
61 * @param pSurface Cairo Surface
63 * This constructor only stores data, it does no processing.
64 * It is used with e.g. cairo_image_surface_create_for_data()
65 * and QuartzSurface::getSimilar()
67 * Set the mpSurface to the new surface or NULL
69 QuartzSurface::QuartzSurface( const CairoSurfaceSharedPtr
& pSurface
) :
73 // Necessary, context is lost otherwise
74 CGContextRetain( getCGContext() ); // == NULL for non-native surfaces
78 * QuartzSurface::Surface: Create Canvas surface from Window reference.
80 * @param x horizontal location of the new surface
81 * @param y vertical location of the new surface
82 * @param width width of the new surface
83 * @param height height of the new surface
85 * pSysData contains the platform native Window reference.
86 * pSysData is used to create a surface on the Window
88 * Set the mpSurface to the new surface or NULL
90 QuartzSurface::QuartzSurface( NSView
* pView
, int x
, int y
, int width
, int height
) :
94 OSL_TRACE("Canvas::cairo::Surface(NSView*, x:%d, y:%d, w:%d, h:%d): New Surface for window", x
, y
, width
, height
);
96 // on Mac OS X / Quartz we are not drawing directly to the screen, but via regular CGContextRef.
97 // The actual drawing to NSView (i.e. screen) is done in QuartzSurface::flush()
99 // HACK: currently initial size for windowsurface is 0x0, which is not possible for us.
100 if (width
== 0 || height
== 0) {
101 width
= [mpView bounds
].size
.width
;
102 height
= [mpView bounds
].size
.height
;
103 OSL_TRACE("Canvas::cairo::Surface(): BUG!! size is ZERO! fixing to %d x %d...", width
, height
);
106 // create a generic surface, NSView/Window is ARGB32.
108 cairo_quartz_surface_create(CAIRO_FORMAT_ARGB32
, width
, height
),
109 &cairo_surface_destroy
);
111 cairo_surface_set_device_offset( mpSurface
.get(), x
, y
);
115 * QuartzSurface::Surface: Create Canvas surface from CGContextRef.
116 * @param CGContext Native graphics context
117 * @param x horizontal location of the new surface
118 * @param y vertical location of the new surface
119 * @param width width of the new surface
120 * @param height height of the new surface
122 * Set the mpSurface to the new surface or NULL
124 QuartzSurface::QuartzSurface( CGContextRef rContext
, int x
, int y
, int width
, int height
) :
128 OSL_TRACE("Canvas::cairo::Surface(CGContext:%p, x:%d, y:%d, w:%d, h:%d): New Surface.", rContext
, x
, y
, width
, height
);
129 // create surface based on CGContext
131 // ensure kCGBitmapByteOrder32Host flag, otherwise Cairo breaks (we are practically always using CGBitmapContext)
132 OSL_ASSERT ((CGBitmapContextGetBitsPerPixel(rContext
) != 32) ||
133 (CGBitmapContextGetBitmapInfo(rContext
) & kCGBitmapByteOrderMask
) == kCGBitmapByteOrder32Host
);
135 mpSurface
.reset(cairo_quartz_surface_create_for_cg_context(rContext
, width
, height
),
136 &cairo_surface_destroy
);
138 cairo_surface_set_device_offset( mpSurface
.get(), x
, y
);
140 // Necessary, context is lost otherwise
141 CGContextRetain(rContext
);
146 * QuartzSurface::getCairo: Create Cairo (drawing object) for the Canvas surface
148 * @return new Cairo or NULL
150 CairoSharedPtr
QuartzSurface::getCairo() const
152 if (mpSurface
.get()){
153 return CairoSharedPtr( cairo_create(mpSurface
.get()),
156 return CairoSharedPtr();
161 * QuartzSurface::getSimilar: Create new similar Canvas surface
162 * @param aContent format of the new surface (cairo_content_t from cairo/src/cairo.h)
163 * @param width width of the new surface
164 * @param height height of the new surface
166 * Creates a new Canvas surface. This normally creates platform native surface, even though
167 * generic function is used.
169 * Cairo surface from aContent (cairo_content_t)
171 * @return new surface or NULL
173 SurfaceSharedPtr
QuartzSurface::getSimilar( Content aContent
, int width
, int height
) const
175 return SurfaceSharedPtr(
177 CairoSurfaceSharedPtr(
178 cairo_surface_create_similar( mpSurface
.get(), aContent
, width
, height
),
179 &cairo_surface_destroy
)));
183 * QuartzSurface::Resize: Resizes the Canvas surface.
184 * @param width new width of the surface
185 * @param height new height of the surface
189 * @return The new surface or NULL
191 void QuartzSurface::Resize( int width
, int height
)
193 OSL_ENSURE(false,"not supposed to be called!");
198 * QuartzSurface::flush: Draw the data to screen
200 void QuartzSurface::flush() const
202 // can only flush surfaces with NSView
203 if( !mpView
) return;
205 OSL_TRACE("Canvas::cairo::QuartzSurface::flush(): flush to NSView");
207 CGContextRef mrContext
= getCGContext();
209 if (!mrContext
) return;
214 * This code is using same screen update code as in VCL (esp. AquaSalGraphics::UpdateWindow() )
216 CGContextRef rViewContext
= reinterpret_cast<CGContextRef
>([[NSGraphicsContext currentContext
] graphicsPort
]);
217 CGImageRef xImage
= CGBitmapContextCreateImage(mrContext
);
218 CGContextDrawImage(rViewContext
,
220 CGImageGetWidth(xImage
),
221 CGImageGetHeight(xImage
)),
223 CGImageRelease( xImage
);
224 CGContextFlush( rViewContext
);
226 [mpView unlockFocus
];
230 * QuartzSurface::getDepth: Get the color depth of the Canvas surface.
232 * @return color depth
234 int QuartzSurface::getDepth() const
236 if (mpSurface
.get()) {
237 switch (cairo_surface_get_content (mpSurface
.get())) {
238 case CAIRO_CONTENT_ALPHA
: return 8; break;
239 case CAIRO_CONTENT_COLOR
: return 24; break;
240 case CAIRO_CONTENT_COLOR_ALPHA
: return 32; break;
243 OSL_TRACE("Canvas::cairo::QuartzSurface::getDepth(): ERROR - depth unspecified!");
249 * QuartzSurface::getCGContext: Get the native CGContextRef of the Canvas's cairo surface
251 * @return graphics context
253 CGContextRef
QuartzSurface::getCGContext() const
256 return cairo_quartz_surface_get_cg_context(mpSurface
.get());
262 * cairo::createVirtualDevice: Create a VCL virtual device for the CGContext in the cairo Surface
264 * @return The new virtual device
266 boost::shared_ptr
<VirtualDevice
> QuartzSurface::createVirtualDevice() const
268 SystemGraphicsData aSystemGraphicsData
;
269 aSystemGraphicsData
.nSize
= sizeof(SystemGraphicsData
);
270 aSystemGraphicsData
.rCGContext
= getCGContext();
271 return boost::shared_ptr
<VirtualDevice
>(
272 new VirtualDevice( &aSystemGraphicsData
, getDepth() ));
276 * cairo::createSurface: Create generic Canvas surface using given Cairo Surface
278 * @param rSurface Cairo Surface
280 * @return new Surface
282 SurfaceSharedPtr
createSurface( const CairoSurfaceSharedPtr
& rSurface
)
284 return SurfaceSharedPtr(new QuartzSurface(rSurface
));
288 * cairo::createSurface: Create Canvas surface using given VCL Window or Virtualdevice
290 * @param rSurface Cairo Surface
292 * For VCL Window, use platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx)
293 * For VCL Virtualdevice, use platform native system graphics data (struct SystemGraphicsData in vcl/inc/sysdata.hxx)
295 * @return new Surface
297 SurfaceSharedPtr
createSurface( const OutputDevice
& rRefDevice
,
298 int x
, int y
, int width
, int height
)
300 SurfaceSharedPtr surf
;
302 if( rRefDevice
.GetOutDevType() == OUTDEV_WINDOW
)
304 const Window
&rWindow
= (const Window
&) rRefDevice
;
305 const SystemEnvData
* pSysData
= GetSysData(&rWindow
);
307 surf
= SurfaceSharedPtr(new QuartzSurface(pSysData
->pView
, x
, y
, width
, height
));
309 else if( rRefDevice
.GetOutDevType() == OUTDEV_VIRDEV
)
311 SystemGraphicsData aSysData
= ((const VirtualDevice
&) rRefDevice
).GetSystemGfxData();
313 if (aSysData
.rCGContext
)
314 surf
= SurfaceSharedPtr(new QuartzSurface(aSysData
.rCGContext
, x
, y
, width
, height
));
320 * cairo::createBitmapSurface: Create platfrom native Canvas surface from BitmapSystemData
321 * @param OutputDevice (not used)
322 * @param rData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx)
323 * @param rSize width and height of the new surface
325 * Create a surface based on image data on rData
327 * @return new surface or empty surface
329 SurfaceSharedPtr
createBitmapSurface( const OutputDevice
& /* rRefDevice */,
330 const BitmapSystemData
& rData
,
333 OSL_TRACE( "requested size: %d x %d available size: %d x %d",
334 rSize
.Width(), rSize
.Height(), rData
.mnWidth
, rData
.mnHeight
);
336 if ( rData
.mnWidth
== rSize
.Width() && rData
.mnHeight
== rSize
.Height() )
338 CGContextRef rContext
= (CGContextRef
)rData
.rImageContext
;
339 OSL_TRACE("Canvas::cairo::createBitmapSurface(): New native image surface, context = %p.", rData
.rImageContext
);
341 return SurfaceSharedPtr(new QuartzSurface(rContext
, 0, 0, rData
.mnWidth
, rData
.mnHeight
));
343 return SurfaceSharedPtr();
348 #endif // CAIRO_HAS_QUARTZ_SURFACE