提交 b1f1509a 编写于 作者: S Seigo Nonaka 提交者: Android (Google) Code Review

Merge "Remove MinikinRefCounted and use shared_ptr instead"

...@@ -17,20 +17,19 @@ ...@@ -17,20 +17,19 @@
#ifndef MINIKIN_FONT_COLLECTION_H #ifndef MINIKIN_FONT_COLLECTION_H
#define MINIKIN_FONT_COLLECTION_H #define MINIKIN_FONT_COLLECTION_H
#include <vector> #include <memory>
#include <unordered_set> #include <unordered_set>
#include <vector>
#include <minikin/MinikinRefCounted.h>
#include <minikin/MinikinFont.h> #include <minikin/MinikinFont.h>
#include <minikin/FontFamily.h> #include <minikin/FontFamily.h>
namespace minikin { namespace minikin {
class FontCollection : public MinikinRefCounted { class FontCollection {
public: public:
explicit FontCollection(const std::vector<FontFamily*>& typefaces); explicit FontCollection(const std::vector<std::shared_ptr<FontFamily>>& typefaces);
explicit FontCollection(std::shared_ptr<FontFamily>&& typeface);
~FontCollection();
struct Run { struct Run {
FakedFont fakedFont; FakedFont fakedFont;
...@@ -46,15 +45,13 @@ public: ...@@ -46,15 +45,13 @@ public:
// selector pair, or invalid variation selector is passed. // selector pair, or invalid variation selector is passed.
bool hasVariationSelector(uint32_t baseCodepoint, uint32_t variationSelector) const; bool hasVariationSelector(uint32_t baseCodepoint, uint32_t variationSelector) const;
// 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) // Get base font with fakery information (fake bold could affect metrics)
FakedFont baseFontFaked(FontStyle style); FakedFont baseFontFaked(FontStyle style);
// Creates new FontCollection based on this collection while applying font variations. Returns // Creates new FontCollection based on this collection while applying font variations. Returns
// nullptr if none of variations apply to this collection. // nullptr if none of variations apply to this collection.
FontCollection* createCollectionWithVariation(const std::vector<FontVariation>& variations); std::shared_ptr<FontCollection>
createCollectionWithVariation(const std::vector<FontVariation>& variations);
uint32_t getId() const; uint32_t getId() const;
...@@ -67,12 +64,17 @@ private: ...@@ -67,12 +64,17 @@ private:
size_t end; size_t end;
}; };
FontFamily* getFamilyForChar(uint32_t ch, uint32_t vs, uint32_t langListId, int variant) const; // Initialize the FontCollection.
void init(const std::vector<std::shared_ptr<FontFamily>>& typefaces);
const std::shared_ptr<FontFamily>& getFamilyForChar(uint32_t ch, uint32_t vs,
uint32_t langListId, int variant) const;
uint32_t calcFamilyScore(uint32_t ch, uint32_t vs, int variant, uint32_t langListId, uint32_t calcFamilyScore(uint32_t ch, uint32_t vs, int variant, uint32_t langListId,
FontFamily* fontFamily) const; const std::shared_ptr<FontFamily>& fontFamily) const;
uint32_t calcCoverageScore(uint32_t ch, uint32_t vs, FontFamily* fontFamily) const; uint32_t calcCoverageScore(uint32_t ch, uint32_t vs,
const std::shared_ptr<FontFamily>& fontFamily) const;
static uint32_t calcLanguageMatchingScore(uint32_t userLangListId, static uint32_t calcLanguageMatchingScore(uint32_t userLangListId,
const FontFamily& fontFamily); const FontFamily& fontFamily);
...@@ -88,19 +90,19 @@ private: ...@@ -88,19 +90,19 @@ private:
// Highest UTF-32 code point that can be mapped // Highest UTF-32 code point that can be mapped
uint32_t mMaxChar; uint32_t mMaxChar;
// This vector has ownership of the bitsets and typeface objects. // This vector has pointers to the all font family instances in this collection.
// This vector can't be empty. // This vector can't be empty.
std::vector<FontFamily*> mFamilies; std::vector<std::shared_ptr<FontFamily>> mFamilies;
// This vector contains pointers into mInstances // Following two vectors are pre-calculated tables for resolving coverage faster.
// This vector can't be empty. // For example, to iterate over all fonts which support Unicode code point U+XXYYZZ,
std::vector<FontFamily*> mFamilyVec; // iterate font families from mFamilyVec[mRanges[0xXXYY].start] to
// mFamilyVec[mRange[0xXXYY].end] instead of whole mFamilies.
// This vector has pointers to the font family instance which has cmap 14 subtable.
std::vector<FontFamily*> mVSFamilyVec;
// These are offsets into mInstanceVec, one range per page
std::vector<Range> mRanges; std::vector<Range> mRanges;
std::vector<std::shared_ptr<FontFamily>> mFamilyVec;
// This vector has pointers to the font family instances which have cmap 14 subtables.
std::vector<std::shared_ptr<FontFamily>> mVSFamilyVec;
// Set of supported axes in this collection. // Set of supported axes in this collection.
std::unordered_set<AxisTag> mSupportedAxes; std::unordered_set<AxisTag> mSupportedAxes;
......
...@@ -17,14 +17,15 @@ ...@@ -17,14 +17,15 @@
#ifndef MINIKIN_FONT_FAMILY_H #ifndef MINIKIN_FONT_FAMILY_H
#define MINIKIN_FONT_FAMILY_H #define MINIKIN_FONT_FAMILY_H
#include <vector> #include <memory>
#include <string> #include <string>
#include <unordered_set> #include <unordered_set>
#include <vector>
#include <hb.h> #include <hb.h>
#include <utils/TypeHelpers.h> #include <utils/TypeHelpers.h>
#include <minikin/MinikinRefCounted.h>
#include <minikin/SparseBitSet.h> #include <minikin/SparseBitSet.h>
namespace minikin { namespace minikin {
...@@ -102,19 +103,17 @@ struct FakedFont { ...@@ -102,19 +103,17 @@ struct FakedFont {
typedef uint32_t AxisTag; typedef uint32_t AxisTag;
struct Font { struct Font {
Font(MinikinFont* typeface, FontStyle style); Font(const std::shared_ptr<MinikinFont>& typeface, FontStyle style);
Font(std::shared_ptr<MinikinFont>&& typeface, FontStyle style);
Font(Font&& o); Font(Font&& o);
Font(const Font& o); Font(const Font& o);
~Font();
MinikinFont* typeface; std::shared_ptr<MinikinFont> typeface;
FontStyle style; FontStyle style;
std::unordered_set<AxisTag> supportedAxes; std::unordered_set<AxisTag> supportedAxes;
// TODO: remove this weird function. http://b/28119474 private:
// MinikinFont requres mutex lock for destruction, but the mutex lock is not void loadAxes();
// visible from outside of minikin library.
static void clearElementsWithLock(std::vector<minikin::Font>* fonts);
}; };
struct FontVariation { struct FontVariation {
...@@ -123,7 +122,7 @@ struct FontVariation { ...@@ -123,7 +122,7 @@ struct FontVariation {
float value; float value;
}; };
class FontFamily : public MinikinRefCounted { class FontFamily {
public: public:
explicit FontFamily(std::vector<Font>&& fonts); explicit FontFamily(std::vector<Font>&& fonts);
FontFamily(int variant, std::vector<Font>&& fonts); FontFamily(int variant, std::vector<Font>&& fonts);
...@@ -132,8 +131,8 @@ public: ...@@ -132,8 +131,8 @@ public:
~FontFamily(); ~FontFamily();
// TODO: Good to expose FontUtil.h. // TODO: Good to expose FontUtil.h.
static bool analyzeStyle(MinikinFont* typeface, int* weight, bool* italic); static bool analyzeStyle(const std::shared_ptr<MinikinFont>& typeface, int* weight,
bool* italic);
FakedFont getClosestMatch(FontStyle style) const; FakedFont getClosestMatch(FontStyle style) const;
uint32_t langId() const { return mLangId; } uint32_t langId() const { return mLangId; }
...@@ -141,7 +140,9 @@ public: ...@@ -141,7 +140,9 @@ public:
// API's for enumerating the fonts in a family. These don't guarantee any particular order // API's for enumerating the fonts in a family. These don't guarantee any particular order
size_t getNumFonts() const { return mFonts.size(); } size_t getNumFonts() const { return mFonts.size(); }
MinikinFont* getFont(size_t index) const { return mFonts[index].typeface; } const std::shared_ptr<MinikinFont>& getFont(size_t index) const {
return mFonts[index].typeface;
}
FontStyle getStyle(size_t index) const { return mFonts[index].style; } FontStyle getStyle(size_t index) const { return mFonts[index].style; }
bool isColorEmojiFamily() const; bool isColorEmojiFamily() const;
const std::unordered_set<AxisTag>& supportedAxes() const { return mSupportedAxes; } const std::unordered_set<AxisTag>& supportedAxes() const { return mSupportedAxes; }
...@@ -158,7 +159,8 @@ public: ...@@ -158,7 +159,8 @@ public:
// Creates new FontFamily based on this family while applying font variations. Returns nullptr // Creates new FontFamily based on this family while applying font variations. Returns nullptr
// if none of variations apply to this family. // if none of variations apply to this family.
FontFamily* createFamilyWithVariation(const std::vector<FontVariation>& variations) const; std::shared_ptr<FontFamily> createFamilyWithVariation(
const std::vector<FontVariation>& variations) const;
private: private:
void computeCoverage(); void computeCoverage();
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <hb.h> #include <hb.h>
#include <memory>
#include <vector> #include <vector>
#include <minikin/FontCollection.h> #include <minikin/FontCollection.h>
...@@ -71,37 +72,34 @@ enum { ...@@ -71,37 +72,34 @@ enum {
// Lifecycle and threading assumptions for Layout: // Lifecycle and threading assumptions for Layout:
// The object is assumed to be owned by a single thread; multiple threads // The object is assumed to be owned by a single thread; multiple threads
// may not mutate it at the same time. // may not mutate it at the same time.
// The lifetime of the FontCollection set through setFontCollection must
// extend through the lifetime of the Layout object.
class Layout { class Layout {
public: public:
Layout() : mGlyphs(), mAdvances(), mCollection(0), mFaces(), mAdvance(0), mBounds() { Layout(const std::shared_ptr<FontCollection>& collection)
: mGlyphs(), mAdvances(), mCollection(collection), mFaces(), mAdvance(0), mBounds() {
mBounds.setEmpty(); mBounds.setEmpty();
} }
// Clears layout, ready to be used again Layout(Layout&& layout) = default;
void reset();
// Forbid copying and assignment.
Layout(const Layout&) = delete;
void operator=(const Layout&) = delete;
void dump() const; void dump() const;
void setFontCollection(const FontCollection* collection);
void doLayout(const uint16_t* buf, size_t start, size_t count, size_t bufSize, void doLayout(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
int bidiFlags, const FontStyle &style, const MinikinPaint &paint); int bidiFlags, const FontStyle &style, const MinikinPaint &paint);
static float measureText(const uint16_t* buf, size_t start, size_t count, size_t bufSize, static float measureText(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
int bidiFlags, const FontStyle &style, const MinikinPaint &paint, int bidiFlags, const FontStyle &style, const MinikinPaint &paint,
const FontCollection* collection, float* advances); const std::shared_ptr<FontCollection>& collection, float* advances);
void draw(minikin::Bitmap*, int x0, int y0, float size) const; void draw(minikin::Bitmap*, int x0, int y0, float size) const;
// Deprecated. Nont needed. Remove when callers are removed.
static void init();
// public accessors // public accessors
size_t nGlyphs() const; size_t nGlyphs() const;
// Does not bump reference; ownership is still layout const MinikinFont* getFont(int i) const;
MinikinFont *getFont(int i) const;
FontFakery getFakery(int i) const; FontFakery getFakery(int i) const;
unsigned int getGlyphId(int i) const; unsigned int getGlyphId(int i) const;
float getX(int i) const; float getX(int i) const;
...@@ -117,7 +115,7 @@ public: ...@@ -117,7 +115,7 @@ public:
// start and count are the parameters to doLayout // start and count are the parameters to doLayout
float getCharAdvance(size_t i) const { return mAdvances[i]; } float getCharAdvance(size_t i) const { return mAdvances[i]; }
void getBounds(MinikinRect* rect); void getBounds(MinikinRect* rect) const;
// Purge all caches, useful in low memory conditions // Purge all caches, useful in low memory conditions
static void purgeCaches(); static void purgeCaches();
...@@ -126,19 +124,22 @@ private: ...@@ -126,19 +124,22 @@ private:
friend class LayoutCacheKey; friend class LayoutCacheKey;
// Find a face in the mFaces vector, or create a new entry // Find a face in the mFaces vector, or create a new entry
int findFace(FakedFont face, LayoutContext* ctx); int findFace(const FakedFont& face, LayoutContext* ctx);
// Clears layout, ready to be used again
void reset();
// Lay out a single bidi run // Lay out a single bidi run
// When layout is not null, layout info will be stored in the object. // When layout is not null, layout info will be stored in the object.
// When advances is not null, measurement results will be stored in the array. // When advances is not null, measurement results will be stored in the array.
static float doLayoutRunCached(const uint16_t* buf, size_t runStart, size_t runLength, static float doLayoutRunCached(const uint16_t* buf, size_t runStart, size_t runLength,
size_t bufSize, bool isRtl, LayoutContext* ctx, size_t dstStart, size_t bufSize, bool isRtl, LayoutContext* ctx, size_t dstStart,
const FontCollection* collection, Layout* layout, float* advances); const std::shared_ptr<FontCollection>& collection, Layout* layout, float* advances);
// Lay out a single word // Lay out a single word
static float doLayoutWord(const uint16_t* buf, size_t start, size_t count, size_t bufSize, static float doLayoutWord(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
bool isRtl, LayoutContext* ctx, size_t bufStart, const FontCollection* collection, bool isRtl, LayoutContext* ctx, size_t bufStart,
Layout* layout, float* advances); const std::shared_ptr<FontCollection>& collection, Layout* layout, float* advances);
// Lay out a single bidi run // Lay out a single bidi run
void doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t bufSize, void doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
...@@ -150,7 +151,7 @@ private: ...@@ -150,7 +151,7 @@ private:
std::vector<LayoutGlyph> mGlyphs; std::vector<LayoutGlyph> mGlyphs;
std::vector<float> mAdvances; std::vector<float> mAdvances;
const FontCollection* mCollection; std::shared_ptr<FontCollection> mCollection;
std::vector<FakedFont> mFaces; std::vector<FakedFont> mFaces;
float mAdvance; float mAdvance;
MinikinRect mBounds; MinikinRect mBounds;
......
...@@ -159,8 +159,8 @@ class LineBreaker { ...@@ -159,8 +159,8 @@ class LineBreaker {
// Minikin to do the shaping of the strings. The main thing that would need to be changed // Minikin to do the shaping of the strings. The main thing that would need to be changed
// is having some kind of callback (or virtual class, or maybe even template), which could // is having some kind of callback (or virtual class, or maybe even template), which could
// easily be instantiated with Minikin's Layout. Future work for when needed. // easily be instantiated with Minikin's Layout. Future work for when needed.
float addStyleRun(MinikinPaint* paint, const FontCollection* typeface, FontStyle style, float addStyleRun(MinikinPaint* paint, const std::shared_ptr<FontCollection>& typeface,
size_t start, size_t end, bool isRtl); FontStyle style, size_t start, size_t end, bool isRtl);
void addReplacement(size_t start, size_t end, float width); void addReplacement(size_t start, size_t end, float width);
......
...@@ -18,8 +18,8 @@ ...@@ -18,8 +18,8 @@
#define MINIKIN_FONT_H #define MINIKIN_FONT_H
#include <string> #include <string>
#include <memory>
#include <minikin/MinikinRefCounted.h>
#include <minikin/FontFamily.h> #include <minikin/FontFamily.h>
// An abstraction for platform fonts, allowing Minikin to be used with // An abstraction for platform fonts, allowing Minikin to be used with
...@@ -45,7 +45,7 @@ class MinikinFont; ...@@ -45,7 +45,7 @@ class MinikinFont;
// Possibly move into own .h file? // Possibly move into own .h file?
// Note: if you add a field here, either add it to LayoutCacheKey or to skipCache() // Note: if you add a field here, either add it to LayoutCacheKey or to skipCache()
struct MinikinPaint { struct MinikinPaint {
MinikinPaint() : font(0), size(0), scaleX(0), skewX(0), letterSpacing(0), wordSpacing(0), MinikinPaint() : font(nullptr), size(0), scaleX(0), skewX(0), letterSpacing(0), wordSpacing(0),
paintFlags(0), fakery(), hyphenEdit(), fontFeatureSettings() { } paintFlags(0), fakery(), hyphenEdit(), fontFeatureSettings() { }
bool skipCache() const { bool skipCache() const {
...@@ -98,7 +98,7 @@ class MinikinFontFreeType; ...@@ -98,7 +98,7 @@ class MinikinFontFreeType;
// Callback for freeing data // Callback for freeing data
typedef void (*MinikinDestroyFunc) (void* data); typedef void (*MinikinDestroyFunc) (void* data);
class MinikinFont : public MinikinRefCounted { class MinikinFont {
public: public:
explicit MinikinFont(int32_t uniqueId) : mUniqueId(uniqueId) {} explicit MinikinFont(int32_t uniqueId) : mUniqueId(uniqueId) {}
...@@ -128,7 +128,8 @@ public: ...@@ -128,7 +128,8 @@ public:
virtual const std::vector<minikin::FontVariation>& GetAxes() const = 0; virtual const std::vector<minikin::FontVariation>& GetAxes() const = 0;
virtual MinikinFont* createFontWithVariation(const std::vector<FontVariation>&) const { virtual std::shared_ptr<MinikinFont> createFontWithVariation(
const std::vector<FontVariation>&) const {
return nullptr; return nullptr;
} }
......
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Base class for reference counted objects in Minikin
#ifndef MINIKIN_REF_COUNTED_H
#define MINIKIN_REF_COUNTED_H
namespace minikin {
class MinikinRefCounted {
public:
void RefLocked() { mRefcount_++; }
void UnrefLocked() { if (--mRefcount_ == 0) { delete this; } }
// These refcount operations take the global lock.
void Ref();
void Unref();
MinikinRefCounted() : mRefcount_(1) { }
virtual ~MinikinRefCounted() { };
private:
int mRefcount_;
};
// An RAII container for reference counted objects.
// Note: this is only suitable for clients which are _not_ holding the global lock.
template <typename T>
class MinikinAutoUnref {
public:
explicit MinikinAutoUnref(T* obj) : mObj(obj) {
}
~MinikinAutoUnref() {
mObj->Unref();
}
T& operator*() const { return *mObj; }
T* operator->() const { return mObj; }
T* get() const { return mObj; }
private:
T* mObj;
};
} // namespace minikin
#endif // MINIKIN_REF_COUNTED_H
...@@ -44,7 +44,6 @@ minikin_src_files := \ ...@@ -44,7 +44,6 @@ minikin_src_files := \
LineBreaker.cpp \ LineBreaker.cpp \
Measurement.cpp \ Measurement.cpp \
MinikinInternal.cpp \ MinikinInternal.cpp \
MinikinRefCounted.cpp \
MinikinFont.cpp \ MinikinFont.cpp \
MinikinFontFreeType.cpp \ MinikinFontFreeType.cpp \
SparseBitSet.cpp \ SparseBitSet.cpp \
......
...@@ -79,8 +79,18 @@ static bool isEmojiStyleVSBase(uint32_t cp) { ...@@ -79,8 +79,18 @@ static bool isEmojiStyleVSBase(uint32_t cp) {
uint32_t FontCollection::sNextId = 0; uint32_t FontCollection::sNextId = 0;
FontCollection::FontCollection(const vector<FontFamily*>& typefaces) : FontCollection::FontCollection(std::shared_ptr<FontFamily>&& typeface) : mMaxChar(0) {
std::vector<std::shared_ptr<FontFamily>> typefaces;
typefaces.push_back(typeface);
init(typefaces);
}
FontCollection::FontCollection(const vector<std::shared_ptr<FontFamily>>& typefaces) :
mMaxChar(0) { mMaxChar(0) {
init(typefaces);
}
void FontCollection::init(const vector<std::shared_ptr<FontFamily>>& typefaces) {
android::AutoMutex _l(gMinikinLock); android::AutoMutex _l(gMinikinLock);
mId = sNextId++; mId = sNextId++;
vector<uint32_t> lastChar; vector<uint32_t> lastChar;
...@@ -90,12 +100,10 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) : ...@@ -90,12 +100,10 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) :
#endif #endif
const FontStyle defaultStyle; const FontStyle defaultStyle;
for (size_t i = 0; i < nTypefaces; i++) { for (size_t i = 0; i < nTypefaces; i++) {
FontFamily* family = typefaces[i]; const std::shared_ptr<FontFamily>& family = typefaces[i];
MinikinFont* typeface = family->getClosestMatch(defaultStyle).font; if (family->getClosestMatch(defaultStyle).font == nullptr) {
if (typeface == NULL) {
continue; continue;
} }
family->RefLocked();
const SparseBitSet& coverage = family->getCoverage(); const SparseBitSet& coverage = family->getCoverage();
mFamilies.push_back(family); // emplace_back would be better mFamilies.push_back(family); // emplace_back would be better
if (family->hasVSTable()) { if (family->hasVSTable()) {
...@@ -126,7 +134,7 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) : ...@@ -126,7 +134,7 @@ 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) {
FontFamily* family = mFamilies[j]; const std::shared_ptr<FontFamily>& family = mFamilies[j];
mFamilyVec.push_back(family); mFamilyVec.push_back(family);
offset++; offset++;
uint32_t nextChar = family->getCoverage().nextSetBit((i + 1) << kLogCharsPerPage); uint32_t nextChar = family->getCoverage().nextSetBit((i + 1) << kLogCharsPerPage);
...@@ -140,12 +148,6 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) : ...@@ -140,12 +148,6 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) :
} }
} }
FontCollection::~FontCollection() {
for (size_t i = 0; i < mFamilies.size(); i++) {
mFamilies[i]->UnrefLocked();
}
}
// Special scores for the font fallback. // Special scores for the font fallback.
const uint32_t kUnsupportedFontScore = 0; const uint32_t kUnsupportedFontScore = 0;
const uint32_t kFirstFontScore = UINT32_MAX; const uint32_t kFirstFontScore = UINT32_MAX;
...@@ -167,7 +169,7 @@ const uint32_t kFirstFontScore = UINT32_MAX; ...@@ -167,7 +169,7 @@ const uint32_t kFirstFontScore = UINT32_MAX;
// - kFirstFontScore: When the font is the first font family in the collection and it supports the // - kFirstFontScore: When the font is the first font family in the collection and it supports the
// given character or variation sequence. // given character or variation sequence.
uint32_t FontCollection::calcFamilyScore(uint32_t ch, uint32_t vs, int variant, uint32_t langListId, uint32_t FontCollection::calcFamilyScore(uint32_t ch, uint32_t vs, int variant, uint32_t langListId,
FontFamily* fontFamily) const { const std::shared_ptr<FontFamily>& fontFamily) const {
const uint32_t coverageScore = calcCoverageScore(ch, vs, fontFamily); const uint32_t coverageScore = calcCoverageScore(ch, vs, fontFamily);
if (coverageScore == kFirstFontScore || coverageScore == kUnsupportedFontScore) { if (coverageScore == kFirstFontScore || coverageScore == kUnsupportedFontScore) {
...@@ -194,7 +196,8 @@ uint32_t FontCollection::calcFamilyScore(uint32_t ch, uint32_t vs, int variant, ...@@ -194,7 +196,8 @@ uint32_t FontCollection::calcFamilyScore(uint32_t ch, uint32_t vs, int variant,
// - Returns 2 if the vs is a text variation selector (U+FE0E) and if the font is not an emoji font. // - Returns 2 if the vs is a text variation selector (U+FE0E) and if the font is not an emoji font.
// - Returns 1 if the variation selector is not specified or if the font family only supports the // - Returns 1 if the variation selector is not specified or if the font family only supports the
// variation sequence's base character. // variation sequence's base character.
uint32_t FontCollection::calcCoverageScore(uint32_t ch, uint32_t vs, FontFamily* fontFamily) const { uint32_t FontCollection::calcCoverageScore(uint32_t ch, uint32_t vs,
const std::shared_ptr<FontFamily>& fontFamily) const {
const bool hasVSGlyph = (vs != 0) && fontFamily->hasGlyph(ch, vs); const bool hasVSGlyph = (vs != 0) && fontFamily->hasGlyph(ch, vs);
if (!hasVSGlyph && !fontFamily->getCoverage().get(ch)) { if (!hasVSGlyph && !fontFamily->getCoverage().get(ch)) {
// The font doesn't support either variation sequence or even the base character. // The font doesn't support either variation sequence or even the base character.
...@@ -277,13 +280,13 @@ uint32_t FontCollection::calcVariantMatchingScore(int variant, const FontFamily& ...@@ -277,13 +280,13 @@ uint32_t FontCollection::calcVariantMatchingScore(int variant, const FontFamily&
// 2. Calculate a score for the font family. See comments in calcFamilyScore for the detail. // 2. Calculate a score for the font family. See comments in calcFamilyScore for the detail.
// 3. Highest score wins, with ties resolved to the first font. // 3. Highest score wins, with ties resolved to the first font.
// This method never returns nullptr. // This method never returns nullptr.
FontFamily* FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs, const std::shared_ptr<FontFamily>& FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs,
uint32_t langListId, int variant) const { uint32_t langListId, int variant) const {
if (ch >= mMaxChar) { if (ch >= mMaxChar) {
return mFamilies[0]; return mFamilies[0];
} }
const std::vector<FontFamily*>& familyVec = (vs == 0) ? mFamilyVec : mFamilies; const std::vector<std::shared_ptr<FontFamily>>& familyVec = (vs == 0) ? mFamilyVec : mFamilies;
Range range = mRanges[ch >> kLogCharsPerPage]; Range range = mRanges[ch >> kLogCharsPerPage];
if (vs != 0) { if (vs != 0) {
...@@ -293,10 +296,10 @@ FontFamily* FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs, ...@@ -293,10 +296,10 @@ FontFamily* FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs,
#ifdef VERBOSE_DEBUG #ifdef VERBOSE_DEBUG
ALOGD("querying range %zd:%zd\n", range.start, range.end); ALOGD("querying range %zd:%zd\n", range.start, range.end);
#endif #endif
FontFamily* bestFamily = nullptr; int bestFamilyIndex = -1;
uint32_t bestScore = kUnsupportedFontScore; uint32_t bestScore = kUnsupportedFontScore;
for (size_t i = range.start; i < range.end; i++) { for (size_t i = range.start; i < range.end; i++) {
FontFamily* family = familyVec[i]; const std::shared_ptr<FontFamily>& family = familyVec[i];
const uint32_t score = calcFamilyScore(ch, vs, variant, langListId, family); const uint32_t score = calcFamilyScore(ch, vs, variant, langListId, family);
if (score == kFirstFontScore) { if (score == kFirstFontScore) {
// If the first font family supports the given character or variation sequence, always // If the first font family supports the given character or variation sequence, always
...@@ -305,10 +308,10 @@ FontFamily* FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs, ...@@ -305,10 +308,10 @@ FontFamily* FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs,
} }
if (score > bestScore) { if (score > bestScore) {
bestScore = score; bestScore = score;
bestFamily = family; bestFamilyIndex = i;
} }
} }
if (bestFamily == nullptr) { if (bestFamilyIndex == -1) {
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)) {
...@@ -320,9 +323,9 @@ FontFamily* FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs, ...@@ -320,9 +323,9 @@ FontFamily* FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs,
return getFamilyForChar(ch, vs, langListId, variant); return getFamilyForChar(ch, vs, langListId, variant);
} }
} }
bestFamily = mFamilies[0]; return mFamilies[0];
} }
return bestFamily; return familyVec[bestFamilyIndex];
} }
const uint32_t NBSP = 0xA0; const uint32_t NBSP = 0xA0;
...@@ -375,7 +378,7 @@ bool FontCollection::hasVariationSelector(uint32_t baseCodepoint, ...@@ -375,7 +378,7 @@ bool FontCollection::hasVariationSelector(uint32_t baseCodepoint,
if (isEmojiStyleVSBase(baseCodepoint) && variationSelector == TEXT_STYLE_VS) { if (isEmojiStyleVSBase(baseCodepoint) && variationSelector == TEXT_STYLE_VS) {
for (size_t i = 0; i < mFamilies.size(); ++i) { for (size_t i = 0; i < mFamilies.size(); ++i) {
if (!mFamilies[i]->isColorEmojiFamily() && variationSelector == TEXT_STYLE_VS && if (!mFamilies[i]->isColorEmojiFamily() && variationSelector == TEXT_STYLE_VS &&
mFamilies[i]->hasGlyph(baseCodepoint, 0)) { mFamilies[i]->hasGlyph(baseCodepoint, 0)) {
return true; return true;
} }
} }
...@@ -388,7 +391,7 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty ...@@ -388,7 +391,7 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
vector<Run>* result) const { vector<Run>* result) const {
const uint32_t langListId = style.getLanguageListId(); const uint32_t langListId = style.getLanguageListId();
int variant = style.getVariant(); int variant = style.getVariant();
FontFamily* lastFamily = NULL; const FontFamily* lastFamily = nullptr;
Run* run = NULL; Run* run = NULL;
if (string_size == 0) { if (string_size == 0) {
...@@ -425,9 +428,9 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty ...@@ -425,9 +428,9 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
} }
if (!shouldContinueRun) { if (!shouldContinueRun) {
FontFamily* family = getFamilyForChar(ch, isVariationSelector(nextCh) ? nextCh : 0, const std::shared_ptr<FontFamily>& family = getFamilyForChar(
langListId, variant); ch, isVariationSelector(nextCh) ? nextCh : 0, langListId, variant);
if (utf16Pos == 0 || family != lastFamily) { if (utf16Pos == 0 || family.get() != lastFamily) {
size_t start = utf16Pos; size_t start = utf16Pos;
// Workaround for combining marks and emoji modifiers until we implement // Workaround for combining marks and emoji modifiers until we implement
// per-cluster font selection: if a combining mark or an emoji modifier is found in // per-cluster font selection: if a combining mark or an emoji modifier is found in
...@@ -437,7 +440,7 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty ...@@ -437,7 +440,7 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
if (utf16Pos != 0 && if (utf16Pos != 0 &&
((U_GET_GC_MASK(ch) & U_GC_M_MASK) != 0 || ((U_GET_GC_MASK(ch) & U_GC_M_MASK) != 0 ||
(isEmojiModifier(ch) && isEmojiBase(prevCh))) && (isEmojiModifier(ch) && isEmojiBase(prevCh))) &&
family && family->getCoverage().get(prevCh)) { family != nullptr && family->getCoverage().get(prevCh)) {
const size_t prevChLength = U16_LENGTH(prevCh); const size_t prevChLength = U16_LENGTH(prevCh);
run->end -= prevChLength; run->end -= prevChLength;
if (run->start == run->end) { if (run->start == run->end) {
...@@ -445,12 +448,9 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty ...@@ -445,12 +448,9 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
} }
start -= prevChLength; start -= prevChLength;
} }
Run dummy; result->push_back({family->getClosestMatch(style), static_cast<int>(start), 0});
result->push_back(dummy);
run = &result->back(); run = &result->back();
run->fakedFont = family->getClosestMatch(style); lastFamily = family.get();
lastFamily = family;
run->start = start;
} }
} }
prevCh = ch; prevCh = ch;
...@@ -458,15 +458,11 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty ...@@ -458,15 +458,11 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
} while (nextCh != kEndOfString); } while (nextCh != kEndOfString);
} }
MinikinFont* FontCollection::baseFont(FontStyle style) {
return baseFontFaked(style).font;
}
FakedFont FontCollection::baseFontFaked(FontStyle style) { FakedFont FontCollection::baseFontFaked(FontStyle style) {
return mFamilies[0]->getClosestMatch(style); return mFamilies[0]->getClosestMatch(style);
} }
FontCollection* FontCollection::createCollectionWithVariation( std::shared_ptr<FontCollection> FontCollection::createCollectionWithVariation(
const std::vector<FontVariation>& variations) { const std::vector<FontVariation>& variations) {
if (variations.empty() || mSupportedAxes.empty()) { if (variations.empty() || mSupportedAxes.empty()) {
return nullptr; return nullptr;
...@@ -484,22 +480,17 @@ FontCollection* FontCollection::createCollectionWithVariation( ...@@ -484,22 +480,17 @@ FontCollection* FontCollection::createCollectionWithVariation(
return nullptr; return nullptr;
} }
std::vector<FontFamily*> families; std::vector<std::shared_ptr<FontFamily> > families;
for (FontFamily* family : mFamilies) { for (const std::shared_ptr<FontFamily>& family : mFamilies) {
FontFamily* newFamily = family->createFamilyWithVariation(variations); std::shared_ptr<FontFamily> newFamily = family->createFamilyWithVariation(variations);
if (newFamily) { if (newFamily) {
families.push_back(newFamily); families.push_back(newFamily);
} else { } else {
family->Ref();
families.push_back(family); families.push_back(family);
} }
} }
FontCollection* result = new FontCollection(families); return std::shared_ptr<FontCollection>(new FontCollection(families));
for (FontFamily* family : families) {
family->Unref();
}
return result;
} }
uint32_t FontCollection::getId() const { uint32_t FontCollection::getId() const {
......
...@@ -65,13 +65,20 @@ uint32_t FontStyle::pack(int variant, int weight, bool italic) { ...@@ -65,13 +65,20 @@ uint32_t FontStyle::pack(int variant, int weight, bool italic) {
return (weight & kWeightMask) | (italic ? kItalicMask : 0) | (variant << kVariantShift); return (weight & kWeightMask) | (italic ? kItalicMask : 0) | (variant << kVariantShift);
} }
Font::Font(MinikinFont* typeface, FontStyle style) Font::Font(const std::shared_ptr<MinikinFont>& typeface, FontStyle style)
: typeface(typeface), style(style) { : typeface(typeface), style(style) {
android::AutoMutex _l(gMinikinLock); loadAxes();
typeface->RefLocked(); }
Font::Font(std::shared_ptr<MinikinFont>&& typeface, FontStyle style)
: typeface(typeface), style(style) {
loadAxes();
}
void Font::loadAxes() {
android::AutoMutex _l(gMinikinLock);
const uint32_t fvarTag = MinikinFont::MakeTag('f', 'v', 'a', 'r'); const uint32_t fvarTag = MinikinFont::MakeTag('f', 'v', 'a', 'r');
HbBlob fvarTable(getFontTable(typeface, fvarTag)); HbBlob fvarTable(getFontTable(typeface.get(), fvarTag));
if (fvarTable.size() == 0) { if (fvarTable.size() == 0) {
return; return;
} }
...@@ -80,7 +87,7 @@ Font::Font(MinikinFont* typeface, FontStyle style) ...@@ -80,7 +87,7 @@ Font::Font(MinikinFont* typeface, FontStyle style)
} }
Font::Font(Font&& o) { Font::Font(Font&& o) {
typeface = o.typeface; typeface = std::move(o.typeface);
style = o.style; style = o.style;
o.typeface = nullptr; o.typeface = nullptr;
supportedAxes = std::move(o.supportedAxes); supportedAxes = std::move(o.supportedAxes);
...@@ -88,23 +95,11 @@ Font::Font(Font&& o) { ...@@ -88,23 +95,11 @@ Font::Font(Font&& o) {
Font::Font(const Font& o) { Font::Font(const Font& o) {
typeface = o.typeface; typeface = o.typeface;
typeface->Ref();
style = o.style; style = o.style;
supportedAxes = o.supportedAxes; supportedAxes = o.supportedAxes;
} }
Font::~Font() { // static
if (typeface == nullptr) {
return;
}
typeface->UnrefLocked();
}
void Font::clearElementsWithLock(std::vector<minikin::Font>* fonts) {
android::AutoMutex _l(gMinikinLock);
fonts->clear();
}
FontFamily::FontFamily(std::vector<Font>&& fonts) : FontFamily(0 /* variant */, std::move(fonts)) { FontFamily::FontFamily(std::vector<Font>&& fonts) : FontFamily(0 /* variant */, std::move(fonts)) {
} }
...@@ -120,10 +115,11 @@ FontFamily::FontFamily(uint32_t langId, int variant, std::vector<Font>&& fonts) ...@@ -120,10 +115,11 @@ FontFamily::FontFamily(uint32_t langId, int variant, std::vector<Font>&& fonts)
FontFamily::~FontFamily() { FontFamily::~FontFamily() {
} }
bool FontFamily::analyzeStyle(MinikinFont* typeface, int* weight, bool* italic) { bool FontFamily::analyzeStyle(const std::shared_ptr<MinikinFont>& typeface, int* weight,
bool* italic) {
android::AutoMutex _l(gMinikinLock); android::AutoMutex _l(gMinikinLock);
const uint32_t os2Tag = MinikinFont::MakeTag('O', 'S', '/', '2'); const uint32_t os2Tag = MinikinFont::MakeTag('O', 'S', '/', '2');
HbBlob os2Table(getFontTable(typeface, os2Tag)); HbBlob os2Table(getFontTable(typeface.get(), os2Tag));
if (os2Table.get() == nullptr) return false; if (os2Table.get() == nullptr) return false;
return ::minikin::analyzeStyle(os2Table.get(), os2Table.size(), weight, italic); return ::minikin::analyzeStyle(os2Table.get(), os2Table.size(), weight, italic);
} }
...@@ -149,7 +145,7 @@ static FontFakery computeFakery(FontStyle wanted, FontStyle actual) { ...@@ -149,7 +145,7 @@ static FontFakery computeFakery(FontStyle wanted, FontStyle actual) {
} }
FakedFont FontFamily::getClosestMatch(FontStyle style) const { FakedFont FontFamily::getClosestMatch(FontStyle style) const {
const Font* bestFont = NULL; const Font* bestFont = nullptr;
int bestMatch = 0; int bestMatch = 0;
for (size_t i = 0; i < mFonts.size(); i++) { for (size_t i = 0; i < mFonts.size(); i++) {
const Font& font = mFonts[i]; const Font& font = mFonts[i];
...@@ -159,14 +155,10 @@ FakedFont FontFamily::getClosestMatch(FontStyle style) const { ...@@ -159,14 +155,10 @@ FakedFont FontFamily::getClosestMatch(FontStyle style) const {
bestMatch = match; bestMatch = match;
} }
} }
FakedFont result; if (bestFont != nullptr) {
if (bestFont == NULL) { return FakedFont{ bestFont->typeface.get(), computeFakery(style, bestFont->style) };
result.font = NULL;
} else {
result.font = bestFont->typeface;
result.fakery = computeFakery(style, bestFont->style);
} }
return result; return FakedFont{ nullptr, FontFakery() };
} }
bool FontFamily::isColorEmojiFamily() const { bool FontFamily::isColorEmojiFamily() const {
...@@ -182,7 +174,7 @@ bool FontFamily::isColorEmojiFamily() const { ...@@ -182,7 +174,7 @@ bool FontFamily::isColorEmojiFamily() const {
void FontFamily::computeCoverage() { void FontFamily::computeCoverage() {
android::AutoMutex _l(gMinikinLock); android::AutoMutex _l(gMinikinLock);
const FontStyle defaultStyle; const FontStyle defaultStyle;
MinikinFont* typeface = getClosestMatch(defaultStyle).font; const MinikinFont* typeface = getClosestMatch(defaultStyle).font;
const uint32_t cmapTag = MinikinFont::MakeTag('c', 'm', 'a', 'p'); const uint32_t cmapTag = MinikinFont::MakeTag('c', 'm', 'a', 'p');
HbBlob cmapTable(getFontTable(typeface, cmapTag)); HbBlob cmapTable(getFontTable(typeface, cmapTag));
if (cmapTable.get() == nullptr) { if (cmapTable.get() == nullptr) {
...@@ -206,15 +198,14 @@ bool FontFamily::hasGlyph(uint32_t codepoint, uint32_t variationSelector) const ...@@ -206,15 +198,14 @@ bool FontFamily::hasGlyph(uint32_t codepoint, uint32_t variationSelector) const
} }
const FontStyle defaultStyle; const FontStyle defaultStyle;
MinikinFont* minikinFont = getClosestMatch(defaultStyle).font; hb_font_t* font = getHbFontLocked(getClosestMatch(defaultStyle).font);
hb_font_t* font = getHbFontLocked(minikinFont);
uint32_t unusedGlyph; uint32_t unusedGlyph;
bool result = hb_font_get_glyph(font, codepoint, variationSelector, &unusedGlyph); bool result = hb_font_get_glyph(font, codepoint, variationSelector, &unusedGlyph);
hb_font_destroy(font); hb_font_destroy(font);
return result; return result;
} }
FontFamily* FontFamily::createFamilyWithVariation( std::shared_ptr<FontFamily> FontFamily::createFamilyWithVariation(
const std::vector<FontVariation>& variations) const { const std::vector<FontVariation>& variations) const {
if (variations.empty() || mSupportedAxes.empty()) { if (variations.empty() || mSupportedAxes.empty()) {
return nullptr; return nullptr;
...@@ -243,19 +234,17 @@ FontFamily* FontFamily::createFamilyWithVariation( ...@@ -243,19 +234,17 @@ FontFamily* FontFamily::createFamilyWithVariation(
} }
} }
} }
MinikinFont* minikinFont = nullptr; std::shared_ptr<MinikinFont> minikinFont;
if (supportedVariations) { if (supportedVariations) {
minikinFont = font.typeface->createFontWithVariation(variations); minikinFont = font.typeface->createFontWithVariation(variations);
} }
if (minikinFont == nullptr) { if (minikinFont == nullptr) {
minikinFont = font.typeface; minikinFont = font.typeface;
minikinFont->Ref();
} }
fonts.push_back(Font(minikinFont, font.style)); fonts.push_back(Font(std::move(minikinFont), font.style));
minikinFont->Unref();
} }
return new FontFamily(mLangId, mVariant, std::move(fonts)); return std::shared_ptr<FontFamily>(new FontFamily(mLangId, mVariant, std::move(fonts)));
} }
} // namespace minikin } // namespace minikin
...@@ -84,7 +84,7 @@ void purgeHbFontLocked(const MinikinFont* minikinFont) { ...@@ -84,7 +84,7 @@ void purgeHbFontLocked(const MinikinFont* minikinFont) {
// Returns a new reference to a hb_font_t object, caller is // Returns a new reference to a hb_font_t object, caller is
// responsible for calling hb_font_destroy() on it. // responsible for calling hb_font_destroy() on it.
hb_font_t* getHbFontLocked(MinikinFont* minikinFont) { hb_font_t* getHbFontLocked(const MinikinFont* minikinFont) {
assertMinikinLocked(); assertMinikinLocked();
// TODO: get rid of nullFaceFont // TODO: get rid of nullFaceFont
static hb_font_t* nullFaceFont = nullptr; static hb_font_t* nullFaceFont = nullptr;
......
...@@ -24,7 +24,7 @@ class MinikinFont; ...@@ -24,7 +24,7 @@ class MinikinFont;
void purgeHbFontCacheLocked(); void purgeHbFontCacheLocked();
void purgeHbFontLocked(const MinikinFont* minikinFont); void purgeHbFontLocked(const MinikinFont* minikinFont);
hb_font_t* getHbFontLocked(MinikinFont* minikinFont); hb_font_t* getHbFontLocked(const MinikinFont* minikinFont);
} // namespace minikin } // namespace minikin
#endif // MINIKIN_HBFONT_CACHE_H #endif // MINIKIN_HBFONT_CACHE_H
...@@ -104,8 +104,9 @@ struct LayoutContext { ...@@ -104,8 +104,9 @@ struct LayoutContext {
class LayoutCacheKey { class LayoutCacheKey {
public: public:
LayoutCacheKey(const FontCollection* collection, const MinikinPaint& paint, FontStyle style, LayoutCacheKey(const std::shared_ptr<FontCollection>& collection, const MinikinPaint& paint,
const uint16_t* chars, size_t start, size_t count, size_t nchars, bool dir) FontStyle style, const uint16_t* chars, size_t start, size_t count, size_t nchars,
bool dir)
: mChars(chars), mNchars(nchars), : mChars(chars), mNchars(nchars),
mStart(start), mCount(count), mId(collection->getId()), mStyle(style), mStart(start), mCount(count), mId(collection->getId()), mStyle(style),
mSize(paint.size), mScaleX(paint.scaleX), mSkewX(paint.skewX), mSize(paint.size), mScaleX(paint.scaleX), mSkewX(paint.skewX),
...@@ -129,8 +130,7 @@ public: ...@@ -129,8 +130,7 @@ public:
mChars = NULL; mChars = NULL;
} }
void doLayout(Layout* layout, LayoutContext* ctx, const FontCollection* collection) const { void doLayout(Layout* layout, LayoutContext* ctx) const {
layout->setFontCollection(collection);
layout->mAdvances.resize(mCount, 0); layout->mAdvances.resize(mCount, 0);
ctx->clearHbFonts(); ctx->clearHbFonts();
layout->doLayoutRun(mChars, mStart, mCount, mNchars, mIsRtl, ctx); layout->doLayoutRun(mChars, mStart, mCount, mNchars, mIsRtl, ctx);
...@@ -167,12 +167,13 @@ public: ...@@ -167,12 +167,13 @@ public:
mCache.clear(); mCache.clear();
} }
Layout* get(LayoutCacheKey& key, LayoutContext* ctx, const FontCollection* collection) { Layout* get(LayoutCacheKey& key, LayoutContext* ctx,
const std::shared_ptr<FontCollection>& collection) {
Layout* layout = mCache.get(key); Layout* layout = mCache.get(key);
if (layout == NULL) { if (layout == NULL) {
key.copyText(); key.copyText();
layout = new Layout(); layout = new Layout(collection);
key.doLayout(layout, ctx, collection); key.doLayout(layout, ctx);
mCache.put(key, layout); mCache.put(key, layout);
} }
return layout; return layout;
...@@ -262,10 +263,6 @@ void MinikinRect::join(const MinikinRect& r) { ...@@ -262,10 +263,6 @@ void MinikinRect::join(const MinikinRect& r) {
} }
} }
// Deprecated. Remove when callers are removed.
void Layout::init() {
}
void Layout::reset() { void Layout::reset() {
mGlyphs.clear(); mGlyphs.clear();
mFaces.clear(); mFaces.clear();
...@@ -274,15 +271,10 @@ void Layout::reset() { ...@@ -274,15 +271,10 @@ void Layout::reset() {
mAdvance = 0; mAdvance = 0;
} }
void Layout::setFontCollection(const FontCollection* collection) {
mCollection = collection;
}
static hb_position_t harfbuzzGetGlyphHorizontalAdvance(hb_font_t* /* hbFont */, void* fontData, static hb_position_t harfbuzzGetGlyphHorizontalAdvance(hb_font_t* /* hbFont */, void* fontData,
hb_codepoint_t glyph, void* /* userData */) { hb_codepoint_t glyph, void* /* userData */) {
MinikinPaint* paint = reinterpret_cast<MinikinPaint*>(fontData); MinikinPaint* paint = reinterpret_cast<MinikinPaint*>(fontData);
MinikinFont* font = paint->font; float advance = paint->font->GetHorizontalAdvance(glyph, *paint);
float advance = font->GetHorizontalAdvance(glyph, *paint);
return 256 * advance + 0.5; return 256 * advance + 0.5;
} }
...@@ -343,7 +335,7 @@ void Layout::dump() const { ...@@ -343,7 +335,7 @@ void Layout::dump() const {
} }
} }
int Layout::findFace(FakedFont face, LayoutContext* ctx) { int Layout::findFace(const FakedFont& face, LayoutContext* ctx) {
unsigned int ix; unsigned int ix;
for (ix = 0; ix < mFaces.size(); ix++) { for (ix = 0; ix < mFaces.size(); ix++) {
if (mFaces[ix].font == face.font) { if (mFaces[ix].font == face.font) {
...@@ -610,7 +602,7 @@ void Layout::doLayout(const uint16_t* buf, size_t start, size_t count, size_t bu ...@@ -610,7 +602,7 @@ void Layout::doLayout(const uint16_t* buf, size_t start, size_t count, size_t bu
float Layout::measureText(const uint16_t* buf, size_t start, size_t count, size_t bufSize, float Layout::measureText(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
int bidiFlags, const FontStyle &style, const MinikinPaint &paint, int bidiFlags, const FontStyle &style, const MinikinPaint &paint,
const FontCollection* collection, float* advances) { const std::shared_ptr<FontCollection>& collection, float* advances) {
android::AutoMutex _l(gMinikinLock); android::AutoMutex _l(gMinikinLock);
LayoutContext ctx; LayoutContext ctx;
...@@ -629,8 +621,8 @@ float Layout::measureText(const uint16_t* buf, size_t start, size_t count, size_ ...@@ -629,8 +621,8 @@ float Layout::measureText(const uint16_t* buf, size_t start, size_t count, size_
} }
float Layout::doLayoutRunCached(const uint16_t* buf, size_t start, size_t count, size_t bufSize, float Layout::doLayoutRunCached(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
bool isRtl, LayoutContext* ctx, size_t dstStart, const FontCollection* collection, bool isRtl, LayoutContext* ctx, size_t dstStart,
Layout* layout, float* advances) { const std::shared_ptr<FontCollection>& collection, Layout* layout, float* advances) {
HyphenEdit hyphen = ctx->paint.hyphenEdit; HyphenEdit hyphen = ctx->paint.hyphenEdit;
float advance = 0; float advance = 0;
if (!isRtl) { if (!isRtl) {
...@@ -668,8 +660,8 @@ float Layout::doLayoutRunCached(const uint16_t* buf, size_t start, size_t count, ...@@ -668,8 +660,8 @@ float Layout::doLayoutRunCached(const uint16_t* buf, size_t start, size_t count,
} }
float Layout::doLayoutWord(const uint16_t* buf, size_t start, size_t count, size_t bufSize, float Layout::doLayoutWord(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
bool isRtl, LayoutContext* ctx, size_t bufStart, const FontCollection* collection, bool isRtl, LayoutContext* ctx, size_t bufStart,
Layout* layout, float* advances) { const std::shared_ptr<FontCollection>& collection, Layout* layout, float* advances) {
LayoutCache& cache = LayoutEngine::getInstance().layoutCache; LayoutCache& cache = LayoutEngine::getInstance().layoutCache;
LayoutCacheKey key(collection, ctx->paint, ctx->style, buf, start, count, bufSize, isRtl); LayoutCacheKey key(collection, ctx->paint, ctx->style, buf, start, count, bufSize, isRtl);
...@@ -677,8 +669,8 @@ float Layout::doLayoutWord(const uint16_t* buf, size_t start, size_t count, size ...@@ -677,8 +669,8 @@ float Layout::doLayoutWord(const uint16_t* buf, size_t start, size_t count, size
float advance; float advance;
if (ctx->paint.skipCache()) { if (ctx->paint.skipCache()) {
Layout layoutForWord; Layout layoutForWord(collection);
key.doLayout(&layoutForWord, ctx, collection); key.doLayout(&layoutForWord, ctx);
if (layout) { if (layout) {
layout->appendLayout(&layoutForWord, bufStart, wordSpacing); layout->appendLayout(&layoutForWord, bufStart, wordSpacing);
} }
...@@ -732,9 +724,6 @@ void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t ...@@ -732,9 +724,6 @@ void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t
hb_buffer_t* buffer = LayoutEngine::getInstance().hbBuffer; hb_buffer_t* buffer = LayoutEngine::getInstance().hbBuffer;
vector<FontCollection::Run> items; vector<FontCollection::Run> items;
mCollection->itemize(buf + start, count, ctx->style, &items); mCollection->itemize(buf + start, count, ctx->style, &items);
if (isRtl) {
std::reverse(items.begin(), items.end());
}
vector<hb_feature_t> features; vector<hb_feature_t> features;
// Disable default-on non-required ligature features if letter-spacing // Disable default-on non-required ligature features if letter-spacing
...@@ -756,7 +745,9 @@ void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t ...@@ -756,7 +745,9 @@ void Layout::doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t
float x = mAdvance; float x = mAdvance;
float y = 0; float y = 0;
for (size_t run_ix = 0; run_ix < items.size(); run_ix++) { for (int run_ix = isRtl ? items.size() - 1 : 0;
isRtl ? run_ix >= 0 : run_ix < static_cast<int>(items.size());
isRtl ? --run_ix : ++run_ix) {
FontCollection::Run &run = items[run_ix]; FontCollection::Run &run = items[run_ix];
if (run.fakedFont.font == NULL) { if (run.fakedFont.font == NULL) {
ALOGE("no font for run starting u+%04x length %d", buf[run.start], run.end - run.start); ALOGE("no font for run starting u+%04x length %d", buf[run.start], run.end - run.start);
...@@ -967,7 +958,7 @@ size_t Layout::nGlyphs() const { ...@@ -967,7 +958,7 @@ size_t Layout::nGlyphs() const {
return mGlyphs.size(); return mGlyphs.size();
} }
MinikinFont* Layout::getFont(int i) const { const MinikinFont* Layout::getFont(int i) const {
const LayoutGlyph& glyph = mGlyphs[i]; const LayoutGlyph& glyph = mGlyphs[i];
return mFaces[glyph.font_ix].font; return mFaces[glyph.font_ix].font;
} }
...@@ -1000,7 +991,7 @@ void Layout::getAdvances(float* advances) { ...@@ -1000,7 +991,7 @@ void Layout::getAdvances(float* advances) {
memcpy(advances, &mAdvances[0], mAdvances.size() * sizeof(float)); memcpy(advances, &mAdvances[0], mAdvances.size() * sizeof(float));
} }
void Layout::getBounds(MinikinRect* bounds) { void Layout::getBounds(MinikinRect* bounds) const {
bounds->set(mBounds); bounds->set(mBounds);
} }
......
...@@ -129,7 +129,7 @@ static bool isLineBreakingHyphen(uint16_t c) { ...@@ -129,7 +129,7 @@ static bool isLineBreakingHyphen(uint16_t c) {
// width buffer. // width buffer.
// This method finds the candidate word breaks (using the ICU break iterator) and sends them // This method finds the candidate word breaks (using the ICU break iterator) and sends them
// to addCandidate. // to addCandidate.
float LineBreaker::addStyleRun(MinikinPaint* paint, const FontCollection* typeface, float LineBreaker::addStyleRun(MinikinPaint* paint, const std::shared_ptr<FontCollection>& typeface,
FontStyle style, size_t start, size_t end, bool isRtl) { FontStyle style, size_t start, size_t end, bool isRtl) {
float width = 0.0f; float width = 0.0f;
int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR; int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
......
...@@ -16,10 +16,12 @@ ...@@ -16,10 +16,12 @@
#include <minikin/MinikinFont.h> #include <minikin/MinikinFont.h>
#include "HbFontCache.h" #include "HbFontCache.h"
#include "MinikinInternal.h"
namespace minikin { namespace minikin {
MinikinFont::~MinikinFont() { MinikinFont::~MinikinFont() {
android::AutoMutex _l(gMinikinLock);
purgeHbFontLocked(this); purgeHbFontLocked(this);
} }
......
...@@ -85,7 +85,7 @@ bool isEmojiBase(uint32_t c) { ...@@ -85,7 +85,7 @@ bool isEmojiBase(uint32_t c) {
} }
} }
hb_blob_t* getFontTable(MinikinFont* minikinFont, uint32_t tag) { hb_blob_t* getFontTable(const MinikinFont* minikinFont, uint32_t tag) {
assertMinikinLocked(); assertMinikinLocked();
hb_font_t* font = getHbFontLocked(minikinFont); hb_font_t* font = getHbFontLocked(minikinFont);
hb_face_t* face = hb_font_get_face(font); hb_face_t* face = hb_font_get_face(font);
......
...@@ -45,7 +45,7 @@ bool isEmojiBase(uint32_t c); ...@@ -45,7 +45,7 @@ bool isEmojiBase(uint32_t c);
// Returns true if c is emoji modifier. // Returns true if c is emoji modifier.
bool isEmojiModifier(uint32_t c); bool isEmojiModifier(uint32_t c);
hb_blob_t* getFontTable(MinikinFont* minikinFont, uint32_t tag); hb_blob_t* getFontTable(const MinikinFont* minikinFont, uint32_t tag);
// An RAII wrapper for hb_blob_t // An RAII wrapper for hb_blob_t
class HbBlob { class HbBlob {
......
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Base class for reference counted objects in Minikin
#include "MinikinInternal.h"
#include <minikin/MinikinRefCounted.h>
namespace minikin {
void MinikinRefCounted::Ref() {
android::AutoMutex _l(gMinikinLock);
this->RefLocked();
}
void MinikinRefCounted::Unref() {
android::AutoMutex _l(gMinikinLock);
this->UnrefLocked();
}
} // namespace minikin
...@@ -44,7 +44,8 @@ void MinikinFontSkia::GetBounds(MinikinRect* bounds, uint32_t glyph_id, ...@@ -44,7 +44,8 @@ void MinikinFontSkia::GetBounds(MinikinRect* bounds, uint32_t glyph_id,
bounds->mBottom = skBounds.fBottom; bounds->mBottom = skBounds.fBottom;
} }
const void* MinikinFontSkia::GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy) { const void* MinikinFontSkia::GetTable(uint32_t tag, size_t* size,
MinikinDestroyFunc* destroy) const {
// we don't have a buffer to the font data, copy to own buffer // we don't have a buffer to the font data, copy to own buffer
const size_t tableSize = mTypeface->getTableSize(tag); const size_t tableSize = mTypeface->getTableSize(tag);
*size = tableSize; *size = tableSize;
...@@ -60,7 +61,7 @@ const void* MinikinFontSkia::GetTable(uint32_t tag, size_t* size, MinikinDestroy ...@@ -60,7 +61,7 @@ const void* MinikinFontSkia::GetTable(uint32_t tag, size_t* size, MinikinDestroy
return buf; return buf;
} }
SkTypeface *MinikinFontSkia::GetSkTypeface() { SkTypeface *MinikinFontSkia::GetSkTypeface() const {
return mTypeface.get(); return mTypeface.get();
} }
......
...@@ -25,12 +25,12 @@ public: ...@@ -25,12 +25,12 @@ public:
void GetBounds(MinikinRect* bounds, uint32_t glyph_id, void GetBounds(MinikinRect* bounds, uint32_t glyph_id,
const MinikinPaint& paint) const; const MinikinPaint& paint) const;
const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy);
const std::vector<minikin::FontVariation>& GetAxes() const { const std::vector<minikin::FontVariation>& GetAxes() const {
return mAxes; return mAxes;
} }
const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy) const;
SkTypeface *GetSkTypeface(); SkTypeface *GetSkTypeface() const;
private: private:
sk_sp<SkTypeface> mTypeface; sk_sp<SkTypeface> mTypeface;
......
...@@ -33,7 +33,7 @@ using namespace minikin; ...@@ -33,7 +33,7 @@ using namespace minikin;
FT_Library library; // TODO: this should not be a global FT_Library library; // TODO: this should not be a global
FontCollection *makeFontCollection() { FontCollection *makeFontCollection() {
vector<FontFamily *>typefaces; vector<std::shared_ptr<FontFamily>>typefaces;
const char *fns[] = { const char *fns[] = {
"/system/fonts/Roboto-Regular.ttf", "/system/fonts/Roboto-Regular.ttf",
"/system/fonts/Roboto-Italic.ttf", "/system/fonts/Roboto-Italic.ttf",
...@@ -55,17 +55,17 @@ FontCollection *makeFontCollection() { ...@@ -55,17 +55,17 @@ FontCollection *makeFontCollection() {
if (error != 0) { if (error != 0) {
printf("error loading %s, %d\n", fn, error); printf("error loading %s, %d\n", fn, error);
} }
MinikinFont *font = new MinikinFontFreeType(face); std::shared_ptr<MinikinFont> font(new MinikinFontFreeType(face));
fonts.push_back(Font(font, FontStyle())); fonts.push_back(Font(font, FontStyle()));
} }
FontFamily *family = new FontFamily(std::move(fonts)); std::shared_ptr<FontFamily> family(new FontFamily(std::move(fonts)));
typefaces.push_back(family); typefaces.push_back(family);
#if 1 #if 1
const char *fn = "/system/fonts/DroidSansDevanagari-Regular.ttf"; const char *fn = "/system/fonts/DroidSansDevanagari-Regular.ttf";
error = FT_New_Face(library, fn, 0, &face); error = FT_New_Face(library, fn, 0, &face);
MinikinFont *font = new MinikinFontFreeType(face); std::shared_ptr<MinikinFont> font(new MinikinFontFreeType(face));
family = new FontFamily(std::vector<Font>({ Font(font, FontStyle()) })); family.reset(new FontFamily(std::vector<Font>({ Font(font, FontStyle()) })));
typefaces.push_back(family); typefaces.push_back(family);
#endif #endif
...@@ -77,11 +77,8 @@ int runMinikinTest() { ...@@ -77,11 +77,8 @@ int runMinikinTest() {
if (error) { if (error) {
return -1; return -1;
} }
Layout::init(); std::shared_ptr<FontCollection> collection(makeFontCollection());
Layout layout(collection);
FontCollection *collection = makeFontCollection();
Layout layout;
layout.setFontCollection(collection);
const char *text = "fine world \xe0\xa4\xa8\xe0\xa4\xae\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\xa4\xe0\xa5\x87"; const char *text = "fine world \xe0\xa4\xa8\xe0\xa4\xae\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\xa4\xe0\xa5\x87";
int bidiFlags = 0; int bidiFlags = 0;
FontStyle fontStyle; FontStyle fontStyle;
......
...@@ -42,7 +42,7 @@ namespace minikin { ...@@ -42,7 +42,7 @@ namespace minikin {
FT_Library library; // TODO: this should not be a global FT_Library library; // TODO: this should not be a global
FontCollection *makeFontCollection() { FontCollection *makeFontCollection() {
vector<FontFamily *>typefaces; vector<std::shared_ptr<FontFamily>> typefaces;
const char *fns[] = { const char *fns[] = {
"/system/fonts/Roboto-Regular.ttf", "/system/fonts/Roboto-Regular.ttf",
"/system/fonts/Roboto-Italic.ttf", "/system/fonts/Roboto-Italic.ttf",
...@@ -58,20 +58,19 @@ FontCollection *makeFontCollection() { ...@@ -58,20 +58,19 @@ FontCollection *makeFontCollection() {
for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) { for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
const char *fn = fns[i]; const char *fn = fns[i];
sk_sp<SkTypeface> skFace = SkTypeface::MakeFromFile(fn); sk_sp<SkTypeface> skFace = SkTypeface::MakeFromFile(fn);
MinikinFont *font = new MinikinFontSkia(std::move(skFace)); std::shared_ptr<MinikinFont> font(new MinikinFontSkia(std::move(skFace)));
fonts.push_back(Font(font, FontStyle())); fonts.push_back(Font(font, FontStyle()));
} }
FontFamily *family = new FontFamily(std::move(fonts)); std::shared_ptr<FontFamily> family(new FontFamily(std::move(fonts)));
typefaces.push_back(family); typefaces.push_back(family);
#if 1 #if 1
const char *fn = "/system/fonts/DroidSansDevanagari-Regular.ttf"; const char *fn = "/system/fonts/DroidSansDevanagari-Regular.ttf";
sk_sp<SkTypeface> skFace = SkTypeface::MakeFromFile(fn); sk_sp<SkTypeface> skFace = SkTypeface::MakeFromFile(fn);
MinikinFont *font = new MinikinFontSkia(std::move(skFace)); std::shared_ptr<MinikinFont> font(new MinikinFontSkia(std::move(skFace)));
family = new FontFamily(std::vector<Font>({ Font(font, FontStyle()) })); family.reset(new FontFamily(std::vector<Font>({ Font(font, FontStyle()) })));
typefaces.push_back(family); typefaces.push_back(family);
#endif #endif
return new FontCollection(typefaces); return new FontCollection(typefaces);
} }
...@@ -87,7 +86,7 @@ void drawToSkia(SkCanvas *canvas, SkPaint *paint, Layout *layout, float x, float ...@@ -87,7 +86,7 @@ void drawToSkia(SkCanvas *canvas, SkPaint *paint, Layout *layout, float x, float
paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
for (size_t i = 0; i < nGlyphs; i++) { for (size_t i = 0; i < nGlyphs; i++) {
MinikinFontSkia *mfs = static_cast<MinikinFontSkia *>(layout->getFont(i)); const MinikinFontSkia *mfs = static_cast<const MinikinFontSkia *>(layout->getFont(i));
skFace = mfs->GetSkTypeface(); skFace = mfs->GetSkTypeface();
glyphs[i] = layout->getGlyphId(i); glyphs[i] = layout->getGlyphId(i);
pos[i].fX = x + layout->getX(i); pos[i].fX = x + layout->getX(i);
...@@ -110,11 +109,9 @@ int runMinikinTest() { ...@@ -110,11 +109,9 @@ int runMinikinTest() {
if (error) { if (error) {
return -1; return -1;
} }
Layout::init();
FontCollection *collection = makeFontCollection(); std::shared_ptr<FontCollection> collection(makeFontCollection());
Layout layout; Layout layout(collection);
layout.setFontCollection(collection);
const char *text = "fine world \xe0\xa4\xa8\xe0\xa4\xae\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\xa4\xe0\xa5\x87"; const char *text = "fine world \xe0\xa4\xa8\xe0\xa4\xae\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\xa4\xe0\xa5\x87";
int bidiFlags = 0; int bidiFlags = 0;
FontStyle fontStyle(7); FontStyle fontStyle(7);
......
...@@ -15,7 +15,8 @@ ...@@ -15,7 +15,8 @@
*/ */
#include <benchmark/benchmark.h> #include <benchmark/benchmark.h>
#include <minikin/MinikinRefCounted.h> #include <memory>
#include <minikin/FontCollection.h> #include <minikin/FontCollection.h>
#include <util/FontTestUtils.h> #include <util/FontTestUtils.h>
#include <util/UnicodeUtils.h> #include <util/UnicodeUtils.h>
...@@ -27,7 +28,7 @@ const char* SYSTEM_FONT_PATH = "/system/fonts/"; ...@@ -27,7 +28,7 @@ const char* SYSTEM_FONT_PATH = "/system/fonts/";
const char* SYSTEM_FONT_XML = "/system/etc/fonts.xml"; const char* SYSTEM_FONT_XML = "/system/etc/fonts.xml";
static void BM_FontCollection_hasVariationSelector(benchmark::State& state) { static void BM_FontCollection_hasVariationSelector(benchmark::State& state) {
MinikinAutoUnref<FontCollection> collection( std::shared_ptr<FontCollection> collection(
getFontCollection(SYSTEM_FONT_PATH, SYSTEM_FONT_XML)); getFontCollection(SYSTEM_FONT_PATH, SYSTEM_FONT_XML));
uint32_t baseCp = state.range(0); uint32_t baseCp = state.range(0);
...@@ -63,7 +64,7 @@ struct ItemizeTestCases { ...@@ -63,7 +64,7 @@ struct ItemizeTestCases {
}; };
static void BM_FontCollection_itemize(benchmark::State& state) { static void BM_FontCollection_itemize(benchmark::State& state) {
MinikinAutoUnref<FontCollection> collection( std::shared_ptr<FontCollection> collection(
getFontCollection(SYSTEM_FONT_PATH, SYSTEM_FONT_XML)); getFontCollection(SYSTEM_FONT_PATH, SYSTEM_FONT_XML));
size_t testIndex = state.range(0); size_t testIndex = state.range(0);
......
...@@ -57,11 +57,11 @@ void expectVSGlyphs(const FontCollection* fc, uint32_t codepoint, const std::set ...@@ -57,11 +57,11 @@ void expectVSGlyphs(const FontCollection* fc, uint32_t codepoint, const std::set
} }
TEST(FontCollectionTest, hasVariationSelectorTest) { TEST(FontCollectionTest, hasVariationSelectorTest) {
MinikinAutoUnref<MinikinFont> font(new MinikinFontForTest(kVsTestFont)); std::shared_ptr<MinikinFont> font(new MinikinFontForTest(kVsTestFont));
MinikinAutoUnref<FontFamily> family(new FontFamily( std::shared_ptr<FontFamily> family(new FontFamily(
std::vector<Font>({ Font(font.get(), FontStyle()) }))); std::vector<Font>({ Font(font, FontStyle()) })));
std::vector<FontFamily*> families({family.get()}); std::vector<std::shared_ptr<FontFamily>> families({ family });
MinikinAutoUnref<FontCollection> fc(new FontCollection(families)); std::shared_ptr<FontCollection> fc(new FontCollection(families));
EXPECT_FALSE(fc->hasVariationSelector(0x82A6, 0)); EXPECT_FALSE(fc->hasVariationSelector(0x82A6, 0));
expectVSGlyphs(fc.get(), 0x82A6, std::set<uint32_t>({0xFE00, 0xE0100, 0xE0101, 0xE0102})); expectVSGlyphs(fc.get(), 0x82A6, std::set<uint32_t>({0xFE00, 0xE0100, 0xE0101, 0xE0102}));
...@@ -79,7 +79,7 @@ TEST(FontCollectionTest, hasVariationSelectorTest) { ...@@ -79,7 +79,7 @@ TEST(FontCollectionTest, hasVariationSelectorTest) {
const char kEmojiXmlFile[] = kTestFontDir "emoji.xml"; const char kEmojiXmlFile[] = kTestFontDir "emoji.xml";
TEST(FontCollectionTest, hasVariationSelectorTest_emoji) { TEST(FontCollectionTest, hasVariationSelectorTest_emoji) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kEmojiXmlFile)); std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kEmojiXmlFile));
// Both text/color font have cmap format 14 subtable entry for VS15/VS16 respectively. // Both text/color font have cmap format 14 subtable entry for VS15/VS16 respectively.
EXPECT_TRUE(collection->hasVariationSelector(0x2623, 0xFE0E)); EXPECT_TRUE(collection->hasVariationSelector(0x2623, 0xFE0E));
...@@ -109,7 +109,7 @@ TEST(FontCollectionTest, hasVariationSelectorTest_emoji) { ...@@ -109,7 +109,7 @@ TEST(FontCollectionTest, hasVariationSelectorTest_emoji) {
} }
TEST(FontCollectionTest, newEmojiTest) { TEST(FontCollectionTest, newEmojiTest) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kEmojiXmlFile)); std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kEmojiXmlFile));
// U+2695, U+2640, U+2642 are not in emoji catrgory in Unicode 9 but they are now in emoji // U+2695, U+2640, U+2642 are not in emoji catrgory in Unicode 9 but they are now in emoji
// category. Should return true even if U+FE0E was appended. // category. Should return true even if U+FE0E was appended.
...@@ -126,17 +126,17 @@ TEST(FontCollectionTest, createWithVariations) { ...@@ -126,17 +126,17 @@ TEST(FontCollectionTest, createWithVariations) {
const char kMultiAxisFont[] = kTestFontDir "/MultiAxis.ttf"; const char kMultiAxisFont[] = kTestFontDir "/MultiAxis.ttf";
const char kNoAxisFont[] = kTestFontDir "/Regular.ttf"; const char kNoAxisFont[] = kTestFontDir "/Regular.ttf";
MinikinAutoUnref<MinikinFont> multiAxisFont(new MinikinFontForTest(kMultiAxisFont)); std::shared_ptr<MinikinFont> multiAxisFont(new MinikinFontForTest(kMultiAxisFont));
MinikinAutoUnref<FontFamily> multiAxisFamily(new FontFamily( std::shared_ptr<FontFamily> multiAxisFamily(new FontFamily(
std::vector<Font>({ Font(multiAxisFont.get(), FontStyle()) }))); std::vector<Font>({ Font(multiAxisFont, FontStyle()) })));
std::vector<FontFamily*> multiAxisFamilies({multiAxisFamily.get()}); std::vector<std::shared_ptr<FontFamily>> multiAxisFamilies({multiAxisFamily});
MinikinAutoUnref<FontCollection> multiAxisFc(new FontCollection(multiAxisFamilies)); std::shared_ptr<FontCollection> multiAxisFc(new FontCollection(multiAxisFamilies));
MinikinAutoUnref<MinikinFont> noAxisFont(new MinikinFontForTest(kNoAxisFont)); std::shared_ptr<MinikinFont> noAxisFont(new MinikinFontForTest(kNoAxisFont));
MinikinAutoUnref<FontFamily> noAxisFamily(new FontFamily( std::shared_ptr<FontFamily> noAxisFamily(new FontFamily(
std::vector<Font>({ Font(noAxisFont.get(), FontStyle()) }))); std::vector<Font>({ Font(noAxisFont, FontStyle()) })));
std::vector<FontFamily*> noAxisFamilies({noAxisFamily.get()}); std::vector<std::shared_ptr<FontFamily>> noAxisFamilies({noAxisFamily});
MinikinAutoUnref<FontCollection> noAxisFc(new FontCollection(noAxisFamilies)); std::shared_ptr<FontCollection> noAxisFc(new FontCollection(noAxisFamilies));
{ {
// Do not ceate new instance if none of variations are specified. // Do not ceate new instance if none of variations are specified.
...@@ -150,7 +150,7 @@ TEST(FontCollectionTest, createWithVariations) { ...@@ -150,7 +150,7 @@ TEST(FontCollectionTest, createWithVariations) {
std::vector<FontVariation> variations = { std::vector<FontVariation> variations = {
{ MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f } { MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f }
}; };
MinikinAutoUnref<FontCollection> newFc( std::shared_ptr<FontCollection> newFc(
multiAxisFc->createCollectionWithVariation(variations)); multiAxisFc->createCollectionWithVariation(variations));
EXPECT_NE(nullptr, newFc.get()); EXPECT_NE(nullptr, newFc.get());
EXPECT_NE(multiAxisFc.get(), newFc.get()); EXPECT_NE(multiAxisFc.get(), newFc.get());
...@@ -163,7 +163,7 @@ TEST(FontCollectionTest, createWithVariations) { ...@@ -163,7 +163,7 @@ TEST(FontCollectionTest, createWithVariations) {
{ MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f }, { MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f },
{ MinikinFont::MakeTag('w', 'g', 'h', 't'), 1.0f } { MinikinFont::MakeTag('w', 'g', 'h', 't'), 1.0f }
}; };
MinikinAutoUnref<FontCollection> newFc( std::shared_ptr<FontCollection> newFc(
multiAxisFc->createCollectionWithVariation(variations)); multiAxisFc->createCollectionWithVariation(variations));
EXPECT_NE(nullptr, newFc.get()); EXPECT_NE(nullptr, newFc.get());
EXPECT_NE(multiAxisFc.get(), newFc.get()); EXPECT_NE(multiAxisFc.get(), newFc.get());
...@@ -184,7 +184,7 @@ TEST(FontCollectionTest, createWithVariations) { ...@@ -184,7 +184,7 @@ TEST(FontCollectionTest, createWithVariations) {
{ MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f }, { MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f },
{ MinikinFont::MakeTag('Z', 'Z', 'Z', 'Z'), 1.0f } { MinikinFont::MakeTag('Z', 'Z', 'Z', 'Z'), 1.0f }
}; };
MinikinAutoUnref<FontCollection> newFc( std::shared_ptr<FontCollection> newFc(
multiAxisFc->createCollectionWithVariation(variations)); multiAxisFc->createCollectionWithVariation(variations));
EXPECT_NE(nullptr, newFc.get()); EXPECT_NE(nullptr, newFc.get());
EXPECT_NE(multiAxisFc.get(), newFc.get()); EXPECT_NE(multiAxisFc.get(), newFc.get());
......
...@@ -529,12 +529,9 @@ void expectVSGlyphs(FontFamily* family, uint32_t codepoint, const std::set<uint3 ...@@ -529,12 +529,9 @@ void expectVSGlyphs(FontFamily* family, uint32_t codepoint, const std::set<uint3
} }
TEST_F(FontFamilyTest, hasVariationSelectorTest) { TEST_F(FontFamilyTest, hasVariationSelectorTest) {
MinikinAutoUnref<MinikinFontForTest> std::shared_ptr<MinikinFont> minikinFont(new MinikinFontForTest(kVsTestFont));
minikinFont(new MinikinFontForTest(kVsTestFont)); std::shared_ptr<FontFamily> family(
MinikinAutoUnref<FontFamily> family( new FontFamily(std::vector<Font>{ Font(minikinFont, FontStyle()) }));
new FontFamily(std::vector<Font>{
Font(minikinFont.get(), FontStyle())
}));
android::AutoMutex _l(gMinikinLock); android::AutoMutex _l(gMinikinLock);
...@@ -585,10 +582,10 @@ TEST_F(FontFamilyTest, hasVSTableTest) { ...@@ -585,10 +582,10 @@ TEST_F(FontFamilyTest, hasVSTableTest) {
"Font " + testCase.fontPath + " should have a variation sequence table." : "Font " + testCase.fontPath + " should have a variation sequence table." :
"Font " + testCase.fontPath + " shouldn't have a variation sequence table."); "Font " + testCase.fontPath + " shouldn't have a variation sequence table.");
MinikinAutoUnref<MinikinFontForTest> minikinFont( std::shared_ptr<MinikinFont> minikinFont(
new MinikinFontForTest(testCase.fontPath)); new MinikinFontForTest(testCase.fontPath));
MinikinAutoUnref<FontFamily> family(new FontFamily( std::shared_ptr<FontFamily> family(new FontFamily(
std::vector<Font>{ Font(minikinFont.get(), FontStyle()) })); std::vector<Font>{ Font(minikinFont, FontStyle()) }));
android::AutoMutex _l(gMinikinLock); android::AutoMutex _l(gMinikinLock);
EXPECT_EQ(testCase.hasVSTable, family->hasVSTable()); EXPECT_EQ(testCase.hasVSTable, family->hasVSTable());
} }
...@@ -599,13 +596,15 @@ TEST_F(FontFamilyTest, createFamilyWithVariationTest) { ...@@ -599,13 +596,15 @@ TEST_F(FontFamilyTest, createFamilyWithVariationTest) {
const char kMultiAxisFont[] = kTestFontDir "/MultiAxis.ttf"; const char kMultiAxisFont[] = kTestFontDir "/MultiAxis.ttf";
const char kNoAxisFont[] = kTestFontDir "/Regular.ttf"; const char kNoAxisFont[] = kTestFontDir "/Regular.ttf";
MinikinAutoUnref<MinikinFont> multiAxisFont(new MinikinFontForTest(kMultiAxisFont)); std::shared_ptr<MinikinFont> multiAxisFont(new MinikinFontForTest(kMultiAxisFont));
MinikinAutoUnref<FontFamily> multiAxisFamily(new FontFamily( std::shared_ptr<FontFamily> multiAxisFamily(
std::vector<Font>({Font(multiAxisFont.get(), FontStyle())}))); std::shared_ptr<FontFamily>(new FontFamily(
std::vector<Font>({Font(multiAxisFont, FontStyle())}))));
MinikinAutoUnref<MinikinFont> noAxisFont(new MinikinFontForTest(kNoAxisFont)); std::shared_ptr<MinikinFont> noAxisFont(new MinikinFontForTest(kNoAxisFont));
MinikinAutoUnref<FontFamily> noAxisFamily(new FontFamily( std::shared_ptr<FontFamily> noAxisFamily(
std::vector<Font>({Font(noAxisFont.get(), FontStyle())}))); std::shared_ptr<FontFamily>(new FontFamily(
std::vector<Font>({Font(noAxisFont, FontStyle())}))));
{ {
// Do not ceate new instance if none of variations are specified. // Do not ceate new instance if none of variations are specified.
...@@ -617,7 +616,7 @@ TEST_F(FontFamilyTest, createFamilyWithVariationTest) { ...@@ -617,7 +616,7 @@ TEST_F(FontFamilyTest, createFamilyWithVariationTest) {
{ {
// New instance should be used for supported variation. // New instance should be used for supported variation.
std::vector<FontVariation> variations = {{MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f}}; std::vector<FontVariation> variations = {{MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f}};
MinikinAutoUnref<FontFamily> newFamily( std::shared_ptr<FontFamily> newFamily(
multiAxisFamily->createFamilyWithVariation(variations)); multiAxisFamily->createFamilyWithVariation(variations));
EXPECT_NE(nullptr, newFamily.get()); EXPECT_NE(nullptr, newFamily.get());
EXPECT_NE(multiAxisFamily.get(), newFamily.get()); EXPECT_NE(multiAxisFamily.get(), newFamily.get());
...@@ -629,7 +628,7 @@ TEST_F(FontFamilyTest, createFamilyWithVariationTest) { ...@@ -629,7 +628,7 @@ TEST_F(FontFamilyTest, createFamilyWithVariationTest) {
{ MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f }, { MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f },
{ MinikinFont::MakeTag('w', 'g', 'h', 't'), 1.0f } { MinikinFont::MakeTag('w', 'g', 'h', 't'), 1.0f }
}; };
MinikinAutoUnref<FontFamily> newFamily( std::shared_ptr<FontFamily> newFamily(
multiAxisFamily->createFamilyWithVariation(variations)); multiAxisFamily->createFamilyWithVariation(variations));
EXPECT_NE(nullptr, newFamily.get()); EXPECT_NE(nullptr, newFamily.get());
EXPECT_NE(multiAxisFamily.get(), newFamily.get()); EXPECT_NE(multiAxisFamily.get(), newFamily.get());
...@@ -649,7 +648,7 @@ TEST_F(FontFamilyTest, createFamilyWithVariationTest) { ...@@ -649,7 +648,7 @@ TEST_F(FontFamilyTest, createFamilyWithVariationTest) {
{ MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f }, { MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f },
{ MinikinFont::MakeTag('Z', 'Z', 'Z', 'Z'), 1.0f } { MinikinFont::MakeTag('Z', 'Z', 'Z', 'Z'), 1.0f }
}; };
MinikinAutoUnref<FontFamily> newFamily( std::shared_ptr<FontFamily> newFamily(
multiAxisFamily->createFamilyWithVariation(variations)); multiAxisFamily->createFamilyWithVariation(variations));
EXPECT_NE(nullptr, newFamily.get()); EXPECT_NE(nullptr, newFamily.get());
EXPECT_NE(multiAxisFamily.get(), newFamily.get()); EXPECT_NE(multiAxisFamily.get(), newFamily.get());
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <utils/Mutex.h> #include <utils/Mutex.h>
#include <memory>
#include <hb.h> #include <hb.h>
#include "MinikinInternal.h" #include "MinikinInternal.h"
...@@ -37,13 +39,13 @@ public: ...@@ -37,13 +39,13 @@ public:
}; };
TEST_F(HbFontCacheTest, getHbFontLockedTest) { TEST_F(HbFontCacheTest, getHbFontLockedTest) {
MinikinAutoUnref<MinikinFontForTest> fontA( std::shared_ptr<MinikinFontForTest> fontA(
new MinikinFontForTest(kTestFontDir "Regular.ttf")); new MinikinFontForTest(kTestFontDir "Regular.ttf"));
MinikinAutoUnref<MinikinFontForTest> fontB( std::shared_ptr<MinikinFontForTest> fontB(
new MinikinFontForTest(kTestFontDir "Bold.ttf")); new MinikinFontForTest(kTestFontDir "Bold.ttf"));
MinikinAutoUnref<MinikinFontForTest> fontC( std::shared_ptr<MinikinFontForTest> fontC(
new MinikinFontForTest(kTestFontDir "BoldItalic.ttf")); new MinikinFontForTest(kTestFontDir "BoldItalic.ttf"));
android::AutoMutex _l(gMinikinLock); android::AutoMutex _l(gMinikinLock);
...@@ -65,7 +67,7 @@ TEST_F(HbFontCacheTest, getHbFontLockedTest) { ...@@ -65,7 +67,7 @@ TEST_F(HbFontCacheTest, getHbFontLockedTest) {
} }
TEST_F(HbFontCacheTest, purgeCacheTest) { TEST_F(HbFontCacheTest, purgeCacheTest) {
MinikinAutoUnref<MinikinFontForTest> minikinFont( std::shared_ptr<MinikinFontForTest> minikinFont(
new MinikinFontForTest(kTestFontDir "Regular.ttf")); new MinikinFontForTest(kTestFontDir "Regular.ttf"));
android::AutoMutex _l(gMinikinLock); android::AutoMutex _l(gMinikinLock);
......
...@@ -53,14 +53,14 @@ protected: ...@@ -53,14 +53,14 @@ protected:
virtual ~LayoutTest() {} virtual ~LayoutTest() {}
virtual void SetUp() override { virtual void SetUp() override {
mCollection = getFontCollection(SYSTEM_FONT_PATH, SYSTEM_FONT_XML); mCollection = std::shared_ptr<FontCollection>(
getFontCollection(SYSTEM_FONT_PATH, SYSTEM_FONT_XML));
} }
virtual void TearDown() override { virtual void TearDown() override {
mCollection->Unref();
} }
FontCollection* mCollection; std::shared_ptr<FontCollection> mCollection;
}; };
TEST_F(LayoutTest, doLayoutTest) { TEST_F(LayoutTest, doLayoutTest) {
...@@ -70,8 +70,7 @@ TEST_F(LayoutTest, doLayoutTest) { ...@@ -70,8 +70,7 @@ TEST_F(LayoutTest, doLayoutTest) {
float advances[kMaxAdvanceLength]; float advances[kMaxAdvanceLength];
std::vector<float> expectedValues; std::vector<float> expectedValues;
Layout layout; Layout layout(mCollection);
layout.setFontCollection(mCollection);
std::vector<uint16_t> text; std::vector<uint16_t> text;
// The mock implementation returns 10.0f advance and 0,0-10x10 bounds for all glyph. // The mock implementation returns 10.0f advance and 0,0-10x10 bounds for all glyph.
...@@ -157,8 +156,7 @@ TEST_F(LayoutTest, doLayoutTest_wordSpacing) { ...@@ -157,8 +156,7 @@ TEST_F(LayoutTest, doLayoutTest_wordSpacing) {
std::vector<float> expectedValues; std::vector<float> expectedValues;
std::vector<uint16_t> text; std::vector<uint16_t> text;
Layout layout; Layout layout(mCollection);
layout.setFontCollection(mCollection);
paint.wordSpacing = 5.0f; paint.wordSpacing = 5.0f;
...@@ -252,8 +250,7 @@ TEST_F(LayoutTest, doLayoutTest_negativeWordSpacing) { ...@@ -252,8 +250,7 @@ TEST_F(LayoutTest, doLayoutTest_negativeWordSpacing) {
float advances[kMaxAdvanceLength]; float advances[kMaxAdvanceLength];
std::vector<float> expectedValues; std::vector<float> expectedValues;
Layout layout; Layout layout(mCollection);
layout.setFontCollection(mCollection);
std::vector<uint16_t> text; std::vector<uint16_t> text;
// Negative word spacing also should work. // Negative word spacing also should work.
...@@ -338,6 +335,27 @@ TEST_F(LayoutTest, doLayoutTest_negativeWordSpacing) { ...@@ -338,6 +335,27 @@ TEST_F(LayoutTest, doLayoutTest_negativeWordSpacing) {
} }
} }
TEST_F(LayoutTest, doLayoutTest_rtlTest) {
MinikinPaint paint;
std::vector<uint16_t> text = parseUnicodeString("'a' 'b' U+3042 U+3043 'c' 'd'");
Layout ltrLayout(mCollection);
ltrLayout.doLayout(text.data(), 0, text.size(), text.size(), kBidi_LTR, FontStyle(), paint);
Layout rtlLayout(mCollection);
rtlLayout.doLayout(text.data(), 0, text.size(), text.size(), kBidi_RTL, FontStyle(), paint);
ASSERT_EQ(ltrLayout.nGlyphs(), rtlLayout.nGlyphs());
ASSERT_EQ(6u, ltrLayout.nGlyphs());
size_t nGlyphs = ltrLayout.nGlyphs();
for (size_t i = 0; i < nGlyphs; ++i) {
EXPECT_EQ(ltrLayout.getFont(i), rtlLayout.getFont(nGlyphs - i - 1));
EXPECT_EQ(ltrLayout.getGlyphId(i), rtlLayout.getGlyphId(nGlyphs - i - 1));
}
}
// TODO: Add more test cases, e.g. measure text, letter spacing. // TODO: Add more test cases, e.g. measure text, letter spacing.
} // namespace minikin } // namespace minikin
...@@ -32,7 +32,7 @@ FontCollection* getFontCollection(const char* fontDir, const char* fontXml) { ...@@ -32,7 +32,7 @@ FontCollection* getFontCollection(const char* fontDir, const char* fontXml) {
xmlDoc* doc = xmlReadFile(fontXml, NULL, 0); xmlDoc* doc = xmlReadFile(fontXml, NULL, 0);
xmlNode* familySet = xmlDocGetRootElement(doc); xmlNode* familySet = xmlDocGetRootElement(doc);
std::vector<FontFamily*> families; std::vector<std::shared_ptr<FontFamily>> families;
for (xmlNode* familyNode = familySet->children; familyNode; familyNode = familyNode->next) { for (xmlNode* familyNode = familySet->children; familyNode; familyNode = familyNode->next) {
if (xmlStrcmp(familyNode->name, (const xmlChar*)"family") != 0) { if (xmlStrcmp(familyNode->name, (const xmlChar*)"family") != 0) {
continue; continue;
...@@ -69,34 +69,29 @@ FontCollection* getFontCollection(const char* fontDir, const char* fontXml) { ...@@ -69,34 +69,29 @@ FontCollection* getFontCollection(const char* fontDir, const char* fontXml) {
} }
if (index == nullptr) { if (index == nullptr) {
MinikinAutoUnref<MinikinFontForTest> std::shared_ptr<MinikinFont> minikinFont(new MinikinFontForTest(fontPath));
minikinFont(new MinikinFontForTest(fontPath)); fonts.push_back(Font(minikinFont, FontStyle(weight, italic)));
fonts.push_back(Font(minikinFont.get(), FontStyle(weight, italic)));
} else { } else {
MinikinAutoUnref<MinikinFontForTest> std::shared_ptr<MinikinFont> minikinFont(
minikinFont(new MinikinFontForTest(fontPath, atoi((const char*)index))); new MinikinFontForTest(fontPath, atoi((const char*)index)));
fonts.push_back(Font(minikinFont.get(), FontStyle(weight, italic))); fonts.push_back(Font(minikinFont, FontStyle(weight, italic)));
} }
} }
xmlChar* lang = xmlGetProp(familyNode, (const xmlChar*)"lang"); xmlChar* lang = xmlGetProp(familyNode, (const xmlChar*)"lang");
FontFamily* family; std::shared_ptr<FontFamily> family;
if (lang == nullptr) { if (lang == nullptr) {
family = new FontFamily(variant, std::move(fonts)); family.reset(new FontFamily(variant, std::move(fonts)));
} else { } else {
uint32_t langId = FontStyle::registerLanguageList( uint32_t langId = FontStyle::registerLanguageList(
std::string((const char*)lang, xmlStrlen(lang))); std::string((const char*)lang, xmlStrlen(lang)));
family = new FontFamily(langId, variant, std::move(fonts)); family.reset(new FontFamily(langId, variant, std::move(fonts)));
} }
families.push_back(family); families.push_back(family);
} }
xmlFreeDoc(doc); xmlFreeDoc(doc);
FontCollection* collection = new FontCollection(families); return new FontCollection(families);
for (size_t i = 0; i < families.size(); ++i) {
families[i]->Unref();
}
return collection;
} }
} // namespace minikin } // namespace minikin
...@@ -69,9 +69,9 @@ void MinikinFontForTest::GetBounds(MinikinRect* bounds, uint32_t /* glyph_id */, ...@@ -69,9 +69,9 @@ void MinikinFontForTest::GetBounds(MinikinRect* bounds, uint32_t /* glyph_id */,
bounds->mBottom = 10.0f; bounds->mBottom = 10.0f;
} }
MinikinFont* MinikinFontForTest::createFontWithVariation( std::shared_ptr<MinikinFont> MinikinFontForTest::createFontWithVariation(
const std::vector<FontVariation>& variations) const { const std::vector<FontVariation>& variations) const {
return new MinikinFontForTest(mFontPath, mFontIndex, variations); return std::shared_ptr<MinikinFont>(new MinikinFontForTest(mFontPath, mFontIndex, variations));
} }
} // namespace minikin } // namespace minikin
...@@ -43,7 +43,8 @@ public: ...@@ -43,7 +43,8 @@ public:
size_t GetFontSize() const { return mFontSize; } size_t GetFontSize() const { return mFontSize; }
int GetFontIndex() const { return mFontIndex; } int GetFontIndex() const { return mFontIndex; }
const std::vector<minikin::FontVariation>& GetAxes() const { return mVariations; } const std::vector<minikin::FontVariation>& GetAxes() const { return mVariations; }
MinikinFont* createFontWithVariation(const std::vector<FontVariation>& variations) const; std::shared_ptr<MinikinFont> createFontWithVariation(
const std::vector<FontVariation>& variations) const;
private: private:
MinikinFontForTest() = delete; MinikinFontForTest() = delete;
MinikinFontForTest(const MinikinFontForTest&) = delete; MinikinFontForTest(const MinikinFontForTest&) = delete;
......
...@@ -88,6 +88,17 @@ void ParseUnicode(uint16_t* buf, size_t buf_size, const char* src, size_t* resul ...@@ -88,6 +88,17 @@ void ParseUnicode(uint16_t* buf, size_t buf_size, const char* src, size_t* resul
LOG_ALWAYS_FATAL_IF(!seen_offset && offset != nullptr); LOG_ALWAYS_FATAL_IF(!seen_offset && offset != nullptr);
} }
std::vector<uint16_t> parseUnicodeStringWithOffset(const std::string& in, size_t* offset) {
std::unique_ptr<uint16_t[]> buffer(new uint16_t[in.size()]);
size_t result_size = 0;
ParseUnicode(buffer.get(), in.size(), in.c_str(), &result_size, offset);
return std::vector<uint16_t>(buffer.get(), buffer.get() + result_size);
}
std::vector<uint16_t> parseUnicodeString(const std::string& in) {
return parseUnicodeStringWithOffset(in, nullptr);
}
std::vector<uint16_t> utf8ToUtf16(const std::string& text) { std::vector<uint16_t> utf8ToUtf16(const std::string& text) {
std::vector<uint16_t> result; std::vector<uint16_t> result;
int32_t i = 0; int32_t i = 0;
......
...@@ -19,6 +19,9 @@ namespace minikin { ...@@ -19,6 +19,9 @@ namespace minikin {
void ParseUnicode(uint16_t* buf, size_t buf_size, const char* src, size_t* result_size, void ParseUnicode(uint16_t* buf, size_t buf_size, const char* src, size_t* result_size,
size_t* offset); size_t* offset);
std::vector<uint16_t> parseUnicodeStringWithOffset(const std::string& in, size_t* offset);
std::vector<uint16_t> parseUnicodeString(const std::string& in);
// Converts UTF-8 to UTF-16. // Converts UTF-8 to UTF-16.
std::vector<uint16_t> utf8ToUtf16(const std::string& text); std::vector<uint16_t> utf8ToUtf16(const std::string& text);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册