1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/2d/DrawTargetSkia.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,839 @@ 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 +#include "DrawTargetSkia.h" 1.10 +#include "SourceSurfaceSkia.h" 1.11 +#include "ScaledFontBase.h" 1.12 +#include "ScaledFontCairo.h" 1.13 +#include "skia/SkGpuDevice.h" 1.14 +#include "skia/SkBitmapDevice.h" 1.15 +#include "FilterNodeSoftware.h" 1.16 + 1.17 +#ifdef USE_SKIA_GPU 1.18 +#include "skia/SkGpuDevice.h" 1.19 +#include "skia/GrGLInterface.h" 1.20 +#endif 1.21 + 1.22 +#include "skia/SkTypeface.h" 1.23 +#include "skia/SkGradientShader.h" 1.24 +#include "skia/SkBlurDrawLooper.h" 1.25 +#include "skia/SkBlurMaskFilter.h" 1.26 +#include "skia/SkColorFilter.h" 1.27 +#include "skia/SkDropShadowImageFilter.h" 1.28 +#include "skia/SkLayerRasterizer.h" 1.29 +#include "skia/SkLayerDrawLooper.h" 1.30 +#include "skia/SkDashPathEffect.h" 1.31 +#include "Logging.h" 1.32 +#include "HelpersSkia.h" 1.33 +#include "Tools.h" 1.34 +#include "DataSurfaceHelpers.h" 1.35 +#include <algorithm> 1.36 + 1.37 +namespace mozilla { 1.38 +namespace gfx { 1.39 + 1.40 +class GradientStopsSkia : public GradientStops 1.41 +{ 1.42 +public: 1.43 + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsSkia) 1.44 + GradientStopsSkia(const std::vector<GradientStop>& aStops, uint32_t aNumStops, ExtendMode aExtendMode) 1.45 + : mCount(aNumStops) 1.46 + , mExtendMode(aExtendMode) 1.47 + { 1.48 + if (mCount == 0) { 1.49 + return; 1.50 + } 1.51 + 1.52 + // Skia gradients always require a stop at 0.0 and 1.0, insert these if 1.53 + // we don't have them. 1.54 + uint32_t shift = 0; 1.55 + if (aStops[0].offset != 0) { 1.56 + mCount++; 1.57 + shift = 1; 1.58 + } 1.59 + if (aStops[aNumStops-1].offset != 1) { 1.60 + mCount++; 1.61 + } 1.62 + mColors.resize(mCount); 1.63 + mPositions.resize(mCount); 1.64 + if (aStops[0].offset != 0) { 1.65 + mColors[0] = ColorToSkColor(aStops[0].color, 1.0); 1.66 + mPositions[0] = 0; 1.67 + } 1.68 + for (uint32_t i = 0; i < aNumStops; i++) { 1.69 + mColors[i + shift] = ColorToSkColor(aStops[i].color, 1.0); 1.70 + mPositions[i + shift] = SkFloatToScalar(aStops[i].offset); 1.71 + } 1.72 + if (aStops[aNumStops-1].offset != 1) { 1.73 + mColors[mCount-1] = ColorToSkColor(aStops[aNumStops-1].color, 1.0); 1.74 + mPositions[mCount-1] = SK_Scalar1; 1.75 + } 1.76 + } 1.77 + 1.78 + BackendType GetBackendType() const { return BackendType::SKIA; } 1.79 + 1.80 + std::vector<SkColor> mColors; 1.81 + std::vector<SkScalar> mPositions; 1.82 + int mCount; 1.83 + ExtendMode mExtendMode; 1.84 +}; 1.85 + 1.86 +/** 1.87 + * When constructing a temporary SkBitmap via GetBitmapForSurface, we may also 1.88 + * have to construct a temporary DataSourceSurface, which must live as long as 1.89 + * the SkBitmap. So we return a pair of the SkBitmap and the (optional) 1.90 + * temporary surface. 1.91 + */ 1.92 +struct TempBitmap 1.93 +{ 1.94 + SkBitmap mBitmap; 1.95 + RefPtr<SourceSurface> mTmpSurface; 1.96 +}; 1.97 + 1.98 +static TempBitmap 1.99 +GetBitmapForSurface(SourceSurface* aSurface) 1.100 +{ 1.101 + TempBitmap result; 1.102 + 1.103 + if (aSurface->GetType() == SurfaceType::SKIA) { 1.104 + result.mBitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap(); 1.105 + return result; 1.106 + } 1.107 + 1.108 + RefPtr<DataSourceSurface> surf = aSurface->GetDataSurface(); 1.109 + if (!surf) { 1.110 + MOZ_CRASH("Non-skia SourceSurfaces need to be DataSourceSurfaces"); 1.111 + } 1.112 + 1.113 + result.mBitmap.setConfig(GfxFormatToSkiaConfig(surf->GetFormat()), 1.114 + surf->GetSize().width, surf->GetSize().height, 1.115 + surf->Stride()); 1.116 + result.mBitmap.setPixels(surf->GetData()); 1.117 + result.mTmpSurface = surf.forget(); 1.118 + return result; 1.119 +} 1.120 + 1.121 +DrawTargetSkia::DrawTargetSkia() 1.122 + : mTexture(0), mSnapshot(nullptr) 1.123 +{ 1.124 +} 1.125 + 1.126 +DrawTargetSkia::~DrawTargetSkia() 1.127 +{ 1.128 +} 1.129 + 1.130 +TemporaryRef<SourceSurface> 1.131 +DrawTargetSkia::Snapshot() 1.132 +{ 1.133 + RefPtr<SourceSurfaceSkia> snapshot = mSnapshot; 1.134 + if (!snapshot) { 1.135 + snapshot = new SourceSurfaceSkia(); 1.136 + mSnapshot = snapshot; 1.137 + if (!snapshot->InitFromCanvas(mCanvas.get(), mFormat, this)) 1.138 + return nullptr; 1.139 + } 1.140 + 1.141 + return snapshot; 1.142 +} 1.143 + 1.144 +static void 1.145 +SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, TempBitmap& aTmpBitmap, 1.146 + Float aAlpha = 1.0) 1.147 +{ 1.148 + switch (aPattern.GetType()) { 1.149 + case PatternType::COLOR: { 1.150 + Color color = static_cast<const ColorPattern&>(aPattern).mColor; 1.151 + aPaint.setColor(ColorToSkColor(color, aAlpha)); 1.152 + break; 1.153 + } 1.154 + case PatternType::LINEAR_GRADIENT: { 1.155 + const LinearGradientPattern& pat = static_cast<const LinearGradientPattern&>(aPattern); 1.156 + GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get()); 1.157 + SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode); 1.158 + 1.159 + if (stops->mCount >= 2) { 1.160 + SkPoint points[2]; 1.161 + points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x), SkFloatToScalar(pat.mBegin.y)); 1.162 + points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x), SkFloatToScalar(pat.mEnd.y)); 1.163 + 1.164 + SkShader* shader = SkGradientShader::CreateLinear(points, 1.165 + &stops->mColors.front(), 1.166 + &stops->mPositions.front(), 1.167 + stops->mCount, 1.168 + mode); 1.169 + 1.170 + if (shader) { 1.171 + SkMatrix mat; 1.172 + GfxMatrixToSkiaMatrix(pat.mMatrix, mat); 1.173 + shader->setLocalMatrix(mat); 1.174 + SkSafeUnref(aPaint.setShader(shader)); 1.175 + } 1.176 + 1.177 + } else { 1.178 + aPaint.setColor(SkColorSetARGB(0, 0, 0, 0)); 1.179 + } 1.180 + break; 1.181 + } 1.182 + case PatternType::RADIAL_GRADIENT: { 1.183 + const RadialGradientPattern& pat = static_cast<const RadialGradientPattern&>(aPattern); 1.184 + GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get()); 1.185 + SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode); 1.186 + 1.187 + if (stops->mCount >= 2) { 1.188 + SkPoint points[2]; 1.189 + points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x), SkFloatToScalar(pat.mCenter1.y)); 1.190 + points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x), SkFloatToScalar(pat.mCenter2.y)); 1.191 + 1.192 + SkShader* shader = SkGradientShader::CreateTwoPointConical(points[0], 1.193 + SkFloatToScalar(pat.mRadius1), 1.194 + points[1], 1.195 + SkFloatToScalar(pat.mRadius2), 1.196 + &stops->mColors.front(), 1.197 + &stops->mPositions.front(), 1.198 + stops->mCount, 1.199 + mode); 1.200 + if (shader) { 1.201 + SkMatrix mat; 1.202 + GfxMatrixToSkiaMatrix(pat.mMatrix, mat); 1.203 + shader->setLocalMatrix(mat); 1.204 + SkSafeUnref(aPaint.setShader(shader)); 1.205 + } 1.206 + 1.207 + } else { 1.208 + aPaint.setColor(SkColorSetARGB(0, 0, 0, 0)); 1.209 + } 1.210 + break; 1.211 + } 1.212 + case PatternType::SURFACE: { 1.213 + const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern); 1.214 + aTmpBitmap = GetBitmapForSurface(pat.mSurface); 1.215 + const SkBitmap& bitmap = aTmpBitmap.mBitmap; 1.216 + 1.217 + SkShader::TileMode mode = ExtendModeToTileMode(pat.mExtendMode); 1.218 + SkShader* shader = SkShader::CreateBitmapShader(bitmap, mode, mode); 1.219 + SkMatrix mat; 1.220 + GfxMatrixToSkiaMatrix(pat.mMatrix, mat); 1.221 + shader->setLocalMatrix(mat); 1.222 + SkSafeUnref(aPaint.setShader(shader)); 1.223 + if (pat.mFilter == Filter::POINT) { 1.224 + aPaint.setFilterLevel(SkPaint::kNone_FilterLevel); 1.225 + } 1.226 + break; 1.227 + } 1.228 + } 1.229 +} 1.230 + 1.231 +static inline Rect 1.232 +GetClipBounds(SkCanvas *aCanvas) 1.233 +{ 1.234 + SkRect clipBounds; 1.235 + aCanvas->getClipBounds(&clipBounds); 1.236 + return SkRectToRect(clipBounds); 1.237 +} 1.238 + 1.239 +struct AutoPaintSetup { 1.240 + AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Pattern& aPattern, const Rect* aMaskBounds = nullptr) 1.241 + : mNeedsRestore(false), mAlpha(1.0) 1.242 + { 1.243 + Init(aCanvas, aOptions, aMaskBounds); 1.244 + SetPaintPattern(mPaint, aPattern, mTmpBitmap, mAlpha); 1.245 + } 1.246 + 1.247 + AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Rect* aMaskBounds = nullptr) 1.248 + : mNeedsRestore(false), mAlpha(1.0) 1.249 + { 1.250 + Init(aCanvas, aOptions, aMaskBounds); 1.251 + } 1.252 + 1.253 + ~AutoPaintSetup() 1.254 + { 1.255 + if (mNeedsRestore) { 1.256 + mCanvas->restore(); 1.257 + } 1.258 + } 1.259 + 1.260 + void Init(SkCanvas *aCanvas, const DrawOptions& aOptions, const Rect* aMaskBounds) 1.261 + { 1.262 + mPaint.setXfermodeMode(GfxOpToSkiaOp(aOptions.mCompositionOp)); 1.263 + mCanvas = aCanvas; 1.264 + 1.265 + //TODO: Can we set greyscale somehow? 1.266 + if (aOptions.mAntialiasMode != AntialiasMode::NONE) { 1.267 + mPaint.setAntiAlias(true); 1.268 + } else { 1.269 + mPaint.setAntiAlias(false); 1.270 + } 1.271 + 1.272 + Rect clipBounds = GetClipBounds(aCanvas); 1.273 + bool needsGroup = !IsOperatorBoundByMask(aOptions.mCompositionOp) && 1.274 + (!aMaskBounds || !aMaskBounds->Contains(clipBounds)); 1.275 + 1.276 + // TODO: We could skip the temporary for operator_source and just 1.277 + // clear the clip rect. The other operators would be harder 1.278 + // but could be worth it to skip pushing a group. 1.279 + if (needsGroup) { 1.280 + mPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode); 1.281 + SkPaint temp; 1.282 + temp.setXfermodeMode(GfxOpToSkiaOp(aOptions.mCompositionOp)); 1.283 + temp.setAlpha(U8CPU(aOptions.mAlpha*255)); 1.284 + //TODO: Get a rect here 1.285 + mCanvas->saveLayer(nullptr, &temp); 1.286 + mNeedsRestore = true; 1.287 + } else { 1.288 + mPaint.setAlpha(U8CPU(aOptions.mAlpha*255.0)); 1.289 + mAlpha = aOptions.mAlpha; 1.290 + } 1.291 + mPaint.setFilterLevel(SkPaint::kLow_FilterLevel); 1.292 + } 1.293 + 1.294 + // TODO: Maybe add an operator overload to access this easier? 1.295 + SkPaint mPaint; 1.296 + TempBitmap mTmpBitmap; 1.297 + bool mNeedsRestore; 1.298 + SkCanvas* mCanvas; 1.299 + Float mAlpha; 1.300 +}; 1.301 + 1.302 +void 1.303 +DrawTargetSkia::Flush() 1.304 +{ 1.305 + mCanvas->flush(); 1.306 +} 1.307 + 1.308 +void 1.309 +DrawTargetSkia::DrawSurface(SourceSurface *aSurface, 1.310 + const Rect &aDest, 1.311 + const Rect &aSource, 1.312 + const DrawSurfaceOptions &aSurfOptions, 1.313 + const DrawOptions &aOptions) 1.314 +{ 1.315 + RefPtr<SourceSurface> dataSurface; 1.316 + 1.317 + if (!(aSurface->GetType() == SurfaceType::SKIA || aSurface->GetType() == SurfaceType::DATA)) { 1.318 + dataSurface = aSurface->GetDataSurface(); 1.319 + if (!dataSurface) { 1.320 + gfxDebug() << *this << ": DrawSurface() can't draw surface"; 1.321 + return; 1.322 + } 1.323 + aSurface = dataSurface.get(); 1.324 + } 1.325 + 1.326 + if (aSource.IsEmpty()) { 1.327 + return; 1.328 + } 1.329 + 1.330 + MarkChanged(); 1.331 + 1.332 + SkRect destRect = RectToSkRect(aDest); 1.333 + SkRect sourceRect = RectToSkRect(aSource); 1.334 + 1.335 + TempBitmap bitmap = GetBitmapForSurface(aSurface); 1.336 + 1.337 + AutoPaintSetup paint(mCanvas.get(), aOptions, &aDest); 1.338 + if (aSurfOptions.mFilter == Filter::POINT) { 1.339 + paint.mPaint.setFilterLevel(SkPaint::kNone_FilterLevel); 1.340 + } 1.341 + 1.342 + mCanvas->drawBitmapRectToRect(bitmap.mBitmap, &sourceRect, destRect, &paint.mPaint); 1.343 +} 1.344 + 1.345 +void 1.346 +DrawTargetSkia::DrawFilter(FilterNode *aNode, 1.347 + const Rect &aSourceRect, 1.348 + const Point &aDestPoint, 1.349 + const DrawOptions &aOptions) 1.350 +{ 1.351 + FilterNodeSoftware* filter = static_cast<FilterNodeSoftware*>(aNode); 1.352 + filter->Draw(this, aSourceRect, aDestPoint, aOptions); 1.353 +} 1.354 + 1.355 +void 1.356 +DrawTargetSkia::DrawSurfaceWithShadow(SourceSurface *aSurface, 1.357 + const Point &aDest, 1.358 + const Color &aColor, 1.359 + const Point &aOffset, 1.360 + Float aSigma, 1.361 + CompositionOp aOperator) 1.362 +{ 1.363 + if (!(aSurface->GetType() == SurfaceType::SKIA || aSurface->GetType() == SurfaceType::DATA)) { 1.364 + return; 1.365 + } 1.366 + 1.367 + MarkChanged(); 1.368 + 1.369 + mCanvas->save(SkCanvas::kMatrix_SaveFlag); 1.370 + mCanvas->resetMatrix(); 1.371 + 1.372 + TempBitmap bitmap = GetBitmapForSurface(aSurface); 1.373 + 1.374 + SkPaint paint; 1.375 + 1.376 + SkImageFilter* filter = SkDropShadowImageFilter::Create(aOffset.x, aOffset.y, 1.377 + aSigma, ColorToSkColor(aColor, 1.0)); 1.378 + 1.379 + paint.setImageFilter(filter); 1.380 + paint.setXfermodeMode(GfxOpToSkiaOp(aOperator)); 1.381 + 1.382 + mCanvas->drawBitmap(bitmap.mBitmap, aDest.x, aDest.y, &paint); 1.383 + mCanvas->restore(); 1.384 +} 1.385 + 1.386 +void 1.387 +DrawTargetSkia::FillRect(const Rect &aRect, 1.388 + const Pattern &aPattern, 1.389 + const DrawOptions &aOptions) 1.390 +{ 1.391 + MarkChanged(); 1.392 + SkRect rect = RectToSkRect(aRect); 1.393 + AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern, &aRect); 1.394 + 1.395 + mCanvas->drawRect(rect, paint.mPaint); 1.396 +} 1.397 + 1.398 +void 1.399 +DrawTargetSkia::Stroke(const Path *aPath, 1.400 + const Pattern &aPattern, 1.401 + const StrokeOptions &aStrokeOptions, 1.402 + const DrawOptions &aOptions) 1.403 +{ 1.404 + MarkChanged(); 1.405 + MOZ_ASSERT(aPath, "Null path"); 1.406 + if (aPath->GetBackendType() != BackendType::SKIA) { 1.407 + return; 1.408 + } 1.409 + 1.410 + const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath); 1.411 + 1.412 + 1.413 + AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern); 1.414 + if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) { 1.415 + return; 1.416 + } 1.417 + 1.418 + mCanvas->drawPath(skiaPath->GetPath(), paint.mPaint); 1.419 +} 1.420 + 1.421 +void 1.422 +DrawTargetSkia::StrokeRect(const Rect &aRect, 1.423 + const Pattern &aPattern, 1.424 + const StrokeOptions &aStrokeOptions, 1.425 + const DrawOptions &aOptions) 1.426 +{ 1.427 + MarkChanged(); 1.428 + AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern); 1.429 + if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) { 1.430 + return; 1.431 + } 1.432 + 1.433 + mCanvas->drawRect(RectToSkRect(aRect), paint.mPaint); 1.434 +} 1.435 + 1.436 +void 1.437 +DrawTargetSkia::StrokeLine(const Point &aStart, 1.438 + const Point &aEnd, 1.439 + const Pattern &aPattern, 1.440 + const StrokeOptions &aStrokeOptions, 1.441 + const DrawOptions &aOptions) 1.442 +{ 1.443 + MarkChanged(); 1.444 + AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern); 1.445 + if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) { 1.446 + return; 1.447 + } 1.448 + 1.449 + mCanvas->drawLine(SkFloatToScalar(aStart.x), SkFloatToScalar(aStart.y), 1.450 + SkFloatToScalar(aEnd.x), SkFloatToScalar(aEnd.y), 1.451 + paint.mPaint); 1.452 +} 1.453 + 1.454 +void 1.455 +DrawTargetSkia::Fill(const Path *aPath, 1.456 + const Pattern &aPattern, 1.457 + const DrawOptions &aOptions) 1.458 +{ 1.459 + MarkChanged(); 1.460 + if (aPath->GetBackendType() != BackendType::SKIA) { 1.461 + return; 1.462 + } 1.463 + 1.464 + const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath); 1.465 + 1.466 + AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern); 1.467 + 1.468 + mCanvas->drawPath(skiaPath->GetPath(), paint.mPaint); 1.469 +} 1.470 + 1.471 +void 1.472 +DrawTargetSkia::FillGlyphs(ScaledFont *aFont, 1.473 + const GlyphBuffer &aBuffer, 1.474 + const Pattern &aPattern, 1.475 + const DrawOptions &aOptions, 1.476 + const GlyphRenderingOptions *aRenderingOptions) 1.477 +{ 1.478 + if (aFont->GetType() != FontType::MAC && 1.479 + aFont->GetType() != FontType::SKIA && 1.480 + aFont->GetType() != FontType::GDI) { 1.481 + return; 1.482 + } 1.483 + 1.484 + MarkChanged(); 1.485 + 1.486 + ScaledFontBase* skiaFont = static_cast<ScaledFontBase*>(aFont); 1.487 + 1.488 + AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern); 1.489 + paint.mPaint.setTypeface(skiaFont->GetSkTypeface()); 1.490 + paint.mPaint.setTextSize(SkFloatToScalar(skiaFont->mSize)); 1.491 + paint.mPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 1.492 + 1.493 + if (aRenderingOptions && aRenderingOptions->GetType() == FontType::CAIRO) { 1.494 + switch (static_cast<const GlyphRenderingOptionsCairo*>(aRenderingOptions)->GetHinting()) { 1.495 + case FontHinting::NONE: 1.496 + paint.mPaint.setHinting(SkPaint::kNo_Hinting); 1.497 + break; 1.498 + case FontHinting::LIGHT: 1.499 + paint.mPaint.setHinting(SkPaint::kSlight_Hinting); 1.500 + break; 1.501 + case FontHinting::NORMAL: 1.502 + paint.mPaint.setHinting(SkPaint::kNormal_Hinting); 1.503 + break; 1.504 + case FontHinting::FULL: 1.505 + paint.mPaint.setHinting(SkPaint::kFull_Hinting); 1.506 + break; 1.507 + } 1.508 + 1.509 + if (static_cast<const GlyphRenderingOptionsCairo*>(aRenderingOptions)->GetAutoHinting()) { 1.510 + paint.mPaint.setAutohinted(true); 1.511 + } 1.512 + } else { 1.513 + paint.mPaint.setHinting(SkPaint::kNormal_Hinting); 1.514 + } 1.515 + 1.516 + std::vector<uint16_t> indices; 1.517 + std::vector<SkPoint> offsets; 1.518 + indices.resize(aBuffer.mNumGlyphs); 1.519 + offsets.resize(aBuffer.mNumGlyphs); 1.520 + 1.521 + for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) { 1.522 + indices[i] = aBuffer.mGlyphs[i].mIndex; 1.523 + offsets[i].fX = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.x); 1.524 + offsets[i].fY = SkFloatToScalar(aBuffer.mGlyphs[i].mPosition.y); 1.525 + } 1.526 + 1.527 + mCanvas->drawPosText(&indices.front(), aBuffer.mNumGlyphs*2, &offsets.front(), paint.mPaint); 1.528 +} 1.529 + 1.530 +void 1.531 +DrawTargetSkia::Mask(const Pattern &aSource, 1.532 + const Pattern &aMask, 1.533 + const DrawOptions &aOptions) 1.534 +{ 1.535 + MarkChanged(); 1.536 + AutoPaintSetup paint(mCanvas.get(), aOptions, aSource); 1.537 + 1.538 + SkPaint maskPaint; 1.539 + TempBitmap tmpBitmap; 1.540 + SetPaintPattern(maskPaint, aMask, tmpBitmap); 1.541 + 1.542 + SkLayerRasterizer *raster = new SkLayerRasterizer(); 1.543 + raster->addLayer(maskPaint); 1.544 + SkSafeUnref(paint.mPaint.setRasterizer(raster)); 1.545 + 1.546 + mCanvas->drawRect(SkRectCoveringWholeSurface(), paint.mPaint); 1.547 +} 1.548 + 1.549 +void 1.550 +DrawTargetSkia::MaskSurface(const Pattern &aSource, 1.551 + SourceSurface *aMask, 1.552 + Point aOffset, 1.553 + const DrawOptions &aOptions) 1.554 +{ 1.555 + MarkChanged(); 1.556 + AutoPaintSetup paint(mCanvas.get(), aOptions, aSource); 1.557 + 1.558 + SkPaint maskPaint; 1.559 + TempBitmap tmpBitmap; 1.560 + SetPaintPattern(maskPaint, SurfacePattern(aMask, ExtendMode::CLAMP), tmpBitmap); 1.561 + 1.562 + SkMatrix transform = maskPaint.getShader()->getLocalMatrix(); 1.563 + transform.postTranslate(SkFloatToScalar(aOffset.x), SkFloatToScalar(aOffset.y)); 1.564 + maskPaint.getShader()->setLocalMatrix(transform); 1.565 + 1.566 + SkLayerRasterizer *raster = new SkLayerRasterizer(); 1.567 + raster->addLayer(maskPaint); 1.568 + SkSafeUnref(paint.mPaint.setRasterizer(raster)); 1.569 + 1.570 + IntSize size = aMask->GetSize(); 1.571 + Rect rect = Rect(aOffset.x, aOffset.y, size.width, size.height); 1.572 + mCanvas->drawRect(RectToSkRect(rect), paint.mPaint); 1.573 +} 1.574 + 1.575 +TemporaryRef<SourceSurface> 1.576 +DrawTargetSkia::CreateSourceSurfaceFromData(unsigned char *aData, 1.577 + const IntSize &aSize, 1.578 + int32_t aStride, 1.579 + SurfaceFormat aFormat) const 1.580 +{ 1.581 + RefPtr<SourceSurfaceSkia> newSurf = new SourceSurfaceSkia(); 1.582 + 1.583 + if (!newSurf->InitFromData(aData, aSize, aStride, aFormat)) { 1.584 + gfxDebug() << *this << ": Failure to create source surface from data. Size: " << aSize; 1.585 + return nullptr; 1.586 + } 1.587 + 1.588 + return newSurf; 1.589 +} 1.590 + 1.591 +TemporaryRef<DrawTarget> 1.592 +DrawTargetSkia::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const 1.593 +{ 1.594 + RefPtr<DrawTargetSkia> target = new DrawTargetSkia(); 1.595 + if (!target->Init(aSize, aFormat)) { 1.596 + return nullptr; 1.597 + } 1.598 + return target; 1.599 +} 1.600 + 1.601 +TemporaryRef<SourceSurface> 1.602 +DrawTargetSkia::OptimizeSourceSurface(SourceSurface *aSurface) const 1.603 +{ 1.604 + if (aSurface->GetType() == SurfaceType::SKIA) { 1.605 + return aSurface; 1.606 + } 1.607 + 1.608 + return aSurface->GetDataSurface(); 1.609 +} 1.610 + 1.611 +TemporaryRef<SourceSurface> 1.612 +DrawTargetSkia::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const 1.613 +{ 1.614 + return nullptr; 1.615 +} 1.616 + 1.617 +void 1.618 +DrawTargetSkia::CopySurface(SourceSurface *aSurface, 1.619 + const IntRect& aSourceRect, 1.620 + const IntPoint &aDestination) 1.621 +{ 1.622 + //TODO: We could just use writePixels() here if the sourceRect is the entire source 1.623 + 1.624 + if (aSurface->GetType() != SurfaceType::SKIA) { 1.625 + return; 1.626 + } 1.627 + 1.628 + MarkChanged(); 1.629 + 1.630 + TempBitmap bitmap = GetBitmapForSurface(aSurface); 1.631 + 1.632 + mCanvas->save(); 1.633 + mCanvas->resetMatrix(); 1.634 + SkRect dest = IntRectToSkRect(IntRect(aDestination.x, aDestination.y, aSourceRect.width, aSourceRect.height)); 1.635 + SkIRect source = IntRectToSkIRect(aSourceRect); 1.636 + mCanvas->clipRect(dest, SkRegion::kReplace_Op); 1.637 + SkPaint paint; 1.638 + 1.639 + if (mCanvas->getDevice()->config() == SkBitmap::kRGB_565_Config) { 1.640 + // Set the xfermode to SOURCE_OVER to workaround 1.641 + // http://code.google.com/p/skia/issues/detail?id=628 1.642 + // RGB565 is opaque so they're equivalent anyway 1.643 + paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); 1.644 + } else { 1.645 + paint.setXfermodeMode(SkXfermode::kSrc_Mode); 1.646 + } 1.647 + 1.648 + mCanvas->drawBitmapRect(bitmap.mBitmap, &source, dest, &paint); 1.649 + mCanvas->restore(); 1.650 +} 1.651 + 1.652 +bool 1.653 +DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat) 1.654 +{ 1.655 + SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(GfxFormatToSkiaConfig(aFormat), 1.656 + aSize.width, aSize.height, 1.657 + aFormat == SurfaceFormat::B8G8R8X8)); 1.658 + 1.659 + SkBitmap bitmap = device->accessBitmap(true); 1.660 + if (!bitmap.allocPixels()) { 1.661 + return false; 1.662 + } 1.663 + 1.664 + bitmap.eraseARGB(0, 0, 0, 0); 1.665 + 1.666 + SkAutoTUnref<SkCanvas> canvas(new SkCanvas(device.get())); 1.667 + mSize = aSize; 1.668 + 1.669 + mCanvas = canvas.get(); 1.670 + mFormat = aFormat; 1.671 + return true; 1.672 +} 1.673 + 1.674 +#ifdef USE_SKIA_GPU 1.675 +bool 1.676 +DrawTargetSkia::InitWithGrContext(GrContext* aGrContext, 1.677 + const IntSize &aSize, 1.678 + SurfaceFormat aFormat) 1.679 +{ 1.680 + MOZ_ASSERT(aGrContext, "null GrContext"); 1.681 + 1.682 + mGrContext = aGrContext; 1.683 + 1.684 + mSize = aSize; 1.685 + mFormat = aFormat; 1.686 + 1.687 + GrTextureDesc targetDescriptor; 1.688 + 1.689 + targetDescriptor.fFlags = kRenderTarget_GrTextureFlagBit; 1.690 + targetDescriptor.fWidth = mSize.width; 1.691 + targetDescriptor.fHeight = mSize.height; 1.692 + targetDescriptor.fConfig = GfxFormatToGrConfig(mFormat); 1.693 + targetDescriptor.fOrigin = kBottomLeft_GrSurfaceOrigin; 1.694 + targetDescriptor.fSampleCnt = 0; 1.695 + 1.696 + SkAutoTUnref<GrTexture> skiaTexture(mGrContext->createUncachedTexture(targetDescriptor, NULL, 0)); 1.697 + if (!skiaTexture) { 1.698 + return false; 1.699 + } 1.700 + 1.701 + mTexture = (uint32_t)skiaTexture->getTextureHandle(); 1.702 + 1.703 + SkAutoTUnref<SkBaseDevice> device(new SkGpuDevice(mGrContext.get(), skiaTexture->asRenderTarget())); 1.704 + SkAutoTUnref<SkCanvas> canvas(new SkCanvas(device.get())); 1.705 + mCanvas = canvas.get(); 1.706 + 1.707 + return true; 1.708 +} 1.709 + 1.710 +#endif 1.711 + 1.712 +void 1.713 +DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) 1.714 +{ 1.715 + SkAlphaType alphaType = kPremul_SkAlphaType; 1.716 + if (aFormat == SurfaceFormat::B8G8R8X8) { 1.717 + // We have to manually set the A channel to be 255 as Skia doesn't understand BGRX 1.718 + ConvertBGRXToBGRA(aData, aSize, aStride); 1.719 + alphaType = kOpaque_SkAlphaType; 1.720 + } 1.721 + 1.722 + SkBitmap bitmap; 1.723 + bitmap.setConfig(GfxFormatToSkiaConfig(aFormat), aSize.width, aSize.height, aStride, alphaType); 1.724 + bitmap.setPixels(aData); 1.725 + SkAutoTUnref<SkCanvas> canvas(new SkCanvas(new SkBitmapDevice(bitmap))); 1.726 + 1.727 + mSize = aSize; 1.728 + mCanvas = canvas.get(); 1.729 + mFormat = aFormat; 1.730 +} 1.731 + 1.732 +void 1.733 +DrawTargetSkia::SetTransform(const Matrix& aTransform) 1.734 +{ 1.735 + SkMatrix mat; 1.736 + GfxMatrixToSkiaMatrix(aTransform, mat); 1.737 + mCanvas->setMatrix(mat); 1.738 + mTransform = aTransform; 1.739 +} 1.740 + 1.741 +void* 1.742 +DrawTargetSkia::GetNativeSurface(NativeSurfaceType aType) 1.743 +{ 1.744 + if (aType == NativeSurfaceType::OPENGL_TEXTURE) { 1.745 + return (void*)((uintptr_t)mTexture); 1.746 + } 1.747 + 1.748 + return nullptr; 1.749 +} 1.750 + 1.751 + 1.752 +TemporaryRef<PathBuilder> 1.753 +DrawTargetSkia::CreatePathBuilder(FillRule aFillRule) const 1.754 +{ 1.755 + RefPtr<PathBuilderSkia> pb = new PathBuilderSkia(aFillRule); 1.756 + return pb; 1.757 +} 1.758 + 1.759 +void 1.760 +DrawTargetSkia::ClearRect(const Rect &aRect) 1.761 +{ 1.762 + MarkChanged(); 1.763 + SkPaint paint; 1.764 + mCanvas->save(); 1.765 + mCanvas->clipRect(RectToSkRect(aRect), SkRegion::kIntersect_Op, true); 1.766 + paint.setColor(SkColorSetARGB(0, 0, 0, 0)); 1.767 + paint.setXfermodeMode(SkXfermode::kSrc_Mode); 1.768 + mCanvas->drawPaint(paint); 1.769 + mCanvas->restore(); 1.770 +} 1.771 + 1.772 +void 1.773 +DrawTargetSkia::PushClip(const Path *aPath) 1.774 +{ 1.775 + if (aPath->GetBackendType() != BackendType::SKIA) { 1.776 + return; 1.777 + } 1.778 + 1.779 + const PathSkia *skiaPath = static_cast<const PathSkia*>(aPath); 1.780 + mCanvas->save(SkCanvas::kClip_SaveFlag); 1.781 + mCanvas->clipPath(skiaPath->GetPath(), SkRegion::kIntersect_Op, true); 1.782 +} 1.783 + 1.784 +void 1.785 +DrawTargetSkia::PushClipRect(const Rect& aRect) 1.786 +{ 1.787 + SkRect rect = RectToSkRect(aRect); 1.788 + 1.789 + mCanvas->save(SkCanvas::kClip_SaveFlag); 1.790 + mCanvas->clipRect(rect, SkRegion::kIntersect_Op, true); 1.791 +} 1.792 + 1.793 +void 1.794 +DrawTargetSkia::PopClip() 1.795 +{ 1.796 + mCanvas->restore(); 1.797 +} 1.798 + 1.799 +TemporaryRef<GradientStops> 1.800 +DrawTargetSkia::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const 1.801 +{ 1.802 + std::vector<GradientStop> stops; 1.803 + stops.resize(aNumStops); 1.804 + for (uint32_t i = 0; i < aNumStops; i++) { 1.805 + stops[i] = aStops[i]; 1.806 + } 1.807 + std::stable_sort(stops.begin(), stops.end()); 1.808 + 1.809 + return new GradientStopsSkia(stops, aNumStops, aExtendMode); 1.810 +} 1.811 + 1.812 +TemporaryRef<FilterNode> 1.813 +DrawTargetSkia::CreateFilter(FilterType aType) 1.814 +{ 1.815 + return FilterNodeSoftware::Create(aType); 1.816 +} 1.817 + 1.818 +void 1.819 +DrawTargetSkia::MarkChanged() 1.820 +{ 1.821 + if (mSnapshot) { 1.822 + mSnapshot->DrawTargetWillChange(); 1.823 + mSnapshot = nullptr; 1.824 + } 1.825 +} 1.826 + 1.827 +// Return a rect (in user space) that covers the entire surface by applying 1.828 +// the inverse of GetTransform() to (0, 0, mSize.width, mSize.height). 1.829 +SkRect 1.830 +DrawTargetSkia::SkRectCoveringWholeSurface() const 1.831 +{ 1.832 + return RectToSkRect(mTransform.TransformBounds(Rect(0, 0, mSize.width, mSize.height))); 1.833 +} 1.834 + 1.835 +void 1.836 +DrawTargetSkia::SnapshotDestroyed() 1.837 +{ 1.838 + mSnapshot = nullptr; 1.839 +} 1.840 + 1.841 +} 1.842 +}