19db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein/* 29db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein * Copyright 2015 Google Inc. 39db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein * 49db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein * Use of this source code is governed by a BSD-style license that can be 59db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein * found in the LICENSE file. 69db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein */ 703a7f5fe2de9b0c886be4063533c91720ced0bf9Hal Canary#ifndef SkPictureCommon_DEFINED 803a7f5fe2de9b0c886be4063533c91720ced0bf9Hal Canary#define SkPictureCommon_DEFINED 99db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 109db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein// Some shared code used by both SkBigPicture and SkMiniPicture. 119db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein// SkTextHunter -- SkRecord visitor that returns true when the op draws text. 12a16af21b17885c517a587482e9062efb99c19306mtklein// SkBitmapHunter -- SkRecord visitor that returns true when the op draws a bitmap or image. 139db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein// SkPathCounter -- SkRecord visitor that counts paths that draw slowly on the GPU. 149db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 159db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein#include "SkPathEffect.h" 169db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein#include "SkRecords.h" 179db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein#include "SkTLogic.h" 189db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 19a16af21b17885c517a587482e9062efb99c19306mtklein// N.B. This name is slightly historical: hunting season is now open for SkImages too. 209db912c2ac2ab53bc24f2d50a3e5a80162051dccmtkleinstruct SkBitmapHunter { 219db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein // Some ops have a paint, some have an optional paint. Either way, get back a pointer. 229db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein static const SkPaint* AsPtr(const SkPaint& p) { return &p; } 239db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein static const SkPaint* AsPtr(const SkRecords::Optional<SkPaint>& p) { return p; } 249db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 259db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein // Main entry for visitor: 269db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein // If the op is a DrawPicture, recurse. 27a16af21b17885c517a587482e9062efb99c19306mtklein // If the op has a bitmap or image directly, return true. 289db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein // If the op has a paint and the paint has a bitmap, return true. 299db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein // Otherwise, return false. 309db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein bool operator()(const SkRecords::DrawPicture& op) { return op.picture->willPlayBackBitmaps(); } 31449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein bool operator()(const SkRecords::DrawDrawable&) { /*TODO*/ return false; } 329db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 339db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein template <typename T> 34449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein bool operator()(const T& op) { return CheckBitmap(op); } 359db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 36449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein // If the op is tagged as having an image, return true. 379db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein template <typename T> 38449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein static SK_WHEN(T::kTags & SkRecords::kHasImage_Tag, bool) CheckBitmap(const T&) { 39a16af21b17885c517a587482e9062efb99c19306mtklein return true; 40a16af21b17885c517a587482e9062efb99c19306mtklein } 419db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 429db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein // If not, look for one in its paint (if it has a paint). 439db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein template <typename T> 44449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein static SK_WHEN(!(T::kTags & SkRecords::kHasImage_Tag), bool) CheckBitmap(const T& op) { 45449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein return CheckPaint(op); 46449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein } 47449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein 48449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein // Most draws-type ops have paints. 49449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein template <typename T> 501bb5fecbea494d77d7d5633522be1cdc76d043aemtklein static SK_WHEN(T::kTags & SkRecords::kHasPaint_Tag, bool) CheckPaint(const T& op) { 51449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein return PaintHasBitmap(AsPtr(op.paint)); 52449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein } 53449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein 549db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein template <typename T> 551bb5fecbea494d77d7d5633522be1cdc76d043aemtklein static SK_WHEN(!(T::kTags & SkRecords::kHasPaint_Tag), bool) CheckPaint(const T&) { 56449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein return false; 57449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein } 58449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein 59449d9b7e2d1b2e20963f18639c6e541ef953f069mtkleinprivate: 60449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein static bool PaintHasBitmap(const SkPaint* paint) { 619db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein if (paint) { 629db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein const SkShader* shader = paint->getShader(); 63627778d5ba4fd6f4a4a1238bbf7a1b561469fe21Mike Reed if (shader && shader->isAImage()) { 649db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein return true; 659db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } 669db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } 679db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein return false; 689db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } 699db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein}; 709db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 719db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein// TODO: might be nicer to have operator() return an int (the number of slow paths) ? 729db912c2ac2ab53bc24f2d50a3e5a80162051dccmtkleinstruct SkPathCounter { 739db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein // Some ops have a paint, some have an optional paint. Either way, get back a pointer. 749db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein static const SkPaint* AsPtr(const SkPaint& p) { return &p; } 759db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein static const SkPaint* AsPtr(const SkRecords::Optional<SkPaint>& p) { return p; } 769db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 779db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein SkPathCounter() : fNumSlowPathsAndDashEffects(0) {} 789db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 799db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein // Recurse into nested pictures. 809db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein void operator()(const SkRecords::DrawPicture& op) { 819db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein fNumSlowPathsAndDashEffects += op.picture->numSlowPaths(); 829db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } 83449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein void operator()(const SkRecords::DrawDrawable&) { /* TODO */ } 849db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 859db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein void checkPaint(const SkPaint* paint) { 869db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein if (paint && paint->getPathEffect()) { 879db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein // Initially assume it's slow. 889db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein fNumSlowPathsAndDashEffects++; 899db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } 909db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } 919db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 929db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein void operator()(const SkRecords::DrawPoints& op) { 939db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein this->checkPaint(&op.paint); 949db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein const SkPathEffect* effect = op.paint.getPathEffect(); 959db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein if (effect) { 969db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein SkPathEffect::DashInfo info; 979db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein SkPathEffect::DashType dashType = effect->asADash(&info); 989db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein if (2 == op.count && SkPaint::kRound_Cap != op.paint.getStrokeCap() && 999db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein SkPathEffect::kDash_DashType == dashType && 2 == info.fCount) { 1009db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein fNumSlowPathsAndDashEffects--; 1019db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } 1029db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } 1039db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } 1049db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 1059db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein void operator()(const SkRecords::DrawPath& op) { 1069db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein this->checkPaint(&op.paint); 1079db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein if (op.paint.isAntiAlias() && !op.path.isConvex()) { 1089db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein SkPaint::Style paintStyle = op.paint.getStyle(); 1099db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein const SkRect& pathBounds = op.path.getBounds(); 1109db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein if (SkPaint::kStroke_Style == paintStyle && 1119db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 0 == op.paint.getStrokeWidth()) { 1129db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein // AA hairline concave path is not slow. 1139db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } else if (SkPaint::kFill_Style == paintStyle && pathBounds.width() < 64.f && 1149db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein pathBounds.height() < 64.f && !op.path.isVolatile()) { 1159db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein // AADF eligible concave path is not slow. 1169db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } else { 1179db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein fNumSlowPathsAndDashEffects++; 1189db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } 1199db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } 1209db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } 1219db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 122b5fc58e1de6c2428f786034262a2ecdc8388d21dfmalita void operator()(const SkRecords::ClipPath& op) { 123b5fc58e1de6c2428f786034262a2ecdc8388d21dfmalita // TODO: does the SkRegion op matter? 124ebfce6d9b42198e04288a15953f40c395a7b6139Mike Reed if (op.opAA.aa() && !op.path.isConvex()) { 125b5fc58e1de6c2428f786034262a2ecdc8388d21dfmalita fNumSlowPathsAndDashEffects++; 126b5fc58e1de6c2428f786034262a2ecdc8388d21dfmalita } 127b5fc58e1de6c2428f786034262a2ecdc8388d21dfmalita } 128b5fc58e1de6c2428f786034262a2ecdc8388d21dfmalita 129449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein void operator()(const SkRecords::SaveLayer& op) { 130449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein this->checkPaint(AsPtr(op.paint)); 131449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein } 132449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein 1339db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein template <typename T> 134449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein SK_WHEN(T::kTags & SkRecords::kDraw_Tag, void) operator()(const T& op) { 1359db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein this->checkPaint(AsPtr(op.paint)); 1369db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein } 1379db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 1389db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein template <typename T> 139449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein SK_WHEN(!(T::kTags & SkRecords::kDraw_Tag), void) operator()(const T& op) { /* do nothing */ } 1409db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein 1419db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein int fNumSlowPathsAndDashEffects; 1429db912c2ac2ab53bc24f2d50a3e5a80162051dccmtklein}; 14303a7f5fe2de9b0c886be4063533c91720ced0bf9Hal Canary#endif // SkPictureCommon_DEFINED 144