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
872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkFontMgr_indirect.h"
972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
1072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkDataTable.h"
1172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkFontStyle.h"
1272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkOnce.h"
1372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkStream.h"
1472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkTSearch.h"
1572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkTypeface.h"
1672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
1772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comclass SkData;
1872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comclass SkString;
1972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
2072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comclass SkStyleSet_Indirect : public SkFontStyleSet {
2172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.compublic:
2272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    /** Takes ownership of the SkRemotableFontIdentitySet. */
2372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkStyleSet_Indirect(const SkFontMgr_Indirect* owner, int familyIndex,
2472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                        SkRemotableFontIdentitySet* data)
2572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        : fOwner(SkRef(owner)), fFamilyIndex(familyIndex), fData(data)
2672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    { }
2772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
2872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    virtual int count() SK_OVERRIDE { return fData->count(); }
2972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
3072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    virtual void getStyle(int index, SkFontStyle* fs, SkString* style) SK_OVERRIDE {
3172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (fs) {
3272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            *fs = fData->at(index).fFontStyle;
3372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
3472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (style) {
3572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // TODO: is this useful? Current locale?
3672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            style->reset();
3772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
3872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
3972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
4072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
4172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return fOwner->createTypefaceFromFontId(fData->at(index));
4272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
4372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
4472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
4572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (fFamilyIndex >= 0) {
4672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            SkFontIdentity id = fOwner->fProxy->matchIndexStyle(fFamilyIndex, pattern);
4772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return fOwner->createTypefaceFromFontId(id);
4872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
4972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
5072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // If this SkStyleSet was created via onMatchFamily we would need a call like
5172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // fOwner->fProxy->matchNameStyle(fFamilyName, pattern);
5272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // but would not activate fonts (only consider fonts which would come back from matchName).
5372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
5472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // CSS policy sounds good.
5572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        struct Score {
5672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            int score;
5772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            int index;
5872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        };
5972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
6072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // Width has the greatest priority.
6172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // If the value of pattern.width is 5 (normal) or less,
6272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        //    narrower width values are checked first, then wider values.
6372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // If the value of pattern.width is greater than 5 (normal),
6472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        //    wider values are checked first, followed by narrower values.
6572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
6672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // Italic/Oblique has the next highest priority.
6772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // If italic requested and there is some italic font, use it.
6872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // If oblique requested and there is some oblique font, use it.
6972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // If italic requested and there is some oblique font, use it.
7072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // If oblique requested and there is some italic font, use it.
7172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
7272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // Exact match.
7372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // If pattern.weight < 400, weights below pattern.weight are checked
7472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        //   in descending order followed by weights above pattern.weight
7572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        //   in ascending order until a match is found.
7672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // If pattern.weight > 500, weights above pattern.weight are checked
7772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        //   in ascending order followed by weights below pattern.weight
7872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        //   in descending order until a match is found.
7972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // If pattern.weight is 400, 500 is checked first
8072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        //   and then the rule for pattern.weight < 400 is used.
8172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        // If pattern.weight is 500, 400 is checked first
8272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        //   and then the rule for pattern.weight < 400 is used
8372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
8472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        Score maxScore = { 0, 0 };
8572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        for (int i = 0; i < fData->count(); ++i) {
8672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            const SkFontStyle& current = fData->at(i).fFontStyle;
8772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            Score currentScore = { 0, i };
8872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
8972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // CSS stretch. (This is the width.)
9072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // This has the highest priority.
9172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (pattern.width() <= SkFontStyle::kNormal_Width) {
9272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                if (current.width() <= pattern.width()) {
9372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                    currentScore.score += 10 - pattern.width() + current.width();
9472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                } else {
9572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                    currentScore.score += 10 - current.width();
9672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                }
9772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            } else {
9872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                if (current.width() > pattern.width()) {
9972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                    currentScore.score += 10 + pattern.width() - current.width();
10072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                } else {
10172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                    currentScore.score += current.width();
10272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                }
10372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
10472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            currentScore.score *= 1002;
10572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
10672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // CSS style (italic/oblique)
10772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // Being italic trumps all valid weights which are not italic.
10872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // Note that newer specs differentiate between italic and oblique.
10972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (pattern.isItalic() && current.isItalic()) {
11072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                currentScore.score += 1001;
11172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
11272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
11372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // Synthetics (weight/style) [no stretch synthetic?]
11472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
11572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // The 'closer' to the target weight, the higher the score.
11672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            // 1000 is the 'heaviest' recognized weight
11772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (pattern.weight() == current.weight()) {
11872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                currentScore.score += 1000;
11972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            } else if (pattern.weight() <= 500) {
12072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                if (pattern.weight() >= 400 && pattern.weight() < 450) {
12172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                    if (current.weight() >= 450 && current.weight() <= 500) {
12272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                        // Artificially boost the 500 weight.
12372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                        // TODO: determine correct number to use.
12472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                        currentScore.score += 500;
12572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                    }
12672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                }
12772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                if (current.weight() <= pattern.weight()) {
12872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                    currentScore.score += 1000 - pattern.weight() + current.weight();
12972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                } else {
13072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                    currentScore.score += 1000 - current.weight();
13172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                }
13272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            } else if (pattern.weight() > 500) {
13372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                if (current.weight() > pattern.weight()) {
13472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                    currentScore.score += 1000 + pattern.weight() - current.weight();
13572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                } else {
13672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                    currentScore.score += current.weight();
13772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                }
13872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
13972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
14072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (currentScore.score > maxScore.score) {
14172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                maxScore = currentScore;
14272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
14372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
14472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
14572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return this->createTypeface(maxScore.index);
14672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
14772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comprivate:
14872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkAutoTUnref<const SkFontMgr_Indirect> fOwner;
14972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    int fFamilyIndex;
15072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkAutoTUnref<SkRemotableFontIdentitySet> fData;
15172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com};
15272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
15372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comvoid SkFontMgr_Indirect::set_up_family_names(const SkFontMgr_Indirect* self) {
15472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    self->fFamilyNames.reset(self->fProxy->getFamilyNames());
15572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
15672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
15772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comint SkFontMgr_Indirect::onCountFamilies() const {
1581ba62629f4d8300eb5ff82a83807119032eb0c02bungeman@google.com    SkOnce(&fFamilyNamesInited, &fFamilyNamesMutex, SkFontMgr_Indirect::set_up_family_names, this);
15972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return fFamilyNames->count();
16072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
16172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
16272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comvoid SkFontMgr_Indirect::onGetFamilyName(int index, SkString* familyName) const {
1631ba62629f4d8300eb5ff82a83807119032eb0c02bungeman@google.com    SkOnce(&fFamilyNamesInited, &fFamilyNamesMutex, SkFontMgr_Indirect::set_up_family_names, this);
16472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    if (index >= fFamilyNames->count()) {
16572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        familyName->reset();
16672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return;
16772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
16872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    familyName->set(fFamilyNames->atStr(index));
16972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
17072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
17172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkFontStyleSet* SkFontMgr_Indirect::onCreateStyleSet(int index) const {
17272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkRemotableFontIdentitySet* set = fProxy->getIndex(index);
17372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    if (NULL == set) {
17472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return NULL;
17572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
17672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return SkNEW_ARGS(SkStyleSet_Indirect, (this, index, set));
17772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
17872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
17972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkFontStyleSet* SkFontMgr_Indirect::onMatchFamily(const char familyName[]) const {
18072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return SkNEW_ARGS(SkStyleSet_Indirect, (this, -1, fProxy->matchName(familyName)));
18172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
18272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
18372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkTypeface* SkFontMgr_Indirect::createTypefaceFromFontId(const SkFontIdentity& id) const {
18472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    if (id.fDataId == SkFontIdentity::kInvalidDataId) {
18572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return NULL;
18672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
18772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
18872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkAutoMutexAcquire ama(fDataCacheMutex);
18972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
19072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkAutoTUnref<SkTypeface> dataTypeface;
19172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    int dataTypefaceIndex = 0;
19272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    for (int i = 0; i < fDataCache.count(); ++i) {
19372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        const DataEntry& entry = fDataCache[i];
19472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (entry.fDataId == id.fDataId) {
19572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (entry.fTtcIndex == id.fTtcIndex &&
19672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
19772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            {
19872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                return entry.fTypeface;
19972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
20072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            if (dataTypeface.get() == NULL &&
20172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref())
20272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            {
20372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                dataTypeface.reset(entry.fTypeface);
20472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                dataTypefaceIndex = entry.fTtcIndex;
20572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            }
20672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
20772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
20872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (entry.fTypeface->weak_expired()) {
20972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            fDataCache.removeShuffle(i);
21072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            --i;
21172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
21272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
21372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
21472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    // No exact match, but did find a data match.
21572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    if (dataTypeface.get() != NULL) {
21672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkAutoTUnref<SkStream> stream(dataTypeface->openStream(NULL));
21772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        if (stream.get() != NULL) {
21872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com            return fImpl->createFromStream(stream.get(), dataTypefaceIndex);
21972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        }
22072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
22172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
22272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    // No data match, request data and add entry.
22372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkAutoTUnref<SkStreamAsset> stream(fProxy->getData(id.fDataId));
22472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    if (stream.get() == NULL) {
22572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return NULL;
22672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
22772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
22872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkAutoTUnref<SkTypeface> typeface(fImpl->createFromStream(stream, id.fTtcIndex));
22972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    if (typeface.get() == NULL) {
23072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        return NULL;
23172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
23272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
23372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    DataEntry& newEntry = fDataCache.push_back();
23472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    typeface->weak_ref();
23572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    newEntry.fDataId = id.fDataId;
23672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    newEntry.fTtcIndex = id.fTtcIndex;
23772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    newEntry.fTypeface = typeface.get();  // weak reference passed to new entry.
23872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
23972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return typeface.detach();
24072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
24172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
24272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkTypeface* SkFontMgr_Indirect::onMatchFamilyStyle(const char familyName[],
24372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                   const SkFontStyle& fontStyle) const {
24472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkFontIdentity id = fProxy->matchNameStyle(familyName, fontStyle);
24572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return this->createTypefaceFromFontId(id);
24672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
24772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
24872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkTypeface* SkFontMgr_Indirect::onMatchFamilyStyleCharacter(const char familyName[],
24972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                            const SkFontStyle& style,
25072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                            const char bpc47[],
25172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                            uint32_t character) const {
25272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkFontIdentity id = fProxy->matchNameStyleCharacter(familyName, style, bpc47, character);
25372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return this->createTypefaceFromFontId(id);
25472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
25572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
25672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkTypeface* SkFontMgr_Indirect::onMatchFaceStyle(const SkTypeface* familyMember,
25772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                 const SkFontStyle& fontStyle) const {
25872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkString familyName;
25972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    familyMember->getFamilyName(&familyName);
26072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return this->matchFamilyStyle(familyName.c_str(), fontStyle);
26172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
26272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
26372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkTypeface* SkFontMgr_Indirect::onCreateFromStream(SkStream* stream, int ttcIndex) const {
26472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return fImpl->createFromStream(stream, ttcIndex);
26572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
26672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
26772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkTypeface* SkFontMgr_Indirect::onCreateFromFile(const char path[], int ttcIndex) const {
26872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return fImpl->createFromFile(path, ttcIndex);
26972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
27072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
27172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkTypeface* SkFontMgr_Indirect::onCreateFromData(SkData* data, int ttcIndex) const {
27272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return fImpl->createFromData(data, ttcIndex);
27372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
27472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
27572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comSkTypeface* SkFontMgr_Indirect::onLegacyCreateTypeface(const char familyName[],
27672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                                       unsigned styleBits) const {
27772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    bool bold = SkToBool(styleBits & SkTypeface::kBold);
27872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    bool italic = SkToBool(styleBits & SkTypeface::kItalic);
27972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight
28072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                         : SkFontStyle::kNormal_Weight,
28172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                    SkFontStyle::kNormal_Width,
28272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                    italic ? SkFontStyle::kItalic_Slant
28372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com                                           : SkFontStyle::kUpright_Slant);
28472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
28572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    SkAutoTUnref<SkTypeface> face(this->matchFamilyStyle(familyName, style));
28672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
28772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    if (NULL == face.get()) {
28872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        face.reset(this->matchFamilyStyle(NULL, style));
28972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
29072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
29172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    if (NULL == face.get()) {
29272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        SkFontIdentity fontId = this->fProxy->matchIndexStyle(0, style);
29372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com        face.reset(this->createTypefaceFromFontId(fontId));
29472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    }
29572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com
29672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com    return face.detach();
29772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com}
298