1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2014 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkAlphaType.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlendMode.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorPriv.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorType.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontTypes.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPathBuilder.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPathTypes.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPicture.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPixelRef.h" // IWYU pragma: keep
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPixmap.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint3.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSamplingOptions.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextBlob.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTileMode.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/SkColorData.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkCPUTypes.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkFontPriv.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "tools/SkMetaData.h"
43*c8dee2aaSAndroid Build Coastguard Worker
44*c8dee2aaSAndroid Build Coastguard Worker #include <cmath>
45*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
46*c8dee2aaSAndroid Build Coastguard Worker
47*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
48*c8dee2aaSAndroid Build Coastguard Worker
49*c8dee2aaSAndroid Build Coastguard Worker namespace ToolUtils {
50*c8dee2aaSAndroid Build Coastguard Worker
alphatype_name(SkAlphaType at)51*c8dee2aaSAndroid Build Coastguard Worker const char* alphatype_name(SkAlphaType at) {
52*c8dee2aaSAndroid Build Coastguard Worker switch (at) {
53*c8dee2aaSAndroid Build Coastguard Worker case kUnknown_SkAlphaType: return "Unknown";
54*c8dee2aaSAndroid Build Coastguard Worker case kOpaque_SkAlphaType: return "Opaque";
55*c8dee2aaSAndroid Build Coastguard Worker case kPremul_SkAlphaType: return "Premul";
56*c8dee2aaSAndroid Build Coastguard Worker case kUnpremul_SkAlphaType: return "Unpremul";
57*c8dee2aaSAndroid Build Coastguard Worker }
58*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
59*c8dee2aaSAndroid Build Coastguard Worker }
60*c8dee2aaSAndroid Build Coastguard Worker
colortype_name(SkColorType ct)61*c8dee2aaSAndroid Build Coastguard Worker const char* colortype_name(SkColorType ct) {
62*c8dee2aaSAndroid Build Coastguard Worker switch (ct) {
63*c8dee2aaSAndroid Build Coastguard Worker case kUnknown_SkColorType: return "Unknown";
64*c8dee2aaSAndroid Build Coastguard Worker case kAlpha_8_SkColorType: return "Alpha_8";
65*c8dee2aaSAndroid Build Coastguard Worker case kA16_unorm_SkColorType: return "Alpha_16";
66*c8dee2aaSAndroid Build Coastguard Worker case kA16_float_SkColorType: return "A16_float";
67*c8dee2aaSAndroid Build Coastguard Worker case kRGB_565_SkColorType: return "RGB_565";
68*c8dee2aaSAndroid Build Coastguard Worker case kARGB_4444_SkColorType: return "ARGB_4444";
69*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_8888_SkColorType: return "RGBA_8888";
70*c8dee2aaSAndroid Build Coastguard Worker case kSRGBA_8888_SkColorType: return "SRGBA_8888";
71*c8dee2aaSAndroid Build Coastguard Worker case kRGB_888x_SkColorType: return "RGB_888x";
72*c8dee2aaSAndroid Build Coastguard Worker case kBGRA_8888_SkColorType: return "BGRA_8888";
73*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_1010102_SkColorType: return "RGBA_1010102";
74*c8dee2aaSAndroid Build Coastguard Worker case kBGRA_1010102_SkColorType: return "BGRA_1010102";
75*c8dee2aaSAndroid Build Coastguard Worker case kRGB_101010x_SkColorType: return "RGB_101010x";
76*c8dee2aaSAndroid Build Coastguard Worker case kBGR_101010x_SkColorType: return "BGR_101010x";
77*c8dee2aaSAndroid Build Coastguard Worker case kBGR_101010x_XR_SkColorType: return "BGR_101010x_XR";
78*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_10x6_SkColorType: return "RGBA_10x6";
79*c8dee2aaSAndroid Build Coastguard Worker case kGray_8_SkColorType: return "Gray_8";
80*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_F16Norm_SkColorType: return "RGBA_F16Norm";
81*c8dee2aaSAndroid Build Coastguard Worker case kRGB_F16F16F16x_SkColorType: return "RGB_F16F16F16x";
82*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_F16_SkColorType: return "RGBA_F16";
83*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_F32_SkColorType: return "RGBA_F32";
84*c8dee2aaSAndroid Build Coastguard Worker case kR8G8_unorm_SkColorType: return "R8G8_unorm";
85*c8dee2aaSAndroid Build Coastguard Worker case kR16G16_unorm_SkColorType: return "R16G16_unorm";
86*c8dee2aaSAndroid Build Coastguard Worker case kR16G16_float_SkColorType: return "R16G16_float";
87*c8dee2aaSAndroid Build Coastguard Worker case kR16G16B16A16_unorm_SkColorType: return "R16G16B16A16_unorm";
88*c8dee2aaSAndroid Build Coastguard Worker case kR8_unorm_SkColorType: return "R8_unorm";
89*c8dee2aaSAndroid Build Coastguard Worker case kBGRA_10101010_XR_SkColorType: return "BGRA_10101010_XR";
90*c8dee2aaSAndroid Build Coastguard Worker }
91*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
92*c8dee2aaSAndroid Build Coastguard Worker }
93*c8dee2aaSAndroid Build Coastguard Worker
colortype_depth(SkColorType ct)94*c8dee2aaSAndroid Build Coastguard Worker const char* colortype_depth(SkColorType ct) {
95*c8dee2aaSAndroid Build Coastguard Worker switch (ct) {
96*c8dee2aaSAndroid Build Coastguard Worker case kUnknown_SkColorType: return "Unknown";
97*c8dee2aaSAndroid Build Coastguard Worker case kAlpha_8_SkColorType: return "A8";
98*c8dee2aaSAndroid Build Coastguard Worker case kA16_unorm_SkColorType: return "A16";
99*c8dee2aaSAndroid Build Coastguard Worker case kA16_float_SkColorType: return "AF16";
100*c8dee2aaSAndroid Build Coastguard Worker case kRGB_565_SkColorType: return "565";
101*c8dee2aaSAndroid Build Coastguard Worker case kARGB_4444_SkColorType: return "4444";
102*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_8888_SkColorType: return "8888";
103*c8dee2aaSAndroid Build Coastguard Worker case kSRGBA_8888_SkColorType: return "8888";
104*c8dee2aaSAndroid Build Coastguard Worker case kRGB_888x_SkColorType: return "888";
105*c8dee2aaSAndroid Build Coastguard Worker case kBGRA_8888_SkColorType: return "8888";
106*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_1010102_SkColorType: return "1010102";
107*c8dee2aaSAndroid Build Coastguard Worker case kBGRA_1010102_SkColorType: return "1010102";
108*c8dee2aaSAndroid Build Coastguard Worker case kRGB_101010x_SkColorType: return "101010";
109*c8dee2aaSAndroid Build Coastguard Worker case kBGR_101010x_SkColorType: return "101010";
110*c8dee2aaSAndroid Build Coastguard Worker case kBGR_101010x_XR_SkColorType: return "101010";
111*c8dee2aaSAndroid Build Coastguard Worker case kBGRA_10101010_XR_SkColorType: return "10101010";
112*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_10x6_SkColorType: return "10101010";
113*c8dee2aaSAndroid Build Coastguard Worker case kGray_8_SkColorType: return "G8";
114*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_F16Norm_SkColorType: return "F16Norm";
115*c8dee2aaSAndroid Build Coastguard Worker case kRGB_F16F16F16x_SkColorType: return "F16F16F16x";
116*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_F16_SkColorType: return "F16";
117*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_F32_SkColorType: return "F32";
118*c8dee2aaSAndroid Build Coastguard Worker case kR8G8_unorm_SkColorType: return "88";
119*c8dee2aaSAndroid Build Coastguard Worker case kR16G16_unorm_SkColorType: return "1616";
120*c8dee2aaSAndroid Build Coastguard Worker case kR16G16_float_SkColorType: return "F16F16";
121*c8dee2aaSAndroid Build Coastguard Worker case kR16G16B16A16_unorm_SkColorType: return "16161616";
122*c8dee2aaSAndroid Build Coastguard Worker case kR8_unorm_SkColorType: return "R8";
123*c8dee2aaSAndroid Build Coastguard Worker }
124*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
125*c8dee2aaSAndroid Build Coastguard Worker }
126*c8dee2aaSAndroid Build Coastguard Worker
tilemode_name(SkTileMode mode)127*c8dee2aaSAndroid Build Coastguard Worker const char* tilemode_name(SkTileMode mode) {
128*c8dee2aaSAndroid Build Coastguard Worker switch (mode) {
129*c8dee2aaSAndroid Build Coastguard Worker case SkTileMode::kClamp: return "clamp";
130*c8dee2aaSAndroid Build Coastguard Worker case SkTileMode::kRepeat: return "repeat";
131*c8dee2aaSAndroid Build Coastguard Worker case SkTileMode::kMirror: return "mirror";
132*c8dee2aaSAndroid Build Coastguard Worker case SkTileMode::kDecal: return "decal";
133*c8dee2aaSAndroid Build Coastguard Worker }
134*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
135*c8dee2aaSAndroid Build Coastguard Worker }
136*c8dee2aaSAndroid Build Coastguard Worker
color_to_565(SkColor color)137*c8dee2aaSAndroid Build Coastguard Worker SkColor color_to_565(SkColor color) {
138*c8dee2aaSAndroid Build Coastguard Worker // Not a good idea to use this function for greyscale colors...
139*c8dee2aaSAndroid Build Coastguard Worker // it will add an obvious purple or green tint.
140*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(SkColorGetR(color) != SkColorGetG(color) || SkColorGetR(color) != SkColorGetB(color) ||
141*c8dee2aaSAndroid Build Coastguard Worker SkColorGetG(color) != SkColorGetB(color));
142*c8dee2aaSAndroid Build Coastguard Worker
143*c8dee2aaSAndroid Build Coastguard Worker SkPMColor pmColor = SkPreMultiplyColor(color);
144*c8dee2aaSAndroid Build Coastguard Worker U16CPU color16 = SkPixel32ToPixel16(pmColor);
145*c8dee2aaSAndroid Build Coastguard Worker return SkPixel16ToColor(color16);
146*c8dee2aaSAndroid Build Coastguard Worker }
147*c8dee2aaSAndroid Build Coastguard Worker
create_checkerboard_shader(SkColor c1,SkColor c2,int size)148*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> create_checkerboard_shader(SkColor c1, SkColor c2, int size) {
149*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm;
150*c8dee2aaSAndroid Build Coastguard Worker bm.allocPixels(SkImageInfo::MakeS32(2 * size, 2 * size, kPremul_SkAlphaType));
151*c8dee2aaSAndroid Build Coastguard Worker bm.eraseColor(c1);
152*c8dee2aaSAndroid Build Coastguard Worker bm.eraseArea(SkIRect::MakeLTRB(0, 0, size, size), c2);
153*c8dee2aaSAndroid Build Coastguard Worker bm.eraseArea(SkIRect::MakeLTRB(size, size, 2 * size, 2 * size), c2);
154*c8dee2aaSAndroid Build Coastguard Worker return bm.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, SkSamplingOptions());
155*c8dee2aaSAndroid Build Coastguard Worker }
156*c8dee2aaSAndroid Build Coastguard Worker
create_checkerboard_bitmap(int w,int h,SkColor c1,SkColor c2,int checkSize)157*c8dee2aaSAndroid Build Coastguard Worker SkBitmap create_checkerboard_bitmap(int w, int h, SkColor c1, SkColor c2, int checkSize) {
158*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bitmap;
159*c8dee2aaSAndroid Build Coastguard Worker bitmap.allocPixels(SkImageInfo::MakeS32(w, h, kPremul_SkAlphaType));
160*c8dee2aaSAndroid Build Coastguard Worker SkCanvas canvas(bitmap);
161*c8dee2aaSAndroid Build Coastguard Worker
162*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::draw_checkerboard(&canvas, c1, c2, checkSize);
163*c8dee2aaSAndroid Build Coastguard Worker return bitmap;
164*c8dee2aaSAndroid Build Coastguard Worker }
165*c8dee2aaSAndroid Build Coastguard Worker
create_checkerboard_image(int w,int h,SkColor c1,SkColor c2,int checkSize)166*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> create_checkerboard_image(int w, int h, SkColor c1, SkColor c2, int checkSize) {
167*c8dee2aaSAndroid Build Coastguard Worker auto surf = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(w, h));
168*c8dee2aaSAndroid Build Coastguard Worker ToolUtils::draw_checkerboard(surf->getCanvas(), c1, c2, checkSize);
169*c8dee2aaSAndroid Build Coastguard Worker return surf->makeImageSnapshot();
170*c8dee2aaSAndroid Build Coastguard Worker }
171*c8dee2aaSAndroid Build Coastguard Worker
draw_checkerboard(SkCanvas * canvas,SkColor c1,SkColor c2,int size)172*c8dee2aaSAndroid Build Coastguard Worker void draw_checkerboard(SkCanvas* canvas, SkColor c1, SkColor c2, int size) {
173*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
174*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(create_checkerboard_shader(c1, c2, size));
175*c8dee2aaSAndroid Build Coastguard Worker paint.setBlendMode(SkBlendMode::kSrc);
176*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPaint(paint);
177*c8dee2aaSAndroid Build Coastguard Worker }
178*c8dee2aaSAndroid Build Coastguard Worker
make_pixmaps(SkColorType ct,SkAlphaType at,bool withMips,const SkColor4f colors[6],SkPixmap pixmaps[6],std::unique_ptr<char[]> * mem)179*c8dee2aaSAndroid Build Coastguard Worker int make_pixmaps(SkColorType ct,
180*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType at,
181*c8dee2aaSAndroid Build Coastguard Worker bool withMips,
182*c8dee2aaSAndroid Build Coastguard Worker const SkColor4f colors[6],
183*c8dee2aaSAndroid Build Coastguard Worker SkPixmap pixmaps[6],
184*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<char[]>* mem) {
185*c8dee2aaSAndroid Build Coastguard Worker
186*c8dee2aaSAndroid Build Coastguard Worker int levelSize = 32;
187*c8dee2aaSAndroid Build Coastguard Worker int numMipLevels = withMips ? 6 : 1;
188*c8dee2aaSAndroid Build Coastguard Worker size_t size = 0;
189*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo ii[6];
190*c8dee2aaSAndroid Build Coastguard Worker size_t rowBytes[6];
191*c8dee2aaSAndroid Build Coastguard Worker for (int level = 0; level < numMipLevels; ++level) {
192*c8dee2aaSAndroid Build Coastguard Worker ii[level] = SkImageInfo::Make(levelSize, levelSize, ct, at);
193*c8dee2aaSAndroid Build Coastguard Worker rowBytes[level] = ii[level].minRowBytes();
194*c8dee2aaSAndroid Build Coastguard Worker // Make sure we test row bytes that aren't tight.
195*c8dee2aaSAndroid Build Coastguard Worker if (!(level % 2)) {
196*c8dee2aaSAndroid Build Coastguard Worker rowBytes[level] += (level + 1)*SkColorTypeBytesPerPixel(ii[level].colorType());
197*c8dee2aaSAndroid Build Coastguard Worker }
198*c8dee2aaSAndroid Build Coastguard Worker size += rowBytes[level]*ii[level].height();
199*c8dee2aaSAndroid Build Coastguard Worker levelSize /= 2;
200*c8dee2aaSAndroid Build Coastguard Worker }
201*c8dee2aaSAndroid Build Coastguard Worker mem->reset(new char[size]);
202*c8dee2aaSAndroid Build Coastguard Worker char* addr = mem->get();
203*c8dee2aaSAndroid Build Coastguard Worker for (int level = 0; level < numMipLevels; ++level) {
204*c8dee2aaSAndroid Build Coastguard Worker pixmaps[level].reset(ii[level], addr, rowBytes[level]);
205*c8dee2aaSAndroid Build Coastguard Worker addr += rowBytes[level]*ii[level].height();
206*c8dee2aaSAndroid Build Coastguard Worker pixmaps[level].erase(colors[level]);
207*c8dee2aaSAndroid Build Coastguard Worker }
208*c8dee2aaSAndroid Build Coastguard Worker return numMipLevels;
209*c8dee2aaSAndroid Build Coastguard Worker }
210*c8dee2aaSAndroid Build Coastguard Worker
add_to_text_blob_w_len(SkTextBlobBuilder * builder,const char * text,size_t len,SkTextEncoding encoding,const SkFont & font,SkScalar x,SkScalar y)211*c8dee2aaSAndroid Build Coastguard Worker void add_to_text_blob_w_len(SkTextBlobBuilder* builder,
212*c8dee2aaSAndroid Build Coastguard Worker const char* text,
213*c8dee2aaSAndroid Build Coastguard Worker size_t len,
214*c8dee2aaSAndroid Build Coastguard Worker SkTextEncoding encoding,
215*c8dee2aaSAndroid Build Coastguard Worker const SkFont& font,
216*c8dee2aaSAndroid Build Coastguard Worker SkScalar x,
217*c8dee2aaSAndroid Build Coastguard Worker SkScalar y) {
218*c8dee2aaSAndroid Build Coastguard Worker int count = font.countText(text, len, encoding);
219*c8dee2aaSAndroid Build Coastguard Worker if (count < 1) {
220*c8dee2aaSAndroid Build Coastguard Worker return;
221*c8dee2aaSAndroid Build Coastguard Worker }
222*c8dee2aaSAndroid Build Coastguard Worker auto run = builder->allocRun(font, count, x, y);
223*c8dee2aaSAndroid Build Coastguard Worker font.textToGlyphs(text, len, encoding, run.glyphs, count);
224*c8dee2aaSAndroid Build Coastguard Worker }
225*c8dee2aaSAndroid Build Coastguard Worker
add_to_text_blob(SkTextBlobBuilder * builder,const char * text,const SkFont & font,SkScalar x,SkScalar y)226*c8dee2aaSAndroid Build Coastguard Worker void add_to_text_blob(SkTextBlobBuilder* builder,
227*c8dee2aaSAndroid Build Coastguard Worker const char* text,
228*c8dee2aaSAndroid Build Coastguard Worker const SkFont& font,
229*c8dee2aaSAndroid Build Coastguard Worker SkScalar x,
230*c8dee2aaSAndroid Build Coastguard Worker SkScalar y) {
231*c8dee2aaSAndroid Build Coastguard Worker add_to_text_blob_w_len(builder, text, strlen(text), SkTextEncoding::kUTF8, font, x, y);
232*c8dee2aaSAndroid Build Coastguard Worker }
233*c8dee2aaSAndroid Build Coastguard Worker
get_text_path(const SkFont & font,const void * text,size_t length,SkTextEncoding encoding,SkPath * dst,const SkPoint pos[])234*c8dee2aaSAndroid Build Coastguard Worker void get_text_path(const SkFont& font,
235*c8dee2aaSAndroid Build Coastguard Worker const void* text,
236*c8dee2aaSAndroid Build Coastguard Worker size_t length,
237*c8dee2aaSAndroid Build Coastguard Worker SkTextEncoding encoding,
238*c8dee2aaSAndroid Build Coastguard Worker SkPath* dst,
239*c8dee2aaSAndroid Build Coastguard Worker const SkPoint pos[]) {
240*c8dee2aaSAndroid Build Coastguard Worker SkAutoToGlyphs atg(font, text, length, encoding);
241*c8dee2aaSAndroid Build Coastguard Worker const int count = atg.count();
242*c8dee2aaSAndroid Build Coastguard Worker AutoTArray<SkPoint> computedPos;
243*c8dee2aaSAndroid Build Coastguard Worker if (pos == nullptr) {
244*c8dee2aaSAndroid Build Coastguard Worker computedPos.reset(count);
245*c8dee2aaSAndroid Build Coastguard Worker font.getPos(atg.glyphs(), count, &computedPos[0]);
246*c8dee2aaSAndroid Build Coastguard Worker pos = computedPos.get();
247*c8dee2aaSAndroid Build Coastguard Worker }
248*c8dee2aaSAndroid Build Coastguard Worker
249*c8dee2aaSAndroid Build Coastguard Worker struct Rec {
250*c8dee2aaSAndroid Build Coastguard Worker SkPath* fDst;
251*c8dee2aaSAndroid Build Coastguard Worker const SkPoint* fPos;
252*c8dee2aaSAndroid Build Coastguard Worker } rec = {dst, pos};
253*c8dee2aaSAndroid Build Coastguard Worker font.getPaths(atg.glyphs(),
254*c8dee2aaSAndroid Build Coastguard Worker atg.count(),
255*c8dee2aaSAndroid Build Coastguard Worker [](const SkPath* src, const SkMatrix& mx, void* ctx) {
256*c8dee2aaSAndroid Build Coastguard Worker Rec* rec = (Rec*)ctx;
257*c8dee2aaSAndroid Build Coastguard Worker if (src) {
258*c8dee2aaSAndroid Build Coastguard Worker SkMatrix tmp(mx);
259*c8dee2aaSAndroid Build Coastguard Worker tmp.postTranslate(rec->fPos->fX, rec->fPos->fY);
260*c8dee2aaSAndroid Build Coastguard Worker rec->fDst->addPath(*src, tmp);
261*c8dee2aaSAndroid Build Coastguard Worker }
262*c8dee2aaSAndroid Build Coastguard Worker rec->fPos += 1;
263*c8dee2aaSAndroid Build Coastguard Worker },
264*c8dee2aaSAndroid Build Coastguard Worker &rec);
265*c8dee2aaSAndroid Build Coastguard Worker }
266*c8dee2aaSAndroid Build Coastguard Worker
make_star(const SkRect & bounds,int numPts,int step)267*c8dee2aaSAndroid Build Coastguard Worker SkPath make_star(const SkRect& bounds, int numPts, int step) {
268*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(numPts != step);
269*c8dee2aaSAndroid Build Coastguard Worker SkPathBuilder builder;
270*c8dee2aaSAndroid Build Coastguard Worker builder.setFillType(SkPathFillType::kEvenOdd);
271*c8dee2aaSAndroid Build Coastguard Worker builder.moveTo(0, -1);
272*c8dee2aaSAndroid Build Coastguard Worker for (int i = 1; i < numPts; ++i) {
273*c8dee2aaSAndroid Build Coastguard Worker int idx = i * step % numPts;
274*c8dee2aaSAndroid Build Coastguard Worker SkScalar theta = idx * 2 * SK_ScalarPI / numPts + SK_ScalarPI / 2;
275*c8dee2aaSAndroid Build Coastguard Worker SkScalar x = SkScalarCos(theta);
276*c8dee2aaSAndroid Build Coastguard Worker SkScalar y = -SkScalarSin(theta);
277*c8dee2aaSAndroid Build Coastguard Worker builder.lineTo(x, y);
278*c8dee2aaSAndroid Build Coastguard Worker }
279*c8dee2aaSAndroid Build Coastguard Worker SkPath path = builder.detach();
280*c8dee2aaSAndroid Build Coastguard Worker path.transform(SkMatrix::RectToRect(path.getBounds(), bounds));
281*c8dee2aaSAndroid Build Coastguard Worker return path;
282*c8dee2aaSAndroid Build Coastguard Worker }
283*c8dee2aaSAndroid Build Coastguard Worker
norm_to_rgb(SkBitmap * bm,int x,int y,const SkVector3 & norm)284*c8dee2aaSAndroid Build Coastguard Worker static inline void norm_to_rgb(SkBitmap* bm, int x, int y, const SkVector3& norm) {
285*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(SkScalarNearlyEqual(norm.length(), 1.0f));
286*c8dee2aaSAndroid Build Coastguard Worker unsigned char r = static_cast<unsigned char>((0.5f * norm.fX + 0.5f) * 255);
287*c8dee2aaSAndroid Build Coastguard Worker unsigned char g = static_cast<unsigned char>((-0.5f * norm.fY + 0.5f) * 255);
288*c8dee2aaSAndroid Build Coastguard Worker unsigned char b = static_cast<unsigned char>((0.5f * norm.fZ + 0.5f) * 255);
289*c8dee2aaSAndroid Build Coastguard Worker *bm->getAddr32(x, y) = SkPackARGB32(0xFF, r, g, b);
290*c8dee2aaSAndroid Build Coastguard Worker }
291*c8dee2aaSAndroid Build Coastguard Worker
create_hemi_normal_map(SkBitmap * bm,const SkIRect & dst)292*c8dee2aaSAndroid Build Coastguard Worker void create_hemi_normal_map(SkBitmap* bm, const SkIRect& dst) {
293*c8dee2aaSAndroid Build Coastguard Worker const SkPoint center =
294*c8dee2aaSAndroid Build Coastguard Worker SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), dst.fTop + (dst.height() / 2.0f));
295*c8dee2aaSAndroid Build Coastguard Worker const SkPoint halfSize = SkPoint::Make(dst.width() / 2.0f, dst.height() / 2.0f);
296*c8dee2aaSAndroid Build Coastguard Worker
297*c8dee2aaSAndroid Build Coastguard Worker SkVector3 norm;
298*c8dee2aaSAndroid Build Coastguard Worker
299*c8dee2aaSAndroid Build Coastguard Worker for (int y = dst.fTop; y < dst.fBottom; ++y) {
300*c8dee2aaSAndroid Build Coastguard Worker for (int x = dst.fLeft; x < dst.fRight; ++x) {
301*c8dee2aaSAndroid Build Coastguard Worker norm.fX = (x + 0.5f - center.fX) / halfSize.fX;
302*c8dee2aaSAndroid Build Coastguard Worker norm.fY = (y + 0.5f - center.fY) / halfSize.fY;
303*c8dee2aaSAndroid Build Coastguard Worker
304*c8dee2aaSAndroid Build Coastguard Worker SkScalar tmp = norm.fX * norm.fX + norm.fY * norm.fY;
305*c8dee2aaSAndroid Build Coastguard Worker if (tmp >= 1.0f) {
306*c8dee2aaSAndroid Build Coastguard Worker norm.set(0.0f, 0.0f, 1.0f);
307*c8dee2aaSAndroid Build Coastguard Worker } else {
308*c8dee2aaSAndroid Build Coastguard Worker norm.fZ = sqrtf(1.0f - tmp);
309*c8dee2aaSAndroid Build Coastguard Worker }
310*c8dee2aaSAndroid Build Coastguard Worker
311*c8dee2aaSAndroid Build Coastguard Worker norm_to_rgb(bm, x, y, norm);
312*c8dee2aaSAndroid Build Coastguard Worker }
313*c8dee2aaSAndroid Build Coastguard Worker }
314*c8dee2aaSAndroid Build Coastguard Worker }
315*c8dee2aaSAndroid Build Coastguard Worker
create_frustum_normal_map(SkBitmap * bm,const SkIRect & dst)316*c8dee2aaSAndroid Build Coastguard Worker void create_frustum_normal_map(SkBitmap* bm, const SkIRect& dst) {
317*c8dee2aaSAndroid Build Coastguard Worker const SkPoint center =
318*c8dee2aaSAndroid Build Coastguard Worker SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), dst.fTop + (dst.height() / 2.0f));
319*c8dee2aaSAndroid Build Coastguard Worker
320*c8dee2aaSAndroid Build Coastguard Worker SkIRect inner = dst;
321*c8dee2aaSAndroid Build Coastguard Worker inner.inset(dst.width() / 4, dst.height() / 4);
322*c8dee2aaSAndroid Build Coastguard Worker
323*c8dee2aaSAndroid Build Coastguard Worker SkPoint3 norm;
324*c8dee2aaSAndroid Build Coastguard Worker const SkPoint3 left = SkPoint3::Make(-SK_ScalarRoot2Over2, 0.0f, SK_ScalarRoot2Over2);
325*c8dee2aaSAndroid Build Coastguard Worker const SkPoint3 up = SkPoint3::Make(0.0f, -SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
326*c8dee2aaSAndroid Build Coastguard Worker const SkPoint3 right = SkPoint3::Make(SK_ScalarRoot2Over2, 0.0f, SK_ScalarRoot2Over2);
327*c8dee2aaSAndroid Build Coastguard Worker const SkPoint3 down = SkPoint3::Make(0.0f, SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
328*c8dee2aaSAndroid Build Coastguard Worker
329*c8dee2aaSAndroid Build Coastguard Worker for (int y = dst.fTop; y < dst.fBottom; ++y) {
330*c8dee2aaSAndroid Build Coastguard Worker for (int x = dst.fLeft; x < dst.fRight; ++x) {
331*c8dee2aaSAndroid Build Coastguard Worker if (inner.contains(x, y)) {
332*c8dee2aaSAndroid Build Coastguard Worker norm.set(0.0f, 0.0f, 1.0f);
333*c8dee2aaSAndroid Build Coastguard Worker } else {
334*c8dee2aaSAndroid Build Coastguard Worker SkScalar locX = x + 0.5f - center.fX;
335*c8dee2aaSAndroid Build Coastguard Worker SkScalar locY = y + 0.5f - center.fY;
336*c8dee2aaSAndroid Build Coastguard Worker
337*c8dee2aaSAndroid Build Coastguard Worker if (locX >= 0.0f) {
338*c8dee2aaSAndroid Build Coastguard Worker if (locY > 0.0f) {
339*c8dee2aaSAndroid Build Coastguard Worker norm = locX >= locY ? right : down; // LR corner
340*c8dee2aaSAndroid Build Coastguard Worker } else {
341*c8dee2aaSAndroid Build Coastguard Worker norm = locX > -locY ? right : up; // UR corner
342*c8dee2aaSAndroid Build Coastguard Worker }
343*c8dee2aaSAndroid Build Coastguard Worker } else {
344*c8dee2aaSAndroid Build Coastguard Worker if (locY > 0.0f) {
345*c8dee2aaSAndroid Build Coastguard Worker norm = -locX > locY ? left : down; // LL corner
346*c8dee2aaSAndroid Build Coastguard Worker } else {
347*c8dee2aaSAndroid Build Coastguard Worker norm = locX > locY ? up : left; // UL corner
348*c8dee2aaSAndroid Build Coastguard Worker }
349*c8dee2aaSAndroid Build Coastguard Worker }
350*c8dee2aaSAndroid Build Coastguard Worker }
351*c8dee2aaSAndroid Build Coastguard Worker
352*c8dee2aaSAndroid Build Coastguard Worker norm_to_rgb(bm, x, y, norm);
353*c8dee2aaSAndroid Build Coastguard Worker }
354*c8dee2aaSAndroid Build Coastguard Worker }
355*c8dee2aaSAndroid Build Coastguard Worker }
356*c8dee2aaSAndroid Build Coastguard Worker
create_tetra_normal_map(SkBitmap * bm,const SkIRect & dst)357*c8dee2aaSAndroid Build Coastguard Worker void create_tetra_normal_map(SkBitmap* bm, const SkIRect& dst) {
358*c8dee2aaSAndroid Build Coastguard Worker const SkPoint center =
359*c8dee2aaSAndroid Build Coastguard Worker SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), dst.fTop + (dst.height() / 2.0f));
360*c8dee2aaSAndroid Build Coastguard Worker
361*c8dee2aaSAndroid Build Coastguard Worker static const SkScalar k1OverRoot3 = 0.5773502692f;
362*c8dee2aaSAndroid Build Coastguard Worker
363*c8dee2aaSAndroid Build Coastguard Worker SkPoint3 norm;
364*c8dee2aaSAndroid Build Coastguard Worker const SkPoint3 leftUp = SkPoint3::Make(-k1OverRoot3, -k1OverRoot3, k1OverRoot3);
365*c8dee2aaSAndroid Build Coastguard Worker const SkPoint3 rightUp = SkPoint3::Make(k1OverRoot3, -k1OverRoot3, k1OverRoot3);
366*c8dee2aaSAndroid Build Coastguard Worker const SkPoint3 down = SkPoint3::Make(0.0f, SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
367*c8dee2aaSAndroid Build Coastguard Worker
368*c8dee2aaSAndroid Build Coastguard Worker for (int y = dst.fTop; y < dst.fBottom; ++y) {
369*c8dee2aaSAndroid Build Coastguard Worker for (int x = dst.fLeft; x < dst.fRight; ++x) {
370*c8dee2aaSAndroid Build Coastguard Worker SkScalar locX = x + 0.5f - center.fX;
371*c8dee2aaSAndroid Build Coastguard Worker SkScalar locY = y + 0.5f - center.fY;
372*c8dee2aaSAndroid Build Coastguard Worker
373*c8dee2aaSAndroid Build Coastguard Worker if (locX >= 0.0f) {
374*c8dee2aaSAndroid Build Coastguard Worker if (locY > 0.0f) {
375*c8dee2aaSAndroid Build Coastguard Worker norm = locX >= locY ? rightUp : down; // LR corner
376*c8dee2aaSAndroid Build Coastguard Worker } else {
377*c8dee2aaSAndroid Build Coastguard Worker norm = rightUp;
378*c8dee2aaSAndroid Build Coastguard Worker }
379*c8dee2aaSAndroid Build Coastguard Worker } else {
380*c8dee2aaSAndroid Build Coastguard Worker if (locY > 0.0f) {
381*c8dee2aaSAndroid Build Coastguard Worker norm = -locX > locY ? leftUp : down; // LL corner
382*c8dee2aaSAndroid Build Coastguard Worker } else {
383*c8dee2aaSAndroid Build Coastguard Worker norm = leftUp;
384*c8dee2aaSAndroid Build Coastguard Worker }
385*c8dee2aaSAndroid Build Coastguard Worker }
386*c8dee2aaSAndroid Build Coastguard Worker
387*c8dee2aaSAndroid Build Coastguard Worker norm_to_rgb(bm, x, y, norm);
388*c8dee2aaSAndroid Build Coastguard Worker }
389*c8dee2aaSAndroid Build Coastguard Worker }
390*c8dee2aaSAndroid Build Coastguard Worker }
391*c8dee2aaSAndroid Build Coastguard Worker
copy_to(SkBitmap * dst,SkColorType dstColorType,const SkBitmap & src)392*c8dee2aaSAndroid Build Coastguard Worker bool copy_to(SkBitmap* dst, SkColorType dstColorType, const SkBitmap& src) {
393*c8dee2aaSAndroid Build Coastguard Worker SkPixmap srcPM;
394*c8dee2aaSAndroid Build Coastguard Worker if (!src.peekPixels(&srcPM)) {
395*c8dee2aaSAndroid Build Coastguard Worker return false;
396*c8dee2aaSAndroid Build Coastguard Worker }
397*c8dee2aaSAndroid Build Coastguard Worker
398*c8dee2aaSAndroid Build Coastguard Worker SkBitmap tmpDst;
399*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType);
400*c8dee2aaSAndroid Build Coastguard Worker if (!tmpDst.setInfo(dstInfo)) {
401*c8dee2aaSAndroid Build Coastguard Worker return false;
402*c8dee2aaSAndroid Build Coastguard Worker }
403*c8dee2aaSAndroid Build Coastguard Worker
404*c8dee2aaSAndroid Build Coastguard Worker if (!tmpDst.tryAllocPixels()) {
405*c8dee2aaSAndroid Build Coastguard Worker return false;
406*c8dee2aaSAndroid Build Coastguard Worker }
407*c8dee2aaSAndroid Build Coastguard Worker
408*c8dee2aaSAndroid Build Coastguard Worker SkPixmap dstPM;
409*c8dee2aaSAndroid Build Coastguard Worker if (!tmpDst.peekPixels(&dstPM)) {
410*c8dee2aaSAndroid Build Coastguard Worker return false;
411*c8dee2aaSAndroid Build Coastguard Worker }
412*c8dee2aaSAndroid Build Coastguard Worker
413*c8dee2aaSAndroid Build Coastguard Worker if (!srcPM.readPixels(dstPM)) {
414*c8dee2aaSAndroid Build Coastguard Worker return false;
415*c8dee2aaSAndroid Build Coastguard Worker }
416*c8dee2aaSAndroid Build Coastguard Worker
417*c8dee2aaSAndroid Build Coastguard Worker dst->swap(tmpDst);
418*c8dee2aaSAndroid Build Coastguard Worker return true;
419*c8dee2aaSAndroid Build Coastguard Worker }
420*c8dee2aaSAndroid Build Coastguard Worker
copy_to_g8(SkBitmap * dst,const SkBitmap & src)421*c8dee2aaSAndroid Build Coastguard Worker void copy_to_g8(SkBitmap* dst, const SkBitmap& src) {
422*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(kBGRA_8888_SkColorType == src.colorType() ||
423*c8dee2aaSAndroid Build Coastguard Worker kRGBA_8888_SkColorType == src.colorType());
424*c8dee2aaSAndroid Build Coastguard Worker
425*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo grayInfo = src.info().makeColorType(kGray_8_SkColorType);
426*c8dee2aaSAndroid Build Coastguard Worker dst->allocPixels(grayInfo);
427*c8dee2aaSAndroid Build Coastguard Worker uint8_t* dst8 = (uint8_t*)dst->getPixels();
428*c8dee2aaSAndroid Build Coastguard Worker const uint32_t* src32 = (const uint32_t*)src.getPixels();
429*c8dee2aaSAndroid Build Coastguard Worker
430*c8dee2aaSAndroid Build Coastguard Worker const int w = src.width();
431*c8dee2aaSAndroid Build Coastguard Worker const int h = src.height();
432*c8dee2aaSAndroid Build Coastguard Worker const bool isBGRA = (kBGRA_8888_SkColorType == src.colorType());
433*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < h; ++y) {
434*c8dee2aaSAndroid Build Coastguard Worker if (isBGRA) {
435*c8dee2aaSAndroid Build Coastguard Worker // BGRA
436*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < w; ++x) {
437*c8dee2aaSAndroid Build Coastguard Worker uint32_t s = src32[x];
438*c8dee2aaSAndroid Build Coastguard Worker dst8[x] = SkComputeLuminance((s >> 16) & 0xFF, (s >> 8) & 0xFF, s & 0xFF);
439*c8dee2aaSAndroid Build Coastguard Worker }
440*c8dee2aaSAndroid Build Coastguard Worker } else {
441*c8dee2aaSAndroid Build Coastguard Worker // RGBA
442*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < w; ++x) {
443*c8dee2aaSAndroid Build Coastguard Worker uint32_t s = src32[x];
444*c8dee2aaSAndroid Build Coastguard Worker dst8[x] = SkComputeLuminance(s & 0xFF, (s >> 8) & 0xFF, (s >> 16) & 0xFF);
445*c8dee2aaSAndroid Build Coastguard Worker }
446*c8dee2aaSAndroid Build Coastguard Worker }
447*c8dee2aaSAndroid Build Coastguard Worker src32 = (const uint32_t*)((const char*)src32 + src.rowBytes());
448*c8dee2aaSAndroid Build Coastguard Worker dst8 += dst->rowBytes();
449*c8dee2aaSAndroid Build Coastguard Worker }
450*c8dee2aaSAndroid Build Coastguard Worker }
451*c8dee2aaSAndroid Build Coastguard Worker
452*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////////////////////
453*c8dee2aaSAndroid Build Coastguard Worker
equal_pixels(const SkPixmap & a,const SkPixmap & b)454*c8dee2aaSAndroid Build Coastguard Worker bool equal_pixels(const SkPixmap& a, const SkPixmap& b) {
455*c8dee2aaSAndroid Build Coastguard Worker if (a.width() != b.width() || a.height() != b.height()) {
456*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("[ToolUtils::equal_pixels] Dimensions do not match (%d x %d) != (%d x %d)\n",
457*c8dee2aaSAndroid Build Coastguard Worker a.width(), a.height(), b.width(), b.height());
458*c8dee2aaSAndroid Build Coastguard Worker return false;
459*c8dee2aaSAndroid Build Coastguard Worker }
460*c8dee2aaSAndroid Build Coastguard Worker
461*c8dee2aaSAndroid Build Coastguard Worker if (a.colorType() != b.colorType()) {
462*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("[ToolUtils::equal_pixels] colorType does not match %d != %d\n",
463*c8dee2aaSAndroid Build Coastguard Worker (int) a.colorType(), (int) b.colorType());
464*c8dee2aaSAndroid Build Coastguard Worker return false;
465*c8dee2aaSAndroid Build Coastguard Worker }
466*c8dee2aaSAndroid Build Coastguard Worker
467*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < a.height(); ++y) {
468*c8dee2aaSAndroid Build Coastguard Worker const char* aptr = (const char*)a.addr(0, y);
469*c8dee2aaSAndroid Build Coastguard Worker const char* bptr = (const char*)b.addr(0, y);
470*c8dee2aaSAndroid Build Coastguard Worker if (0 != memcmp(aptr, bptr, a.width() * a.info().bytesPerPixel())) {
471*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("[ToolUtils::equal_pixels] row %d does not match byte for byte\n", y);
472*c8dee2aaSAndroid Build Coastguard Worker return false;
473*c8dee2aaSAndroid Build Coastguard Worker }
474*c8dee2aaSAndroid Build Coastguard Worker }
475*c8dee2aaSAndroid Build Coastguard Worker return true;
476*c8dee2aaSAndroid Build Coastguard Worker }
477*c8dee2aaSAndroid Build Coastguard Worker
equal_pixels(const SkBitmap & bm0,const SkBitmap & bm1)478*c8dee2aaSAndroid Build Coastguard Worker bool equal_pixels(const SkBitmap& bm0, const SkBitmap& bm1) {
479*c8dee2aaSAndroid Build Coastguard Worker SkPixmap pm0, pm1;
480*c8dee2aaSAndroid Build Coastguard Worker if (!bm0.peekPixels(&pm0)) {
481*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Could not read pixels from A\n");
482*c8dee2aaSAndroid Build Coastguard Worker return false;
483*c8dee2aaSAndroid Build Coastguard Worker }
484*c8dee2aaSAndroid Build Coastguard Worker if (!bm1.peekPixels(&pm1)) {
485*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Could not read pixels from B\n");
486*c8dee2aaSAndroid Build Coastguard Worker return false;
487*c8dee2aaSAndroid Build Coastguard Worker }
488*c8dee2aaSAndroid Build Coastguard Worker return equal_pixels(pm0, pm1);
489*c8dee2aaSAndroid Build Coastguard Worker }
490*c8dee2aaSAndroid Build Coastguard Worker
equal_pixels(const SkImage * a,const SkImage * b)491*c8dee2aaSAndroid Build Coastguard Worker bool equal_pixels(const SkImage* a, const SkImage* b) {
492*c8dee2aaSAndroid Build Coastguard Worker SkASSERT_RELEASE(a);
493*c8dee2aaSAndroid Build Coastguard Worker SkASSERT_RELEASE(b);
494*c8dee2aaSAndroid Build Coastguard Worker // ensure that peekPixels will succeed
495*c8dee2aaSAndroid Build Coastguard Worker auto imga = a->makeRasterImage();
496*c8dee2aaSAndroid Build Coastguard Worker auto imgb = b->makeRasterImage();
497*c8dee2aaSAndroid Build Coastguard Worker
498*c8dee2aaSAndroid Build Coastguard Worker SkPixmap pm0, pm1;
499*c8dee2aaSAndroid Build Coastguard Worker if (!imga->peekPixels(&pm0)) {
500*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Could not read pixels from A\n");
501*c8dee2aaSAndroid Build Coastguard Worker return false;
502*c8dee2aaSAndroid Build Coastguard Worker }
503*c8dee2aaSAndroid Build Coastguard Worker if (!imgb->peekPixels(&pm1)) {
504*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Could not read pixels from B\n");
505*c8dee2aaSAndroid Build Coastguard Worker return false;
506*c8dee2aaSAndroid Build Coastguard Worker }
507*c8dee2aaSAndroid Build Coastguard Worker return equal_pixels(pm0, pm1);
508*c8dee2aaSAndroid Build Coastguard Worker }
509*c8dee2aaSAndroid Build Coastguard Worker
makeSurface(SkCanvas * canvas,const SkImageInfo & info,const SkSurfaceProps * props)510*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> makeSurface(SkCanvas* canvas,
511*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo& info,
512*c8dee2aaSAndroid Build Coastguard Worker const SkSurfaceProps* props) {
513*c8dee2aaSAndroid Build Coastguard Worker auto surf = canvas->makeSurface(info, props);
514*c8dee2aaSAndroid Build Coastguard Worker if (!surf) {
515*c8dee2aaSAndroid Build Coastguard Worker surf = SkSurfaces::Raster(info, props);
516*c8dee2aaSAndroid Build Coastguard Worker }
517*c8dee2aaSAndroid Build Coastguard Worker return surf;
518*c8dee2aaSAndroid Build Coastguard Worker }
519*c8dee2aaSAndroid Build Coastguard Worker
VariationSliders(SkTypeface * typeface,SkFontArguments::VariationPosition variationPosition)520*c8dee2aaSAndroid Build Coastguard Worker VariationSliders::VariationSliders(SkTypeface* typeface,
521*c8dee2aaSAndroid Build Coastguard Worker SkFontArguments::VariationPosition variationPosition) {
522*c8dee2aaSAndroid Build Coastguard Worker if (!typeface) {
523*c8dee2aaSAndroid Build Coastguard Worker return;
524*c8dee2aaSAndroid Build Coastguard Worker }
525*c8dee2aaSAndroid Build Coastguard Worker
526*c8dee2aaSAndroid Build Coastguard Worker int numAxes = typeface->getVariationDesignParameters(nullptr, 0);
527*c8dee2aaSAndroid Build Coastguard Worker if (numAxes < 0) {
528*c8dee2aaSAndroid Build Coastguard Worker return;
529*c8dee2aaSAndroid Build Coastguard Worker }
530*c8dee2aaSAndroid Build Coastguard Worker
531*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkFontParameters::Variation::Axis[]> copiedAxes =
532*c8dee2aaSAndroid Build Coastguard Worker std::make_unique<SkFontParameters::Variation::Axis[]>(numAxes);
533*c8dee2aaSAndroid Build Coastguard Worker
534*c8dee2aaSAndroid Build Coastguard Worker numAxes = typeface->getVariationDesignParameters(copiedAxes.get(), numAxes);
535*c8dee2aaSAndroid Build Coastguard Worker if (numAxes < 0) {
536*c8dee2aaSAndroid Build Coastguard Worker return;
537*c8dee2aaSAndroid Build Coastguard Worker }
538*c8dee2aaSAndroid Build Coastguard Worker
539*c8dee2aaSAndroid Build Coastguard Worker auto argVariationPositionOrDefault = [&variationPosition](SkFourByteTag tag,
540*c8dee2aaSAndroid Build Coastguard Worker SkScalar defaultValue) -> SkScalar {
541*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < variationPosition.coordinateCount; ++i) {
542*c8dee2aaSAndroid Build Coastguard Worker if (variationPosition.coordinates[i].axis == tag) {
543*c8dee2aaSAndroid Build Coastguard Worker return variationPosition.coordinates[i].value;
544*c8dee2aaSAndroid Build Coastguard Worker }
545*c8dee2aaSAndroid Build Coastguard Worker }
546*c8dee2aaSAndroid Build Coastguard Worker return defaultValue;
547*c8dee2aaSAndroid Build Coastguard Worker };
548*c8dee2aaSAndroid Build Coastguard Worker
549*c8dee2aaSAndroid Build Coastguard Worker fAxisSliders.resize(numAxes);
550*c8dee2aaSAndroid Build Coastguard Worker fCoords = std::make_unique<SkFontArguments::VariationPosition::Coordinate[]>(numAxes);
551*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < numAxes; ++i) {
552*c8dee2aaSAndroid Build Coastguard Worker fAxisSliders[i].axis = copiedAxes[i];
553*c8dee2aaSAndroid Build Coastguard Worker fAxisSliders[i].current =
554*c8dee2aaSAndroid Build Coastguard Worker argVariationPositionOrDefault(copiedAxes[i].tag, copiedAxes[i].def);
555*c8dee2aaSAndroid Build Coastguard Worker fAxisSliders[i].name = tagToString(fAxisSliders[i].axis.tag);
556*c8dee2aaSAndroid Build Coastguard Worker fCoords[i] = { fAxisSliders[i].axis.tag, fAxisSliders[i].current };
557*c8dee2aaSAndroid Build Coastguard Worker }
558*c8dee2aaSAndroid Build Coastguard Worker }
559*c8dee2aaSAndroid Build Coastguard Worker
560*c8dee2aaSAndroid Build Coastguard Worker /* static */
tagToString(SkFourByteTag tag)561*c8dee2aaSAndroid Build Coastguard Worker SkString VariationSliders::tagToString(SkFourByteTag tag) {
562*c8dee2aaSAndroid Build Coastguard Worker char tagAsString[5];
563*c8dee2aaSAndroid Build Coastguard Worker tagAsString[4] = 0;
564*c8dee2aaSAndroid Build Coastguard Worker tagAsString[0] = (char)(uint8_t)(tag >> 24);
565*c8dee2aaSAndroid Build Coastguard Worker tagAsString[1] = (char)(uint8_t)(tag >> 16);
566*c8dee2aaSAndroid Build Coastguard Worker tagAsString[2] = (char)(uint8_t)(tag >> 8);
567*c8dee2aaSAndroid Build Coastguard Worker tagAsString[3] = (char)(uint8_t)(tag >> 0);
568*c8dee2aaSAndroid Build Coastguard Worker return SkString(tagAsString);
569*c8dee2aaSAndroid Build Coastguard Worker }
570*c8dee2aaSAndroid Build Coastguard Worker
writeControls(SkMetaData * controls)571*c8dee2aaSAndroid Build Coastguard Worker bool VariationSliders::writeControls(SkMetaData* controls) {
572*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < fAxisSliders.size(); ++i) {
573*c8dee2aaSAndroid Build Coastguard Worker SkScalar axisVars[kAxisVarsSize];
574*c8dee2aaSAndroid Build Coastguard Worker
575*c8dee2aaSAndroid Build Coastguard Worker axisVars[0] = fAxisSliders[i].current;
576*c8dee2aaSAndroid Build Coastguard Worker axisVars[1] = fAxisSliders[i].axis.min;
577*c8dee2aaSAndroid Build Coastguard Worker axisVars[2] = fAxisSliders[i].axis.max;
578*c8dee2aaSAndroid Build Coastguard Worker controls->setScalars(fAxisSliders[i].name.c_str(), kAxisVarsSize, axisVars);
579*c8dee2aaSAndroid Build Coastguard Worker }
580*c8dee2aaSAndroid Build Coastguard Worker return true;
581*c8dee2aaSAndroid Build Coastguard Worker }
582*c8dee2aaSAndroid Build Coastguard Worker
readControls(const SkMetaData & controls,bool * changed)583*c8dee2aaSAndroid Build Coastguard Worker void VariationSliders::readControls(const SkMetaData& controls, bool* changed) {
584*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < fAxisSliders.size(); ++i) {
585*c8dee2aaSAndroid Build Coastguard Worker SkScalar axisVars[kAxisVarsSize] = {0};
586*c8dee2aaSAndroid Build Coastguard Worker int resultAxisVarsSize = 0;
587*c8dee2aaSAndroid Build Coastguard Worker SkASSERT_RELEASE(controls.findScalars(
588*c8dee2aaSAndroid Build Coastguard Worker tagToString(fAxisSliders[i].axis.tag).c_str(), &resultAxisVarsSize, axisVars));
589*c8dee2aaSAndroid Build Coastguard Worker SkASSERT_RELEASE(resultAxisVarsSize == kAxisVarsSize);
590*c8dee2aaSAndroid Build Coastguard Worker if (changed) {
591*c8dee2aaSAndroid Build Coastguard Worker *changed |= fAxisSliders[i].current != axisVars[0];
592*c8dee2aaSAndroid Build Coastguard Worker }
593*c8dee2aaSAndroid Build Coastguard Worker fAxisSliders[i].current = axisVars[0];
594*c8dee2aaSAndroid Build Coastguard Worker fCoords[i] = { fAxisSliders[i].axis.tag, fAxisSliders[i].current };
595*c8dee2aaSAndroid Build Coastguard Worker }
596*c8dee2aaSAndroid Build Coastguard Worker }
597*c8dee2aaSAndroid Build Coastguard Worker
getCoordinates()598*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkFontArguments::VariationPosition::Coordinate> VariationSliders::getCoordinates() {
599*c8dee2aaSAndroid Build Coastguard Worker return SkSpan<const SkFontArguments::VariationPosition::Coordinate>{fCoords.get(),
600*c8dee2aaSAndroid Build Coastguard Worker fAxisSliders.size()};
601*c8dee2aaSAndroid Build Coastguard Worker }
602*c8dee2aaSAndroid Build Coastguard Worker
603*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////////////////////////
HilbertGenerator(float desiredSize,float desiredLineWidth,int desiredDepth)604*c8dee2aaSAndroid Build Coastguard Worker HilbertGenerator::HilbertGenerator(float desiredSize, float desiredLineWidth, int desiredDepth)
605*c8dee2aaSAndroid Build Coastguard Worker : fDesiredSize(desiredSize)
606*c8dee2aaSAndroid Build Coastguard Worker , fDesiredDepth(desiredDepth)
607*c8dee2aaSAndroid Build Coastguard Worker , fSegmentLength(fDesiredSize / ((0x1 << fDesiredDepth) - 1.0f))
608*c8dee2aaSAndroid Build Coastguard Worker , fDesiredLineWidth(desiredLineWidth)
609*c8dee2aaSAndroid Build Coastguard Worker , fActualBounds(SkRect::MakeEmpty())
610*c8dee2aaSAndroid Build Coastguard Worker , fCurPos(SkPoint::Make(0.0f, 0.0f))
611*c8dee2aaSAndroid Build Coastguard Worker , fCurDir(0)
612*c8dee2aaSAndroid Build Coastguard Worker , fExpectedLen(fSegmentLength * ((0x1 << (2*fDesiredDepth)) - 1.0f))
613*c8dee2aaSAndroid Build Coastguard Worker , fCurLen(0.0f) {
614*c8dee2aaSAndroid Build Coastguard Worker }
615*c8dee2aaSAndroid Build Coastguard Worker
draw(SkCanvas * canvas)616*c8dee2aaSAndroid Build Coastguard Worker void HilbertGenerator::draw(SkCanvas* canvas) {
617*c8dee2aaSAndroid Build Coastguard Worker this->recursiveDraw(canvas, /* curDepth= */ 0, /* turnLeft= */ true);
618*c8dee2aaSAndroid Build Coastguard Worker
619*c8dee2aaSAndroid Build Coastguard Worker SkScalarNearlyEqual(fExpectedLen, fCurLen, 0.01f);
620*c8dee2aaSAndroid Build Coastguard Worker SkScalarNearlyEqual(fDesiredSize, fActualBounds.width(), 0.01f);
621*c8dee2aaSAndroid Build Coastguard Worker SkScalarNearlyEqual(fDesiredSize, fActualBounds.height(), 0.01f);
622*c8dee2aaSAndroid Build Coastguard Worker }
623*c8dee2aaSAndroid Build Coastguard Worker
turn90(bool turnLeft)624*c8dee2aaSAndroid Build Coastguard Worker void HilbertGenerator::turn90(bool turnLeft) {
625*c8dee2aaSAndroid Build Coastguard Worker fCurDir += turnLeft ? 90 : -90;
626*c8dee2aaSAndroid Build Coastguard Worker if (fCurDir >= 360) {
627*c8dee2aaSAndroid Build Coastguard Worker fCurDir = 0;
628*c8dee2aaSAndroid Build Coastguard Worker } else if (fCurDir < 0) {
629*c8dee2aaSAndroid Build Coastguard Worker fCurDir = 270;
630*c8dee2aaSAndroid Build Coastguard Worker }
631*c8dee2aaSAndroid Build Coastguard Worker
632*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fCurDir == 0 || fCurDir == 90 || fCurDir == 180 || fCurDir == 270);
633*c8dee2aaSAndroid Build Coastguard Worker }
634*c8dee2aaSAndroid Build Coastguard Worker
line(SkCanvas * canvas)635*c8dee2aaSAndroid Build Coastguard Worker void HilbertGenerator::line(SkCanvas* canvas) {
636*c8dee2aaSAndroid Build Coastguard Worker
637*c8dee2aaSAndroid Build Coastguard Worker SkPoint before = fCurPos;
638*c8dee2aaSAndroid Build Coastguard Worker
639*c8dee2aaSAndroid Build Coastguard Worker SkRect r;
640*c8dee2aaSAndroid Build Coastguard Worker switch (fCurDir) {
641*c8dee2aaSAndroid Build Coastguard Worker case 0:
642*c8dee2aaSAndroid Build Coastguard Worker r.fLeft = fCurPos.fX;
643*c8dee2aaSAndroid Build Coastguard Worker r.fTop = fCurPos.fY - fDesiredLineWidth / 2.0f;
644*c8dee2aaSAndroid Build Coastguard Worker r.fRight = fCurPos.fX + fSegmentLength;
645*c8dee2aaSAndroid Build Coastguard Worker r.fBottom = fCurPos.fY + fDesiredLineWidth / 2.0f;
646*c8dee2aaSAndroid Build Coastguard Worker fCurPos.fX += fSegmentLength;
647*c8dee2aaSAndroid Build Coastguard Worker break;
648*c8dee2aaSAndroid Build Coastguard Worker case 90:
649*c8dee2aaSAndroid Build Coastguard Worker r.fLeft = fCurPos.fX - fDesiredLineWidth / 2.0f;
650*c8dee2aaSAndroid Build Coastguard Worker r.fTop = fCurPos.fY - fSegmentLength;
651*c8dee2aaSAndroid Build Coastguard Worker r.fRight = fCurPos.fX + fDesiredLineWidth / 2.0f;
652*c8dee2aaSAndroid Build Coastguard Worker r.fBottom = fCurPos.fY;
653*c8dee2aaSAndroid Build Coastguard Worker fCurPos.fY -= fSegmentLength;
654*c8dee2aaSAndroid Build Coastguard Worker break;
655*c8dee2aaSAndroid Build Coastguard Worker case 180:
656*c8dee2aaSAndroid Build Coastguard Worker r.fLeft = fCurPos.fX - fSegmentLength;
657*c8dee2aaSAndroid Build Coastguard Worker r.fTop = fCurPos.fY - fDesiredLineWidth / 2.0f;
658*c8dee2aaSAndroid Build Coastguard Worker r.fRight = fCurPos.fX;
659*c8dee2aaSAndroid Build Coastguard Worker r.fBottom = fCurPos.fY + fDesiredLineWidth / 2.0f;
660*c8dee2aaSAndroid Build Coastguard Worker fCurPos.fX -= fSegmentLength;
661*c8dee2aaSAndroid Build Coastguard Worker break;
662*c8dee2aaSAndroid Build Coastguard Worker case 270:
663*c8dee2aaSAndroid Build Coastguard Worker r.fLeft = fCurPos.fX - fDesiredLineWidth / 2.0f;
664*c8dee2aaSAndroid Build Coastguard Worker r.fTop = fCurPos.fY;
665*c8dee2aaSAndroid Build Coastguard Worker r.fRight = fCurPos.fX + fDesiredLineWidth / 2.0f;
666*c8dee2aaSAndroid Build Coastguard Worker r.fBottom = fCurPos.fY + fSegmentLength;
667*c8dee2aaSAndroid Build Coastguard Worker fCurPos.fY += fSegmentLength;
668*c8dee2aaSAndroid Build Coastguard Worker break;
669*c8dee2aaSAndroid Build Coastguard Worker default:
670*c8dee2aaSAndroid Build Coastguard Worker return;
671*c8dee2aaSAndroid Build Coastguard Worker }
672*c8dee2aaSAndroid Build Coastguard Worker
673*c8dee2aaSAndroid Build Coastguard Worker SkPoint pts[2] = { before, fCurPos };
674*c8dee2aaSAndroid Build Coastguard Worker
675*c8dee2aaSAndroid Build Coastguard Worker SkColor4f colors[2] = {
676*c8dee2aaSAndroid Build Coastguard Worker this->getColor(fCurLen),
677*c8dee2aaSAndroid Build Coastguard Worker this->getColor(fCurLen + fSegmentLength),
678*c8dee2aaSAndroid Build Coastguard Worker };
679*c8dee2aaSAndroid Build Coastguard Worker
680*c8dee2aaSAndroid Build Coastguard Worker fCurLen += fSegmentLength;
681*c8dee2aaSAndroid Build Coastguard Worker if (fActualBounds.isEmpty()) {
682*c8dee2aaSAndroid Build Coastguard Worker fActualBounds = r;
683*c8dee2aaSAndroid Build Coastguard Worker } else {
684*c8dee2aaSAndroid Build Coastguard Worker fActualBounds.join(r);
685*c8dee2aaSAndroid Build Coastguard Worker }
686*c8dee2aaSAndroid Build Coastguard Worker
687*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
688*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(SkGradientShader::MakeLinear(pts, colors, /* colorSpace= */ nullptr,
689*c8dee2aaSAndroid Build Coastguard Worker /* pos= */ nullptr, 2, SkTileMode::kClamp));
690*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
691*c8dee2aaSAndroid Build Coastguard Worker }
692*c8dee2aaSAndroid Build Coastguard Worker
recursiveDraw(SkCanvas * canvas,int curDepth,bool turnLeft)693*c8dee2aaSAndroid Build Coastguard Worker void HilbertGenerator::recursiveDraw(SkCanvas* canvas, int curDepth, bool turnLeft) {
694*c8dee2aaSAndroid Build Coastguard Worker if (curDepth >= fDesiredDepth) {
695*c8dee2aaSAndroid Build Coastguard Worker return;
696*c8dee2aaSAndroid Build Coastguard Worker }
697*c8dee2aaSAndroid Build Coastguard Worker
698*c8dee2aaSAndroid Build Coastguard Worker this->turn90(turnLeft);
699*c8dee2aaSAndroid Build Coastguard Worker this->recursiveDraw(canvas, curDepth + 1, !turnLeft);
700*c8dee2aaSAndroid Build Coastguard Worker this->line(canvas);
701*c8dee2aaSAndroid Build Coastguard Worker this->turn90(!turnLeft);
702*c8dee2aaSAndroid Build Coastguard Worker this->recursiveDraw(canvas, curDepth + 1, turnLeft);
703*c8dee2aaSAndroid Build Coastguard Worker this->line(canvas);
704*c8dee2aaSAndroid Build Coastguard Worker this->recursiveDraw(canvas, curDepth + 1, turnLeft);
705*c8dee2aaSAndroid Build Coastguard Worker this->turn90(!turnLeft);
706*c8dee2aaSAndroid Build Coastguard Worker this->line(canvas);
707*c8dee2aaSAndroid Build Coastguard Worker this->recursiveDraw(canvas, curDepth + 1, !turnLeft);
708*c8dee2aaSAndroid Build Coastguard Worker this->turn90(turnLeft);
709*c8dee2aaSAndroid Build Coastguard Worker }
710*c8dee2aaSAndroid Build Coastguard Worker
getColor(float curLen)711*c8dee2aaSAndroid Build Coastguard Worker SkColor4f HilbertGenerator::getColor(float curLen) {
712*c8dee2aaSAndroid Build Coastguard Worker static const SkColor4f kColors[] = {
713*c8dee2aaSAndroid Build Coastguard Worker SkColors::kBlack,
714*c8dee2aaSAndroid Build Coastguard Worker SkColors::kBlue,
715*c8dee2aaSAndroid Build Coastguard Worker SkColors::kCyan,
716*c8dee2aaSAndroid Build Coastguard Worker SkColors::kGreen,
717*c8dee2aaSAndroid Build Coastguard Worker SkColors::kYellow,
718*c8dee2aaSAndroid Build Coastguard Worker SkColors::kRed,
719*c8dee2aaSAndroid Build Coastguard Worker SkColors::kWhite,
720*c8dee2aaSAndroid Build Coastguard Worker };
721*c8dee2aaSAndroid Build Coastguard Worker
722*c8dee2aaSAndroid Build Coastguard Worker static const float kStops[] = {
723*c8dee2aaSAndroid Build Coastguard Worker 0.0f,
724*c8dee2aaSAndroid Build Coastguard Worker 1.0f/6.0f,
725*c8dee2aaSAndroid Build Coastguard Worker 2.0f/6.0f,
726*c8dee2aaSAndroid Build Coastguard Worker 0.5f,
727*c8dee2aaSAndroid Build Coastguard Worker 4.0f/6.0f,
728*c8dee2aaSAndroid Build Coastguard Worker 5.0f/6.0f,
729*c8dee2aaSAndroid Build Coastguard Worker 1.0f,
730*c8dee2aaSAndroid Build Coastguard Worker };
731*c8dee2aaSAndroid Build Coastguard Worker static_assert(std::size(kColors) == std::size(kStops));
732*c8dee2aaSAndroid Build Coastguard Worker
733*c8dee2aaSAndroid Build Coastguard Worker float t = curLen / fExpectedLen;
734*c8dee2aaSAndroid Build Coastguard Worker if (t <= 0.0f) {
735*c8dee2aaSAndroid Build Coastguard Worker return kColors[0];
736*c8dee2aaSAndroid Build Coastguard Worker } else if (t >= 1.0f) {
737*c8dee2aaSAndroid Build Coastguard Worker return kColors[std::size(kColors)-1];
738*c8dee2aaSAndroid Build Coastguard Worker }
739*c8dee2aaSAndroid Build Coastguard Worker
740*c8dee2aaSAndroid Build Coastguard Worker for (unsigned int i = 0; i < std::size(kColors)-1; ++i) {
741*c8dee2aaSAndroid Build Coastguard Worker if (kStops[i] <= t && t <= kStops[i+1]) {
742*c8dee2aaSAndroid Build Coastguard Worker t = (t - kStops[i]) / (kStops[i+1] - kStops[i]);
743*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(0.0f <= t && t <= 1.0f);
744*c8dee2aaSAndroid Build Coastguard Worker return { kColors[i].fR * (1 - t) + kColors[i+1].fR * t,
745*c8dee2aaSAndroid Build Coastguard Worker kColors[i].fG * (1 - t) + kColors[i+1].fG * t,
746*c8dee2aaSAndroid Build Coastguard Worker kColors[i].fB * (1 - t) + kColors[i+1].fB * t,
747*c8dee2aaSAndroid Build Coastguard Worker kColors[i].fA * (1 - t) + kColors[i+1].fA * t };
748*c8dee2aaSAndroid Build Coastguard Worker
749*c8dee2aaSAndroid Build Coastguard Worker }
750*c8dee2aaSAndroid Build Coastguard Worker }
751*c8dee2aaSAndroid Build Coastguard Worker
752*c8dee2aaSAndroid Build Coastguard Worker return SkColors::kBlack;
753*c8dee2aaSAndroid Build Coastguard Worker }
754*c8dee2aaSAndroid Build Coastguard Worker
ExtractPathsFromSKP(const char filepath[],std::function<PathSniffCallback> callback)755*c8dee2aaSAndroid Build Coastguard Worker void ExtractPathsFromSKP(const char filepath[], std::function<PathSniffCallback> callback) {
756*c8dee2aaSAndroid Build Coastguard Worker SkFILEStream stream(filepath);
757*c8dee2aaSAndroid Build Coastguard Worker if (!stream.isValid()) {
758*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("ExtractPaths: invalid input file at \"%s\"\n", filepath);
759*c8dee2aaSAndroid Build Coastguard Worker return;
760*c8dee2aaSAndroid Build Coastguard Worker }
761*c8dee2aaSAndroid Build Coastguard Worker
762*c8dee2aaSAndroid Build Coastguard Worker class PathSniffer : public SkCanvas {
763*c8dee2aaSAndroid Build Coastguard Worker public:
764*c8dee2aaSAndroid Build Coastguard Worker PathSniffer(std::function<PathSniffCallback> callback)
765*c8dee2aaSAndroid Build Coastguard Worker : SkCanvas(4096, 4096, nullptr)
766*c8dee2aaSAndroid Build Coastguard Worker , fPathSniffCallback(callback) {}
767*c8dee2aaSAndroid Build Coastguard Worker private:
768*c8dee2aaSAndroid Build Coastguard Worker void onDrawPath(const SkPath& path, const SkPaint& paint) override {
769*c8dee2aaSAndroid Build Coastguard Worker fPathSniffCallback(this->getTotalMatrix(), path, paint);
770*c8dee2aaSAndroid Build Coastguard Worker }
771*c8dee2aaSAndroid Build Coastguard Worker std::function<PathSniffCallback> fPathSniffCallback;
772*c8dee2aaSAndroid Build Coastguard Worker };
773*c8dee2aaSAndroid Build Coastguard Worker
774*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkPicture> skp = SkPicture::MakeFromStream(&stream);
775*c8dee2aaSAndroid Build Coastguard Worker if (!skp) {
776*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("ExtractPaths: couldn't load skp at \"%s\"\n", filepath);
777*c8dee2aaSAndroid Build Coastguard Worker return;
778*c8dee2aaSAndroid Build Coastguard Worker }
779*c8dee2aaSAndroid Build Coastguard Worker PathSniffer pathSniffer(callback);
780*c8dee2aaSAndroid Build Coastguard Worker skp->playback(&pathSniffer);
781*c8dee2aaSAndroid Build Coastguard Worker }
782*c8dee2aaSAndroid Build Coastguard Worker
783*c8dee2aaSAndroid Build Coastguard Worker } // namespace ToolUtils
784