/src/libreoffice/canvas/source/vcl/impltools.cxx
Line | Count | Source |
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 <sal/config.h> |
21 | | |
22 | | #include <basegfx/matrix/b2dhommatrix.hxx> |
23 | | #include <basegfx/numeric/ftools.hxx> |
24 | | #include <basegfx/point/b2dpoint.hxx> |
25 | | #include <basegfx/polygon/b2dpolygontools.hxx> |
26 | | #include <basegfx/range/b2drectangle.hxx> |
27 | | #include <basegfx/utils/canvastools.hxx> |
28 | | #include <basegfx/tuple/b2dtuple.hxx> |
29 | | #include <rtl/math.hxx> |
30 | | #include <comphelper/diagnose_ex.hxx> |
31 | | #include <sal/log.hxx> |
32 | | #include <vcl/bitmap.hxx> |
33 | | #include <vcl/canvastools.hxx> |
34 | | #include <vcl/BitmapTools.hxx> |
35 | | #include <vcl/metric.hxx> |
36 | | #include <vcl/skia/SkiaHelper.hxx> |
37 | | |
38 | | #include <canvas/canvastools.hxx> |
39 | | |
40 | | #include "canvasbitmap.hxx" |
41 | | #include "impltools.hxx" |
42 | | #include "spritecanvas.hxx" |
43 | | |
44 | | |
45 | | using namespace ::com::sun::star; |
46 | | |
47 | | namespace vclcanvastools |
48 | | { |
49 | | using namespace vclcanvas; |
50 | | ::Bitmap bitmapFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap ) |
51 | 0 | { |
52 | | // TODO(F3): CanvasCustomSprite should also be tunnelled |
53 | | // through (also implements XIntegerBitmap interface) |
54 | 0 | CanvasBitmap* pBitmapImpl = dynamic_cast< CanvasBitmap* >( xBitmap.get() ); |
55 | |
|
56 | 0 | if( pBitmapImpl ) |
57 | 0 | { |
58 | 0 | return pBitmapImpl->getBitmap(); |
59 | 0 | } |
60 | 0 | else |
61 | 0 | { |
62 | 0 | SpriteCanvas* pCanvasImpl = dynamic_cast< SpriteCanvas* >( xBitmap.get() ); |
63 | 0 | if( pCanvasImpl && pCanvasImpl->getBackBuffer() ) |
64 | 0 | { |
65 | | // TODO(F3): mind the plain Canvas impl. Consolidate with CWS canvas05 |
66 | 0 | const ::OutputDevice& rDev( pCanvasImpl->getBackBuffer()->getOutDev() ); |
67 | 0 | const ::Point aEmptyPoint; |
68 | 0 | return rDev.GetBitmap( aEmptyPoint, rDev.GetOutputSizePixel() ); |
69 | 0 | } |
70 | | |
71 | | // TODO(F2): add support for floating point bitmap formats |
72 | 0 | uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntBmp( |
73 | 0 | xBitmap, uno::UNO_QUERY_THROW ); |
74 | |
|
75 | 0 | ::Bitmap aBmp = vcl::unotools::bitmapFromXBitmap( xIntBmp ); |
76 | 0 | if( !aBmp.IsEmpty() ) |
77 | 0 | return aBmp; |
78 | | |
79 | | // TODO(F1): extract pixel from XBitmap interface |
80 | 0 | ENSURE_OR_THROW( false, |
81 | 0 | "bitmapExFromXBitmap(): could not extract bitmap" ); |
82 | 0 | } |
83 | | |
84 | 0 | return ::Bitmap(); |
85 | 0 | } |
86 | | |
87 | | bool setupFontTransform( ::Point& o_rPoint, |
88 | | vcl::Font& io_rVCLFont, |
89 | | const rendering::ViewState& rViewState, |
90 | | const rendering::RenderState& rRenderState, |
91 | | ::OutputDevice const & rOutDev ) |
92 | 0 | { |
93 | 0 | ::basegfx::B2DHomMatrix aMatrix; |
94 | |
|
95 | 0 | ::canvastools::mergeViewAndRenderTransform(aMatrix, |
96 | 0 | rViewState, |
97 | 0 | rRenderState); |
98 | |
|
99 | 0 | ::basegfx::B2DTuple aScale; |
100 | 0 | ::basegfx::B2DTuple aTranslate; |
101 | 0 | double nRotate, nShearX; |
102 | |
|
103 | 0 | aMatrix.decompose( aScale, aTranslate, nRotate, nShearX ); |
104 | | |
105 | | // query font metric _before_ tampering with width and height |
106 | 0 | if( !::rtl::math::approxEqual(aScale.getX(), aScale.getY()) ) |
107 | 0 | { |
108 | | // retrieve true font width |
109 | 0 | const sal_Int32 nFontWidth( rOutDev.GetFontMetric( io_rVCLFont ).GetAverageFontWidth() ); |
110 | |
|
111 | 0 | const sal_Int32 nScaledFontWidth( ::basegfx::fround(nFontWidth * aScale.getX()) ); |
112 | |
|
113 | 0 | if( !nScaledFontWidth ) |
114 | 0 | { |
115 | | // scale is smaller than one pixel - disable text |
116 | | // output altogether |
117 | 0 | return false; |
118 | 0 | } |
119 | | |
120 | 0 | io_rVCLFont.SetAverageFontWidth( nScaledFontWidth ); |
121 | 0 | } |
122 | | |
123 | 0 | if( !::rtl::math::approxEqual(aScale.getY(), 1.0) ) |
124 | 0 | { |
125 | 0 | const sal_Int32 nFontHeight( io_rVCLFont.GetFontHeight() ); |
126 | 0 | io_rVCLFont.SetFontHeight( ::basegfx::fround<::tools::Long>(nFontHeight * aScale.getY()) ); |
127 | 0 | } |
128 | |
|
129 | 0 | io_rVCLFont.SetOrientation( Degree10( ::basegfx::fround(-basegfx::rad2deg<10>(fmod(nRotate, 2*M_PI))) ) ); |
130 | | |
131 | | // TODO(F2): Missing functionality in VCL: shearing |
132 | 0 | o_rPoint.setX( ::basegfx::fround<::tools::Long>(aTranslate.getX()) ); |
133 | 0 | o_rPoint.setY( ::basegfx::fround<::tools::Long>(aTranslate.getY()) ); |
134 | |
|
135 | 0 | return true; |
136 | 0 | } |
137 | | |
138 | | void setupFontWidth(const css::geometry::Matrix2D& rFontMatrix, |
139 | | vcl::Font& rFont, |
140 | | OutputDevice& rOutDev) |
141 | 0 | { |
142 | 0 | rFont.SetFontSize(Size(0, rFont.GetFontHeight())); |
143 | |
|
144 | 0 | if (!::rtl::math::approxEqual(rFontMatrix.m00, rFontMatrix.m11)) |
145 | 0 | { |
146 | 0 | const bool bOldMapState(rOutDev.IsMapModeEnabled()); |
147 | 0 | rOutDev.EnableMapMode(false); |
148 | |
|
149 | 0 | const Size aSize = rOutDev.GetFontMetric(rFont).GetFontSize(); |
150 | |
|
151 | 0 | const double fDividend(rFontMatrix.m10 + rFontMatrix.m11); |
152 | 0 | double fStretch = rFontMatrix.m00 + rFontMatrix.m01; |
153 | |
|
154 | 0 | if (!::basegfx::fTools::equalZero(fDividend)) |
155 | 0 | fStretch /= fDividend; |
156 | |
|
157 | 0 | const ::tools::Long nNewWidth = ::basegfx::fround<::tools::Long>(aSize.Width() * fStretch); |
158 | |
|
159 | 0 | rFont.SetAverageFontWidth(nNewWidth); |
160 | |
|
161 | 0 | rOutDev.EnableMapMode(bOldMapState); |
162 | 0 | } |
163 | 0 | } |
164 | | |
165 | | bool isRectangle( const ::tools::PolyPolygon& rPolyPoly ) |
166 | 0 | { |
167 | | // exclude some cheap cases first |
168 | 0 | if( rPolyPoly.Count() != 1 ) |
169 | 0 | return false; |
170 | | |
171 | 0 | const ::tools::Polygon& rPoly( rPolyPoly[0] ); |
172 | |
|
173 | 0 | sal_uInt16 nCount( rPoly.GetSize() ); |
174 | 0 | if( nCount < 4 ) |
175 | 0 | return false; |
176 | | |
177 | | // delegate to basegfx |
178 | 0 | return ::basegfx::utils::isRectangle( rPoly.getB2DPolygon() ); |
179 | 0 | } |
180 | | |
181 | | |
182 | | // VCL-Canvas related |
183 | | |
184 | | |
185 | | ::Point mapRealPoint2D( const geometry::RealPoint2D& rPoint, |
186 | | const rendering::ViewState& rViewState, |
187 | | const rendering::RenderState& rRenderState ) |
188 | 0 | { |
189 | 0 | ::basegfx::B2DPoint aPoint( ::basegfx::unotools::b2DPointFromRealPoint2D(rPoint) ); |
190 | |
|
191 | 0 | ::basegfx::B2DHomMatrix aMatrix; |
192 | 0 | aPoint *= ::canvastools::mergeViewAndRenderTransform(aMatrix, |
193 | 0 | rViewState, |
194 | 0 | rRenderState); |
195 | |
|
196 | 0 | return vcl::unotools::pointFromB2DPoint( aPoint ); |
197 | 0 | } |
198 | | |
199 | | ::tools::PolyPolygon mapPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly, |
200 | | const rendering::ViewState& rViewState, |
201 | | const rendering::RenderState& rRenderState ) |
202 | 0 | { |
203 | 0 | ::basegfx::B2DHomMatrix aMatrix; |
204 | 0 | ::canvastools::mergeViewAndRenderTransform(aMatrix, |
205 | 0 | rViewState, |
206 | 0 | rRenderState); |
207 | |
|
208 | 0 | ::basegfx::B2DPolyPolygon aTemp( rPoly ); |
209 | |
|
210 | 0 | aTemp.transform( aMatrix ); |
211 | |
|
212 | 0 | return ::tools::PolyPolygon( aTemp ); |
213 | 0 | } |
214 | | |
215 | | ::Bitmap transformBitmap( const ::Bitmap& rBitmap, |
216 | | const ::basegfx::B2DHomMatrix& rTransform ) |
217 | 0 | { |
218 | 0 | SAL_INFO( "canvas.vcl", "::vclcanvastools::transformBitmap()" ); |
219 | 0 | SAL_INFO( "canvas.vcl", "::vclcanvastools::transformBitmap: 0x" << std::hex << &rBitmap ); |
220 | | |
221 | | // calc transformation and size of bitmap to be |
222 | | // generated. Note, that the translational components are |
223 | | // deleted from the transformation; this can be handled by |
224 | | // an offset when painting the bitmap |
225 | 0 | const Size aBmpSize( rBitmap.GetSizePixel() ); |
226 | | |
227 | | // calc effective transformation for bitmap |
228 | 0 | const ::basegfx::B2DRectangle aSrcRect( 0, 0, |
229 | 0 | aBmpSize.Width(), |
230 | 0 | aBmpSize.Height() ); |
231 | 0 | ::basegfx::B2DRectangle aDestRect = ::canvastools::calcTransformedRectBounds( |
232 | 0 | aSrcRect, |
233 | 0 | rTransform ); |
234 | | |
235 | | // re-center bitmap, such that it's left, top border is |
236 | | // aligned with (0,0). The method takes the given |
237 | | // rectangle, and calculates a transformation that maps |
238 | | // this rectangle unscaled to the origin. |
239 | 0 | ::basegfx::B2DHomMatrix aLocalTransform = ::canvastools::calcRectToOriginTransform( |
240 | 0 | aSrcRect, |
241 | 0 | rTransform ); |
242 | |
|
243 | 0 | return vcl::bitmap::CanvasTransformBitmap(rBitmap, rTransform, aDestRect, aLocalTransform); |
244 | 0 | } |
245 | | |
246 | | void SetDefaultDeviceAntiAliasing( OutputDevice* pDevice ) |
247 | 0 | { |
248 | | #if defined( MACOSX ) |
249 | | // use AA on VCLCanvas for Mac |
250 | | pDevice->SetAntialiasing( AntialiasingFlags::Enable | pDevice->GetAntialiasing() ); |
251 | | #else |
252 | | // switch off AA for WIN32 and UNIX, the VCLCanvas does not look good with it and |
253 | | // is not required to do AA. It would need to be adapted to use it correctly |
254 | | // (especially gradient painting). This will need extra work. |
255 | 0 | if( SkiaHelper::isVCLSkiaEnabled()) // But Skia handles AA fine. |
256 | 0 | pDevice->SetAntialiasing( AntialiasingFlags::Enable | pDevice->GetAntialiasing() ); |
257 | 0 | else |
258 | 0 | pDevice->SetAntialiasing(pDevice->GetAntialiasing() & ~AntialiasingFlags::Enable); |
259 | 0 | #endif |
260 | 0 | } |
261 | | |
262 | | } |
263 | | |
264 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |