15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "skia/ext/pixel_ref_utils.h"
63240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include <algorithm>
8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmapDevice.h"
103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "third_party/skia/include/core/SkCanvas.h"
113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "third_party/skia/include/core/SkData.h"
123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "third_party/skia/include/core/SkDraw.h"
133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "third_party/skia/include/core/SkPixelRef.h"
143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "third_party/skia/include/core/SkRRect.h"
153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "third_party/skia/include/core/SkRect.h"
163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "third_party/skia/include/core/SkShader.h"
17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "third_party/skia/include/utils/SkNoSaveLayerCanvas.h"
183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "third_party/skia/src/core/SkRasterClip.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace skia {
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// URI label for a discardable SkPixelRef.
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kLabelDiscardable[] = "discardable";
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class DiscardablePixelRefSet {
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DiscardablePixelRefSet(
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::vector<PixelRefUtils::PositionPixelRef>* pixel_refs)
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : pixel_refs_(pixel_refs) {}
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void Add(SkPixelRef* pixel_ref, const SkRect& rect) {
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Only save discardable pixel refs.
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (pixel_ref->getURI() &&
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        !strcmp(pixel_ref->getURI(), kLabelDiscardable)) {
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      PixelRefUtils::PositionPixelRef position_pixel_ref;
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      position_pixel_ref.pixel_ref = pixel_ref;
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      position_pixel_ref.pixel_ref_rect = rect;
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pixel_refs_->push_back(position_pixel_ref);
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<PixelRefUtils::PositionPixelRef>* pixel_refs_;
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
48424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)class GatherPixelRefDevice : public SkBitmapDevice {
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GatherPixelRefDevice(const SkBitmap& bm,
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       DiscardablePixelRefSet* pixel_ref_set)
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : SkBitmapDevice(bm), pixel_ref_set_(pixel_ref_set) {}
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void clear(SkColor color) SK_OVERRIDE {}
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkBitmap bitmap;
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (GetBitmapFromPaint(paint, &bitmap)) {
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SkRect clip_rect = SkRect::Make(draw.fRC->getBounds());
598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      AddBitmap(bitmap, clip_rect);
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void drawPoints(const SkDraw& draw,
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          SkCanvas::PointMode mode,
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          size_t count,
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          const SkPoint points[],
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          const SkPaint& paint) SK_OVERRIDE {
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkBitmap bitmap;
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!GetBitmapFromPaint(paint, &bitmap))
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (count == 0)
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkPoint min_point = points[0];
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkPoint max_point = points[0];
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (size_t i = 1; i < count; ++i) {
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const SkPoint& point = points[i];
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      min_point.set(std::min(min_point.x(), point.x()),
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    std::min(min_point.y(), point.y()));
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      max_point.set(std::max(max_point.x(), point.x()),
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    std::max(max_point.y(), point.y()));
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkRect bounds = SkRect::MakeLTRB(
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        min_point.x(), min_point.y(), max_point.x(), max_point.y());
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    GatherPixelRefDevice::drawRect(draw, bounds, paint);
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void drawRect(const SkDraw& draw,
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        const SkRect& rect,
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        const SkPaint& paint) SK_OVERRIDE {
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkBitmap bitmap;
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (GetBitmapFromPaint(paint, &bitmap)) {
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SkRect mapped_rect;
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      draw.fMatrix->mapRect(&mapped_rect, rect);
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      mapped_rect.intersect(SkRect::Make(draw.fRC->getBounds()));
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      AddBitmap(bitmap, mapped_rect);
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void drawOval(const SkDraw& draw,
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        const SkRect& rect,
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        const SkPaint& paint) SK_OVERRIDE {
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    GatherPixelRefDevice::drawRect(draw, rect, paint);
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void drawRRect(const SkDraw& draw,
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         const SkRRect& rect,
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         const SkPaint& paint) SK_OVERRIDE {
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    GatherPixelRefDevice::drawRect(draw, rect.rect(), paint);
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void drawPath(const SkDraw& draw,
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        const SkPath& path,
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        const SkPaint& paint,
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        const SkMatrix* pre_path_matrix,
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        bool path_is_mutable) SK_OVERRIDE {
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkBitmap bitmap;
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!GetBitmapFromPaint(paint, &bitmap))
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkRect path_bounds = path.getBounds();
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkRect final_rect;
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (pre_path_matrix != NULL)
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pre_path_matrix->mapRect(&final_rect, path_bounds);
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    else
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      final_rect = path_bounds;
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    GatherPixelRefDevice::drawRect(draw, final_rect, paint);
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void drawBitmap(const SkDraw& draw,
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          const SkBitmap& bitmap,
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          const SkMatrix& matrix,
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          const SkPaint& paint) SK_OVERRIDE {
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkMatrix total_matrix;
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    total_matrix.setConcat(*draw.fMatrix, matrix);
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkRect bitmap_rect = SkRect::MakeWH(bitmap.width(), bitmap.height());
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkRect mapped_rect;
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    total_matrix.mapRect(&mapped_rect, bitmap_rect);
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    AddBitmap(bitmap, mapped_rect);
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkBitmap paint_bitmap;
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (GetBitmapFromPaint(paint, &paint_bitmap))
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      AddBitmap(paint_bitmap, mapped_rect);
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void drawBitmapRect(const SkDraw& draw,
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const SkBitmap& bitmap,
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const SkRect* src_or_null,
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const SkRect& dst,
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              const SkPaint& paint,
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkRect bitmap_rect = SkRect::MakeWH(bitmap.width(), bitmap.height());
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkMatrix matrix;
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    matrix.setRectToRect(bitmap_rect, dst, SkMatrix::kFill_ScaleToFit);
154558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    GatherPixelRefDevice::drawBitmap(draw, bitmap, matrix, paint);
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void drawSprite(const SkDraw& draw,
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          const SkBitmap& bitmap,
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          int x,
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          int y,
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          const SkPaint& paint) SK_OVERRIDE {
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Sprites aren't affected by current matrix, so we can't reuse drawRect.
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkMatrix matrix;
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    matrix.setTranslate(x, y);
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkRect bitmap_rect = SkRect::MakeWH(bitmap.width(), bitmap.height());
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkRect mapped_rect;
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    matrix.mapRect(&mapped_rect, bitmap_rect);
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    AddBitmap(bitmap, mapped_rect);
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkBitmap paint_bitmap;
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (GetBitmapFromPaint(paint, &paint_bitmap))
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      AddBitmap(paint_bitmap, mapped_rect);
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void drawText(const SkDraw& draw,
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        const void* text,
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        size_t len,
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        SkScalar x,
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        SkScalar y,
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        const SkPaint& paint) SK_OVERRIDE {
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkBitmap bitmap;
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!GetBitmapFromPaint(paint, &bitmap))
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Math is borrowed from SkBBoxRecord
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkRect bounds;
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    paint.measureText(text, len, &bounds);
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkPaint::FontMetrics metrics;
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    paint.getFontMetrics(&metrics);
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (paint.isVerticalText()) {
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SkScalar h = bounds.fBottom - bounds.fTop;
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (paint.getTextAlign() == SkPaint::kCenter_Align) {
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bounds.fTop -= h / 2;
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bounds.fBottom -= h / 2;
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      bounds.fBottom += metrics.fBottom;
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      bounds.fTop += metrics.fTop;
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SkScalar w = bounds.fRight - bounds.fLeft;
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (paint.getTextAlign() == SkPaint::kCenter_Align) {
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bounds.fLeft -= w / 2;
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bounds.fRight -= w / 2;
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bounds.fLeft -= w;
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bounds.fRight -= w;
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      bounds.fTop = metrics.fTop;
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      bounds.fBottom = metrics.fBottom;
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bounds.fLeft -= pad;
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bounds.fRight += pad;
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bounds.fLeft += x;
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bounds.fRight += x;
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bounds.fTop += y;
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bounds.fBottom += y;
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    GatherPixelRefDevice::drawRect(draw, bounds, paint);
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void drawPosText(const SkDraw& draw,
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           const void* text,
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           size_t len,
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           const SkScalar pos[],
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           SkScalar const_y,
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           int scalars_per_pos,
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           const SkPaint& paint) SK_OVERRIDE {
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkBitmap bitmap;
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!GetBitmapFromPaint(paint, &bitmap))
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (len == 0)
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Similar to SkDraw asserts.
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkASSERT(scalars_per_pos == 1 || scalars_per_pos == 2);
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkPoint min_point;
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkPoint max_point;
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (scalars_per_pos == 1) {
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      min_point.set(pos[0], const_y);
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      max_point.set(pos[0], const_y);
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else if (scalars_per_pos == 2) {
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      min_point.set(pos[0], const_y + pos[1]);
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      max_point.set(pos[0], const_y + pos[1]);
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (size_t i = 0; i < len; ++i) {
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SkScalar x = pos[i * scalars_per_pos];
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SkScalar y = const_y;
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (scalars_per_pos == 2)
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        y += pos[i * scalars_per_pos + 1];
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      min_point.set(std::min(x, min_point.x()), std::min(y, min_point.y()));
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      max_point.set(std::max(x, max_point.x()), std::max(y, max_point.y()));
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkRect bounds = SkRect::MakeLTRB(
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        min_point.x(), min_point.y(), max_point.x(), max_point.y());
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Math is borrowed from SkBBoxRecord
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkPaint::FontMetrics metrics;
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    paint.getFontMetrics(&metrics);
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bounds.fTop += metrics.fTop;
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bounds.fBottom += metrics.fBottom;
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bounds.fLeft += pad;
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bounds.fRight -= pad;
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    GatherPixelRefDevice::drawRect(draw, bounds, paint);
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void drawTextOnPath(const SkDraw& draw,
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const void* text,
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              size_t len,
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const SkPath& path,
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const SkMatrix* matrix,
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const SkPaint& paint) SK_OVERRIDE {
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkBitmap bitmap;
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!GetBitmapFromPaint(paint, &bitmap))
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Math is borrowed from SkBBoxRecord
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkRect bounds = path.getBounds();
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkPaint::FontMetrics metrics;
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    paint.getFontMetrics(&metrics);
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkScalar pad = metrics.fTop;
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bounds.fLeft += pad;
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bounds.fRight -= pad;
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bounds.fTop += pad;
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bounds.fBottom -= pad;
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    GatherPixelRefDevice::drawRect(draw, bounds, paint);
296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void drawVertices(const SkDraw& draw,
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            SkCanvas::VertexMode,
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            int vertex_count,
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const SkPoint verts[],
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const SkPoint texs[],
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const SkColor colors[],
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            SkXfermode* xmode,
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const uint16_t indices[],
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            int index_count,
306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            const SkPaint& paint) SK_OVERRIDE {
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    GatherPixelRefDevice::drawPoints(
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        draw, SkCanvas::kPolygon_PointMode, vertex_count, verts, paint);
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void drawDevice(const SkDraw&,
311424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                          SkBaseDevice*,
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          int x,
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          int y,
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          const SkPaint&) SK_OVERRIDE {}
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) protected:
317effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  virtual bool onReadPixels(const SkImageInfo& info,
318effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            void* pixels,
319effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            size_t rowBytes,
320effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            int x,
321effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                            int y) SK_OVERRIDE {
322effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return false;
323effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
324effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual bool onWritePixels(const SkImageInfo& info,
326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             const void* pixels,
327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             size_t rowBytes,
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             int x,
329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             int y) SK_OVERRIDE {
330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DiscardablePixelRefSet* pixel_ref_set_;
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void AddBitmap(const SkBitmap& bm, const SkRect& rect) {
3378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    SkRect canvas_rect = SkRect::MakeWH(width(), height());
3388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    SkRect paint_rect = SkRect::MakeEmpty();
3398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    paint_rect.intersect(rect, canvas_rect);
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pixel_ref_set_->Add(bm.pixelRef(), paint_rect);
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool GetBitmapFromPaint(const SkPaint& paint, SkBitmap* bm) {
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkShader* shader = paint.getShader();
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (shader) {
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Check whether the shader is a gradient in order to prevent generation
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // of bitmaps from gradient shaders, which implement asABitmap.
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (SkShader::kNone_GradientType == shader->asAGradient(NULL))
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return shader->asABitmap(bm, NULL, NULL);
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PixelRefUtils::GatherDiscardablePixelRefs(
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SkPicture* picture,
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::vector<PositionPixelRef>* pixel_refs) {
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pixel_refs->clear();
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DiscardablePixelRefSet pixel_ref_set(pixel_refs);
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SkBitmap empty_bitmap;
364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  empty_bitmap.setInfo(SkImageInfo::MakeUnknown(picture->width(), picture->height()));
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GatherPixelRefDevice device(empty_bitmap, &pixel_ref_set);
367effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  SkNoSaveLayerCanvas canvas(&device);
368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  canvas.clipRect(SkRect::MakeWH(picture->width(), picture->height()),
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  SkRegion::kIntersect_Op,
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  false);
37246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  canvas.drawPicture(picture);
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace skia
376