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