Bug 1890689 accumulate input in LargerReceiverBlockSizeThanDesiredBuffering GTest...
[gecko.git] / gfx / 2d / HelpersCairo.h
blobe3c707944b0f258bdb3b9ac17d97526c1e3aec56
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_
10 #include "2D.h"
11 #include "cairo.h"
12 #include "Logging.h"
14 namespace mozilla {
15 namespace gfx {
17 static inline cairo_operator_t GfxOpToCairoOp(CompositionOp op) {
18 switch (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:
74 break;
77 return CAIRO_OPERATOR_OVER;
80 static inline cairo_antialias_t GfxAntialiasToCairoAntialias(
81 AntialiasMode antialias) {
82 switch (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;
89 default:
90 return CAIRO_ANTIALIAS_DEFAULT;
94 static inline AntialiasMode CairoAntialiasToGfxAntialias(
95 cairo_antialias_t aAntialias) {
96 switch (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;
103 default:
104 return AntialiasMode::DEFAULT;
108 static inline cairo_filter_t GfxSamplingFilterToCairoFilter(
109 SamplingFilter filter) {
110 switch (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;
117 default:
118 MOZ_CRASH("GFX: bad Cairo filter");
121 return CAIRO_FILTER_BILINEAR;
124 static inline cairo_extend_t GfxExtendToCairoExtend(ExtendMode extend) {
125 switch (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) {
142 switch (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;
151 default:
152 gfxCriticalError() << "Unknown image format " << (int)format;
153 return CAIRO_FORMAT_ARGB32;
157 static inline cairo_format_t CairoContentToCairoFormat(
158 cairo_content_t content) {
159 switch (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;
166 default:
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) {
173 switch (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;
181 default:
182 gfxCriticalError() << "Unknown image content format " << (int)format;
183 return CAIRO_CONTENT_COLOR_ALPHA;
187 static inline cairo_line_join_t GfxLineJoinToCairoLineJoin(JoinStyle style) {
188 switch (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) {
203 switch (style) {
204 case CapStyle::BUTT:
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) {
216 switch (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) {
230 switch (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;
239 default:
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;
256 default:
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,
266 mat._32);
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) {
281 nonZero = true;
283 dashes[i] = aStrokeOptions.mDashPattern[i];
285 // Avoid all-zero patterns that would trigger the CAIRO_STATUS_INVALID_DASH
286 // context error state.
287 if (nonZero) {
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) {
300 switch (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 {
315 public:
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); }
325 private:
326 cairo_t* mCtx;
327 cairo_matrix_t mSaveMatrix;
330 } // namespace gfx
331 } // namespace mozilla
333 #endif /* MOZILLA_GFX_HELPERSCAIRO_H_ */