1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2019 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontMgr.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/encode/SkPngEncoder.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/chromium/SkChromeRemoteGlyphCache.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkScalerContext.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "tools/text/SkTextBlobTrace.h"
17*c8dee2aaSAndroid Build Coastguard Worker
18*c8dee2aaSAndroid Build Coastguard Worker #include <iostream>
19*c8dee2aaSAndroid Build Coastguard Worker #include <string>
20*c8dee2aaSAndroid Build Coastguard Worker #include <unordered_map>
21*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
22*c8dee2aaSAndroid Build Coastguard Worker
main(int argc,char ** argv)23*c8dee2aaSAndroid Build Coastguard Worker int main(int argc, char** argv) {
24*c8dee2aaSAndroid Build Coastguard Worker std::unordered_map<uint64_t, uint32_t> counts;
25*c8dee2aaSAndroid Build Coastguard Worker size_t total = 0;
26*c8dee2aaSAndroid Build Coastguard Worker
27*c8dee2aaSAndroid Build Coastguard Worker for (int i = 1; i < argc; i++) {
28*c8dee2aaSAndroid Build Coastguard Worker const char* filename = argv[i];
29*c8dee2aaSAndroid Build Coastguard Worker
30*c8dee2aaSAndroid Build Coastguard Worker SkFILEStream in{filename};
31*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkTextBlobTrace::Record> trace = SkTextBlobTrace::CreateBlobTrace(&in, nullptr);
32*c8dee2aaSAndroid Build Coastguard Worker for (const SkTextBlobTrace::Record& record : trace) {
33*c8dee2aaSAndroid Build Coastguard Worker total++;
34*c8dee2aaSAndroid Build Coastguard Worker const SkPaint paint = record.paint;
35*c8dee2aaSAndroid Build Coastguard Worker bool fastByPass = paint.getStyle() == SkPaint::kFill_Style
36*c8dee2aaSAndroid Build Coastguard Worker && paint.getPathEffect() == nullptr
37*c8dee2aaSAndroid Build Coastguard Worker && paint.getMaskFilter() == nullptr;
38*c8dee2aaSAndroid Build Coastguard Worker if (fastByPass) {
39*c8dee2aaSAndroid Build Coastguard Worker uint64_t blobID = record.origUniqueID;
40*c8dee2aaSAndroid Build Coastguard Worker SkPoint offset = record.offset;
41*c8dee2aaSAndroid Build Coastguard Worker SkColor c = SkMaskGamma::CanonicalColor(paint.getColor());
42*c8dee2aaSAndroid Build Coastguard Worker uint32_t colorBits =
43*c8dee2aaSAndroid Build Coastguard Worker (SkColorGetR(c) >> 5u) << 6u
44*c8dee2aaSAndroid Build Coastguard Worker | (SkColorGetG(c) >> 5u) << 3u
45*c8dee2aaSAndroid Build Coastguard Worker | SkColorGetB(c) >> 5u;
46*c8dee2aaSAndroid Build Coastguard Worker
47*c8dee2aaSAndroid Build Coastguard Worker SkFixed fx = (SkScalarToFixed(offset.x()) >> 13) & 7;
48*c8dee2aaSAndroid Build Coastguard Worker SkFixed fy = (SkScalarToFixed(offset.y()) >> 13) & 7;
49*c8dee2aaSAndroid Build Coastguard Worker uint32_t posBits = (fx << 3 | fy) << 12;
50*c8dee2aaSAndroid Build Coastguard Worker
51*c8dee2aaSAndroid Build Coastguard Worker uint64_t blobKey = blobID << 32u | posBits | colorBits;
52*c8dee2aaSAndroid Build Coastguard Worker auto lookup = counts.find(blobKey);
53*c8dee2aaSAndroid Build Coastguard Worker if (lookup == counts.end()) {
54*c8dee2aaSAndroid Build Coastguard Worker bool ok;
55*c8dee2aaSAndroid Build Coastguard Worker std::tie(lookup, ok) = counts.insert({blobKey, 0});
56*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(ok);
57*c8dee2aaSAndroid Build Coastguard Worker }
58*c8dee2aaSAndroid Build Coastguard Worker lookup->second += 1;
59*c8dee2aaSAndroid Build Coastguard Worker std::cout << std::hex << blobKey << "\n";
60*c8dee2aaSAndroid Build Coastguard Worker }
61*c8dee2aaSAndroid Build Coastguard Worker }
62*c8dee2aaSAndroid Build Coastguard Worker std::cerr << "trace: " << filename
63*c8dee2aaSAndroid Build Coastguard Worker << " unique: " << counts.size()
64*c8dee2aaSAndroid Build Coastguard Worker << " all: " << total
65*c8dee2aaSAndroid Build Coastguard Worker << " ratio: " << (float)total/counts.size() << "\n";
66*c8dee2aaSAndroid Build Coastguard Worker
67*c8dee2aaSAndroid Build Coastguard Worker SkRect bounds = {0, 0, 0, 0};
68*c8dee2aaSAndroid Build Coastguard Worker for (const SkTextBlobTrace::Record& record : trace) {
69*c8dee2aaSAndroid Build Coastguard Worker bounds.join(record.blob->bounds().makeOffset(record.offset.x(), record.offset.y()));
70*c8dee2aaSAndroid Build Coastguard Worker }
71*c8dee2aaSAndroid Build Coastguard Worker SkIRect iBounds = bounds.roundOut();
72*c8dee2aaSAndroid Build Coastguard Worker if (iBounds.size().isEmpty()) {
73*c8dee2aaSAndroid Build Coastguard Worker continue;
74*c8dee2aaSAndroid Build Coastguard Worker }
75*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkColor kBackground = SK_ColorWHITE;
76*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surf = SkSurfaces::Raster(
77*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo::MakeN32Premul(iBounds.width() + 16, iBounds.height() + 16));
78*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surf->getCanvas();
79*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(8.0f - iBounds.x(), 8.0f - iBounds.y());
80*c8dee2aaSAndroid Build Coastguard Worker canvas->clear(kBackground);
81*c8dee2aaSAndroid Build Coastguard Worker
82*c8dee2aaSAndroid Build Coastguard Worker for (const SkTextBlobTrace::Record& record : trace) {
83*c8dee2aaSAndroid Build Coastguard Worker canvas->drawTextBlob(
84*c8dee2aaSAndroid Build Coastguard Worker record.blob.get(), record.offset.x(), record.offset.y(), record.paint);
85*c8dee2aaSAndroid Build Coastguard Worker }
86*c8dee2aaSAndroid Build Coastguard Worker
87*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> img(surf->makeImageSnapshot());
88*c8dee2aaSAndroid Build Coastguard Worker if (img) {
89*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> png = SkPngEncoder::Encode(nullptr, img.get(), {});
90*c8dee2aaSAndroid Build Coastguard Worker if (png) {
91*c8dee2aaSAndroid Build Coastguard Worker SkString path = SkStringPrintf("text_blob_trace_%04d.png", i);
92*c8dee2aaSAndroid Build Coastguard Worker SkFILEWStream(path.c_str()).write(png->data(), png->size());
93*c8dee2aaSAndroid Build Coastguard Worker }
94*c8dee2aaSAndroid Build Coastguard Worker }
95*c8dee2aaSAndroid Build Coastguard Worker }
96*c8dee2aaSAndroid Build Coastguard Worker return 0;
97*c8dee2aaSAndroid Build Coastguard Worker }
98