1 /*
2 * Copyright 2022 Google LLC
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 "src/core/SkGlyph.h"
9 #include "src/gpu/GrResourceProvider.h"
10 #include "src/gpu/text/GrGlyphVector.h"
11
12 #include "src/core/SkGlyphBuffer.h"
13 #include "src/core/SkReadBuffer.h"
14 #include "src/core/SkStrikeCache.h"
15 #include "src/core/SkStrikeSpec.h"
16 #include "src/core/SkWriteBuffer.h"
17 #include "src/gpu/GrSubRunAllocator.h"
18 #include "tests/Test.h"
19
20 class TestingPeer {
21 public:
GetDescriptor(const GrGlyphVector & v)22 static const SkDescriptor& GetDescriptor(const GrGlyphVector& v) {
23 return v.fStrike->getDescriptor();
24 }
GetGlyphs(const GrGlyphVector & v)25 static SkSpan<GrGlyphVector::Variant> GetGlyphs(const GrGlyphVector& v) {
26 return v.fGlyphs;
27 }
28 };
29
DEF_TEST(GrGlyphVector_Serialization,r)30 DEF_TEST(GrGlyphVector_Serialization, r) {
31 SkFont font;
32 auto [strikeSpec, _] = SkStrikeSpec::MakeCanonicalized(font);
33
34 GrSubRunAllocator alloc;
35
36 SkBulkGlyphMetricsAndImages glyphFinder{strikeSpec};
37 const int N = 10;
38 SkGlyphVariant* glyphs = alloc.makePODArray<SkGlyphVariant>(N);
39 for (int i = 0; i < N; i++) {
40 glyphs[i] = glyphFinder.glyph(SkPackedGlyphID(SkTo<SkGlyphID>(i + 1)));
41 }
42
43 GrGlyphVector src = GrGlyphVector::Make(
44 strikeSpec.findOrCreateStrike(), SkMakeSpan(glyphs, N), &alloc);
45
46 SkBinaryWriteBuffer wBuffer;
47 src.flatten(wBuffer);
48
49 auto data = wBuffer.snapshotAsData();
50 SkReadBuffer rBuffer{data->data(), data->size()};
51 auto dst = GrGlyphVector::MakeFromBuffer(rBuffer, &alloc);
52 REPORTER_ASSERT(r, dst.has_value());
53 REPORTER_ASSERT(r, TestingPeer::GetDescriptor(src) == TestingPeer::GetDescriptor(*dst));
54
55 auto srcGlyphs = TestingPeer::GetGlyphs(src);
56 auto dstGlyphs = TestingPeer::GetGlyphs(*dst);
57 for (auto [srcGlyphID, dstGlyphID] : SkMakeZip(srcGlyphs, dstGlyphs)) {
58 REPORTER_ASSERT(r, srcGlyphID.packedGlyphID == dstGlyphID.packedGlyphID);
59 }
60 }
61
DEF_TEST(GrGlyphVector_BadLengths,r)62 DEF_TEST(GrGlyphVector_BadLengths, r) {
63 {
64 SkFont font;
65 auto [strikeSpec, _] = SkStrikeSpec::MakeCanonicalized(font);
66
67 // Make broken stream by hand - zero length
68 SkBinaryWriteBuffer wBuffer;
69 strikeSpec.descriptor().flatten(wBuffer);
70 wBuffer.write32(0); // length
71 auto data = wBuffer.snapshotAsData();
72 SkReadBuffer rBuffer{data->data(), data->size()};
73 GrSubRunAllocator alloc;
74 auto dst = GrGlyphVector::MakeFromBuffer(rBuffer, &alloc);
75 REPORTER_ASSERT(r, !dst.has_value());
76 }
77
78 {
79 SkFont font;
80 auto [strikeSpec, _] = SkStrikeSpec::MakeCanonicalized(font);
81
82 // Make broken stream by hand - stream is too short
83 SkBinaryWriteBuffer wBuffer;
84 strikeSpec.descriptor().flatten(wBuffer);
85 wBuffer.write32(5); // length
86 wBuffer.writeUInt(12); // random data
87 wBuffer.writeUInt(12); // random data
88 wBuffer.writeUInt(12); // random data
89 auto data = wBuffer.snapshotAsData();
90 SkReadBuffer rBuffer{data->data(), data->size()};
91 GrSubRunAllocator alloc;
92 auto dst = GrGlyphVector::MakeFromBuffer(rBuffer, &alloc);
93 REPORTER_ASSERT(r, !dst.has_value());
94 }
95
96 {
97 SkFont font;
98 auto [strikeSpec, _] = SkStrikeSpec::MakeCanonicalized(font);
99
100 // Make broken stream by hand - length out of range of safe calculations
101 SkBinaryWriteBuffer wBuffer;
102 strikeSpec.descriptor().flatten(wBuffer);
103 wBuffer.write32(INT_MAX - 10); // length
104 wBuffer.writeUInt(12); // random data
105 wBuffer.writeUInt(12); // random data
106 wBuffer.writeUInt(12); // random data
107 auto data = wBuffer.snapshotAsData();
108 SkReadBuffer rBuffer{data->data(), data->size()};
109 GrSubRunAllocator alloc;
110 auto dst = GrGlyphVector::MakeFromBuffer(rBuffer, &alloc);
111 REPORTER_ASSERT(r, !dst.has_value());
112 }
113 }
114