1308ff0c0d3d3673784ddb582aa083cee229d3e6
[WebKit-https.git] / WebCore / platform / graphics / win / FontDatabase.cpp
1 /*
2  * Copyright (C) 2007 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "FontDatabase.h"
31
32 #include "CString.h"
33 #include "FileSystem.h"
34 #include "PlatformString.h"
35 #include <WebKitSystemInterface/WebKitSystemInterface.h>
36 #include <shlobj.h>
37 #include <wtf/RetainPtr.h>
38
39 namespace WebCore {
40
41 static String systemFontsDirectory()
42 {
43     static bool initialized;
44     static String directory;
45
46     if (!initialized) {
47         initialized = true;
48
49         Vector<UChar> buffer(MAX_PATH);
50         if (FAILED(SHGetFolderPath(0, CSIDL_FONTS | CSIDL_FLAG_CREATE, 0, 0, buffer.data())))
51             return directory;
52         buffer.resize(wcslen(buffer.data()));
53
54         directory = String::adopt(buffer);
55     }
56
57     return directory;
58 }
59
60 static String fontsPlistPath()
61 {
62     static String path = pathByAppendingComponent(localUserSpecificStorageDirectory(), "FontsList.plist");
63     return path;
64 }
65
66 static bool systemHasFontsNewerThanFontsPlist()
67 {
68     WIN32_FILE_ATTRIBUTE_DATA plistAttributes = {0};
69     if (!GetFileAttributesEx(fontsPlistPath().charactersWithNullTermination(), GetFileExInfoStandard, &plistAttributes))
70         return true;
71
72     WIN32_FILE_ATTRIBUTE_DATA fontsDirectoryAttributes = {0};
73     if (!GetFileAttributesEx(systemFontsDirectory().charactersWithNullTermination(), GetFileExInfoStandard, &fontsDirectoryAttributes))
74         return true;
75
76     return CompareFileTime(&plistAttributes.ftLastWriteTime, &fontsDirectoryAttributes.ftLastWriteTime) < 0;
77 }
78
79 static RetainPtr<CFPropertyListRef> readFontPlist()
80 {
81     CString plistPath = fontsPlistPath().utf8();
82
83     RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateFromFileSystemRepresentation(0, reinterpret_cast<const UInt8*>(plistPath.data()), plistPath.length(), false));
84     if (!url)
85         return 0;
86
87     RetainPtr<CFReadStreamRef> stream(AdoptCF, CFReadStreamCreateWithFile(0, url.get()));
88     if (!stream)
89         return 0;
90
91     if (!CFReadStreamOpen(stream.get()))
92         return 0;
93
94     CFPropertyListFormat format = kCFPropertyListBinaryFormat_v1_0 | kCFPropertyListXMLFormat_v1_0;
95     RetainPtr<CFPropertyListRef> plist(AdoptCF, CFPropertyListCreateFromStream(0, stream.get(), 0, kCFPropertyListMutableContainersAndLeaves, &format, 0));
96
97     CFReadStreamClose(stream.get());
98
99     return plist;
100 }
101
102 static bool populateFontDatabaseFromPlist()
103 {
104     RetainPtr<CFPropertyListRef> plist = readFontPlist();
105     if (!plist)
106         return false;
107
108     RetainPtr<CFDataRef> data(AdoptCF, CFPropertyListCreateXMLData(0, plist.get()));
109     if (!data)
110         return false;
111
112     wkAddFontsFromPlistRepresentation(data.get());
113     return true;
114 }
115
116 static bool populateFontDatabaseFromFileSystem()
117 {
118     RetainPtr<CFStringRef> directory(AdoptCF, systemFontsDirectory().createCFString());
119     if (!directory)
120         return false;
121
122     wkAddFontsInDirectory(directory.get());
123     return true;
124 }
125
126 static void writeFontDatabaseToPlist()
127 {
128     RetainPtr<CFDataRef> data(AdoptCF, wkCreateFontsPlistRepresentation());
129     if (!data)
130         return;
131
132     safeCreateFile(fontsPlistPath(), data.get());
133 }
134
135 void populateFontDatabase()
136 {
137     static bool initialized;
138     if (initialized)
139         return;
140     initialized = true;
141
142     if (!systemHasFontsNewerThanFontsPlist())
143         if (populateFontDatabaseFromPlist())
144             return;
145
146     if (populateFontDatabaseFromFileSystem())
147         writeFontDatabaseToPlist();
148 }
149
150 } // namespace WebCore