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