Fix minikin_unittests
This CL fixes following test cases in minikin_tests
- FontFamilyTest.hasVariationSelectorTest
- HbFontCacheTest.getHbFontLockedTest
- HbFontCacheTest.purgeCacheTest
For the fix of FontFamilyTest.hasVariationSelectorTest, removing virtual
from GetUniqueId() in MinikinFont. After [1], MinikinFont's destructor
started calling purgeHbCache() which calls virtual method,
MinikinFont::GetUniqueId(). Fortunately, the SkTypeface::uniqueID()
returns just internal value, so we can store it at the construction time
and use it instead of calling SkTypeface::uniqueID() every time.
This patch also changes purgeHbFont to purgeHbFontLocked, as all uses of
it were already under global mutex. This change avoids deadlock on
explicit unref, as when invoked by a Java finalizer from the Java object
that holds a reference to the font.
Some of the tests needed to change to using the ref counting protocol
rather than explicitly destructing font objects, as well.
[1] 1ea4165cef
Bug: 28105730
Bug: 28105688
Change-Id: Ie5983c4869147dacabdca81af1605066cd680b3f
This commit is contained in:
committed by
Raph Levien
parent
d2161cf80f
commit
bb8b7fd32f
@@ -99,6 +99,8 @@ typedef void (*MinikinDestroyFunc) (void* data);
|
|||||||
|
|
||||||
class MinikinFont : public MinikinRefCounted {
|
class MinikinFont : public MinikinRefCounted {
|
||||||
public:
|
public:
|
||||||
|
MinikinFont(int32_t uniqueId) : mUniqueId(uniqueId) {}
|
||||||
|
|
||||||
virtual ~MinikinFont();
|
virtual ~MinikinFont();
|
||||||
|
|
||||||
virtual float GetHorizontalAdvance(uint32_t glyph_id,
|
virtual float GetHorizontalAdvance(uint32_t glyph_id,
|
||||||
@@ -125,12 +127,14 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int32_t GetUniqueId() const = 0;
|
|
||||||
|
|
||||||
static uint32_t MakeTag(char c1, char c2, char c3, char c4) {
|
static uint32_t MakeTag(char c1, char c2, char c3, char c4) {
|
||||||
return ((uint32_t)c1 << 24) | ((uint32_t)c2 << 16) |
|
return ((uint32_t)c1 << 24) | ((uint32_t)c2 << 16) |
|
||||||
((uint32_t)c3 << 8) | (uint32_t)c4;
|
((uint32_t)c3 << 8) | (uint32_t)c4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t GetUniqueId() const { return mUniqueId; }
|
||||||
|
private:
|
||||||
|
const int32_t mUniqueId;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|||||||
@@ -52,8 +52,6 @@ public:
|
|||||||
|
|
||||||
// TODO: provide access to raw data, as an optimization.
|
// TODO: provide access to raw data, as an optimization.
|
||||||
|
|
||||||
int32_t GetUniqueId() const;
|
|
||||||
|
|
||||||
// Not a virtual method, as the protocol to access rendered
|
// Not a virtual method, as the protocol to access rendered
|
||||||
// glyph bitmaps is probably different depending on the
|
// glyph bitmaps is probably different depending on the
|
||||||
// backend.
|
// backend.
|
||||||
@@ -64,7 +62,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
FT_Face mTypeface;
|
FT_Face mTypeface;
|
||||||
int32_t mUniqueId;
|
|
||||||
static int32_t sIdCounter;
|
static int32_t sIdCounter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,23 @@ private:
|
|||||||
int mRefcount_;
|
int mRefcount_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// An RAII container for reference counted objects.
|
||||||
|
// Note: this is only suitable for clients which are _not_ holding the global lock.
|
||||||
|
template <typename T>
|
||||||
|
class MinikinAutoUnref {
|
||||||
|
public:
|
||||||
|
MinikinAutoUnref(T* obj) : mObj(obj) {
|
||||||
|
}
|
||||||
|
~MinikinAutoUnref() {
|
||||||
|
mObj->Unref();
|
||||||
|
}
|
||||||
|
T& operator*() const { return *mObj; }
|
||||||
|
T* operator->() const { return mObj; }
|
||||||
|
T* get() const { return mObj; }
|
||||||
|
private:
|
||||||
|
T* mObj;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MINIKIN_REF_COUNTED_H
|
#endif // MINIKIN_REF_COUNTED_H
|
||||||
@@ -91,8 +91,8 @@ void purgeHbFontCacheLocked() {
|
|||||||
getFontCacheLocked()->clear();
|
getFontCacheLocked()->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void purgeHbFont(const MinikinFont* minikinFont) {
|
void purgeHbFontLocked(const MinikinFont* minikinFont) {
|
||||||
AutoMutex _l(gMinikinLock);
|
assertMinikinLocked();
|
||||||
const int32_t fontId = minikinFont->GetUniqueId();
|
const int32_t fontId = minikinFont->GetUniqueId();
|
||||||
getFontCacheLocked()->remove(fontId);
|
getFontCacheLocked()->remove(fontId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace android {
|
|||||||
class MinikinFont;
|
class MinikinFont;
|
||||||
|
|
||||||
void purgeHbFontCacheLocked();
|
void purgeHbFontCacheLocked();
|
||||||
void purgeHbFont(const MinikinFont* minikinFont);
|
void purgeHbFontLocked(const MinikinFont* minikinFont);
|
||||||
hb_font_t* getHbFontLocked(MinikinFont* minikinFont);
|
hb_font_t* getHbFontLocked(MinikinFont* minikinFont);
|
||||||
|
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
MinikinFont::~MinikinFont() {
|
MinikinFont::~MinikinFont() {
|
||||||
purgeHbFont(this);
|
purgeHbFontLocked(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ namespace android {
|
|||||||
int32_t MinikinFontFreeType::sIdCounter = 0;
|
int32_t MinikinFontFreeType::sIdCounter = 0;
|
||||||
|
|
||||||
MinikinFontFreeType::MinikinFontFreeType(FT_Face typeface) :
|
MinikinFontFreeType::MinikinFontFreeType(FT_Face typeface) :
|
||||||
|
MinikinFont(sIdCounter++),
|
||||||
mTypeface(typeface) {
|
mTypeface(typeface) {
|
||||||
mUniqueId = sIdCounter++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MinikinFontFreeType::~MinikinFontFreeType() {
|
MinikinFontFreeType::~MinikinFontFreeType() {
|
||||||
@@ -72,10 +72,6 @@ const void* MinikinFontFreeType::GetTable(uint32_t tag, size_t* size, MinikinDes
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t MinikinFontFreeType::GetUniqueId() const {
|
|
||||||
return mUniqueId;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MinikinFontFreeType::Render(uint32_t glyph_id, const MinikinPaint& /* paint */,
|
bool MinikinFontFreeType::Render(uint32_t glyph_id, const MinikinPaint& /* paint */,
|
||||||
GlyphBitmap *result) {
|
GlyphBitmap *result) {
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
MinikinFontSkia::MinikinFontSkia(SkTypeface *typeface) :
|
MinikinFontSkia::MinikinFontSkia(SkTypeface *typeface) :
|
||||||
|
MinikinFont(typeface->uniqueID()),
|
||||||
mTypeface(typeface) {
|
mTypeface(typeface) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,8 +68,4 @@ SkTypeface *MinikinFontSkia::GetSkTypeface() {
|
|||||||
return mTypeface;
|
return mTypeface;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t MinikinFontSkia::GetUniqueId() const {
|
|
||||||
return mTypeface->uniqueID();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ public:
|
|||||||
|
|
||||||
const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy);
|
const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy);
|
||||||
|
|
||||||
int32_t GetUniqueId() const;
|
|
||||||
|
|
||||||
SkTypeface *GetSkTypeface();
|
SkTypeface *GetSkTypeface();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -350,9 +350,9 @@ void expectVSGlyphs(FontFamily* family, uint32_t codepoint, const std::set<uint3
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FontFamilyTest, hasVariationSelectorTest) {
|
TEST_F(FontFamilyTest, hasVariationSelectorTest) {
|
||||||
MinikinFontForTest minikinFont(kVsTestFont);
|
MinikinAutoUnref<MinikinFontForTest> minikinFont(new MinikinFontForTest(kVsTestFont));
|
||||||
FontFamily family;
|
MinikinAutoUnref<FontFamily> family(new FontFamily);
|
||||||
family.addFont(&minikinFont);
|
family->addFont(minikinFont.get());
|
||||||
|
|
||||||
AutoMutex _l(gMinikinLock);
|
AutoMutex _l(gMinikinLock);
|
||||||
|
|
||||||
@@ -365,24 +365,24 @@ TEST_F(FontFamilyTest, hasVariationSelectorTest) {
|
|||||||
const uint32_t kVS20 = 0xE0103;
|
const uint32_t kVS20 = 0xE0103;
|
||||||
|
|
||||||
const uint32_t kSupportedChar1 = 0x82A6;
|
const uint32_t kSupportedChar1 = 0x82A6;
|
||||||
EXPECT_TRUE(family.getCoverage()->get(kSupportedChar1));
|
EXPECT_TRUE(family->getCoverage()->get(kSupportedChar1));
|
||||||
expectVSGlyphs(&family, kSupportedChar1, std::set<uint32_t>({kVS1, kVS17, kVS18, kVS19}));
|
expectVSGlyphs(family.get(), kSupportedChar1, std::set<uint32_t>({kVS1, kVS17, kVS18, kVS19}));
|
||||||
|
|
||||||
const uint32_t kSupportedChar2 = 0x845B;
|
const uint32_t kSupportedChar2 = 0x845B;
|
||||||
EXPECT_TRUE(family.getCoverage()->get(kSupportedChar2));
|
EXPECT_TRUE(family->getCoverage()->get(kSupportedChar2));
|
||||||
expectVSGlyphs(&family, kSupportedChar2, std::set<uint32_t>({kVS2, kVS18, kVS19, kVS20}));
|
expectVSGlyphs(family.get(), kSupportedChar2, std::set<uint32_t>({kVS2, kVS18, kVS19, kVS20}));
|
||||||
|
|
||||||
const uint32_t kNoVsSupportedChar = 0x537F;
|
const uint32_t kNoVsSupportedChar = 0x537F;
|
||||||
EXPECT_TRUE(family.getCoverage()->get(kNoVsSupportedChar));
|
EXPECT_TRUE(family->getCoverage()->get(kNoVsSupportedChar));
|
||||||
expectVSGlyphs(&family, kNoVsSupportedChar, std::set<uint32_t>());
|
expectVSGlyphs(family.get(), kNoVsSupportedChar, std::set<uint32_t>());
|
||||||
|
|
||||||
const uint32_t kVsOnlySupportedChar = 0x717D;
|
const uint32_t kVsOnlySupportedChar = 0x717D;
|
||||||
EXPECT_FALSE(family.getCoverage()->get(kVsOnlySupportedChar));
|
EXPECT_FALSE(family->getCoverage()->get(kVsOnlySupportedChar));
|
||||||
expectVSGlyphs(&family, kVsOnlySupportedChar, std::set<uint32_t>({kVS3, kVS19, kVS20}));
|
expectVSGlyphs(family.get(), kVsOnlySupportedChar, std::set<uint32_t>({kVS3, kVS19, kVS20}));
|
||||||
|
|
||||||
const uint32_t kNotSupportedChar = 0x845C;
|
const uint32_t kNotSupportedChar = 0x845C;
|
||||||
EXPECT_FALSE(family.getCoverage()->get(kNotSupportedChar));
|
EXPECT_FALSE(family->getCoverage()->get(kNotSupportedChar));
|
||||||
expectVSGlyphs(&family, kNotSupportedChar, std::set<uint32_t>());
|
expectVSGlyphs(family.get(), kNotSupportedChar, std::set<uint32_t>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FontFamilyTest, hasVSTableTest) {
|
TEST_F(FontFamilyTest, hasVSTableTest) {
|
||||||
@@ -403,12 +403,13 @@ TEST_F(FontFamilyTest, hasVSTableTest) {
|
|||||||
"Font " + testCase.fontPath + " should have a variation sequence table." :
|
"Font " + testCase.fontPath + " should have a variation sequence table." :
|
||||||
"Font " + testCase.fontPath + " shouldn't have a variation sequence table.");
|
"Font " + testCase.fontPath + " shouldn't have a variation sequence table.");
|
||||||
|
|
||||||
MinikinFontForTest minikinFont(testCase.fontPath);
|
MinikinAutoUnref<MinikinFontForTest> minikinFont(new MinikinFontForTest(testCase.fontPath));
|
||||||
FontFamily family;
|
MinikinAutoUnref<FontFamily> family(new FontFamily);
|
||||||
family.addFont(&minikinFont);
|
family->addFont(minikinFont.get());
|
||||||
family.getCoverage();
|
AutoMutex _l(gMinikinLock);
|
||||||
|
family->getCoverage();
|
||||||
|
|
||||||
EXPECT_EQ(testCase.hasVSTable, family.hasVSTable());
|
EXPECT_EQ(testCase.hasVSTable, family->hasVSTable());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,14 @@
|
|||||||
|
|
||||||
#include <cutils/log.h>
|
#include <cutils/log.h>
|
||||||
|
|
||||||
MinikinFontForTest::MinikinFontForTest(const std::string& font_path) : mFontPath(font_path) {
|
MinikinFontForTest::MinikinFontForTest(const std::string& font_path) :
|
||||||
mTypeface = SkTypeface::CreateFromFile(font_path.c_str());
|
MinikinFontForTest(font_path, SkTypeface::CreateFromFile(font_path.c_str())) {
|
||||||
|
}
|
||||||
|
|
||||||
|
MinikinFontForTest::MinikinFontForTest(const std::string& font_path, SkTypeface* typeface) :
|
||||||
|
MinikinFont(typeface->uniqueID()),
|
||||||
|
mTypeface(typeface),
|
||||||
|
mFontPath(font_path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MinikinFontForTest::~MinikinFontForTest() {
|
MinikinFontForTest::~MinikinFontForTest() {
|
||||||
@@ -55,7 +61,3 @@ const void* MinikinFontForTest::GetTable(uint32_t tag, size_t* size,
|
|||||||
*destroy = free;
|
*destroy = free;
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t MinikinFontForTest::GetUniqueId() const {
|
|
||||||
return mTypeface->uniqueID();
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ class SkTypeface;
|
|||||||
class MinikinFontForTest : public android::MinikinFont {
|
class MinikinFontForTest : public android::MinikinFont {
|
||||||
public:
|
public:
|
||||||
explicit MinikinFontForTest(const std::string& font_path);
|
explicit MinikinFontForTest(const std::string& font_path);
|
||||||
|
MinikinFontForTest(const std::string& font_path, SkTypeface* typeface);
|
||||||
~MinikinFontForTest();
|
~MinikinFontForTest();
|
||||||
|
|
||||||
// MinikinFont overrides.
|
// MinikinFont overrides.
|
||||||
@@ -31,7 +32,6 @@ public:
|
|||||||
void GetBounds(android::MinikinRect* bounds, uint32_t glyph_id,
|
void GetBounds(android::MinikinRect* bounds, uint32_t glyph_id,
|
||||||
const android::MinikinPaint& paint) const;
|
const android::MinikinPaint& paint) const;
|
||||||
const void* GetTable(uint32_t tag, size_t* size, android::MinikinDestroyFunc* destroy);
|
const void* GetTable(uint32_t tag, size_t* size, android::MinikinDestroyFunc* destroy);
|
||||||
int32_t GetUniqueId() const;
|
|
||||||
|
|
||||||
const std::string& fontPath() const { return mFontPath; }
|
const std::string& fontPath() const { return mFontPath; }
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
mmm -j8 frameworks/minikin/tests &&
|
mmm -j8 frameworks/minikin/tests &&
|
||||||
adb push $OUT/data/nativetest/minikin_tests/minikin_tests \
|
adb push $OUT/data/nativetest/minikin_tests/minikin_tests \
|
||||||
/data/nativetest/minikin_tests/minikin_tests &&
|
/data/nativetest/minikin_tests/minikin_tests &&
|
||||||
adb push frameworks/minikin/tests/data /data/nativetest/minikin_tests/data &&
|
adb push frameworks/minikin/tests/data /data/nativetest/minikin_tests/ &&
|
||||||
adb shell /data/nativetest/minikin_tests/minikin_tests
|
adb shell /data/nativetest/minikin_tests/minikin_tests
|
||||||
|
|||||||
Reference in New Issue
Block a user