Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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: */