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 "minikin/LayoutCore.h"
     18 
     19 #include <gtest/gtest.h>
     20 
     21 #include "minikin/FontCollection.h"
     22 #include "minikin/LayoutPieces.h"
     23 
     24 #include "FontTestUtils.h"
     25 #include "UnicodeUtils.h"
     26 
     27 namespace minikin {
     28 namespace {
     29 
     30 static LayoutPiece buildLayout(const std::string& text, const MinikinPaint& paint) {
     31     auto utf16 = utf8ToUtf16(text);
     32     return LayoutPiece(utf16, Range(0, utf16.size()), false /* rtl */, paint,
     33                        StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT);
     34 }
     35 
     36 static LayoutPiece buildLayout(const std::string& text, const std::vector<std::string>& fonts) {
     37     std::vector<std::shared_ptr<FontFamily>> families;
     38     for (const auto& fontPath : fonts) {
     39         families.push_back(buildFontFamily(fontPath));
     40     }
     41     auto fc = std::make_shared<FontCollection>(families);
     42     MinikinPaint paint(fc);
     43     paint.size = 10.0f;  // make 1em = 10px
     44     return buildLayout(text, paint);
     45 }
     46 
     47 static LayoutPiece buildLayout(const std::string& text, const std::vector<std::string>& fonts,
     48                                const std::string fontFeaturesSettings) {
     49     std::vector<std::shared_ptr<FontFamily>> families;
     50     for (const auto& fontPath : fonts) {
     51         families.push_back(buildFontFamily(fontPath));
     52     }
     53     auto fc = std::make_shared<FontCollection>(families);
     54     MinikinPaint paint(fc);
     55     paint.size = 10.0f;  // make 1em = 10px
     56     paint.fontFeatureSettings = fontFeaturesSettings;
     57     return buildLayout(text, paint);
     58 }
     59 
     60 TEST(LayoutPieceTest, doLayoutTest) {
     61     // The LayoutTestFont.ttf has following coverage, extent, width and bbox.
     62     // Ascender: 10em, Descender: -2em
     63     // U+0020: 10em, (0, 0) - (10, 10)
     64     // U+002E (.): 10em, (0, 0) - (10, 10)
     65     // U+0043 (C): 100em, (0, 0) - (100, 100)
     66     // U+0049 (I): 1em, (0, 0) - (1, 1)
     67     // U+004C (L): 50em, (0, 0) - (50, 50)
     68     // U+0056 (V): 5em, (0, 0) - (5, 5)
     69     // U+0058 (X): 10em, (0, 0) - (10, 10)
     70     // U+005F (_): 0em, (0, 0) - (0, 0)
     71     // U+FFFD (invalid surrogate will be replaced to this): 7em, (0, 0) - (7, 7)
     72     // U+10331 (\uD800\uDF31): 10em, (0, 0) - (10, 10)
     73     {
     74         auto layout = buildLayout("I", {"LayoutTestFont.ttf"});
     75         EXPECT_EQ(1u, layout.glyphCount());
     76         EXPECT_EQ(Point(0, 0), layout.pointAt(0));
     77         EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), layout.bounds());
     78         EXPECT_EQ(MinikinExtent(-100.0f, 20.0f), layout.extent());
     79         EXPECT_EQ(1u, layout.fonts().size());
     80         EXPECT_TRUE(layout.fontAt(0).font);
     81         EXPECT_EQ(1u, layout.advances().size());
     82         EXPECT_EQ(10.0f, layout.advances()[0]);
     83         EXPECT_EQ(10.0f, layout.advance());
     84     }
     85     {
     86         auto layout = buildLayout("II", {"LayoutTestFont.ttf"});
     87         EXPECT_EQ(2u, layout.glyphCount());
     88         EXPECT_EQ(Point(0, 0), layout.pointAt(0));
     89         EXPECT_EQ(Point(10.0f, 0), layout.pointAt(1));
     90         EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), layout.bounds());
     91         EXPECT_EQ(MinikinExtent(-100.0f, 20.0f), layout.extent());
     92         EXPECT_EQ(1u, layout.fonts().size());
     93         EXPECT_TRUE(layout.fontAt(0).font);
     94         EXPECT_TRUE(layout.fontAt(1).font);
     95         EXPECT_EQ(layout.fontAt(0), layout.fontAt(1));
     96         EXPECT_EQ(2u, layout.advances().size());
     97         EXPECT_EQ(10.0f, layout.advances()[0]);
     98         EXPECT_EQ(10.0f, layout.advances()[1]);
     99         EXPECT_EQ(20.0f, layout.advance());
    100     }
    101     {
    102         auto layout = buildLayout("IV", {"LayoutTestFont.ttf"});
    103         EXPECT_EQ(2u, layout.glyphCount());
    104         EXPECT_EQ(Point(0, 0), layout.pointAt(0));
    105         EXPECT_EQ(Point(10.0f, 0), layout.pointAt(1));
    106         EXPECT_EQ(MinikinRect(0.0f, 10.0f, 60.0f, 0.0f), layout.bounds());
    107         EXPECT_EQ(MinikinExtent(-100.0f, 20.0f), layout.extent());
    108         EXPECT_EQ(1u, layout.fonts().size());
    109         EXPECT_TRUE(layout.fontAt(0).font);
    110         EXPECT_TRUE(layout.fontAt(1).font);
    111         EXPECT_EQ(layout.fontAt(0), layout.fontAt(1));
    112         EXPECT_EQ(2u, layout.advances().size());
    113         EXPECT_EQ(10.0f, layout.advances()[0]);
    114         EXPECT_EQ(50.0f, layout.advances()[1]);
    115         EXPECT_EQ(60.0f, layout.advance());
    116     }
    117 }
    118 
    119 TEST(LayoutPieceTest, doLayoutTest_MultiFont) {
    120     // See doLayoutTest for the details of LayoutTestFont.ttf
    121     // The Hiragana.ttf has following coverage, extent, width and bbox.
    122     // Ascender: 16em, Descender: -4em
    123     // U+3042: 2em, (0, 0) - (2, 2)
    124     // U+3044: 2em, (0, 0) - (2, 2)
    125     // U+3046: 2em, (0, 0) - (2, 2)
    126     // U+3048: 2em, (0, 0) - (2, 2)
    127     // U+304A: 2em, (0, 0) - (2, 2)
    128     {
    129         auto layout = buildLayout("I\u3042", {"LayoutTestFont.ttf", "Hiragana.ttf"});
    130         EXPECT_EQ(2u, layout.glyphCount());
    131         EXPECT_EQ(Point(0, 0), layout.pointAt(0));
    132         EXPECT_EQ(Point(10.0f, 0), layout.pointAt(1));
    133         EXPECT_EQ(MinikinRect(0.0f, 10.0f, 30.0f, 0.0f), layout.bounds());
    134         EXPECT_EQ(MinikinExtent(-160.0f, 40.0f), layout.extent());
    135         EXPECT_EQ(2u, layout.fonts().size());
    136         EXPECT_TRUE(layout.fontAt(0).font);
    137         EXPECT_TRUE(layout.fontAt(1).font);
    138         EXPECT_NE(layout.fontAt(0), layout.fontAt(1));
    139         EXPECT_EQ(2u, layout.advances().size());
    140         EXPECT_EQ(10.0f, layout.advances()[0]);
    141         EXPECT_EQ(20.0f, layout.advances()[1]);
    142         EXPECT_EQ(30.0f, layout.advance());
    143     }
    144     {
    145         auto layout = buildLayout("\u3042I", {"LayoutTestFont.ttf", "Hiragana.ttf"});
    146         EXPECT_EQ(2u, layout.glyphCount());
    147         EXPECT_EQ(Point(0, 0), layout.pointAt(0));
    148         EXPECT_EQ(Point(20.0f, 0), layout.pointAt(1));
    149         EXPECT_EQ(MinikinRect(0.0f, 10.0f, 30.0f, 0.0f), layout.bounds());
    150         EXPECT_EQ(MinikinExtent(-160.0f, 40.0f), layout.extent());
    151         EXPECT_EQ(2u, layout.fonts().size());
    152         EXPECT_TRUE(layout.fontAt(0).font);
    153         EXPECT_TRUE(layout.fontAt(1).font);
    154         EXPECT_NE(layout.fontAt(0), layout.fontAt(1));
    155         EXPECT_EQ(2u, layout.advances().size());
    156         EXPECT_EQ(20.0f, layout.advances()[0]);
    157         EXPECT_EQ(10.0f, layout.advances()[1]);
    158         EXPECT_EQ(30.0f, layout.advance());
    159     }
    160 }
    161 
    162 TEST(LayoutPieceTest, doLayoutTest_Ligature) {
    163     // Ligature.ttf support all ASCII characters.
    164     // Ascender: 8em, Descender: -2em
    165     // U+0020..U+007E: 1em, (0, 0) - (1, 1)
    166     // Also this has ligature entry for fi as "ccmp" feature, ff as "liga" feature.
    167     {
    168         auto layout = buildLayout("fi", {"Ligature.ttf"});
    169         EXPECT_EQ(1u, layout.glyphCount());
    170         EXPECT_EQ(Point(0, 0), layout.pointAt(0));
    171         EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), layout.bounds());
    172         EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), layout.extent());
    173         EXPECT_EQ(1u, layout.fonts().size());
    174         EXPECT_TRUE(layout.fontAt(0).font);
    175         EXPECT_EQ(2u, layout.advances().size());
    176         EXPECT_EQ(10.0f, layout.advances()[0]);
    177         EXPECT_EQ(0.0f, layout.advances()[1]);  // Ligature assigns all width to the first char.
    178         EXPECT_EQ(10.0f, layout.advance());
    179     }
    180     {
    181         auto layout = buildLayout("ff", {"Ligature.ttf"});
    182         EXPECT_EQ(1u, layout.glyphCount());
    183         EXPECT_EQ(Point(0, 0), layout.pointAt(0));
    184         EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), layout.bounds());
    185         EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), layout.extent());
    186         EXPECT_EQ(1u, layout.fonts().size());
    187         EXPECT_TRUE(layout.fontAt(0).font);
    188         EXPECT_EQ(2u, layout.advances().size());
    189         EXPECT_EQ(10.0f, layout.advances()[0]);
    190         EXPECT_EQ(0.0f, layout.advances()[1]);  // Ligature assigns all width to the first char.
    191         EXPECT_EQ(10.0f, layout.advance());
    192     }
    193     {
    194         auto layout = buildLayout("fi", {"Ligature.ttf"}, "'liga' off");
    195         EXPECT_EQ(1u, layout.glyphCount());
    196         EXPECT_EQ(Point(0, 0), layout.pointAt(0));
    197         EXPECT_EQ(MinikinRect(0.0f, 10.0f, 10.0f, 0.0f), layout.bounds());
    198         EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), layout.extent());
    199         EXPECT_EQ(1u, layout.fonts().size());
    200         EXPECT_TRUE(layout.fontAt(0).font);
    201         EXPECT_EQ(2u, layout.advances().size());
    202         EXPECT_EQ(10.0f, layout.advances()[0]);
    203         EXPECT_EQ(0.0f, layout.advances()[1]);  // Ligature assigns all width to the first char.
    204         EXPECT_EQ(10.0f, layout.advance());
    205     }
    206     {
    207         auto layout = buildLayout("ff", {"Ligature.ttf"}, "'liga' off");
    208         EXPECT_EQ(2u, layout.glyphCount());
    209         EXPECT_EQ(Point(0, 0), layout.pointAt(0));
    210         EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), layout.bounds());
    211         EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), layout.extent());
    212         EXPECT_EQ(1u, layout.fonts().size());
    213         EXPECT_TRUE(layout.fontAt(0).font);
    214         EXPECT_TRUE(layout.fontAt(1).font);
    215         EXPECT_EQ(2u, layout.advances().size());
    216         EXPECT_EQ(layout.fontAt(0), layout.fontAt(1));
    217         EXPECT_EQ(10.0f, layout.advances()[0]);
    218         EXPECT_EQ(10.0f, layout.advances()[1]);
    219         EXPECT_EQ(20.0f, layout.advance());
    220     }
    221     {
    222         auto layout = buildLayout("fii", {"Ligature.ttf"});
    223         EXPECT_EQ(2u, layout.glyphCount());
    224         EXPECT_EQ(Point(0, 0), layout.pointAt(0));
    225         EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), layout.bounds());
    226         EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), layout.extent());
    227         EXPECT_EQ(1u, layout.fonts().size());
    228         EXPECT_TRUE(layout.fontAt(0).font);
    229         EXPECT_TRUE(layout.fontAt(1).font);
    230         EXPECT_EQ(layout.fontAt(0), layout.fontAt(1));
    231         EXPECT_EQ(3u, layout.advances().size());
    232         EXPECT_EQ(10.0f, layout.advances()[0]);
    233         EXPECT_EQ(0.0f, layout.advances()[1]);  // Ligature assigns all width to the first char.
    234         EXPECT_EQ(10.0f, layout.advances()[2]);
    235         EXPECT_EQ(20.0f, layout.advance());
    236     }
    237     {
    238         auto layout = buildLayout("if", {"Ligature.ttf"});
    239         EXPECT_EQ(2u, layout.glyphCount());
    240         EXPECT_EQ(Point(0, 0), layout.pointAt(0));
    241         EXPECT_EQ(MinikinRect(0.0f, 10.0f, 20.0f, 0.0f), layout.bounds());
    242         EXPECT_EQ(MinikinExtent(-80.0f, 20.0f), layout.extent());
    243         EXPECT_EQ(1u, layout.fonts().size());
    244         EXPECT_TRUE(layout.fontAt(0).font);
    245         EXPECT_TRUE(layout.fontAt(1).font);
    246         EXPECT_EQ(layout.fontAt(0), layout.fontAt(1));
    247         EXPECT_EQ(2u, layout.advances().size());
    248         EXPECT_EQ(10.0f, layout.advances()[0]);
    249         EXPECT_EQ(10.0f, layout.advances()[1]);
    250         EXPECT_EQ(20.0f, layout.advance());
    251     }
    252 }
    253 
    254 }  // namespace
    255 }  // namespace minikin
    256