1/* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "include/core/SkOverdrawCanvas.h" 9 10#include "include/core/SkColorFilter.h" 11#include "include/core/SkDrawable.h" 12#include "include/core/SkPath.h" 13#include "include/core/SkRRect.h" 14#include "include/core/SkRSXform.h" 15#include "include/core/SkTextBlob.h" 16#include "include/private/SkTo.h" 17#include "src/core/SkDevice.h" 18#include "src/core/SkDrawShadowInfo.h" 19#include "src/core/SkGlyphRunPainter.h" 20#include "src/core/SkImagePriv.h" 21#include "src/core/SkLatticeIter.h" 22#include "src/core/SkStrikeCache.h" 23#include "src/core/SkTextBlobPriv.h" 24#include "src/utils/SkPatchUtils.h" 25 26SkOverdrawCanvas::SkOverdrawCanvas(SkCanvas* canvas) 27 : INHERITED(canvas->onImageInfo().width(), canvas->onImageInfo().height()) 28{ 29 // Non-drawing calls that SkOverdrawCanvas does not override (translate, save, etc.) 30 // will pass through to the input canvas. 31 this->addCanvas(canvas); 32 33 static constexpr float kIncrementAlpha[] = { 34 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 35 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 36 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 37 0.0f, 0.0f, 0.0f, 0.0f, 1.0f/255, 38 }; 39 40 fPaint.setAntiAlias(false); 41 fPaint.setBlendMode(SkBlendMode::kPlus); 42 fPaint.setColorFilter(SkColorFilters::Matrix(kIncrementAlpha)); 43} 44 45namespace { 46class TextDevice : public SkNoPixelsDevice, public SkGlyphRunListPainter::BitmapDevicePainter { 47public: 48 TextDevice(SkCanvas* overdrawCanvas, const SkSurfaceProps& props) 49 : SkNoPixelsDevice{SkIRect::MakeWH(32767, 32767), props}, 50 fOverdrawCanvas{overdrawCanvas}, 51 fPainter{props, kN32_SkColorType, nullptr, SkStrikeCache::GlobalStrikeCache()} {} 52 53 void paintPaths(SkDrawableGlyphBuffer*, SkScalar, SkPoint, const SkPaint&) const override {} 54 55 void paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const override { 56 for (auto t : drawables->drawable()) { 57 SkGlyphVariant glyph; SkPoint pos; 58 std::tie(glyph, pos) = t; 59 SkMask mask = glyph.glyph()->mask(pos); 60 fOverdrawCanvas->drawRect(SkRect::Make(mask.fBounds), SkPaint()); 61 } 62 } 63 64 void drawBitmap(const SkBitmap&, const SkMatrix&, const SkRect* dstOrNull, 65 const SkSamplingOptions&, const SkPaint&) const override {} 66 67 void onDrawGlyphRunList(const SkGlyphRunList& glyphRunList, const SkPaint& paint) override { 68 SkASSERT(!glyphRunList.hasRSXForm()); 69 fPainter.drawForBitmapDevice(glyphRunList, paint, SkMatrix(), this); 70 } 71 72private: 73 SkCanvas* const fOverdrawCanvas; 74 SkGlyphRunListPainter fPainter; 75}; 76} // namespace 77 78void SkOverdrawCanvas::onDrawTextBlob( 79 const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) { 80 SkGlyphRunBuilder b; 81 auto glyphRunList = b.blobToGlyphRunList(*blob, {x, y}); 82 this->onDrawGlyphRunList(glyphRunList, paint); 83} 84 85void SkOverdrawCanvas::onDrawGlyphRunList( 86 const SkGlyphRunList& glyphRunList, const SkPaint& paint) { 87 SkSurfaceProps props{0, kUnknown_SkPixelGeometry}; 88 this->getProps(&props); 89 TextDevice device{this, props}; 90 91 device.drawGlyphRunList(glyphRunList, paint); 92} 93 94void SkOverdrawCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 95 const SkPoint texCoords[4], SkBlendMode blendMode, 96 const SkPaint&) { 97 fList[0]->onDrawPatch(cubics, colors, texCoords, blendMode, fPaint); 98} 99 100void SkOverdrawCanvas::onDrawPaint(const SkPaint& paint) { 101 if (0 == paint.getColor() && !paint.getColorFilter() && !paint.getShader()) { 102 // This is a clear, ignore it. 103 } else { 104 fList[0]->onDrawPaint(this->overdrawPaint(paint)); 105 } 106} 107 108void SkOverdrawCanvas::onDrawBehind(const SkPaint& paint) { 109 fList[0]->onDrawBehind(this->overdrawPaint(paint)); 110} 111 112void SkOverdrawCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) { 113 fList[0]->onDrawRect(rect, this->overdrawPaint(paint)); 114} 115 116void SkOverdrawCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) { 117 fList[0]->onDrawRegion(region, this->overdrawPaint(paint)); 118} 119 120void SkOverdrawCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) { 121 fList[0]->onDrawOval(oval, this->overdrawPaint(paint)); 122} 123 124void SkOverdrawCanvas::onDrawArc(const SkRect& arc, SkScalar startAngle, SkScalar sweepAngle, 125 bool useCenter, const SkPaint& paint) { 126 fList[0]->onDrawArc(arc, startAngle, sweepAngle, useCenter, this->overdrawPaint(paint)); 127} 128 129void SkOverdrawCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 130 const SkPaint& paint) { 131 fList[0]->onDrawDRRect(outer, inner, this->overdrawPaint(paint)); 132} 133 134void SkOverdrawCanvas::onDrawRRect(const SkRRect& rect, const SkPaint& paint) { 135 fList[0]->onDrawRRect(rect, this->overdrawPaint(paint)); 136} 137 138void SkOverdrawCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint points[], 139 const SkPaint& paint) { 140 fList[0]->onDrawPoints(mode, count, points, this->overdrawPaint(paint)); 141} 142 143void SkOverdrawCanvas::onDrawVerticesObject(const SkVertices* vertices, 144 SkBlendMode blendMode, const SkPaint& paint) { 145 fList[0]->onDrawVerticesObject(vertices, blendMode, this->overdrawPaint(paint)); 146} 147 148void SkOverdrawCanvas::onDrawAtlas2(const SkImage* image, const SkRSXform xform[], 149 const SkRect texs[], const SkColor colors[], int count, 150 SkBlendMode mode, const SkSamplingOptions& sampling, 151 const SkRect* cull, const SkPaint* paint) { 152 SkPaint* paintPtr = &fPaint; 153 SkPaint storage; 154 if (paint) { 155 storage = this->overdrawPaint(*paint); 156 paintPtr = &storage; 157 } 158 159 fList[0]->onDrawAtlas2(image, xform, texs, colors, count, mode, sampling, cull, paintPtr); 160} 161 162void SkOverdrawCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { 163 fList[0]->onDrawPath(path, fPaint); 164} 165 166void SkOverdrawCanvas::onDrawImage2(const SkImage* image, SkScalar x, SkScalar y, 167 const SkSamplingOptions&, const SkPaint*) { 168 fList[0]->onDrawRect(SkRect::MakeXYWH(x, y, image->width(), image->height()), fPaint); 169} 170 171void SkOverdrawCanvas::onDrawImageRect2(const SkImage* image, const SkRect& src, const SkRect& dst, 172 const SkSamplingOptions&, const SkPaint*, SrcRectConstraint) { 173 fList[0]->onDrawRect(dst, fPaint); 174} 175 176void SkOverdrawCanvas::onDrawImageLattice2(const SkImage* image, const Lattice& lattice, 177 const SkRect& dst, SkFilterMode, const SkPaint*) { 178 SkIRect bounds; 179 Lattice latticePlusBounds = lattice; 180 if (!latticePlusBounds.fBounds) { 181 bounds = SkIRect::MakeWH(image->width(), image->height()); 182 latticePlusBounds.fBounds = &bounds; 183 } 184 185 if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) { 186 SkLatticeIter iter(latticePlusBounds, dst); 187 188 SkRect ignored, iterDst; 189 while (iter.next(&ignored, &iterDst)) { 190 fList[0]->onDrawRect(iterDst, fPaint); 191 } 192 } else { 193 fList[0]->onDrawRect(dst, fPaint); 194 } 195} 196 197void SkOverdrawCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) { 198 drawable->draw(this, matrix); 199} 200 201void SkOverdrawCanvas::onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) { 202 SkASSERT(false); 203 return; 204} 205 206void SkOverdrawCanvas::onDrawAnnotation(const SkRect&, const char[], SkData*) {} 207 208void SkOverdrawCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) { 209 SkRect bounds; 210 SkDrawShadowMetrics::GetLocalBounds(path, rec, this->getTotalMatrix(), &bounds); 211 fList[0]->onDrawRect(bounds, fPaint); 212} 213 214void SkOverdrawCanvas::onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], 215 QuadAAFlags aa, const SkColor4f& color, SkBlendMode mode) { 216 if (clip) { 217 fList[0]->onDrawPath(SkPath::Polygon(clip, 4, true), fPaint); 218 } else { 219 fList[0]->onDrawRect(rect, fPaint); 220 } 221} 222 223void SkOverdrawCanvas::onDrawEdgeAAImageSet2(const ImageSetEntry set[], int count, 224 const SkPoint dstClips[], 225 const SkMatrix preViewMatrices[], 226 const SkSamplingOptions& sampling, 227 const SkPaint* paint, 228 SrcRectConstraint constraint) { 229 int clipIndex = 0; 230 for (int i = 0; i < count; ++i) { 231 if (set[i].fMatrixIndex >= 0) { 232 fList[0]->save(); 233 fList[0]->concat(preViewMatrices[set[i].fMatrixIndex]); 234 } 235 if (set[i].fHasClip) { 236 fList[0]->onDrawPath(SkPath::Polygon(dstClips + clipIndex, 4, true), fPaint); 237 clipIndex += 4; 238 } else { 239 fList[0]->onDrawRect(set[i].fDstRect, fPaint); 240 } 241 if (set[i].fMatrixIndex >= 0) { 242 fList[0]->restore(); 243 } 244 } 245} 246 247inline SkPaint SkOverdrawCanvas::overdrawPaint(const SkPaint& paint) { 248 SkPaint newPaint = fPaint; 249 newPaint.setStyle(paint.getStyle()); 250 newPaint.setStrokeWidth(paint.getStrokeWidth()); 251 return newPaint; 252} 253