1 /*
2 * Copyright (C) 2007 Apple Computer, Inc.
3 * Copyright (c) 2007, 2008, 2009, Google Inc. All rights reserved.
4 * Copyright (C) 2010 Company 100, Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include "config.h"
34 #include "FontCustomPlatformData.h"
35
36 #if OS(WINDOWS)
37 #include "Base64.h"
38 #include "OpenTypeUtilities.h"
39 #include "PlatformBridge.h"
40 #elif OS(LINUX) || OS(FREEBSD) || PLATFORM(BREWMP)
41 #include "SkStream.h"
42 #endif
43
44 #include "FontPlatformData.h"
45 #include "NotImplemented.h"
46 #include "OpenTypeSanitizer.h"
47 #include "SharedBuffer.h"
48
49 #if OS(WINDOWS)
50 #include <objbase.h>
51 #elif OS(LINUX) || OS(FREEBSD) || PLATFORM(BREWMP)
52 #include <cstring>
53 #endif
54
55 namespace WebCore {
56
~FontCustomPlatformData()57 FontCustomPlatformData::~FontCustomPlatformData()
58 {
59 #if OS(WINDOWS)
60 if (m_fontReference)
61 RemoveFontMemResourceEx(m_fontReference);
62 #elif OS(LINUX) || OS(FREEBSD) || PLATFORM(BREWMP)
63 if (m_fontReference)
64 m_fontReference->unref();
65 #endif
66 }
67
fontPlatformData(int size,bool bold,bool italic,FontOrientation orientation,TextOrientation textOrientation,FontWidthVariant,FontRenderingMode mode)68 FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation,
69 TextOrientation textOrientation, FontWidthVariant, FontRenderingMode mode)
70 {
71 #if OS(WINDOWS)
72 ASSERT(m_fontReference);
73
74 LOGFONT logFont;
75 // m_name comes from createUniqueFontName, which, in turn, gets
76 // it from base64-encoded uuid (128-bit). So, m_name
77 // can never be longer than LF_FACESIZE (32).
78 if (m_name.length() + 1 >= LF_FACESIZE) {
79 ASSERT_NOT_REACHED();
80 return FontPlatformData();
81 }
82 memcpy(logFont.lfFaceName, m_name.charactersWithNullTermination(),
83 sizeof(logFont.lfFaceName[0]) * (1 + m_name.length()));
84
85 // FIXME: almost identical to FillLogFont in FontCacheWin.cpp.
86 // Need to refactor.
87 logFont.lfHeight = -size;
88 logFont.lfWidth = 0;
89 logFont.lfEscapement = 0;
90 logFont.lfOrientation = 0;
91 logFont.lfUnderline = false;
92 logFont.lfStrikeOut = false;
93 logFont.lfCharSet = DEFAULT_CHARSET;
94 logFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
95 logFont.lfQuality = PlatformBridge::layoutTestMode() ?
96 NONANTIALIASED_QUALITY :
97 DEFAULT_QUALITY; // Honor user's desktop settings.
98 logFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
99 logFont.lfItalic = italic;
100 logFont.lfWeight = bold ? 700 : 400;
101
102 HFONT hfont = CreateFontIndirect(&logFont);
103 return FontPlatformData(hfont, size);
104 #elif OS(LINUX) || OS(FREEBSD) || PLATFORM(BREWMP)
105 ASSERT(m_fontReference);
106 return FontPlatformData(m_fontReference, "", size, bold && !m_fontReference->isBold(), italic && !m_fontReference->isItalic(), orientation, textOrientation);
107 #else
108 notImplemented();
109 return FontPlatformData();
110 #endif
111 }
112
113 #if OS(WINDOWS)
114 // Creates a unique and unpredictable font name, in order to avoid collisions and to
115 // not allow access from CSS.
createUniqueFontName()116 static String createUniqueFontName()
117 {
118 GUID fontUuid;
119 CoCreateGuid(&fontUuid);
120
121 String fontName = base64Encode(reinterpret_cast<char*>(&fontUuid), sizeof(fontUuid));
122 ASSERT(fontName.length() < LF_FACESIZE);
123 return fontName;
124 }
125 #endif
126
127 #if OS(LINUX) || OS(FREEBSD) || PLATFORM(BREWMP)
128 class RemoteFontStream : public SkStream {
129 public:
RemoteFontStream(PassRefPtr<SharedBuffer> buffer)130 explicit RemoteFontStream(PassRefPtr<SharedBuffer> buffer)
131 : m_buffer(buffer)
132 , m_offset(0)
133 {
134 }
135
~RemoteFontStream()136 virtual ~RemoteFontStream()
137 {
138 }
139
rewind()140 virtual bool rewind()
141 {
142 m_offset = 0;
143 return true;
144 }
145
read(void * buffer,size_t size)146 virtual size_t read(void* buffer, size_t size)
147 {
148 if (!buffer && !size) {
149 // This is request for the length of the stream.
150 return m_buffer->size();
151 }
152 // This is a request to read bytes or skip bytes (when buffer is 0).
153 if (!m_buffer->data() || !m_buffer->size())
154 return 0;
155 size_t left = m_buffer->size() - m_offset;
156 size_t bytesToConsume = std::min(left, size);
157 if (buffer)
158 std::memcpy(buffer, m_buffer->data() + m_offset, bytesToConsume);
159 m_offset += bytesToConsume;
160 return bytesToConsume;
161 }
162
163 private:
164 RefPtr<SharedBuffer> m_buffer;
165 size_t m_offset;
166 };
167 #endif
168
createFontCustomPlatformData(SharedBuffer * buffer)169 FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
170 {
171 ASSERT_ARG(buffer, buffer);
172
173 #if ENABLE(OPENTYPE_SANITIZER)
174 OpenTypeSanitizer sanitizer(buffer);
175 RefPtr<SharedBuffer> transcodeBuffer = sanitizer.sanitize();
176 if (!transcodeBuffer)
177 return 0; // validation failed.
178 buffer = transcodeBuffer.get();
179 #endif
180
181 #if OS(WINDOWS)
182 // Introduce the font to GDI. AddFontMemResourceEx should be used with care, because it will pollute the process's
183 // font namespace (Windows has no API for creating an HFONT from data without exposing the font to the
184 // entire process first).
185 String fontName = createUniqueFontName();
186 HANDLE fontReference = renameAndActivateFont(buffer, fontName);
187 if (!fontReference)
188 return 0;
189 return new FontCustomPlatformData(fontReference, fontName);
190 #elif OS(LINUX) || OS(FREEBSD) || PLATFORM(BREWMP)
191 RemoteFontStream* stream = new RemoteFontStream(buffer);
192 SkTypeface* typeface = SkTypeface::CreateFromStream(stream);
193 if (!typeface)
194 return 0;
195 return new FontCustomPlatformData(typeface);
196 #else
197 notImplemented();
198 return 0;
199 #endif
200 }
201
supportsFormat(const String & format)202 bool FontCustomPlatformData::supportsFormat(const String& format)
203 {
204 return equalIgnoringCase(format, "truetype") || equalIgnoringCase(format, "opentype")
205 #if ENABLE(OPENTYPE_SANITIZER)
206 || equalIgnoringCase(format, "woff")
207 #endif
208 ;
209 }
210
211 }
212