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 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. 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 } 212