172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com/*
272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com * Copyright 2014 Google Inc.
372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com *
472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com * Use of this source code is governed by a BSD-style license that can be
572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com * found in the LICENSE file.
672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com */
772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
8f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkFontMgr.h"
9f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkFontMgr_indirect.h"
1072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkFontStyle.h"
11f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkMutex.h"
1272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkOnce.h"
13f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkRefCnt.h"
14f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkRemotableFontMgr.h"
1572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkStream.h"
16f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkString.h"
17f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkTArray.h"
1872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkTypeface.h"
19f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkTypes.h"
20f20488b4f2139e6ca09fee7e39b731dd8ab467dbbungeman#include "SkTemplates.h"
2172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
2272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comclass SkData;
2372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
2472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comclass SkStyleSet_Indirect : public SkFontStyleSet {
2572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.compublic:
2672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    /** Takes ownership of the SkRemotableFontIdentitySet. */
2772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkStyleSet_Indirect(const SkFontMgr_Indirect* owner, int familyIndex,
2872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                        SkRemotableFontIdentitySet* data)
2972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        : fOwner(SkRef(owner)), fFamilyIndex(familyIndex), fData(data)
3072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    { }
3172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
3236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    int count() override { return fData->count(); }
3372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
3436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void getStyle(int index, SkFontStyle* fs, SkString* style) override {
3572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (fs) {
3672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            *fs = fData->at(index).fFontStyle;
3772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
3872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (style) {
3972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // TODO: is this useful? Current locale?
4072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            style->reset();
4172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
4272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
4372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
4436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkTypeface* createTypeface(int index) override {
4572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return fOwner->createTypefaceFromFontId(fData->at(index));
4672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
4772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
4836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkTypeface* matchStyle(const SkFontStyle& pattern) override {
4972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (fFamilyIndex >= 0) {
5072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkFontIdentity id = fOwner->fProxy->matchIndexStyle(fFamilyIndex, pattern);
5172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return fOwner->createTypefaceFromFontId(id);
5272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
5372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
54147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        return this->matchStyleCSS3(pattern);
5572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
5672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comprivate:
5767b39de70fb5d10caebfc75f418754186e5226c3Hal Canary    sk_sp<const SkFontMgr_Indirect> fOwner;
5872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    int fFamilyIndex;
5967b39de70fb5d10caebfc75f418754186e5226c3Hal Canary    sk_sp<SkRemotableFontIdentitySet> fData;
6072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com};
6172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
6272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comint SkFontMgr_Indirect::onCountFamilies() const {
639adfef8680c22ce8980031b4bcb9f1fadd066a80Herb Derby    return 0;
6472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
6572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
6672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comvoid SkFontMgr_Indirect::onGetFamilyName(int index, SkString* familyName) const {
67b4aab9ae6d27c446af8302b79d15b832c816c633Ben Wagner    SK_ABORT("Not implemented");
6872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
6972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
7072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkFontStyleSet* SkFontMgr_Indirect::onCreateStyleSet(int index) const {
71b4aab9ae6d27c446af8302b79d15b832c816c633Ben Wagner    SK_ABORT("Not implemented");
729adfef8680c22ce8980031b4bcb9f1fadd066a80Herb Derby    return nullptr;
7372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
7472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
7572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkFontStyleSet* SkFontMgr_Indirect::onMatchFamily(const char familyName[]) const {
76385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    return new SkStyleSet_Indirect(this, -1, fProxy->matchName(familyName));
7772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
7872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
7972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkTypeface* SkFontMgr_Indirect::createTypefaceFromFontId(const SkFontIdentity& id) const {
8072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    if (id.fDataId == SkFontIdentity::kInvalidDataId) {
8196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
8272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
8372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
8472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkAutoMutexAcquire ama(fDataCacheMutex);
8572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
8667b39de70fb5d10caebfc75f418754186e5226c3Hal Canary    sk_sp<SkTypeface> dataTypeface;
8772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    int dataTypefaceIndex = 0;
8872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    for (int i = 0; i < fDataCache.count(); ++i) {
8972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        const DataEntry& entry = fDataCache[i];
9072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (entry.fDataId == id.fDataId) {
9172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (entry.fTtcIndex == id.fTtcIndex &&
9272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
9372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            {
9472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                return entry.fTypeface;
9572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
9696fcdcc219d2a0d3579719b84b28bede76efba64halcanary            if (dataTypeface.get() == nullptr &&
9772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
9872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            {
9972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                dataTypeface.reset(entry.fTypeface);
10072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                dataTypefaceIndex = entry.fTtcIndex;
10172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
10272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
10372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
10472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (entry.fTypeface->weak_expired()) {
10572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            fDataCache.removeShuffle(i);
10672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            --i;
10772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
10872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
10972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
11072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    // No exact match, but did find a data match.
11196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (dataTypeface.get() != nullptr) {
112145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner        std::unique_ptr<SkStreamAsset> stream(dataTypeface->openStream(nullptr));
11396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (stream.get() != nullptr) {
114592273965a7fc7fc403252e420d15f6555b8f25dMike Reed            return fImpl->makeFromStream(std::move(stream), dataTypefaceIndex).release();
11572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
11672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
11772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
11872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    // No data match, request data and add entry.
119145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner    std::unique_ptr<SkStreamAsset> stream(fProxy->getData(id.fDataId));
12096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (stream.get() == nullptr) {
12196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
12272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
12372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
124592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    sk_sp<SkTypeface> typeface(fImpl->makeFromStream(std::move(stream), id.fTtcIndex));
12596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (typeface.get() == nullptr) {
12696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
12772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
12872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
12972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    DataEntry& newEntry = fDataCache.push_back();
13072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    typeface->weak_ref();
13172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    newEntry.fDataId = id.fDataId;
13272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    newEntry.fTtcIndex = id.fTtcIndex;
13372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    newEntry.fTypeface = typeface.get();  // weak reference passed to new entry.
13472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
13518300a3aa7cb6eb55d21bb0450dffa58b6fc062cmtklein    return typeface.release();
13672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
13772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
13872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkTypeface* SkFontMgr_Indirect::onMatchFamilyStyle(const char familyName[],
13972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                   const SkFontStyle& fontStyle) const {
14072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkFontIdentity id = fProxy->matchNameStyle(familyName, fontStyle);
14172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return this->createTypefaceFromFontId(id);
14272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
14372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
14472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkTypeface* SkFontMgr_Indirect::onMatchFamilyStyleCharacter(const char familyName[],
14572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                            const SkFontStyle& style,
146c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman                                                            const char* bcp47[],
147c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman                                                            int bcp47Count,
148c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman                                                            SkUnichar character) const {
149c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman    SkFontIdentity id = fProxy->matchNameStyleCharacter(familyName, style, bcp47,
150c20386e3937d3d398ac9b35f9c7d997e972ade98bungeman                                                        bcp47Count, character);
15172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return this->createTypefaceFromFontId(id);
15272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
15372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
15472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkTypeface* SkFontMgr_Indirect::onMatchFaceStyle(const SkTypeface* familyMember,
15572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                 const SkFontStyle& fontStyle) const {
15672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkString familyName;
15772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    familyMember->getFamilyName(&familyName);
15872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return this->matchFamilyStyle(familyName.c_str(), fontStyle);
15972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
16072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
161592273965a7fc7fc403252e420d15f6555b8f25dMike Reedsk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset> stream,
162592273965a7fc7fc403252e420d15f6555b8f25dMike Reed                                                            int ttcIndex) const {
163592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    return fImpl->makeFromStream(std::move(stream), ttcIndex);
16472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
16572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
166592273965a7fc7fc403252e420d15f6555b8f25dMike Reedsk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromFile(const char path[], int ttcIndex) const {
167592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    return fImpl->makeFromFile(path, ttcIndex);
16872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
16972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
170592273965a7fc7fc403252e420d15f6555b8f25dMike Reedsk_sp<SkTypeface> SkFontMgr_Indirect::onMakeFromData(sk_sp<SkData> data, int ttcIndex) const {
171592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    return fImpl->makeFromData(std::move(data), ttcIndex);
17272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
17372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
174592273965a7fc7fc403252e420d15f6555b8f25dMike Reedsk_sp<SkTypeface> SkFontMgr_Indirect::onLegacyMakeTypeface(const char familyName[],
175592273965a7fc7fc403252e420d15f6555b8f25dMike Reed                                                           SkFontStyle style) const {
17667b39de70fb5d10caebfc75f418754186e5226c3Hal Canary    sk_sp<SkTypeface> face(this->matchFamilyStyle(familyName, style));
17772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
17896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == face.get()) {
17996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        face.reset(this->matchFamilyStyle(nullptr, style));
18072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
18172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
18296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == face.get()) {
18372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkFontIdentity fontId = this->fProxy->matchIndexStyle(0, style);
18472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        face.reset(this->createTypefaceFromFontId(fontId));
18572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
18672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
187592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    return face;
18872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
189