gfx/2d/DrawTargetSkia.cpp

changeset 0
6474c204b198
     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 +}

mercurial