summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/minikin/FontCollection.h23
-rw-r--r--include/minikin/FontFamily.h21
-rw-r--r--include/minikin/Layout.h5
-rw-r--r--include/minikin/MinikinFont.h2
-rw-r--r--libs/minikin/FontCollection.cpp15
-rw-r--r--libs/minikin/FontFamily.cpp21
-rw-r--r--libs/minikin/Layout.cpp22
7 files changed, 70 insertions, 39 deletions
diff --git a/include/minikin/FontCollection.h b/include/minikin/FontCollection.h
index 508a129..12700c6 100644
--- a/include/minikin/FontCollection.h
+++ b/include/minikin/FontCollection.h
@@ -32,24 +32,8 @@ public:
~FontCollection();
- class Run {
- public:
- // Do copy constructor, assignment, destructor so it can be used in vectors
- Run() : font(NULL) { }
- Run(const Run& other): font(other.font), start(other.start), end(other.end) {
- if (font) font->RefLocked();
- }
- Run& operator=(const Run& other) {
- if (other.font) other.font->RefLocked();
- if (font) font->UnrefLocked();
- font = other.font;
- start = other.start;
- end = other.end;
- return *this;
- }
- ~Run() { if (font) font->UnrefLocked(); }
-
- MinikinFont* font;
+ struct Run {
+ FakedFont fakedFont;
int start;
int end;
};
@@ -60,6 +44,9 @@ public:
// Get the base font for the given style, useful for font-wide metrics.
MinikinFont* baseFont(FontStyle style);
+ // Get base font with fakery information (fake bold could affect metrics)
+ FakedFont baseFontFaked(FontStyle style);
+
uint32_t getId() const;
private:
static const int kLogCharsPerPage = 8;
diff --git a/include/minikin/FontFamily.h b/include/minikin/FontFamily.h
index 6bdf5d6..060d167 100644
--- a/include/minikin/FontFamily.h
+++ b/include/minikin/FontFamily.h
@@ -94,6 +94,25 @@ inline hash_t hash_type(const FontStyle &style) {
return style.hash();
}
+// attributes representing transforms (fake bold, fake italic) to match styles
+class FontFakery {
+public:
+ FontFakery() : mFakeBold(false), mFakeItalic(false) { }
+ FontFakery(bool fakeBold, bool fakeItalic) : mFakeBold(fakeBold), mFakeItalic(fakeItalic) { }
+ // TODO: want to support graded fake bolding
+ bool isFakeBold() { return mFakeBold; }
+ bool isFakeItalic() { return mFakeItalic; }
+private:
+ bool mFakeBold;
+ bool mFakeItalic;
+};
+
+struct FakedFont {
+ // ownership is the enclosing FontCollection
+ MinikinFont* font;
+ FontFakery fakery;
+};
+
class FontFamily : public MinikinRefCounted {
public:
FontFamily() { }
@@ -107,7 +126,7 @@ public:
bool addFont(MinikinFont* typeface);
void addFont(MinikinFont* typeface, FontStyle style);
- MinikinFont* getClosestMatch(FontStyle style) const;
+ FakedFont getClosestMatch(FontStyle style) const;
FontLanguage lang() const { return mLang; }
int variant() const { return mVariant; }
diff --git a/include/minikin/Layout.h b/include/minikin/Layout.h
index 91b8ef6..1b91ad8 100644
--- a/include/minikin/Layout.h
+++ b/include/minikin/Layout.h
@@ -87,6 +87,7 @@ public:
size_t nGlyphs() const;
// Does not bump reference; ownership is still layout
MinikinFont *getFont(int i) const;
+ FontFakery getFakery(int i) const;
unsigned int getGlyphId(int i) const;
float getX(int i) const;
float getY(int i) const;
@@ -101,7 +102,7 @@ public:
private:
// Find a face in the mFaces vector, or create a new entry
- int findFace(MinikinFont* face, LayoutContext* ctx);
+ int findFace(FakedFont face, LayoutContext* ctx);
// Lay out a single bidi run
void doLayoutRunCached(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
@@ -125,7 +126,7 @@ private:
std::vector<float> mAdvances;
const FontCollection* mCollection;
- std::vector<MinikinFont *> mFaces;
+ std::vector<FakedFont> mFaces;
float mAdvance;
MinikinRect mBounds;
};
diff --git a/include/minikin/MinikinFont.h b/include/minikin/MinikinFont.h
index 9ff08a9..7915ef2 100644
--- a/include/minikin/MinikinFont.h
+++ b/include/minikin/MinikinFont.h
@@ -18,6 +18,7 @@
#define MINIKIN_FONT_H
#include <minikin/MinikinRefCounted.h>
+#include <minikin/FontFamily.h>
// An abstraction for platform fonts, allowing Minikin to be used with
// multiple actual implementations of fonts.
@@ -34,6 +35,7 @@ struct MinikinPaint {
float scaleX;
float skewX;
uint32_t paintFlags;
+ FontFakery fakery;
};
struct MinikinRect {
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 {