ToolUtils.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  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. #include "include/core/SkBitmap.h"
  8. #include "include/core/SkBlendMode.h"
  9. #include "include/core/SkCanvas.h"
  10. #include "include/core/SkColorPriv.h"
  11. #include "include/core/SkImage.h"
  12. #include "include/core/SkMatrix.h"
  13. #include "include/core/SkPaint.h"
  14. #include "include/core/SkPath.h"
  15. #include "include/core/SkPixelRef.h"
  16. #include "include/core/SkPixmap.h"
  17. #include "include/core/SkPoint3.h"
  18. #include "include/core/SkRRect.h"
  19. #include "include/core/SkShader.h"
  20. #include "include/core/SkSurface.h"
  21. #include "include/core/SkTextBlob.h"
  22. #include "include/ports/SkTypeface_win.h"
  23. #include "include/private/SkColorData.h"
  24. #include "include/private/SkFloatingPoint.h"
  25. #include "src/core/SkFontMgrPriv.h"
  26. #include "src/core/SkFontPriv.h"
  27. #include "tools/ToolUtils.h"
  28. #include "tools/flags/CommandLineFlags.h"
  29. #include "tools/fonts/TestFontMgr.h"
  30. #include <cmath>
  31. #include <cstring>
  32. #include <memory>
  33. namespace ToolUtils {
  34. const char* alphatype_name(SkAlphaType at) {
  35. switch (at) {
  36. case kUnknown_SkAlphaType: return "Unknown";
  37. case kOpaque_SkAlphaType: return "Opaque";
  38. case kPremul_SkAlphaType: return "Premul";
  39. case kUnpremul_SkAlphaType: return "Unpremul";
  40. }
  41. SkASSERT(false);
  42. return "unexpected alphatype";
  43. }
  44. const char* colortype_name(SkColorType ct) {
  45. switch (ct) {
  46. case kUnknown_SkColorType: return "Unknown";
  47. case kAlpha_8_SkColorType: return "Alpha_8";
  48. case kRGB_565_SkColorType: return "RGB_565";
  49. case kARGB_4444_SkColorType: return "ARGB_4444";
  50. case kRGBA_8888_SkColorType: return "RGBA_8888";
  51. case kRGB_888x_SkColorType: return "RGB_888x";
  52. case kBGRA_8888_SkColorType: return "BGRA_8888";
  53. case kRGBA_1010102_SkColorType: return "RGBA_1010102";
  54. case kRGB_101010x_SkColorType: return "RGB_101010x";
  55. case kGray_8_SkColorType: return "Gray_8";
  56. case kRGBA_F16Norm_SkColorType: return "RGBA_F16Norm";
  57. case kRGBA_F16_SkColorType: return "RGBA_F16";
  58. case kRGBA_F32_SkColorType: return "RGBA_F32";
  59. }
  60. SkASSERT(false);
  61. return "unexpected colortype";
  62. }
  63. const char* colortype_depth(SkColorType ct) {
  64. switch (ct) {
  65. case kUnknown_SkColorType: return "Unknown";
  66. case kAlpha_8_SkColorType: return "A8";
  67. case kRGB_565_SkColorType: return "565";
  68. case kARGB_4444_SkColorType: return "4444";
  69. case kRGBA_8888_SkColorType: return "8888";
  70. case kRGB_888x_SkColorType: return "888";
  71. case kBGRA_8888_SkColorType: return "8888";
  72. case kRGBA_1010102_SkColorType: return "1010102";
  73. case kRGB_101010x_SkColorType: return "101010";
  74. case kGray_8_SkColorType: return "G8";
  75. case kRGBA_F16Norm_SkColorType: return "F16Norm"; // TODO: "F16"?
  76. case kRGBA_F16_SkColorType: return "F16";
  77. case kRGBA_F32_SkColorType: return "F32";
  78. }
  79. SkASSERT(false);
  80. return "unexpected colortype";
  81. }
  82. SkColor color_to_565(SkColor color) {
  83. // Not a good idea to use this function for greyscale colors...
  84. // it will add an obvious purple or green tint.
  85. SkASSERT(SkColorGetR(color) != SkColorGetG(color) || SkColorGetR(color) != SkColorGetB(color) ||
  86. SkColorGetG(color) != SkColorGetB(color));
  87. SkPMColor pmColor = SkPreMultiplyColor(color);
  88. U16CPU color16 = SkPixel32ToPixel16(pmColor);
  89. return SkPixel16ToColor(color16);
  90. }
  91. sk_sp<SkShader> create_checkerboard_shader(SkColor c1, SkColor c2, int size) {
  92. SkBitmap bm;
  93. bm.allocPixels(SkImageInfo::MakeS32(2 * size, 2 * size, kPremul_SkAlphaType));
  94. bm.eraseColor(c1);
  95. bm.eraseArea(SkIRect::MakeLTRB(0, 0, size, size), c2);
  96. bm.eraseArea(SkIRect::MakeLTRB(size, size, 2 * size, 2 * size), c2);
  97. return bm.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat);
  98. }
  99. SkBitmap create_checkerboard_bitmap(int w, int h, SkColor c1, SkColor c2, int checkSize) {
  100. SkBitmap bitmap;
  101. bitmap.allocPixels(SkImageInfo::MakeS32(w, h, kPremul_SkAlphaType));
  102. SkCanvas canvas(bitmap);
  103. ToolUtils::draw_checkerboard(&canvas, c1, c2, checkSize);
  104. return bitmap;
  105. }
  106. void draw_checkerboard(SkCanvas* canvas, SkColor c1, SkColor c2, int size) {
  107. SkPaint paint;
  108. paint.setShader(create_checkerboard_shader(c1, c2, size));
  109. paint.setBlendMode(SkBlendMode::kSrc);
  110. canvas->drawPaint(paint);
  111. }
  112. SkBitmap
  113. create_string_bitmap(int w, int h, SkColor c, int x, int y, int textSize, const char* str) {
  114. SkBitmap bitmap;
  115. bitmap.allocN32Pixels(w, h);
  116. SkCanvas canvas(bitmap);
  117. SkPaint paint;
  118. paint.setColor(c);
  119. SkFont font(ToolUtils::create_portable_typeface(), textSize);
  120. canvas.clear(0x00000000);
  121. canvas.drawSimpleText(str,
  122. strlen(str),
  123. SkTextEncoding::kUTF8,
  124. SkIntToScalar(x),
  125. SkIntToScalar(y),
  126. font,
  127. paint);
  128. // Tag data as sRGB (without doing any color space conversion). Color-space aware configs
  129. // will process this correctly but legacy configs will render as if this returned N32.
  130. SkBitmap result;
  131. result.setInfo(SkImageInfo::MakeS32(w, h, kPremul_SkAlphaType));
  132. result.setPixelRef(sk_ref_sp(bitmap.pixelRef()), 0, 0);
  133. return result;
  134. }
  135. void add_to_text_blob_w_len(SkTextBlobBuilder* builder,
  136. const char* text,
  137. size_t len,
  138. SkTextEncoding encoding,
  139. const SkFont& font,
  140. SkScalar x,
  141. SkScalar y) {
  142. int count = font.countText(text, len, encoding);
  143. auto run = builder->allocRun(font, count, x, y);
  144. font.textToGlyphs(text, len, encoding, run.glyphs, count);
  145. }
  146. void add_to_text_blob(SkTextBlobBuilder* builder,
  147. const char* text,
  148. const SkFont& font,
  149. SkScalar x,
  150. SkScalar y) {
  151. add_to_text_blob_w_len(builder, text, strlen(text), SkTextEncoding::kUTF8, font, x, y);
  152. }
  153. void get_text_path(const SkFont& font,
  154. const void* text,
  155. size_t length,
  156. SkTextEncoding encoding,
  157. SkPath* dst,
  158. const SkPoint pos[]) {
  159. SkAutoToGlyphs atg(font, text, length, encoding);
  160. const int count = atg.count();
  161. SkAutoTArray<SkPoint> computedPos;
  162. if (pos == nullptr) {
  163. computedPos.reset(count);
  164. font.getPos(atg.glyphs(), count, &computedPos[0]);
  165. pos = computedPos.get();
  166. }
  167. struct Rec {
  168. SkPath* fDst;
  169. const SkPoint* fPos;
  170. } rec = {dst, pos};
  171. font.getPaths(atg.glyphs(),
  172. atg.count(),
  173. [](const SkPath* src, const SkMatrix& mx, void* ctx) {
  174. Rec* rec = (Rec*)ctx;
  175. if (src) {
  176. SkMatrix tmp(mx);
  177. tmp.postTranslate(rec->fPos->fX, rec->fPos->fY);
  178. rec->fDst->addPath(*src, tmp);
  179. }
  180. rec->fPos += 1;
  181. },
  182. &rec);
  183. }
  184. SkPath make_star(const SkRect& bounds, int numPts, int step) {
  185. SkASSERT(numPts != step);
  186. SkPath path;
  187. path.setFillType(SkPath::kEvenOdd_FillType);
  188. path.moveTo(0, -1);
  189. for (int i = 1; i < numPts; ++i) {
  190. int idx = i * step % numPts;
  191. SkScalar theta = idx * 2 * SK_ScalarPI / numPts + SK_ScalarPI / 2;
  192. SkScalar x = SkScalarCos(theta);
  193. SkScalar y = -SkScalarSin(theta);
  194. path.lineTo(x, y);
  195. }
  196. path.transform(SkMatrix::MakeRectToRect(path.getBounds(), bounds, SkMatrix::kFill_ScaleToFit));
  197. return path;
  198. }
  199. static inline void norm_to_rgb(SkBitmap* bm, int x, int y, const SkVector3& norm) {
  200. SkASSERT(SkScalarNearlyEqual(norm.length(), 1.0f));
  201. unsigned char r = static_cast<unsigned char>((0.5f * norm.fX + 0.5f) * 255);
  202. unsigned char g = static_cast<unsigned char>((-0.5f * norm.fY + 0.5f) * 255);
  203. unsigned char b = static_cast<unsigned char>((0.5f * norm.fZ + 0.5f) * 255);
  204. *bm->getAddr32(x, y) = SkPackARGB32(0xFF, r, g, b);
  205. }
  206. void create_hemi_normal_map(SkBitmap* bm, const SkIRect& dst) {
  207. const SkPoint center =
  208. SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), dst.fTop + (dst.height() / 2.0f));
  209. const SkPoint halfSize = SkPoint::Make(dst.width() / 2.0f, dst.height() / 2.0f);
  210. SkVector3 norm;
  211. for (int y = dst.fTop; y < dst.fBottom; ++y) {
  212. for (int x = dst.fLeft; x < dst.fRight; ++x) {
  213. norm.fX = (x + 0.5f - center.fX) / halfSize.fX;
  214. norm.fY = (y + 0.5f - center.fY) / halfSize.fY;
  215. SkScalar tmp = norm.fX * norm.fX + norm.fY * norm.fY;
  216. if (tmp >= 1.0f) {
  217. norm.set(0.0f, 0.0f, 1.0f);
  218. } else {
  219. norm.fZ = sqrtf(1.0f - tmp);
  220. }
  221. norm_to_rgb(bm, x, y, norm);
  222. }
  223. }
  224. }
  225. void create_frustum_normal_map(SkBitmap* bm, const SkIRect& dst) {
  226. const SkPoint center =
  227. SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), dst.fTop + (dst.height() / 2.0f));
  228. SkIRect inner = dst;
  229. inner.inset(dst.width() / 4, dst.height() / 4);
  230. SkPoint3 norm;
  231. const SkPoint3 left = SkPoint3::Make(-SK_ScalarRoot2Over2, 0.0f, SK_ScalarRoot2Over2);
  232. const SkPoint3 up = SkPoint3::Make(0.0f, -SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
  233. const SkPoint3 right = SkPoint3::Make(SK_ScalarRoot2Over2, 0.0f, SK_ScalarRoot2Over2);
  234. const SkPoint3 down = SkPoint3::Make(0.0f, SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
  235. for (int y = dst.fTop; y < dst.fBottom; ++y) {
  236. for (int x = dst.fLeft; x < dst.fRight; ++x) {
  237. if (inner.contains(x, y)) {
  238. norm.set(0.0f, 0.0f, 1.0f);
  239. } else {
  240. SkScalar locX = x + 0.5f - center.fX;
  241. SkScalar locY = y + 0.5f - center.fY;
  242. if (locX >= 0.0f) {
  243. if (locY > 0.0f) {
  244. norm = locX >= locY ? right : down; // LR corner
  245. } else {
  246. norm = locX > -locY ? right : up; // UR corner
  247. }
  248. } else {
  249. if (locY > 0.0f) {
  250. norm = -locX > locY ? left : down; // LL corner
  251. } else {
  252. norm = locX > locY ? up : left; // UL corner
  253. }
  254. }
  255. }
  256. norm_to_rgb(bm, x, y, norm);
  257. }
  258. }
  259. }
  260. void create_tetra_normal_map(SkBitmap* bm, const SkIRect& dst) {
  261. const SkPoint center =
  262. SkPoint::Make(dst.fLeft + (dst.width() / 2.0f), dst.fTop + (dst.height() / 2.0f));
  263. static const SkScalar k1OverRoot3 = 0.5773502692f;
  264. SkPoint3 norm;
  265. const SkPoint3 leftUp = SkPoint3::Make(-k1OverRoot3, -k1OverRoot3, k1OverRoot3);
  266. const SkPoint3 rightUp = SkPoint3::Make(k1OverRoot3, -k1OverRoot3, k1OverRoot3);
  267. const SkPoint3 down = SkPoint3::Make(0.0f, SK_ScalarRoot2Over2, SK_ScalarRoot2Over2);
  268. for (int y = dst.fTop; y < dst.fBottom; ++y) {
  269. for (int x = dst.fLeft; x < dst.fRight; ++x) {
  270. SkScalar locX = x + 0.5f - center.fX;
  271. SkScalar locY = y + 0.5f - center.fY;
  272. if (locX >= 0.0f) {
  273. if (locY > 0.0f) {
  274. norm = locX >= locY ? rightUp : down; // LR corner
  275. } else {
  276. norm = rightUp;
  277. }
  278. } else {
  279. if (locY > 0.0f) {
  280. norm = -locX > locY ? leftUp : down; // LL corner
  281. } else {
  282. norm = leftUp;
  283. }
  284. }
  285. norm_to_rgb(bm, x, y, norm);
  286. }
  287. }
  288. }
  289. #if !defined(__clang__) && defined(_MSC_VER)
  290. // MSVC takes ~2 minutes to compile this function with optimization.
  291. // We don't really care to wait that long for this function.
  292. #pragma optimize("", off)
  293. #endif
  294. void make_big_path(SkPath& path) {
  295. #include "BigPathBench.inc" // IWYU pragma: keep
  296. }
  297. bool copy_to(SkBitmap* dst, SkColorType dstColorType, const SkBitmap& src) {
  298. SkPixmap srcPM;
  299. if (!src.peekPixels(&srcPM)) {
  300. return false;
  301. }
  302. SkBitmap tmpDst;
  303. SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType);
  304. if (!tmpDst.setInfo(dstInfo)) {
  305. return false;
  306. }
  307. if (!tmpDst.tryAllocPixels()) {
  308. return false;
  309. }
  310. SkPixmap dstPM;
  311. if (!tmpDst.peekPixels(&dstPM)) {
  312. return false;
  313. }
  314. if (!srcPM.readPixels(dstPM)) {
  315. return false;
  316. }
  317. dst->swap(tmpDst);
  318. return true;
  319. }
  320. void copy_to_g8(SkBitmap* dst, const SkBitmap& src) {
  321. SkASSERT(kBGRA_8888_SkColorType == src.colorType() ||
  322. kRGBA_8888_SkColorType == src.colorType());
  323. SkImageInfo grayInfo = src.info().makeColorType(kGray_8_SkColorType);
  324. dst->allocPixels(grayInfo);
  325. uint8_t* dst8 = (uint8_t*)dst->getPixels();
  326. const uint32_t* src32 = (const uint32_t*)src.getPixels();
  327. const int w = src.width();
  328. const int h = src.height();
  329. const bool isBGRA = (kBGRA_8888_SkColorType == src.colorType());
  330. for (int y = 0; y < h; ++y) {
  331. if (isBGRA) {
  332. // BGRA
  333. for (int x = 0; x < w; ++x) {
  334. uint32_t s = src32[x];
  335. dst8[x] = SkComputeLuminance((s >> 16) & 0xFF, (s >> 8) & 0xFF, s & 0xFF);
  336. }
  337. } else {
  338. // RGBA
  339. for (int x = 0; x < w; ++x) {
  340. uint32_t s = src32[x];
  341. dst8[x] = SkComputeLuminance(s & 0xFF, (s >> 8) & 0xFF, (s >> 16) & 0xFF);
  342. }
  343. }
  344. src32 = (const uint32_t*)((const char*)src32 + src.rowBytes());
  345. dst8 += dst->rowBytes();
  346. }
  347. }
  348. //////////////////////////////////////////////////////////////////////////////////////////////
  349. bool equal_pixels(const SkPixmap& a, const SkPixmap& b) {
  350. if (a.width() != b.width() || a.height() != b.height() || a.colorType() != b.colorType()) {
  351. return false;
  352. }
  353. for (int y = 0; y < a.height(); ++y) {
  354. const char* aptr = (const char*)a.addr(0, y);
  355. const char* bptr = (const char*)b.addr(0, y);
  356. if (memcmp(aptr, bptr, a.width() * a.info().bytesPerPixel())) {
  357. return false;
  358. }
  359. aptr += a.rowBytes();
  360. bptr += b.rowBytes();
  361. }
  362. return true;
  363. }
  364. bool equal_pixels(const SkBitmap& bm0, const SkBitmap& bm1) {
  365. SkPixmap pm0, pm1;
  366. return bm0.peekPixels(&pm0) && bm1.peekPixels(&pm1) && equal_pixels(pm0, pm1);
  367. }
  368. bool equal_pixels(const SkImage* a, const SkImage* b) {
  369. // ensure that peekPixels will succeed
  370. auto imga = a->makeRasterImage();
  371. auto imgb = b->makeRasterImage();
  372. SkPixmap pm0, pm1;
  373. return imga->peekPixels(&pm0) && imgb->peekPixels(&pm1) && equal_pixels(pm0, pm1);
  374. }
  375. sk_sp<SkSurface> makeSurface(SkCanvas* canvas,
  376. const SkImageInfo& info,
  377. const SkSurfaceProps* props) {
  378. auto surf = canvas->makeSurface(info, props);
  379. if (!surf) {
  380. surf = SkSurface::MakeRaster(info, props);
  381. }
  382. return surf;
  383. }
  384. static DEFINE_bool(nativeFonts, true,
  385. "If true, use native font manager and rendering. "
  386. "If false, fonts will draw as portably as possible.");
  387. #if defined(SK_BUILD_FOR_WIN)
  388. static DEFINE_bool(gdi, false,
  389. "Use GDI instead of DirectWrite for font rendering.");
  390. #endif
  391. void SetDefaultFontMgr() {
  392. if (!FLAGS_nativeFonts) {
  393. gSkFontMgr_DefaultFactory = &ToolUtils::MakePortableFontMgr;
  394. }
  395. #if defined(SK_BUILD_FOR_WIN)
  396. if (FLAGS_gdi) {
  397. gSkFontMgr_DefaultFactory = &SkFontMgr_New_GDI;
  398. }
  399. #endif
  400. }
  401. } // namespace ToolUtils