summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/minikin/FontCollection.h12
-rw-r--r--include/minikin/FontFamily.h7
-rw-r--r--libs/minikin/FontCollection.cpp83
-rw-r--r--libs/minikin/FontFamily.cpp21
4 files changed, 63 insertions, 60 deletions
diff --git a/include/minikin/FontCollection.h b/include/minikin/FontCollection.h
index 12700c6..ffdb4d1 100644
--- a/include/minikin/FontCollection.h
+++ b/include/minikin/FontCollection.h
@@ -21,7 +21,6 @@
#include <minikin/MinikinRefCounted.h>
#include <minikin/MinikinFont.h>
-#include <minikin/SparseBitSet.h>
#include <minikin/FontFamily.h>
namespace android {
@@ -52,17 +51,12 @@ private:
static const int kLogCharsPerPage = 8;
static const int kPageMask = (1 << kLogCharsPerPage) - 1;
- struct FontInstance {
- SparseBitSet* mCoverage;
- FontFamily* mFamily;
- };
-
struct Range {
size_t start;
size_t end;
};
- const FontInstance* getInstanceForChar(uint32_t ch, FontLanguage lang, int variant) const;
+ FontFamily* getFamilyForChar(uint32_t ch, FontLanguage lang, int variant) const;
// static for allocating unique id's
static uint32_t sNextId;
@@ -74,10 +68,10 @@ private:
uint32_t mMaxChar;
// This vector has ownership of the bitsets and typeface objects.
- std::vector<FontInstance> mInstances;
+ std::vector<FontFamily*> mFamilies;
// This vector contains pointers into mInstances
- std::vector<const FontInstance*> mInstanceVec;
+ std::vector<FontFamily*> mFamilyVec;
// These are offsets into mInstanceVec, one range per page
std::vector<Range> mRanges;
diff --git a/include/minikin/FontFamily.h b/include/minikin/FontFamily.h
index bcc2e3a..08c7a2c 100644
--- a/include/minikin/FontFamily.h
+++ b/include/minikin/FontFamily.h
@@ -23,6 +23,7 @@
#include <utils/TypeHelpers.h>
#include <minikin/MinikinRefCounted.h>
+#include <minikin/SparseBitSet.h>
namespace android {
@@ -139,6 +140,9 @@ public:
size_t getNumFonts() const;
MinikinFont* getFont(size_t index) const;
FontStyle getStyle(size_t index) const;
+
+ // Get Unicode coverage. Lifetime of returned bitset is same as receiver.
+ const SparseBitSet* getCoverage();
private:
void addFontLocked(MinikinFont* typeface, FontStyle style);
@@ -152,6 +156,9 @@ private:
FontLanguage mLang;
int mVariant;
std::vector<Font> mFonts;
+
+ SparseBitSet mCoverage;
+ bool mCoverageValid;
};
} // namespace android
diff --git a/libs/minikin/FontCollection.cpp b/libs/minikin/FontCollection.cpp
index ca5b1d1..7b6b950 100644
--- a/libs/minikin/FontCollection.cpp
+++ b/libs/minikin/FontCollection.cpp
@@ -23,7 +23,6 @@
#include "unicode/unorm2.h"
#include "MinikinInternal.h"
-#include <minikin/CmapCoverage.h>
#include <minikin/FontCollection.h>
using std::vector;
@@ -54,28 +53,12 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) :
continue;
}
family->RefLocked();
- FontInstance dummy;
- mInstances.push_back(dummy); // emplace_back would be better
- FontInstance* instance = &mInstances.back();
- instance->mFamily = family;
- instance->mCoverage = new SparseBitSet;
-#ifdef VERBOSE_DEBUG
- ALOGD("closest match = %p, family size = %d\n", typeface, family->getNumFonts());
-#endif
- const uint32_t cmapTag = MinikinFont::MakeTag('c', 'm', 'a', 'p');
- size_t cmapSize = 0;
- bool ok = typeface->GetTable(cmapTag, NULL, &cmapSize);
- UniquePtr<uint8_t[]> cmapData(new uint8_t[cmapSize]);
- ok = typeface->GetTable(cmapTag, cmapData.get(), &cmapSize);
- CmapCoverage::getCoverage(*instance->mCoverage, cmapData.get(), cmapSize);
-#ifdef VERBOSE_DEBUG
- ALOGD("font coverage length=%d, first ch=%x\n", instance->mCoverage->length(),
- instance->mCoverage->nextSetBit(0));
-#endif
- mMaxChar = max(mMaxChar, instance->mCoverage->length());
- lastChar.push_back(instance->mCoverage->nextSetBit(0));
+ mFamilies.push_back(family); // emplace_back would be better
+ const SparseBitSet* coverage = family->getCoverage();
+ mMaxChar = max(mMaxChar, coverage->length());
+ lastChar.push_back(coverage->nextSetBit(0));
}
- nTypefaces = mInstances.size();
+ nTypefaces = mFamilies.size();
LOG_ALWAYS_FATAL_IF(nTypefaces == 0,
"Font collection must have at least one valid typeface");
size_t nPages = (mMaxChar + kPageMask) >> kLogCharsPerPage;
@@ -90,10 +73,10 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) :
range->start = offset;
for (size_t j = 0; j < nTypefaces; j++) {
if (lastChar[j] < (i + 1) << kLogCharsPerPage) {
- const FontInstance* instance = &mInstances[j];
- mInstanceVec.push_back(instance);
+ FontFamily* family = mFamilies[j];
+ mFamilyVec.push_back(family);
offset++;
- uint32_t nextChar = instance->mCoverage->nextSetBit((i + 1) << kLogCharsPerPage);
+ uint32_t nextChar = family->getCoverage()->nextSetBit((i + 1) << kLogCharsPerPage);
#ifdef VERBOSE_DEBUG
ALOGD("nextChar = %d (j = %d)\n", nextChar, j);
#endif
@@ -105,9 +88,8 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) :
}
FontCollection::~FontCollection() {
- for (size_t i = 0; i < mInstances.size(); i++) {
- delete mInstances[i].mCoverage;
- mInstances[i].mFamily->UnrefLocked();
+ for (size_t i = 0; i < mFamilies.size(); i++) {
+ mFamilies[i]->UnrefLocked();
}
}
@@ -117,7 +99,7 @@ FontCollection::~FontCollection() {
// 3. If a font matches just language, it gets a score of 2.
// 4. Matching the "compact" or "elegant" variant adds one to the score.
// 5. Highest score wins, with ties resolved to the first font.
-const FontCollection::FontInstance* FontCollection::getInstanceForChar(uint32_t ch,
+FontFamily* FontCollection::getFamilyForChar(uint32_t ch,
FontLanguage lang, int variant) const {
if (ch >= mMaxChar) {
return NULL;
@@ -126,15 +108,14 @@ const FontCollection::FontInstance* FontCollection::getInstanceForChar(uint32_t
#ifdef VERBOSE_DEBUG
ALOGD("querying range %d:%d\n", range.start, range.end);
#endif
- const FontInstance* bestInstance = NULL;
+ FontFamily* bestFamily = NULL;
int bestScore = -1;
for (size_t i = range.start; i < range.end; i++) {
- const FontInstance* instance = mInstanceVec[i];
- if (instance->mCoverage->get(ch)) {
- FontFamily* family = instance->mFamily;
+ FontFamily* family = mFamilyVec[i];
+ if (family->getCoverage()->get(ch)) {
// First font family in collection always matches
- if (mInstances[0].mFamily == family) {
- return instance;
+ if (mFamilies[0] == family) {
+ return family;
}
int score = lang.match(family->lang()) * 2;
if (variant != 0 && variant == family->variant()) {
@@ -142,11 +123,11 @@ const FontCollection::FontInstance* FontCollection::getInstanceForChar(uint32_t
}
if (score > bestScore) {
bestScore = score;
- bestInstance = instance;
+ bestFamily = family;
}
}
}
- if (bestInstance == NULL && !mInstanceVec.empty()) {
+ if (bestFamily == NULL && !mFamilyVec.empty()) {
UErrorCode errorCode = U_ZERO_ERROR;
const UNormalizer2* normalizer = unorm2_getNFDInstance(&errorCode);
if (U_SUCCESS(errorCode)) {
@@ -155,12 +136,12 @@ const FontCollection::FontInstance* FontCollection::getInstanceForChar(uint32_t
if (U_SUCCESS(errorCode) && len > 0) {
int off = 0;
U16_NEXT_UNSAFE(decomposed, off, ch);
- return getInstanceForChar(ch, lang, variant);
+ return getFamilyForChar(ch, lang, variant);
}
}
- bestInstance = &mInstances[0];
+ bestFamily = mFamilies[0];
}
- return bestInstance;
+ return bestFamily;
}
const uint32_t NBSP = 0xa0;
@@ -183,7 +164,7 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
vector<Run>* result) const {
FontLanguage lang = style.getLanguage();
int variant = style.getVariant();
- const FontInstance* lastInstance = NULL;
+ FontFamily* lastFamily = NULL;
Run* run = NULL;
int nShorts;
for (size_t i = 0; i < string_size; i += nShorts) {
@@ -197,17 +178,17 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
}
}
// Continue using existing font as long as it has coverage and is whitelisted
- if (lastInstance == NULL
- || !(isStickyWhitelisted(ch) && lastInstance->mCoverage->get(ch))) {
- const FontInstance* instance = getInstanceForChar(ch, lang, variant);
- if (i == 0 || instance != lastInstance) {
+ if (lastFamily == NULL
+ || !(isStickyWhitelisted(ch) && lastFamily->getCoverage()->get(ch))) {
+ FontFamily* family = getFamilyForChar(ch, lang, variant);
+ if (i == 0 || family != lastFamily) {
size_t start = i;
// Workaround for Emoji keycap until we implement per-cluster font
// selection: if keycap is found in a different font that also
// supports previous char, attach previous char to the new run.
// Only handles non-surrogate characters.
// Bug 7557244.
- if (ch == KEYCAP && i && instance && instance->mCoverage->get(string[i - 1])) {
+ if (ch == KEYCAP && i && family && family->getCoverage()->get(string[i - 1])) {
run->end--;
if (run->start == run->end) {
result->pop_back();
@@ -217,12 +198,12 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
Run dummy;
result->push_back(dummy);
run = &result->back();
- if (instance == NULL) {
+ if (family == NULL) {
run->fakedFont.font = NULL;
} else {
- run->fakedFont = instance->mFamily->getClosestMatch(style);
+ run->fakedFont = family->getClosestMatch(style);
}
- lastInstance = instance;
+ lastFamily = family;
run->start = start;
}
}
@@ -235,10 +216,10 @@ MinikinFont* FontCollection::baseFont(FontStyle style) {
}
FakedFont FontCollection::baseFontFaked(FontStyle style) {
- if (mInstances.empty()) {
+ if (mFamilies.empty()) {
return FakedFont();
}
- return mInstances[0].mFamily->getClosestMatch(style);
+ return mFamilies[0]->getClosestMatch(style);
}
uint32_t FontCollection::getId() const {
diff --git a/libs/minikin/FontFamily.cpp b/libs/minikin/FontFamily.cpp
index f688a33..d2e5867 100644
--- a/libs/minikin/FontFamily.cpp
+++ b/libs/minikin/FontFamily.cpp
@@ -23,6 +23,7 @@
#include "MinikinInternal.h"
#include <minikin/MinikinFont.h>
#include <minikin/AnalyzeStyle.h>
+#include <minikin/CmapCoverage.h>
#include <minikin/FontFamily.h>
#include <UniquePtr.h>
@@ -128,6 +129,7 @@ void FontFamily::addFont(MinikinFont* typeface, FontStyle style) {
void FontFamily::addFontLocked(MinikinFont* typeface, FontStyle style) { typeface->RefLocked();
mFonts.push_back(Font(typeface, style));
+ mCoverageValid = false;
}
// Compute a matching metric between two styles - 0 is an exact match
@@ -183,4 +185,23 @@ FontStyle FontFamily::getStyle(size_t index) const {
return mFonts[index].style;
}
+const SparseBitSet* FontFamily::getCoverage() {
+ if (!mCoverageValid) {
+ const FontStyle defaultStyle;
+ MinikinFont* typeface = getClosestMatch(defaultStyle).font;
+ const uint32_t cmapTag = MinikinFont::MakeTag('c', 'm', 'a', 'p');
+ size_t cmapSize = 0;
+ bool ok = typeface->GetTable(cmapTag, NULL, &cmapSize);
+ UniquePtr<uint8_t[]> cmapData(new uint8_t[cmapSize]);
+ ok = typeface->GetTable(cmapTag, cmapData.get(), &cmapSize);
+ CmapCoverage::getCoverage(mCoverage, cmapData.get(), cmapSize);
+#ifdef VERBOSE_DEBUG
+ ALOGD("font coverage length=%d, first ch=%x\n", mCoverage->length(),
+ mCoverage->nextSetBit(0));
+#endif
+ mCoverageValid = true;
+ }
+ return &mCoverage;
+}
+
} // namespace android