From a6198608722f8c2ce49f993adfab39398105c240 Mon Sep 17 00:00:00 2001 From: Seigo Nonaka Date: Fri, 10 Feb 2017 14:52:05 +0900 Subject: [PATCH] Remove MinikinRefCounted and use shared_ptr instead Let's use shared_ptr since manual ref counting can be a bug-prone and using the global mutex inside destructor is not useful for some time. To remove raw pointer manipulation, needed to change Layout constructors. Layout is no longer copyable and need to pass FontCollection to constructor. Bug: 28119474 Test: minikin_tests passed Test: hwui_unit_tests passed Test: No performance regression in minikin_perftest. Change-Id: I8824593206ecba74cbc9731e298f045e1ae442a3 --- .../flutter/include/minikin/FontCollection.h | 48 +-- .../src/flutter/include/minikin/FontFamily.h | 30 +- engine/src/flutter/include/minikin/Layout.h | 37 +- .../src/flutter/include/minikin/LineBreaker.h | 4 +- .../src/flutter/include/minikin/MinikinFont.h | 9 +- .../include/minikin/MinikinRefCounted.h | 59 ---- engine/src/flutter/libs/minikin/Android.mk | 1 - .../flutter/libs/minikin/FontCollection.cpp | 85 ++--- .../src/flutter/libs/minikin/FontFamily.cpp | 63 ++-- .../src/flutter/libs/minikin/HbFontCache.cpp | 2 +- engine/src/flutter/libs/minikin/HbFontCache.h | 2 +- engine/src/flutter/libs/minikin/Layout.cpp | 53 ++- .../src/flutter/libs/minikin/LineBreaker.cpp | 2 +- .../src/flutter/libs/minikin/MinikinFont.cpp | 2 + .../flutter/libs/minikin/MinikinInternal.cpp | 2 +- .../flutter/libs/minikin/MinikinInternal.h | 2 +- .../libs/minikin/MinikinRefCounted.cpp | 35 -- engine/src/flutter/sample/MinikinSkia.cpp | 5 +- engine/src/flutter/sample/MinikinSkia.h | 4 +- engine/src/flutter/sample/example.cpp | 17 +- engine/src/flutter/sample/example_skia.cpp | 19 +- .../tests/perftests/FontCollection.cpp | 7 +- .../unittest/FontCollectionItemizeTest.cpp | 327 +++++++++--------- .../tests/unittest/FontCollectionTest.cpp | 40 +-- .../flutter/tests/unittest/FontFamilyTest.cpp | 35 +- .../tests/unittest/HbFontCacheTest.cpp | 10 +- .../src/flutter/tests/unittest/LayoutTest.cpp | 36 +- .../src/flutter/tests/util/FontTestUtils.cpp | 25 +- .../flutter/tests/util/MinikinFontForTest.cpp | 4 +- .../flutter/tests/util/MinikinFontForTest.h | 3 +- .../src/flutter/tests/util/UnicodeUtils.cpp | 11 + engine/src/flutter/tests/util/UnicodeUtils.h | 3 + 32 files changed, 443 insertions(+), 539 deletions(-) delete mode 100644 engine/src/flutter/include/minikin/MinikinRefCounted.h delete mode 100644 engine/src/flutter/libs/minikin/MinikinRefCounted.cpp 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);