1 /* 2 * Copyright (C) 2018 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 "FontUtils.h" 18 19 #include <gtest/gtest.h> 20 21 namespace minikin { 22 namespace { 23 24 constexpr uint32_t MakeTag(char c1, char c2, char c3, char c4) { 25 return ((uint32_t)c1 << 24) | ((uint32_t)c2 << 16) | ((uint32_t)c3 << 8) | (uint32_t)c4; 26 } 27 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 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 static uint32_t floatToFixed(float x) { 43 return (uint32_t)(x * 65536); 44 } 45 46 struct Fvar { 47 Fvar(uint32_t tag, float minValue, float defaultValue, float maxValue) 48 : tag(tag), minValue(minValue), defaultValue(defaultValue), maxValue(maxValue) {} 49 50 uint32_t tag; 51 float minValue; 52 float defaultValue; 53 float maxValue; 54 }; 55 56 // Returns valid fvar table contents. No InstanceRecord are filled. 57 static std::vector<uint8_t> buildFvarTable(const std::vector<Fvar>& fvars) { 58 const uint32_t HEADER_SIZE = 0x10; 59 const uint32_t AXIS_RECORD_SIZE = 0x14; 60 std::vector<uint8_t> out(HEADER_SIZE + fvars.size() * AXIS_RECORD_SIZE); 61 size_t head = writeU16(1, out.data(), 0); // major version 62 head = writeU16(0, out.data(), head); // minor version 63 head = writeU16(HEADER_SIZE, out.data(), head); // axes array offset 64 head = writeU16(2, out.data(), head); // reserved 65 head = writeU16(fvars.size(), out.data(), head); // count of axes 66 head = writeU16(AXIS_RECORD_SIZE, out.data(), head); // size of variaiton axis record 67 head = writeU16(0, out.data(), head); // number of instance record count 68 head = writeU16(0, out.data(), head); // instance record size 69 70 for (const Fvar& fvar : fvars) { 71 head = writeU32(fvar.tag, out.data(), head); 72 head = writeU32(floatToFixed(fvar.minValue), out.data(), head); 73 head = writeU32(floatToFixed(fvar.defaultValue), out.data(), head); 74 head = writeU32(floatToFixed(fvar.maxValue), out.data(), head); 75 head = writeU16(0, out.data(), head); // flags 76 head = writeU16(0, out.data(), head); // axis name ID 77 } 78 79 return out; 80 } 81 82 TEST(FontUtilsTest, analyzeAxes_tagCount) { 83 std::vector<uint8_t> fvarTable = buildFvarTable({ 84 Fvar(MakeTag('w', 'd', 't', 'h'), 0.0f, 1.0f, 2.0f), 85 Fvar(MakeTag('w', 'g', 'h', 't'), 0.0f, 1.0f, 2.0f), 86 }); 87 88 std::unordered_set<uint32_t> axes; 89 ASSERT_TRUE(analyzeAxes(fvarTable.data(), fvarTable.size(), &axes)); 90 ASSERT_EQ(2u, axes.size()); 91 EXPECT_EQ(1u, axes.count(MakeTag('w', 'd', 't', 'h'))); 92 EXPECT_EQ(1u, axes.count(MakeTag('w', 'g', 'h', 't'))); 93 EXPECT_EQ(0u, axes.count(MakeTag('s', 'l', 'n', 't'))); 94 } 95 96 TEST(FontUtilsTest, analyzeAxes_emptyBuffer) { 97 std::vector<uint8_t> fvarTable; 98 std::unordered_set<uint32_t> axes; 99 ASSERT_FALSE(analyzeAxes(fvarTable.data(), fvarTable.size(), &axes)); 100 } 101 102 TEST(FontUtilsTest, analyzeAxes_invalidTableSize) { 103 std::vector<uint8_t> fvarTable = buildFvarTable({ 104 Fvar(MakeTag('w', 'd', 't', 'h'), 0.0f, 1.0f, 2.0f), 105 Fvar(MakeTag('w', 'g', 'h', 't'), 0.0f, 1.0f, 2.0f), 106 }); 107 108 fvarTable.resize(1000); 109 writeU16(50, fvarTable.data(), 8); // Set axisCount = 50 110 111 std::unordered_set<uint32_t> axes; 112 ASSERT_FALSE(analyzeAxes(fvarTable.data(), fvarTable.size(), &axes)); 113 } 114 115 } // namespace 116 } // namespace minikin 117