1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "content/browser/renderer_host/pepper/pepper_truetype_font.h" 6 7#include <windows.h> 8#include <set> 9 10#include "base/compiler_specific.h" 11#include "base/memory/scoped_ptr.h" 12#include "base/strings/utf_string_conversions.h" 13#include "base/sys_byteorder.h" 14#include "base/win/scoped_gdi_object.h" 15#include "base/win/scoped_hdc.h" 16#include "base/win/scoped_select_object.h" 17#include "ppapi/c/dev/ppb_truetype_font_dev.h" 18#include "ppapi/c/pp_errors.h" 19 20namespace content { 21 22namespace { 23 24class PepperTrueTypeFontWin : public PepperTrueTypeFont { 25 public: 26 PepperTrueTypeFontWin(); 27 28 // PepperTrueTypeFont implementation. 29 virtual int32_t Initialize( 30 ppapi::proxy::SerializedTrueTypeFontDesc* desc) OVERRIDE; 31 virtual int32_t GetTableTags(std::vector<uint32_t>* tags) OVERRIDE; 32 virtual int32_t GetTable(uint32_t table_tag, 33 int32_t offset, 34 int32_t max_data_length, 35 std::string* data) OVERRIDE; 36 37 private: 38 virtual ~PepperTrueTypeFontWin(); 39 40 DWORD GetFontData(HDC hdc, 41 DWORD table, 42 DWORD offset, 43 LPVOID buffer, 44 DWORD length); 45 46 base::win::ScopedHFONT font_; 47 48 DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontWin); 49}; 50 51PepperTrueTypeFontWin::PepperTrueTypeFontWin() { 52} 53 54PepperTrueTypeFontWin::~PepperTrueTypeFontWin() { 55} 56 57int32_t PepperTrueTypeFontWin::Initialize( 58 ppapi::proxy::SerializedTrueTypeFontDesc* desc) { 59 DWORD pitch_and_family = DEFAULT_PITCH; 60 switch (desc->generic_family) { 61 case PP_TRUETYPEFONTFAMILY_SERIF: 62 pitch_and_family |= FF_ROMAN; 63 break; 64 case PP_TRUETYPEFONTFAMILY_SANSSERIF: 65 pitch_and_family |= FF_SWISS; 66 break; 67 case PP_TRUETYPEFONTFAMILY_CURSIVE: 68 pitch_and_family |= FF_SCRIPT; 69 break; 70 case PP_TRUETYPEFONTFAMILY_FANTASY: 71 pitch_and_family |= FF_DECORATIVE; 72 break; 73 case PP_TRUETYPEFONTFAMILY_MONOSPACE: 74 pitch_and_family |= FF_MODERN; 75 break; 76 } 77 // TODO(bbudge) support widths (extended, condensed). 78 79 font_.Set(CreateFont(0 /* height */, 80 0 /* width */, 81 0 /* escapement */, 82 0 /* orientation */, 83 desc->weight, // our weight enum matches Windows. 84 (desc->style & PP_TRUETYPEFONTSTYLE_ITALIC) ? 1 : 0, 85 0 /* underline */, 86 0 /* strikeout */, 87 desc->charset, // our charset enum matches Windows. 88 OUT_OUTLINE_PRECIS, // truetype and other outline fonts 89 CLIP_DEFAULT_PRECIS, 90 DEFAULT_QUALITY, 91 pitch_and_family, 92 base::UTF8ToUTF16(desc->family).c_str())); 93 if (!font_.Get()) 94 return PP_ERROR_FAILED; 95 96 LOGFONT font_desc; 97 if (!::GetObject(font_.Get(), sizeof(LOGFONT), &font_desc)) 98 return PP_ERROR_FAILED; 99 100 switch (font_desc.lfPitchAndFamily & 0xF0) { // Top 4 bits are family. 101 case FF_ROMAN: 102 desc->generic_family = PP_TRUETYPEFONTFAMILY_SERIF; 103 break; 104 case FF_SWISS: 105 desc->generic_family = PP_TRUETYPEFONTFAMILY_SANSSERIF; 106 break; 107 case FF_SCRIPT: 108 desc->generic_family = PP_TRUETYPEFONTFAMILY_CURSIVE; 109 break; 110 case FF_DECORATIVE: 111 desc->generic_family = PP_TRUETYPEFONTFAMILY_FANTASY; 112 break; 113 case FF_MODERN: 114 desc->generic_family = PP_TRUETYPEFONTFAMILY_MONOSPACE; 115 break; 116 } 117 118 desc->style = font_desc.lfItalic ? PP_TRUETYPEFONTSTYLE_ITALIC 119 : PP_TRUETYPEFONTSTYLE_NORMAL; 120 desc->weight = static_cast<PP_TrueTypeFontWeight_Dev>(font_desc.lfWeight); 121 desc->width = PP_TRUETYPEFONTWIDTH_NORMAL; 122 desc->charset = static_cast<PP_TrueTypeFontCharset_Dev>(font_desc.lfCharSet); 123 124 // To get the face name, select the font and query for the name. GetObject 125 // doesn't fill in the name field of the LOGFONT structure. 126 base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL)); 127 if (hdc.IsValid()) { 128 base::win::ScopedSelectObject select_object(hdc.Get(), font_.Get()); 129 WCHAR name[LF_FACESIZE]; 130 GetTextFace(hdc.Get(), LF_FACESIZE, name); 131 desc->family = base::UTF16ToUTF8(name); 132 } 133 134 return PP_OK; 135} 136 137int32_t PepperTrueTypeFontWin::GetTableTags(std::vector<uint32_t>* tags) { 138 if (!font_.Get()) 139 return PP_ERROR_FAILED; 140 141 base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL)); 142 if (!hdc.IsValid()) 143 return PP_ERROR_FAILED; 144 145 base::win::ScopedSelectObject select_object(hdc.Get(), font_.Get()); 146 147 // Get the whole font header. 148 static const DWORD kFontHeaderSize = 12; 149 uint8_t header_buf[kFontHeaderSize]; 150 if (GetFontData(hdc.Get(), 0, 0, header_buf, kFontHeaderSize) == GDI_ERROR) 151 return PP_ERROR_FAILED; 152 153 // The numTables follows a 4 byte scalerType tag. Font data is stored in 154 // big-endian order. 155 DWORD num_tables = (header_buf[4] << 8) | header_buf[5]; 156 157 // The size in bytes of an entry in the table directory. 158 static const DWORD kDirectoryEntrySize = 16; 159 DWORD directory_size = num_tables * kDirectoryEntrySize; 160 scoped_ptr<uint8_t[]> directory(new uint8_t[directory_size]); 161 // Get the table directory entries after the font header. 162 if (GetFontData(hdc.Get(), 0 /* tag */, kFontHeaderSize, directory.get(), 163 directory_size) == 164 GDI_ERROR) 165 return PP_ERROR_FAILED; 166 167 tags->resize(num_tables); 168 for (DWORD i = 0; i < num_tables; i++) { 169 const uint8_t* entry = directory.get() + i * kDirectoryEntrySize; 170 uint32_t tag = static_cast<uint32_t>(entry[0]) << 24 | 171 static_cast<uint32_t>(entry[1]) << 16 | 172 static_cast<uint32_t>(entry[2]) << 8 | 173 static_cast<uint32_t>(entry[3]); 174 (*tags)[i] = tag; 175 } 176 177 return num_tables; 178} 179 180int32_t PepperTrueTypeFontWin::GetTable(uint32_t table_tag, 181 int32_t offset, 182 int32_t max_data_length, 183 std::string* data) { 184 if (!font_.Get()) 185 return PP_ERROR_FAILED; 186 187 base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL)); 188 if (!hdc.IsValid()) 189 return PP_ERROR_FAILED; 190 191 base::win::ScopedSelectObject select_object(hdc.Get(), font_.Get()); 192 193 // Tags are byte swapped on Windows. 194 table_tag = base::ByteSwap(table_tag); 195 // Get the size of the font table first. 196 DWORD table_size = GetFontData(hdc.Get(), table_tag, 0, NULL, 0); 197 if (table_size == GDI_ERROR) 198 return PP_ERROR_FAILED; 199 200 DWORD safe_offset = std::min(static_cast<DWORD>(offset), table_size); 201 DWORD safe_length = 202 std::min(table_size - safe_offset, static_cast<DWORD>(max_data_length)); 203 data->resize(safe_length); 204 if (safe_length == 0) { 205 table_size = 0; 206 } else { 207 table_size = GetFontData(hdc.Get(), 208 table_tag, 209 safe_offset, 210 reinterpret_cast<uint8_t*>(&(*data)[0]), 211 safe_length); 212 if (table_size == GDI_ERROR) 213 return PP_ERROR_FAILED; 214 } 215 return static_cast<int32_t>(table_size); 216} 217 218DWORD PepperTrueTypeFontWin::GetFontData(HDC hdc, 219 DWORD table, 220 DWORD offset, 221 void* buffer, 222 DWORD length) { 223 // If this is a zero byte read, return a successful result. 224 if (buffer && !length) 225 return 0; 226 227 return ::GetFontData(hdc, table, offset, buffer, length); 228} 229 230} // namespace 231 232// static 233PepperTrueTypeFont* PepperTrueTypeFont::Create() { 234 return new PepperTrueTypeFontWin(); 235} 236 237} // namespace content 238