1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2014 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h"
9cb93a386Sopenharmony_ci#include "include/core/SkBlendMode.h"
10cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
11cb93a386Sopenharmony_ci#include "include/core/SkColorPriv.h"
12cb93a386Sopenharmony_ci#include "include/core/SkImage.h"
13cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h"
14cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
15cb93a386Sopenharmony_ci#include "include/core/SkPathBuilder.h"
16cb93a386Sopenharmony_ci#include "include/core/SkPicture.h"
17cb93a386Sopenharmony_ci#include "include/core/SkPixelRef.h"
18cb93a386Sopenharmony_ci#include "include/core/SkPixmap.h"
19cb93a386Sopenharmony_ci#include "include/core/SkPoint3.h"
20cb93a386Sopenharmony_ci#include "include/core/SkRRect.h"
21cb93a386Sopenharmony_ci#include "include/core/SkShader.h"
22cb93a386Sopenharmony_ci#include "include/core/SkSurface.h"
23cb93a386Sopenharmony_ci#include "include/core/SkTextBlob.h"
24cb93a386Sopenharmony_ci#include "include/ports/SkTypeface_win.h"
25cb93a386Sopenharmony_ci#include "include/private/SkColorData.h"
26cb93a386Sopenharmony_ci#include "include/private/SkFloatingPoint.h"
27cb93a386Sopenharmony_ci#include "src/core/SkFontPriv.h"
28cb93a386Sopenharmony_ci#include "tools/ToolUtils.h"
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_ci#include <cmath>
31cb93a386Sopenharmony_ci#include <cstring>
32cb93a386Sopenharmony_ci
33cb93a386Sopenharmony_ci#if defined(SK_ENABLE_SVG)
34cb93a386Sopenharmony_ci#include "modules/svg/include/SkSVGDOM.h"
35cb93a386Sopenharmony_ci#include "modules/svg/include/SkSVGNode.h"
36cb93a386Sopenharmony_ci#include "src/xml/SkDOM.h"
37cb93a386Sopenharmony_ci#endif
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_cinamespace ToolUtils {
40cb93a386Sopenharmony_ci
41cb93a386Sopenharmony_ciconst char* alphatype_name(SkAlphaType at) {
42cb93a386Sopenharmony_ci    switch (at) {
43cb93a386Sopenharmony_ci        case kUnknown_SkAlphaType:  return "Unknown";
44cb93a386Sopenharmony_ci        case kOpaque_SkAlphaType:   return "Opaque";
45cb93a386Sopenharmony_ci        case kPremul_SkAlphaType:   return "Premul";
46cb93a386Sopenharmony_ci        case kUnpremul_SkAlphaType: return "Unpremul";
47cb93a386Sopenharmony_ci    }
48cb93a386Sopenharmony_ci    SkASSERT(false);
49cb93a386Sopenharmony_ci    return "unexpected alphatype";
50cb93a386Sopenharmony_ci}
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_ciconst char* colortype_name(SkColorType ct) {
53cb93a386Sopenharmony_ci    switch (ct) {
54cb93a386Sopenharmony_ci        case kUnknown_SkColorType:            return "Unknown";
55cb93a386Sopenharmony_ci        case kAlpha_8_SkColorType:            return "Alpha_8";
56cb93a386Sopenharmony_ci        case kA16_unorm_SkColorType:          return "Alpha_16";
57cb93a386Sopenharmony_ci        case kA16_float_SkColorType:          return "A16_float";
58cb93a386Sopenharmony_ci        case kRGB_565_SkColorType:            return "RGB_565";
59cb93a386Sopenharmony_ci        case kARGB_4444_SkColorType:          return "ARGB_4444";
60cb93a386Sopenharmony_ci        case kRGBA_8888_SkColorType:          return "RGBA_8888";
61cb93a386Sopenharmony_ci        case kSRGBA_8888_SkColorType:         return "SRGBA_8888";
62cb93a386Sopenharmony_ci        case kRGB_888x_SkColorType:           return "RGB_888x";
63cb93a386Sopenharmony_ci        case kBGRA_8888_SkColorType:          return "BGRA_8888";
64cb93a386Sopenharmony_ci        case kRGBA_1010102_SkColorType:       return "RGBA_1010102";
65cb93a386Sopenharmony_ci        case kBGRA_1010102_SkColorType:       return "BGRA_1010102";
66cb93a386Sopenharmony_ci        case kRGB_101010x_SkColorType:        return "RGB_101010x";
67cb93a386Sopenharmony_ci        case kBGR_101010x_SkColorType:        return "BGR_101010x";
68cb93a386Sopenharmony_ci        case kGray_8_SkColorType:             return "Gray_8";
69cb93a386Sopenharmony_ci        case kRGBA_F16Norm_SkColorType:       return "RGBA_F16Norm";
70cb93a386Sopenharmony_ci        case kRGBA_F16_SkColorType:           return "RGBA_F16";
71cb93a386Sopenharmony_ci        case kRGBA_F32_SkColorType:           return "RGBA_F32";
72cb93a386Sopenharmony_ci        case kR8G8_unorm_SkColorType:         return "R8G8_unorm";
73cb93a386Sopenharmony_ci        case kR16G16_unorm_SkColorType:       return "R16G16_unorm";
74cb93a386Sopenharmony_ci        case kR16G16_float_SkColorType:       return "R16G16_float";
75cb93a386Sopenharmony_ci        case kR16G16B16A16_unorm_SkColorType: return "R16G16B16A16_unorm";
76cb93a386Sopenharmony_ci    }
77cb93a386Sopenharmony_ci    SkASSERT(false);
78cb93a386Sopenharmony_ci    return "unexpected colortype";
79cb93a386Sopenharmony_ci}
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ciconst char* colortype_depth(SkColorType ct) {
82cb93a386Sopenharmony_ci    switch (ct) {
83cb93a386Sopenharmony_ci        case kUnknown_SkColorType:            return "Unknown";
84cb93a386Sopenharmony_ci        case kAlpha_8_SkColorType:            return "A8";
85cb93a386Sopenharmony_ci        case kA16_unorm_SkColorType:          return "A16";
86cb93a386Sopenharmony_ci        case kA16_float_SkColorType:          return "AF16";
87cb93a386Sopenharmony_ci        case kRGB_565_SkColorType:            return "565";
88cb93a386Sopenharmony_ci        case kARGB_4444_SkColorType:          return "4444";
89cb93a386Sopenharmony_ci        case kRGBA_8888_SkColorType:          return "8888";
90cb93a386Sopenharmony_ci        case kSRGBA_8888_SkColorType:         return "8888";
91cb93a386Sopenharmony_ci        case kRGB_888x_SkColorType:           return "888";
92cb93a386Sopenharmony_ci        case kBGRA_8888_SkColorType:          return "8888";
93cb93a386Sopenharmony_ci        case kRGBA_1010102_SkColorType:       return "1010102";
94cb93a386Sopenharmony_ci        case kBGRA_1010102_SkColorType:       return "1010102";
95cb93a386Sopenharmony_ci        case kRGB_101010x_SkColorType:        return "101010";
96cb93a386Sopenharmony_ci        case kBGR_101010x_SkColorType:        return "101010";
97cb93a386Sopenharmony_ci        case kGray_8_SkColorType:             return "G8";
98cb93a386Sopenharmony_ci        case kRGBA_F16Norm_SkColorType:       return "F16Norm";  // TODO: "F16"?
99cb93a386Sopenharmony_ci        case kRGBA_F16_SkColorType:           return "F16";
100cb93a386Sopenharmony_ci        case kRGBA_F32_SkColorType:           return "F32";
101cb93a386Sopenharmony_ci        case kR8G8_unorm_SkColorType:         return "88";
102cb93a386Sopenharmony_ci        case kR16G16_unorm_SkColorType:       return "1616";
103cb93a386Sopenharmony_ci        case kR16G16_float_SkColorType:       return "F16F16";
104cb93a386Sopenharmony_ci        case kR16G16B16A16_unorm_SkColorType: return "16161616";
105cb93a386Sopenharmony_ci    }
106cb93a386Sopenharmony_ci    SkASSERT(false);
107cb93a386Sopenharmony_ci    return "unexpected colortype";
108cb93a386Sopenharmony_ci}
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_ciconst char* tilemode_name(SkTileMode mode) {
111cb93a386Sopenharmony_ci    switch (mode) {
112cb93a386Sopenharmony_ci        case SkTileMode::kClamp:  return "clamp";
113cb93a386Sopenharmony_ci        case SkTileMode::kRepeat: return "repeat";
114cb93a386Sopenharmony_ci        case SkTileMode::kMirror: return "mirror";
115cb93a386Sopenharmony_ci        case SkTileMode::kDecal:  return "decal";
116cb93a386Sopenharmony_ci    }
117cb93a386Sopenharmony_ci    SkASSERT(false);
118cb93a386Sopenharmony_ci    return "unexpected tilemode";
119cb93a386Sopenharmony_ci}
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_ciSkColor color_to_565(SkColor color) {
122cb93a386Sopenharmony_ci    // Not a good idea to use this function for greyscale colors...
123cb93a386Sopenharmony_ci    // it will add an obvious purple or green tint.
124cb93a386Sopenharmony_ci    SkASSERT(SkColorGetR(color) != SkColorGetG(color) || SkColorGetR(color) != SkColorGetB(color) ||
125cb93a386Sopenharmony_ci             SkColorGetG(color) != SkColorGetB(color));
126cb93a386Sopenharmony_ci
127cb93a386Sopenharmony_ci    SkPMColor pmColor = SkPreMultiplyColor(color);
128cb93a386Sopenharmony_ci    U16CPU    color16 = SkPixel32ToPixel16(pmColor);
129cb93a386Sopenharmony_ci    return SkPixel16ToColor(color16);
130cb93a386Sopenharmony_ci}
131cb93a386Sopenharmony_ci
132cb93a386Sopenharmony_cisk_sp<SkShader> create_checkerboard_shader(SkColor c1, SkColor c2, int size) {
133cb93a386Sopenharmony_ci    SkBitmap bm;
134cb93a386Sopenharmony_ci    bm.allocPixels(SkImageInfo::MakeS32(2 * size, 2 * size, kPremul_SkAlphaType));
135cb93a386Sopenharmony_ci    bm.eraseColor(c1);
136cb93a386Sopenharmony_ci    bm.eraseArea(SkIRect::MakeLTRB(0, 0, size, size), c2);
137cb93a386Sopenharmony_ci    bm.eraseArea(SkIRect::MakeLTRB(size, size, 2 * size, 2 * size), c2);
138cb93a386Sopenharmony_ci    return bm.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, SkSamplingOptions());
139cb93a386Sopenharmony_ci}
140cb93a386Sopenharmony_ci
141cb93a386Sopenharmony_ciSkBitmap create_checkerboard_bitmap(int w, int h, SkColor c1, SkColor c2, int checkSize) {
142cb93a386Sopenharmony_ci    SkBitmap bitmap;
143cb93a386Sopenharmony_ci    bitmap.allocPixels(SkImageInfo::MakeS32(w, h, kPremul_SkAlphaType));
144cb93a386Sopenharmony_ci    SkCanvas canvas(bitmap);
145cb93a386Sopenharmony_ci
146cb93a386Sopenharmony_ci    ToolUtils::draw_checkerboard(&canvas, c1, c2, checkSize);
147cb93a386Sopenharmony_ci    return bitmap;
148cb93a386Sopenharmony_ci}
149cb93a386Sopenharmony_ci
150cb93a386Sopenharmony_cisk_sp<SkImage> create_checkerboard_image(int w, int h, SkColor c1, SkColor c2, int checkSize) {
151cb93a386Sopenharmony_ci    auto surf = SkSurface::MakeRasterN32Premul(w, h);
152cb93a386Sopenharmony_ci    ToolUtils::draw_checkerboard(surf->getCanvas(), c1, c2, checkSize);
153cb93a386Sopenharmony_ci    return surf->makeImageSnapshot();
154cb93a386Sopenharmony_ci}
155cb93a386Sopenharmony_ci
156cb93a386Sopenharmony_civoid draw_checkerboard(SkCanvas* canvas, SkColor c1, SkColor c2, int size) {
157cb93a386Sopenharmony_ci    SkPaint paint;
158cb93a386Sopenharmony_ci    paint.setShader(create_checkerboard_shader(c1, c2, size));
159cb93a386Sopenharmony_ci    paint.setBlendMode(SkBlendMode::kSrc);
160cb93a386Sopenharmony_ci    canvas->drawPaint(paint);
161cb93a386Sopenharmony_ci}
162cb93a386Sopenharmony_ci
163cb93a386Sopenharmony_ciSkBitmap
164cb93a386Sopenharmony_cicreate_string_bitmap(int w, int h, SkColor c, int x, int y, int textSize, const char* str) {
165cb93a386Sopenharmony_ci    SkBitmap bitmap;
166cb93a386Sopenharmony_ci    bitmap.allocN32Pixels(w, h);
167cb93a386Sopenharmony_ci    SkCanvas canvas(bitmap);
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_ci    SkPaint paint;
170cb93a386Sopenharmony_ci    paint.setColor(c);
171cb93a386Sopenharmony_ci
172cb93a386Sopenharmony_ci    SkFont font(ToolUtils::create_portable_typeface(), textSize);
173cb93a386Sopenharmony_ci
174cb93a386Sopenharmony_ci    canvas.clear(0x00000000);
175cb93a386Sopenharmony_ci    canvas.drawSimpleText(str,
176cb93a386Sopenharmony_ci                          strlen(str),
177cb93a386Sopenharmony_ci                          SkTextEncoding::kUTF8,
178cb93a386Sopenharmony_ci                          SkIntToScalar(x),
179cb93a386Sopenharmony_ci                          SkIntToScalar(y),
180cb93a386Sopenharmony_ci                          font,
181cb93a386Sopenharmony_ci                          paint);
182cb93a386Sopenharmony_ci
183cb93a386Sopenharmony_ci    // Tag data as sRGB (without doing any color space conversion). Color-space aware configs
184cb93a386Sopenharmony_ci    // will process this correctly but legacy configs will render as if this returned N32.
185cb93a386Sopenharmony_ci    SkBitmap result;
186cb93a386Sopenharmony_ci    result.setInfo(SkImageInfo::MakeS32(w, h, kPremul_SkAlphaType));
187cb93a386Sopenharmony_ci    result.setPixelRef(sk_ref_sp(bitmap.pixelRef()), 0, 0);
188cb93a386Sopenharmony_ci    return result;
189cb93a386Sopenharmony_ci}
190cb93a386Sopenharmony_ci
191cb93a386Sopenharmony_cisk_sp<SkImage> create_string_image(int w, int h, SkColor c, int x, int y, int textSize,
192cb93a386Sopenharmony_ci                                   const char* str) {
193cb93a386Sopenharmony_ci    return create_string_bitmap(w, h, c, x, y, textSize, str).asImage();
194cb93a386Sopenharmony_ci}
195cb93a386Sopenharmony_ci
196cb93a386Sopenharmony_civoid add_to_text_blob_w_len(SkTextBlobBuilder* builder,
197cb93a386Sopenharmony_ci                            const char*        text,
198cb93a386Sopenharmony_ci                            size_t             len,
199cb93a386Sopenharmony_ci                            SkTextEncoding     encoding,
200cb93a386Sopenharmony_ci                            const SkFont&      font,
201cb93a386Sopenharmony_ci                            SkScalar           x,
202cb93a386Sopenharmony_ci                            SkScalar           y) {
203cb93a386Sopenharmony_ci    int  count = font.countText(text, len, encoding);
204cb93a386Sopenharmony_ci    if (count < 1) {
205cb93a386Sopenharmony_ci        return;
206cb93a386Sopenharmony_ci    }
207cb93a386Sopenharmony_ci    auto run   = builder->allocRun(font, count, x, y);
208cb93a386Sopenharmony_ci    font.textToGlyphs(text, len, encoding, run.glyphs, count);
209cb93a386Sopenharmony_ci}
210cb93a386Sopenharmony_ci
211cb93a386Sopenharmony_civoid add_to_text_blob(SkTextBlobBuilder* builder,
212cb93a386Sopenharmony_ci                      const char*        text,
213cb93a386Sopenharmony_ci                      const SkFont&      font,
214cb93a386Sopenharmony_ci                      SkScalar           x,
215cb93a386Sopenharmony_ci                      SkScalar           y) {
216cb93a386Sopenharmony_ci    add_to_text_blob_w_len(builder, text, strlen(text), SkTextEncoding::kUTF8, font, x, y);
217cb93a386Sopenharmony_ci}
218cb93a386Sopenharmony_ci
219cb93a386Sopenharmony_civoid get_text_path(const SkFont&  font,
220cb93a386Sopenharmony_ci                   const void*    text,
221cb93a386Sopenharmony_ci                   size_t         length,
222cb93a386Sopenharmony_ci                   SkTextEncoding encoding,
223cb93a386Sopenharmony_ci                   SkPath*        dst,
224cb93a386Sopenharmony_ci                   const SkPoint  pos[]) {
225cb93a386Sopenharmony_ci    SkAutoToGlyphs        atg(font, text, length, encoding);
226cb93a386Sopenharmony_ci    const int             count = atg.count();
227cb93a386Sopenharmony_ci    SkAutoTArray<SkPoint> computedPos;
228cb93a386Sopenharmony_ci    if (pos == nullptr) {
229cb93a386Sopenharmony_ci        computedPos.reset(count);
230cb93a386Sopenharmony_ci        font.getPos(atg.glyphs(), count, &computedPos[0]);
231cb93a386Sopenharmony_ci        pos = computedPos.get();
232cb93a386Sopenharmony_ci    }
233cb93a386Sopenharmony_ci
234cb93a386Sopenharmony_ci    struct Rec {
235cb93a386Sopenharmony_ci        SkPath*        fDst;
236cb93a386Sopenharmony_ci        const SkPoint* fPos;
237cb93a386Sopenharmony_ci    } rec = {dst, pos};
238cb93a386Sopenharmony_ci    font.getPaths(atg.glyphs(),
239cb93a386Sopenharmony_ci                  atg.count(),
240cb93a386Sopenharmony_ci                  [](const SkPath* src, const SkMatrix& mx, void* ctx) {
241cb93a386Sopenharmony_ci                      Rec* rec = (Rec*)ctx;
242cb93a386Sopenharmony_ci                      if (src) {
243cb93a386Sopenharmony_ci                          SkMatrix tmp(mx);
244cb93a386Sopenharmony_ci                          tmp.postTranslate(rec->fPos->fX, rec->fPos->fY);
245cb93a386Sopenharmony_ci                          rec->fDst->addPath(*src, tmp);
246cb93a386Sopenharmony_ci                      }
247cb93a386Sopenharmony_ci                      rec->fPos += 1;
248cb93a386Sopenharmony_ci                  },
249cb93a386Sopenharmony_ci                  &rec);
250cb93a386Sopenharmony_ci}
251cb93a386Sopenharmony_ci
252cb93a386Sopenharmony_ciSkPath make_star(const SkRect& bounds, int numPts, int step) {
253cb93a386Sopenharmony_ci    SkASSERT(numPts != step);
254cb93a386Sopenharmony_ci    SkPathBuilder builder;
255cb93a386Sopenharmony_ci    builder.setFillType(SkPathFillType::kEvenOdd);
256cb93a386Sopenharmony_ci    builder.moveTo(0, -1);
257cb93a386Sopenharmony_ci    for (int i = 1; i < numPts; ++i) {
258cb93a386Sopenharmony_ci        int      idx   = i * step % numPts;
259cb93a386Sopenharmony_ci        SkScalar theta = idx * 2 * SK_ScalarPI / numPts + SK_ScalarPI / 2;
260cb93a386Sopenharmony_ci        SkScalar x     = SkScalarCos(theta);
261cb93a386Sopenharmony_ci        SkScalar y     = -SkScalarSin(theta);
262cb93a386Sopenharmony_ci        builder.lineTo(x, y);
263cb93a386Sopenharmony_ci    }
264cb93a386Sopenharmony_ci    SkPath path = builder.detach();
265cb93a386Sopenharmony_ci    path.transform(SkMatrix::RectToRect(path.getBounds(), bounds));
266cb93a386Sopenharmony_ci    return path;
267cb93a386Sopenharmony_ci}
268cb93a386Sopenharmony_ci
269cb93a386Sopenharmony_cistatic inline void norm_to_rgb(SkBitmap* bm, int x, int y, const SkVector3& norm) {
270cb93a386Sopenharmony_ci    SkASSERT(SkScalarNearlyEqual(norm.length(), 1.0f));
271cb93a386Sopenharmony_ci    unsigned char r      = static_cast<unsigned char>((0.5f * norm.fX + 0.5f) * 255);
272cb93a386Sopenharmony_ci    unsigned char g      = static_cast<unsigned char>((-0.5f * norm.fY + 0.5f) * 255);
273cb93a386Sopenharmony_ci    unsigned char b      = static_cast<unsigned char>((0.5f * norm.fZ + 0.5f) * 255);
274cb93a386Sopenharmony_ci    *bm->getAddr32(x, y) = SkPackARGB32(0xFF, r, g, b);
275cb93a386Sopenharmony_ci}
276cb93a386Sopenharmony_ci
277cb93a386Sopenharmony_civoid create_hemi_normal_map(SkBitmap* bm, const SkIRect& dst) {
278cb93a386Sopenharmony_ci    const SkPoint center =
279cb93a386Sopenharmony_ci            SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), dst.fTop + (dst.height() / 2.0f));
280cb93a386Sopenharmony_ci    const SkPoint halfSize = SkPoint::Make(dst.width() / 2.0f, dst.height() / 2.0f);
281cb93a386Sopenharmony_ci
282cb93a386Sopenharmony_ci    SkVector3 norm;
283cb93a386Sopenharmony_ci
284cb93a386Sopenharmony_ci    for (int y = dst.fTop; y < dst.fBottom; ++y) {
285cb93a386Sopenharmony_ci        for (int x = dst.fLeft; x < dst.fRight; ++x) {
286cb93a386Sopenharmony_ci            norm.fX = (x + 0.5f - center.fX) / halfSize.fX;
287cb93a386Sopenharmony_ci            norm.fY = (y + 0.5f - center.fY) / halfSize.fY;
288cb93a386Sopenharmony_ci
289cb93a386Sopenharmony_ci            SkScalar tmp = norm.fX * norm.fX + norm.fY * norm.fY;
290cb93a386Sopenharmony_ci            if (tmp >= 1.0f) {
291cb93a386Sopenharmony_ci                norm.set(0.0f, 0.0f, 1.0f);
292cb93a386Sopenharmony_ci            } else {
293cb93a386Sopenharmony_ci                norm.fZ = sqrtf(1.0f - tmp);
294cb93a386Sopenharmony_ci            }
295cb93a386Sopenharmony_ci
296cb93a386Sopenharmony_ci            norm_to_rgb(bm, x, y, norm);
297cb93a386Sopenharmony_ci        }
298cb93a386Sopenharmony_ci    }
299cb93a386Sopenharmony_ci}
300cb93a386Sopenharmony_ci
301cb93a386Sopenharmony_civoid create_frustum_normal_map(SkBitmap* bm, const SkIRect& dst) {
302cb93a386Sopenharmony_ci    const SkPoint center =
303cb93a386Sopenharmony_ci            SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), dst.fTop + (dst.height() / 2.0f));
304cb93a386Sopenharmony_ci
305cb93a386Sopenharmony_ci    SkIRect inner = dst;
306cb93a386Sopenharmony_ci    inner.inset(dst.width() / 4, dst.height() / 4);
307cb93a386Sopenharmony_ci
308cb93a386Sopenharmony_ci    SkPoint3       norm;
309cb93a386Sopenharmony_ci    const SkPoint3 left  = SkPoint3::Make(-SK_ScalarRoot2Over2, 0.0f, SK_ScalarRoot2Over2);
310cb93a386Sopenharmony_ci    const SkPoint3 up    = SkPoint3::Make(0.0f, -SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
311cb93a386Sopenharmony_ci    const SkPoint3 right = SkPoint3::Make(SK_ScalarRoot2Over2, 0.0f, SK_ScalarRoot2Over2);
312cb93a386Sopenharmony_ci    const SkPoint3 down  = SkPoint3::Make(0.0f, SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
313cb93a386Sopenharmony_ci
314cb93a386Sopenharmony_ci    for (int y = dst.fTop; y < dst.fBottom; ++y) {
315cb93a386Sopenharmony_ci        for (int x = dst.fLeft; x < dst.fRight; ++x) {
316cb93a386Sopenharmony_ci            if (inner.contains(x, y)) {
317cb93a386Sopenharmony_ci                norm.set(0.0f, 0.0f, 1.0f);
318cb93a386Sopenharmony_ci            } else {
319cb93a386Sopenharmony_ci                SkScalar locX = x + 0.5f - center.fX;
320cb93a386Sopenharmony_ci                SkScalar locY = y + 0.5f - center.fY;
321cb93a386Sopenharmony_ci
322cb93a386Sopenharmony_ci                if (locX >= 0.0f) {
323cb93a386Sopenharmony_ci                    if (locY > 0.0f) {
324cb93a386Sopenharmony_ci                        norm = locX >= locY ? right : down;  // LR corner
325cb93a386Sopenharmony_ci                    } else {
326cb93a386Sopenharmony_ci                        norm = locX > -locY ? right : up;  // UR corner
327cb93a386Sopenharmony_ci                    }
328cb93a386Sopenharmony_ci                } else {
329cb93a386Sopenharmony_ci                    if (locY > 0.0f) {
330cb93a386Sopenharmony_ci                        norm = -locX > locY ? left : down;  // LL corner
331cb93a386Sopenharmony_ci                    } else {
332cb93a386Sopenharmony_ci                        norm = locX > locY ? up : left;  // UL corner
333cb93a386Sopenharmony_ci                    }
334cb93a386Sopenharmony_ci                }
335cb93a386Sopenharmony_ci            }
336cb93a386Sopenharmony_ci
337cb93a386Sopenharmony_ci            norm_to_rgb(bm, x, y, norm);
338cb93a386Sopenharmony_ci        }
339cb93a386Sopenharmony_ci    }
340cb93a386Sopenharmony_ci}
341cb93a386Sopenharmony_ci
342cb93a386Sopenharmony_civoid create_tetra_normal_map(SkBitmap* bm, const SkIRect& dst) {
343cb93a386Sopenharmony_ci    const SkPoint center =
344cb93a386Sopenharmony_ci            SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), dst.fTop + (dst.height() / 2.0f));
345cb93a386Sopenharmony_ci
346cb93a386Sopenharmony_ci    static const SkScalar k1OverRoot3 = 0.5773502692f;
347cb93a386Sopenharmony_ci
348cb93a386Sopenharmony_ci    SkPoint3       norm;
349cb93a386Sopenharmony_ci    const SkPoint3 leftUp  = SkPoint3::Make(-k1OverRoot3, -k1OverRoot3, k1OverRoot3);
350cb93a386Sopenharmony_ci    const SkPoint3 rightUp = SkPoint3::Make(k1OverRoot3, -k1OverRoot3, k1OverRoot3);
351cb93a386Sopenharmony_ci    const SkPoint3 down    = SkPoint3::Make(0.0f, SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
352cb93a386Sopenharmony_ci
353cb93a386Sopenharmony_ci    for (int y = dst.fTop; y < dst.fBottom; ++y) {
354cb93a386Sopenharmony_ci        for (int x = dst.fLeft; x < dst.fRight; ++x) {
355cb93a386Sopenharmony_ci            SkScalar locX = x + 0.5f - center.fX;
356cb93a386Sopenharmony_ci            SkScalar locY = y + 0.5f - center.fY;
357cb93a386Sopenharmony_ci
358cb93a386Sopenharmony_ci            if (locX >= 0.0f) {
359cb93a386Sopenharmony_ci                if (locY > 0.0f) {
360cb93a386Sopenharmony_ci                    norm = locX >= locY ? rightUp : down;  // LR corner
361cb93a386Sopenharmony_ci                } else {
362cb93a386Sopenharmony_ci                    norm = rightUp;
363cb93a386Sopenharmony_ci                }
364cb93a386Sopenharmony_ci            } else {
365cb93a386Sopenharmony_ci                if (locY > 0.0f) {
366cb93a386Sopenharmony_ci                    norm = -locX > locY ? leftUp : down;  // LL corner
367cb93a386Sopenharmony_ci                } else {
368cb93a386Sopenharmony_ci                    norm = leftUp;
369cb93a386Sopenharmony_ci                }
370cb93a386Sopenharmony_ci            }
371cb93a386Sopenharmony_ci
372cb93a386Sopenharmony_ci            norm_to_rgb(bm, x, y, norm);
373cb93a386Sopenharmony_ci        }
374cb93a386Sopenharmony_ci    }
375cb93a386Sopenharmony_ci}
376cb93a386Sopenharmony_ci
377cb93a386Sopenharmony_cibool copy_to(SkBitmap* dst, SkColorType dstColorType, const SkBitmap& src) {
378cb93a386Sopenharmony_ci    SkPixmap srcPM;
379cb93a386Sopenharmony_ci    if (!src.peekPixels(&srcPM)) {
380cb93a386Sopenharmony_ci        return false;
381cb93a386Sopenharmony_ci    }
382cb93a386Sopenharmony_ci
383cb93a386Sopenharmony_ci    SkBitmap    tmpDst;
384cb93a386Sopenharmony_ci    SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType);
385cb93a386Sopenharmony_ci    if (!tmpDst.setInfo(dstInfo)) {
386cb93a386Sopenharmony_ci        return false;
387cb93a386Sopenharmony_ci    }
388cb93a386Sopenharmony_ci
389cb93a386Sopenharmony_ci    if (!tmpDst.tryAllocPixels()) {
390cb93a386Sopenharmony_ci        return false;
391cb93a386Sopenharmony_ci    }
392cb93a386Sopenharmony_ci
393cb93a386Sopenharmony_ci    SkPixmap dstPM;
394cb93a386Sopenharmony_ci    if (!tmpDst.peekPixels(&dstPM)) {
395cb93a386Sopenharmony_ci        return false;
396cb93a386Sopenharmony_ci    }
397cb93a386Sopenharmony_ci
398cb93a386Sopenharmony_ci    if (!srcPM.readPixels(dstPM)) {
399cb93a386Sopenharmony_ci        return false;
400cb93a386Sopenharmony_ci    }
401cb93a386Sopenharmony_ci
402cb93a386Sopenharmony_ci    dst->swap(tmpDst);
403cb93a386Sopenharmony_ci    return true;
404cb93a386Sopenharmony_ci}
405cb93a386Sopenharmony_ci
406cb93a386Sopenharmony_civoid copy_to_g8(SkBitmap* dst, const SkBitmap& src) {
407cb93a386Sopenharmony_ci    SkASSERT(kBGRA_8888_SkColorType == src.colorType() ||
408cb93a386Sopenharmony_ci             kRGBA_8888_SkColorType == src.colorType());
409cb93a386Sopenharmony_ci
410cb93a386Sopenharmony_ci    SkImageInfo grayInfo = src.info().makeColorType(kGray_8_SkColorType);
411cb93a386Sopenharmony_ci    dst->allocPixels(grayInfo);
412cb93a386Sopenharmony_ci    uint8_t*        dst8  = (uint8_t*)dst->getPixels();
413cb93a386Sopenharmony_ci    const uint32_t* src32 = (const uint32_t*)src.getPixels();
414cb93a386Sopenharmony_ci
415cb93a386Sopenharmony_ci    const int  w      = src.width();
416cb93a386Sopenharmony_ci    const int  h      = src.height();
417cb93a386Sopenharmony_ci    const bool isBGRA = (kBGRA_8888_SkColorType == src.colorType());
418cb93a386Sopenharmony_ci    for (int y = 0; y < h; ++y) {
419cb93a386Sopenharmony_ci        if (isBGRA) {
420cb93a386Sopenharmony_ci            // BGRA
421cb93a386Sopenharmony_ci            for (int x = 0; x < w; ++x) {
422cb93a386Sopenharmony_ci                uint32_t s = src32[x];
423cb93a386Sopenharmony_ci                dst8[x]    = SkComputeLuminance((s >> 16) & 0xFF, (s >> 8) & 0xFF, s & 0xFF);
424cb93a386Sopenharmony_ci            }
425cb93a386Sopenharmony_ci        } else {
426cb93a386Sopenharmony_ci            // RGBA
427cb93a386Sopenharmony_ci            for (int x = 0; x < w; ++x) {
428cb93a386Sopenharmony_ci                uint32_t s = src32[x];
429cb93a386Sopenharmony_ci                dst8[x]    = SkComputeLuminance(s & 0xFF, (s >> 8) & 0xFF, (s >> 16) & 0xFF);
430cb93a386Sopenharmony_ci            }
431cb93a386Sopenharmony_ci        }
432cb93a386Sopenharmony_ci        src32 = (const uint32_t*)((const char*)src32 + src.rowBytes());
433cb93a386Sopenharmony_ci        dst8 += dst->rowBytes();
434cb93a386Sopenharmony_ci    }
435cb93a386Sopenharmony_ci}
436cb93a386Sopenharmony_ci
437cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////////////////
438cb93a386Sopenharmony_ci
439cb93a386Sopenharmony_cibool equal_pixels(const SkPixmap& a, const SkPixmap& b) {
440cb93a386Sopenharmony_ci    if (a.width() != b.width() || a.height() != b.height() || a.colorType() != b.colorType()) {
441cb93a386Sopenharmony_ci        return false;
442cb93a386Sopenharmony_ci    }
443cb93a386Sopenharmony_ci
444cb93a386Sopenharmony_ci    for (int y = 0; y < a.height(); ++y) {
445cb93a386Sopenharmony_ci        const char* aptr = (const char*)a.addr(0, y);
446cb93a386Sopenharmony_ci        const char* bptr = (const char*)b.addr(0, y);
447cb93a386Sopenharmony_ci        if (0 != memcmp(aptr, bptr, a.width() * a.info().bytesPerPixel())) {
448cb93a386Sopenharmony_ci            return false;
449cb93a386Sopenharmony_ci        }
450cb93a386Sopenharmony_ci    }
451cb93a386Sopenharmony_ci    return true;
452cb93a386Sopenharmony_ci}
453cb93a386Sopenharmony_ci
454cb93a386Sopenharmony_cibool equal_pixels(const SkBitmap& bm0, const SkBitmap& bm1) {
455cb93a386Sopenharmony_ci    SkPixmap pm0, pm1;
456cb93a386Sopenharmony_ci    return bm0.peekPixels(&pm0) && bm1.peekPixels(&pm1) && equal_pixels(pm0, pm1);
457cb93a386Sopenharmony_ci}
458cb93a386Sopenharmony_ci
459cb93a386Sopenharmony_cibool equal_pixels(const SkImage* a, const SkImage* b) {
460cb93a386Sopenharmony_ci    // ensure that peekPixels will succeed
461cb93a386Sopenharmony_ci    auto imga = a->makeRasterImage();
462cb93a386Sopenharmony_ci    auto imgb = b->makeRasterImage();
463cb93a386Sopenharmony_ci
464cb93a386Sopenharmony_ci    SkPixmap pm0, pm1;
465cb93a386Sopenharmony_ci    return imga->peekPixels(&pm0) && imgb->peekPixels(&pm1) && equal_pixels(pm0, pm1);
466cb93a386Sopenharmony_ci}
467cb93a386Sopenharmony_ci
468cb93a386Sopenharmony_cisk_sp<SkSurface> makeSurface(SkCanvas*             canvas,
469cb93a386Sopenharmony_ci                             const SkImageInfo&    info,
470cb93a386Sopenharmony_ci                             const SkSurfaceProps* props) {
471cb93a386Sopenharmony_ci    auto surf = canvas->makeSurface(info, props);
472cb93a386Sopenharmony_ci    if (!surf) {
473cb93a386Sopenharmony_ci        surf = SkSurface::MakeRaster(info, props);
474cb93a386Sopenharmony_ci    }
475cb93a386Sopenharmony_ci    return surf;
476cb93a386Sopenharmony_ci}
477cb93a386Sopenharmony_ci
478cb93a386Sopenharmony_civoid sniff_paths(const char filepath[], std::function<PathSniffCallback> callback) {
479cb93a386Sopenharmony_ci    SkFILEStream stream(filepath);
480cb93a386Sopenharmony_ci    if (!stream.isValid()) {
481cb93a386Sopenharmony_ci        SkDebugf("sniff_paths: invalid input file at \"%s\"\n", filepath);
482cb93a386Sopenharmony_ci        return;
483cb93a386Sopenharmony_ci    }
484cb93a386Sopenharmony_ci
485cb93a386Sopenharmony_ci    class PathSniffer : public SkCanvas {
486cb93a386Sopenharmony_ci    public:
487cb93a386Sopenharmony_ci        PathSniffer(std::function<PathSniffCallback> callback)
488cb93a386Sopenharmony_ci                : SkCanvas(4096, 4096, nullptr)
489cb93a386Sopenharmony_ci                , fPathSniffCallback(callback) {}
490cb93a386Sopenharmony_ci    private:
491cb93a386Sopenharmony_ci        void onDrawPath(const SkPath& path, const SkPaint& paint) override {
492cb93a386Sopenharmony_ci            fPathSniffCallback(this->getTotalMatrix(), path, paint);
493cb93a386Sopenharmony_ci        }
494cb93a386Sopenharmony_ci        std::function<PathSniffCallback> fPathSniffCallback;
495cb93a386Sopenharmony_ci    };
496cb93a386Sopenharmony_ci
497cb93a386Sopenharmony_ci    PathSniffer pathSniffer(callback);
498cb93a386Sopenharmony_ci    if (const char* ext = strrchr(filepath, '.'); ext && !strcmp(ext, ".svg")) {
499cb93a386Sopenharmony_ci#if defined(SK_ENABLE_SVG)
500cb93a386Sopenharmony_ci        sk_sp<SkSVGDOM> svg = SkSVGDOM::MakeFromStream(stream);
501cb93a386Sopenharmony_ci        if (!svg) {
502cb93a386Sopenharmony_ci            SkDebugf("sniff_paths: couldn't load svg at \"%s\"\n", filepath);
503cb93a386Sopenharmony_ci            return;
504cb93a386Sopenharmony_ci        }
505cb93a386Sopenharmony_ci        svg->setContainerSize(SkSize::Make(pathSniffer.getBaseLayerSize()));
506cb93a386Sopenharmony_ci        svg->render(&pathSniffer);
507cb93a386Sopenharmony_ci#endif
508cb93a386Sopenharmony_ci    } else {
509cb93a386Sopenharmony_ci        sk_sp<SkPicture> skp = SkPicture::MakeFromStream(&stream);
510cb93a386Sopenharmony_ci        if (!skp) {
511cb93a386Sopenharmony_ci            SkDebugf("sniff_paths: couldn't load skp at \"%s\"\n", filepath);
512cb93a386Sopenharmony_ci            return;
513cb93a386Sopenharmony_ci        }
514cb93a386Sopenharmony_ci        skp->playback(&pathSniffer);
515cb93a386Sopenharmony_ci    }
516cb93a386Sopenharmony_ci}
517cb93a386Sopenharmony_ci
518cb93a386Sopenharmony_ci}  // namespace ToolUtils
519