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.
5 #include "content/browser/renderer_host/pepper/pepper_truetype_font.h"
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"
24 class PepperTrueTypeFontWin : public PepperTrueTypeFont {
26 PepperTrueTypeFontWin();
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,
34 int32_t max_data_length,
35 std::string* data) OVERRIDE;
38 virtual ~PepperTrueTypeFontWin();
40 DWORD GetFontData(HDC hdc,
46 base::win::ScopedHFONT font_;
48 DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontWin);
51 PepperTrueTypeFontWin::PepperTrueTypeFontWin() {
54 PepperTrueTypeFontWin::~PepperTrueTypeFontWin() {
57 int32_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;
64 case PP_TRUETYPEFONTFAMILY_SANSSERIF:
65 pitch_and_family |= FF_SWISS;
67 case PP_TRUETYPEFONTFAMILY_CURSIVE:
68 pitch_and_family |= FF_SCRIPT;
70 case PP_TRUETYPEFONTFAMILY_FANTASY:
71 pitch_and_family |= FF_DECORATIVE;
73 case PP_TRUETYPEFONTFAMILY_MONOSPACE:
74 pitch_and_family |= FF_MODERN;
77 // TODO(bbudge) support widths (extended, condensed).
79 font_.Set(CreateFont(0 /* height */,
83 desc->weight, // our weight enum matches Windows.
84 (desc->style & PP_TRUETYPEFONTSTYLE_ITALIC) ? 1 : 0,
87 desc->charset, // our charset enum matches Windows.
88 OUT_OUTLINE_PRECIS, // truetype and other outline fonts
92 base::UTF8ToUTF16(desc->family).c_str()));
94 return PP_ERROR_FAILED;
97 if (!::GetObject(font_.Get(), sizeof(LOGFONT), &font_desc))
98 return PP_ERROR_FAILED;
100 switch (font_desc.lfPitchAndFamily & 0xF0) { // Top 4 bits are family.
102 desc->generic_family = PP_TRUETYPEFONTFAMILY_SERIF;
105 desc->generic_family = PP_TRUETYPEFONTFAMILY_SANSSERIF;
108 desc->generic_family = PP_TRUETYPEFONTFAMILY_CURSIVE;
111 desc->generic_family = PP_TRUETYPEFONTFAMILY_FANTASY;
114 desc->generic_family = PP_TRUETYPEFONTFAMILY_MONOSPACE;
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);
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));
128 base::win::ScopedSelectObject select_object(hdc, font_.Get());
129 WCHAR name[LF_FACESIZE];
130 GetTextFace(hdc, LF_FACESIZE, name);
131 desc->family = base::UTF16ToUTF8(name);
137 int32_t PepperTrueTypeFontWin::GetTableTags(std::vector<uint32_t>* tags) {
139 return PP_ERROR_FAILED;
141 base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
143 return PP_ERROR_FAILED;
145 base::win::ScopedSelectObject select_object(hdc, font_.Get());
147 // Get the whole font header.
148 static const DWORD kFontHeaderSize = 12;
149 uint8_t header_buf[kFontHeaderSize];
150 if (GetFontData(hdc, 0, 0, header_buf, kFontHeaderSize) == GDI_ERROR)
151 return PP_ERROR_FAILED;
153 // The numTables follows a 4 byte scalerType tag. Font data is stored in
155 DWORD num_tables = (header_buf[4] << 8) | header_buf[5];
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.
163 hdc, 0 /* tag */, kFontHeaderSize, directory.get(), directory_size) ==
165 return PP_ERROR_FAILED;
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]);
180 int32_t PepperTrueTypeFontWin::GetTable(uint32_t table_tag,
182 int32_t max_data_length,
185 return PP_ERROR_FAILED;
187 base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
189 return PP_ERROR_FAILED;
191 base::win::ScopedSelectObject select_object(hdc, font_.Get());
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, table_tag, 0, NULL, 0);
197 if (table_size == GDI_ERROR)
198 return PP_ERROR_FAILED;
200 DWORD safe_offset = std::min(static_cast<DWORD>(offset), table_size);
202 std::min(table_size - safe_offset, static_cast<DWORD>(max_data_length));
203 data->resize(safe_length);
204 if (safe_length == 0) {
207 table_size = GetFontData(hdc,
210 reinterpret_cast<uint8_t*>(&(*data)[0]),
212 if (table_size == GDI_ERROR)
213 return PP_ERROR_FAILED;
215 return static_cast<int32_t>(table_size);
218 DWORD PepperTrueTypeFontWin::GetFontData(HDC hdc,
223 // If this is a zero byte read, return a successful result.
224 if (buffer && !length)
227 return ::GetFontData(hdc, table, offset, buffer, length);
233 PepperTrueTypeFont* PepperTrueTypeFont::Create() {
234 return new PepperTrueTypeFontWin();
237 } // namespace content