summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRicardo Cerqueira <ricardo@cyngn.com>2015-03-10 12:05:00 +0000
committerRicardo Cerqueira <ricardo@cyngn.com>2015-03-10 12:05:00 +0000
commiteff9f1e9373a61d65217fdfec3702d376a793978 (patch)
tree1de01efab8dc3c9ec5026fa93cfe3d60d0d5d217
parentc5d47d11e65f603a3e37ee876bc74751a30df592 (diff)
parent253320d25fccbb49621926d49dcf5ef64cf529c6 (diff)
downloadandroid_frameworks_minikin-eff9f1e9373a61d65217fdfec3702d376a793978.tar.gz
android_frameworks_minikin-eff9f1e9373a61d65217fdfec3702d376a793978.tar.bz2
android_frameworks_minikin-eff9f1e9373a61d65217fdfec3702d376a793978.zip
Merge tag 'android-5.1.0_r1' into HEADstaging/cm-12.1stable/cm-12.1-YOG3C
Android 5.1.0 release 1
-rw-r--r--include/minikin/FontCollection.h12
-rw-r--r--include/minikin/FontFamily.h7
-rw-r--r--libs/minikin/CmapCoverage.cpp23
-rw-r--r--libs/minikin/FontCollection.cpp83
-rw-r--r--libs/minikin/FontFamily.cpp21
5 files changed, 75 insertions, 71 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/CmapCoverage.cpp b/libs/minikin/CmapCoverage.cpp
index 4156d69..7503372 100644
--- a/libs/minikin/CmapCoverage.cpp
+++ b/libs/minikin/CmapCoverage.cpp
@@ -16,9 +16,8 @@
// Determine coverage of font given its raw "cmap" OpenType table
-#ifdef PRINTF_DEBUG
-#include <stdio.h>
-#endif
+#define LOG_TAG "Minikin"
+#include <cutils/log.h>
#include <vector>
using std::vector;
@@ -38,8 +37,8 @@ static uint32_t readU32(const uint8_t* data, size_t offset) {
}
static void addRange(vector<uint32_t> &coverage, uint32_t start, uint32_t end) {
-#ifdef PRINTF_DEBUG
- printf("adding range %d-%d\n", start, end);
+#ifdef VERBOSE_DEBUG
+ ALOGD("adding range %d-%d\n", start, end);
#endif
if (coverage.empty() || coverage.back() < start) {
coverage.push_back(start);
@@ -82,7 +81,8 @@ static bool getCoverageFormat4(vector<uint32_t>& coverage, const uint8_t* data,
uint32_t actualRangeOffset = kHeaderSize + 6 * segCount + rangeOffset +
(i + j - start) * 2;
if (actualRangeOffset + 2 > size) {
- return false;
+ // invalid rangeOffset is considered a "warning" by OpenType Sanitizer
+ continue;
}
int glyphId = readU16(data, actualRangeOffset);
if (glyphId != 0) {
@@ -146,8 +146,8 @@ bool CmapCoverage::getCoverage(SparseBitSet& coverage, const uint8_t* cmap_data,
bestTable = i;
}
}
-#ifdef PRINTF_DEBUG
- printf("best table = %d\n", bestTable);
+#ifdef VERBOSE_DEBUG
+ ALOGD("best table = %d\n", bestTable);
#endif
if (bestTable < 0) {
return false;
@@ -168,10 +168,11 @@ bool CmapCoverage::getCoverage(SparseBitSet& coverage, const uint8_t* cmap_data,
if (success) {
coverage.initFromRanges(&coverageVec.front(), coverageVec.size() >> 1);
}
-#ifdef PRINTF_DEBUG
- for (int i = 0; i < coverageVec.size(); i += 2) {
- printf("%x:%x\n", coverageVec[i], coverageVec[i + 1]);
+#ifdef VERBOSE_DEBUG
+ for (size_t i = 0; i < coverageVec.size(); i += 2) {
+ ALOGD("%x:%x\n", coverageVec[i], coverageVec[i + 1]);
}
+ ALOGD("success = %d", success);
#endif
return success;
}
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