michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef MOZILLA_GFX_HELPERSSKIA_H_ michael@0: #define MOZILLA_GFX_HELPERSSKIA_H_ michael@0: michael@0: #include "2D.h" michael@0: #include "skia/SkCanvas.h" michael@0: #include "skia/SkDashPathEffect.h" michael@0: #include "skia/SkShader.h" michael@0: #ifdef USE_SKIA_GPU michael@0: #include "skia/GrTypes.h" michael@0: #endif michael@0: #include "mozilla/Assertions.h" michael@0: #include michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: michael@0: static inline SkBitmap::Config michael@0: GfxFormatToSkiaConfig(SurfaceFormat format) michael@0: { michael@0: switch (format) michael@0: { michael@0: case SurfaceFormat::B8G8R8A8: michael@0: return SkBitmap::kARGB_8888_Config; michael@0: case SurfaceFormat::B8G8R8X8: michael@0: // We probably need to do something here. michael@0: return SkBitmap::kARGB_8888_Config; michael@0: case SurfaceFormat::R5G6B5: michael@0: return SkBitmap::kRGB_565_Config; michael@0: case SurfaceFormat::A8: michael@0: return SkBitmap::kA8_Config; michael@0: default: michael@0: return SkBitmap::kARGB_8888_Config; michael@0: } michael@0: } michael@0: michael@0: static inline SkColorType michael@0: GfxFormatToSkiaColorType(SurfaceFormat format) michael@0: { michael@0: switch (format) michael@0: { michael@0: case SurfaceFormat::B8G8R8A8: michael@0: return kBGRA_8888_SkColorType; michael@0: case SurfaceFormat::B8G8R8X8: michael@0: // We probably need to do something here. michael@0: return kBGRA_8888_SkColorType; michael@0: case SurfaceFormat::R5G6B5: michael@0: return kRGB_565_SkColorType; michael@0: case SurfaceFormat::A8: michael@0: return kAlpha_8_SkColorType; michael@0: default: michael@0: return kRGBA_8888_SkColorType; michael@0: } michael@0: } michael@0: michael@0: static inline SurfaceFormat michael@0: SkiaConfigToGfxFormat(SkBitmap::Config config) michael@0: { michael@0: switch (config) michael@0: { michael@0: case SkBitmap::kARGB_8888_Config: michael@0: return SurfaceFormat::B8G8R8A8; michael@0: case SkBitmap::kRGB_565_Config: michael@0: return SurfaceFormat::R5G6B5; michael@0: case SkBitmap::kA8_Config: michael@0: return SurfaceFormat::A8; michael@0: default: michael@0: return SurfaceFormat::B8G8R8A8; michael@0: } michael@0: } michael@0: michael@0: #ifdef USE_SKIA_GPU michael@0: static inline GrPixelConfig michael@0: GfxFormatToGrConfig(SurfaceFormat format) michael@0: { michael@0: switch (format) michael@0: { michael@0: case SurfaceFormat::B8G8R8A8: michael@0: return kBGRA_8888_GrPixelConfig; michael@0: case SurfaceFormat::B8G8R8X8: michael@0: // We probably need to do something here. michael@0: return kBGRA_8888_GrPixelConfig; michael@0: case SurfaceFormat::R5G6B5: michael@0: return kRGB_565_GrPixelConfig; michael@0: case SurfaceFormat::A8: michael@0: return kAlpha_8_GrPixelConfig; michael@0: default: michael@0: return kRGBA_8888_GrPixelConfig; michael@0: } michael@0: michael@0: } michael@0: #endif michael@0: static inline void michael@0: GfxMatrixToSkiaMatrix(const Matrix& mat, SkMatrix& retval) michael@0: { michael@0: retval.setAll(SkFloatToScalar(mat._11), SkFloatToScalar(mat._21), SkFloatToScalar(mat._31), michael@0: SkFloatToScalar(mat._12), SkFloatToScalar(mat._22), SkFloatToScalar(mat._32), michael@0: 0, 0, SK_Scalar1); michael@0: } michael@0: michael@0: static inline SkPaint::Cap michael@0: CapStyleToSkiaCap(CapStyle aCap) michael@0: { michael@0: switch (aCap) michael@0: { michael@0: case CapStyle::BUTT: michael@0: return SkPaint::kButt_Cap; michael@0: case CapStyle::ROUND: michael@0: return SkPaint::kRound_Cap; michael@0: case CapStyle::SQUARE: michael@0: return SkPaint::kSquare_Cap; michael@0: } michael@0: return SkPaint::kDefault_Cap; michael@0: } michael@0: michael@0: static inline SkPaint::Join michael@0: JoinStyleToSkiaJoin(JoinStyle aJoin) michael@0: { michael@0: switch (aJoin) michael@0: { michael@0: case JoinStyle::BEVEL: michael@0: return SkPaint::kBevel_Join; michael@0: case JoinStyle::ROUND: michael@0: return SkPaint::kRound_Join; michael@0: case JoinStyle::MITER: michael@0: case JoinStyle::MITER_OR_BEVEL: michael@0: return SkPaint::kMiter_Join; michael@0: } michael@0: return SkPaint::kDefault_Join; michael@0: } michael@0: michael@0: static inline bool michael@0: StrokeOptionsToPaint(SkPaint& aPaint, const StrokeOptions &aOptions) michael@0: { michael@0: // Skia renders 0 width strokes with a width of 1 (and in black), michael@0: // so we should just skip the draw call entirely. michael@0: if (!aOptions.mLineWidth) { michael@0: return false; michael@0: } michael@0: aPaint.setStrokeWidth(SkFloatToScalar(aOptions.mLineWidth)); michael@0: aPaint.setStrokeMiter(SkFloatToScalar(aOptions.mMiterLimit)); michael@0: aPaint.setStrokeCap(CapStyleToSkiaCap(aOptions.mLineCap)); michael@0: aPaint.setStrokeJoin(JoinStyleToSkiaJoin(aOptions.mLineJoin)); michael@0: michael@0: if (aOptions.mDashLength > 0) { michael@0: // Skia only supports dash arrays that are multiples of 2. michael@0: uint32_t dashCount; michael@0: michael@0: if (aOptions.mDashLength % 2 == 0) { michael@0: dashCount = aOptions.mDashLength; michael@0: } else { michael@0: dashCount = aOptions.mDashLength * 2; michael@0: } michael@0: michael@0: std::vector pattern; michael@0: pattern.resize(dashCount); michael@0: michael@0: for (uint32_t i = 0; i < dashCount; i++) { michael@0: pattern[i] = SkFloatToScalar(aOptions.mDashPattern[i % aOptions.mDashLength]); michael@0: } michael@0: michael@0: SkDashPathEffect* dash = SkDashPathEffect::Create(&pattern.front(), michael@0: dashCount, michael@0: SkFloatToScalar(aOptions.mDashOffset)); michael@0: SkSafeUnref(aPaint.setPathEffect(dash)); michael@0: } michael@0: michael@0: aPaint.setStyle(SkPaint::kStroke_Style); michael@0: return true; michael@0: } michael@0: michael@0: static inline SkXfermode::Mode michael@0: GfxOpToSkiaOp(CompositionOp op) michael@0: { michael@0: switch (op) michael@0: { michael@0: case CompositionOp::OP_OVER: michael@0: return SkXfermode::kSrcOver_Mode; michael@0: case CompositionOp::OP_ADD: michael@0: return SkXfermode::kPlus_Mode; michael@0: case CompositionOp::OP_ATOP: michael@0: return SkXfermode::kSrcATop_Mode; michael@0: case CompositionOp::OP_OUT: michael@0: return SkXfermode::kSrcOut_Mode; michael@0: case CompositionOp::OP_IN: michael@0: return SkXfermode::kSrcIn_Mode; michael@0: case CompositionOp::OP_SOURCE: michael@0: return SkXfermode::kSrc_Mode; michael@0: case CompositionOp::OP_DEST_IN: michael@0: return SkXfermode::kDstIn_Mode; michael@0: case CompositionOp::OP_DEST_OUT: michael@0: return SkXfermode::kDstOut_Mode; michael@0: case CompositionOp::OP_DEST_OVER: michael@0: return SkXfermode::kDstOver_Mode; michael@0: case CompositionOp::OP_DEST_ATOP: michael@0: return SkXfermode::kDstATop_Mode; michael@0: case CompositionOp::OP_XOR: michael@0: return SkXfermode::kXor_Mode; michael@0: case CompositionOp::OP_MULTIPLY: michael@0: return SkXfermode::kMultiply_Mode; michael@0: case CompositionOp::OP_SCREEN: michael@0: return SkXfermode::kScreen_Mode; michael@0: case CompositionOp::OP_OVERLAY: michael@0: return SkXfermode::kOverlay_Mode; michael@0: case CompositionOp::OP_DARKEN: michael@0: return SkXfermode::kDarken_Mode; michael@0: case CompositionOp::OP_LIGHTEN: michael@0: return SkXfermode::kLighten_Mode; michael@0: case CompositionOp::OP_COLOR_DODGE: michael@0: return SkXfermode::kColorDodge_Mode; michael@0: case CompositionOp::OP_COLOR_BURN: michael@0: return SkXfermode::kColorBurn_Mode; michael@0: case CompositionOp::OP_HARD_LIGHT: michael@0: return SkXfermode::kHardLight_Mode; michael@0: case CompositionOp::OP_SOFT_LIGHT: michael@0: return SkXfermode::kSoftLight_Mode; michael@0: case CompositionOp::OP_DIFFERENCE: michael@0: return SkXfermode::kDifference_Mode; michael@0: case CompositionOp::OP_EXCLUSION: michael@0: return SkXfermode::kExclusion_Mode; michael@0: case CompositionOp::OP_HUE: michael@0: return SkXfermode::kHue_Mode; michael@0: case CompositionOp::OP_SATURATION: michael@0: return SkXfermode::kSaturation_Mode; michael@0: case CompositionOp::OP_COLOR: michael@0: return SkXfermode::kColor_Mode; michael@0: case CompositionOp::OP_LUMINOSITY: michael@0: return SkXfermode::kLuminosity_Mode; michael@0: default: michael@0: return SkXfermode::kSrcOver_Mode; michael@0: } michael@0: } michael@0: michael@0: static inline SkColor ColorToSkColor(const Color &color, Float aAlpha) michael@0: { michael@0: //XXX: do a better job converting to int michael@0: return SkColorSetARGB(U8CPU(color.a*aAlpha*255.0), U8CPU(color.r*255.0), michael@0: U8CPU(color.g*255.0), U8CPU(color.b*255.0)); michael@0: } michael@0: michael@0: static inline SkRect michael@0: RectToSkRect(const Rect& aRect) michael@0: { michael@0: return SkRect::MakeXYWH(SkFloatToScalar(aRect.x), SkFloatToScalar(aRect.y), michael@0: SkFloatToScalar(aRect.width), SkFloatToScalar(aRect.height)); michael@0: } michael@0: michael@0: static inline SkRect michael@0: IntRectToSkRect(const IntRect& aRect) michael@0: { michael@0: return SkRect::MakeXYWH(SkIntToScalar(aRect.x), SkIntToScalar(aRect.y), michael@0: SkIntToScalar(aRect.width), SkIntToScalar(aRect.height)); michael@0: } michael@0: michael@0: static inline SkIRect michael@0: RectToSkIRect(const Rect& aRect) michael@0: { michael@0: return SkIRect::MakeXYWH(int32_t(aRect.x), int32_t(aRect.y), michael@0: int32_t(aRect.width), int32_t(aRect.height)); michael@0: } michael@0: michael@0: static inline SkIRect michael@0: IntRectToSkIRect(const IntRect& aRect) michael@0: { michael@0: return SkIRect::MakeXYWH(aRect.x, aRect.y, aRect.width, aRect.height); michael@0: } michael@0: michael@0: static inline Point michael@0: SkPointToPoint(const SkPoint &aPoint) michael@0: { michael@0: return Point(SkScalarToFloat(aPoint.x()), SkScalarToFloat(aPoint.y())); michael@0: } michael@0: michael@0: static inline Rect michael@0: SkRectToRect(const SkRect &aRect) michael@0: { michael@0: return Rect(SkScalarToFloat(aRect.x()), SkScalarToFloat(aRect.y()), michael@0: SkScalarToFloat(aRect.width()), SkScalarToFloat(aRect.height())); michael@0: } michael@0: michael@0: static inline SkShader::TileMode michael@0: ExtendModeToTileMode(ExtendMode aMode) michael@0: { michael@0: switch (aMode) michael@0: { michael@0: case ExtendMode::CLAMP: michael@0: return SkShader::kClamp_TileMode; michael@0: case ExtendMode::REPEAT: michael@0: return SkShader::kRepeat_TileMode; michael@0: case ExtendMode::REFLECT: michael@0: return SkShader::kMirror_TileMode; michael@0: } michael@0: return SkShader::kClamp_TileMode; michael@0: } michael@0: michael@0: } michael@0: } michael@0: michael@0: #endif /* MOZILLA_GFX_HELPERSSKIA_H_ */