19cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien/* 29cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Copyright (C) 2013 The Android Open Source Project 39cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * 49cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Licensed under the Apache License, Version 2.0 (the "License"); 59cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * you may not use this file except in compliance with the License. 69cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * You may obtain a copy of the License at 79cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * 89cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * http://www.apache.org/licenses/LICENSE-2.0 99cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * 109cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Unless required by applicable law or agreed to in writing, software 119cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * distributed under the License is distributed on an "AS IS" BASIS, 129cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * See the License for the specific language governing permissions and 149cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * limitations under the License. 159cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien */ 169cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 179cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#define LOG_TAG "Minikin" 189cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 199cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include <stdint.h> 20555d84c6f98eafcbe677cdcb8e9605760acd8ce5Mark Salyzyn#include <stdlib.h> 214b723bf22b1bbc5fcdaa9bd96178c921199905d5Roozbeh Pournader#include <string.h> 22c31e3883456e018d742e9f29815ba5ff8b315ea1Raph Levien 2339ab40115fae6d0c948e435233b3dd997ee7d8e5Mark Salyzyn#include <log/log.h> 24555d84c6f98eafcbe677cdcb8e9605760acd8ce5Mark Salyzyn#include <utils/JenkinsHash.h> 25555d84c6f98eafcbe677cdcb8e9605760acd8ce5Mark Salyzyn 260f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka#include <hb.h> 270f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka#include <hb-ot.h> 280f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka 29198b46f1fea3f47ef8eb6317799c0d77aaec52f6Seigo Nonaka#include "FontLanguage.h" 306d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka#include "FontLanguageListCache.h" 31065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka#include "FontUtils.h" 3289e80237bc27af084c9ff316d4f47abf426eced8Seigo Nonaka#include "HbFontCache.h" 33c31e3883456e018d742e9f29815ba5ff8b315ea1Raph Levien#include "MinikinInternal.h" 3413f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien#include <minikin/CmapCoverage.h> 35065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka#include <minikin/MinikinFont.h> 369cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include <minikin/FontFamily.h> 37555d84c6f98eafcbe677cdcb8e9605760acd8ce5Mark Salyzyn#include <minikin/MinikinFont.h> 389cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 399cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienusing std::vector; 409cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 4114e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonakanamespace minikin { 429cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 436d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo NonakaFontStyle::FontStyle(int variant, int weight, bool italic) 44fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka : FontStyle(FontLanguageListCache::kEmptyListId, variant, weight, italic) { 456d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka} 466d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka 476d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo NonakaFontStyle::FontStyle(uint32_t languageListId, int variant, int weight, bool italic) 486d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka : bits(pack(variant, weight, italic)), mLanguageListId(languageListId) { 496d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka} 506d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka 5114e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonakaandroid::hash_t FontStyle::hash() const { 5214e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonaka uint32_t hash = android::JenkinsHashMix(0, bits); 5314e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonaka hash = android::JenkinsHashMix(hash, mLanguageListId); 5414e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonaka return android::JenkinsHashWhiten(hash); 556d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka} 566d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka 576d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka// static 586d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonakauint32_t FontStyle::registerLanguageList(const std::string& languages) { 59fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka android::AutoMutex _l(gMinikinLock); 60fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka return FontLanguageListCache::getId(languages); 616d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka} 626d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka 636d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka// static 646d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonakauint32_t FontStyle::pack(int variant, int weight, bool italic) { 656d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka return (weight & kWeightMask) | (italic ? kItalicMask : 0) | (variant << kVariantShift); 666d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka} 676d9dcd2cf3d3ed26a886e02d94c907311e7b1f83Seigo Nonaka 68dfbc6e374259f9d81940b5195ac013b02429af27Seigo NonakaFont::Font(const std::shared_ptr<MinikinFont>& typeface, FontStyle style) 6941718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka : typeface(typeface), style(style) { 70dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka} 71dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka 72dfbc6e374259f9d81940b5195ac013b02429af27Seigo NonakaFont::Font(std::shared_ptr<MinikinFont>&& typeface, FontStyle style) 73dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka : typeface(typeface), style(style) { 74dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka} 75065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka 761adbccfd0f40ef416e4f76ea16cbc0bae549d669Seigo Nonakastd::unordered_set<AxisTag> Font::getSupportedAxesLocked() const { 77065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka const uint32_t fvarTag = MinikinFont::MakeTag('f', 'v', 'a', 'r'); 78dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka HbBlob fvarTable(getFontTable(typeface.get(), fvarTag)); 79065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka if (fvarTable.size() == 0) { 801adbccfd0f40ef416e4f76ea16cbc0bae549d669Seigo Nonaka return std::unordered_set<AxisTag>(); 81065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka } 82065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka 831adbccfd0f40ef416e4f76ea16cbc0bae549d669Seigo Nonaka std::unordered_set<AxisTag> supportedAxes; 84065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka analyzeAxes(fvarTable.get(), fvarTable.size(), &supportedAxes); 851adbccfd0f40ef416e4f76ea16cbc0bae549d669Seigo Nonaka return supportedAxes; 86994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka} 87994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka 8841718c770d0ae12133270a4ee4a8dbd27851480dSeigo NonakaFont::Font(Font&& o) { 89dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka typeface = std::move(o.typeface); 9041718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka style = o.style; 9141718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka o.typeface = nullptr; 9241e02e96131c1ec66d013e4615348be013518dc4Seigo Nonaka} 9341e02e96131c1ec66d013e4615348be013518dc4Seigo Nonaka 9441718c770d0ae12133270a4ee4a8dbd27851480dSeigo NonakaFont::Font(const Font& o) { 9541718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka typeface = o.typeface; 9641718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka style = o.style; 97c31e3883456e018d742e9f29815ba5ff8b315ea1Raph Levien} 98c31e3883456e018d742e9f29815ba5ff8b315ea1Raph Levien 99dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka// static 10041718c770d0ae12133270a4ee4a8dbd27851480dSeigo NonakaFontFamily::FontFamily(std::vector<Font>&& fonts) : FontFamily(0 /* variant */, std::move(fonts)) { 10141718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka} 10241718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka 10341718c770d0ae12133270a4ee4a8dbd27851480dSeigo NonakaFontFamily::FontFamily(int variant, std::vector<Font>&& fonts) 104fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka : FontFamily(FontLanguageListCache::kEmptyListId, variant, std::move(fonts)) { 10541718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka} 10641718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka 10741718c770d0ae12133270a4ee4a8dbd27851480dSeigo NonakaFontFamily::FontFamily(uint32_t langId, int variant, std::vector<Font>&& fonts) 1089196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka : mLangId(langId), mVariant(variant), mFonts(std::move(fonts)) { 10941718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka computeCoverage(); 11041718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka} 11141718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka 112dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonakabool FontFamily::analyzeStyle(const std::shared_ptr<MinikinFont>& typeface, int* weight, 113dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka bool* italic) { 114fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka android::AutoMutex _l(gMinikinLock); 11541718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka const uint32_t os2Tag = MinikinFont::MakeTag('O', 'S', '/', '2'); 116dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka HbBlob os2Table(getFontTable(typeface.get(), os2Tag)); 11741718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka if (os2Table.get() == nullptr) return false; 11841718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka return ::minikin::analyzeStyle(os2Table.get(), os2Table.size(), weight, italic); 1199cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien} 1209cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 1219cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien// Compute a matching metric between two styles - 0 is an exact match 1229a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levienstatic int computeMatch(FontStyle style1, FontStyle style2) { 1239cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien if (style1 == style2) return 0; 1249cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien int score = abs(style1.getWeight() - style2.getWeight()); 1259cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien if (style1.getItalic() != style2.getItalic()) { 1269cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien score += 2; 1279cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien } 1289cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien return score; 1299cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien} 1309cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 1319a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levienstatic FontFakery computeFakery(FontStyle wanted, FontStyle actual) { 132d5804e3937a961736e5cef0e8a70eacf91ee00bbRaph Levien // If desired weight is semibold or darker, and 2 or more grades 133d5804e3937a961736e5cef0e8a70eacf91ee00bbRaph Levien // higher than actual (for example, medium 500 -> bold 700), then 134d5804e3937a961736e5cef0e8a70eacf91ee00bbRaph Levien // select fake bold. 1359f9f3b1ef40f7358dca6acd9dfef686cedefb6aaRaph Levien int wantedWeight = wanted.getWeight(); 136d5804e3937a961736e5cef0e8a70eacf91ee00bbRaph Levien bool isFakeBold = wantedWeight >= 6 && (wantedWeight - actual.getWeight()) >= 2; 1379a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien bool isFakeItalic = wanted.getItalic() && !actual.getItalic(); 1389a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien return FontFakery(isFakeBold, isFakeItalic); 1399a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien} 1409a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien 1419a5f713add8cfb91ac2c9ed5c917309053201ab6Raph LevienFakedFont FontFamily::getClosestMatch(FontStyle style) const { 142dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka const Font* bestFont = nullptr; 1439cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien int bestMatch = 0; 1449cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien for (size_t i = 0; i < mFonts.size(); i++) { 1459cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien const Font& font = mFonts[i]; 1469cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien int match = computeMatch(font.style, style); 1479cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien if (i == 0 || match < bestMatch) { 1489cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien bestFont = &font; 1499cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien bestMatch = match; 1509cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien } 1519cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien } 152dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka if (bestFont != nullptr) { 153dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka return FakedFont{ bestFont->typeface.get(), computeFakery(style, bestFont->style) }; 1549a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien } 155dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka return FakedFont{ nullptr, FontFakery() }; 1569cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien} 1579cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien 158994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonakabool FontFamily::isColorEmojiFamily() const { 159fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka const FontLanguages& languageList = FontLanguageListCache::getById(mLangId); 160994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka for (size_t i = 0; i < languageList.size(); ++i) { 161e1d7f6168a0a485ecac75cfc9ae3bdc5143d0fb1yirui if (languageList[i].getEmojiStyle() == FontLanguage::EMSTYLE_EMOJI) { 162994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka return true; 163994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka } 164994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka } 165994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka return false; 166994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka} 167994aa84f7b18466806fe552ea57da1852b909f24Seigo Nonaka 16841718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonakavoid FontFamily::computeCoverage() { 169fd4124c53399581dd94eac5a9749bc07b474a294Seigo Nonaka android::AutoMutex _l(gMinikinLock); 17041718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka const FontStyle defaultStyle; 171dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka const MinikinFont* typeface = getClosestMatch(defaultStyle).font; 17241718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka const uint32_t cmapTag = MinikinFont::MakeTag('c', 'm', 'a', 'p'); 17341718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka HbBlob cmapTable(getFontTable(typeface, cmapTag)); 17441718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka if (cmapTable.get() == nullptr) { 17541718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka ALOGE("Could not get cmap table size!\n"); 17641718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka return; 17741718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonaka } 1789196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka mCoverage = CmapCoverage::getCoverage(cmapTable.get(), cmapTable.size(), &mCmapFmt14Coverage); 179065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka 180065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka for (size_t i = 0; i < mFonts.size(); ++i) { 1811adbccfd0f40ef416e4f76ea16cbc0bae549d669Seigo Nonaka std::unordered_set<AxisTag> supportedAxes = mFonts[i].getSupportedAxesLocked(); 1821adbccfd0f40ef416e4f76ea16cbc0bae549d669Seigo Nonaka mSupportedAxes.insert(supportedAxes.begin(), supportedAxes.end()); 183065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka } 18413f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien} 18513f1aae02bacd475722bc8ea3fc2cf6abc1a82e3Raph Levien 18641718c770d0ae12133270a4ee4a8dbd27851480dSeigo Nonakabool FontFamily::hasGlyph(uint32_t codepoint, uint32_t variationSelector) const { 1879196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka if (variationSelector == 0) { 1889196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka return mCoverage.get(codepoint); 1899196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka } 1909196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka 1919196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka if (mCmapFmt14Coverage.empty()) { 1926b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka return false; 1936b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka } 1946b1c227da6492a435f0341d7fe95d9992669920eSeigo Nonaka 1959196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka const uint16_t vsIndex = getVsIndex(variationSelector); 1969196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka 1979196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka if (vsIndex >= mCmapFmt14Coverage.size()) { 1989196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka // Even if vsIndex is INVALID_VS_INDEX, we reach here since INVALID_VS_INDEX is defined to 1999196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka // be at the maximum end of the range. 2009196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka return false; 2019196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka } 2029196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka 2039196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka const std::unique_ptr<SparseBitSet>& bitset = mCmapFmt14Coverage[vsIndex]; 2049196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka if (bitset.get() == nullptr) { 2059196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka return false; 2069196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka } 2079196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka 2089196194d76e4325c5bb0c23f22a5787a717067edSeigo Nonaka return bitset->get(codepoint); 2090f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka} 2100f2a025d135f9ca52cc3cf917fffc29d6c126094Seigo Nonaka 211dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonakastd::shared_ptr<FontFamily> FontFamily::createFamilyWithVariation( 212065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka const std::vector<FontVariation>& variations) const { 213065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka if (variations.empty() || mSupportedAxes.empty()) { 214065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka return nullptr; 215065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka } 216065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka 217065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka bool hasSupportedAxis = false; 218065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka for (const FontVariation& variation : variations) { 219065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka if (mSupportedAxes.find(variation.axisTag) != mSupportedAxes.end()) { 220065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka hasSupportedAxis = true; 221065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka break; 222065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka } 223065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka } 224065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka if (!hasSupportedAxis) { 225065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka // None of variation axes are suppored by this family. 226065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka return nullptr; 227065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka } 228065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka 229065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka std::vector<Font> fonts; 230065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka for (const Font& font : mFonts) { 231065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka bool supportedVariations = false; 2321adbccfd0f40ef416e4f76ea16cbc0bae549d669Seigo Nonaka android::AutoMutex _l(gMinikinLock); 2331adbccfd0f40ef416e4f76ea16cbc0bae549d669Seigo Nonaka std::unordered_set<AxisTag> supportedAxes = font.getSupportedAxesLocked(); 2341adbccfd0f40ef416e4f76ea16cbc0bae549d669Seigo Nonaka if (!supportedAxes.empty()) { 235065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka for (const FontVariation& variation : variations) { 2361adbccfd0f40ef416e4f76ea16cbc0bae549d669Seigo Nonaka if (supportedAxes.find(variation.axisTag) != supportedAxes.end()) { 237065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka supportedVariations = true; 238065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka break; 239065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka } 240065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka } 241065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka } 242dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka std::shared_ptr<MinikinFont> minikinFont; 243065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka if (supportedVariations) { 244065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka minikinFont = font.typeface->createFontWithVariation(variations); 245065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka } 246065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka if (minikinFont == nullptr) { 247065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka minikinFont = font.typeface; 248065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka } 249dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka fonts.push_back(Font(std::move(minikinFont), font.style)); 250065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka } 251065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka 252dfbc6e374259f9d81940b5195ac013b02429af27Seigo Nonaka return std::shared_ptr<FontFamily>(new FontFamily(mLangId, mVariant, std::move(fonts))); 253065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka} 254065c46a665d562c93ffa82fda10dee52a16ac23bSeigo Nonaka 25514e2d136aaef271ba131f917cf5f27baa31ae5adSeigo Nonaka} // namespace minikin 256