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/SkFont.h"
9 #include "include/core/SkFontTypes.h"
10 #include "include/core/SkRefCnt.h"
11 #include "include/core/SkTypeface.h"
12 #include "include/core/SkTypes.h"
13 #include "include/private/base/SkTo.h"
14 #include "src/base/SkAutoMalloc.h"
15 #include "src/core/SkFontPriv.h"
16 #include "src/core/SkPtrRecorder.h"
17 #include "src/core/SkReadBuffer.h"
18 #include "src/core/SkWriteBuffer.h"
19 #include "tests/Test.h"
20 #include "tools/ToolUtils.h"
21 #include "tools/fonts/FontToolUtils.h"
22
23 #include <cstddef>
24
serialize_deserialize(const SkFont & font,skiatest::Reporter * reporter)25 static SkFont serialize_deserialize(const SkFont& font, skiatest::Reporter* reporter) {
26 sk_sp<SkRefCntSet> typefaces = sk_make_sp<SkRefCntSet>();
27 SkBinaryWriteBuffer wb({});
28 wb.setTypefaceRecorder(typefaces);
29
30 SkFontPriv::Flatten(font, wb);
31 size_t size = wb.bytesWritten();
32 SkAutoMalloc storage(size);
33 wb.writeToMemory(storage.get());
34
35 int count = typefaces->count();
36 SkASSERT((!font.getTypeface() && count == 0) ||
37 ( font.getTypeface() && count == 1));
38 if (count) {
39 SkTypeface* typeface;
40 typefaces->copyToArray((SkRefCnt**)&typeface);
41 SkASSERT(typeface == font.getTypeface());
42 }
43
44 SkReadBuffer rb(storage.get(), size);
45 sk_sp<SkTypeface> cloneTypeface = font.refTypeface();
46 if (count) {
47 rb.setTypefaceArray(&cloneTypeface, 1);
48 }
49 SkFont clone;
50 REPORTER_ASSERT(reporter, SkFontPriv::Unflatten(&clone, rb));
51 return clone;
52 }
53
54 enum {
55 kForceAutoHinting = 1 << 0,
56 kEmbeddedBitmaps = 1 << 1,
57 kSubpixel = 1 << 2,
58 kLinearMetrics = 1 << 3,
59 kEmbolden = 1 << 4,
60 kBaselineSnap = 1 << 5,
61
62 kAllBits = 0x3F,
63 };
64
apply_flags(SkFont * font,unsigned flags)65 static void apply_flags(SkFont* font, unsigned flags) {
66 font->setForceAutoHinting(SkToBool(flags & kForceAutoHinting));
67 font->setEmbeddedBitmaps( SkToBool(flags & kEmbeddedBitmaps));
68 font->setSubpixel( SkToBool(flags & kSubpixel));
69 font->setLinearMetrics( SkToBool(flags & kLinearMetrics));
70 font->setEmbolden( SkToBool(flags & kEmbolden));
71 font->setBaselineSnap( SkToBool(flags & kBaselineSnap));
72 }
73
DEF_TEST(Font_flatten,reporter)74 DEF_TEST(Font_flatten, reporter) {
75 const float sizes[] = {0, 0.001f, 1, 10, 10.001f, 100000.01f};
76 const float scales[] = {-5, 0, 1, 5};
77 const float skews[] = {-5, 0, 5};
78 const SkFont::Edging edges[] = {
79 SkFont::Edging::kAlias, SkFont::Edging::kSubpixelAntiAlias
80 };
81 const SkFontHinting hints[] = {
82 SkFontHinting::kNone, SkFontHinting::kFull
83 };
84 const unsigned int flags[] = {
85 kForceAutoHinting, kEmbeddedBitmaps, kSubpixel, kLinearMetrics, kEmbolden, kBaselineSnap,
86 kAllBits,
87 };
88 const sk_sp<SkTypeface> typefaces[] = {
89 nullptr, ToolUtils::SampleUserTypeface()
90 };
91
92 SkFont font;
93 for (float size : sizes) {
94 font.setSize(size);
95 for (float scale : scales) {
96 font.setScaleX(scale);
97 for (float skew : skews) {
98 font.setSkewX(skew);
99 for (auto edge : edges) {
100 font.setEdging(edge);
101 for (auto hint : hints) {
102 font.setHinting(hint);
103 for (auto flag : flags) {
104 apply_flags(&font, flag);
105 for (const sk_sp<SkTypeface>& typeface : typefaces) {
106 font.setTypeface(typeface);
107 SkFont clone = serialize_deserialize(font, reporter);
108 REPORTER_ASSERT(reporter, font == clone);
109 }
110 }
111 }
112 }
113 }
114 }
115 }
116 }
117