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 #include <config_cairo_canvas.h>
22 #if ENABLE_CAIRO_CANVAS
23 /************************************************************************
24 * Mac OS X/Quartz and iOS surface backend for LibreOffice Cairo Canvas *
25 ************************************************************************/
27 #include <osl/diagnose.h>
28 #include <vcl/sysdata.hxx>
29 #include <vcl/bitmap.hxx>
30 #include <vcl/virdev.hxx>
32 #include "cairo_cairo.hxx"
34 #include <config_cairo_canvas.h>
36 #include "cairo_quartz_cairo.hxx"
41 * QuartzSurface::Surface: Create generic Canvas surface using given Cairo Surface
43 * @param pSurface Cairo Surface
45 * This constructor only stores data, it does no processing.
46 * It is used with e.g. cairo_image_surface_create_for_data()
47 * and QuartzSurface::getSimilar()
49 * Set the mpSurface to the new surface or NULL
51 QuartzSurface::QuartzSurface( const CairoSurfaceSharedPtr
& pSurface
) :
55 // Necessary, context is lost otherwise
56 CGContextRetain( getCGContext() ); // == NULL for non-native surfaces
60 * QuartzSurface::Surface: Create Canvas surface from Window reference.
62 * @param x horizontal location of the new surface
63 * @param y vertical location of the new surface
64 * @param width width of the new surface
65 * @param height height of the new surface
67 * pSysData contains the platform native Window reference.
68 * pSysData is used to create a surface on the Window
70 * Set the mpSurface to the new surface or NULL
72 QuartzSurface::QuartzSurface( NSView
* pView
, int x
, int y
, int width
, int height
) :
76 OSL_TRACE("Canvas::cairo::Surface(NSView*, x:%d, y:%d, w:%d, h:%d): New Surface for window", x
, y
, width
, height
);
78 // on Mac OS X / Quartz we are not drawing directly to the screen, but via regular CGContextRef.
79 // The actual drawing to NSView (i.e. screen) is done in QuartzSurface::flush()
81 // HACK: currently initial size for windowsurface is 0x0, which is not possible for us.
82 if (width
== 0 || height
== 0) {
83 width
= [mpView bounds
].size
.width
;
84 height
= [mpView bounds
].size
.height
;
85 OSL_TRACE("Canvas::cairo::Surface(): BUG!! size is ZERO! fixing to %d x %d...", width
, height
);
88 // create a generic surface, NSView/Window is ARGB32.
90 cairo_quartz_surface_create(CAIRO_FORMAT_ARGB32
, width
, height
),
91 &cairo_surface_destroy
);
93 cairo_surface_set_device_offset( mpSurface
.get(), x
, y
);
97 * QuartzSurface::Surface: Create Canvas surface from CGContextRef.
98 * @param CGContext Native graphics context
99 * @param x horizontal location of the new surface
100 * @param y vertical location of the new surface
101 * @param width width of the new surface
102 * @param height height of the new surface
104 * Set the mpSurface to the new surface or NULL
106 QuartzSurface::QuartzSurface( CGContextRef rContext
, int x
, int y
, int width
, int height
) :
110 OSL_TRACE("Canvas::cairo::Surface(CGContext:%p, x:%d, y:%d, w:%d, h:%d): New Surface.", rContext
, x
, y
, width
, height
);
111 // create surface based on CGContext
113 // ensure kCGBitmapByteOrder32Host flag, otherwise Cairo breaks (we are practically always using CGBitmapContext)
114 OSL_ASSERT ((CGBitmapContextGetBitsPerPixel(rContext
) != 32) ||
115 (CGBitmapContextGetBitmapInfo(rContext
) & kCGBitmapByteOrderMask
) == kCGBitmapByteOrder32Host
);
117 mpSurface
.reset(cairo_quartz_surface_create_for_cg_context(rContext
, width
, height
),
118 &cairo_surface_destroy
);
120 cairo_surface_set_device_offset( mpSurface
.get(), x
, y
);
122 // Necessary, context is lost otherwise
123 CGContextRetain(rContext
);
128 * QuartzSurface::getCairo: Create Cairo (drawing object) for the Canvas surface
130 * @return new Cairo or NULL
132 CairoSharedPtr
QuartzSurface::getCairo() const
136 return CairoSharedPtr( cairo_create(mpSurface
.get()),
141 return CairoSharedPtr();
146 * QuartzSurface::getSimilar: Create new similar Canvas surface
147 * @param aContent format of the new surface (cairo_content_t from cairo/src/cairo.h)
148 * @param width width of the new surface
149 * @param height height of the new surface
151 * Creates a new Canvas surface. This normally creates platform native surface, even though
152 * generic function is used.
154 * Cairo surface from aContent (cairo_content_t)
156 * @return new surface or NULL
158 SurfaceSharedPtr
QuartzSurface::getSimilar( Content aContent
, int width
, int height
) const
160 return SurfaceSharedPtr(
162 CairoSurfaceSharedPtr(
163 cairo_surface_create_similar( mpSurface
.get(), aContent
, width
, height
),
164 &cairo_surface_destroy
)));
168 * QuartzSurface::flush: Draw the data to screen
170 void QuartzSurface::flush() const
172 // can only flush surfaces with NSView
176 OSL_TRACE("Canvas::cairo::QuartzSurface::flush(): flush to NSView");
178 CGContextRef mrContext
= getCGContext();
188 * This code is using same screen update code as in VCL (esp. AquaSalGraphics::UpdateWindow() )
190 CGContextRef rViewContext
= reinterpret_cast<CGContextRef
>([[NSGraphicsContext currentContext
] graphicsPort
]);
192 // Just guessing for now...
193 CGContextRef rViewContext
= UIGraphicsGetCurrentContext();
195 CGImageRef xImage
= CGBitmapContextCreateImage(mrContext
);
196 CGContextDrawImage(rViewContext
,
198 CGImageGetWidth(xImage
),
199 CGImageGetHeight(xImage
)),
201 CGImageRelease( xImage
);
202 CGContextFlush( rViewContext
);
204 [mpView unlockFocus
];
209 * QuartzSurface::getDepth: Get the color depth of the Canvas surface.
211 * @return color depth
213 int QuartzSurface::getDepth() const
217 switch (cairo_surface_get_content (mpSurface
.get()))
219 case CAIRO_CONTENT_ALPHA
: return 8; break;
220 case CAIRO_CONTENT_COLOR
: return 24; break;
221 case CAIRO_CONTENT_COLOR_ALPHA
: return 32; break;
224 OSL_TRACE("Canvas::cairo::QuartzSurface::getDepth(): ERROR - depth unspecified!");
230 * QuartzSurface::getCGContext: Get the native CGContextRef of the Canvas's cairo surface
232 * @return graphics context
234 CGContextRef
QuartzSurface::getCGContext() const
237 return cairo_quartz_surface_get_cg_context(mpSurface
.get());
243 * cairo::createVirtualDevice: Create a VCL virtual device for the CGContext in the cairo Surface
245 * @return The new virtual device
247 VclPtr
<VirtualDevice
> QuartzSurface::createVirtualDevice() const
249 SystemGraphicsData aSystemGraphicsData
;
250 aSystemGraphicsData
.nSize
= sizeof(SystemGraphicsData
);
251 aSystemGraphicsData
.rCGContext
= getCGContext();
252 return VclPtr
<VirtualDevice
>(
253 VclPtr
<VirtualDevice
>::Create( &aSystemGraphicsData
, Size(1, 1), getDepth() ));
260 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */