1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
8d71fe99fe4d54230572223915166bea8efd67d85reed@google.com#include "SkFontConfigInterface.h"
96930b57221ea7010dcab516559fa6bc5a0fb3807djsollen@google.com#include "SkFontConfigTypeface.h"
10d71fe99fe4d54230572223915166bea8efd67d85reed@google.com#include "SkFontDescriptor.h"
11df8ecfbcffb297c361cb3e30ab4d7469a6b2e966agl@chromium.org#include "SkFontHost.h"
120da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com#include "SkFontHost_FreeType_common.h"
13822bde74b954df6ed91b01529477e7fd41716fffreed@google.com#include "SkFontStream.h"
14df8ecfbcffb297c361cb3e30ab4d7469a6b2e966agl@chromium.org#include "SkStream.h"
1580f5465083bdc5449223f5875b401648616e8e09reed@google.com#include "SkTypeface.h"
16f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com#include "SkTypefaceCache.h"
17b1c65b62bf276872ab4f9da7569ea7f0899a3569reed@google.com
186d2fef9834531ea0e400b6d57a9619f77ca1962bdjsollen@google.com///////////////////////////////////////////////////////////////////////////////
196d2fef9834531ea0e400b6d57a9619f77ca1962bdjsollen@google.com///////////////////////////////////////////////////////////////////////////////
206d2fef9834531ea0e400b6d57a9619f77ca1962bdjsollen@google.com
21d71fe99fe4d54230572223915166bea8efd67d85reed@google.comSK_DECLARE_STATIC_MUTEX(gFontConfigInterfaceMutex);
22d71fe99fe4d54230572223915166bea8efd67d85reed@google.comstatic SkFontConfigInterface* gFontConfigInterface;
23df8ecfbcffb297c361cb3e30ab4d7469a6b2e966agl@chromium.org
24d71fe99fe4d54230572223915166bea8efd67d85reed@google.comSkFontConfigInterface* SkFontConfigInterface::RefGlobal() {
25d71fe99fe4d54230572223915166bea8efd67d85reed@google.com    SkAutoMutexAcquire ac(gFontConfigInterfaceMutex);
265ca3bd0cbb34cb4e61c0ea3591a4967ee1d6140askia.committer@gmail.com
27d71fe99fe4d54230572223915166bea8efd67d85reed@google.com    return SkSafeRef(gFontConfigInterface);
28d71fe99fe4d54230572223915166bea8efd67d85reed@google.com}
29b13d63c4c0878a3de7230f79a7044830c93d3849bungeman@google.com
30d71fe99fe4d54230572223915166bea8efd67d85reed@google.comSkFontConfigInterface* SkFontConfigInterface::SetGlobal(SkFontConfigInterface* fc) {
31d71fe99fe4d54230572223915166bea8efd67d85reed@google.com    SkAutoMutexAcquire ac(gFontConfigInterfaceMutex);
32df8ecfbcffb297c361cb3e30ab4d7469a6b2e966agl@chromium.org
33d71fe99fe4d54230572223915166bea8efd67d85reed@google.com    SkRefCnt_SafeAssign(gFontConfigInterface, fc);
34d71fe99fe4d54230572223915166bea8efd67d85reed@google.com    return fc;
35d71fe99fe4d54230572223915166bea8efd67d85reed@google.com}
36d71fe99fe4d54230572223915166bea8efd67d85reed@google.com
37d71fe99fe4d54230572223915166bea8efd67d85reed@google.com///////////////////////////////////////////////////////////////////////////////
38f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com///////////////////////////////////////////////////////////////////////////////
39f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com
40f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com// convenience function to create the direct interface if none is installed.
41f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.comextern SkFontConfigInterface* SkCreateDirectFontConfigInterface();
42d71fe99fe4d54230572223915166bea8efd67d85reed@google.com
4380f5465083bdc5449223f5875b401648616e8e09reed@google.comstatic SkFontConfigInterface* RefFCI() {
44b1c65b62bf276872ab4f9da7569ea7f0899a3569reed@google.com    for (;;) {
45b1c65b62bf276872ab4f9da7569ea7f0899a3569reed@google.com        SkFontConfigInterface* fci = SkFontConfigInterface::RefGlobal();
46b1c65b62bf276872ab4f9da7569ea7f0899a3569reed@google.com        if (fci) {
47b1c65b62bf276872ab4f9da7569ea7f0899a3569reed@google.com            return fci;
48b1c65b62bf276872ab4f9da7569ea7f0899a3569reed@google.com        }
49e438ddbc7451ec80f953266409fea4695e78c8c2tomhudson        fci = SkFontConfigInterface::GetSingletonDirectInterface(&gFontConfigInterfaceMutex);
50750a24bb3d39e59d32db3f166ad3f39c7560c0a9reed@google.com        SkFontConfigInterface::SetGlobal(fci);
51b1c65b62bf276872ab4f9da7569ea7f0899a3569reed@google.com    }
5280f5465083bdc5449223f5875b401648616e8e09reed@google.com}
5380f5465083bdc5449223f5875b401648616e8e09reed@google.com
54381bb43efb1697a67b1c02d1d9774fef9c643c4breed@google.com// export this to SkFontMgr_fontconfig.cpp until this file just goes away.
55381bb43efb1697a67b1c02d1d9774fef9c643c4breed@google.comSkFontConfigInterface* SkFontHost_fontconfig_ref_global();
56381bb43efb1697a67b1c02d1d9774fef9c643c4breed@google.comSkFontConfigInterface* SkFontHost_fontconfig_ref_global() {
57381bb43efb1697a67b1c02d1d9774fef9c643c4breed@google.com    return RefFCI();
58381bb43efb1697a67b1c02d1d9774fef9c643c4breed@google.com}
59381bb43efb1697a67b1c02d1d9774fef9c643c4breed@google.com
60381bb43efb1697a67b1c02d1d9774fef9c643c4breed@google.com///////////////////////////////////////////////////////////////////////////////
61381bb43efb1697a67b1c02d1d9774fef9c643c4breed@google.com
62f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.comstruct FindRec {
63f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    FindRec(const char* name, SkTypeface::Style style)
64f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com        : fFamilyName(name)  // don't need to make a deep copy
65f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com        , fStyle(style) {}
66d71fe99fe4d54230572223915166bea8efd67d85reed@google.com
67f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    const char* fFamilyName;
68f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    SkTypeface::Style fStyle;
69f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com};
70df8ecfbcffb297c361cb3e30ab4d7469a6b2e966agl@chromium.org
71f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.comstatic bool find_proc(SkTypeface* face, SkTypeface::Style style, void* ctx) {
72f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    FontConfigTypeface* fci = (FontConfigTypeface*)face;
73f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    const FindRec* rec = (const FindRec*)ctx;
74df8ecfbcffb297c361cb3e30ab4d7469a6b2e966agl@chromium.org
75f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    return rec->fStyle == style && fci->isFamilyName(rec->fFamilyName);
76f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com}
77df8ecfbcffb297c361cb3e30ab4d7469a6b2e966agl@chromium.org
78e027a6ed9b9e2a96be846ddefb2b06e350858eedreed@google.comSkTypeface* FontConfigTypeface::LegacyCreateTypeface(
79e027a6ed9b9e2a96be846ddefb2b06e350858eedreed@google.com                const SkTypeface* familyFace,
80e027a6ed9b9e2a96be846ddefb2b06e350858eedreed@google.com                const char familyName[],
81e027a6ed9b9e2a96be846ddefb2b06e350858eedreed@google.com                SkTypeface::Style style) {
8280f5465083bdc5449223f5875b401648616e8e09reed@google.com    SkAutoTUnref<SkFontConfigInterface> fci(RefFCI());
8380f5465083bdc5449223f5875b401648616e8e09reed@google.com    if (NULL == fci.get()) {
8480f5465083bdc5449223f5875b401648616e8e09reed@google.com        return NULL;
8580f5465083bdc5449223f5875b401648616e8e09reed@google.com    }
8680f5465083bdc5449223f5875b401648616e8e09reed@google.com
87df8ecfbcffb297c361cb3e30ab4d7469a6b2e966agl@chromium.org    if (familyFace) {
88f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com        FontConfigTypeface* fct = (FontConfigTypeface*)familyFace;
89f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com        familyName = fct->getFamilyName();
90b13d63c4c0878a3de7230f79a7044830c93d3849bungeman@google.com    }
91b13d63c4c0878a3de7230f79a7044830c93d3849bungeman@google.com
92f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    FindRec rec(familyName, style);
93f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_proc, &rec);
94f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    if (face) {
950b8a2fe2cde14d15dec1b8252d0f328312f9e59creed@google.com//        SkDebugf("found cached face <%s> <%s> %p [%d]\n", familyName, ((FontConfigTypeface*)face)->getFamilyName(), face, face->getRefCnt());
96f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com        return face;
97f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    }
98f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com
99f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    SkFontConfigInterface::FontIdentity indentity;
100f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    SkString                            outFamilyName;
101f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    SkTypeface::Style                   outStyle;
102f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com
103f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    if (!fci->matchFamilyName(familyName, style,
104f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com                              &indentity, &outFamilyName, &outStyle)) {
105d71fe99fe4d54230572223915166bea8efd67d85reed@google.com        return NULL;
106df8ecfbcffb297c361cb3e30ab4d7469a6b2e966agl@chromium.org    }
10780f5465083bdc5449223f5875b401648616e8e09reed@google.com
108d44d988127841cf9180bb7ba91b6eba8127af467reed@google.com    // check if we, in fact, already have this. perhaps fontconfig aliased the
109d44d988127841cf9180bb7ba91b6eba8127af467reed@google.com    // requested name to some other name we actually have...
110d44d988127841cf9180bb7ba91b6eba8127af467reed@google.com    rec.fFamilyName = outFamilyName.c_str();
111d44d988127841cf9180bb7ba91b6eba8127af467reed@google.com    rec.fStyle = outStyle;
112d44d988127841cf9180bb7ba91b6eba8127af467reed@google.com    face = SkTypefaceCache::FindByProcAndRef(find_proc, &rec);
113d44d988127841cf9180bb7ba91b6eba8127af467reed@google.com    if (face) {
114d44d988127841cf9180bb7ba91b6eba8127af467reed@google.com        return face;
115d44d988127841cf9180bb7ba91b6eba8127af467reed@google.com    }
116d44d988127841cf9180bb7ba91b6eba8127af467reed@google.com
117c4df655b37aea7097d3007b299de582ba517ef16commit-bot@chromium.org    face = FontConfigTypeface::Create(outStyle, indentity, outFamilyName);
118f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    SkTypefaceCache::Add(face, style);
1190b8a2fe2cde14d15dec1b8252d0f328312f9e59creed@google.com//    SkDebugf("add face <%s> <%s> %p [%d]\n", familyName, outFamilyName.c_str(), face, face->getRefCnt());
120f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    return face;
121d71fe99fe4d54230572223915166bea8efd67d85reed@google.com}
122df8ecfbcffb297c361cb3e30ab4d7469a6b2e966agl@chromium.org
123822bde74b954df6ed91b01529477e7fd41716fffreed@google.com///////////////////////////////////////////////////////////////////////////////
124822bde74b954df6ed91b01529477e7fd41716fffreed@google.com
1252cdc6713fb04c46ecbc73a724029a8b266004ddfreed@google.comSkStream* FontConfigTypeface::onOpenStream(int* ttcIndex) const {
1262cdc6713fb04c46ecbc73a724029a8b266004ddfreed@google.com    SkStream* stream = this->getLocalStream();
127f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    if (stream) {
1285bfc8396228b7a9e5be679aeb10f30860adf938freed@google.com        // should have been provided by CreateFromStream()
1295bfc8396228b7a9e5be679aeb10f30860adf938freed@google.com        *ttcIndex = 0;
1306cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
1316cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        SkAutoTUnref<SkStream> dupStream(stream->duplicate());
1326cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        if (dupStream) {
1336cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com            return dupStream.detach();
1346cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        }
1356cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
1366cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        // TODO: update interface use, remove the following code in this block.
1376cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        size_t length = stream->getLength();
1386cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
1396cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        const void* memory = stream->getMemoryBase();
14049f085dddff10473b6ebf832a974288300224e60bsalomon        if (memory) {
1416cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com            return new SkMemoryStream(memory, length, true);
1426cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        }
1436cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
1446cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        SkAutoTMalloc<uint8_t> allocMemory(length);
1456cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        stream->rewind();
1466cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        if (length == stream->read(allocMemory.get(), length)) {
14788605bb51d9f90e03c9cc448ed2ebcba2854ed14bungeman@google.com            SkAutoTUnref<SkMemoryStream> copyStream(new SkMemoryStream());
14888605bb51d9f90e03c9cc448ed2ebcba2854ed14bungeman@google.com            copyStream->setMemoryOwned(allocMemory.detach(), length);
14988605bb51d9f90e03c9cc448ed2ebcba2854ed14bungeman@google.com            return copyStream.detach();
1506cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        }
1516cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com
1526cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        stream->rewind();
1536cab1a4b6a68aa81237731308ff37a646d48f51cbungeman@google.com        stream->ref();
154f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    } else {
155f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com        SkAutoTUnref<SkFontConfigInterface> fci(RefFCI());
156f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com        if (NULL == fci.get()) {
157f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com            return NULL;
158f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com        }
1592cdc6713fb04c46ecbc73a724029a8b266004ddfreed@google.com        stream = fci->openStream(this->getIdentity());
1602cdc6713fb04c46ecbc73a724029a8b266004ddfreed@google.com        *ttcIndex = this->getIdentity().fTTCIndex;
161f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    }
162f71a2335f9b64442c65b45d1f703cd4ffb84129dreed@google.com    return stream;
163df8ecfbcffb297c361cb3e30ab4d7469a6b2e966agl@chromium.org}
164df8ecfbcffb297c361cb3e30ab4d7469a6b2e966agl@chromium.org
165b374d6a62c0259387d90cad74753d8bad9ee1beabungemanvoid FontConfigTypeface::onGetFamilyName(SkString* familyName) const {
166b374d6a62c0259387d90cad74753d8bad9ee1beabungeman    *familyName = this->getFamilyName();
167b374d6a62c0259387d90cad74753d8bad9ee1beabungeman}
168b374d6a62c0259387d90cad74753d8bad9ee1beabungeman
1695526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.comvoid FontConfigTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
1705526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.com                                             bool* isLocalStream) const {
171822bde74b954df6ed91b01529477e7fd41716fffreed@google.com    desc->setFamilyName(this->getFamilyName());
172d71b75757335393d9643a5b7a0f2769b6ba52fb6bungeman    desc->setFontIndex(this->getIdentity().fTTCIndex);
1735526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.com    *isLocalStream = SkToBool(this->getLocalStream());
174822bde74b954df6ed91b01529477e7fd41716fffreed@google.com}
175