diff --git a/engine/src/flutter/include/minikin/FontCollection.h b/engine/src/flutter/include/minikin/FontCollection.h index 42499a04699..23645387997 100644 --- a/engine/src/flutter/include/minikin/FontCollection.h +++ b/engine/src/flutter/include/minikin/FontCollection.h @@ -17,20 +17,19 @@ #ifndef MINIKIN_FONT_COLLECTION_H #define MINIKIN_FONT_COLLECTION_H -#include +#include #include +#include -#include #include #include namespace minikin { -class FontCollection : public MinikinRefCounted { +class FontCollection { public: - explicit FontCollection(const std::vector& typefaces); - - ~FontCollection(); + explicit FontCollection(const std::vector>& typefaces); + explicit FontCollection(std::shared_ptr&& 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& variations); + std::shared_ptr + createCollectionWithVariation(const std::vector& 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>& typefaces); + + const std::shared_ptr& 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) 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) 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 mFamilies; + std::vector> mFamilies; - // This vector contains pointers into mInstances - // This vector can't be empty. - std::vector mFamilyVec; - - // This vector has pointers to the font family instance which has cmap 14 subtable. - std::vector 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 mRanges; + std::vector> mFamilyVec; + + // This vector has pointers to the font family instances which have cmap 14 subtables. + std::vector> mVSFamilyVec; // Set of supported axes in this collection. std::unordered_set mSupportedAxes; diff --git a/engine/src/flutter/include/minikin/FontFamily.h b/engine/src/flutter/include/minikin/FontFamily.h index 9ce8c6537c0..c7018a6f8c0 100644 --- a/engine/src/flutter/include/minikin/FontFamily.h +++ b/engine/src/flutter/include/minikin/FontFamily.h @@ -17,14 +17,15 @@ #ifndef MINIKIN_FONT_FAMILY_H #define MINIKIN_FONT_FAMILY_H -#include +#include #include #include +#include + #include #include -#include #include namespace minikin { @@ -102,19 +103,17 @@ struct FakedFont { typedef uint32_t AxisTag; struct Font { - Font(MinikinFont* typeface, FontStyle style); + Font(const std::shared_ptr& typeface, FontStyle style); + Font(std::shared_ptr&& typeface, FontStyle style); Font(Font&& o); Font(const Font& o); - ~Font(); - MinikinFont* typeface; + std::shared_ptr typeface; FontStyle style; std::unordered_set 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* 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&& fonts); FontFamily(int variant, std::vector&& 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& 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& 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& 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& variations) const; + std::shared_ptr createFamilyWithVariation( + const std::vector& variations) const; private: void computeCoverage(); diff --git a/engine/src/flutter/include/minikin/Layout.h b/engine/src/flutter/include/minikin/Layout.h index 625e05c433c..e9849c382c3 100644 --- a/engine/src/flutter/include/minikin/Layout.h +++ b/engine/src/flutter/include/minikin/Layout.h @@ -19,6 +19,7 @@ #include +#include #include #include @@ -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& 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& 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& 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& 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 mGlyphs; std::vector mAdvances; - const FontCollection* mCollection; + std::shared_ptr mCollection; std::vector mFaces; float mAdvance; MinikinRect mBounds; diff --git a/engine/src/flutter/include/minikin/LineBreaker.h b/engine/src/flutter/include/minikin/LineBreaker.h index 75e54b05f1b..e93953666be 100644 --- a/engine/src/flutter/include/minikin/LineBreaker.h +++ b/engine/src/flutter/include/minikin/LineBreaker.h @@ -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& typeface, + FontStyle style, size_t start, size_t end, bool isRtl); void addReplacement(size_t start, size_t end, float width); diff --git a/engine/src/flutter/include/minikin/MinikinFont.h b/engine/src/flutter/include/minikin/MinikinFont.h index 64bab02a206..1d5ebb774a8 100644 --- a/engine/src/flutter/include/minikin/MinikinFont.h +++ b/engine/src/flutter/include/minikin/MinikinFont.h @@ -18,8 +18,8 @@ #define MINIKIN_FONT_H #include +#include -#include #include // 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& GetAxes() const = 0; - virtual MinikinFont* createFontWithVariation(const std::vector&) const { + virtual std::shared_ptr createFontWithVariation( + const std::vector&) const { return nullptr; } diff --git a/engine/src/flutter/include/minikin/MinikinRefCounted.h b/engine/src/flutter/include/minikin/MinikinRefCounted.h deleted file mode 100644 index 960b6cc46da..00000000000 --- a/engine/src/flutter/include/minikin/MinikinRefCounted.h +++ /dev/null @@ -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 -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 diff --git a/engine/src/flutter/libs/minikin/Android.mk b/engine/src/flutter/libs/minikin/Android.mk index 44abb885325..603638e754d 100644 --- a/engine/src/flutter/libs/minikin/Android.mk +++ b/engine/src/flutter/libs/minikin/Android.mk @@ -44,7 +44,6 @@ minikin_src_files := \ LineBreaker.cpp \ Measurement.cpp \ MinikinInternal.cpp \ - MinikinRefCounted.cpp \ MinikinFont.cpp \ MinikinFontFreeType.cpp \ SparseBitSet.cpp \ diff --git a/engine/src/flutter/libs/minikin/FontCollection.cpp b/engine/src/flutter/libs/minikin/FontCollection.cpp index 9d0e2c8b381..c351c3a58dc 100644 --- a/engine/src/flutter/libs/minikin/FontCollection.cpp +++ b/engine/src/flutter/libs/minikin/FontCollection.cpp @@ -79,8 +79,18 @@ static bool isEmojiStyleVSBase(uint32_t cp) { uint32_t FontCollection::sNextId = 0; -FontCollection::FontCollection(const vector& typefaces) : +FontCollection::FontCollection(std::shared_ptr&& typeface) : mMaxChar(0) { + std::vector> typefaces; + typefaces.push_back(typeface); + init(typefaces); +} + +FontCollection::FontCollection(const vector>& typefaces) : mMaxChar(0) { + init(typefaces); +} + +void FontCollection::init(const vector>& typefaces) { android::AutoMutex _l(gMinikinLock); mId = sNextId++; vector lastChar; @@ -90,12 +100,10 @@ FontCollection::FontCollection(const vector& 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& 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& 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& 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& 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) 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) 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& FontCollection::getFamilyForChar(uint32_t ch, uint32_t vs, uint32_t langListId, int variant) const { if (ch >= mMaxChar) { return mFamilies[0]; } - const std::vector& familyVec = (vs == 0) ? mFamilyVec : mFamilies; + const std::vector>& 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& 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* 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& 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(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::createCollectionWithVariation( const std::vector& variations) { if (variations.empty() || mSupportedAxes.empty()) { return nullptr; @@ -484,22 +480,17 @@ FontCollection* FontCollection::createCollectionWithVariation( return nullptr; } - std::vector families; - for (FontFamily* family : mFamilies) { - FontFamily* newFamily = family->createFamilyWithVariation(variations); + std::vector > families; + for (const std::shared_ptr& family : mFamilies) { + std::shared_ptr 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(new FontCollection(families)); } uint32_t FontCollection::getId() const { diff --git a/engine/src/flutter/libs/minikin/FontFamily.cpp b/engine/src/flutter/libs/minikin/FontFamily.cpp index 6d44bc395c1..d0a0138ef2d 100644 --- a/engine/src/flutter/libs/minikin/FontFamily.cpp +++ b/engine/src/flutter/libs/minikin/FontFamily.cpp @@ -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& typeface, FontStyle style) : typeface(typeface), style(style) { - android::AutoMutex _l(gMinikinLock); - typeface->RefLocked(); + loadAxes(); +} +Font::Font(std::shared_ptr&& 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* fonts) { - android::AutoMutex _l(gMinikinLock); - fonts->clear(); -} - +// static FontFamily::FontFamily(std::vector&& fonts) : FontFamily(0 /* variant */, std::move(fonts)) { } @@ -120,10 +115,11 @@ FontFamily::FontFamily(uint32_t langId, int variant, std::vector&& fonts) FontFamily::~FontFamily() { } -bool FontFamily::analyzeStyle(MinikinFont* typeface, int* weight, bool* italic) { +bool FontFamily::analyzeStyle(const std::shared_ptr& 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::createFamilyWithVariation( const std::vector& variations) const { if (variations.empty() || mSupportedAxes.empty()) { return nullptr; @@ -243,19 +234,17 @@ FontFamily* FontFamily::createFamilyWithVariation( } } } - MinikinFont* minikinFont = nullptr; + std::shared_ptr 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(new FontFamily(mLangId, mVariant, std::move(fonts))); } } // namespace minikin diff --git a/engine/src/flutter/libs/minikin/HbFontCache.cpp b/engine/src/flutter/libs/minikin/HbFontCache.cpp index e871b4ef9b4..af3d783bc84 100644 --- a/engine/src/flutter/libs/minikin/HbFontCache.cpp +++ b/engine/src/flutter/libs/minikin/HbFontCache.cpp @@ -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; diff --git a/engine/src/flutter/libs/minikin/HbFontCache.h b/engine/src/flutter/libs/minikin/HbFontCache.h index fba685aeb27..59969e287e0 100644 --- a/engine/src/flutter/libs/minikin/HbFontCache.h +++ b/engine/src/flutter/libs/minikin/HbFontCache.h @@ -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 diff --git a/engine/src/flutter/libs/minikin/Layout.cpp b/engine/src/flutter/libs/minikin/Layout.cpp index 117f3262363..6b28f57a331 100644 --- a/engine/src/flutter/libs/minikin/Layout.cpp +++ b/engine/src/flutter/libs/minikin/Layout.cpp @@ -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& 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& 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(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& 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& 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& 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 items; mCollection->itemize(buf + start, count, ctx->style, &items); - if (isRtl) { - std::reverse(items.begin(), items.end()); - } vector 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(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); } diff --git a/engine/src/flutter/libs/minikin/LineBreaker.cpp b/engine/src/flutter/libs/minikin/LineBreaker.cpp index c21e6384c33..3965cbd4c84 100644 --- a/engine/src/flutter/libs/minikin/LineBreaker.cpp +++ b/engine/src/flutter/libs/minikin/LineBreaker.cpp @@ -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& typeface, FontStyle style, size_t start, size_t end, bool isRtl) { float width = 0.0f; int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR; diff --git a/engine/src/flutter/libs/minikin/MinikinFont.cpp b/engine/src/flutter/libs/minikin/MinikinFont.cpp index 8aee01de7ed..6bf6a4ae3b7 100644 --- a/engine/src/flutter/libs/minikin/MinikinFont.cpp +++ b/engine/src/flutter/libs/minikin/MinikinFont.cpp @@ -16,10 +16,12 @@ #include #include "HbFontCache.h" +#include "MinikinInternal.h" namespace minikin { MinikinFont::~MinikinFont() { + android::AutoMutex _l(gMinikinLock); purgeHbFontLocked(this); } diff --git a/engine/src/flutter/libs/minikin/MinikinInternal.cpp b/engine/src/flutter/libs/minikin/MinikinInternal.cpp index a98fc19e4cd..e766dce992d 100644 --- a/engine/src/flutter/libs/minikin/MinikinInternal.cpp +++ b/engine/src/flutter/libs/minikin/MinikinInternal.cpp @@ -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); diff --git a/engine/src/flutter/libs/minikin/MinikinInternal.h b/engine/src/flutter/libs/minikin/MinikinInternal.h index 9557d827df1..365f20cc0df 100644 --- a/engine/src/flutter/libs/minikin/MinikinInternal.h +++ b/engine/src/flutter/libs/minikin/MinikinInternal.h @@ -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 { diff --git a/engine/src/flutter/libs/minikin/MinikinRefCounted.cpp b/engine/src/flutter/libs/minikin/MinikinRefCounted.cpp deleted file mode 100644 index 6914a012f84..00000000000 --- a/engine/src/flutter/libs/minikin/MinikinRefCounted.cpp +++ /dev/null @@ -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 - -namespace minikin { - -void MinikinRefCounted::Ref() { - android::AutoMutex _l(gMinikinLock); - this->RefLocked(); -} - -void MinikinRefCounted::Unref() { - android::AutoMutex _l(gMinikinLock); - this->UnrefLocked(); -} - -} // namespace minikin diff --git a/engine/src/flutter/sample/MinikinSkia.cpp b/engine/src/flutter/sample/MinikinSkia.cpp index ec1e9da78c2..1ba7cccb417 100644 --- a/engine/src/flutter/sample/MinikinSkia.cpp +++ b/engine/src/flutter/sample/MinikinSkia.cpp @@ -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(); } diff --git a/engine/src/flutter/sample/MinikinSkia.h b/engine/src/flutter/sample/MinikinSkia.h index 8284f5d0f9a..5ebf1b61617 100644 --- a/engine/src/flutter/sample/MinikinSkia.h +++ b/engine/src/flutter/sample/MinikinSkia.h @@ -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& GetAxes() const { return mAxes; } + const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy) const; - SkTypeface *GetSkTypeface(); + SkTypeface *GetSkTypeface() const; private: sk_sp mTypeface; diff --git a/engine/src/flutter/sample/example.cpp b/engine/src/flutter/sample/example.cpp index 1c9c322d232..3df09050030 100644 --- a/engine/src/flutter/sample/example.cpp +++ b/engine/src/flutter/sample/example.cpp @@ -33,7 +33,7 @@ using namespace minikin; FT_Library library; // TODO: this should not be a global FontCollection *makeFontCollection() { - vectortypefaces; + vector>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 font(new MinikinFontFreeType(face)); fonts.push_back(Font(font, FontStyle())); } - FontFamily *family = new FontFamily(std::move(fonts)); + std::shared_ptr 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, FontStyle()) })); + std::shared_ptr font(new MinikinFontFreeType(face)); + family.reset(new FontFamily(std::vector({ 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 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; diff --git a/engine/src/flutter/sample/example_skia.cpp b/engine/src/flutter/sample/example_skia.cpp index 6e6f868051c..6fa788b9e77 100644 --- a/engine/src/flutter/sample/example_skia.cpp +++ b/engine/src/flutter/sample/example_skia.cpp @@ -42,7 +42,7 @@ namespace minikin { FT_Library library; // TODO: this should not be a global FontCollection *makeFontCollection() { - vectortypefaces; + vector> 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 skFace = SkTypeface::MakeFromFile(fn); - MinikinFont *font = new MinikinFontSkia(std::move(skFace)); + std::shared_ptr font(new MinikinFontSkia(std::move(skFace))); fonts.push_back(Font(font, FontStyle())); } - FontFamily *family = new FontFamily(std::move(fonts)); + std::shared_ptr family(new FontFamily(std::move(fonts))); typefaces.push_back(family); #if 1 const char *fn = "/system/fonts/DroidSansDevanagari-Regular.ttf"; sk_sp skFace = SkTypeface::MakeFromFile(fn); - MinikinFont *font = new MinikinFontSkia(std::move(skFace)); - family = new FontFamily(std::vector({ Font(font, FontStyle()) })); + std::shared_ptr font(new MinikinFontSkia(std::move(skFace))); + family.reset(new FontFamily(std::vector({ 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(layout->getFont(i)); + const MinikinFontSkia *mfs = static_cast(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 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); diff --git a/engine/src/flutter/tests/perftests/FontCollection.cpp b/engine/src/flutter/tests/perftests/FontCollection.cpp index a54607d1833..6f9d636ca30 100644 --- a/engine/src/flutter/tests/perftests/FontCollection.cpp +++ b/engine/src/flutter/tests/perftests/FontCollection.cpp @@ -15,7 +15,8 @@ */ #include -#include +#include + #include #include #include @@ -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 collection( + std::shared_ptr 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 collection( + std::shared_ptr collection( getFontCollection(SYSTEM_FONT_PATH, SYSTEM_FONT_XML)); size_t testIndex = state.range(0); diff --git a/engine/src/flutter/tests/unittest/FontCollectionItemizeTest.cpp b/engine/src/flutter/tests/unittest/FontCollectionItemizeTest.cpp index 5c5a5d343cb..aa142cccdcd 100644 --- a/engine/src/flutter/tests/unittest/FontCollectionItemizeTest.cpp +++ b/engine/src/flutter/tests/unittest/FontCollectionItemizeTest.cpp @@ -16,6 +16,8 @@ #include +#include + #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& collection, const char* str, FontStyle style, std::vector* 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 collection(getFontCollection(kTestFontDir, kItemizeFontXml)); + std::shared_ptr collection(getFontCollection(kTestFontDir, kItemizeFontXml)); std::vector 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 collection(getFontCollection(kTestFontDir, kItemizeFontXml)); + std::shared_ptr collection(getFontCollection(kTestFontDir, kItemizeFontXml)); std::vector 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 collection(getFontCollection(kTestFontDir, kItemizeFontXml)); + std::shared_ptr collection(getFontCollection(kTestFontDir, kItemizeFontXml)); std::vector 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 collection(getFontCollection(kTestFontDir, kItemizeFontXml)); + std::shared_ptr collection(getFontCollection(kTestFontDir, kItemizeFontXml)); std::vector 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 collection(getFontCollection(kTestFontDir, kItemizeFontXml)); + std::shared_ptr collection(getFontCollection(kTestFontDir, kItemizeFontXml)); std::vector 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 collection(getFontCollection(kTestFontDir, kItemizeFontXml)); + std::shared_ptr collection(getFontCollection(kTestFontDir, kItemizeFontXml)); std::vector 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 collection(getFontCollection(kTestFontDir, kItemizeFontXml)); + std::shared_ptr collection(getFontCollection(kTestFontDir, kItemizeFontXml)); std::vector 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 collection(getFontCollection(kTestFontDir, kItemizeFontXml)); + std::shared_ptr collection(getFontCollection(kTestFontDir, kItemizeFontXml)); std::vector 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 families; - MinikinAutoUnref font(new MinikinFontForTest(kLatinFont)); - FontFamily* family1 = new FontFamily(VARIANT_DEFAULT, - std::vector{ Font(font.get(), FontStyle()) }); + std::vector> families; + std::shared_ptr font(new MinikinFontForTest(kLatinFont)); + std::shared_ptr family1(new FontFamily(VARIANT_DEFAULT, + std::vector{ Font(font, FontStyle()) })); families.push_back(family1); - MinikinAutoUnref font2(new MinikinFontForTest(kVSTestFont)); - FontFamily* family2 = new FontFamily(VARIANT_DEFAULT, - std::vector{ Font(font2.get(), FontStyle()) }); + std::shared_ptr font2(new MinikinFontForTest(kVSTestFont)); + std::shared_ptr family2(new FontFamily(VARIANT_DEFAULT, + std::vector{ Font(font2, FontStyle()) })); families.push_back(family2); - FontCollection collection(families); + std::shared_ptr collection(new FontCollection(families)); std::vector 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 families; + std::vector> families; // Prepare first font which doesn't supports U+9AA8 - MinikinAutoUnref firstFamilyMinikinFont( + std::shared_ptr firstFamilyMinikinFont( new MinikinFontForTest(kNoGlyphFont)); - FontFamily* firstFamily = new FontFamily( + std::shared_ptr firstFamily(new FontFamily( FontStyle::registerLanguageList("und"), 0 /* variant */, - std::vector({ Font(firstFamilyMinikinFont.get(), FontStyle()) })); + std::vector({ Font(firstFamilyMinikinFont, FontStyle()) }))); families.push_back(firstFamily); // Prepare font families @@ -824,23 +823,19 @@ TEST_F(FontCollectionItemizeTest, itemize_LanguageScore) { std::unordered_map fontLangIdxMap; for (size_t i = 0; i < testCase.fontLanguages.size(); ++i) { - MinikinAutoUnref minikin_font(new MinikinFontForTest(kJAFont)); - FontFamily* family = new FontFamily( + std::shared_ptr minikin_font(new MinikinFontForTest(kJAFont)); + std::shared_ptr family(new FontFamily( FontStyle::registerLanguageList(testCase.fontLanguages[i]), 0 /* variant */, - std::vector({ Font(minikin_font.get(), FontStyle()) })); + std::vector({ Font(minikin_font, FontStyle()) }))); families.push_back(family); fontLangIdxMap.insert(std::make_pair(minikin_font.get(), i)); } - MinikinAutoUnref collection(new FontCollection(families)); - for (auto family : families) { - family->Unref(); - } - + std::shared_ptr collection(new FontCollection(families)); // Do itemize const FontStyle style = FontStyle( FontStyle::registerLanguageList(testCase.userPreferredLanguages)); std::vector 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 collection(getFontCollection(kTestFontDir, kItemizeFontXml)); + std::shared_ptr 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 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 collection(getFontCollection(kTestFontDir, kEmojiXmlFile)); + std::shared_ptr collection(getFontCollection(kTestFontDir, kEmojiXmlFile)); std::vector 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 collection(getFontCollection(kTestFontDir, kEmojiXmlFile)); + std::shared_ptr collection(getFontCollection(kTestFontDir, kEmojiXmlFile)); std::vector 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 collection(getFontCollection(kTestFontDir, kEmojiXmlFile)); + std::shared_ptr collection(getFontCollection(kTestFontDir, kEmojiXmlFile)); std::vector 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 collection(getFontCollection(kTestFontDir, kEmojiXmlFile)); + std::shared_ptr collection(getFontCollection(kTestFontDir, kEmojiXmlFile)); std::vector 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 collection(getFontCollection(kTestFontDir, kEmojiXmlFile)); + std::shared_ptr collection(getFontCollection(kTestFontDir, kEmojiXmlFile)); std::vector 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 dummyFont(new MinikinFontForTest(kNoGlyphFont)); - MinikinAutoUnref fontA(new MinikinFontForTest(kZH_HansFont)); - MinikinAutoUnref fontB(new MinikinFontForTest(kZH_HansFont)); + std::shared_ptr dummyFont(new MinikinFontForTest(kNoGlyphFont)); + std::shared_ptr fontA(new MinikinFontForTest(kZH_HansFont)); + std::shared_ptr fontB(new MinikinFontForTest(kZH_HansFont)); - MinikinAutoUnref dummyFamily(new FontFamily( - std::vector({ Font(dummyFont.get(), FontStyle()) }))); - MinikinAutoUnref familyA(new FontFamily( - std::vector({ Font(fontA.get(), FontStyle()) }))); - MinikinAutoUnref familyB(new FontFamily( - std::vector({ Font(fontB.get(), FontStyle()) }))); + std::shared_ptr dummyFamily(new FontFamily( + std::vector({ Font(dummyFont, FontStyle()) }))); + std::shared_ptr familyA(new FontFamily( + std::vector({ Font(fontA, FontStyle()) }))); + std::shared_ptr familyB(new FontFamily( + std::vector({ Font(fontB, FontStyle()) }))); - std::vector families = - { dummyFamily.get(), familyA.get(), familyB.get() }; - std::vector reversedFamilies = - { dummyFamily.get(), familyB.get(), familyA.get() }; + std::vector> families = + { dummyFamily, familyA, familyB }; + std::vector> reversedFamilies = + { dummyFamily, familyB, familyA }; - MinikinAutoUnref collection(new FontCollection(families)); - MinikinAutoUnref reversedCollection(new FontCollection(reversedFamilies)); + std::shared_ptr collection(new FontCollection(families)); + std::shared_ptr 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 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 dummyFont(new MinikinFontForTest(kNoGlyphFont)); - MinikinAutoUnref hasCmapFormat14Font( + std::shared_ptr dummyFont(new MinikinFontForTest(kNoGlyphFont)); + std::shared_ptr hasCmapFormat14Font( new MinikinFontForTest(kHasCmapFormat14Font)); - MinikinAutoUnref noCmapFormat14Font( + std::shared_ptr noCmapFormat14Font( new MinikinFontForTest(kNoCmapFormat14Font)); - MinikinAutoUnref dummyFamily(new FontFamily( - std::vector({ Font(dummyFont.get(), FontStyle()) }))); - MinikinAutoUnref hasCmapFormat14Family(new FontFamily( - std::vector({ Font(hasCmapFormat14Font.get(), FontStyle()) }))); - MinikinAutoUnref noCmapFormat14Family(new FontFamily( - std::vector({ Font(noCmapFormat14Font.get(), FontStyle()) }))); + std::shared_ptr dummyFamily(new FontFamily( + std::vector({ Font(dummyFont, FontStyle()) }))); + std::shared_ptr hasCmapFormat14Family(new FontFamily( + std::vector({ Font(hasCmapFormat14Font, FontStyle()) }))); + std::shared_ptr noCmapFormat14Family(new FontFamily( + std::vector({ Font(noCmapFormat14Font, FontStyle()) }))); - std::vector families = - { dummyFamily.get(), hasCmapFormat14Family.get(), noCmapFormat14Family.get() }; - std::vector reversedFamilies = - { dummyFamily.get(), noCmapFormat14Family.get(), hasCmapFormat14Family.get() }; + std::vector> families = + { dummyFamily, hasCmapFormat14Family, noCmapFormat14Family }; + std::vector> reversedFamilies = + { dummyFamily, noCmapFormat14Family, hasCmapFormat14Family }; - MinikinAutoUnref collection(new FontCollection(families)); - MinikinAutoUnref reversedCollection(new FontCollection(reversedFamilies)); + std::shared_ptr collection(new FontCollection(families)); + std::shared_ptr 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 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); } diff --git a/engine/src/flutter/tests/unittest/FontCollectionTest.cpp b/engine/src/flutter/tests/unittest/FontCollectionTest.cpp index 68fe582aa3f..100e2069752 100644 --- a/engine/src/flutter/tests/unittest/FontCollectionTest.cpp +++ b/engine/src/flutter/tests/unittest/FontCollectionTest.cpp @@ -57,11 +57,11 @@ void expectVSGlyphs(const FontCollection* fc, uint32_t codepoint, const std::set } TEST(FontCollectionTest, hasVariationSelectorTest) { - MinikinAutoUnref font(new MinikinFontForTest(kVsTestFont)); - MinikinAutoUnref family(new FontFamily( - std::vector({ Font(font.get(), FontStyle()) }))); - std::vector families({family.get()}); - MinikinAutoUnref fc(new FontCollection(families)); + std::shared_ptr font(new MinikinFontForTest(kVsTestFont)); + std::shared_ptr family(new FontFamily( + std::vector({ Font(font, FontStyle()) }))); + std::vector> families({ family }); + std::shared_ptr fc(new FontCollection(families)); EXPECT_FALSE(fc->hasVariationSelector(0x82A6, 0)); expectVSGlyphs(fc.get(), 0x82A6, std::set({0xFE00, 0xE0100, 0xE0101, 0xE0102})); @@ -79,7 +79,7 @@ TEST(FontCollectionTest, hasVariationSelectorTest) { const char kEmojiXmlFile[] = kTestFontDir "emoji.xml"; TEST(FontCollectionTest, hasVariationSelectorTest_emoji) { - MinikinAutoUnref collection(getFontCollection(kTestFontDir, kEmojiXmlFile)); + std::shared_ptr 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 collection(getFontCollection(kTestFontDir, kEmojiXmlFile)); + std::shared_ptr 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 multiAxisFont(new MinikinFontForTest(kMultiAxisFont)); - MinikinAutoUnref multiAxisFamily(new FontFamily( - std::vector({ Font(multiAxisFont.get(), FontStyle()) }))); - std::vector multiAxisFamilies({multiAxisFamily.get()}); - MinikinAutoUnref multiAxisFc(new FontCollection(multiAxisFamilies)); + std::shared_ptr multiAxisFont(new MinikinFontForTest(kMultiAxisFont)); + std::shared_ptr multiAxisFamily(new FontFamily( + std::vector({ Font(multiAxisFont, FontStyle()) }))); + std::vector> multiAxisFamilies({multiAxisFamily}); + std::shared_ptr multiAxisFc(new FontCollection(multiAxisFamilies)); - MinikinAutoUnref noAxisFont(new MinikinFontForTest(kNoAxisFont)); - MinikinAutoUnref noAxisFamily(new FontFamily( - std::vector({ Font(noAxisFont.get(), FontStyle()) }))); - std::vector noAxisFamilies({noAxisFamily.get()}); - MinikinAutoUnref noAxisFc(new FontCollection(noAxisFamilies)); + std::shared_ptr noAxisFont(new MinikinFontForTest(kNoAxisFont)); + std::shared_ptr noAxisFamily(new FontFamily( + std::vector({ Font(noAxisFont, FontStyle()) }))); + std::vector> noAxisFamilies({noAxisFamily}); + std::shared_ptr noAxisFc(new FontCollection(noAxisFamilies)); { // Do not ceate new instance if none of variations are specified. @@ -150,7 +150,7 @@ TEST(FontCollectionTest, createWithVariations) { std::vector variations = { { MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f } }; - MinikinAutoUnref newFc( + std::shared_ptr 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 newFc( + std::shared_ptr 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 newFc( + std::shared_ptr newFc( multiAxisFc->createCollectionWithVariation(variations)); EXPECT_NE(nullptr, newFc.get()); EXPECT_NE(multiAxisFc.get(), newFc.get()); diff --git a/engine/src/flutter/tests/unittest/FontFamilyTest.cpp b/engine/src/flutter/tests/unittest/FontFamilyTest.cpp index fb917500f07..5285f2642b4 100644 --- a/engine/src/flutter/tests/unittest/FontFamilyTest.cpp +++ b/engine/src/flutter/tests/unittest/FontFamilyTest.cpp @@ -529,12 +529,9 @@ void expectVSGlyphs(FontFamily* family, uint32_t codepoint, const std::set - minikinFont(new MinikinFontForTest(kVsTestFont)); - MinikinAutoUnref family( - new FontFamily(std::vector{ - Font(minikinFont.get(), FontStyle()) - })); + std::shared_ptr minikinFont(new MinikinFontForTest(kVsTestFont)); + std::shared_ptr family( + new FontFamily(std::vector{ 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 minikinFont( + std::shared_ptr minikinFont( new MinikinFontForTest(testCase.fontPath)); - MinikinAutoUnref family(new FontFamily( - std::vector{ Font(minikinFont.get(), FontStyle()) })); + std::shared_ptr family(new FontFamily( + std::vector{ 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 multiAxisFont(new MinikinFontForTest(kMultiAxisFont)); - MinikinAutoUnref multiAxisFamily(new FontFamily( - std::vector({Font(multiAxisFont.get(), FontStyle())}))); + std::shared_ptr multiAxisFont(new MinikinFontForTest(kMultiAxisFont)); + std::shared_ptr multiAxisFamily( + std::shared_ptr(new FontFamily( + std::vector({Font(multiAxisFont, FontStyle())})))); - MinikinAutoUnref noAxisFont(new MinikinFontForTest(kNoAxisFont)); - MinikinAutoUnref noAxisFamily(new FontFamily( - std::vector({Font(noAxisFont.get(), FontStyle())}))); + std::shared_ptr noAxisFont(new MinikinFontForTest(kNoAxisFont)); + std::shared_ptr noAxisFamily( + std::shared_ptr(new FontFamily( + std::vector({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 variations = {{MinikinFont::MakeTag('w', 'd', 't', 'h'), 1.0f}}; - MinikinAutoUnref newFamily( + std::shared_ptr 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 newFamily( + std::shared_ptr 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 newFamily( + std::shared_ptr newFamily( multiAxisFamily->createFamilyWithVariation(variations)); EXPECT_NE(nullptr, newFamily.get()); EXPECT_NE(multiAxisFamily.get(), newFamily.get()); diff --git a/engine/src/flutter/tests/unittest/HbFontCacheTest.cpp b/engine/src/flutter/tests/unittest/HbFontCacheTest.cpp index 9a7e63fb2c0..a5581a27b88 100644 --- a/engine/src/flutter/tests/unittest/HbFontCacheTest.cpp +++ b/engine/src/flutter/tests/unittest/HbFontCacheTest.cpp @@ -20,6 +20,8 @@ #include #include +#include + #include #include "MinikinInternal.h" @@ -37,13 +39,13 @@ public: }; TEST_F(HbFontCacheTest, getHbFontLockedTest) { - MinikinAutoUnref fontA( + std::shared_ptr fontA( new MinikinFontForTest(kTestFontDir "Regular.ttf")); - MinikinAutoUnref fontB( + std::shared_ptr fontB( new MinikinFontForTest(kTestFontDir "Bold.ttf")); - MinikinAutoUnref fontC( + std::shared_ptr fontC( new MinikinFontForTest(kTestFontDir "BoldItalic.ttf")); android::AutoMutex _l(gMinikinLock); @@ -65,7 +67,7 @@ TEST_F(HbFontCacheTest, getHbFontLockedTest) { } TEST_F(HbFontCacheTest, purgeCacheTest) { - MinikinAutoUnref minikinFont( + std::shared_ptr minikinFont( new MinikinFontForTest(kTestFontDir "Regular.ttf")); android::AutoMutex _l(gMinikinLock); diff --git a/engine/src/flutter/tests/unittest/LayoutTest.cpp b/engine/src/flutter/tests/unittest/LayoutTest.cpp index c023625b16f..4a849aa3ebc 100644 --- a/engine/src/flutter/tests/unittest/LayoutTest.cpp +++ b/engine/src/flutter/tests/unittest/LayoutTest.cpp @@ -53,14 +53,14 @@ protected: virtual ~LayoutTest() {} virtual void SetUp() override { - mCollection = getFontCollection(SYSTEM_FONT_PATH, SYSTEM_FONT_XML); + mCollection = std::shared_ptr( + getFontCollection(SYSTEM_FONT_PATH, SYSTEM_FONT_XML)); } virtual void TearDown() override { - mCollection->Unref(); } - FontCollection* mCollection; + std::shared_ptr mCollection; }; TEST_F(LayoutTest, doLayoutTest) { @@ -70,8 +70,7 @@ TEST_F(LayoutTest, doLayoutTest) { float advances[kMaxAdvanceLength]; std::vector expectedValues; - Layout layout; - layout.setFontCollection(mCollection); + Layout layout(mCollection); std::vector 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 expectedValues; std::vector 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 expectedValues; - Layout layout; - layout.setFontCollection(mCollection); + Layout layout(mCollection); std::vector 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 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 diff --git a/engine/src/flutter/tests/util/FontTestUtils.cpp b/engine/src/flutter/tests/util/FontTestUtils.cpp index e29a2fe5344..27a693e16dc 100644 --- a/engine/src/flutter/tests/util/FontTestUtils.cpp +++ b/engine/src/flutter/tests/util/FontTestUtils.cpp @@ -32,7 +32,7 @@ FontCollection* getFontCollection(const char* fontDir, const char* fontXml) { xmlDoc* doc = xmlReadFile(fontXml, NULL, 0); xmlNode* familySet = xmlDocGetRootElement(doc); - std::vector families; + std::vector> 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 - minikinFont(new MinikinFontForTest(fontPath)); - fonts.push_back(Font(minikinFont.get(), FontStyle(weight, italic))); + std::shared_ptr minikinFont(new MinikinFontForTest(fontPath)); + fonts.push_back(Font(minikinFont, FontStyle(weight, italic))); } else { - MinikinAutoUnref - minikinFont(new MinikinFontForTest(fontPath, atoi((const char*)index))); - fonts.push_back(Font(minikinFont.get(), FontStyle(weight, italic))); + std::shared_ptr 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 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 diff --git a/engine/src/flutter/tests/util/MinikinFontForTest.cpp b/engine/src/flutter/tests/util/MinikinFontForTest.cpp index f191f07d6e9..723e86ac2d2 100644 --- a/engine/src/flutter/tests/util/MinikinFontForTest.cpp +++ b/engine/src/flutter/tests/util/MinikinFontForTest.cpp @@ -69,9 +69,9 @@ void MinikinFontForTest::GetBounds(MinikinRect* bounds, uint32_t /* glyph_id */, bounds->mBottom = 10.0f; } -MinikinFont* MinikinFontForTest::createFontWithVariation( +std::shared_ptr MinikinFontForTest::createFontWithVariation( const std::vector& variations) const { - return new MinikinFontForTest(mFontPath, mFontIndex, variations); + return std::shared_ptr(new MinikinFontForTest(mFontPath, mFontIndex, variations)); } } // namespace minikin diff --git a/engine/src/flutter/tests/util/MinikinFontForTest.h b/engine/src/flutter/tests/util/MinikinFontForTest.h index 1d0628319bb..6e230e1d319 100644 --- a/engine/src/flutter/tests/util/MinikinFontForTest.h +++ b/engine/src/flutter/tests/util/MinikinFontForTest.h @@ -43,7 +43,8 @@ public: size_t GetFontSize() const { return mFontSize; } int GetFontIndex() const { return mFontIndex; } const std::vector& GetAxes() const { return mVariations; } - MinikinFont* createFontWithVariation(const std::vector& variations) const; + std::shared_ptr createFontWithVariation( + const std::vector& variations) const; private: MinikinFontForTest() = delete; MinikinFontForTest(const MinikinFontForTest&) = delete; diff --git a/engine/src/flutter/tests/util/UnicodeUtils.cpp b/engine/src/flutter/tests/util/UnicodeUtils.cpp index 2f811daec25..e66ff934893 100644 --- a/engine/src/flutter/tests/util/UnicodeUtils.cpp +++ b/engine/src/flutter/tests/util/UnicodeUtils.cpp @@ -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 parseUnicodeStringWithOffset(const std::string& in, size_t* offset) { + std::unique_ptr 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(buffer.get(), buffer.get() + result_size); +} + +std::vector parseUnicodeString(const std::string& in) { + return parseUnicodeStringWithOffset(in, nullptr); +} + std::vector utf8ToUtf16(const std::string& text) { std::vector result; int32_t i = 0; diff --git a/engine/src/flutter/tests/util/UnicodeUtils.h b/engine/src/flutter/tests/util/UnicodeUtils.h index 571be7a31ef..6ce2fcbd90e 100644 --- a/engine/src/flutter/tests/util/UnicodeUtils.h +++ b/engine/src/flutter/tests/util/UnicodeUtils.h @@ -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 parseUnicodeStringWithOffset(const std::string& in, size_t* offset); +std::vector parseUnicodeString(const std::string& in); + // Converts UTF-8 to UTF-16. std::vector utf8ToUtf16(const std::string& text);