Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <canvas/debug.hxx>
21 : #include <canvas/canvastools.hxx>
22 : #include <tools/diagnose_ex.h>
23 :
24 : #include "cairo_canvasbitmap.hxx"
25 :
26 : #ifdef CAIRO_HAS_XLIB_SURFACE
27 : # include "cairo_xlib_cairo.hxx"
28 : #elif defined CAIRO_HAS_QUARTZ_SURFACE
29 : # include "cairo_quartz_cairo.hxx"
30 : #elif defined CAIRO_HAS_WIN32_SURFACE
31 : # include "cairo_win32_cairo.hxx"
32 : # include <cairo-win32.h>
33 : #else
34 : # error Native API needed.
35 : #endif
36 :
37 : using namespace ::cairo;
38 : using namespace ::com::sun::star;
39 :
40 : #ifdef CAIRO_HAS_WIN32_SURFACE
41 : namespace
42 : {
43 : HBITMAP surface2HBitmap( const SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize )
44 : {
45 : // cant seem to retrieve HBITMAP from cairo. copy content then
46 : HDC hScreenDC=GetDC(NULL);
47 : HBITMAP hBmpBitmap = CreateCompatibleBitmap( hScreenDC,
48 : rSize.getX(),
49 : rSize.getY() );
50 :
51 : HDC hBmpDC = CreateCompatibleDC( 0 );
52 : HBITMAP hBmpOld = (HBITMAP) SelectObject( hBmpDC, hBmpBitmap );
53 :
54 : BitBlt( hBmpDC, 0, 0, rSize.getX(), rSize.getX(),
55 : cairo_win32_surface_get_dc(rSurface->getCairoSurface().get()),
56 : 0, 0, SRCCOPY );
57 :
58 : SelectObject( hBmpDC, hBmpOld );
59 : DeleteDC( hBmpDC );
60 :
61 : return hBmpBitmap;
62 : }
63 : }
64 : #endif
65 :
66 : namespace cairocanvas
67 : {
68 0 : CanvasBitmap::CanvasBitmap( const ::basegfx::B2ISize& rSize,
69 : const SurfaceProviderRef& rSurfaceProvider,
70 : rendering::XGraphicDevice* pDevice,
71 : bool bHasAlpha ) :
72 : mpSurfaceProvider( rSurfaceProvider ),
73 : mpBufferSurface(),
74 : mpBufferCairo(),
75 : maSize(rSize),
76 0 : mbHasAlpha(bHasAlpha)
77 : {
78 0 : ENSURE_OR_THROW( mpSurfaceProvider.is(),
79 : "CanvasBitmap::CanvasBitmap(): Invalid surface or device" );
80 :
81 : OSL_TRACE( "bitmap size: %dx%d", rSize.getX(), rSize.getY() );
82 :
83 0 : mpBufferSurface = mpSurfaceProvider->createSurface( rSize, bHasAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR );
84 0 : mpBufferCairo = mpBufferSurface->getCairo();
85 :
86 0 : maCanvasHelper.init( rSize, *mpSurfaceProvider, pDevice );
87 0 : maCanvasHelper.setSurface( mpBufferSurface, bHasAlpha );
88 :
89 : // clear bitmap to 100% transparent
90 0 : maCanvasHelper.clear();
91 0 : }
92 :
93 0 : void CanvasBitmap::disposeThis()
94 : {
95 0 : mpSurfaceProvider.clear();
96 :
97 0 : mpBufferCairo.reset();
98 0 : mpBufferSurface.reset();
99 :
100 : // forward to parent
101 0 : CanvasBitmap_Base::disposeThis();
102 0 : }
103 :
104 0 : SurfaceSharedPtr CanvasBitmap::getSurface()
105 : {
106 0 : return mpBufferSurface;
107 : }
108 :
109 0 : SurfaceSharedPtr CanvasBitmap::createSurface( const ::basegfx::B2ISize& rSize, Content aContent )
110 : {
111 0 : return mpSurfaceProvider->createSurface(rSize,aContent);
112 : }
113 :
114 0 : SurfaceSharedPtr CanvasBitmap::createSurface( ::Bitmap& rBitmap )
115 : {
116 0 : return mpSurfaceProvider->createSurface(rBitmap);
117 : }
118 :
119 0 : SurfaceSharedPtr CanvasBitmap::changeSurface( bool, bool )
120 : {
121 : // non-modifiable surface here
122 0 : return SurfaceSharedPtr();
123 : }
124 :
125 0 : OutputDevice* CanvasBitmap::getOutputDevice()
126 : {
127 0 : return mpSurfaceProvider->getOutputDevice();
128 : }
129 :
130 0 : bool CanvasBitmap::repaint( const SurfaceSharedPtr& pSurface,
131 : const rendering::ViewState& viewState,
132 : const rendering::RenderState& renderState )
133 : {
134 0 : return maCanvasHelper.repaint( pSurface, viewState, renderState );
135 : }
136 :
137 0 : uno::Any SAL_CALL CanvasBitmap::getFastPropertyValue( sal_Int32 nHandle ) throw (uno::RuntimeException)
138 : {
139 0 : uno::Any aRV( sal_Int32(0) );
140 : // 0 ... get BitmapEx
141 : // 1 ... get Pixbuf with bitmap RGB content
142 : // 2 ... get Pixbuf with bitmap alpha mask
143 0 : switch( nHandle )
144 : {
145 : case 0:
146 : {
147 0 : aRV = uno::Any( reinterpret_cast<sal_Int64>( (BitmapEx*) NULL ) );
148 0 : break;
149 : }
150 : case 1:
151 : {
152 : #ifdef CAIRO_HAS_XLIB_SURFACE
153 0 : X11Surface* pXlibSurface=dynamic_cast<X11Surface*>(mpBufferSurface.get());
154 : OSL_ASSERT(pXlibSurface);
155 0 : uno::Sequence< uno::Any > args( 3 );
156 0 : args[0] = uno::Any( false ); // do not call XFreePixmap on it
157 0 : args[1] = uno::Any( pXlibSurface->getPixmap()->mhDrawable );
158 0 : args[2] = uno::Any( sal_Int32( pXlibSurface->getDepth() ) );
159 :
160 0 : aRV = uno::Any( args );
161 : #elif defined CAIRO_HAS_QUARTZ_SURFACE
162 : QuartzSurface* pQuartzSurface = dynamic_cast<QuartzSurface*>(mpBufferSurface.get());
163 : OSL_ASSERT(pQuartzSurface);
164 : uno::Sequence< uno::Any > args( 1 );
165 : args[0] = uno::Any( sal_IntPtr (pQuartzSurface->getCGContext()) );
166 : aRV = uno::Any( args );
167 : #elif defined CAIRO_HAS_WIN32_SURFACE
168 : // TODO(F2): check whether under all circumstances,
169 : // the alpha channel is ignored here.
170 : uno::Sequence< uno::Any > args( 1 );
171 : args[1] = uno::Any( sal_Int64(surface2HBitmap(mpBufferSurface,maSize)) );
172 :
173 : aRV = uno::Any( args );
174 : // caller frees the bitmap
175 : #else
176 : # error Please define fast prop retrieval for your platform!
177 : #endif
178 0 : break;
179 : }
180 : case 2:
181 : {
182 : #ifdef CAIRO_HAS_XLIB_SURFACE
183 0 : uno::Sequence< uno::Any > args( 3 );
184 0 : SurfaceSharedPtr pAlphaSurface = mpSurfaceProvider->createSurface( maSize, CAIRO_CONTENT_COLOR );
185 0 : CairoSharedPtr pAlphaCairo = pAlphaSurface->getCairo();
186 0 : X11Surface* pXlibSurface=dynamic_cast<X11Surface*>(pAlphaSurface.get());
187 : OSL_ASSERT(pXlibSurface);
188 :
189 : // create RGB image (levels of gray) of alpha channel of original picture
190 0 : cairo_set_source_rgba( pAlphaCairo.get(), 1, 1, 1, 1 );
191 0 : cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_SOURCE );
192 0 : cairo_paint( pAlphaCairo.get() );
193 0 : cairo_set_source_surface( pAlphaCairo.get(), mpBufferSurface->getCairoSurface().get(), 0, 0 );
194 0 : cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_XOR );
195 0 : cairo_paint( pAlphaCairo.get() );
196 0 : pAlphaCairo.reset();
197 :
198 0 : X11PixmapSharedPtr pPixmap = pXlibSurface->getPixmap();
199 0 : args[0] = uno::Any( true );
200 0 : args[1] = ::com::sun::star::uno::Any( pPixmap->mhDrawable );
201 0 : args[2] = ::com::sun::star::uno::Any( sal_Int32( pXlibSurface->getDepth () ) );
202 0 : pPixmap->clear(); // caller takes ownership of pixmap
203 :
204 : // return pixmap and alphachannel pixmap - it will be used in BitmapEx
205 0 : aRV = uno::Any( args );
206 : #elif defined CAIRO_HAS_QUARTZ_SURFACE
207 : SurfaceSharedPtr pAlphaSurface = mpSurfaceProvider->createSurface( maSize, CAIRO_CONTENT_COLOR );
208 : CairoSharedPtr pAlphaCairo = pAlphaSurface->getCairo();
209 : QuartzSurface* pQuartzSurface=dynamic_cast<QuartzSurface*>(pAlphaSurface.get());
210 : OSL_ASSERT(pQuartzSurface);
211 :
212 : // create RGB image (levels of gray) of alpha channel of original picture
213 : cairo_set_source_rgba( pAlphaCairo.get(), 1, 1, 1, 1 );
214 : cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_SOURCE );
215 : cairo_paint( pAlphaCairo.get() );
216 : cairo_set_source_surface( pAlphaCairo.get(), mpBufferSurface->getCairoSurface().get(), 0, 0 );
217 : cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_XOR );
218 : cairo_paint( pAlphaCairo.get() );
219 : pAlphaCairo.reset();
220 :
221 : uno::Sequence< uno::Any > args( 1 );
222 : args[0] = uno::Any( sal_IntPtr (pQuartzSurface->getCGContext()) );
223 : // return ??? and alphachannel ??? - it will be used in BitmapEx
224 : aRV = uno::Any( args );
225 : #elif defined CAIRO_HAS_WIN32_SURFACE
226 : SurfaceSharedPtr pAlphaSurface = mpSurfaceProvider->createSurface( maSize, CAIRO_CONTENT_COLOR );
227 : CairoSharedPtr pAlphaCairo = pAlphaSurface->getCairo();
228 :
229 : // create RGB image (levels of gray) of alpha channel of original picture
230 : cairo_set_source_rgba( pAlphaCairo.get(), 1, 1, 1, 1 );
231 : cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_SOURCE );
232 : cairo_paint( pAlphaCairo.get() );
233 : cairo_set_source_surface( pAlphaCairo.get(), mpBufferSurface->getCairoSurface().get(), 0, 0 );
234 : cairo_set_operator( pAlphaCairo.get(), CAIRO_OPERATOR_XOR );
235 : cairo_paint( pAlphaCairo.get() );
236 : pAlphaCairo.reset();
237 :
238 : // cant seem to retrieve HBITMAP from cairo. copy content then
239 : uno::Sequence< uno::Any > args( 1 );
240 : args[1] = uno::Any( sal_Int64(surface2HBitmap(pAlphaSurface,maSize)) );
241 :
242 : aRV = uno::Any( args );
243 : // caller frees the bitmap
244 : #else
245 : # error Please define fast prop retrieval for your platform!
246 : #endif
247 0 : break;
248 : }
249 : }
250 :
251 0 : return aRV;
252 : }
253 :
254 : #define IMPLEMENTATION_NAME "CairoCanvas.CanvasBitmap"
255 : #define SERVICE_NAME "com.sun.star.rendering.CanvasBitmap"
256 :
257 0 : OUString SAL_CALL CanvasBitmap::getImplementationName( ) throw (uno::RuntimeException)
258 : {
259 0 : return OUString( IMPLEMENTATION_NAME );
260 : }
261 :
262 0 : sal_Bool SAL_CALL CanvasBitmap::supportsService( const OUString& ServiceName ) throw (uno::RuntimeException)
263 : {
264 0 : return ServiceName == SERVICE_NAME;
265 : }
266 :
267 0 : uno::Sequence< OUString > SAL_CALL CanvasBitmap::getSupportedServiceNames( ) throw (uno::RuntimeException)
268 : {
269 0 : uno::Sequence< OUString > aRet(1);
270 0 : aRet[0] = SERVICE_NAME;
271 :
272 0 : return aRet;
273 : }
274 :
275 0 : }
276 :
277 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|