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 "SkDataTable.h"
      9 #include "SkFontMgr.h"
     10 #include "SkFontMgr_indirect.h"
     11 #include "SkFontStyle.h"
     12 #include "SkMutex.h"
     13 #include "SkOnce.h"
     14 #include "SkRefCnt.h"
     15 #include "SkRemotableFontMgr.h"
     16 #include "SkStream.h"
     17 #include "SkString.h"
     18 #include "SkTArray.h"
     19 #include "SkTypeface.h"
     20 #include "SkTypes.h"
     21 #include "SkTemplates.h"
     22 
     23 class SkData;
     24 
     25 class SkStyleSet_Indirect : public SkFontStyleSet {
     26 public:
     27     /** Takes ownership of the SkRemotableFontIdentitySet. */
     28     SkStyleSet_Indirect(const SkFontMgr_Indirect* owner, int familyIndex,
     29                         SkRemotableFontIdentitySet* data)
     30         : fOwner(SkRef(owner)), fFamilyIndex(familyIndex), fData(data)
     31     { }
     32 
     33     int count() override { return fData->count(); }
     34 
     35     void getStyle(int index, SkFontStyle* fs, SkString* style) override {
     36         if (fs) {
     37             *fs = fData->at(index).fFontStyle;
     38         }
     39         if (style) {
     40             // TODO: is this useful? Current locale?
     41             style->reset();
     42         }
     43     }
     44 
     45     SkTypeface* createTypeface(int index) override {
     46         return fOwner->createTypefaceFromFontId(fData->at(index));
     47     }
     48 
     49     SkTypeface* matchStyle(const SkFontStyle& pattern) override {
     50         if (fFamilyIndex >= 0) {
     51             SkFontIdentity id = fOwner->fProxy->matchIndexStyle(fFamilyIndex, pattern);
     52             return fOwner->createTypefaceFromFontId(id);
     53         }
     54 
     55         return this->matchStyleCSS3(pattern);
     56     }
     57 private:
     58     SkAutoTUnref<const SkFontMgr_Indirect> fOwner;
     59     int fFamilyIndex;
     60     SkAutoTUnref<SkRemotableFontIdentitySet> fData;
     61 };
     62 
     63 void SkFontMgr_Indirect::set_up_family_names(const SkFontMgr_Indirect* self) {
     64     self->fFamilyNames.reset(self->fProxy->getFamilyNames());
     65 }
     66 
     67 int SkFontMgr_Indirect::onCountFamilies() const {
     68     SkOnce(&fFamilyNamesInited, &fFamilyNamesMutex, SkFontMgr_Indirect::set_up_family_names, this);
     69     return fFamilyNames->count();
     70 }
     71 
     72 void SkFontMgr_Indirect::onGetFamilyName(int index, SkString* familyName) const {
     73     SkOnce(&fFamilyNamesInited, &fFamilyNamesMutex, SkFontMgr_Indirect::set_up_family_names, this);
     74     if (index >= fFamilyNames->count()) {
     75         familyName->reset();
     76         return;
     77     }
     78     familyName->set(fFamilyNames->atStr(index));
     79 }
     80 
     81 SkFontStyleSet* SkFontMgr_Indirect::onCreateStyleSet(int index) const {
     82     SkRemotableFontIdentitySet* set = fProxy->getIndex(index);
     83     if (nullptr == set) {
     84         return nullptr;
     85     }
     86     return new SkStyleSet_Indirect(this, index, set);
     87 }
     88 
     89 SkFontStyleSet* SkFontMgr_Indirect::onMatchFamily(const char familyName[]) const {
     90     return new SkStyleSet_Indirect(this, -1, fProxy->matchName(familyName));
     91 }
     92 
     93 SkTypeface* SkFontMgr_Indirect::createTypefaceFromFontId(const SkFontIdentity& id) const {
     94     if (id.fDataId == SkFontIdentity::kInvalidDataId) {
     95         return nullptr;
     96     }
     97 
     98     SkAutoMutexAcquire ama(fDataCacheMutex);
     99 
    100     SkAutoTUnref<SkTypeface> dataTypeface;
    101     int dataTypefaceIndex = 0;
    102     for (int i = 0; i < fDataCache.count(); ++i) {
    103         const DataEntry& entry = fDataCache[i];
    104         if (entry.fDataId == id.fDataId) {
    105             if (entry.fTtcIndex == id.fTtcIndex &&
    106                 !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
    107             {
    108                 return entry.fTypeface;
    109             }
    110             if (dataTypeface.get() == nullptr &&
    111                 !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
    112             {
    113                 dataTypeface.reset(entry.fTypeface);
    114                 dataTypefaceIndex = entry.fTtcIndex;
    115             }
    116         }
    117 
    118         if (entry.fTypeface->weak_expired()) {
    119             fDataCache.removeShuffle(i);
    120             --i;
    121         }
    122     }
    123 
    124     // No exact match, but did find a data match.
    125     if (dataTypeface.get() != nullptr) {
    126         SkAutoTDelete<SkStreamAsset> stream(dataTypeface->openStream(nullptr));
    127         if (stream.get() != nullptr) {
    128             return fImpl->createFromStream(stream.detach(), dataTypefaceIndex);
    129         }
    130     }
    131 
    132     // No data match, request data and add entry.
    133     SkAutoTDelete<SkStreamAsset> stream(fProxy->getData(id.fDataId));
    134     if (stream.get() == nullptr) {
    135         return nullptr;
    136     }
    137 
    138     SkAutoTUnref<SkTypeface> typeface(fImpl->createFromStream(stream.detach(), id.fTtcIndex));
    139     if (typeface.get() == nullptr) {
    140         return nullptr;
    141     }
    142 
    143     DataEntry& newEntry = fDataCache.push_back();
    144     typeface->weak_ref();
    145     newEntry.fDataId = id.fDataId;
    146     newEntry.fTtcIndex = id.fTtcIndex;
    147     newEntry.fTypeface = typeface.get();  // weak reference passed to new entry.
    148 
    149     return typeface.detach();
    150 }
    151 
    152 SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyle(const char familyName[],
    153                                                    const SkFontStyle& fontStyle) const {
    154     SkFontIdentity id = fProxy->matchNameStyle(familyName, fontStyle);
    155     return this->createTypefaceFromFontId(id);
    156 }
    157 
    158 SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyleCharacter(const char familyName[],
    159                                                             const SkFontStyle& style,
    160                                                             const char* bcp47[],
    161                                                             int bcp47Count,
    162                                                             SkUnichar character) const {
    163     SkFontIdentity id = fProxy->matchNameStyleCharacter(familyName, style, bcp47,
    164                                                         bcp47Count, character);
    165     return this->createTypefaceFromFontId(id);
    166 }
    167 
    168 SkTypeface* SkFontMgr_Indirect::onMatchFaceStyle(const SkTypeface* familyMember,
    169                                                  const SkFontStyle& fontStyle) const {
    170     SkString familyName;
    171     familyMember->getFamilyName(&familyName);
    172     return this->matchFamilyStyle(familyName.c_str(), fontStyle);
    173 }
    174 
    175 SkTypeface* SkFontMgr_Indirect::onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const {
    176     return fImpl->createFromStream(stream, ttcIndex);
    177 }
    178 
    179 SkTypeface* SkFontMgr_Indirect::onCreateFromFile(const char path[], int ttcIndex) const {
    180     return fImpl->createFromFile(path, ttcIndex);
    181 }
    182 
    183 SkTypeface* SkFontMgr_Indirect::onCreateFromData(SkData* data, int ttcIndex) const {
    184     return fImpl->createFromData(data, ttcIndex);
    185 }
    186 
    187 SkTypeface* SkFontMgr_Indirect::onLegacyCreateTypeface(const char familyName[],
    188                                                        unsigned styleBits) const {
    189     bool bold = SkToBool(styleBits & SkTypeface::kBold);
    190     bool italic = SkToBool(styleBits & SkTypeface::kItalic);
    191     SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight
    192                                          : SkFontStyle::kNormal_Weight,
    193                                     SkFontStyle::kNormal_Width,
    194                                     italic ? SkFontStyle::kItalic_Slant
    195                                            : SkFontStyle::kUpright_Slant);
    196 
    197     SkAutoTUnref<SkTypeface> face(this->matchFamilyStyle(familyName, style));
    198 
    199     if (nullptr == face.get()) {
    200         face.reset(this->matchFamilyStyle(nullptr, style));
    201     }
    202 
    203     if (nullptr == face.get()) {
    204         SkFontIdentity fontId = this->fProxy->matchIndexStyle(0, style);
    205         face.reset(this->createTypefaceFromFontId(fontId));
    206     }
    207 
    208     return face.detach();
    209 }
    210