Home | History | Annotate | Download | only in unittest
      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