Merge "Remove MinikinRefCounted and use shared_ptr instead"

This commit is contained in:
Seigo Nonaka 2017-02-27 04:30:27 +00:00 committed by Android (Google) Code Review
commit 2f1aebfcc6
32 changed files with 443 additions and 539 deletions

View File

@ -17,20 +17,19 @@
#ifndef MINIKIN_FONT_COLLECTION_H
#define MINIKIN_FONT_COLLECTION_H
#include <vector>
#include <memory>
#include <unordered_set>
#include <vector>
#include <minikin/MinikinRefCounted.h>
#include <minikin/MinikinFont.h>
#include <minikin/FontFamily.h>
namespace minikin {
class FontCollection : public MinikinRefCounted {
class FontCollection {
public:
explicit FontCollection(const std::vector<FontFamily*>& typefaces);
~FontCollection();
explicit FontCollection(const std::vector<std::shared_ptr<FontFamily>>& typefaces);
explicit FontCollection(std::shared_ptr<FontFamily>&& typeface);
struct Run {
FakedFont fakedFont;
@ -46,15 +45,13 @@ public:
// selector pair, or invalid variation selector is passed.
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)
FakedFont baseFontFaked(FontStyle style);
// Creates new FontCollection based on this collection while applying font variations. Returns
// 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;
@ -67,12 +64,17 @@ private:
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,
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,
const FontFamily& fontFamily);
@ -88,19 +90,19 @@ private:
// Highest UTF-32 code point that can be mapped
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.
std::vector<FontFamily*> mFamilies;
std::vector<std::shared_ptr<FontFamily>> mFamilies;
// This vector contains pointers into mInstances
// This vector can't be empty.
std::vector<FontFamily*> mFamilyVec;
// 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
// Following two vectors are pre-calculated tables for resolving coverage faster.
// For example, to iterate over all fonts which support Unicode code point U+XXYYZZ,
// iterate font families from mFamilyVec[mRanges[0xXXYY].start] to
// mFamilyVec[mRange[0xXXYY].end] instead of whole mFamilies.
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.
std::unordered_set<AxisTag> mSupportedAxes;

View File

@ -17,14 +17,15 @@
#ifndef MINIKIN_FONT_FAMILY_H
#define MINIKIN_FONT_FAMILY_H
#include <vector>
#include <memory>
#include <string>
#include <unordered_set>
#include <vector>
#include <hb.h>
#include <utils/TypeHelpers.h>
#include <minikin/MinikinRefCounted.h>
#include <minikin/SparseBitSet.h>
namespace minikin {
@ -102,19 +103,17 @@ struct FakedFont {
typedef uint32_t AxisTag;
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(const Font& o);
~Font();
MinikinFont* typeface;
std::shared_ptr<MinikinFont> typeface;
FontStyle style;
std::unordered_set<AxisTag> supportedAxes;
// TODO: remove this weird function. http://b/28119474
// MinikinFont requres mutex lock for destruction, but the mutex lock is not
// visible from outside of minikin library.
static void clearElementsWithLock(std::vector<minikin::Font>* fonts);
private:
void loadAxes();
};
struct FontVariation {
@ -123,7 +122,7 @@ struct FontVariation {
float value;
};
class FontFamily : public MinikinRefCounted {
class FontFamily {
public:
explicit FontFamily(std::vector<Font>&& fonts);
FontFamily(int variant, std::vector<Font>&& fonts);
@ -132,8 +131,8 @@ public:
~FontFamily();
// 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;
uint32_t langId() const { return mLangId; }
@ -141,7 +140,9 @@ public:
// API's for enumerating the fonts in a family. These don't guarantee any particular order
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; }
bool isColorEmojiFamily() const;
const std::unordered_set<AxisTag>& supportedAxes() const { return mSupportedAxes; }
@ -158,7 +159,8 @@ public:
// Creates new FontFamily based on this family while applying font variations. Returns nullptr
// 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:
void computeCoverage();

View File

@ -19,6 +19,7 @@
#include <hb.h>
#include <memory>
#include <vector>
#include <minikin/FontCollection.h>
@ -71,37 +72,34 @@ enum {
// Lifecycle and threading assumptions for Layout:
// The object is assumed to be owned by a single thread; multiple threads
// 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 {
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();
}
// Clears layout, ready to be used again
void reset();
Layout(Layout&& layout) = default;
// Forbid copying and assignment.
Layout(const Layout&) = delete;
void operator=(const Layout&) = delete;
void dump() const;
void setFontCollection(const FontCollection* collection);
void doLayout(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
int bidiFlags, const FontStyle &style, const MinikinPaint &paint);
static float measureText(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
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;
// Deprecated. Nont needed. Remove when callers are removed.
static void init();
// public accessors
size_t nGlyphs() const;
// Does not bump reference; ownership is still layout
MinikinFont *getFont(int i) const;
const MinikinFont* getFont(int i) const;
FontFakery getFakery(int i) const;
unsigned int getGlyphId(int i) const;
float getX(int i) const;
@ -117,7 +115,7 @@ public:
// start and count are the parameters to doLayout
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
static void purgeCaches();
@ -126,19 +124,22 @@ private:
friend class LayoutCacheKey;
// 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
// 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.
static float doLayoutRunCached(const uint16_t* buf, size_t runStart, size_t runLength,
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
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,
Layout* layout, float* advances);
bool isRtl, LayoutContext* ctx, size_t bufStart,
const std::shared_ptr<FontCollection>& collection, Layout* layout, float* advances);
// Lay out a single bidi run
void doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
@ -150,7 +151,7 @@ private:
std::vector<LayoutGlyph> mGlyphs;
std::vector<float> mAdvances;
const FontCollection* mCollection;
std::shared_ptr<FontCollection> mCollection;
std::vector<FakedFont> mFaces;
float mAdvance;
MinikinRect mBounds;

View File

@ -159,8 +159,8 @@ class LineBreaker {
// 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
// easily be instantiated with Minikin's Layout. Future work for when needed.
float addStyleRun(MinikinPaint* paint, const FontCollection* typeface, FontStyle style,
size_t start, size_t end, bool isRtl);
float addStyleRun(MinikinPaint* paint, const std::shared_ptr<FontCollection>& typeface,
FontStyle style, size_t start, size_t end, bool isRtl);
void addReplacement(size_t start, size_t end, float width);

View File

@ -18,8 +18,8 @@
#define MINIKIN_FONT_H
#include <string>
#include <memory>
#include <minikin/MinikinRefCounted.h>
#include <minikin/FontFamily.h>
// An abstraction for platform fonts, allowing Minikin to be used with
@ -45,7 +45,7 @@ class MinikinFont;
// Possibly move into own .h file?
// Note: if you add a field here, either add it to LayoutCacheKey or to skipCache()
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() { }
bool skipCache() const {
@ -98,7 +98,7 @@ class MinikinFontFreeType;
// Callback for freeing data
typedef void (*MinikinDestroyFunc) (void* data);
class MinikinFont : public MinikinRefCounted {
class MinikinFont {
public:
explicit MinikinFont(int32_t uniqueId) : mUniqueId(uniqueId) {}
@ -128,7 +128,8 @@ public:
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;
}

View File

@ -1,59 +0,0 @@
/*
* 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

View File

@ -44,7 +44,6 @@ minikin_src_files := \
LineBreaker.cpp \
Measurement.cpp \
MinikinInternal.cpp \
MinikinRefCounted.cpp \
MinikinFont.cpp \
MinikinFontFreeType.cpp \
SparseBitSet.cpp \

View File

@ -79,8 +79,18 @@ static bool isEmojiStyleVSBase(uint32_t cp) {
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) {
init(typefaces);
}
void FontCollection::init(const vector<std::shared_ptr<FontFamily>>& typefaces) {
android::AutoMutex _l(gMinikinLock);
mId = sNextId++;
vector<uint32_t> lastChar;
@ -90,12 +100,10 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) :
#endif
const FontStyle defaultStyle;
for (size_t i = 0; i < nTypefaces; i++) {
FontFamily* family = typefaces[i];
MinikinFont* typeface = family->getClosestMatch(defaultStyle).font;
if (typeface == NULL) {
const std::shared_ptr<FontFamily>& family = typefaces[i];
if (family->getClosestMatch(defaultStyle).font == nullptr) {
continue;
}
family->RefLocked();
const SparseBitSet& coverage = family->getCoverage();
mFamilies.push_back(family); // emplace_back would be better
if (family->hasVSTable()) {
@ -126,7 +134,7 @@ FontCollection::FontCollection(const vector<FontFamily*>& typefaces) :
range->start = offset;
for (size_t j = 0; j < nTypefaces; j++) {
if (lastChar[j] < (i + 1) << kLogCharsPerPage) {
FontFamily* family = mFamilies[j];
const std::shared_ptr<FontFamily>& family = mFamilies[j];
mFamilyVec.push_back(family);
offset++;
uint32_t nextChar = family->getCoverage().nextSetBit((i + 1) << kLogCharsPerPage);
@ -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.
const uint32_t kUnsupportedFontScore = 0;
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
// given character or variation sequence.
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);
if (coverageScore == kFirstFontScore || coverageScore == kUnsupportedFontScore) {
@ -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 1 if the variation selector is not specified or if the font family only supports the
// 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);
if (!hasVSGlyph && !fontFamily->getCoverage().get(ch)) {
// 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&
// 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.
// 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 {
if (ch >= mMaxChar) {
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];
if (vs != 0) {
@ -293,10 +296,10 @@ FontFamily* FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs,
#ifdef VERBOSE_DEBUG
ALOGD("querying range %zd:%zd\n", range.start, range.end);
#endif
FontFamily* bestFamily = nullptr;
int bestFamilyIndex = -1;
uint32_t bestScore = kUnsupportedFontScore;
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);
if (score == kFirstFontScore) {
// 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,
}
if (score > bestScore) {
bestScore = score;
bestFamily = family;
bestFamilyIndex = i;
}
}
if (bestFamily == nullptr) {
if (bestFamilyIndex == -1) {
UErrorCode errorCode = U_ZERO_ERROR;
const UNormalizer2* normalizer = unorm2_getNFDInstance(&errorCode);
if (U_SUCCESS(errorCode)) {
@ -320,9 +323,9 @@ FontFamily* FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs,
return getFamilyForChar(ch, vs, langListId, variant);
}
}
bestFamily = mFamilies[0];
return mFamilies[0];
}
return bestFamily;
return familyVec[bestFamilyIndex];
}
const uint32_t NBSP = 0xA0;
@ -375,7 +378,7 @@ bool FontCollection::hasVariationSelector(uint32_t baseCodepoint,
if (isEmojiStyleVSBase(baseCodepoint) && variationSelector == TEXT_STYLE_VS) {
for (size_t i = 0; i < mFamilies.size(); ++i) {
if (!mFamilies[i]->isColorEmojiFamily() && variationSelector == TEXT_STYLE_VS &&
mFamilies[i]->hasGlyph(baseCodepoint, 0)) {
mFamilies[i]->hasGlyph(baseCodepoint, 0)) {
return true;
}
}
@ -388,7 +391,7 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
vector<Run>* result) const {
const uint32_t langListId = style.getLanguageListId();
int variant = style.getVariant();
FontFamily* lastFamily = NULL;
const FontFamily* lastFamily = nullptr;
Run* run = NULL;
if (string_size == 0) {
@ -425,9 +428,9 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
}
if (!shouldContinueRun) {
FontFamily* family = getFamilyForChar(ch, isVariationSelector(nextCh) ? nextCh : 0,
langListId, variant);
if (utf16Pos == 0 || family != lastFamily) {
const std::shared_ptr<FontFamily>& family = getFamilyForChar(
ch, isVariationSelector(nextCh) ? nextCh : 0, langListId, variant);
if (utf16Pos == 0 || family.get() != lastFamily) {
size_t start = utf16Pos;
// 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
@ -437,7 +440,7 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
if (utf16Pos != 0 &&
((U_GET_GC_MASK(ch) & U_GC_M_MASK) != 0 ||
(isEmojiModifier(ch) && isEmojiBase(prevCh))) &&
family && family->getCoverage().get(prevCh)) {
family != nullptr && family->getCoverage().get(prevCh)) {
const size_t prevChLength = U16_LENGTH(prevCh);
run->end -= prevChLength;
if (run->start == run->end) {
@ -445,12 +448,9 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
}
start -= prevChLength;
}
Run dummy;
result->push_back(dummy);
result->push_back({family->getClosestMatch(style), static_cast<int>(start), 0});
run = &result->back();
run->fakedFont = family->getClosestMatch(style);
lastFamily = family;
run->start = start;
lastFamily = family.get();
}
}
prevCh = ch;
@ -458,15 +458,11 @@ void FontCollection::itemize(const uint16_t *string, size_t string_size, FontSty
} while (nextCh != kEndOfString);
}
MinikinFont* FontCollection::baseFont(FontStyle style) {
return baseFontFaked(style).font;
}
FakedFont FontCollection::baseFontFaked(FontStyle style) {
return mFamilies[0]->getClosestMatch(style);
}
FontCollection* FontCollection::createCollectionWithVariation(
std::shared_ptr<FontCollection> FontCollection::createCollectionWithVariation(
const std::vector<FontVariation>& variations) {
if (variations.empty() || mSupportedAxes.empty()) {
return nullptr;
@ -484,22 +480,17 @@ FontCollection* FontCollection::createCollectionWithVariation(
return nullptr;
}
std::vector<FontFamily*> families;
for (FontFamily* family : mFamilies) {
FontFamily* newFamily = family->createFamilyWithVariation(variations);
std::vector<std::shared_ptr<FontFamily> > families;
for (const std::shared_ptr<FontFamily>& family : mFamilies) {
std::shared_ptr<FontFamily> newFamily = family->createFamilyWithVariation(variations);
if (newFamily) {
families.push_back(newFamily);
} else {
family->Ref();
families.push_back(family);
}
}
FontCollection* result = new FontCollection(families);
for (FontFamily* family : families) {
family->Unref();
}
return result;
return std::shared_ptr<FontCollection>(new FontCollection(families));
}
uint32_t FontCollection::getId() const {

View File

@ -65,13 +65,20 @@ uint32_t FontStyle::pack(int variant, int weight, bool italic) {
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) {
android::AutoMutex _l(gMinikinLock);
typeface->RefLocked();
loadAxes();
}
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');
HbBlob fvarTable(getFontTable(typeface, fvarTag));
HbBlob fvarTable(getFontTable(typeface.get(), fvarTag));
if (fvarTable.size() == 0) {
return;
}
@ -80,7 +87,7 @@ Font::Font(MinikinFont* typeface, FontStyle style)
}
Font::Font(Font&& o) {
typeface = o.typeface;
typeface = std::move(o.typeface);
style = o.style;
o.typeface = nullptr;
supportedAxes = std::move(o.supportedAxes);
@ -88,23 +95,11 @@ Font::Font(Font&& o) {
Font::Font(const Font& o) {
typeface = o.typeface;
typeface->Ref();
style = o.style;
supportedAxes = o.supportedAxes;
}
Font::~Font() {
if (typeface == nullptr) {
return;
}
typeface->UnrefLocked();
}
void Font::clearElementsWithLock(std::vector<minikin::Font>* fonts) {
android::AutoMutex _l(gMinikinLock);
fonts->clear();
}
// static
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)
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);
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;
return ::minikin::analyzeStyle(os2Table.get(), os2Table.size(), weight, italic);
}
@ -149,7 +145,7 @@ static FontFakery computeFakery(FontStyle wanted, FontStyle actual) {
}
FakedFont FontFamily::getClosestMatch(FontStyle style) const {
const Font* bestFont = NULL;
const Font* bestFont = nullptr;
int bestMatch = 0;
for (size_t i = 0; i < mFonts.size(); i++) {
const Font& font = mFonts[i];
@ -159,14 +155,10 @@ FakedFont FontFamily::getClosestMatch(FontStyle style) const {
bestMatch = match;
}
}
FakedFont result;
if (bestFont == NULL) {
result.font = NULL;
} else {
result.font = bestFont->typeface;
result.fakery = computeFakery(style, bestFont->style);
if (bestFont != nullptr) {
return FakedFont{ bestFont->typeface.get(), computeFakery(style, bestFont->style) };
}
return result;
return FakedFont{ nullptr, FontFakery() };
}
bool FontFamily::isColorEmojiFamily() const {
@ -182,7 +174,7 @@ bool FontFamily::isColorEmojiFamily() const {
void FontFamily::computeCoverage() {
android::AutoMutex _l(gMinikinLock);
const FontStyle defaultStyle;
MinikinFont* typeface = getClosestMatch(defaultStyle).font;
const MinikinFont* typeface = getClosestMatch(defaultStyle).font;
const uint32_t cmapTag = MinikinFont::MakeTag('c', 'm', 'a', 'p');
HbBlob cmapTable(getFontTable(typeface, cmapTag));
if (cmapTable.get() == nullptr) {
@ -206,15 +198,14 @@ bool FontFamily::hasGlyph(uint32_t codepoint, uint32_t variationSelector) const
}
const FontStyle defaultStyle;
MinikinFont* minikinFont = getClosestMatch(defaultStyle).font;
hb_font_t* font = getHbFontLocked(minikinFont);
hb_font_t* font = getHbFontLocked(getClosestMatch(defaultStyle).font);
uint32_t unusedGlyph;
bool result = hb_font_get_glyph(font, codepoint, variationSelector, &unusedGlyph);
hb_font_destroy(font);
return result;
}
FontFamily* FontFamily::createFamilyWithVariation(
std::shared_ptr<FontFamily> FontFamily::createFamilyWithVariation(
const std::vector<FontVariation>& variations) const {
if (variations.empty() || mSupportedAxes.empty()) {
return nullptr;
@ -243,19 +234,17 @@ FontFamily* FontFamily::createFamilyWithVariation(
}
}
}
MinikinFont* minikinFont = nullptr;
std::shared_ptr<MinikinFont> minikinFont;
if (supportedVariations) {
minikinFont = font.typeface->createFontWithVariation(variations);
}
if (minikinFont == nullptr) {
minikinFont = font.typeface;
minikinFont->Ref();
}
fonts.push_back(Font(minikinFont, font.style));
minikinFont->Unref();
fonts.push_back(Font(std::move(minikinFont), font.style));
}
return new FontFamily(mLangId, mVariant, std::move(fonts));
return std::shared_ptr<FontFamily>(new FontFamily(mLangId, mVariant, std::move(fonts)));
}
} // namespace minikin

View File

@ -84,7 +84,7 @@ void purgeHbFontLocked(const MinikinFont* minikinFont) {
// Returns a new reference to a hb_font_t object, caller is
// responsible for calling hb_font_destroy() on it.
hb_font_t* getHbFontLocked(MinikinFont* minikinFont) {
hb_font_t* getHbFontLocked(const MinikinFont* minikinFont) {
assertMinikinLocked();
// TODO: get rid of nullFaceFont
static hb_font_t* nullFaceFont = nullptr;

View File

@ -24,7 +24,7 @@ class MinikinFont;
void purgeHbFontCacheLocked();
void purgeHbFontLocked(const MinikinFont* minikinFont);
hb_font_t* getHbFontLocked(MinikinFont* minikinFont);
hb_font_t* getHbFontLocked(const MinikinFont* minikinFont);
} // namespace minikin
#endif // MINIKIN_HBFONT_CACHE_H

View File

@ -104,8 +104,9 @@ struct LayoutContext {
class LayoutCacheKey {
public:
LayoutCacheKey(const FontCollection* collection, const MinikinPaint& paint, FontStyle style,
const uint16_t* chars, size_t start, size_t count, size_t nchars, bool dir)
LayoutCacheKey(const std::shared_ptr<FontCollection>& collection, const MinikinPaint& paint,
FontStyle style, const uint16_t* chars, size_t start, size_t count, size_t nchars,
bool dir)
: mChars(chars), mNchars(nchars),
mStart(start), mCount(count), mId(collection->getId()), mStyle(style),
mSize(paint.size), mScaleX(paint.scaleX), mSkewX(paint.skewX),
@ -129,8 +130,7 @@ public:
mChars = NULL;
}
void doLayout(Layout* layout, LayoutContext* ctx, const FontCollection* collection) const {
layout->setFontCollection(collection);
void doLayout(Layout* layout, LayoutContext* ctx) const {
layout->mAdvances.resize(mCount, 0);
ctx->clearHbFonts();
layout->doLayoutRun(mChars, mStart, mCount, mNchars, mIsRtl, ctx);
@ -167,12 +167,13 @@ public:
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);
if (layout == NULL) {
key.copyText();
layout = new Layout();
key.doLayout(layout, ctx, collection);
layout = new Layout(collection);
key.doLayout(layout, ctx);
mCache.put(key, layout);
}
return layout;
@ -262,10 +263,6 @@ void MinikinRect::join(const MinikinRect& r) {
}
}
// Deprecated. Remove when callers are removed.
void Layout::init() {
}
void Layout::reset() {
mGlyphs.clear();
mFaces.clear();
@ -274,15 +271,10 @@ void Layout::reset() {
mAdvance = 0;
}
void Layout::setFontCollection(const FontCollection* collection) {
mCollection = collection;
}
static hb_position_t harfbuzzGetGlyphHorizontalAdvance(hb_font_t* /* hbFont */, void* fontData,
hb_codepoint_t glyph, void* /* userData */) {
MinikinPaint* paint = reinterpret_cast<MinikinPaint*>(fontData);
MinikinFont* font = paint->font;
float advance = font->GetHorizontalAdvance(glyph, *paint);
float advance = paint->font->GetHorizontalAdvance(glyph, *paint);
return 256 * advance + 0.5;
}
@ -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;
for (ix = 0; ix < mFaces.size(); ix++) {
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
float Layout::measureText(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
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);
LayoutContext ctx;
@ -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,
bool isRtl, LayoutContext* ctx, size_t dstStart, const FontCollection* collection,
Layout* layout, float* advances) {
bool isRtl, LayoutContext* ctx, size_t dstStart,
const std::shared_ptr<FontCollection>& collection, Layout* layout, float* advances) {
HyphenEdit hyphen = ctx->paint.hyphenEdit;
float advance = 0;
if (!isRtl) {
@ -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,
bool isRtl, LayoutContext* ctx, size_t bufStart, const FontCollection* collection,
Layout* layout, float* advances) {
bool isRtl, LayoutContext* ctx, size_t bufStart,
const std::shared_ptr<FontCollection>& collection, Layout* layout, float* advances) {
LayoutCache& cache = LayoutEngine::getInstance().layoutCache;
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
float advance;
if (ctx->paint.skipCache()) {
Layout layoutForWord;
key.doLayout(&layoutForWord, ctx, collection);
Layout layoutForWord(collection);
key.doLayout(&layoutForWord, ctx);
if (layout) {
layout->appendLayout(&layoutForWord, bufStart, wordSpacing);
}
@ -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;
vector<FontCollection::Run> items;
mCollection->itemize(buf + start, count, ctx->style, &items);
if (isRtl) {
std::reverse(items.begin(), items.end());
}
vector<hb_feature_t> features;
// 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
float x = mAdvance;
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];
if (run.fakedFont.font == NULL) {
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 {
return mGlyphs.size();
}
MinikinFont* Layout::getFont(int i) const {
const MinikinFont* Layout::getFont(int i) const {
const LayoutGlyph& glyph = mGlyphs[i];
return mFaces[glyph.font_ix].font;
}
@ -1000,7 +991,7 @@ void Layout::getAdvances(float* advances) {
memcpy(advances, &mAdvances[0], mAdvances.size() * sizeof(float));
}
void Layout::getBounds(MinikinRect* bounds) {
void Layout::getBounds(MinikinRect* bounds) const {
bounds->set(mBounds);
}

View File

@ -129,7 +129,7 @@ static bool isLineBreakingHyphen(uint16_t c) {
// width buffer.
// This method finds the candidate word breaks (using the ICU break iterator) and sends them
// 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) {
float width = 0.0f;
int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;

View File

@ -16,10 +16,12 @@
#include <minikin/MinikinFont.h>
#include "HbFontCache.h"
#include "MinikinInternal.h"
namespace minikin {
MinikinFont::~MinikinFont() {
android::AutoMutex _l(gMinikinLock);
purgeHbFontLocked(this);
}

View File

@ -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();
hb_font_t* font = getHbFontLocked(minikinFont);
hb_face_t* face = hb_font_get_face(font);

View File

@ -45,7 +45,7 @@ bool isEmojiBase(uint32_t c);
// Returns true if c is emoji modifier.
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
class HbBlob {

View File

@ -1,35 +0,0 @@
/*
* 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

View File

@ -44,7 +44,8 @@ void MinikinFontSkia::GetBounds(MinikinRect* bounds, uint32_t glyph_id,
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
const size_t tableSize = mTypeface->getTableSize(tag);
*size = tableSize;
@ -60,7 +61,7 @@ const void* MinikinFontSkia::GetTable(uint32_t tag, size_t* size, MinikinDestroy
return buf;
}
SkTypeface *MinikinFontSkia::GetSkTypeface() {
SkTypeface *MinikinFontSkia::GetSkTypeface() const {
return mTypeface.get();
}

View File

@ -25,12 +25,12 @@ public:
void GetBounds(MinikinRect* bounds, uint32_t glyph_id,
const MinikinPaint& paint) const;
const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy);
const std::vector<minikin::FontVariation>& GetAxes() const {
return mAxes;
}
const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy) const;
SkTypeface *GetSkTypeface();
SkTypeface *GetSkTypeface() const;
private:
sk_sp<SkTypeface> mTypeface;

View File

@ -33,7 +33,7 @@ using namespace minikin;
FT_Library library; // TODO: this should not be a global
FontCollection *makeFontCollection() {
vector<FontFamily *>typefaces;
vector<std::shared_ptr<FontFamily>>typefaces;
const char *fns[] = {
"/system/fonts/Roboto-Regular.ttf",
"/system/fonts/Roboto-Italic.ttf",
@ -55,17 +55,17 @@ FontCollection *makeFontCollection() {
if (error != 0) {
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()));
}
FontFamily *family = new FontFamily(std::move(fonts));
std::shared_ptr<FontFamily> family(new FontFamily(std::move(fonts)));
typefaces.push_back(family);
#if 1
const char *fn = "/system/fonts/DroidSansDevanagari-Regular.ttf";
error = FT_New_Face(library, fn, 0, &face);
MinikinFont *font = new MinikinFontFreeType(face);
family = new FontFamily(std::vector<Font>({ Font(font, FontStyle()) }));
std::shared_ptr<MinikinFont> font(new MinikinFontFreeType(face));
family.reset(new FontFamily(std::vector<Font>({ Font(font, FontStyle()) })));
typefaces.push_back(family);
#endif
@ -77,11 +77,8 @@ int runMinikinTest() {
if (error) {
return -1;
}
Layout::init();
FontCollection *collection = makeFontCollection();
Layout layout;
layout.setFontCollection(collection);
std::shared_ptr<FontCollection> collection(makeFontCollection());
Layout layout(collection);
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;
FontStyle fontStyle;

View File

@ -42,7 +42,7 @@ namespace minikin {
FT_Library library; // TODO: this should not be a global
FontCollection *makeFontCollection() {
vector<FontFamily *>typefaces;
vector<std::shared_ptr<FontFamily>> typefaces;
const char *fns[] = {
"/system/fonts/Roboto-Regular.ttf",
"/system/fonts/Roboto-Italic.ttf",
@ -58,20 +58,19 @@ FontCollection *makeFontCollection() {
for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
const char *fn = fns[i];
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()));
}
FontFamily *family = new FontFamily(std::move(fonts));
std::shared_ptr<FontFamily> family(new FontFamily(std::move(fonts)));
typefaces.push_back(family);
#if 1
const char *fn = "/system/fonts/DroidSansDevanagari-Regular.ttf";
sk_sp<SkTypeface> skFace = SkTypeface::MakeFromFile(fn);
MinikinFont *font = new MinikinFontSkia(std::move(skFace));
family = new FontFamily(std::vector<Font>({ Font(font, FontStyle()) }));
std::shared_ptr<MinikinFont> font(new MinikinFontSkia(std::move(skFace)));
family.reset(new FontFamily(std::vector<Font>({ Font(font, FontStyle()) })));
typefaces.push_back(family);
#endif
return new FontCollection(typefaces);
}
@ -87,7 +86,7 @@ void drawToSkia(SkCanvas *canvas, SkPaint *paint, Layout *layout, float x, float
paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
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();
glyphs[i] = layout->getGlyphId(i);
pos[i].fX = x + layout->getX(i);
@ -110,11 +109,9 @@ int runMinikinTest() {
if (error) {
return -1;
}
Layout::init();
FontCollection *collection = makeFontCollection();
Layout layout;
layout.setFontCollection(collection);
std::shared_ptr<FontCollection> collection(makeFontCollection());
Layout layout(collection);
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;
FontStyle fontStyle(7);

View File

@ -15,7 +15,8 @@
*/
#include <benchmark/benchmark.h>
#include <minikin/MinikinRefCounted.h>
#include <memory>
#include <minikin/FontCollection.h>
#include <util/FontTestUtils.h>
#include <util/UnicodeUtils.h>
@ -27,7 +28,7 @@ const char* SYSTEM_FONT_PATH = "/system/fonts/";
const char* SYSTEM_FONT_XML = "/system/etc/fonts.xml";
static void BM_FontCollection_hasVariationSelector(benchmark::State& state) {
MinikinAutoUnref<FontCollection> collection(
std::shared_ptr<FontCollection> collection(
getFontCollection(SYSTEM_FONT_PATH, SYSTEM_FONT_XML));
uint32_t baseCp = state.range(0);
@ -63,7 +64,7 @@ struct ItemizeTestCases {
};
static void BM_FontCollection_itemize(benchmark::State& state) {
MinikinAutoUnref<FontCollection> collection(
std::shared_ptr<FontCollection> collection(
getFontCollection(SYSTEM_FONT_PATH, SYSTEM_FONT_XML));
size_t testIndex = state.range(0);

View File

@ -16,6 +16,8 @@
#include <gtest/gtest.h>
#include <memory>
#include "FontLanguageListCache.h"
#include "FontLanguage.h"
#include "FontTestUtils.h"
@ -50,7 +52,7 @@ const char kNoCmapFormat14Font[] = kTestFontDir "VarioationSelectorTest-Regular
typedef ICUTestBase FontCollectionItemizeTest;
// Utility function for calling itemize function.
void itemize(FontCollection* collection, const char* str, FontStyle style,
void itemize(const std::shared_ptr<FontCollection>& collection, const char* str, FontStyle style,
std::vector<FontCollection::Run>* result) {
const size_t BUF_SIZE = 256;
uint16_t buf[BUF_SIZE];
@ -75,7 +77,7 @@ const FontLanguages& registerAndGetFontLanguages(const std::string& lang_string)
}
TEST_F(FontCollectionItemizeTest, itemize_latin) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::vector<FontCollection::Run> runs;
const FontStyle kRegularStyle = FontStyle();
@ -83,7 +85,7 @@ TEST_F(FontCollectionItemizeTest, itemize_latin) {
const FontStyle kBoldStyle = FontStyle(7, false);
const FontStyle kBoldItalicStyle = FontStyle(7, true);
itemize(collection.get(), "'a' 'b' 'c' 'd' 'e'", kRegularStyle, &runs);
itemize(collection, "'a' 'b' 'c' 'd' 'e'", kRegularStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(5, runs[0].end);
@ -91,7 +93,7 @@ TEST_F(FontCollectionItemizeTest, itemize_latin) {
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
itemize(collection.get(), "'a' 'b' 'c' 'd' 'e'", kItalicStyle, &runs);
itemize(collection, "'a' 'b' 'c' 'd' 'e'", kItalicStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(5, runs[0].end);
@ -99,7 +101,7 @@ TEST_F(FontCollectionItemizeTest, itemize_latin) {
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
itemize(collection.get(), "'a' 'b' 'c' 'd' 'e'", kBoldStyle, &runs);
itemize(collection, "'a' 'b' 'c' 'd' 'e'", kBoldStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(5, runs[0].end);
@ -107,7 +109,7 @@ TEST_F(FontCollectionItemizeTest, itemize_latin) {
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
itemize(collection.get(), "'a' 'b' 'c' 'd' 'e'", kBoldItalicStyle, &runs);
itemize(collection, "'a' 'b' 'c' 'd' 'e'", kBoldItalicStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(5, runs[0].end);
@ -117,7 +119,7 @@ TEST_F(FontCollectionItemizeTest, itemize_latin) {
// Continue if the specific characters (e.g. hyphen, comma, etc.) is
// followed.
itemize(collection.get(), "'a' ',' '-' 'd' '!'", kRegularStyle, &runs);
itemize(collection, "'a' ',' '-' 'd' '!'", kRegularStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(5, runs[0].end);
@ -125,7 +127,7 @@ TEST_F(FontCollectionItemizeTest, itemize_latin) {
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
itemize(collection.get(), "'a' ',' '-' 'd' '!'", kRegularStyle, &runs);
itemize(collection, "'a' ',' '-' 'd' '!'", kRegularStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(5, runs[0].end);
@ -135,7 +137,7 @@ TEST_F(FontCollectionItemizeTest, itemize_latin) {
// U+0301(COMBINING ACUTE ACCENT) must be in the same run with preceding
// chars if the font supports it.
itemize(collection.get(), "'a' U+0301", kRegularStyle, &runs);
itemize(collection, "'a' U+0301", kRegularStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -145,10 +147,10 @@ TEST_F(FontCollectionItemizeTest, itemize_latin) {
}
TEST_F(FontCollectionItemizeTest, itemize_emoji) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::vector<FontCollection::Run> runs;
itemize(collection.get(), "U+1F469 U+1F467", FontStyle(), &runs);
itemize(collection, "U+1F469 U+1F467", FontStyle(), &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(4, runs[0].end);
@ -158,7 +160,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emoji) {
// U+20E3(COMBINING ENCLOSING KEYCAP) must be in the same run with preceding
// character if the font supports.
itemize(collection.get(), "'0' U+20E3", FontStyle(), &runs);
itemize(collection, "'0' U+20E3", FontStyle(), &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -166,7 +168,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emoji) {
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
itemize(collection.get(), "U+1F470 U+20E3", FontStyle(), &runs);
itemize(collection, "U+1F470 U+20E3", FontStyle(), &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(3, runs[0].end);
@ -174,7 +176,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emoji) {
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeBold());
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
itemize(collection.get(), "U+242EE U+1F470 U+20E3", FontStyle(), &runs);
itemize(collection, "U+242EE U+1F470 U+20E3", FontStyle(), &runs);
ASSERT_EQ(2U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -190,7 +192,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emoji) {
// Currently there is no fonts which has a glyph for 'a' + U+20E3, so they
// are splitted into two.
itemize(collection.get(), "'a' U+20E3", FontStyle(), &runs);
itemize(collection, "'a' U+20E3", FontStyle(), &runs);
ASSERT_EQ(2U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
@ -206,7 +208,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emoji) {
}
TEST_F(FontCollectionItemizeTest, itemize_non_latin) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::vector<FontCollection::Run> runs;
FontStyle kJAStyle = FontStyle(FontStyle::registerLanguageList("ja_JP"));
@ -214,7 +216,7 @@ TEST_F(FontCollectionItemizeTest, itemize_non_latin) {
FontStyle kZH_HansStyle = FontStyle(FontStyle::registerLanguageList("zh_Hans"));
// All Japanese Hiragana characters.
itemize(collection.get(), "U+3042 U+3044 U+3046 U+3048 U+304A", kUSStyle, &runs);
itemize(collection, "U+3042 U+3044 U+3046 U+3048 U+304A", kUSStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(5, runs[0].end);
@ -223,7 +225,7 @@ TEST_F(FontCollectionItemizeTest, itemize_non_latin) {
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
// All Korean Hangul characters.
itemize(collection.get(), "U+B300 U+D55C U+BBFC U+AD6D", kUSStyle, &runs);
itemize(collection, "U+B300 U+D55C U+BBFC U+AD6D", kUSStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(4, runs[0].end);
@ -233,7 +235,7 @@ TEST_F(FontCollectionItemizeTest, itemize_non_latin) {
// All Han characters ja, zh-Hans font having.
// Japanese font should be selected if the specified language is Japanese.
itemize(collection.get(), "U+81ED U+82B1 U+5FCD", kJAStyle, &runs);
itemize(collection, "U+81ED U+82B1 U+5FCD", kJAStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(3, runs[0].end);
@ -243,7 +245,7 @@ TEST_F(FontCollectionItemizeTest, itemize_non_latin) {
// Simplified Chinese font should be selected if the specified language is Simplified
// Chinese.
itemize(collection.get(), "U+81ED U+82B1 U+5FCD", kZH_HansStyle, &runs);
itemize(collection, "U+81ED U+82B1 U+5FCD", kZH_HansStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(3, runs[0].end);
@ -253,7 +255,7 @@ TEST_F(FontCollectionItemizeTest, itemize_non_latin) {
// Fallbacks to other fonts if there is no glyph in the specified language's
// font. There is no character U+4F60 in Japanese.
itemize(collection.get(), "U+81ED U+4F60 U+5FCD", kJAStyle, &runs);
itemize(collection, "U+81ED U+4F60 U+5FCD", kJAStyle, &runs);
ASSERT_EQ(3U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
@ -274,7 +276,7 @@ TEST_F(FontCollectionItemizeTest, itemize_non_latin) {
EXPECT_FALSE(runs[2].fakedFont.fakery.isFakeItalic());
// Tone mark.
itemize(collection.get(), "U+4444 U+302D", FontStyle(), &runs);
itemize(collection, "U+4444 U+302D", FontStyle(), &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -285,7 +287,7 @@ TEST_F(FontCollectionItemizeTest, itemize_non_latin) {
// Both zh-Hant and ja fonts support U+242EE, but zh-Hans doesn't.
// Here, ja and zh-Hant font should have the same score but ja should be selected since it is
// listed before zh-Hant.
itemize(collection.get(), "U+242EE", kZH_HansStyle, &runs);
itemize(collection, "U+242EE", kZH_HansStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -295,12 +297,12 @@ TEST_F(FontCollectionItemizeTest, itemize_non_latin) {
}
TEST_F(FontCollectionItemizeTest, itemize_mixed) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::vector<FontCollection::Run> runs;
FontStyle kUSStyle = FontStyle(FontStyle::registerLanguageList("en_US"));
itemize(collection.get(), "'a' U+4F60 'b' U+4F60 'c'", kUSStyle, &runs);
itemize(collection, "'a' U+4F60 'b' U+4F60 'c'", kUSStyle, &runs);
ASSERT_EQ(5U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
@ -334,7 +336,7 @@ TEST_F(FontCollectionItemizeTest, itemize_mixed) {
}
TEST_F(FontCollectionItemizeTest, itemize_variationSelector) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::vector<FontCollection::Run> runs;
// A glyph for U+4FAE is provided by both Japanese font and Simplified
@ -346,19 +348,19 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelector) {
// U+4FAE is available in both zh_Hans and ja font, but U+4FAE,U+FE00 is
// only available in ja font.
itemize(collection.get(), "U+4FAE", kZH_HansStyle, &runs);
itemize(collection, "U+4FAE", kZH_HansStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
EXPECT_EQ(kZH_HansFont, getFontPath(runs[0]));
itemize(collection.get(), "U+4FAE U+FE00", kZH_HansStyle, &runs);
itemize(collection, "U+4FAE U+FE00", kZH_HansStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
itemize(collection.get(), "U+4FAE U+4FAE U+FE00", kZH_HansStyle, &runs);
itemize(collection, "U+4FAE U+4FAE U+FE00", kZH_HansStyle, &runs);
ASSERT_EQ(2U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
@ -367,7 +369,7 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelector) {
EXPECT_EQ(3, runs[1].end);
EXPECT_EQ(kJAFont, getFontPath(runs[1]));
itemize(collection.get(), "U+4FAE U+4FAE U+FE00 U+4FAE", kZH_HansStyle, &runs);
itemize(collection, "U+4FAE U+4FAE U+FE00 U+4FAE", kZH_HansStyle, &runs);
ASSERT_EQ(3U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
@ -380,14 +382,14 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelector) {
EXPECT_EQ(kZH_HansFont, getFontPath(runs[2]));
// Validation selector after validation selector.
itemize(collection.get(), "U+4FAE U+FE00 U+FE00", kZH_HansStyle, &runs);
itemize(collection, "U+4FAE U+FE00 U+FE00", kZH_HansStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(3, runs[0].end);
EXPECT_EQ(kJAFont, getFontPath(runs[1]));
// No font supports U+242EE U+FE0E.
itemize(collection.get(), "U+4FAE U+FE0E", kZH_HansStyle, &runs);
itemize(collection, "U+4FAE U+FE0E", kZH_HansStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -396,19 +398,19 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelector) {
// Surrogate pairs handling.
// U+242EE is available in ja font and zh_Hant font.
// U+242EE U+FE00 is available only in ja font.
itemize(collection.get(), "U+242EE", kZH_HantStyle, &runs);
itemize(collection, "U+242EE", kZH_HantStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
EXPECT_EQ(kZH_HantFont, getFontPath(runs[0]));
itemize(collection.get(), "U+242EE U+FE00", kZH_HantStyle, &runs);
itemize(collection, "U+242EE U+FE00", kZH_HantStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(3, runs[0].end);
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
itemize(collection.get(), "U+242EE U+242EE U+FE00", kZH_HantStyle, &runs);
itemize(collection, "U+242EE U+242EE U+FE00", kZH_HantStyle, &runs);
ASSERT_EQ(2U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -417,7 +419,7 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelector) {
EXPECT_EQ(5, runs[1].end);
EXPECT_EQ(kJAFont, getFontPath(runs[1]));
itemize(collection.get(), "U+242EE U+242EE U+FE00 U+242EE", kZH_HantStyle, &runs);
itemize(collection, "U+242EE U+242EE U+FE00 U+242EE", kZH_HantStyle, &runs);
ASSERT_EQ(3U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -430,27 +432,27 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelector) {
EXPECT_EQ(kZH_HantFont, getFontPath(runs[2]));
// Validation selector after validation selector.
itemize(collection.get(), "U+242EE U+FE00 U+FE00", kZH_HansStyle, &runs);
itemize(collection, "U+242EE U+FE00 U+FE00", kZH_HansStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(4, runs[0].end);
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
// No font supports U+242EE U+FE0E
itemize(collection.get(), "U+242EE U+FE0E", kZH_HantStyle, &runs);
itemize(collection, "U+242EE U+FE0E", kZH_HantStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(3, runs[0].end);
EXPECT_EQ(kZH_HantFont, getFontPath(runs[0]));
// Isolated variation selector supplement.
itemize(collection.get(), "U+FE00", FontStyle(), &runs);
itemize(collection, "U+FE00", FontStyle(), &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
EXPECT_TRUE(runs[0].fakedFont.font == nullptr || kLatinFont == getFontPath(runs[0]));
itemize(collection.get(), "U+FE00", kZH_HantStyle, &runs);
itemize(collection, "U+FE00", kZH_HantStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
@ -458,14 +460,14 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelector) {
// First font family (Regular.ttf) supports U+203C but doesn't support U+203C U+FE0F.
// Emoji.ttf font supports U+203C U+FE0F. Emoji.ttf should be selected.
itemize(collection.get(), "U+203C U+FE0F", kZH_HantStyle, &runs);
itemize(collection, "U+203C U+FE0F", kZH_HantStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
EXPECT_EQ(kEmojiFont, getFontPath(runs[0]));
// First font family (Regular.ttf) supports U+203C U+FE0E.
itemize(collection.get(), "U+203C U+FE0E", kZH_HantStyle, &runs);
itemize(collection, "U+203C U+FE0E", kZH_HantStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -473,7 +475,7 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelector) {
}
TEST_F(FontCollectionItemizeTest, itemize_variationSelectorSupplement) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::vector<FontCollection::Run> runs;
// A glyph for U+845B is provided by both Japanese font and Simplified
@ -485,19 +487,19 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelectorSupplement) {
// U+845B is available in both zh_Hans and ja font, but U+845B,U+E0100 is
// only available in ja font.
itemize(collection.get(), "U+845B", kZH_HansStyle, &runs);
itemize(collection, "U+845B", kZH_HansStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
EXPECT_EQ(kZH_HansFont, getFontPath(runs[0]));
itemize(collection.get(), "U+845B U+E0100", kZH_HansStyle, &runs);
itemize(collection, "U+845B U+E0100", kZH_HansStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(3, runs[0].end);
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
itemize(collection.get(), "U+845B U+845B U+E0100", kZH_HansStyle, &runs);
itemize(collection, "U+845B U+845B U+E0100", kZH_HansStyle, &runs);
ASSERT_EQ(2U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
@ -506,7 +508,7 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelectorSupplement) {
EXPECT_EQ(4, runs[1].end);
EXPECT_EQ(kJAFont, getFontPath(runs[1]));
itemize(collection.get(), "U+845B U+845B U+E0100 U+845B", kZH_HansStyle, &runs);
itemize(collection, "U+845B U+845B U+E0100 U+845B", kZH_HansStyle, &runs);
ASSERT_EQ(3U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
@ -519,14 +521,14 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelectorSupplement) {
EXPECT_EQ(kZH_HansFont, getFontPath(runs[2]));
// Validation selector after validation selector.
itemize(collection.get(), "U+845B U+E0100 U+E0100", kZH_HansStyle, &runs);
itemize(collection, "U+845B U+E0100 U+E0100", kZH_HansStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(5, runs[0].end);
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
// No font supports U+845B U+E01E0.
itemize(collection.get(), "U+845B U+E01E0", kZH_HansStyle, &runs);
itemize(collection, "U+845B U+E01E0", kZH_HansStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(3, runs[0].end);
@ -536,19 +538,19 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelectorSupplement) {
// Surrogate pairs handling.
// U+242EE is available in ja font and zh_Hant font.
// U+242EE U+E0100 is available only in ja font.
itemize(collection.get(), "U+242EE", kZH_HantStyle, &runs);
itemize(collection, "U+242EE", kZH_HantStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
EXPECT_EQ(kZH_HantFont, getFontPath(runs[0]));
itemize(collection.get(), "U+242EE U+E0101", kZH_HantStyle, &runs);
itemize(collection, "U+242EE U+E0101", kZH_HantStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(4, runs[0].end);
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
itemize(collection.get(), "U+242EE U+242EE U+E0101", kZH_HantStyle, &runs);
itemize(collection, "U+242EE U+242EE U+E0101", kZH_HantStyle, &runs);
ASSERT_EQ(2U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -557,7 +559,7 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelectorSupplement) {
EXPECT_EQ(6, runs[1].end);
EXPECT_EQ(kJAFont, getFontPath(runs[1]));
itemize(collection.get(), "U+242EE U+242EE U+E0101 U+242EE", kZH_HantStyle, &runs);
itemize(collection, "U+242EE U+242EE U+E0101 U+242EE", kZH_HantStyle, &runs);
ASSERT_EQ(3U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -570,27 +572,27 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelectorSupplement) {
EXPECT_EQ(kZH_HantFont, getFontPath(runs[2]));
// Validation selector after validation selector.
itemize(collection.get(), "U+242EE U+E0100 U+E0100", kZH_HantStyle, &runs);
itemize(collection, "U+242EE U+E0100 U+E0100", kZH_HantStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(6, runs[0].end);
EXPECT_EQ(kJAFont, getFontPath(runs[0]));
// No font supports U+242EE U+E01E0.
itemize(collection.get(), "U+242EE U+E01E0", kZH_HantStyle, &runs);
itemize(collection, "U+242EE U+E01E0", kZH_HantStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(4, runs[0].end);
EXPECT_EQ(kZH_HantFont, getFontPath(runs[0]));
// Isolated variation selector supplement.
itemize(collection.get(), "U+E0100", FontStyle(), &runs);
itemize(collection, "U+E0100", FontStyle(), &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
EXPECT_TRUE(runs[0].fakedFont.font == nullptr || kLatinFont == getFontPath(runs[0]));
itemize(collection.get(), "U+E0100", kZH_HantStyle, &runs);
itemize(collection, "U+E0100", kZH_HantStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -598,31 +600,31 @@ TEST_F(FontCollectionItemizeTest, itemize_variationSelectorSupplement) {
}
TEST_F(FontCollectionItemizeTest, itemize_no_crash) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::vector<FontCollection::Run> runs;
// Broken Surrogate pairs. Check only not crashing.
itemize(collection.get(), "'a' U+D83D 'a'", FontStyle(), &runs);
itemize(collection.get(), "'a' U+DC69 'a'", FontStyle(), &runs);
itemize(collection.get(), "'a' U+D83D U+D83D 'a'", FontStyle(), &runs);
itemize(collection.get(), "'a' U+DC69 U+DC69 'a'", FontStyle(), &runs);
itemize(collection, "'a' U+D83D 'a'", FontStyle(), &runs);
itemize(collection, "'a' U+DC69 'a'", FontStyle(), &runs);
itemize(collection, "'a' U+D83D U+D83D 'a'", FontStyle(), &runs);
itemize(collection, "'a' U+DC69 U+DC69 'a'", FontStyle(), &runs);
// Isolated variation selector. Check only not crashing.
itemize(collection.get(), "U+FE00 U+FE00", FontStyle(), &runs);
itemize(collection.get(), "U+E0100 U+E0100", FontStyle(), &runs);
itemize(collection.get(), "U+FE00 U+E0100", FontStyle(), &runs);
itemize(collection.get(), "U+E0100 U+FE00", FontStyle(), &runs);
itemize(collection, "U+FE00 U+FE00", FontStyle(), &runs);
itemize(collection, "U+E0100 U+E0100", FontStyle(), &runs);
itemize(collection, "U+FE00 U+E0100", FontStyle(), &runs);
itemize(collection, "U+E0100 U+FE00", FontStyle(), &runs);
// Tone mark only. Check only not crashing.
itemize(collection.get(), "U+302D", FontStyle(), &runs);
itemize(collection.get(), "U+302D U+302D", FontStyle(), &runs);
itemize(collection, "U+302D", FontStyle(), &runs);
itemize(collection, "U+302D U+302D", FontStyle(), &runs);
// Tone mark and variation selector mixed. Check only not crashing.
itemize(collection.get(), "U+FE00 U+302D U+E0100", FontStyle(), &runs);
itemize(collection, "U+FE00 U+302D U+E0100", FontStyle(), &runs);
}
TEST_F(FontCollectionItemizeTest, itemize_fakery) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::vector<FontCollection::Run> runs;
FontStyle kJABoldStyle = FontStyle(FontStyle::registerLanguageList("ja_JP"), 0, 7, false);
@ -634,7 +636,7 @@ TEST_F(FontCollectionItemizeTest, itemize_fakery) {
// the differences between desired and actual font style.
// All Japanese Hiragana characters.
itemize(collection.get(), "U+3042 U+3044 U+3046 U+3048 U+304A", kJABoldStyle, &runs);
itemize(collection, "U+3042 U+3044 U+3046 U+3048 U+304A", kJABoldStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(5, runs[0].end);
@ -643,7 +645,7 @@ TEST_F(FontCollectionItemizeTest, itemize_fakery) {
EXPECT_FALSE(runs[0].fakedFont.fakery.isFakeItalic());
// All Japanese Hiragana characters.
itemize(collection.get(), "U+3042 U+3044 U+3046 U+3048 U+304A", kJAItalicStyle, &runs);
itemize(collection, "U+3042 U+3044 U+3046 U+3048 U+304A", kJAItalicStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(5, runs[0].end);
@ -652,7 +654,7 @@ TEST_F(FontCollectionItemizeTest, itemize_fakery) {
EXPECT_TRUE(runs[0].fakedFont.fakery.isFakeItalic());
// All Japanese Hiragana characters.
itemize(collection.get(), "U+3042 U+3044 U+3046 U+3048 U+304A", kJABoldItalicStyle, &runs);
itemize(collection, "U+3042 U+3044 U+3046 U+3048 U+304A", kJABoldItalicStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(5, runs[0].end);
@ -667,29 +669,26 @@ TEST_F(FontCollectionItemizeTest, itemize_vs_sequence_but_no_base_char) {
// point.
const std::string kVSTestFont = kTestFontDir "VarioationSelectorTest-Regular.ttf";
std::vector<FontFamily*> families;
MinikinAutoUnref<MinikinFont> font(new MinikinFontForTest(kLatinFont));
FontFamily* family1 = new FontFamily(VARIANT_DEFAULT,
std::vector<Font>{ Font(font.get(), FontStyle()) });
std::vector<std::shared_ptr<FontFamily>> families;
std::shared_ptr<MinikinFont> font(new MinikinFontForTest(kLatinFont));
std::shared_ptr<FontFamily> family1(new FontFamily(VARIANT_DEFAULT,
std::vector<Font>{ Font(font, FontStyle()) }));
families.push_back(family1);
MinikinAutoUnref<MinikinFont> font2(new MinikinFontForTest(kVSTestFont));
FontFamily* family2 = new FontFamily(VARIANT_DEFAULT,
std::vector<Font>{ Font(font2.get(), FontStyle()) });
std::shared_ptr<MinikinFont> font2(new MinikinFontForTest(kVSTestFont));
std::shared_ptr<FontFamily> family2(new FontFamily(VARIANT_DEFAULT,
std::vector<Font>{ Font(font2, FontStyle()) }));
families.push_back(family2);
FontCollection collection(families);
std::shared_ptr<FontCollection> collection(new FontCollection(families));
std::vector<FontCollection::Run> runs;
itemize(&collection, "U+717D U+FE02", FontStyle(), &runs);
itemize(collection, "U+717D U+FE02", FontStyle(), &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
EXPECT_EQ(kVSTestFont, getFontPath(runs[0]));
family1->Unref();
family2->Unref();
}
TEST_F(FontCollectionItemizeTest, itemize_LanguageScore) {
@ -808,14 +807,14 @@ TEST_F(FontCollectionItemizeTest, itemize_LanguageScore) {
SCOPED_TRACE("Test of user preferred languages: \"" + testCase.userPreferredLanguages +
"\" with font languages: " + fontLanguagesStr);
std::vector<FontFamily*> families;
std::vector<std::shared_ptr<FontFamily>> families;
// Prepare first font which doesn't supports U+9AA8
MinikinAutoUnref<MinikinFont> firstFamilyMinikinFont(
std::shared_ptr<MinikinFont> firstFamilyMinikinFont(
new MinikinFontForTest(kNoGlyphFont));
FontFamily* firstFamily = new FontFamily(
std::shared_ptr<FontFamily> firstFamily(new FontFamily(
FontStyle::registerLanguageList("und"), 0 /* variant */,
std::vector<Font>({ Font(firstFamilyMinikinFont.get(), FontStyle()) }));
std::vector<Font>({ Font(firstFamilyMinikinFont, FontStyle()) })));
families.push_back(firstFamily);
// Prepare font families
@ -824,23 +823,19 @@ TEST_F(FontCollectionItemizeTest, itemize_LanguageScore) {
std::unordered_map<MinikinFont*, int> fontLangIdxMap;
for (size_t i = 0; i < testCase.fontLanguages.size(); ++i) {
MinikinAutoUnref<MinikinFont> minikin_font(new MinikinFontForTest(kJAFont));
FontFamily* family = new FontFamily(
std::shared_ptr<MinikinFont> minikin_font(new MinikinFontForTest(kJAFont));
std::shared_ptr<FontFamily> family(new FontFamily(
FontStyle::registerLanguageList(testCase.fontLanguages[i]), 0 /* variant */,
std::vector<Font>({ Font(minikin_font.get(), FontStyle()) }));
std::vector<Font>({ Font(minikin_font, FontStyle()) })));
families.push_back(family);
fontLangIdxMap.insert(std::make_pair(minikin_font.get(), i));
}
MinikinAutoUnref<FontCollection> collection(new FontCollection(families));
for (auto family : families) {
family->Unref();
}
std::shared_ptr<FontCollection> collection(new FontCollection(families));
// Do itemize
const FontStyle style = FontStyle(
FontStyle::registerLanguageList(testCase.userPreferredLanguages));
std::vector<FontCollection::Run> runs;
itemize(collection.get(), "U+9AA8", style, &runs);
itemize(collection, "U+9AA8", style, &runs);
ASSERT_EQ(1U, runs.size());
ASSERT_NE(nullptr, runs[0].fakedFont.font);
@ -1146,7 +1141,7 @@ TEST_F(FontCollectionItemizeTest, itemize_LanguageAndCoverage) {
{ "U+1F469", "zh-Hant,ja-Jpan,zh-Hans", kEmojiFont },
};
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kItemizeFontXml));
for (auto testCase : testCases) {
SCOPED_TRACE("Test for \"" + testCase.testString + "\" with languages " +
@ -1155,21 +1150,21 @@ TEST_F(FontCollectionItemizeTest, itemize_LanguageAndCoverage) {
std::vector<FontCollection::Run> runs;
const FontStyle style =
FontStyle(FontStyle::registerLanguageList(testCase.requestedLanguages));
itemize(collection.get(), testCase.testString.c_str(), style, &runs);
itemize(collection, testCase.testString.c_str(), style, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(testCase.expectedFont, getFontPath(runs[0]));
}
}
TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kEmojiXmlFile));
std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kEmojiXmlFile));
std::vector<FontCollection::Run> runs;
const FontStyle kDefaultFontStyle;
// U+00A9 is a text default emoji which is only available in TextEmojiFont.ttf.
// TextEmojiFont.ttf should be selected.
itemize(collection.get(), "U+00A9 U+FE0E", kDefaultFontStyle, &runs);
itemize(collection, "U+00A9 U+FE0E", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1177,7 +1172,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) {
// U+00A9 is a text default emoji which is only available in ColorEmojiFont.ttf.
// ColorEmojiFont.ttf should be selected.
itemize(collection.get(), "U+00AE U+FE0E", kDefaultFontStyle, &runs);
itemize(collection, "U+00AE U+FE0E", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1186,7 +1181,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) {
// U+203C is a text default emoji which is available in both TextEmojiFont.ttf and
// ColorEmojiFont.ttf. TextEmojiFont.ttf should be selected.
itemize(collection.get(), "U+203C U+FE0E", kDefaultFontStyle, &runs);
itemize(collection, "U+203C U+FE0E", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1194,7 +1189,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) {
// U+2049 is a text default emoji which is not available either TextEmojiFont.ttf or
// ColorEmojiFont.ttf. No font should be selected.
itemize(collection.get(), "U+2049 U+FE0E", kDefaultFontStyle, &runs);
itemize(collection, "U+2049 U+FE0E", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1202,7 +1197,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) {
// U+231A is a emoji default emoji which is available only in TextEmojifFont.
// TextEmojiFont.ttf sohuld be selected.
itemize(collection.get(), "U+231A U+FE0E", kDefaultFontStyle, &runs);
itemize(collection, "U+231A U+FE0E", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1210,7 +1205,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) {
// U+231B is a emoji default emoji which is available only in ColorEmojiFont.ttf.
// ColorEmojiFont.ttf should be selected.
itemize(collection.get(), "U+231B U+FE0E", kDefaultFontStyle, &runs);
itemize(collection, "U+231B U+FE0E", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1220,7 +1215,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) {
// U+23E9 is a emoji default emoji which is available in both TextEmojiFont.ttf and
// ColorEmojiFont.ttf. TextEmojiFont.ttf should be selected even if U+23E9 is emoji default
// emoji since U+FE0E is appended.
itemize(collection.get(), "U+23E9 U+FE0E", kDefaultFontStyle, &runs);
itemize(collection, "U+23E9 U+FE0E", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1228,7 +1223,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) {
// U+23EA is a emoji default emoji but which is not available in either TextEmojiFont.ttf or
// ColorEmojiFont.ttf. No font should be selected.
itemize(collection.get(), "U+23EA U+FE0E", kDefaultFontStyle, &runs);
itemize(collection, "U+23EA U+FE0E", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1236,7 +1231,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) {
// U+26FA U+FE0E is specified but ColorTextMixedEmojiFont has a variation sequence U+26F9 U+FE0F
// in its cmap, so ColorTextMixedEmojiFont should be selected instaed of ColorEmojiFont.
itemize(collection.get(), "U+26FA U+FE0E", kDefaultFontStyle, &runs);
itemize(collection, "U+26FA U+FE0E", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1244,14 +1239,14 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0E) {
}
TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kEmojiXmlFile));
std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kEmojiXmlFile));
std::vector<FontCollection::Run> runs;
const FontStyle kDefaultFontStyle;
// U+00A9 is a text default emoji which is available only in TextEmojiFont.ttf.
// TextEmojiFont.ttf shoudl be selected.
itemize(collection.get(), "U+00A9 U+FE0F", kDefaultFontStyle, &runs);
itemize(collection, "U+00A9 U+FE0F", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1260,7 +1255,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) {
// U+00AE is a text default emoji which is available only in ColorEmojiFont.ttf.
// ColorEmojiFont.ttf should be selected.
itemize(collection.get(), "U+00AE U+FE0F", kDefaultFontStyle, &runs);
itemize(collection, "U+00AE U+FE0F", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1269,7 +1264,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) {
// U+203C is a text default emoji which is available in both TextEmojiFont.ttf and
// ColorEmojiFont.ttf. ColorEmojiFont.ttf should be selected even if U+203C is a text default
// emoji since U+FF0F is appended.
itemize(collection.get(), "U+203C U+FE0F", kDefaultFontStyle, &runs);
itemize(collection, "U+203C U+FE0F", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1277,7 +1272,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) {
// U+2049 is a text default emoji which is not available in either TextEmojiFont.ttf or
// ColorEmojiFont.ttf. No font should be selected.
itemize(collection.get(), "U+2049 U+FE0F", kDefaultFontStyle, &runs);
itemize(collection, "U+2049 U+FE0F", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1285,7 +1280,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) {
// U+231A is a emoji default emoji which is available only in TextEmojiFont.ttf.
// TextEmojiFont.ttf should be selected.
itemize(collection.get(), "U+231A U+FE0F", kDefaultFontStyle, &runs);
itemize(collection, "U+231A U+FE0F", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1294,7 +1289,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) {
// U+231B is a emoji default emoji which is available only in ColorEmojiFont.ttf.
// ColorEmojiFont.ttf should be selected.
itemize(collection.get(), "U+231B U+FE0F", kDefaultFontStyle, &runs);
itemize(collection, "U+231B U+FE0F", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1302,7 +1297,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) {
// U+23E9 is a emoji default emoji which is available in both TextEmojiFont.ttf and
// ColorEmojiFont.ttf. ColorEmojiFont.ttf should be selected.
itemize(collection.get(), "U+23E9 U+FE0F", kDefaultFontStyle, &runs);
itemize(collection, "U+23E9 U+FE0F", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1310,7 +1305,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) {
// U+23EA is a emoji default emoji which is not available in either TextEmojiFont.ttf or
// ColorEmojiFont.ttf. No font should be selected.
itemize(collection.get(), "U+23EA U+FE0F", kDefaultFontStyle, &runs);
itemize(collection, "U+23EA U+FE0F", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1318,7 +1313,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) {
// U+26F9 U+FE0F is specified but ColorTextMixedEmojiFont has a variation sequence U+26F9 U+FE0F
// in its cmap, so ColorTextMixedEmojiFont should be selected instaed of ColorEmojiFont.
itemize(collection.get(), "U+26F9 U+FE0F", kDefaultFontStyle, &runs);
itemize(collection, "U+26F9 U+FE0F", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1326,27 +1321,27 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_withFE0F) {
}
TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_with_skinTone) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kEmojiXmlFile));
std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kEmojiXmlFile));
std::vector<FontCollection::Run> runs;
const FontStyle kDefaultFontStyle;
// TextEmoji font is selected since it is listed before ColorEmoji font.
itemize(collection.get(), "U+261D", kDefaultFontStyle, &runs);
itemize(collection, "U+261D", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(1, runs[0].end);
EXPECT_EQ(kTextEmojiFont, getFontPath(runs[0]));
// If skin tone is specified, it should be colored.
itemize(collection.get(), "U+261D U+1F3FD", kDefaultFontStyle, &runs);
itemize(collection, "U+261D U+1F3FD", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(3, runs[0].end);
EXPECT_EQ(kColorEmojiFont, getFontPath(runs[0]));
// Still color font is selected if an emoji variation selector is specified.
itemize(collection.get(), "U+261D U+FE0F U+1F3FD", kDefaultFontStyle, &runs);
itemize(collection, "U+261D U+FE0F U+1F3FD", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(4, runs[0].end);
@ -1354,7 +1349,7 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_with_skinTone) {
// Text font should be selected if a text variation selector is specified and skin tone is
// rendered by itself.
itemize(collection.get(), "U+261D U+FE0E U+1F3FD", kDefaultFontStyle, &runs);
itemize(collection, "U+261D U+FE0E U+1F3FD", kDefaultFontStyle, &runs);
ASSERT_EQ(2U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
@ -1365,19 +1360,19 @@ TEST_F(FontCollectionItemizeTest, itemize_emojiSelection_with_skinTone) {
}
TEST_F(FontCollectionItemizeTest, itemize_PrivateUseArea) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kEmojiXmlFile));
std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kEmojiXmlFile));
std::vector<FontCollection::Run> runs;
const FontStyle kDefaultFontStyle;
// Should not set nullptr to the result run. (Issue 26808815)
itemize(collection.get(), "U+FEE10", kDefaultFontStyle, &runs);
itemize(collection, "U+FEE10", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(2, runs[0].end);
EXPECT_EQ(kNoGlyphFont, getFontPath(runs[0]));
itemize(collection.get(), "U+FEE40 U+FE4C5", kDefaultFontStyle, &runs);
itemize(collection, "U+FEE40 U+FE4C5", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(4, runs[0].end);
@ -1385,24 +1380,24 @@ TEST_F(FontCollectionItemizeTest, itemize_PrivateUseArea) {
}
TEST_F(FontCollectionItemizeTest, itemize_genderBalancedEmoji) {
MinikinAutoUnref<FontCollection> collection(getFontCollection(kTestFontDir, kEmojiXmlFile));
std::shared_ptr<FontCollection> collection(getFontCollection(kTestFontDir, kEmojiXmlFile));
std::vector<FontCollection::Run> runs;
const FontStyle kDefaultFontStyle;
itemize(collection.get(), "U+1F469 U+200D U+1F373", kDefaultFontStyle, &runs);
itemize(collection, "U+1F469 U+200D U+1F373", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(5, runs[0].end);
EXPECT_EQ(kColorEmojiFont, getFontPath(runs[0]));
itemize(collection.get(), "U+1F469 U+200D U+2695 U+FE0F", kDefaultFontStyle, &runs);
itemize(collection, "U+1F469 U+200D U+2695 U+FE0F", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(5, runs[0].end);
EXPECT_EQ(kColorEmojiFont, getFontPath(runs[0]));
itemize(collection.get(), "U+1F469 U+200D U+2695", kDefaultFontStyle, &runs);
itemize(collection, "U+1F469 U+200D U+2695", kDefaultFontStyle, &runs);
ASSERT_EQ(1U, runs.size());
EXPECT_EQ(0, runs[0].start);
EXPECT_EQ(4, runs[0].end);
@ -1413,32 +1408,32 @@ TEST_F(FontCollectionItemizeTest, itemize_genderBalancedEmoji) {
TEST_F(FontCollectionItemizeTest, itemizeShouldKeepOrderForVS) {
const FontStyle kDefaultFontStyle;
MinikinAutoUnref<MinikinFont> dummyFont(new MinikinFontForTest(kNoGlyphFont));
MinikinAutoUnref<MinikinFont> fontA(new MinikinFontForTest(kZH_HansFont));
MinikinAutoUnref<MinikinFont> fontB(new MinikinFontForTest(kZH_HansFont));
std::shared_ptr<MinikinFont> dummyFont(new MinikinFontForTest(kNoGlyphFont));
std::shared_ptr<MinikinFont> fontA(new MinikinFontForTest(kZH_HansFont));
std::shared_ptr<MinikinFont> fontB(new MinikinFontForTest(kZH_HansFont));
MinikinAutoUnref<FontFamily> dummyFamily(new FontFamily(
std::vector<Font>({ Font(dummyFont.get(), FontStyle()) })));
MinikinAutoUnref<FontFamily> familyA(new FontFamily(
std::vector<Font>({ Font(fontA.get(), FontStyle()) })));
MinikinAutoUnref<FontFamily> familyB(new FontFamily(
std::vector<Font>({ Font(fontB.get(), FontStyle()) })));
std::shared_ptr<FontFamily> dummyFamily(new FontFamily(
std::vector<Font>({ Font(dummyFont, FontStyle()) })));
std::shared_ptr<FontFamily> familyA(new FontFamily(
std::vector<Font>({ Font(fontA, FontStyle()) })));
std::shared_ptr<FontFamily> familyB(new FontFamily(
std::vector<Font>({ Font(fontB, FontStyle()) })));
std::vector<FontFamily*> families =
{ dummyFamily.get(), familyA.get(), familyB.get() };
std::vector<FontFamily*> reversedFamilies =
{ dummyFamily.get(), familyB.get(), familyA.get() };
std::vector<std::shared_ptr<FontFamily>> families =
{ dummyFamily, familyA, familyB };
std::vector<std::shared_ptr<FontFamily>> reversedFamilies =
{ dummyFamily, familyB, familyA };
MinikinAutoUnref<FontCollection> collection(new FontCollection(families));
MinikinAutoUnref<FontCollection> reversedCollection(new FontCollection(reversedFamilies));
std::shared_ptr<FontCollection> collection(new FontCollection(families));
std::shared_ptr<FontCollection> reversedCollection(new FontCollection(reversedFamilies));
// Both fontA/fontB support U+35A8 but don't support U+35A8 U+E0100. The first font should be
// selected.
std::vector<FontCollection::Run> runs;
itemize(collection.get(), "U+35A8 U+E0100", kDefaultFontStyle, &runs);
itemize(collection, "U+35A8 U+E0100", kDefaultFontStyle, &runs);
EXPECT_EQ(fontA.get(), runs[0].fakedFont.font);
itemize(reversedCollection.get(), "U+35A8 U+E0100", kDefaultFontStyle, &runs);
itemize(reversedCollection, "U+35A8 U+E0100", kDefaultFontStyle, &runs);
EXPECT_EQ(fontB.get(), runs[0].fakedFont.font);
}
@ -1446,34 +1441,34 @@ TEST_F(FontCollectionItemizeTest, itemizeShouldKeepOrderForVS) {
TEST_F(FontCollectionItemizeTest, itemizeShouldKeepOrderForVS2) {
const FontStyle kDefaultFontStyle;
MinikinAutoUnref<MinikinFont> dummyFont(new MinikinFontForTest(kNoGlyphFont));
MinikinAutoUnref<MinikinFont> hasCmapFormat14Font(
std::shared_ptr<MinikinFont> dummyFont(new MinikinFontForTest(kNoGlyphFont));
std::shared_ptr<MinikinFont> hasCmapFormat14Font(
new MinikinFontForTest(kHasCmapFormat14Font));
MinikinAutoUnref<MinikinFont> noCmapFormat14Font(
std::shared_ptr<MinikinFont> noCmapFormat14Font(
new MinikinFontForTest(kNoCmapFormat14Font));
MinikinAutoUnref<FontFamily> dummyFamily(new FontFamily(
std::vector<Font>({ Font(dummyFont.get(), FontStyle()) })));
MinikinAutoUnref<FontFamily> hasCmapFormat14Family(new FontFamily(
std::vector<Font>({ Font(hasCmapFormat14Font.get(), FontStyle()) })));
MinikinAutoUnref<FontFamily> noCmapFormat14Family(new FontFamily(
std::vector<Font>({ Font(noCmapFormat14Font.get(), FontStyle()) })));
std::shared_ptr<FontFamily> dummyFamily(new FontFamily(
std::vector<Font>({ Font(dummyFont, FontStyle()) })));
std::shared_ptr<FontFamily> hasCmapFormat14Family(new FontFamily(
std::vector<Font>({ Font(hasCmapFormat14Font, FontStyle()) })));
std::shared_ptr<FontFamily> noCmapFormat14Family(new FontFamily(
std::vector<Font>({ Font(noCmapFormat14Font, FontStyle()) })));
std::vector<FontFamily*> families =
{ dummyFamily.get(), hasCmapFormat14Family.get(), noCmapFormat14Family.get() };
std::vector<FontFamily*> reversedFamilies =
{ dummyFamily.get(), noCmapFormat14Family.get(), hasCmapFormat14Family.get() };
std::vector<std::shared_ptr<FontFamily>> families =
{ dummyFamily, hasCmapFormat14Family, noCmapFormat14Family };
std::vector<std::shared_ptr<FontFamily>> reversedFamilies =
{ dummyFamily, noCmapFormat14Family, hasCmapFormat14Family };
MinikinAutoUnref<FontCollection> collection(new FontCollection(families));
MinikinAutoUnref<FontCollection> reversedCollection(new FontCollection(reversedFamilies));
std::shared_ptr<FontCollection> collection(new FontCollection(families));
std::shared_ptr<FontCollection> reversedCollection(new FontCollection(reversedFamilies));
// Both hasCmapFormat14Font/noCmapFormat14Font support U+5380 but don't support U+5380 U+E0100.
// The first font should be selected.
std::vector<FontCollection::Run> runs;
itemize(collection.get(), "U+5380 U+E0100", kDefaultFontStyle, &runs);
itemize(collection, "U+5380 U+E0100", kDefaultFontStyle, &runs);
EXPECT_EQ(hasCmapFormat14Font.get(), runs[0].fakedFont.font);
itemize(reversedCollection.get(), "U+5380 U+E0100", kDefaultFontStyle, &runs);
itemize(reversedCollection, "U+5380 U+E0100", kDefaultFontStyle, &runs);
EXPECT_EQ(noCmapFormat14Font.get(), runs[0].fakedFont.font);
}

View File

@ -57,11 +57,11 @@ void expectVSGlyphs(const FontCollection* fc, uint32_t codepoint, const std::set
}
TEST(FontCollectionTest, hasVariationSelectorTest) {
MinikinAutoUnref<MinikinFont> font(new MinikinFontForTest(kVsTestFont));
MinikinAutoUnref<FontFamily> family(new FontFamily(
std::vector<Font>({ Font(font.get(), FontStyle()) })));
std::vector<FontFamily*> families({family.get()});
MinikinAutoUnref<FontCollection> fc(new FontCollection(families));
std::shared_ptr<MinikinFont> font(new MinikinFontForTest(kVsTestFont));
std::shared_ptr<FontFamily> family(new FontFamily(
std::vector<Font>({ Font(font, FontStyle()) })));
std::vector<std::shared_ptr<FontFamily>> families({ family });
std::shared_ptr<FontCollection> fc(new FontCollection(families));
EXPECT_FALSE(fc->hasVariationSelector(0x82A6, 0));
expectVSGlyphs(fc.get(), 0x82A6, std::set<uint32_t>({0xFE00, 0xE0100, 0xE0101, 0xE0102}));
@ -79,7 +79,7 @@ TEST(FontCollectionTest, hasVariationSelectorTest) {
const char kEmojiXmlFile[] = kTestFontDir "emoji.xml";
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.
EXPECT_TRUE(collection->hasVariationSelector(0x2623, 0xFE0E));
@ -109,7 +109,7 @@ TEST(FontCollectionTest, hasVariationSelectorTest_emoji) {
}
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
// category. Should return true even if U+FE0E was appended.
@ -126,17 +126,17 @@ TEST(FontCollectionTest, createWithVariations) {
const char kMultiAxisFont[] = kTestFontDir "/MultiAxis.ttf";
const char kNoAxisFont[] = kTestFontDir "/Regular.ttf";
MinikinAutoUnref<MinikinFont> multiAxisFont(new MinikinFontForTest(kMultiAxisFont));
MinikinAutoUnref<FontFamily> multiAxisFamily(new FontFamily(
std::vector<Font>({ Font(multiAxisFont.get(), FontStyle()) })));
std::vector<FontFamily*> multiAxisFamilies({multiAxisFamily.get()});
MinikinAutoUnref<FontCollection> multiAxisFc(new FontCollection(multiAxisFamilies));
std::shared_ptr<MinikinFont> multiAxisFont(new MinikinFontForTest(kMultiAxisFont));
std::shared_ptr<FontFamily> multiAxisFamily(new FontFamily(
std::vector<Font>({ Font(multiAxisFont, FontStyle()) })));
std::vector<std::shared_ptr<FontFamily>> multiAxisFamilies({multiAxisFamily});
std::shared_ptr<FontCollection> multiAxisFc(new FontCollection(multiAxisFamilies));
MinikinAutoUnref<MinikinFont> noAxisFont(new MinikinFontForTest(kNoAxisFont));
MinikinAutoUnref<FontFamily> noAxisFamily(new FontFamily(
std::vector<Font>({ Font(noAxisFont.get(), FontStyle()) })));
std::vector<FontFamily*> noAxisFamilies({noAxisFamily.get()});
MinikinAutoUnref<FontCollection> noAxisFc(new FontCollection(noAxisFamilies));
std::shared_ptr<MinikinFont> noAxisFont(new MinikinFontForTest(kNoAxisFont));
std::shared_ptr<FontFamily> noAxisFamily(new FontFamily(
std::vector<Font>({ Font(noAxisFont, FontStyle()) })));
std::vector<std::shared_ptr<FontFamily>> noAxisFamilies({noAxisFamily});
std::shared_ptr<FontCollection> noAxisFc(new FontCollection(noAxisFamilies));
{
// Do not ceate new instance if none of variations are specified.
@ -150,7 +150,7 @@ TEST(FontCollectionTest, createWithVariations) {
std::vector<FontVariation> variations = {
{ MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f }
};
MinikinAutoUnref<FontCollection> newFc(
std::shared_ptr<FontCollection> newFc(
multiAxisFc->createCollectionWithVariation(variations));
EXPECT_NE(nullptr, newFc.get());
EXPECT_NE(multiAxisFc.get(), newFc.get());
@ -163,7 +163,7 @@ TEST(FontCollectionTest, createWithVariations) {
{ MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f },
{ MinikinFont::MakeTag('w', 'g', 'h', 't'), 1.0f }
};
MinikinAutoUnref<FontCollection> newFc(
std::shared_ptr<FontCollection> newFc(
multiAxisFc->createCollectionWithVariation(variations));
EXPECT_NE(nullptr, newFc.get());
EXPECT_NE(multiAxisFc.get(), newFc.get());
@ -184,7 +184,7 @@ TEST(FontCollectionTest, createWithVariations) {
{ MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f },
{ MinikinFont::MakeTag('Z', 'Z', 'Z', 'Z'), 1.0f }
};
MinikinAutoUnref<FontCollection> newFc(
std::shared_ptr<FontCollection> newFc(
multiAxisFc->createCollectionWithVariation(variations));
EXPECT_NE(nullptr, newFc.get());
EXPECT_NE(multiAxisFc.get(), newFc.get());

View File

@ -529,12 +529,9 @@ void expectVSGlyphs(FontFamily* family, uint32_t codepoint, const std::set<uint3
}
TEST_F(FontFamilyTest, hasVariationSelectorTest) {
MinikinAutoUnref<MinikinFontForTest>
minikinFont(new MinikinFontForTest(kVsTestFont));
MinikinAutoUnref<FontFamily> family(
new FontFamily(std::vector<Font>{
Font(minikinFont.get(), FontStyle())
}));
std::shared_ptr<MinikinFont> minikinFont(new MinikinFontForTest(kVsTestFont));
std::shared_ptr<FontFamily> family(
new FontFamily(std::vector<Font>{ Font(minikinFont, FontStyle()) }));
android::AutoMutex _l(gMinikinLock);
@ -585,10 +582,10 @@ TEST_F(FontFamilyTest, hasVSTableTest) {
"Font " + testCase.fontPath + " should 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));
MinikinAutoUnref<FontFamily> family(new FontFamily(
std::vector<Font>{ Font(minikinFont.get(), FontStyle()) }));
std::shared_ptr<FontFamily> family(new FontFamily(
std::vector<Font>{ Font(minikinFont, FontStyle()) }));
android::AutoMutex _l(gMinikinLock);
EXPECT_EQ(testCase.hasVSTable, family->hasVSTable());
}
@ -599,13 +596,15 @@ TEST_F(FontFamilyTest, createFamilyWithVariationTest) {
const char kMultiAxisFont[] = kTestFontDir "/MultiAxis.ttf";
const char kNoAxisFont[] = kTestFontDir "/Regular.ttf";
MinikinAutoUnref<MinikinFont> multiAxisFont(new MinikinFontForTest(kMultiAxisFont));
MinikinAutoUnref<FontFamily> multiAxisFamily(new FontFamily(
std::vector<Font>({Font(multiAxisFont.get(), FontStyle())})));
std::shared_ptr<MinikinFont> multiAxisFont(new MinikinFontForTest(kMultiAxisFont));
std::shared_ptr<FontFamily> multiAxisFamily(
std::shared_ptr<FontFamily>(new FontFamily(
std::vector<Font>({Font(multiAxisFont, FontStyle())}))));
MinikinAutoUnref<MinikinFont> noAxisFont(new MinikinFontForTest(kNoAxisFont));
MinikinAutoUnref<FontFamily> noAxisFamily(new FontFamily(
std::vector<Font>({Font(noAxisFont.get(), FontStyle())})));
std::shared_ptr<MinikinFont> noAxisFont(new MinikinFontForTest(kNoAxisFont));
std::shared_ptr<FontFamily> noAxisFamily(
std::shared_ptr<FontFamily>(new FontFamily(
std::vector<Font>({Font(noAxisFont, FontStyle())}))));
{
// Do not ceate new instance if none of variations are specified.
@ -617,7 +616,7 @@ TEST_F(FontFamilyTest, createFamilyWithVariationTest) {
{
// New instance should be used for supported variation.
std::vector<FontVariation> variations = {{MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f}};
MinikinAutoUnref<FontFamily> newFamily(
std::shared_ptr<FontFamily> newFamily(
multiAxisFamily->createFamilyWithVariation(variations));
EXPECT_NE(nullptr, newFamily.get());
EXPECT_NE(multiAxisFamily.get(), newFamily.get());
@ -629,7 +628,7 @@ TEST_F(FontFamilyTest, createFamilyWithVariationTest) {
{ MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f },
{ MinikinFont::MakeTag('w', 'g', 'h', 't'), 1.0f }
};
MinikinAutoUnref<FontFamily> newFamily(
std::shared_ptr<FontFamily> newFamily(
multiAxisFamily->createFamilyWithVariation(variations));
EXPECT_NE(nullptr, newFamily.get());
EXPECT_NE(multiAxisFamily.get(), newFamily.get());
@ -649,7 +648,7 @@ TEST_F(FontFamilyTest, createFamilyWithVariationTest) {
{ MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f },
{ MinikinFont::MakeTag('Z', 'Z', 'Z', 'Z'), 1.0f }
};
MinikinAutoUnref<FontFamily> newFamily(
std::shared_ptr<FontFamily> newFamily(
multiAxisFamily->createFamilyWithVariation(variations));
EXPECT_NE(nullptr, newFamily.get());
EXPECT_NE(multiAxisFamily.get(), newFamily.get());

View File

@ -20,6 +20,8 @@
#include <gtest/gtest.h>
#include <utils/Mutex.h>
#include <memory>
#include <hb.h>
#include "MinikinInternal.h"
@ -37,13 +39,13 @@ public:
};
TEST_F(HbFontCacheTest, getHbFontLockedTest) {
MinikinAutoUnref<MinikinFontForTest> fontA(
std::shared_ptr<MinikinFontForTest> fontA(
new MinikinFontForTest(kTestFontDir "Regular.ttf"));
MinikinAutoUnref<MinikinFontForTest> fontB(
std::shared_ptr<MinikinFontForTest> fontB(
new MinikinFontForTest(kTestFontDir "Bold.ttf"));
MinikinAutoUnref<MinikinFontForTest> fontC(
std::shared_ptr<MinikinFontForTest> fontC(
new MinikinFontForTest(kTestFontDir "BoldItalic.ttf"));
android::AutoMutex _l(gMinikinLock);
@ -65,7 +67,7 @@ TEST_F(HbFontCacheTest, getHbFontLockedTest) {
}
TEST_F(HbFontCacheTest, purgeCacheTest) {
MinikinAutoUnref<MinikinFontForTest> minikinFont(
std::shared_ptr<MinikinFontForTest> minikinFont(
new MinikinFontForTest(kTestFontDir "Regular.ttf"));
android::AutoMutex _l(gMinikinLock);

View File

@ -53,14 +53,14 @@ protected:
virtual ~LayoutTest() {}
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 {
mCollection->Unref();
}
FontCollection* mCollection;
std::shared_ptr<FontCollection> mCollection;
};
TEST_F(LayoutTest, doLayoutTest) {
@ -70,8 +70,7 @@ TEST_F(LayoutTest, doLayoutTest) {
float advances[kMaxAdvanceLength];
std::vector<float> expectedValues;
Layout layout;
layout.setFontCollection(mCollection);
Layout layout(mCollection);
std::vector<uint16_t> text;
// The mock implementation returns 10.0f advance and 0,0-10x10 bounds for all glyph.
@ -157,8 +156,7 @@ TEST_F(LayoutTest, doLayoutTest_wordSpacing) {
std::vector<float> expectedValues;
std::vector<uint16_t> text;
Layout layout;
layout.setFontCollection(mCollection);
Layout layout(mCollection);
paint.wordSpacing = 5.0f;
@ -252,8 +250,7 @@ TEST_F(LayoutTest, doLayoutTest_negativeWordSpacing) {
float advances[kMaxAdvanceLength];
std::vector<float> expectedValues;
Layout layout;
layout.setFontCollection(mCollection);
Layout layout(mCollection);
std::vector<uint16_t> text;
// Negative word spacing also should work.
@ -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.
} // namespace minikin

View File

@ -32,7 +32,7 @@ FontCollection* getFontCollection(const char* fontDir, const char* fontXml) {
xmlDoc* doc = xmlReadFile(fontXml, NULL, 0);
xmlNode* familySet = xmlDocGetRootElement(doc);
std::vector<FontFamily*> families;
std::vector<std::shared_ptr<FontFamily>> families;
for (xmlNode* familyNode = familySet->children; familyNode; familyNode = familyNode->next) {
if (xmlStrcmp(familyNode->name, (const xmlChar*)"family") != 0) {
continue;
@ -69,34 +69,29 @@ FontCollection* getFontCollection(const char* fontDir, const char* fontXml) {
}
if (index == nullptr) {
MinikinAutoUnref<MinikinFontForTest>
minikinFont(new MinikinFontForTest(fontPath));
fonts.push_back(Font(minikinFont.get(), FontStyle(weight, italic)));
std::shared_ptr<MinikinFont> minikinFont(new MinikinFontForTest(fontPath));
fonts.push_back(Font(minikinFont, FontStyle(weight, italic)));
} else {
MinikinAutoUnref<MinikinFontForTest>
minikinFont(new MinikinFontForTest(fontPath, atoi((const char*)index)));
fonts.push_back(Font(minikinFont.get(), FontStyle(weight, italic)));
std::shared_ptr<MinikinFont> minikinFont(
new MinikinFontForTest(fontPath, atoi((const char*)index)));
fonts.push_back(Font(minikinFont, FontStyle(weight, italic)));
}
}
xmlChar* lang = xmlGetProp(familyNode, (const xmlChar*)"lang");
FontFamily* family;
std::shared_ptr<FontFamily> family;
if (lang == nullptr) {
family = new FontFamily(variant, std::move(fonts));
family.reset(new FontFamily(variant, std::move(fonts)));
} else {
uint32_t langId = FontStyle::registerLanguageList(
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);
}
xmlFreeDoc(doc);
FontCollection* collection = new FontCollection(families);
for (size_t i = 0; i < families.size(); ++i) {
families[i]->Unref();
}
return collection;
return new FontCollection(families);
}
} // namespace minikin

View File

@ -69,9 +69,9 @@ void MinikinFontForTest::GetBounds(MinikinRect* bounds, uint32_t /* glyph_id */,
bounds->mBottom = 10.0f;
}
MinikinFont* MinikinFontForTest::createFontWithVariation(
std::shared_ptr<MinikinFont> MinikinFontForTest::createFontWithVariation(
const std::vector<FontVariation>& variations) const {
return new MinikinFontForTest(mFontPath, mFontIndex, variations);
return std::shared_ptr<MinikinFont>(new MinikinFontForTest(mFontPath, mFontIndex, variations));
}
} // namespace minikin

View File

@ -43,7 +43,8 @@ public:
size_t GetFontSize() const { return mFontSize; }
int GetFontIndex() const { return mFontIndex; }
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:
MinikinFontForTest() = delete;
MinikinFontForTest(const MinikinFontForTest&) = delete;

View File

@ -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);
}
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> result;
int32_t i = 0;

View File

@ -19,6 +19,9 @@ namespace minikin {
void ParseUnicode(uint16_t* buf, size_t buf_size, const char* src, size_t* result_size,
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.
std::vector<uint16_t> utf8ToUtf16(const std::string& text);