1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/2d/HelpersCairo.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,288 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef MOZILLA_GFX_HELPERSCAIRO_H_ 1.10 +#define MOZILLA_GFX_HELPERSCAIRO_H_ 1.11 + 1.12 +#include "2D.h" 1.13 +#include "cairo.h" 1.14 +#include "Logging.h" 1.15 + 1.16 +namespace mozilla { 1.17 +namespace gfx { 1.18 + 1.19 +static inline cairo_operator_t 1.20 +GfxOpToCairoOp(CompositionOp op) 1.21 +{ 1.22 + switch (op) 1.23 + { 1.24 + case CompositionOp::OP_OVER: 1.25 + return CAIRO_OPERATOR_OVER; 1.26 + case CompositionOp::OP_ADD: 1.27 + return CAIRO_OPERATOR_ADD; 1.28 + case CompositionOp::OP_ATOP: 1.29 + return CAIRO_OPERATOR_ATOP; 1.30 + case CompositionOp::OP_OUT: 1.31 + return CAIRO_OPERATOR_OUT; 1.32 + case CompositionOp::OP_IN: 1.33 + return CAIRO_OPERATOR_IN; 1.34 + case CompositionOp::OP_SOURCE: 1.35 + return CAIRO_OPERATOR_SOURCE; 1.36 + case CompositionOp::OP_DEST_IN: 1.37 + return CAIRO_OPERATOR_DEST_IN; 1.38 + case CompositionOp::OP_DEST_OUT: 1.39 + return CAIRO_OPERATOR_DEST_OUT; 1.40 + case CompositionOp::OP_DEST_OVER: 1.41 + return CAIRO_OPERATOR_DEST_OVER; 1.42 + case CompositionOp::OP_DEST_ATOP: 1.43 + return CAIRO_OPERATOR_DEST_ATOP; 1.44 + case CompositionOp::OP_XOR: 1.45 + return CAIRO_OPERATOR_XOR; 1.46 + case CompositionOp::OP_MULTIPLY: 1.47 + return CAIRO_OPERATOR_MULTIPLY; 1.48 + case CompositionOp::OP_SCREEN: 1.49 + return CAIRO_OPERATOR_SCREEN; 1.50 + case CompositionOp::OP_OVERLAY: 1.51 + return CAIRO_OPERATOR_OVERLAY; 1.52 + case CompositionOp::OP_DARKEN: 1.53 + return CAIRO_OPERATOR_DARKEN; 1.54 + case CompositionOp::OP_LIGHTEN: 1.55 + return CAIRO_OPERATOR_LIGHTEN; 1.56 + case CompositionOp::OP_COLOR_DODGE: 1.57 + return CAIRO_OPERATOR_COLOR_DODGE; 1.58 + case CompositionOp::OP_COLOR_BURN: 1.59 + return CAIRO_OPERATOR_COLOR_BURN; 1.60 + case CompositionOp::OP_HARD_LIGHT: 1.61 + return CAIRO_OPERATOR_HARD_LIGHT; 1.62 + case CompositionOp::OP_SOFT_LIGHT: 1.63 + return CAIRO_OPERATOR_SOFT_LIGHT; 1.64 + case CompositionOp::OP_DIFFERENCE: 1.65 + return CAIRO_OPERATOR_DIFFERENCE; 1.66 + case CompositionOp::OP_EXCLUSION: 1.67 + return CAIRO_OPERATOR_EXCLUSION; 1.68 + case CompositionOp::OP_HUE: 1.69 + return CAIRO_OPERATOR_HSL_HUE; 1.70 + case CompositionOp::OP_SATURATION: 1.71 + return CAIRO_OPERATOR_HSL_SATURATION; 1.72 + case CompositionOp::OP_COLOR: 1.73 + return CAIRO_OPERATOR_HSL_COLOR; 1.74 + case CompositionOp::OP_LUMINOSITY: 1.75 + return CAIRO_OPERATOR_HSL_LUMINOSITY; 1.76 + case CompositionOp::OP_COUNT: 1.77 + break; 1.78 + } 1.79 + 1.80 + return CAIRO_OPERATOR_OVER; 1.81 +} 1.82 + 1.83 +static inline cairo_antialias_t 1.84 +GfxAntialiasToCairoAntialias(AntialiasMode antialias) 1.85 +{ 1.86 + switch (antialias) 1.87 + { 1.88 + case AntialiasMode::NONE: 1.89 + return CAIRO_ANTIALIAS_NONE; 1.90 + case AntialiasMode::GRAY: 1.91 + return CAIRO_ANTIALIAS_GRAY; 1.92 + case AntialiasMode::SUBPIXEL: 1.93 + return CAIRO_ANTIALIAS_SUBPIXEL; 1.94 + case AntialiasMode::DEFAULT: 1.95 + return CAIRO_ANTIALIAS_DEFAULT; 1.96 + } 1.97 + return CAIRO_ANTIALIAS_DEFAULT; 1.98 +} 1.99 + 1.100 +static inline cairo_filter_t 1.101 +GfxFilterToCairoFilter(Filter filter) 1.102 +{ 1.103 + switch (filter) 1.104 + { 1.105 + case Filter::GOOD: 1.106 + return CAIRO_FILTER_GOOD; 1.107 + case Filter::LINEAR: 1.108 + return CAIRO_FILTER_BILINEAR; 1.109 + case Filter::POINT: 1.110 + return CAIRO_FILTER_NEAREST; 1.111 + } 1.112 + 1.113 + return CAIRO_FILTER_BILINEAR; 1.114 +} 1.115 + 1.116 +static inline cairo_extend_t 1.117 +GfxExtendToCairoExtend(ExtendMode extend) 1.118 +{ 1.119 + switch (extend) 1.120 + { 1.121 + case ExtendMode::CLAMP: 1.122 + return CAIRO_EXTEND_PAD; 1.123 + case ExtendMode::REPEAT: 1.124 + return CAIRO_EXTEND_REPEAT; 1.125 + case ExtendMode::REFLECT: 1.126 + return CAIRO_EXTEND_REFLECT; 1.127 + } 1.128 + 1.129 + return CAIRO_EXTEND_PAD; 1.130 +} 1.131 + 1.132 +static inline cairo_format_t 1.133 +GfxFormatToCairoFormat(SurfaceFormat format) 1.134 +{ 1.135 + switch (format) 1.136 + { 1.137 + case SurfaceFormat::B8G8R8A8: 1.138 + return CAIRO_FORMAT_ARGB32; 1.139 + case SurfaceFormat::B8G8R8X8: 1.140 + return CAIRO_FORMAT_RGB24; 1.141 + case SurfaceFormat::A8: 1.142 + return CAIRO_FORMAT_A8; 1.143 + case SurfaceFormat::R5G6B5: 1.144 + return CAIRO_FORMAT_RGB16_565; 1.145 + default: 1.146 + gfxWarning() << "Unknown image format"; 1.147 + return CAIRO_FORMAT_ARGB32; 1.148 + } 1.149 +} 1.150 + 1.151 +static inline cairo_content_t 1.152 +GfxFormatToCairoContent(SurfaceFormat format) 1.153 +{ 1.154 + switch (format) 1.155 + { 1.156 + case SurfaceFormat::B8G8R8A8: 1.157 + return CAIRO_CONTENT_COLOR_ALPHA; 1.158 + case SurfaceFormat::B8G8R8X8: 1.159 + case SurfaceFormat::R5G6B5: //fall through 1.160 + return CAIRO_CONTENT_COLOR; 1.161 + case SurfaceFormat::A8: 1.162 + return CAIRO_CONTENT_ALPHA; 1.163 + default: 1.164 + gfxWarning() << "Unknown image format"; 1.165 + return CAIRO_CONTENT_COLOR_ALPHA; 1.166 + } 1.167 +} 1.168 + 1.169 +static inline cairo_line_join_t 1.170 +GfxLineJoinToCairoLineJoin(JoinStyle style) 1.171 +{ 1.172 + switch (style) 1.173 + { 1.174 + case JoinStyle::BEVEL: 1.175 + return CAIRO_LINE_JOIN_BEVEL; 1.176 + case JoinStyle::ROUND: 1.177 + return CAIRO_LINE_JOIN_ROUND; 1.178 + case JoinStyle::MITER: 1.179 + return CAIRO_LINE_JOIN_MITER; 1.180 + case JoinStyle::MITER_OR_BEVEL: 1.181 + return CAIRO_LINE_JOIN_MITER; 1.182 + } 1.183 + 1.184 + return CAIRO_LINE_JOIN_MITER; 1.185 +} 1.186 + 1.187 +static inline cairo_line_cap_t 1.188 +GfxLineCapToCairoLineCap(CapStyle style) 1.189 +{ 1.190 + switch (style) 1.191 + { 1.192 + case CapStyle::BUTT: 1.193 + return CAIRO_LINE_CAP_BUTT; 1.194 + case CapStyle::ROUND: 1.195 + return CAIRO_LINE_CAP_ROUND; 1.196 + case CapStyle::SQUARE: 1.197 + return CAIRO_LINE_CAP_SQUARE; 1.198 + } 1.199 + 1.200 + return CAIRO_LINE_CAP_BUTT; 1.201 +} 1.202 + 1.203 +static inline SurfaceFormat 1.204 +CairoContentToGfxFormat(cairo_content_t content) 1.205 +{ 1.206 + switch (content) 1.207 + { 1.208 + case CAIRO_CONTENT_COLOR_ALPHA: 1.209 + return SurfaceFormat::B8G8R8A8; 1.210 + case CAIRO_CONTENT_COLOR: 1.211 + // BEWARE! format may be 565 1.212 + return SurfaceFormat::B8G8R8X8; 1.213 + case CAIRO_CONTENT_ALPHA: 1.214 + return SurfaceFormat::A8; 1.215 + } 1.216 + 1.217 + return SurfaceFormat::B8G8R8A8; 1.218 +} 1.219 + 1.220 +static inline void 1.221 +GfxMatrixToCairoMatrix(const Matrix& mat, cairo_matrix_t& retval) 1.222 +{ 1.223 + cairo_matrix_init(&retval, mat._11, mat._12, mat._21, mat._22, mat._31, mat._32); 1.224 +} 1.225 + 1.226 +static inline void 1.227 +SetCairoStrokeOptions(cairo_t* aCtx, const StrokeOptions& aStrokeOptions) 1.228 +{ 1.229 + cairo_set_line_width(aCtx, aStrokeOptions.mLineWidth); 1.230 + 1.231 + cairo_set_miter_limit(aCtx, aStrokeOptions.mMiterLimit); 1.232 + 1.233 + if (aStrokeOptions.mDashPattern) { 1.234 + // Convert array of floats to array of doubles 1.235 + std::vector<double> dashes(aStrokeOptions.mDashLength); 1.236 + for (size_t i = 0; i < aStrokeOptions.mDashLength; ++i) { 1.237 + dashes[i] = aStrokeOptions.mDashPattern[i]; 1.238 + } 1.239 + cairo_set_dash(aCtx, &dashes[0], aStrokeOptions.mDashLength, 1.240 + aStrokeOptions.mDashOffset); 1.241 + } 1.242 + 1.243 + cairo_set_line_join(aCtx, GfxLineJoinToCairoLineJoin(aStrokeOptions.mLineJoin)); 1.244 + 1.245 + cairo_set_line_cap(aCtx, GfxLineCapToCairoLineCap(aStrokeOptions.mLineCap)); 1.246 +} 1.247 + 1.248 +static inline cairo_fill_rule_t 1.249 +GfxFillRuleToCairoFillRule(FillRule rule) 1.250 +{ 1.251 + switch (rule) 1.252 + { 1.253 + case FillRule::FILL_WINDING: 1.254 + return CAIRO_FILL_RULE_WINDING; 1.255 + case FillRule::FILL_EVEN_ODD: 1.256 + return CAIRO_FILL_RULE_EVEN_ODD; 1.257 + } 1.258 + 1.259 + return CAIRO_FILL_RULE_WINDING; 1.260 +} 1.261 + 1.262 +// RAII class for temporarily changing the cairo matrix transform. It will use 1.263 +// the given matrix transform while it is in scope. When it goes out of scope 1.264 +// it will put the cairo context back the way it was. 1.265 + 1.266 +class CairoTempMatrix 1.267 +{ 1.268 +public: 1.269 + CairoTempMatrix(cairo_t* aCtx, const Matrix& aMatrix) 1.270 + : mCtx(aCtx) 1.271 + { 1.272 + cairo_get_matrix(aCtx, &mSaveMatrix); 1.273 + cairo_matrix_t matrix; 1.274 + GfxMatrixToCairoMatrix(aMatrix, matrix); 1.275 + cairo_set_matrix(aCtx, &matrix); 1.276 + } 1.277 + 1.278 + ~CairoTempMatrix() 1.279 + { 1.280 + cairo_set_matrix(mCtx, &mSaveMatrix); 1.281 + } 1.282 + 1.283 +private: 1.284 + cairo_t* mCtx; 1.285 + cairo_matrix_t mSaveMatrix; 1.286 +}; 1.287 + 1.288 +} 1.289 +} 1.290 + 1.291 +#endif /* MOZILLA_GFX_HELPERSCAIRO_H_ */