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