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_OVER
:
20 return CAIRO_OPERATOR_OVER
;
21 case CompositionOp::OP_ADD
:
22 return CAIRO_OPERATOR_ADD
;
23 case CompositionOp::OP_ATOP
:
24 return CAIRO_OPERATOR_ATOP
;
25 case CompositionOp::OP_OUT
:
26 return CAIRO_OPERATOR_OUT
;
27 case CompositionOp::OP_IN
:
28 return CAIRO_OPERATOR_IN
;
29 case CompositionOp::OP_SOURCE
:
30 return CAIRO_OPERATOR_SOURCE
;
31 case CompositionOp::OP_DEST_IN
:
32 return CAIRO_OPERATOR_DEST_IN
;
33 case CompositionOp::OP_DEST_OUT
:
34 return CAIRO_OPERATOR_DEST_OUT
;
35 case CompositionOp::OP_DEST_OVER
:
36 return CAIRO_OPERATOR_DEST_OVER
;
37 case CompositionOp::OP_DEST_ATOP
:
38 return CAIRO_OPERATOR_DEST_ATOP
;
39 case CompositionOp::OP_XOR
:
40 return CAIRO_OPERATOR_XOR
;
41 case CompositionOp::OP_MULTIPLY
:
42 return CAIRO_OPERATOR_MULTIPLY
;
43 case CompositionOp::OP_SCREEN
:
44 return CAIRO_OPERATOR_SCREEN
;
45 case CompositionOp::OP_OVERLAY
:
46 return CAIRO_OPERATOR_OVERLAY
;
47 case CompositionOp::OP_DARKEN
:
48 return CAIRO_OPERATOR_DARKEN
;
49 case CompositionOp::OP_LIGHTEN
:
50 return CAIRO_OPERATOR_LIGHTEN
;
51 case CompositionOp::OP_COLOR_DODGE
:
52 return CAIRO_OPERATOR_COLOR_DODGE
;
53 case CompositionOp::OP_COLOR_BURN
:
54 return CAIRO_OPERATOR_COLOR_BURN
;
55 case CompositionOp::OP_HARD_LIGHT
:
56 return CAIRO_OPERATOR_HARD_LIGHT
;
57 case CompositionOp::OP_SOFT_LIGHT
:
58 return CAIRO_OPERATOR_SOFT_LIGHT
;
59 case CompositionOp::OP_DIFFERENCE
:
60 return CAIRO_OPERATOR_DIFFERENCE
;
61 case CompositionOp::OP_EXCLUSION
:
62 return CAIRO_OPERATOR_EXCLUSION
;
63 case CompositionOp::OP_HUE
:
64 return CAIRO_OPERATOR_HSL_HUE
;
65 case CompositionOp::OP_SATURATION
:
66 return CAIRO_OPERATOR_HSL_SATURATION
;
67 case CompositionOp::OP_COLOR
:
68 return CAIRO_OPERATOR_HSL_COLOR
;
69 case CompositionOp::OP_LUMINOSITY
:
70 return CAIRO_OPERATOR_HSL_LUMINOSITY
;
71 case CompositionOp::OP_COUNT
:
75 return CAIRO_OPERATOR_OVER
;
78 static inline cairo_antialias_t
GfxAntialiasToCairoAntialias(
79 AntialiasMode antialias
) {
81 case AntialiasMode::NONE
:
82 return CAIRO_ANTIALIAS_NONE
;
83 case AntialiasMode::GRAY
:
84 return CAIRO_ANTIALIAS_GRAY
;
85 case AntialiasMode::SUBPIXEL
:
86 return CAIRO_ANTIALIAS_SUBPIXEL
;
88 return CAIRO_ANTIALIAS_DEFAULT
;
92 static inline AntialiasMode
CairoAntialiasToGfxAntialias(
93 cairo_antialias_t aAntialias
) {
95 case CAIRO_ANTIALIAS_NONE
:
96 return AntialiasMode::NONE
;
97 case CAIRO_ANTIALIAS_GRAY
:
98 return AntialiasMode::GRAY
;
99 case CAIRO_ANTIALIAS_SUBPIXEL
:
100 return AntialiasMode::SUBPIXEL
;
102 return AntialiasMode::DEFAULT
;
106 static inline cairo_filter_t
GfxSamplingFilterToCairoFilter(
107 SamplingFilter filter
) {
109 case SamplingFilter::GOOD
:
110 return CAIRO_FILTER_GOOD
;
111 case SamplingFilter::LINEAR
:
112 return CAIRO_FILTER_BILINEAR
;
113 case SamplingFilter::POINT
:
114 return CAIRO_FILTER_NEAREST
;
116 MOZ_CRASH("GFX: bad Cairo filter");
119 return CAIRO_FILTER_BILINEAR
;
122 static inline cairo_extend_t
GfxExtendToCairoExtend(ExtendMode extend
) {
124 case ExtendMode::CLAMP
:
125 return CAIRO_EXTEND_PAD
;
126 // Cairo doesn't support tiling in only 1 direction,
127 // So we have to fallback and tile in both.
128 case ExtendMode::REPEAT_X
:
129 case ExtendMode::REPEAT_Y
:
130 case ExtendMode::REPEAT
:
131 return CAIRO_EXTEND_REPEAT
;
132 case ExtendMode::REFLECT
:
133 return CAIRO_EXTEND_REFLECT
;
136 return CAIRO_EXTEND_PAD
;
139 static inline cairo_format_t
GfxFormatToCairoFormat(SurfaceFormat format
) {
141 case SurfaceFormat::A8R8G8B8_UINT32
:
142 return CAIRO_FORMAT_ARGB32
;
143 case SurfaceFormat::X8R8G8B8_UINT32
:
144 return CAIRO_FORMAT_RGB24
;
145 case SurfaceFormat::A8
:
146 return CAIRO_FORMAT_A8
;
147 case SurfaceFormat::R5G6B5_UINT16
:
148 return CAIRO_FORMAT_RGB16_565
;
150 gfxCriticalError() << "Unknown image format " << (int)format
;
151 return CAIRO_FORMAT_ARGB32
;
155 static inline cairo_format_t
CairoContentToCairoFormat(
156 cairo_content_t content
) {
158 case CAIRO_CONTENT_COLOR
:
159 return CAIRO_FORMAT_RGB24
;
160 case CAIRO_CONTENT_ALPHA
:
161 return CAIRO_FORMAT_A8
;
162 case CAIRO_CONTENT_COLOR_ALPHA
:
163 return CAIRO_FORMAT_ARGB32
;
165 gfxCriticalError() << "Unknown cairo content type " << (int)content
;
166 return CAIRO_FORMAT_A8
; // least likely to cause OOB reads
170 static inline cairo_content_t
GfxFormatToCairoContent(SurfaceFormat format
) {
172 case SurfaceFormat::A8R8G8B8_UINT32
:
173 return CAIRO_CONTENT_COLOR_ALPHA
;
174 case SurfaceFormat::X8R8G8B8_UINT32
:
175 case SurfaceFormat::R5G6B5_UINT16
: // fall through
176 return CAIRO_CONTENT_COLOR
;
177 case SurfaceFormat::A8
:
178 return CAIRO_CONTENT_ALPHA
;
180 gfxCriticalError() << "Unknown image content format " << (int)format
;
181 return CAIRO_CONTENT_COLOR_ALPHA
;
185 static inline cairo_line_join_t
GfxLineJoinToCairoLineJoin(JoinStyle style
) {
187 case JoinStyle::BEVEL
:
188 return CAIRO_LINE_JOIN_BEVEL
;
189 case JoinStyle::ROUND
:
190 return CAIRO_LINE_JOIN_ROUND
;
191 case JoinStyle::MITER
:
192 return CAIRO_LINE_JOIN_MITER
;
193 case JoinStyle::MITER_OR_BEVEL
:
194 return CAIRO_LINE_JOIN_MITER
;
197 return CAIRO_LINE_JOIN_MITER
;
200 static inline cairo_line_cap_t
GfxLineCapToCairoLineCap(CapStyle style
) {
203 return CAIRO_LINE_CAP_BUTT
;
204 case CapStyle::ROUND
:
205 return CAIRO_LINE_CAP_ROUND
;
206 case CapStyle::SQUARE
:
207 return CAIRO_LINE_CAP_SQUARE
;
210 return CAIRO_LINE_CAP_BUTT
;
213 static inline SurfaceFormat
CairoContentToGfxFormat(cairo_content_t content
) {
215 case CAIRO_CONTENT_COLOR_ALPHA
:
216 return SurfaceFormat::A8R8G8B8_UINT32
;
217 case CAIRO_CONTENT_COLOR
:
218 // BEWARE! format may be 565
219 return SurfaceFormat::X8R8G8B8_UINT32
;
220 case CAIRO_CONTENT_ALPHA
:
221 return SurfaceFormat::A8
;
224 return SurfaceFormat::B8G8R8A8
;
227 static inline SurfaceFormat
CairoFormatToGfxFormat(cairo_format_t format
) {
229 case CAIRO_FORMAT_ARGB32
:
230 return SurfaceFormat::A8R8G8B8_UINT32
;
231 case CAIRO_FORMAT_RGB24
:
232 return SurfaceFormat::X8R8G8B8_UINT32
;
233 case CAIRO_FORMAT_A8
:
234 return SurfaceFormat::A8
;
235 case CAIRO_FORMAT_RGB16_565
:
236 return SurfaceFormat::R5G6B5_UINT16
;
238 gfxCriticalError() << "Unknown cairo format " << format
;
239 return SurfaceFormat::UNKNOWN
;
243 static inline FontHinting
CairoHintingToGfxHinting(
244 cairo_hint_style_t aHintStyle
) {
245 switch (aHintStyle
) {
246 case CAIRO_HINT_STYLE_NONE
:
247 return FontHinting::NONE
;
248 case CAIRO_HINT_STYLE_SLIGHT
:
249 return FontHinting::LIGHT
;
250 case CAIRO_HINT_STYLE_MEDIUM
:
251 return FontHinting::NORMAL
;
252 case CAIRO_HINT_STYLE_FULL
:
253 return FontHinting::FULL
;
255 return FontHinting::NORMAL
;
259 SurfaceFormat
GfxFormatForCairoSurface(cairo_surface_t
* surface
);
261 static inline void GfxMatrixToCairoMatrix(const Matrix
& mat
,
262 cairo_matrix_t
& retval
) {
263 cairo_matrix_init(&retval
, mat
._11
, mat
._12
, mat
._21
, mat
._22
, mat
._31
,
267 static inline void SetCairoStrokeOptions(cairo_t
* aCtx
,
268 const StrokeOptions
& aStrokeOptions
) {
269 cairo_set_line_width(aCtx
, aStrokeOptions
.mLineWidth
);
271 cairo_set_miter_limit(aCtx
, aStrokeOptions
.mMiterLimit
);
273 if (aStrokeOptions
.mDashPattern
) {
274 // Convert array of floats to array of doubles
275 std::vector
<double> dashes(aStrokeOptions
.mDashLength
);
276 bool nonZero
= false;
277 for (size_t i
= 0; i
< aStrokeOptions
.mDashLength
; ++i
) {
278 if (aStrokeOptions
.mDashPattern
[i
] != 0) {
281 dashes
[i
] = aStrokeOptions
.mDashPattern
[i
];
283 // Avoid all-zero patterns that would trigger the CAIRO_STATUS_INVALID_DASH
284 // context error state.
286 cairo_set_dash(aCtx
, &dashes
[0], aStrokeOptions
.mDashLength
,
287 aStrokeOptions
.mDashOffset
);
291 cairo_set_line_join(aCtx
,
292 GfxLineJoinToCairoLineJoin(aStrokeOptions
.mLineJoin
));
294 cairo_set_line_cap(aCtx
, GfxLineCapToCairoLineCap(aStrokeOptions
.mLineCap
));
297 static inline cairo_fill_rule_t
GfxFillRuleToCairoFillRule(FillRule rule
) {
299 case FillRule::FILL_WINDING
:
300 return CAIRO_FILL_RULE_WINDING
;
301 case FillRule::FILL_EVEN_ODD
:
302 return CAIRO_FILL_RULE_EVEN_ODD
;
305 return CAIRO_FILL_RULE_WINDING
;
308 // RAII class for temporarily changing the cairo matrix transform. It will use
309 // the given matrix transform while it is in scope. When it goes out of scope
310 // it will put the cairo context back the way it was.
312 class CairoTempMatrix
{
314 CairoTempMatrix(cairo_t
* aCtx
, const Matrix
& aMatrix
) : mCtx(aCtx
) {
315 cairo_get_matrix(aCtx
, &mSaveMatrix
);
316 cairo_matrix_t matrix
;
317 GfxMatrixToCairoMatrix(aMatrix
, matrix
);
318 cairo_set_matrix(aCtx
, &matrix
);
321 ~CairoTempMatrix() { cairo_set_matrix(mCtx
, &mSaveMatrix
); }
325 cairo_matrix_t mSaveMatrix
;
329 } // namespace mozilla
331 #endif /* MOZILLA_GFX_HELPERSCAIRO_H_ */