1*c8dee2aaSAndroid Build Coastguard Worker // Copyright 2019 Google LLC.
2*c8dee2aaSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
3*c8dee2aaSAndroid Build Coastguard Worker
4*c8dee2aaSAndroid Build Coastguard Worker #include "tools/text/SkTextBlobTrace.h"
5*c8dee2aaSAndroid Build Coastguard Worker
6*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
7*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h"
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontMgr.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextBlob.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkTLazy.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkChecksum.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkFontPriv.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkPtrRecorder.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkReadBuffer.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTextBlobPriv.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkWriteBuffer.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/text/GlyphRun.h"
22*c8dee2aaSAndroid Build Coastguard Worker
23*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
24*c8dee2aaSAndroid Build Coastguard Worker
CreateBlobTrace(SkStream * stream,sk_sp<SkFontMgr> lastResortMgr)25*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkTextBlobTrace::Record> SkTextBlobTrace::CreateBlobTrace(
26*c8dee2aaSAndroid Build Coastguard Worker SkStream* stream, sk_sp<SkFontMgr> lastResortMgr) {
27*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkTextBlobTrace::Record> trace;
28*c8dee2aaSAndroid Build Coastguard Worker
29*c8dee2aaSAndroid Build Coastguard Worker uint32_t typefaceCount;
30*c8dee2aaSAndroid Build Coastguard Worker if (!stream->readU32(&typefaceCount)) {
31*c8dee2aaSAndroid Build Coastguard Worker return trace;
32*c8dee2aaSAndroid Build Coastguard Worker }
33*c8dee2aaSAndroid Build Coastguard Worker
34*c8dee2aaSAndroid Build Coastguard Worker std::vector<sk_sp<SkTypeface>> typefaceArray;
35*c8dee2aaSAndroid Build Coastguard Worker for (uint32_t i = 0; i < typefaceCount; i++) {
36*c8dee2aaSAndroid Build Coastguard Worker typefaceArray.push_back(SkTypeface::MakeDeserialize(stream, lastResortMgr));
37*c8dee2aaSAndroid Build Coastguard Worker }
38*c8dee2aaSAndroid Build Coastguard Worker
39*c8dee2aaSAndroid Build Coastguard Worker uint32_t restOfFile;
40*c8dee2aaSAndroid Build Coastguard Worker if (!stream->readU32(&restOfFile)) {
41*c8dee2aaSAndroid Build Coastguard Worker return trace;
42*c8dee2aaSAndroid Build Coastguard Worker }
43*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data = SkData::MakeFromStream(stream, restOfFile);
44*c8dee2aaSAndroid Build Coastguard Worker SkReadBuffer readBuffer{data->data(), data->size()};
45*c8dee2aaSAndroid Build Coastguard Worker readBuffer.setTypefaceArray(typefaceArray.data(), typefaceArray.size());
46*c8dee2aaSAndroid Build Coastguard Worker
47*c8dee2aaSAndroid Build Coastguard Worker while (!readBuffer.eof()) {
48*c8dee2aaSAndroid Build Coastguard Worker SkTextBlobTrace::Record record;
49*c8dee2aaSAndroid Build Coastguard Worker record.origUniqueID = readBuffer.readUInt();
50*c8dee2aaSAndroid Build Coastguard Worker record.paint = readBuffer.readPaint();
51*c8dee2aaSAndroid Build Coastguard Worker readBuffer.readPoint(&record.offset);
52*c8dee2aaSAndroid Build Coastguard Worker record.blob = SkTextBlobPriv::MakeFromBuffer(readBuffer);
53*c8dee2aaSAndroid Build Coastguard Worker trace.push_back(std::move(record));
54*c8dee2aaSAndroid Build Coastguard Worker }
55*c8dee2aaSAndroid Build Coastguard Worker return trace;
56*c8dee2aaSAndroid Build Coastguard Worker }
57*c8dee2aaSAndroid Build Coastguard Worker
DumpTrace(const std::vector<SkTextBlobTrace::Record> & trace)58*c8dee2aaSAndroid Build Coastguard Worker void SkTextBlobTrace::DumpTrace(const std::vector<SkTextBlobTrace::Record>& trace) {
59*c8dee2aaSAndroid Build Coastguard Worker for (const SkTextBlobTrace::Record& record : trace) {
60*c8dee2aaSAndroid Build Coastguard Worker const SkTextBlob* blob = record.blob.get();
61*c8dee2aaSAndroid Build Coastguard Worker const SkPaint& p = record.paint;
62*c8dee2aaSAndroid Build Coastguard Worker bool weirdPaint = p.getStyle() != SkPaint::kFill_Style
63*c8dee2aaSAndroid Build Coastguard Worker || p.getMaskFilter() != nullptr
64*c8dee2aaSAndroid Build Coastguard Worker || p.getPathEffect() != nullptr;
65*c8dee2aaSAndroid Build Coastguard Worker
66*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Blob %u ( %g %g ) %d\n ",
67*c8dee2aaSAndroid Build Coastguard Worker blob->uniqueID(), record.offset.x(), record.offset.y(), weirdPaint);
68*c8dee2aaSAndroid Build Coastguard Worker SkTextBlobRunIterator iter(blob);
69*c8dee2aaSAndroid Build Coastguard Worker int runNumber = 0;
70*c8dee2aaSAndroid Build Coastguard Worker while (!iter.done()) {
71*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Run %d\n ", runNumber);
72*c8dee2aaSAndroid Build Coastguard Worker SkFont font = iter.font();
73*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Font %u %g %g %g %d %d %d\n ",
74*c8dee2aaSAndroid Build Coastguard Worker font.getTypeface()->uniqueID(),
75*c8dee2aaSAndroid Build Coastguard Worker font.getSize(),
76*c8dee2aaSAndroid Build Coastguard Worker font.getScaleX(),
77*c8dee2aaSAndroid Build Coastguard Worker font.getSkewX(),
78*c8dee2aaSAndroid Build Coastguard Worker SkFontPriv::Flags(font),
79*c8dee2aaSAndroid Build Coastguard Worker (int)font.getEdging(),
80*c8dee2aaSAndroid Build Coastguard Worker (int)font.getHinting());
81*c8dee2aaSAndroid Build Coastguard Worker uint32_t glyphCount = iter.glyphCount();
82*c8dee2aaSAndroid Build Coastguard Worker const uint16_t* glyphs = iter.glyphs();
83*c8dee2aaSAndroid Build Coastguard Worker for (uint32_t i = 0; i < glyphCount; i++) {
84*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("%02X ", glyphs[i]);
85*c8dee2aaSAndroid Build Coastguard Worker }
86*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("\n");
87*c8dee2aaSAndroid Build Coastguard Worker runNumber += 1;
88*c8dee2aaSAndroid Build Coastguard Worker iter.next();
89*c8dee2aaSAndroid Build Coastguard Worker }
90*c8dee2aaSAndroid Build Coastguard Worker }
91*c8dee2aaSAndroid Build Coastguard Worker }
92*c8dee2aaSAndroid Build Coastguard Worker
Capture()93*c8dee2aaSAndroid Build Coastguard Worker SkTextBlobTrace::Capture::Capture() : fTypefaceSet(new SkRefCntSet), fWriteBuffer({}) {
94*c8dee2aaSAndroid Build Coastguard Worker fWriteBuffer.setTypefaceRecorder(fTypefaceSet);
95*c8dee2aaSAndroid Build Coastguard Worker }
96*c8dee2aaSAndroid Build Coastguard Worker
97*c8dee2aaSAndroid Build Coastguard Worker SkTextBlobTrace::Capture::~Capture() = default;
98*c8dee2aaSAndroid Build Coastguard Worker
capture(const sktext::GlyphRunList & glyphRunList,const SkPaint & paint)99*c8dee2aaSAndroid Build Coastguard Worker void SkTextBlobTrace::Capture::capture(
100*c8dee2aaSAndroid Build Coastguard Worker const sktext::GlyphRunList& glyphRunList, const SkPaint& paint) {
101*c8dee2aaSAndroid Build Coastguard Worker const SkTextBlob* blob = glyphRunList.blob();
102*c8dee2aaSAndroid Build Coastguard Worker if (blob != nullptr) {
103*c8dee2aaSAndroid Build Coastguard Worker fWriteBuffer.writeUInt(blob->uniqueID());
104*c8dee2aaSAndroid Build Coastguard Worker fWriteBuffer.writePaint(paint);
105*c8dee2aaSAndroid Build Coastguard Worker fWriteBuffer.writePoint(glyphRunList.origin());
106*c8dee2aaSAndroid Build Coastguard Worker SkTextBlobPriv::Flatten(*blob, fWriteBuffer);
107*c8dee2aaSAndroid Build Coastguard Worker fBlobCount++;
108*c8dee2aaSAndroid Build Coastguard Worker }
109*c8dee2aaSAndroid Build Coastguard Worker }
110*c8dee2aaSAndroid Build Coastguard Worker
dump(SkWStream * dst) const111*c8dee2aaSAndroid Build Coastguard Worker void SkTextBlobTrace::Capture::dump(SkWStream* dst) const {
112*c8dee2aaSAndroid Build Coastguard Worker SkTLazy<SkFILEWStream> fileStream;
113*c8dee2aaSAndroid Build Coastguard Worker if (!dst) {
114*c8dee2aaSAndroid Build Coastguard Worker uint32_t id = SkChecksum::Mix(reinterpret_cast<uintptr_t>(this));
115*c8dee2aaSAndroid Build Coastguard Worker SkString f = SkStringPrintf("diff-canvas-%08x-%04zu.trace", id, fBlobCount);
116*c8dee2aaSAndroid Build Coastguard Worker dst = fileStream.init(f.c_str());
117*c8dee2aaSAndroid Build Coastguard Worker if (!fileStream->isValid()) {
118*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Error opening '%s'.\n", f.c_str());
119*c8dee2aaSAndroid Build Coastguard Worker return;
120*c8dee2aaSAndroid Build Coastguard Worker }
121*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Saving trace to '%s'.\n", f.c_str());
122*c8dee2aaSAndroid Build Coastguard Worker }
123*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(dst);
124*c8dee2aaSAndroid Build Coastguard Worker int count = fTypefaceSet->count();
125*c8dee2aaSAndroid Build Coastguard Worker dst->write32(count);
126*c8dee2aaSAndroid Build Coastguard Worker SkPtrSet::Iter iter(*fTypefaceSet);
127*c8dee2aaSAndroid Build Coastguard Worker while (void* ptr = iter.next()) {
128*c8dee2aaSAndroid Build Coastguard Worker ((const SkTypeface*)ptr)->serialize(dst, SkTypeface::SerializeBehavior::kDoIncludeData);
129*c8dee2aaSAndroid Build Coastguard Worker }
130*c8dee2aaSAndroid Build Coastguard Worker dst->write32(fWriteBuffer.bytesWritten());
131*c8dee2aaSAndroid Build Coastguard Worker fWriteBuffer.writeToStream(dst);
132*c8dee2aaSAndroid Build Coastguard Worker }
133