Home | History | Annotate | Download | only in fonts
      1 /*
      2  * Copyright 2014 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkFontMgr.h"
      9 #include "SkFontMgr_indirect.h"
     10 #include "SkFontStyle.h"
     11 #include "SkMutex.h"
     12 #include "SkOnce.h"
     13 #include "SkRefCnt.h"
     14 #include "SkRemotableFontMgr.h"
     15 #include "SkStream.h"
     16 #include "SkString.h"
     17 #include "SkTArray.h"
     18 #include "SkTypeface.h"
     19 #include "SkTypes.h"
     20 #include "SkTemplates.h"
     21 
     22 class SkData;
     23 
     24 class SkStyleSet_Indirect : public SkFontStyleSet {
     25 public:
     26     /** Takes ownership of the SkRemotableFontIdentitySet. */
     27     SkStyleSet_Indirect(const SkFontMgr_Indirect* owner, int familyIndex,
     28                         SkRemotableFontIdentitySet* data)
     29         : fOwner(SkRef(owner)), fFamilyIndex(familyIndex), fData(data)
     30     { }
     31 
     32     int count() override { return fData->count(); }
     33 
     34     void getStyle(int index, SkFontStyle* fs, SkString* style) override {
     35         if (fs) {
     36             *fs = fData->at(index).fFontStyle;
     37         }
     38         if (style) {
     39             // TODO: is this useful? Current locale?
     40             style->reset();
     41         }
     42     }
     43 
     44     SkTypeface* createTypeface(int index) override {
     45         return fOwner->createTypefaceFromFontId(fData->at(index));
     46     }
     47 
     48     SkTypeface* matchStyle(const SkFontStyle& pattern) override {
     49         if (fFamilyIndex >= 0) {
     50             SkFontIdentity id = fOwner->fProxy->matchIndexStyle(fFamilyIndex, pattern);
     51             return fOwner->createTypefaceFromFontId(id);
     52         }
     53 
     54         return this->matchStyleCSS3(pattern);
     55     }
     56 private:
     57     sk_sp<const SkFontMgr_Indirect> fOwner;
     58     int fFamilyIndex;
     59     sk_sp<SkRemotableFontIdentitySet> fData;
     60 };
     61 
     62 int SkFontMgr_Indirect::onCountFamilies() const {
     63     return 0;
     64 }
     65 
     66 void SkFontMgr_Indirect::onGetFamilyName(int index, SkString* familyName) const {
     67     SK_ABORT("Not implemented");
     68 }
     69 
     70 SkFontStyleSet* SkFontMgr_Indirect::onCreateStyleSet(int index) const {
     71     SK_ABORT("Not implemented");
     72     return nullptr;
     73 }
     74 
     75 SkFontStyleSet* SkFontMgr_Indirect::onMatchFamily(const char familyName[]) const {
     76     return new SkStyleSet_Indirect(this, -1, fProxy->matchName(familyName));
     77 }
     78 
     79 SkTypeface* SkFontMgr_Indirect::createTypefaceFromFontId(const SkFontIdentity& id) const {
     80     if (id.fDataId == SkFontIdentity::kInvalidDataId) {
     81         return nullptr;
     82     }
     83 
     84     SkAutoMutexAcquire ama(fDataCacheMutex);
     85 
     86     sk_sp<SkTypeface> dataTypeface;
     87     int dataTypefaceIndex = 0;
     88     for (int i = 0; i < fDataCache.count(); ++i) {
     89         const DataEntry& entry = fDataCache[i];
     90         if (entry.fDataId == id.fDataId) {
     91             if (entry.fTtcIndex == id.fTtcIndex &&
     92                 !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
     93             {
     94                 return entry.fTypeface;
     95             }
     96             if (dataTypeface.get() == nullptr &&
     97                 !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
     98             {
     99                 dataTypeface.reset(entry.fTypeface);
    100                 dataTypefaceIndex = entry.fTtcIndex;
    101             }
    102         }
    103 
    104         if (entry.fTypeface->weak_expired()) {
    105             fDataCache.removeShuffle(i);
    106             --i;
    107         }
    108     }
    109 
    110     // No exact match, but did find a data match.
    111     if (dataTypeface.get() != nullptr) {
    112         std::unique_ptr<SkStreamAsset> stream(dataTypeface->openStream(nullptr));
    113         if (stream.get() != nullptr) {
    114             return fImpl->makeFromStream(std::move(stream), dataTypefaceIndex).release();
    115         }
    116     }
    117 
    118     // No data match, request data and add entry.
    119     std::unique_ptr<SkStreamAsset> stream(fProxy->getData(id.fDataId));
    120     if (stream.get() == nullptr) {
    121         return nullptr;
    122     }
    123 
    124     sk_sp<SkTypeface> typeface(fImpl->makeFromStream(std::move(stream), id.fTtcIndex));
    125     if (typeface.get() == nullptr) {
    126         return nullptr;
    127     }
    128 
    129     DataEntry& newEntry = fDataCache.push_back();
    130     typeface->weak_ref();
    131     newEntry.fDataId = id.fDataId;
    132     newEntry.fTtcIndex = id.fTtcIndex;
    133     newEntry.fTypeface = typeface.get();  // weak reference passed to new entry.
    134 
    135     return typeface.release();
    136 }
    137 
    138 SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyle(const char familyName[],
    139                                                    const SkFontStyle& fontStyle) const {
    140     SkFontIdentity id = fProxy->matchNameStyle(familyName, fontStyle);
    141     return this->createTypefaceFromFontId(id);
    142 }
    143 
    144 SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyleCharacter(const char familyName[],
    145                                                             const SkFontStyle& style,
    146                                                             const char* bcp47[],
    147                                                             int bcp47Count,
    148                                                             SkUnichar character) const {
    149     SkFontIdentity id = fProxy->matchNameStyleCharacter(familyName, style, bcp47,
    150                                                         bcp47Count, character);
    151     return this->createTypefaceFromFontId(id);
    152 }
    153 
    154 SkTypeface* SkFontMgr_Indirect::onMatchFaceStyle(const SkTypeface* familyMember,
    155                                                  const SkFontStyle& fontStyle) const {
    156     SkString familyName;
    157     familyMember->getFamilyName(&familyName);
    158     return this->matchFamilyStyle(familyName.c_str(), fontStyle);
    159 }
    160 
    161 sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
    162                                                             int ttcIndex) const {
    163     return fImpl->makeFromStream(std::move(stream), ttcIndex);
    164 }
    165 
    166 sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromFile(const char path[], int ttcIndex) const {
    167     return fImpl->makeFromFile(path, ttcIndex);
    168 }
    169 
    170 sk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromData(sk_sp<SkData> data, int ttcIndex) const {
    171     return fImpl->makeFromData(std::move(data), ttcIndex);
    172 }
    173 
    174 sk_sp<SkTypeface> SkFontMgr_Indirect::onLegacyMakeTypeface(const char familyName[],
    175                                                            SkFontStyle style) const {
    176     sk_sp<SkTypeface> face(this->matchFamilyStyle(familyName, style));
    177 
    178     if (nullptr == face.get()) {
    179         face.reset(this->matchFamilyStyle(nullptr, style));
    180     }
    181 
    182     if (nullptr == face.get()) {
    183         SkFontIdentity fontId = this->fProxy->matchIndexStyle(0, style);
    184         face.reset(this->createTypefaceFromFontId(fontId));
    185     }
    186 
    187     return face;
    188 }
    189