summaryrefslogtreecommitdiffstats
path: root/libs/minikin
diff options
context:
space:
mode:
authorRaph Levien <raph@google.com>2014-06-06 17:56:41 -0700
committerRaph Levien <raph@google.com>2014-06-10 11:59:29 -0700
commit9a5f713add8cfb91ac2c9ed5c917309053201ab6 (patch)
tree7d6be261f3a7d30b0d7f14a66b2ff5e290e1bc4f /libs/minikin
parent89566f0ada1cafe673efa064cde38467990235d4 (diff)
downloadandroid_frameworks_minikin-9a5f713add8cfb91ac2c9ed5c917309053201ab6.tar.gz
android_frameworks_minikin-9a5f713add8cfb91ac2c9ed5c917309053201ab6.tar.bz2
android_frameworks_minikin-9a5f713add8cfb91ac2c9ed5c917309053201ab6.zip
Support for fake bold and italics
This patch adds support for computing when fake bold and fake italics are needed (because the styles are requested but not provided by the matching FontFamily), and providing them as part of the layout result. Part of the fix for bug 15436379 Fake bold doesn't fully work (Minikin) Change-Id: I180c034b559837943673b5c272c8e890178dff0d
Diffstat (limited to 'libs/minikin')
-rw-r--r--libs/minikin/FontCollection.cpp15
-rw-r--r--libs/minikin/FontFamily.cpp21
-rw-r--r--libs/minikin/Layout.cpp22
3 files changed, 40 insertions, 18 deletions
diff --git a/libs/minikin/FontCollection.cpp b/libs/minikin/FontCollection.cpp
index c13670e..6115ecc 100644
--- a/libs/minikin/FontCollection.cpp
+++ b/libs/minikin/FontCollection.cpp
@@ -52,7 +52,7 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) :
FontInstance* instance = &mInstances.back();
instance->mFamily = family;
instance->mCoverage = new SparseBitSet;
- MinikinFont* typeface = family->getClosestMatch(defaultStyle);
+ MinikinFont* typeface = family->getClosestMatch(defaultStyle).font;
if (typeface == NULL) {
ALOGE("FontCollection: closest match was null");
// TODO: we shouldn't hit this, as there should be more robust
@@ -171,11 +171,9 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
result->push_back(dummy);
run = &result->back();
if (instance == NULL) {
- run->font = NULL; // maybe we should do something different here
+ run->fakedFont.font = NULL;
} else {
- run->font = instance->mFamily->getClosestMatch(style);
- // TODO: simplify refcounting (FontCollection lifetime dominates)
- run->font->RefLocked();
+ run->fakedFont = instance->mFamily->getClosestMatch(style);
}
lastInstance = instance;
run->start = i;
@@ -186,13 +184,16 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
}
MinikinFont* FontCollection::baseFont(FontStyle style) {
+ return baseFontFaked(style).font;
+}
+
+FakedFont FontCollection::baseFontFaked(FontStyle style) {
if (mInstances.empty()) {
- return NULL;
+ return FakedFont();
}
return mInstances[0].mFamily->getClosestMatch(style);
}
-
uint32_t FontCollection::getId() const {
return mId;
}
diff --git a/libs/minikin/FontFamily.cpp b/libs/minikin/FontFamily.cpp
index 0fb98ae..9106f63 100644
--- a/libs/minikin/FontFamily.cpp
+++ b/libs/minikin/FontFamily.cpp
@@ -109,7 +109,7 @@ void FontFamily::addFontLocked(MinikinFont* typeface, FontStyle style) { type
}
// Compute a matching metric between two styles - 0 is an exact match
-int computeMatch(FontStyle style1, FontStyle style2) {
+static int computeMatch(FontStyle style1, FontStyle style2) {
if (style1 == style2) return 0;
int score = abs(style1.getWeight() - style2.getWeight());
if (style1.getItalic() != style2.getItalic()) {
@@ -118,7 +118,15 @@ int computeMatch(FontStyle style1, FontStyle style2) {
return score;
}
-MinikinFont* FontFamily::getClosestMatch(FontStyle style) const {
+static FontFakery computeFakery(FontStyle wanted, FontStyle actual) {
+ // If desired weight is 2 or more grades higher than actual
+ // (for example, medium 500 -> bold 700), then select fake bold.
+ bool isFakeBold = (wanted.getWeight() - actual.getWeight()) >= 2;
+ bool isFakeItalic = wanted.getItalic() && !actual.getItalic();
+ return FontFakery(isFakeBold, isFakeItalic);
+}
+
+FakedFont FontFamily::getClosestMatch(FontStyle style) const {
const Font* bestFont = NULL;
int bestMatch = 0;
for (size_t i = 0; i < mFonts.size(); i++) {
@@ -129,7 +137,14 @@ MinikinFont* FontFamily::getClosestMatch(FontStyle style) const {
bestMatch = match;
}
}
- return bestFont == NULL ? NULL : bestFont->typeface;
+ FakedFont result;
+ if (bestFont == NULL) {
+ result.font = NULL;
+ } else {
+ result.font = bestFont->typeface;
+ result.fakery = computeFakery(style, bestFont->style);
+ }
+ return result;
}
size_t FontFamily::getNumFonts() const {
diff --git a/libs/minikin/Layout.cpp b/libs/minikin/Layout.cpp
index 3cab673..709393d 100644
--- a/libs/minikin/Layout.cpp
+++ b/libs/minikin/Layout.cpp
@@ -328,10 +328,10 @@ void Layout::dump() const {
}
}
-int Layout::findFace(MinikinFont* face, LayoutContext* ctx) {
+int Layout::findFace(FakedFont face, LayoutContext* ctx) {
unsigned int ix;
for (ix = 0; ix < mFaces.size(); ix++) {
- if (mFaces[ix] == face) {
+ if (mFaces[ix].font == face.font) {
return ix;
}
}
@@ -339,7 +339,7 @@ int Layout::findFace(MinikinFont* face, LayoutContext* ctx) {
// Note: ctx == NULL means we're copying from the cache, no need to create
// corresponding hb_font object.
if (ctx != NULL) {
- hb_font_t* font = create_hb_font(face, &ctx->paint);
+ hb_font_t* font = create_hb_font(face.font, &ctx->paint);
ctx->hbFonts.push_back(font);
}
return ix;
@@ -631,12 +631,13 @@ void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t
float y = 0;
for (size_t run_ix = 0; run_ix < items.size(); run_ix++) {
FontCollection::Run &run = items[run_ix];
- if (run.font == NULL) {
+ if (run.fakedFont.font == NULL) {
ALOGE("no font for run starting u+%04x length %d", buf[run.start], run.end - run.start);
continue;
}
- int font_ix = findFace(run.font, ctx);
- ctx->paint.font = mFaces[font_ix];
+ int font_ix = findFace(run.fakedFont, ctx);
+ ctx->paint.font = mFaces[font_ix].font;
+ ctx->paint.fakery = mFaces[font_ix].fakery;
hb_font_t* hbFont = ctx->hbFonts[font_ix];
#ifdef VERBOSE
std::cout << "Run " << run_ix << ", font " << font_ix <<
@@ -729,7 +730,7 @@ void Layout::draw(Bitmap* surface, int x0, int y0, float size) const {
*/
for (size_t i = 0; i < mGlyphs.size(); i++) {
const LayoutGlyph& glyph = mGlyphs[i];
- MinikinFont* mf = mFaces[glyph.font_ix];
+ MinikinFont* mf = mFaces[glyph.font_ix].font;
MinikinFontFreeType* face = static_cast<MinikinFontFreeType*>(mf);
GlyphBitmap glyphBitmap;
MinikinPaint paint;
@@ -754,7 +755,12 @@ size_t Layout::nGlyphs() const {
MinikinFont* Layout::getFont(int i) const {
const LayoutGlyph& glyph = mGlyphs[i];
- return mFaces[glyph.font_ix];
+ return mFaces[glyph.font_ix].font;
+}
+
+FontFakery Layout::getFakery(int i) const {
+ const LayoutGlyph& glyph = mGlyphs[i];
+ return mFaces[glyph.font_ix].fakery;
}
unsigned int Layout::getGlyphId(int i) const {