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