Upstream version 9.38.198.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 #ifdef SK_FONTHOST_DOES_NOT_USE_FONTMGR
124
125 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
126                                        const char familyName[],
127                                        SkTypeface::Style style) {
128     return FontConfigTypeface::LegacyCreateTypeface(familyFace, familyName,
129                                                     style);
130 }
131
132 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
133     if (!stream) {
134         return NULL;
135     }
136     const size_t length = stream->getLength();
137     if (!length) {
138         return NULL;
139     }
140     if (length >= 1024 * 1024 * 1024) {
141         return NULL;  // don't accept too large fonts (>= 1GB) for safety.
142     }
143
144     // ask freetype for reported style and if it is a fixed width font
145     SkTypeface::Style style = SkTypeface::kNormal;
146     bool isFixedWidth = false;
147     if (!SkTypeface_FreeType::ScanFont(stream, 0, NULL, &style, &isFixedWidth)) {
148         return NULL;
149     }
150
151     SkTypeface* face = SkNEW_ARGS(FontConfigTypeface, (style, isFixedWidth, stream));
152     return face;
153 }
154
155 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
156     SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
157     return stream.get() ? CreateTypefaceFromStream(stream) : NULL;
158 }
159
160 #endif
161
162 ///////////////////////////////////////////////////////////////////////////////
163
164 SkStream* FontConfigTypeface::onOpenStream(int* ttcIndex) const {
165     SkStream* stream = this->getLocalStream();
166     if (stream) {
167         // should have been provided by CreateFromStream()
168         *ttcIndex = 0;
169
170         SkAutoTUnref<SkStream> dupStream(stream->duplicate());
171         if (dupStream) {
172             return dupStream.detach();
173         }
174
175         // TODO: update interface use, remove the following code in this block.
176         size_t length = stream->getLength();
177
178         const void* memory = stream->getMemoryBase();
179         if (NULL != memory) {
180             return new SkMemoryStream(memory, length, true);
181         }
182
183         SkAutoTMalloc<uint8_t> allocMemory(length);
184         stream->rewind();
185         if (length == stream->read(allocMemory.get(), length)) {
186             SkAutoTUnref<SkMemoryStream> copyStream(new SkMemoryStream());
187             copyStream->setMemoryOwned(allocMemory.detach(), length);
188             return copyStream.detach();
189         }
190
191         stream->rewind();
192         stream->ref();
193     } else {
194         SkAutoTUnref<SkFontConfigInterface> fci(RefFCI());
195         if (NULL == fci.get()) {
196             return NULL;
197         }
198         stream = fci->openStream(this->getIdentity());
199         *ttcIndex = this->getIdentity().fTTCIndex;
200     }
201     return stream;
202 }
203
204 void FontConfigTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
205                                              bool* isLocalStream) const {
206     desc->setFamilyName(this->getFamilyName());
207     *isLocalStream = SkToBool(this->getLocalStream());
208 }