mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Merge "Remove MinikinRefCounted and use shared_ptr instead"
This commit is contained in:
commit
2f1aebfcc6
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
@ -44,7 +44,6 @@ minikin_src_files := \
|
||||
LineBreaker.cpp \
|
||||
Measurement.cpp \
|
||||
MinikinInternal.cpp \
|
||||
MinikinRefCounted.cpp \
|
||||
MinikinFont.cpp \
|
||||
MinikinFontFreeType.cpp \
|
||||
SparseBitSet.cpp \
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -16,10 +16,12 @@
|
||||
|
||||
#include <minikin/MinikinFont.h>
|
||||
#include "HbFontCache.h"
|
||||
#include "MinikinInternal.h"
|
||||
|
||||
namespace minikin {
|
||||
|
||||
MinikinFont::~MinikinFont() {
|
||||
android::AutoMutex _l(gMinikinLock);
|
||||
purgeHbFontLocked(this);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user