1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef MOZILLA_GFX_HELPERSCAIRO_H_
8 #define MOZILLA_GFX_HELPERSCAIRO_H_
17 static inline cairo_operator_t
GfxOpToCairoOp(CompositionOp op
) {
19 case CompositionOp::OP_CLEAR
:
20 return CAIRO_OPERATOR_CLEAR
;
21 case CompositionOp::OP_OVER
:
22 return CAIRO_OPERATOR_OVER
;
23 case CompositionOp::OP_ADD
:
24 return CAIRO_OPERATOR_ADD
;
25 case CompositionOp::OP_ATOP
:
26 return CAIRO_OPERATOR_ATOP
;
27 case CompositionOp::OP_OUT
:
28 return CAIRO_OPERATOR_OUT
;
29 case CompositionOp::OP_IN
:
30 return CAIRO_OPERATOR_IN
;
31 case CompositionOp::OP_SOURCE
:
32 return CAIRO_OPERATOR_SOURCE
;
33 case CompositionOp::OP_DEST_IN
:
34 return CAIRO_OPERATOR_DEST_IN
;
35 case CompositionOp::OP_DEST_OUT
:
36 return CAIRO_OPERATOR_DEST_OUT
;
37 case CompositionOp::OP_DEST_OVER
:
38 return CAIRO_OPERATOR_DEST_OVER
;
39 case CompositionOp::OP_DEST_ATOP
:
40 return CAIRO_OPERATOR_DEST_ATOP
;
41 case CompositionOp::OP_XOR
:
42 return CAIRO_OPERATOR_XOR
;
43 case CompositionOp::OP_MULTIPLY
:
44 return CAIRO_OPERATOR_MULTIPLY
;
45 case CompositionOp::OP_SCREEN
:
46 return CAIRO_OPERATOR_SCREEN
;
47 case CompositionOp::OP_OVERLAY
:
48 return CAIRO_OPERATOR_OVERLAY
;
49 case CompositionOp::OP_DARKEN
:
50 return CAIRO_OPERATOR_DARKEN
;
51 case CompositionOp::OP_LIGHTEN
:
52 return CAIRO_OPERATOR_LIGHTEN
;
53 case CompositionOp::OP_COLOR_DODGE
:
54 return CAIRO_OPERATOR_COLOR_DODGE
;
55 case CompositionOp::OP_COLOR_BURN
:
56 return CAIRO_OPERATOR_COLOR_BURN
;
57 case CompositionOp::OP_HARD_LIGHT
:
58 return CAIRO_OPERATOR_HARD_LIGHT
;
59 case CompositionOp::OP_SOFT_LIGHT
:
60 return CAIRO_OPERATOR_SOFT_LIGHT
;
61 case CompositionOp::OP_DIFFERENCE
:
62 return CAIRO_OPERATOR_DIFFERENCE
;
63 case CompositionOp::OP_EXCLUSION
:
64 return CAIRO_OPERATOR_EXCLUSION
;
65 case CompositionOp::OP_HUE
:
66 return CAIRO_OPERATOR_HSL_HUE
;
67 case CompositionOp::OP_SATURATION
:
68 return CAIRO_OPERATOR_HSL_SATURATION
;
69 case CompositionOp::OP_COLOR
:
70 return CAIRO_OPERATOR_HSL_COLOR
;
71 case CompositionOp::OP_LUMINOSITY
:
72 return CAIRO_OPERATOR_HSL_LUMINOSITY
;
73 case CompositionOp::OP_COUNT
:
77 return CAIRO_OPERATOR_OVER
;
80 static inline cairo_antialias_t
GfxAntialiasToCairoAntialias(
81 AntialiasMode antialias
) {
83 case AntialiasMode::NONE
:
84 return CAIRO_ANTIALIAS_NONE
;
85 case AntialiasMode::GRAY
:
86 return CAIRO_ANTIALIAS_GRAY
;
87 case AntialiasMode::SUBPIXEL
:
88 return CAIRO_ANTIALIAS_SUBPIXEL
;
90 return CAIRO_ANTIALIAS_DEFAULT
;
94 static inline AntialiasMode
CairoAntialiasToGfxAntialias(
95 cairo_antialias_t aAntialias
) {
97 case CAIRO_ANTIALIAS_NONE
:
98 return AntialiasMode::NONE
;
99 case CAIRO_ANTIALIAS_GRAY
:
100 return AntialiasMode::GRAY
;
101 case CAIRO_ANTIALIAS_SUBPIXEL
:
102 return AntialiasMode::SUBPIXEL
;
104 return AntialiasMode::DEFAULT
;
108 static inline cairo_filter_t
GfxSamplingFilterToCairoFilter(
109 SamplingFilter filter
) {
111 case SamplingFilter::GOOD
:
112 return CAIRO_FILTER_GOOD
;
113 case SamplingFilter::LINEAR
:
114 return CAIRO_FILTER_BILINEAR
;
115 case SamplingFilter::POINT
:
116 return CAIRO_FILTER_NEAREST
;
118 MOZ_CRASH("GFX: bad Cairo filter");
121 return CAIRO_FILTER_BILINEAR
;
124 static inline cairo_extend_t
GfxExtendToCairoExtend(ExtendMode extend
) {
126 case ExtendMode::CLAMP
:
127 return CAIRO_EXTEND_PAD
;
128 // Cairo doesn't support tiling in only 1 direction,
129 // So we have to fallback and tile in both.
130 case ExtendMode::REPEAT_X
:
131 case ExtendMode::REPEAT_Y
:
132 case ExtendMode::REPEAT
:
133 return CAIRO_EXTEND_REPEAT
;
134 case ExtendMode::REFLECT
:
135 return CAIRO_EXTEND_REFLECT
;
138 return CAIRO_EXTEND_PAD
;
141 static inline cairo_format_t
GfxFormatToCairoFormat(SurfaceFormat format
) {
143 case SurfaceFormat::A8R8G8B8_UINT32
:
144 return CAIRO_FORMAT_ARGB32
;
145 case SurfaceFormat::X8R8G8B8_UINT32
:
146 return CAIRO_FORMAT_RGB24
;
147 case SurfaceFormat::A8
:
148 return CAIRO_FORMAT_A8
;
149 case SurfaceFormat::R5G6B5_UINT16
:
150 return CAIRO_FORMAT_RGB16_565
;
152 gfxCriticalError() << "Unknown image format " << (int)format
;
153 return CAIRO_FORMAT_ARGB32
;
157 static inline cairo_format_t
CairoContentToCairoFormat(
158 cairo_content_t content
) {
160 case CAIRO_CONTENT_COLOR
:
161 return CAIRO_FORMAT_RGB24
;
162 case CAIRO_CONTENT_ALPHA
:
163 return CAIRO_FORMAT_A8
;
164 case CAIRO_CONTENT_COLOR_ALPHA
:
165 return CAIRO_FORMAT_ARGB32
;
167 gfxCriticalError() << "Unknown cairo content type " << (int)content
;
168 return CAIRO_FORMAT_A8
; // least likely to cause OOB reads
172 static inline cairo_content_t
GfxFormatToCairoContent(SurfaceFormat format
) {
174 case SurfaceFormat::A8R8G8B8_UINT32
:
175 return CAIRO_CONTENT_COLOR_ALPHA
;
176 case SurfaceFormat::X8R8G8B8_UINT32
:
177 case SurfaceFormat::R5G6B5_UINT16
: // fall through
178 return CAIRO_CONTENT_COLOR
;
179 case SurfaceFormat::A8
:
180 return CAIRO_CONTENT_ALPHA
;
182 gfxCriticalError() << "Unknown image content format " << (int)format
;
183 return CAIRO_CONTENT_COLOR_ALPHA
;
187 static inline cairo_line_join_t
GfxLineJoinToCairoLineJoin(JoinStyle style
) {
189 case JoinStyle::BEVEL
:
190 return CAIRO_LINE_JOIN_BEVEL
;
191 case JoinStyle::ROUND
:
192 return CAIRO_LINE_JOIN_ROUND
;
193 case JoinStyle::MITER
:
194 return CAIRO_LINE_JOIN_MITER
;
195 case JoinStyle::MITER_OR_BEVEL
:
196 return CAIRO_LINE_JOIN_MITER
;
199 return CAIRO_LINE_JOIN_MITER
;
202 static inline cairo_line_cap_t
GfxLineCapToCairoLineCap(CapStyle style
) {
205 return CAIRO_LINE_CAP_BUTT
;
206 case CapStyle::ROUND
:
207 return CAIRO_LINE_CAP_ROUND
;
208 case CapStyle::SQUARE
:
209 return CAIRO_LINE_CAP_SQUARE
;
212 return CAIRO_LINE_CAP_BUTT
;
215 static inline SurfaceFormat
CairoContentToGfxFormat(cairo_content_t content
) {
217 case CAIRO_CONTENT_COLOR_ALPHA
:
218 return SurfaceFormat::A8R8G8B8_UINT32
;
219 case CAIRO_CONTENT_COLOR
:
220 // BEWARE! format may be 565
221 return SurfaceFormat::X8R8G8B8_UINT32
;
222 case CAIRO_CONTENT_ALPHA
:
223 return SurfaceFormat::A8
;
226 return SurfaceFormat::B8G8R8A8
;
229 static inline SurfaceFormat
CairoFormatToGfxFormat(cairo_format_t format
) {
231 case CAIRO_FORMAT_ARGB32
:
232 return SurfaceFormat::A8R8G8B8_UINT32
;
233 case CAIRO_FORMAT_RGB24
:
234 return SurfaceFormat::X8R8G8B8_UINT32
;
235 case CAIRO_FORMAT_A8
:
236 return SurfaceFormat::A8
;
237 case CAIRO_FORMAT_RGB16_565
:
238 return SurfaceFormat::R5G6B5_UINT16
;
240 gfxCriticalError() << "Unknown cairo format " << format
;
241 return SurfaceFormat::UNKNOWN
;
245 static inline FontHinting
CairoHintingToGfxHinting(
246 cairo_hint_style_t aHintStyle
) {
247 switch (aHintStyle
) {
248 case CAIRO_HINT_STYLE_NONE
:
249 return FontHinting::NONE
;
250 case CAIRO_HINT_STYLE_SLIGHT
:
251 return FontHinting::LIGHT
;
252 case CAIRO_HINT_STYLE_MEDIUM
:
253 return FontHinting::NORMAL
;
254 case CAIRO_HINT_STYLE_FULL
:
255 return FontHinting::FULL
;
257 return FontHinting::NORMAL
;
261 SurfaceFormat
GfxFormatForCairoSurface(cairo_surface_t
* surface
);
263 static inline void GfxMatrixToCairoMatrix(const Matrix
& mat
,
264 cairo_matrix_t
& retval
) {
265 cairo_matrix_init(&retval
, mat
._11
, mat
._12
, mat
._21
, mat
._22
, mat
._31
,
269 static inline void SetCairoStrokeOptions(cairo_t
* aCtx
,
270 const StrokeOptions
& aStrokeOptions
) {
271 cairo_set_line_width(aCtx
, aStrokeOptions
.mLineWidth
);
273 cairo_set_miter_limit(aCtx
, aStrokeOptions
.mMiterLimit
);
275 if (aStrokeOptions
.mDashPattern
) {
276 // Convert array of floats to array of doubles
277 std::vector
<double> dashes(aStrokeOptions
.mDashLength
);
278 bool nonZero
= false;
279 for (size_t i
= 0; i
< aStrokeOptions
.mDashLength
; ++i
) {
280 if (aStrokeOptions
.mDashPattern
[i
] != 0) {
283 dashes
[i
] = aStrokeOptions
.mDashPattern
[i
];
285 // Avoid all-zero patterns that would trigger the CAIRO_STATUS_INVALID_DASH
286 // context error state.
288 cairo_set_dash(aCtx
, &dashes
[0], aStrokeOptions
.mDashLength
,
289 aStrokeOptions
.mDashOffset
);
293 cairo_set_line_join(aCtx
,
294 GfxLineJoinToCairoLineJoin(aStrokeOptions
.mLineJoin
));
296 cairo_set_line_cap(aCtx
, GfxLineCapToCairoLineCap(aStrokeOptions
.mLineCap
));
299 static inline cairo_fill_rule_t
GfxFillRuleToCairoFillRule(FillRule rule
) {
301 case FillRule::FILL_WINDING
:
302 return CAIRO_FILL_RULE_WINDING
;
303 case FillRule::FILL_EVEN_ODD
:
304 return CAIRO_FILL_RULE_EVEN_ODD
;
307 return CAIRO_FILL_RULE_WINDING
;
310 // RAII class for temporarily changing the cairo matrix transform. It will use
311 // the given matrix transform while it is in scope. When it goes out of scope
312 // it will put the cairo context back the way it was.
314 class CairoTempMatrix
{
316 CairoTempMatrix(cairo_t
* aCtx
, const Matrix
& aMatrix
) : mCtx(aCtx
) {
317 cairo_get_matrix(aCtx
, &mSaveMatrix
);
318 cairo_matrix_t matrix
;
319 GfxMatrixToCairoMatrix(aMatrix
, matrix
);
320 cairo_set_matrix(aCtx
, &matrix
);
323 ~CairoTempMatrix() { cairo_set_matrix(mCtx
, &mSaveMatrix
); }
327 cairo_matrix_t mSaveMatrix
;
331 } // namespace mozilla
333 #endif /* MOZILLA_GFX_HELPERSCAIRO_H_ */