1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "config.h"
6#include "platform/fonts/GlyphPageTreeNode.h"
7
8#include "platform/fonts/SegmentedFontData.h"
9#include "platform/fonts/SimpleFontData.h"
10#include <gtest/gtest.h>
11
12namespace WebCore {
13
14class TestCustomFontData : public CustomFontData {
15public:
16    static PassRefPtr<TestCustomFontData> create() { return adoptRef(new TestCustomFontData()); }
17private:
18    TestCustomFontData() { }
19    virtual bool isLoadingFallback() const OVERRIDE { return true; }
20};
21
22class TestSimpleFontData : public SimpleFontData {
23public:
24    static PassRefPtr<TestSimpleFontData> create(UChar32 from, UChar32 to)
25    {
26        return adoptRef(new TestSimpleFontData(nullptr, from, to));
27    }
28
29    static PassRefPtr<TestSimpleFontData> createUnloaded(UChar32 from, UChar32 to)
30    {
31        return adoptRef(new TestSimpleFontData(TestCustomFontData::create(), from, to));
32    }
33
34private:
35    TestSimpleFontData(PassRefPtr<CustomFontData> customData, UChar32 from, UChar32 to)
36        : SimpleFontData(customData, 10, false, false)
37        , m_from(from)
38        , m_to(to)
39    {
40    }
41
42    bool fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const OVERRIDE
43    {
44        const Glyph kGlyph = 1;
45        String bufferString(buffer, bufferLength);
46        unsigned bufferIndex = 0;
47        bool hasGlyphs = false;
48        for (unsigned i = 0; i < length; i++) {
49            UChar32 c = bufferString.characterStartingAt(bufferIndex);
50            bufferIndex += U16_LENGTH(c);
51            if (m_from <= c && c <= m_to) {
52                pageToFill->setGlyphDataForIndex(offset + i, kGlyph, this);
53                hasGlyphs = true;
54            }
55        }
56        return hasGlyphs;
57    }
58
59    UChar32 m_from;
60    UChar32 m_to;
61};
62
63TEST(GlyphPageTreeNode, rootChild)
64{
65    const unsigned kPageNumber = 0;
66    size_t pageCountBeforeTest = GlyphPageTreeNode::treeGlyphPageCount();
67    {
68        RefPtr<TestSimpleFontData> data = TestSimpleFontData::create('a', 'z');
69        GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(data.get(), kPageNumber);
70        EXPECT_EQ(pageCountBeforeTest + 1, GlyphPageTreeNode::treeGlyphPageCount());
71        EXPECT_TRUE(node->page()->glyphAt('a'));
72        EXPECT_FALSE(node->page()->glyphAt('A'));
73        EXPECT_FALSE(node->isSystemFallback());
74        EXPECT_EQ(1u, node->level());
75        EXPECT_EQ(node, node->page()->owner());
76    }
77    EXPECT_EQ(pageCountBeforeTest, GlyphPageTreeNode::treeGlyphPageCount());
78}
79
80TEST(GlyphPageTreeNode, level2)
81{
82    const unsigned kPageNumber = 0;
83    size_t pageCountBeforeTest = GlyphPageTreeNode::treeGlyphPageCount();
84    {
85        RefPtr<TestSimpleFontData> dataAtoC = TestSimpleFontData::create('A', 'C');
86        RefPtr<TestSimpleFontData> dataCtoE = TestSimpleFontData::create('C', 'E');
87        GlyphPageTreeNode* node1 = GlyphPageTreeNode::getRootChild(dataAtoC.get(), kPageNumber);
88        GlyphPageTreeNode* node2 = node1->getChild(dataCtoE.get(), kPageNumber);
89        EXPECT_EQ(pageCountBeforeTest + 3, GlyphPageTreeNode::treeGlyphPageCount());
90
91        EXPECT_EQ(2u, node2->level());
92        EXPECT_EQ(dataAtoC, node2->page()->glyphDataForCharacter('A').fontData);
93        EXPECT_EQ(dataAtoC, node2->page()->glyphDataForCharacter('C').fontData);
94        EXPECT_EQ(dataCtoE, node2->page()->glyphDataForCharacter('E').fontData);
95    }
96    EXPECT_EQ(pageCountBeforeTest, GlyphPageTreeNode::treeGlyphPageCount());
97}
98
99TEST(GlyphPageTreeNode, segmentedData)
100{
101    const unsigned kPageNumber = 0;
102    size_t pageCountBeforeTest = GlyphPageTreeNode::treeGlyphPageCount();
103    {
104        RefPtr<TestSimpleFontData> dataBtoC = TestSimpleFontData::create('B', 'C');
105        RefPtr<TestSimpleFontData> dataCtoE = TestSimpleFontData::create('C', 'E');
106        RefPtr<SegmentedFontData> segmentedData = SegmentedFontData::create();
107        segmentedData->appendRange(FontDataRange('A', 'C', dataBtoC));
108        segmentedData->appendRange(FontDataRange('C', 'D', dataCtoE));
109        GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(segmentedData.get(), kPageNumber);
110
111        EXPECT_EQ(0, node->page()->glyphDataForCharacter('A').fontData);
112        EXPECT_EQ(dataBtoC, node->page()->glyphDataForCharacter('B').fontData);
113        EXPECT_EQ(dataBtoC, node->page()->glyphDataForCharacter('C').fontData);
114        EXPECT_EQ(dataCtoE, node->page()->glyphDataForCharacter('D').fontData);
115        EXPECT_EQ(0, node->page()->glyphDataForCharacter('E').fontData);
116    }
117    EXPECT_EQ(pageCountBeforeTest, GlyphPageTreeNode::treeGlyphPageCount());
118}
119
120TEST(GlyphPageTreeNode, outsideBMP)
121{
122    const unsigned kPageNumber = 0x1f300 / GlyphPage::size;
123    size_t pageCountBeforeTest = GlyphPageTreeNode::treeGlyphPageCount();
124    {
125        RefPtr<TestSimpleFontData> data = TestSimpleFontData::create(0x1f310, 0x1f320);
126        GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(data.get(), kPageNumber);
127        EXPECT_EQ(pageCountBeforeTest + 1, GlyphPageTreeNode::treeGlyphPageCount());
128        EXPECT_FALSE(node->page()->glyphForCharacter(0x1f30f));
129        EXPECT_TRUE(node->page()->glyphForCharacter(0x1f310));
130        EXPECT_TRUE(node->page()->glyphForCharacter(0x1f320));
131        EXPECT_FALSE(node->page()->glyphForCharacter(0x1f321));
132    }
133    EXPECT_EQ(pageCountBeforeTest, GlyphPageTreeNode::treeGlyphPageCount());
134}
135
136TEST(GlyphPageTreeNode, customData)
137{
138    const unsigned kPageNumber = 0;
139    size_t pageCountBeforeTest = GlyphPageTreeNode::treeGlyphPageCount();
140    {
141        RefPtr<TestSimpleFontData> dataAtoC = TestSimpleFontData::createUnloaded('A', 'C');
142        RefPtr<TestSimpleFontData> dataBtoD = TestSimpleFontData::create('B', 'D');
143        RefPtr<TestSimpleFontData> dataCtoE = TestSimpleFontData::createUnloaded('C', 'E');
144        RefPtr<SegmentedFontData> segmentedData = SegmentedFontData::create();
145        segmentedData->appendRange(FontDataRange('A', 'C', dataAtoC));
146        segmentedData->appendRange(FontDataRange('B', 'D', dataBtoD));
147        segmentedData->appendRange(FontDataRange('C', 'E', dataCtoE));
148        GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(segmentedData.get(), kPageNumber);
149
150        EXPECT_EQ(0, node->page()->glyphDataForCharacter('A').fontData);
151        EXPECT_EQ(dataBtoD, node->page()->glyphDataForCharacter('B').fontData);
152        EXPECT_EQ(dataBtoD, node->page()->glyphDataForCharacter('C').fontData);
153        EXPECT_EQ(dataBtoD, node->page()->glyphDataForCharacter('D').fontData);
154        EXPECT_EQ(0, node->page()->glyphDataForCharacter('E').fontData);
155
156        EXPECT_EQ(dataAtoC->customFontData(), node->page()->customFontToLoadAt('A'));
157        EXPECT_EQ(dataAtoC->customFontData(), node->page()->customFontToLoadAt('B'));
158        EXPECT_EQ(dataAtoC->customFontData(), node->page()->customFontToLoadAt('C'));
159        EXPECT_EQ(0, node->page()->customFontToLoadAt('D'));
160        EXPECT_EQ(dataCtoE->customFontData(), node->page()->customFontToLoadAt('E'));
161    }
162    EXPECT_EQ(pageCountBeforeTest, GlyphPageTreeNode::treeGlyphPageCount());
163}
164
165TEST(GlyphPageTreeNode, customDataWithMultiplePages)
166{
167    const unsigned kPageNumber = 0;
168    size_t pageCountBeforeTest = GlyphPageTreeNode::treeGlyphPageCount();
169    {
170        RefPtr<TestSimpleFontData> dataAtoC = TestSimpleFontData::createUnloaded('A', 'C');
171        RefPtr<TestSimpleFontData> dataBtoD = TestSimpleFontData::create('B', 'D');
172        RefPtr<TestSimpleFontData> dataCtoE = TestSimpleFontData::createUnloaded('C', 'E');
173        RefPtr<SegmentedFontData> segmentedData1 = SegmentedFontData::create();
174        RefPtr<SegmentedFontData> segmentedData2 = SegmentedFontData::create();
175        RefPtr<SegmentedFontData> segmentedData3 = SegmentedFontData::create();
176        segmentedData1->appendRange(FontDataRange('A', 'C', dataAtoC));
177        segmentedData2->appendRange(FontDataRange('B', 'D', dataBtoD));
178        segmentedData3->appendRange(FontDataRange('C', 'E', dataCtoE));
179        GlyphPageTreeNode* node1 = GlyphPageTreeNode::getRootChild(segmentedData1.get(), kPageNumber);
180        GlyphPageTreeNode* node2 = node1->getChild(segmentedData2.get(), kPageNumber);
181        GlyphPageTreeNode* node3 = node2->getChild(segmentedData3.get(), kPageNumber);
182
183        EXPECT_EQ(0, node3->page()->glyphDataForCharacter('A').fontData);
184        EXPECT_EQ(dataBtoD, node3->page()->glyphDataForCharacter('B').fontData);
185        EXPECT_EQ(dataBtoD, node3->page()->glyphDataForCharacter('C').fontData);
186        EXPECT_EQ(dataBtoD, node3->page()->glyphDataForCharacter('D').fontData);
187        EXPECT_EQ(0, node3->page()->glyphDataForCharacter('E').fontData);
188
189        EXPECT_EQ(dataAtoC->customFontData(), node3->page()->customFontToLoadAt('A'));
190        EXPECT_EQ(dataAtoC->customFontData(), node3->page()->customFontToLoadAt('B'));
191        EXPECT_EQ(dataAtoC->customFontData(), node3->page()->customFontToLoadAt('C'));
192        EXPECT_EQ(0, node3->page()->customFontToLoadAt('D'));
193        EXPECT_EQ(dataCtoE->customFontData(), node3->page()->customFontToLoadAt('E'));
194    }
195    EXPECT_EQ(pageCountBeforeTest, GlyphPageTreeNode::treeGlyphPageCount());
196}
197
198TEST(GlyphPageTreeNode, systemFallback)
199{
200    const unsigned kPageNumber = 0;
201    size_t pageCountBeforeTest = GlyphPageTreeNode::treeGlyphPageCount();
202    {
203        RefPtr<TestSimpleFontData> dataAtoC = TestSimpleFontData::createUnloaded('A', 'C');
204        RefPtr<TestSimpleFontData> dataBtoD = TestSimpleFontData::create('B', 'D');
205        RefPtr<SegmentedFontData> segmentedData = SegmentedFontData::create();
206        segmentedData->appendRange(FontDataRange('A', 'C', dataAtoC));
207        GlyphPageTreeNode* node1 = GlyphPageTreeNode::getRootChild(segmentedData.get(), kPageNumber);
208        GlyphPageTreeNode* node2 = node1->getChild(dataBtoD.get(), kPageNumber);
209        GlyphPageTreeNode* node3 = node2->getChild(0, kPageNumber);
210
211        EXPECT_TRUE(node3->isSystemFallback());
212
213        EXPECT_EQ(0, node3->page()->glyphDataForCharacter('A').fontData);
214        EXPECT_EQ(dataBtoD, node3->page()->glyphDataForCharacter('B').fontData);
215        EXPECT_EQ(dataBtoD, node3->page()->glyphDataForCharacter('C').fontData);
216        EXPECT_EQ(dataBtoD, node3->page()->glyphDataForCharacter('D').fontData);
217
218        EXPECT_EQ(dataAtoC->customFontData(), node3->page()->customFontToLoadAt('A'));
219        EXPECT_EQ(dataAtoC->customFontData(), node3->page()->customFontToLoadAt('B'));
220        EXPECT_EQ(dataAtoC->customFontData(), node3->page()->customFontToLoadAt('C'));
221        EXPECT_EQ(0, node3->page()->customFontToLoadAt('D'));
222    }
223    EXPECT_EQ(pageCountBeforeTest, GlyphPageTreeNode::treeGlyphPageCount());
224}
225
226} // namespace WebCore
227