Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / ports / SkFontHost_fontconfig.cpp
1 /*
2  * Copyright 2008 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 "SkFontConfigInterface.h"
9 #include "SkFontConfigTypeface.h"
10 #include "SkFontDescriptor.h"
11 #include "SkFontHost.h"
12 #include "SkFontHost_FreeType_common.h"
13 #include "SkFontStream.h"
14 #include "SkStream.h"
15 #include "SkTypeface.h"
16 #include "SkTypefaceCache.h"
17
18 ///////////////////////////////////////////////////////////////////////////////
19 ///////////////////////////////////////////////////////////////////////////////
20
21 SK_DECLARE_STATIC_MUTEX(gFontConfigInterfaceMutex);
22 static SkFontConfigInterface* gFontConfigInterface;
23
24 SkFontConfigInterface* SkFontConfigInterface::RefGlobal() {
25     SkAutoMutexAcquire ac(gFontConfigInterfaceMutex);
26
27     return SkSafeRef(gFontConfigInterface);
28 }
29
30 SkFontConfigInterface* SkFontConfigInterface::SetGlobal(SkFontConfigInterface* fc) {
31     SkAutoMutexAcquire ac(gFontConfigInterfaceMutex);
32
33     SkRefCnt_SafeAssign(gFontConfigInterface, fc);
34     return fc;
35 }
36
37 ///////////////////////////////////////////////////////////////////////////////
38 ///////////////////////////////////////////////////////////////////////////////
39
40 // convenience function to create the direct interface if none is installed.
41 extern SkFontConfigInterface* SkCreateDirectFontConfigInterface();
42
43 static SkFontConfigInterface* RefFCI() {
44     for (;;) {
45         SkFontConfigInterface* fci = SkFontConfigInterface::RefGlobal();
46         if (fci) {
47             return fci;
48         }
49         fci = SkFontConfigInterface::GetSingletonDirectInterface(&gFontConfigInterfaceMutex);
50         SkFontConfigInterface::SetGlobal(fci);
51     }
52 }
53
54 // export this to SkFontMgr_fontconfig.cpp until this file just goes away.
55 SkFontConfigInterface* SkFontHost_fontconfig_ref_global();
56 SkFontConfigInterface* SkFontHost_fontconfig_ref_global() {
57     return RefFCI();
58 }
59
60 ///////////////////////////////////////////////////////////////////////////////
61
62 struct FindRec {
63     FindRec(const char* name, SkTypeface::Style style)
64         : fFamilyName(name)  // don't need to make a deep copy
65         , fStyle(style) {}
66
67     const char* fFamilyName;
68     SkTypeface::Style fStyle;
69 };
70
71 static bool find_proc(SkTypeface* face, SkTypeface::Style style, void* ctx) {
72     FontConfigTypeface* fci = (FontConfigTypeface*)face;
73     const FindRec* rec = (const FindRec*)ctx;
74
75     return rec->fStyle == style && fci->isFamilyName(rec->fFamilyName);
76 }
77
78 SkTypeface* FontConfigTypeface::LegacyCreateTypeface(
79                 const SkTypeface* familyFace,
80                 const char familyName[],
81                 SkTypeface::Style style) {
82     SkAutoTUnref<SkFontConfigInterface> fci(RefFCI());
83     if (NULL == fci.get()) {
84         return NULL;
85     }
86
87     if (familyFace) {
88         FontConfigTypeface* fct = (FontConfigTypeface*)familyFace;
89         familyName = fct->getFamilyName();
90     }
91
92     FindRec rec(familyName, style);
93     SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_proc, &rec);
94     if (face) {
95 //        SkDebugf("found cached face <%s> <%s> %p [%d]\n", familyName, ((FontConfigTypeface*)face)->getFamilyName(), face, face->getRefCnt());
96         return face;
97     }
98
99     SkFontConfigInterface::FontIdentity indentity;
100     SkString                            outFamilyName;
101     SkTypeface::Style                   outStyle;
102
103     if (!fci->matchFamilyName(familyName, style,
104                               &indentity, &outFamilyName, &outStyle)) {
105         return NULL;
106     }
107
108     // check if we, in fact, already have this. perhaps fontconfig aliased the
109     // requested name to some other name we actually have...
110     rec.fFamilyName = outFamilyName.c_str();
111     rec.fStyle = outStyle;
112     face = SkTypefaceCache::FindByProcAndRef(find_proc, &rec);
113     if (face) {
114         return face;
115     }
116
117     face = FontConfigTypeface::Create(outStyle, indentity, outFamilyName);
118     SkTypefaceCache::Add(face, style);
119 //    SkDebugf("add face <%s> <%s> %p [%d]\n", familyName, outFamilyName.c_str(), face, face->getRefCnt());
120     return face;
121 }
122
123 ///////////////////////////////////////////////////////////////////////////////
124
125 SkStream* FontConfigTypeface::onOpenStream(int* ttcIndex) const {
126     SkStream* stream = this->getLocalStream();
127     if (stream) {
128         // should have been provided by CreateFromStream()
129         *ttcIndex = 0;
130
131         SkAutoTUnref<SkStream> dupStream(stream->duplicate());
132         if (dupStream) {
133             return dupStream.detach();
134         }
135
136         // TODO: update interface use, remove the following code in this block.
137         size_t length = stream->getLength();
138
139         const void* memory = stream->getMemoryBase();
140         if (memory) {
141             return new SkMemoryStream(memory, length, true);
142         }
143
144         SkAutoTMalloc<uint8_t> allocMemory(length);
145         stream->rewind();
146         if (length == stream->read(allocMemory.get(), length)) {
147             SkAutoTUnref<SkMemoryStream> copyStream(new SkMemoryStream());
148             copyStream->setMemoryOwned(allocMemory.detach(), length);
149             return copyStream.detach();
150         }
151
152         stream->rewind();
153         stream->ref();
154     } else {
155         SkAutoTUnref<SkFontConfigInterface> fci(RefFCI());
156         if (NULL == fci.get()) {
157             return NULL;
158         }
159         stream = fci->openStream(this->getIdentity());
160         *ttcIndex = this->getIdentity().fTTCIndex;
161     }
162     return stream;
163 }
164
165 void FontConfigTypeface::onGetFamilyName(SkString* familyName) const {
166     *familyName = this->getFamilyName();
167 }
168
169 void FontConfigTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
170                                              bool* isLocalStream) const {
171     desc->setFamilyName(this->getFamilyName());
172     desc->setFontIndex(this->getIdentity().fTTCIndex);
173     *isLocalStream = SkToBool(this->getLocalStream());
174 }