1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #if defined MACOSX || defined IOS
21 /************************************************************************
22 * Mac OS X/Quartz and iOS surface backend for OpenOffice.org Cairo Canvas *
23 ************************************************************************/
25 #include <osl/diagnose.h>
26 #include <vcl/sysdata.hxx>
27 #include <vcl/bitmap.hxx>
28 #include <vcl/virdev.hxx>
30 #include "cairo_cairo.hxx"
32 #if defined CAIRO_HAS_QUARTZ_SURFACE
34 #include "cairo_quartz_cairo.hxx"
38 bool IsCairoWorking( OutputDevice
* )
40 // trivially true for Mac
45 * QuartzSurface::Surface: Create generic Canvas surface using given Cairo Surface
47 * @param pSurface Cairo Surface
49 * This constructor only stores data, it does no processing.
50 * It is used with e.g. cairo_image_surface_create_for_data()
51 * and QuartzSurface::getSimilar()
53 * Set the mpSurface to the new surface or NULL
55 QuartzSurface::QuartzSurface( const CairoSurfaceSharedPtr
& pSurface
) :
59 // Necessary, context is lost otherwise
60 CGContextRetain( getCGContext() ); // == NULL for non-native surfaces
64 * QuartzSurface::Surface: Create Canvas surface from Window reference.
66 * @param x horizontal location of the new surface
67 * @param y vertical location of the new surface
68 * @param width width of the new surface
69 * @param height height of the new surface
71 * pSysData contains the platform native Window reference.
72 * pSysData is used to create a surface on the Window
74 * Set the mpSurface to the new surface or NULL
76 QuartzSurface::QuartzSurface( NSView
* pView
, int x
, int y
, int width
, int height
) :
80 OSL_TRACE("Canvas::cairo::Surface(NSView*, x:%d, y:%d, w:%d, h:%d): New Surface for window", x
, y
, width
, height
);
82 // on Mac OS X / Quartz we are not drawing directly to the screen, but via regular CGContextRef.
83 // The actual drawing to NSView (i.e. screen) is done in QuartzSurface::flush()
85 // HACK: currently initial size for windowsurface is 0x0, which is not possible for us.
86 if (width
== 0 || height
== 0) {
87 width
= [mpView bounds
].size
.width
;
88 height
= [mpView bounds
].size
.height
;
89 OSL_TRACE("Canvas::cairo::Surface(): BUG!! size is ZERO! fixing to %d x %d...", width
, height
);
92 // create a generic surface, NSView/Window is ARGB32.
94 cairo_quartz_surface_create(CAIRO_FORMAT_ARGB32
, width
, height
),
95 &cairo_surface_destroy
);
97 cairo_surface_set_device_offset( mpSurface
.get(), x
, y
);
101 * QuartzSurface::Surface: Create Canvas surface from CGContextRef.
102 * @param CGContext Native graphics context
103 * @param x horizontal location of the new surface
104 * @param y vertical location of the new surface
105 * @param width width of the new surface
106 * @param height height of the new surface
108 * Set the mpSurface to the new surface or NULL
110 QuartzSurface::QuartzSurface( CGContextRef rContext
, int x
, int y
, int width
, int height
) :
114 OSL_TRACE("Canvas::cairo::Surface(CGContext:%p, x:%d, y:%d, w:%d, h:%d): New Surface.", rContext
, x
, y
, width
, height
);
115 // create surface based on CGContext
117 // ensure kCGBitmapByteOrder32Host flag, otherwise Cairo breaks (we are practically always using CGBitmapContext)
118 OSL_ASSERT ((CGBitmapContextGetBitsPerPixel(rContext
) != 32) ||
119 (CGBitmapContextGetBitmapInfo(rContext
) & kCGBitmapByteOrderMask
) == kCGBitmapByteOrder32Host
);
121 mpSurface
.reset(cairo_quartz_surface_create_for_cg_context(rContext
, width
, height
),
122 &cairo_surface_destroy
);
124 cairo_surface_set_device_offset( mpSurface
.get(), x
, y
);
126 // Necessary, context is lost otherwise
127 CGContextRetain(rContext
);
132 * QuartzSurface::getCairo: Create Cairo (drawing object) for the Canvas surface
134 * @return new Cairo or NULL
136 CairoSharedPtr
QuartzSurface::getCairo() const
140 return CairoSharedPtr( cairo_create(mpSurface
.get()),
145 return CairoSharedPtr();
150 * QuartzSurface::getSimilar: Create new similar Canvas surface
151 * @param aContent format of the new surface (cairo_content_t from cairo/src/cairo.h)
152 * @param width width of the new surface
153 * @param height height of the new surface
155 * Creates a new Canvas surface. This normally creates platform native surface, even though
156 * generic function is used.
158 * Cairo surface from aContent (cairo_content_t)
160 * @return new surface or NULL
162 SurfaceSharedPtr
QuartzSurface::getSimilar( Content aContent
, int width
, int height
) const
164 return SurfaceSharedPtr(
166 CairoSurfaceSharedPtr(
167 cairo_surface_create_similar( mpSurface
.get(), aContent
, width
, height
),
168 &cairo_surface_destroy
)));
172 * QuartzSurface::Resize: Resizes the Canvas surface.
173 * @param width new width of the surface
174 * @param height new height of the surface
178 * @return The new surface or NULL
180 void QuartzSurface::Resize( int /* width */, int /* height */ )
182 OSL_FAIL("not supposed to be called!");
187 * QuartzSurface::flush: Draw the data to screen
189 void QuartzSurface::flush() const
191 // can only flush surfaces with NSView
195 OSL_TRACE("Canvas::cairo::QuartzSurface::flush(): flush to NSView");
197 CGContextRef mrContext
= getCGContext();
207 * This code is using same screen update code as in VCL (esp. AquaSalGraphics::UpdateWindow() )
209 CGContextRef rViewContext
= reinterpret_cast<CGContextRef
>([[NSGraphicsContext currentContext
] graphicsPort
]);
211 // Just guessing for now...
212 CGContextRef rViewContext
= UIGraphicsGetCurrentContext();
214 CGImageRef xImage
= CGBitmapContextCreateImage(mrContext
);
215 CGContextDrawImage(rViewContext
,
217 CGImageGetWidth(xImage
),
218 CGImageGetHeight(xImage
)),
220 CGImageRelease( xImage
);
221 CGContextFlush( rViewContext
);
223 [mpView unlockFocus
];
228 * QuartzSurface::getDepth: Get the color depth of the Canvas surface.
230 * @return color depth
232 int QuartzSurface::getDepth() const
236 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
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */