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 .
22 #include <sal/config.h>
23 #include <config_features.h>
24 #include <config_cairo_rgba.h>
28 #include <vcl/dllapi.h>
29 #include <vcl/region.hxx>
30 #include <vcl/salgtype.hxx>
31 #include <vcl/BitmapBuffer.hxx>
33 #include <com/sun/star/drawing/LineCap.hpp>
35 #include <basegfx/utils/systemdependentdata.hxx>
36 #include <basegfx/range/b2drange.hxx>
37 #include <basegfx/range/b2irange.hxx>
38 #include <basegfx/matrix/b2dhommatrix.hxx>
39 #include <basegfx/polygon/b2dpolypolygon.hxx>
40 #include <basegfx/polygon/b2dpolygon.hxx>
42 #include <unordered_map>
44 // Using formats that match cairo's formats.
45 // SVP_24BIT_FORMAT is used to store 24-bit images in 3-byte pixels to conserve memory.
48 For internal cairo we have the option --enable-cairo-rgba which is potentially
49 useful for Andoid or Online to switch the rgb components. For Android cairo then
50 matches the OpenGL GL_RGBA format so we can use it there where we don't have
51 GL_BGRA support. Similarly for Online we can then use cairo's pixel data
52 without needing to swizzle it for use as a canvas ImageData.
55 #define SVP_24BIT_FORMAT (ScanlineFormat::N24BitTcRgb | ScanlineFormat::TopDown)
56 #define SVP_CAIRO_FORMAT (ScanlineFormat::N32BitTcRgba | ScanlineFormat::TopDown)
57 #define SVP_CAIRO_BLUE 1
58 #define SVP_CAIRO_GREEN 2
59 #define SVP_CAIRO_RED 0
60 #define SVP_CAIRO_ALPHA 3
61 #elif defined OSL_BIGENDIAN
62 #define SVP_24BIT_FORMAT (ScanlineFormat::N24BitTcRgb | ScanlineFormat::TopDown)
63 #define SVP_CAIRO_FORMAT (ScanlineFormat::N32BitTcArgb | ScanlineFormat::TopDown)
64 #define SVP_CAIRO_BLUE 3
65 #define SVP_CAIRO_GREEN 2
66 #define SVP_CAIRO_RED 1
67 #define SVP_CAIRO_ALPHA 0
69 #define SVP_24BIT_FORMAT (ScanlineFormat::N24BitTcBgr | ScanlineFormat::TopDown)
70 #define SVP_CAIRO_FORMAT (ScanlineFormat::N32BitTcBgra | ScanlineFormat::TopDown)
71 #define SVP_CAIRO_BLUE 0
72 #define SVP_CAIRO_GREEN 1
73 #define SVP_CAIRO_RED 2
74 #define SVP_CAIRO_ALPHA 3
77 typedef struct _cairo cairo_t
;
78 typedef struct _cairo_surface cairo_surface_t
;
79 typedef struct _cairo_user_data_key cairo_user_data_key_t
;
81 VCL_DLLPUBLIC
void dl_cairo_surface_set_device_scale(cairo_surface_t
* surface
, double x_scale
,
83 VCL_DLLPUBLIC
void dl_cairo_surface_get_device_scale(cairo_surface_t
* surface
, double* x_scale
,
86 VCL_DLLPUBLIC
basegfx::B2DRange
getFillDamage(cairo_t
* cr
);
87 VCL_DLLPUBLIC
basegfx::B2DRange
getClipBox(cairo_t
* cr
);
88 VCL_DLLPUBLIC
basegfx::B2DRange
getClippedFillDamage(cairo_t
* cr
);
89 VCL_DLLPUBLIC
basegfx::B2DRange
getClippedStrokeDamage(cairo_t
* cr
);
90 VCL_DLLPUBLIC
basegfx::B2DRange
getStrokeDamage(cairo_t
* cr
);
92 class SystemDependentData_CairoPath
: public basegfx::SystemDependentData
95 // the path data itself
96 cairo_path_t
* mpCairoPath
;
98 // all other values the path data is based on and
99 // need to be compared with to check for data validity
102 std::vector
<double> maStroke
;
105 SystemDependentData_CairoPath(size_t nSizeMeasure
, cairo_t
* cr
, bool bNoJoin
, bool bAntiAlias
,
106 const std::vector
<double>* pStroke
); // MM01
107 virtual ~SystemDependentData_CairoPath() override
;
110 cairo_path_t
* getCairoPath() { return mpCairoPath
; }
111 bool getNoJoin() const { return mbNoJoin
; }
112 bool getAntiAlias() const { return mbAntiAlias
; }
113 const std::vector
<double>& getStroke() const { return maStroke
; }
115 virtual sal_Int64
estimateUsageInBytes() const override
;
118 VCL_DLLPUBLIC
size_t AddPolygonToPath(cairo_t
* cr
, const basegfx::B2DPolygon
& rPolygon
,
119 const basegfx::B2DHomMatrix
& rObjectToDevice
, bool bPixelSnap
,
120 bool bPixelSnapHairline
);
122 VCL_DLLPUBLIC
basegfx::B2DPoint
impPixelSnap(const basegfx::B2DPolygon
& rPolygon
,
123 const basegfx::B2DHomMatrix
& rObjectToDevice
,
124 basegfx::B2DHomMatrix
& rObjectToDeviceInv
,
127 VCL_DLLPUBLIC
void add_polygon_path(cairo_t
* cr
, const basegfx::B2DPolyPolygon
& rPolyPolygon
,
128 const basegfx::B2DHomMatrix
& rObjectToDevice
, bool bPixelSnap
);
130 VCL_DLLPUBLIC cairo_format_t
getCairoFormat(const BitmapBuffer
& rBuffer
);
132 VCL_DLLPUBLIC
std::unique_ptr
<BitmapBuffer
>
133 FastConvert24BitRgbTo32BitCairo(const BitmapBuffer
* pSrc
);
135 VCL_DLLPUBLIC
void Toggle1BitTransparency(const BitmapBuffer
& rBuf
);
143 typedef void (*damageHandler
)(void* handle
, sal_Int32 nExtentsX
, sal_Int32 nExtentsY
,
144 sal_Int32 nExtentsWidth
, sal_Int32 nExtentsHeight
);
146 struct VCL_DLLPUBLIC DamageHandler
149 damageHandler damaged
;
152 struct VCL_DLLPUBLIC CairoCommon
154 cairo_surface_t
* m_pSurface
;
155 basegfx::B2IVector m_aFrameSize
;
156 vcl::Region m_aClipRegion
;
159 PaintMode m_ePaintMode
;
163 : m_pSurface(nullptr)
164 , m_aLineColor(Color(0x00, 0x00, 0x00))
165 , m_aFillColor(Color(0xFF, 0xFF, 0XFF))
166 , m_ePaintMode(PaintMode::Over
)
171 static cairo_user_data_key_t
* getDamageKey();
173 cairo_surface_t
* getSurface() const { return m_pSurface
; }
175 cairo_t
* getCairoContext(bool bXorModeAllowed
, bool bAntiAlias
) const;
176 void releaseCairoContext(cairo_t
* cr
, bool bXorModeAllowed
,
177 const basegfx::B2DRange
& rExtents
) const;
179 cairo_t
* createTmpCompatibleCairoContext() const;
181 void applyColor(cairo_t
* cr
, Color rColor
, double fTransparency
= 0.0);
182 void clipRegion(cairo_t
* cr
);
183 static void clipRegion(cairo_t
* cr
, const vcl::Region
& rClipRegion
);
185 // need this static version of ::drawPolyLine for usage from
186 // vcl/unx/generic/gdi/salgdi.cxx. It gets wrapped by
187 // ::drawPolyLine with some added parameters (see there)
188 static bool drawPolyLine(cairo_t
* cr
, basegfx::B2DRange
* pExtents
, const Color
& rLineColor
,
189 bool bAntiAlias
, const basegfx::B2DHomMatrix
& rObjectToDevice
,
190 const basegfx::B2DPolygon
& rPolyLine
, double fTransparency
,
191 double fLineWidth
, const std::vector
<double>* pStroke
,
192 basegfx::B2DLineJoin eLineJoin
, css::drawing::LineCap eLineCap
,
193 double fMiterMinimumAngle
, bool bPixelSnapHairline
);
195 void copyWithOperator(const SalTwoRect
& rTR
, cairo_surface_t
* source
, cairo_operator_t eOp
,
198 void copySource(const SalTwoRect
& rTR
, cairo_surface_t
* source
, bool bAntiAlias
);
200 static basegfx::B2DRange
renderSource(cairo_t
* cr
, const SalTwoRect
& rTR
,
201 cairo_surface_t
* source
);
203 void copyBitsCairo(const SalTwoRect
& rTR
, cairo_surface_t
* pSourceSurface
, bool bAntiAlias
);
205 void invert(const basegfx::B2DPolygon
& rPoly
, SalInvert nFlags
, bool bAntiAlias
);
207 static cairo_surface_t
* createCairoSurface(const BitmapBuffer
* pBuffer
);
210 void doXorOnRelease(sal_Int32 nExtentsLeft
, sal_Int32 nExtentsTop
, sal_Int32 nExtentsRight
,
211 sal_Int32 nExtentsBottom
, cairo_surface_t
* const surface
,
212 sal_Int32 nWidth
) const;
218 cairo_surface_t
* pSurface
;
219 std::unordered_map
<sal_uInt64
, cairo_surface_t
*> maDownscaled
;
221 SurfaceHelper(const SurfaceHelper
&) = delete;
222 SurfaceHelper
& operator=(const SurfaceHelper
&) = delete;
224 cairo_surface_t
* implCreateOrReuseDownscale(unsigned long nTargetWidth
,
225 unsigned long nTargetHeight
);
228 cairo_surface_t
* implGetSurface() const { return pSurface
; }
229 void implSetSurface(cairo_surface_t
* pNew
) { pSurface
= pNew
; }
231 bool isTrivial() const;
234 explicit SurfaceHelper();
237 cairo_surface_t
* getSurface(unsigned long nTargetWidth
= 0,
238 unsigned long nTargetHeight
= 0) const;
241 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */