blob: 8c727f9da9a05d68c18fd51efb229429bcc400e9 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include "minikin/BoundsCache.h"
#include "FontTestUtils.h"
#include "LocaleListCache.h"
#include "UnicodeUtils.h"
namespace minikin {
class TestableBoundsCache : public BoundsCache {
public:
TestableBoundsCache(uint32_t maxEntries) : BoundsCache(maxEntries) {}
};
class BoundsCapture {
public:
BoundsCapture() {}
void operator()(const MinikinRect& rect, float advance) {
mRect = rect;
mAdvance = advance;
}
const MinikinRect& rect() const { return mRect; }
float advance() const { return mAdvance; }
private:
MinikinRect mRect;
float mAdvance;
};
TEST(BoundsCacheTest, cacheHitTest) {
auto text = utf8ToUtf16("android");
Range range(0, text.size());
MinikinPaint paint(buildFontCollection("Ascii.ttf"));
TestableBoundsCache boundsCache(10);
BoundsCapture bounds1;
boundsCache.getOrCreate(text, range, paint, false /* LTR */, StartHyphenEdit::NO_EDIT,
EndHyphenEdit::NO_EDIT, bounds1);
BoundsCapture bounds2;
boundsCache.getOrCreate(text, range, paint, false /* LTR */, StartHyphenEdit::NO_EDIT,
EndHyphenEdit::NO_EDIT, bounds2);
EXPECT_EQ(bounds1.rect(), bounds2.rect());
EXPECT_EQ(bounds1.advance(), bounds2.advance());
}
TEST(BoundsCacheTest, cacheMissTest) {
auto text1 = utf8ToUtf16("android");
auto text2 = utf8ToUtf16("αβγδζ");
MinikinPaint paint(buildFontCollection("Ascii.ttf"));
TestableBoundsCache boundsCache(10);
BoundsCapture bounds1;
BoundsCapture bounds2;
{
SCOPED_TRACE("Different text");
boundsCache.getOrCreate(text1, Range(0, text1.size()), paint, false /* LTR */,
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, bounds1);
boundsCache.getOrCreate(text2, Range(0, text2.size()), paint, false /* LTR */,
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, bounds2);
EXPECT_NE(bounds1.rect(), bounds2.rect());
EXPECT_NE(bounds1.advance(), bounds2.advance());
}
{
SCOPED_TRACE("Different range");
boundsCache.getOrCreate(text1, Range(0, text1.size()), paint, false /* LTR */,
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, bounds1);
boundsCache.getOrCreate(text1, Range(1, text1.size()), paint, false /* LTR */,
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, bounds2);
EXPECT_NE(bounds1.rect(), bounds2.rect());
EXPECT_NE(bounds1.advance(), bounds2.advance());
}
{
SCOPED_TRACE("Different collection");
MinikinPaint paint1(buildFontCollection("Ascii.ttf"));
paint1.size = 10.0f;
paint1.scaleX = 1.0f;
boundsCache.getOrCreate(text1, Range(0, text1.size()), paint1, false /* LTR */,
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, bounds1);
MinikinPaint paint2(buildFontCollection("Emoji.ttf"));
paint2.size = 10.0f;
paint2.scaleX = 1.0f;
boundsCache.getOrCreate(text1, Range(0, text1.size()), paint2, false /* LTR */,
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, bounds2);
EXPECT_NE(bounds1.rect(), bounds2.rect());
EXPECT_NE(bounds1.advance(), bounds2.advance());
}
{
SCOPED_TRACE("Different size");
auto collection = buildFontCollection("Ascii.ttf");
MinikinPaint paint1(collection);
paint1.size = 10.0f;
paint1.scaleX = 1.0f;
boundsCache.getOrCreate(text1, Range(0, text1.size()), paint1, false /* LTR */,
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, bounds1);
MinikinPaint paint2(collection);
paint2.size = 20.0f;
paint2.scaleX = 1.0f;
boundsCache.getOrCreate(text1, Range(0, text1.size()), paint2, false /* LTR */,
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, bounds2);
EXPECT_NE(bounds1.rect(), bounds2.rect());
EXPECT_NE(bounds1.advance(), bounds2.advance());
}
{
SCOPED_TRACE("Different letter spacing");
auto collection = buildFontCollection("Ascii.ttf");
MinikinPaint paint1(collection);
paint1.letterSpacing = 0.0f;
paint1.size = 10.0f;
paint1.scaleX = 1.0f;
boundsCache.getOrCreate(text1, Range(0, text1.size()), paint1, false /* LTR */,
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, bounds1);
MinikinPaint paint2(collection);
paint2.letterSpacing = 1.0f;
paint2.size = 10.0f;
paint2.scaleX = 1.0f;
boundsCache.getOrCreate(text1, Range(0, text1.size()), paint2, false /* LTR */,
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, bounds2);
EXPECT_NE(bounds1.rect(), bounds2.rect());
EXPECT_NE(bounds1.advance(), bounds2.advance());
}
}
TEST(BoundsCacheTest, cacheOverflowTest) {
auto text = utf8ToUtf16("android");
Range range(0, text.size());
MinikinPaint paint(buildFontCollection("Ascii.ttf"));
TestableBoundsCache boundsCache(5);
BoundsCapture bounds1;
boundsCache.getOrCreate(text, range, paint, false /* LTR */, StartHyphenEdit::NO_EDIT,
EndHyphenEdit::NO_EDIT, bounds1);
for (char c = 'a'; c <= 'z'; c++) {
auto text1 = utf8ToUtf16(std::string(10, c));
BoundsCapture bounds2;
boundsCache.getOrCreate(text1, Range(0, text1.size()), paint, false /* LTR */,
StartHyphenEdit::NO_EDIT, EndHyphenEdit::NO_EDIT, bounds2);
}
BoundsCapture bounds3;
boundsCache.getOrCreate(text, range, paint, false /* LTR */, StartHyphenEdit::NO_EDIT,
EndHyphenEdit::NO_EDIT, bounds3);
EXPECT_EQ(bounds1.rect(), bounds3.rect());
EXPECT_EQ(bounds1.advance(), bounds3.advance());
}
} // namespace minikin