https://bugs.webkit.org/show_bug.cgi?id=48540, support the text-orientation CSS property.
[WebKit-https.git] / Source / WebCore / platform / graphics / skia / FontCustomPlatformData.cpp
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
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
68 FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation,
69                                                           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);
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.
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:
130     explicit RemoteFontStream(PassRefPtr<SharedBuffer> buffer)
131         : m_buffer(buffer)
132         , m_offset(0)
133     {
134     }
135
136     virtual ~RemoteFontStream()
137     {
138     }
139
140     virtual bool rewind()
141     {
142         m_offset = 0;
143         return true;
144     }
145
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
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
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 }