• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "minikin/FontFileParser.h"
18 
19 #include <gtest/gtest.h>
20 
21 #include "FontTestUtils.h"
22 #include "FreeTypeMinikinFontForTest.h"
23 #include "PathUtils.h"
24 
25 namespace minikin {
26 namespace {
27 
writeU16(uint16_t x,uint8_t * out,size_t offset)28 static size_t writeU16(uint16_t x, uint8_t* out, size_t offset) {
29     out[offset] = x >> 8;
30     out[offset + 1] = x;
31     return offset + 2;
32 }
33 
writeU32(uint32_t x,uint8_t * out,size_t offset)34 static size_t writeU32(uint32_t x, uint8_t* out, size_t offset) {
35     out[offset] = x >> 24;
36     out[offset + 1] = x >> 16;
37     out[offset + 2] = x >> 8;
38     out[offset + 3] = x;
39     return offset + 4;
40 }
41 
42 class TestableFontFileParser : public FontFileParser {
43 public:
44     using FontFileParser::analyzeFontRevision;
45     using FontFileParser::checkPSName;
46 };
47 
48 // Returns valid head table contents.
buildHeadTable(uint32_t fontRevision)49 static std::vector<uint8_t> buildHeadTable(uint32_t fontRevision) {
50     std::vector<uint8_t> out(46);
51     size_t head = writeU16(1, out.data(), 0);         // major version
52     head = writeU16(0, out.data(), head);             // minor version
53     head = writeU32(fontRevision, out.data(), head);  // fontRevision
54     head = writeU32(0xB1B0AFBA, out.data(), head);    // checksum. (random value)
55     head = writeU32(0x5F0F3CF5, out.data(), head);    // magicNumber
56     head = writeU16(0, out.data(), head);             // flasgs
57     head = writeU16(1024, out.data(), head);          // unitsPerEm
58     head = writeU32(123457890, out.data(), head);     // created (random value)
59     head = writeU32(123457890, out.data(), head);     // modified (random value)
60     head = writeU16(0, out.data(), head);             // xMin
61     head = writeU16(100, out.data(), head);           // yMin
62     head = writeU16(1024, out.data(), head);          // xMax
63     head = writeU16(2048, out.data(), head);          // yMax
64     head = writeU16(0, out.data(), head);             // macStyle
65     head = writeU16(10, out.data(), head);            // lowestRecPPEM
66     head = writeU16(1, out.data(), head);             // fontDirectionHint
67     head = writeU16(1, out.data(), head);             // indexToLocFormat
68     head = writeU16(0, out.data(), head);             // glyphDataFormat;
69 
70     return out;
71 }
72 
TEST(FontFileParserTest,analyzeFontRevision)73 TEST(FontFileParserTest, analyzeFontRevision) {
74     uint32_t rev = 0x12345678;
75     std::vector<uint8_t> head = buildHeadTable(rev);
76 
77     uint32_t out = 0;
78     EXPECT_TRUE(TestableFontFileParser::analyzeFontRevision(head.data(), head.size(), &out));
79     EXPECT_EQ(rev, out);
80 }
81 
TEST(FontFileParserTest,headInvalidLength)82 TEST(FontFileParserTest, headInvalidLength) {
83     uint32_t rev = 0x12345678;
84     std::vector<uint8_t> head = buildHeadTable(rev);
85 
86     uint32_t out = 0;
87     EXPECT_FALSE(TestableFontFileParser::analyzeFontRevision(head.data(), 6, &out));
88 }
89 
TEST(FontFileParserTest,parseFontForRev)90 TEST(FontFileParserTest, parseFontForRev) {
91     auto minikinFont = std::make_shared<FreeTypeMinikinFontForTest>(getTestFontPath("Ascii.ttf"));
92     auto parser = FontFileParser(minikinFont->GetFontData(), minikinFont->GetFontSize(), 0);
93 
94     auto revision = parser.getFontRevision();
95     EXPECT_TRUE(revision.has_value());
96     EXPECT_EQ(0x00010000u, revision.value());
97 }
98 
TEST(FontFileParser,checkPSName)99 TEST(FontFileParser, checkPSName) {
100     EXPECT_TRUE(TestableFontFileParser::checkPSName("Roboto-Regular"));
101     EXPECT_TRUE(TestableFontFileParser::checkPSName("NotoColorEmoji"));
102 
103     // Space character is not allowed.
104     EXPECT_FALSE(TestableFontFileParser::checkPSName("Roboto Regular"));
105     EXPECT_FALSE(TestableFontFileParser::checkPSName("Noto Color Emoji"));
106 
107     // parens are not not allowed.
108     EXPECT_FALSE(TestableFontFileParser::checkPSName("Roboto (Regular)"));
109     EXPECT_FALSE(TestableFontFileParser::checkPSName("Noto <Color> {Emoji}"));
110 
111     // control characters are not allowed
112     EXPECT_FALSE(TestableFontFileParser::checkPSName("Roboto-Regular\b"));
113     EXPECT_FALSE(TestableFontFileParser::checkPSName("NotoColorEmoji\t"));
114 
115     // Up to 63 character is allowed.
116     EXPECT_FALSE(TestableFontFileParser::checkPSName(std::string(64, 'a')));
117 
118     // Only printable ASCII is allowed.
119     EXPECT_FALSE(TestableFontFileParser::checkPSName("ろぼとふぉんと"));
120 }
121 
TEST(FontFileParserTest,parseFontForPSName)122 TEST(FontFileParserTest, parseFontForPSName) {
123     auto minikinFont = std::make_shared<FreeTypeMinikinFontForTest>(getTestFontPath("Ascii.ttf"));
124     auto parser = FontFileParser(minikinFont->GetFontData(), minikinFont->GetFontSize(), 0);
125 
126     auto psName = parser.getPostScriptName();
127     EXPECT_TRUE(psName.has_value());
128     EXPECT_EQ("SampleFont-Regular", psName.value());
129 }
130 
131 }  // namespace
132 }  // namespace minikin
133