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