提交 92065a6f 编写于 作者: R Raph Levien 提交者: Android Git Automerger

am 253320d2: Move coverage bitmap from FontCollection to FontFamily

* commit '253320d2':
  Move coverage bitmap from FontCollection to FontFamily
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <minikin/MinikinRefCounted.h> #include <minikin/MinikinRefCounted.h>
#include <minikin/MinikinFont.h> #include <minikin/MinikinFont.h>
#include <minikin/SparseBitSet.h>
#include <minikin/FontFamily.h> #include <minikin/FontFamily.h>
namespace android { namespace android {
...@@ -52,17 +51,12 @@ private: ...@@ -52,17 +51,12 @@ private:
static const int kLogCharsPerPage = 8; static const int kLogCharsPerPage = 8;
static const int kPageMask = (1 << kLogCharsPerPage) - 1; static const int kPageMask = (1 << kLogCharsPerPage) - 1;
struct FontInstance {
SparseBitSet* mCoverage;
FontFamily* mFamily;
};
struct Range { struct Range {
size_t start; size_t start;
size_t end; 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 for allocating unique id's
static uint32_t sNextId; static uint32_t sNextId;
...@@ -74,10 +68,10 @@ private: ...@@ -74,10 +68,10 @@ private:
uint32_t mMaxChar; uint32_t mMaxChar;
// This vector has ownership of the bitsets and typeface objects. // This vector has ownership of the bitsets and typeface objects.
std::vector<FontInstance> mInstances; std::vector<FontFamily*> mFamilies;
// This vector contains pointers into mInstances // This vector contains pointers into mInstances
std::vector<const FontInstance*> mInstanceVec; std::vector<FontFamily*> mFamilyVec;
// These are offsets into mInstanceVec, one range per page // These are offsets into mInstanceVec, one range per page
std::vector<Range> mRanges; std::vector<Range> mRanges;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <utils/TypeHelpers.h> #include <utils/TypeHelpers.h>
#include <minikin/MinikinRefCounted.h> #include <minikin/MinikinRefCounted.h>
#include <minikin/SparseBitSet.h>
namespace android { namespace android {
...@@ -139,6 +140,9 @@ public: ...@@ -139,6 +140,9 @@ public:
size_t getNumFonts() const; size_t getNumFonts() const;
MinikinFont* getFont(size_t index) const; MinikinFont* getFont(size_t index) const;
FontStyle getStyle(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: private:
void addFontLocked(MinikinFont* typeface, FontStyle style); void addFontLocked(MinikinFont* typeface, FontStyle style);
...@@ -152,6 +156,9 @@ private: ...@@ -152,6 +156,9 @@ private:
FontLanguage mLang; FontLanguage mLang;
int mVariant; int mVariant;
std::vector<Font> mFonts; std::vector<Font> mFonts;
SparseBitSet mCoverage;
bool mCoverageValid;
}; };
} // namespace android } // namespace android
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include "unicode/unorm2.h" #include "unicode/unorm2.h"
#include "MinikinInternal.h" #include "MinikinInternal.h"
#include <minikin/CmapCoverage.h>
#include <minikin/FontCollection.h> #include <minikin/FontCollection.h>
using std::vector; using std::vector;
...@@ -54,28 +53,12 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) : ...@@ -54,28 +53,12 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) :
continue; continue;
} }
family->RefLocked(); family->RefLocked();
FontInstance dummy; mFamilies.push_back(family); // emplace_back would be better
mInstances.push_back(dummy); // emplace_back would be better const SparseBitSet* coverage = family->getCoverage();
FontInstance* instance = &mInstances.back(); mMaxChar = max(mMaxChar, coverage->length());
instance->mFamily = family; lastChar.push_back(coverage->nextSetBit(0));
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));
} }
nTypefaces = mInstances.size(); nTypefaces = mFamilies.size();
LOG_ALWAYS_FATAL_IF(nTypefaces == 0, LOG_ALWAYS_FATAL_IF(nTypefaces == 0,
"Font collection must have at least one valid typeface"); "Font collection must have at least one valid typeface");
size_t nPages = (mMaxChar + kPageMask) >> kLogCharsPerPage; size_t nPages = (mMaxChar + kPageMask) >> kLogCharsPerPage;
...@@ -90,10 +73,10 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) : ...@@ -90,10 +73,10 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) :
range->start = offset; range->start = offset;
for (size_t j = 0; j < nTypefaces; j++) { for (size_t j = 0; j < nTypefaces; j++) {
if (lastChar[j] < (i + 1) << kLogCharsPerPage) { if (lastChar[j] < (i + 1) << kLogCharsPerPage) {
const FontInstance* instance = &mInstances[j]; FontFamily* family = mFamilies[j];
mInstanceVec.push_back(instance); mFamilyVec.push_back(family);
offset++; offset++;
uint32_t nextChar = instance->mCoverage->nextSetBit((i + 1) << kLogCharsPerPage); uint32_t nextChar = family->getCoverage()->nextSetBit((i + 1) << kLogCharsPerPage);
#ifdef VERBOSE_DEBUG #ifdef VERBOSE_DEBUG
ALOGD("nextChar = %d (j = %d)\n", nextChar, j); ALOGD("nextChar = %d (j = %d)\n", nextChar, j);
#endif #endif
...@@ -105,9 +88,8 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) : ...@@ -105,9 +88,8 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) :
} }
FontCollection::~FontCollection() { FontCollection::~FontCollection() {
for (size_t i = 0; i < mInstances.size(); i++) { for (size_t i = 0; i < mFamilies.size(); i++) {
delete mInstances[i].mCoverage; mFamilies[i]->UnrefLocked();
mInstances[i].mFamily->UnrefLocked();
} }
} }
...@@ -117,7 +99,7 @@ FontCollection::~FontCollection() { ...@@ -117,7 +99,7 @@ FontCollection::~FontCollection() {
// 3. If a font matches just language, it gets a score of 2. // 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. // 4. Matching the "compact" or "elegant" variant adds one to the score.
// 5. Highest score wins, with ties resolved to the first font. // 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 { FontLanguage lang, int variant) const {
if (ch >= mMaxChar) { if (ch >= mMaxChar) {
return NULL; return NULL;
...@@ -126,15 +108,14 @@ const FontCollection::FontInstance* FontCollection::getInstanceForChar(uint32_t ...@@ -126,15 +108,14 @@ const FontCollection::FontInstance* FontCollection::getInstanceForChar(uint32_t
#ifdef VERBOSE_DEBUG #ifdef VERBOSE_DEBUG
ALOGD("querying range %d:%d\n", range.start, range.end); ALOGD("querying range %d:%d\n", range.start, range.end);
#endif #endif
const FontInstance* bestInstance = NULL; FontFamily* bestFamily = NULL;
int bestScore = -1; int bestScore = -1;
for (size_t i = range.start; i < range.end; i++) { for (size_t i = range.start; i < range.end; i++) {
const FontInstance* instance = mInstanceVec[i]; FontFamily* family = mFamilyVec[i];
if (instance->mCoverage->get(ch)) { if (family->getCoverage()->get(ch)) {
FontFamily* family = instance->mFamily;
// First font family in collection always matches // First font family in collection always matches
if (mInstances[0].mFamily == family) { if (mFamilies[0] == family) {
return instance; return family;
} }
int score = lang.match(family->lang()) * 2; int score = lang.match(family->lang()) * 2;
if (variant != 0 && variant == family->variant()) { if (variant != 0 && variant == family->variant()) {
...@@ -142,11 +123,11 @@ const FontCollection::FontInstance* FontCollection::getInstanceForChar(uint32_t ...@@ -142,11 +123,11 @@ const FontCollection::FontInstance* FontCollection::getInstanceForChar(uint32_t
} }
if (score > bestScore) { if (score > bestScore) {
bestScore = score; bestScore = score;
bestInstance = instance; bestFamily = family;
} }
} }
} }
if (bestInstance == NULL && !mInstanceVec.empty()) { if (bestFamily == NULL && !mFamilyVec.empty()) {
UErrorCode errorCode = U_ZERO_ERROR; UErrorCode errorCode = U_ZERO_ERROR;
const UNormalizer2* normalizer = unorm2_getNFDInstance(&errorCode); const UNormalizer2* normalizer = unorm2_getNFDInstance(&errorCode);
if (U_SUCCESS(errorCode)) { if (U_SUCCESS(errorCode)) {
...@@ -155,12 +136,12 @@ const FontCollection::FontInstance* FontCollection::getInstanceForChar(uint32_t ...@@ -155,12 +136,12 @@ const FontCollection::FontInstance* FontCollection::getInstanceForChar(uint32_t
if (U_SUCCESS(errorCode) && len > 0) { if (U_SUCCESS(errorCode) && len > 0) {
int off = 0; int off = 0;
U16_NEXT_UNSAFE(decomposed, off, ch); 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; const uint32_t NBSP = 0xa0;
...@@ -183,7 +164,7 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty ...@@ -183,7 +164,7 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
vector<Run>* result) const { vector<Run>* result) const {
FontLanguage lang = style.getLanguage(); FontLanguage lang = style.getLanguage();
int variant = style.getVariant(); int variant = style.getVariant();
const FontInstance* lastInstance = NULL; FontFamily* lastFamily = NULL;
Run* run = NULL; Run* run = NULL;
int nShorts; int nShorts;
for (size_t i = 0; i < string_size; i += 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 ...@@ -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 // Continue using existing font as long as it has coverage and is whitelisted
if (lastInstance == NULL if (lastFamily == NULL
|| !(isStickyWhitelisted(ch) && lastInstance->mCoverage->get(ch))) { || !(isStickyWhitelisted(ch) && lastFamily->getCoverage()->get(ch))) {
const FontInstance* instance = getInstanceForChar(ch, lang, variant); FontFamily* family = getFamilyForChar(ch, lang, variant);
if (i == 0 || instance != lastInstance) { if (i == 0 || family != lastFamily) {
size_t start = i; size_t start = i;
// Workaround for Emoji keycap until we implement per-cluster font // Workaround for Emoji keycap until we implement per-cluster font
// selection: if keycap is found in a different font that also // selection: if keycap is found in a different font that also
// supports previous char, attach previous char to the new run. // supports previous char, attach previous char to the new run.
// Only handles non-surrogate characters. // Only handles non-surrogate characters.
// Bug 7557244. // 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--; run->end--;
if (run->start == run->end) { if (run->start == run->end) {
result->pop_back(); result->pop_back();
...@@ -217,12 +198,12 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty ...@@ -217,12 +198,12 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
Run dummy; Run dummy;
result->push_back(dummy); result->push_back(dummy);
run = &result->back(); run = &result->back();
if (instance == NULL) { if (family == NULL) {
run->fakedFont.font = NULL; run->fakedFont.font = NULL;
} else { } else {
run->fakedFont = instance->mFamily->getClosestMatch(style); run->fakedFont = family->getClosestMatch(style);
} }
lastInstance = instance; lastFamily = family;
run->start = start; run->start = start;
} }
} }
...@@ -235,10 +216,10 @@ MinikinFont* FontCollection::baseFont(FontStyle style) { ...@@ -235,10 +216,10 @@ MinikinFont* FontCollection::baseFont(FontStyle style) {
} }
FakedFont FontCollection::baseFontFaked(FontStyle style) { FakedFont FontCollection::baseFontFaked(FontStyle style) {
if (mInstances.empty()) { if (mFamilies.empty()) {
return FakedFont(); return FakedFont();
} }
return mInstances[0].mFamily->getClosestMatch(style); return mFamilies[0]->getClosestMatch(style);
} }
uint32_t FontCollection::getId() const { uint32_t FontCollection::getId() const {
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "MinikinInternal.h" #include "MinikinInternal.h"
#include <minikin/MinikinFont.h> #include <minikin/MinikinFont.h>
#include <minikin/AnalyzeStyle.h> #include <minikin/AnalyzeStyle.h>
#include <minikin/CmapCoverage.h>
#include <minikin/FontFamily.h> #include <minikin/FontFamily.h>
#include <UniquePtr.h> #include <UniquePtr.h>
...@@ -128,6 +129,7 @@ void FontFamily::addFont(MinikinFont* typeface, FontStyle style) { ...@@ -128,6 +129,7 @@ void FontFamily::addFont(MinikinFont* typeface, FontStyle style) {
void FontFamily::addFontLocked(MinikinFont* typeface, FontStyle style) { typeface->RefLocked(); void FontFamily::addFontLocked(MinikinFont* typeface, FontStyle style) { typeface->RefLocked();
mFonts.push_back(Font(typeface, style)); mFonts.push_back(Font(typeface, style));
mCoverageValid = false;
} }
// Compute a matching metric between two styles - 0 is an exact match // Compute a matching metric between two styles - 0 is an exact match
...@@ -183,4 +185,23 @@ FontStyle FontFamily::getStyle(size_t index) const { ...@@ -183,4 +185,23 @@ FontStyle FontFamily::getStyle(size_t index) const {
return mFonts[index].style; 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 } // namespace android
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册