xref: /aosp_15_r20/external/skia/tools/text/SkTextBlobTrace.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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