1 // Copyright (c) 2013 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/renderer/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_hdc.h"
15 #include "base/win/scoped_select_object.h"
16 #include "content/public/renderer/render_thread.h"
17 #include "ppapi/c/dev/ppb_truetype_font_dev.h"
18 #include "ppapi/c/pp_errors.h"
24 class PepperTrueTypeFontWin : public PepperTrueTypeFont {
26 explicit PepperTrueTypeFontWin(
27 const ppapi::proxy::SerializedTrueTypeFontDesc& desc);
28 virtual ~PepperTrueTypeFontWin();
30 // PepperTrueTypeFont overrides.
31 virtual bool IsValid() OVERRIDE;
32 virtual int32_t Describe(
33 ppapi::proxy::SerializedTrueTypeFontDesc* desc) OVERRIDE;
34 virtual int32_t GetTableTags(std::vector<uint32_t>* tags) OVERRIDE;
35 virtual int32_t GetTable(uint32_t table_tag,
37 int32_t max_data_length,
38 std::string* data) OVERRIDE;
40 DWORD GetFontData(HDC hdc,
48 DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontWin);
51 PepperTrueTypeFontWin::PepperTrueTypeFontWin(
52 const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
53 DWORD pitch_and_family = DEFAULT_PITCH;
54 switch (desc.generic_family) {
55 case PP_TRUETYPEFONTFAMILY_SERIF:
56 pitch_and_family |= FF_ROMAN;
58 case PP_TRUETYPEFONTFAMILY_SANSSERIF:
59 pitch_and_family |= FF_SWISS;
61 case PP_TRUETYPEFONTFAMILY_CURSIVE:
62 pitch_and_family |= FF_SCRIPT;
64 case PP_TRUETYPEFONTFAMILY_FANTASY:
65 pitch_and_family |= FF_DECORATIVE;
67 case PP_TRUETYPEFONTFAMILY_MONOSPACE:
68 pitch_and_family |= FF_MODERN;
71 // TODO(bbudge) support widths (extended, condensed).
73 font_ = CreateFont(0 /* height */,
77 desc.weight, // our weight enum matches Windows.
78 (desc.style & PP_TRUETYPEFONTSTYLE_ITALIC) ? 1 : 0,
81 desc.charset, // our charset enum matches Windows.
82 OUT_OUTLINE_PRECIS, // truetype and other outline fonts
86 UTF8ToUTF16(desc.family).c_str());
89 PepperTrueTypeFontWin::~PepperTrueTypeFontWin() {
92 bool PepperTrueTypeFontWin::IsValid() {
96 int32_t PepperTrueTypeFontWin::Describe(
97 ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
99 if (!::GetObject(font_, sizeof(LOGFONT), &font_desc))
100 return PP_ERROR_FAILED;
102 switch (font_desc.lfPitchAndFamily & 0xF0) { // Top 4 bits are family.
104 desc->generic_family = PP_TRUETYPEFONTFAMILY_SERIF;
107 desc->generic_family = PP_TRUETYPEFONTFAMILY_SANSSERIF;
110 desc->generic_family = PP_TRUETYPEFONTFAMILY_CURSIVE;
113 desc->generic_family = PP_TRUETYPEFONTFAMILY_FANTASY;
116 desc->generic_family = PP_TRUETYPEFONTFAMILY_MONOSPACE;
120 desc->style = font_desc.lfItalic ? PP_TRUETYPEFONTSTYLE_ITALIC :
121 PP_TRUETYPEFONTSTYLE_NORMAL;
122 desc->weight = static_cast<PP_TrueTypeFontWeight_Dev>(font_desc.lfWeight);
123 desc->width = PP_TRUETYPEFONTWIDTH_NORMAL;
125 static_cast<PP_TrueTypeFontCharset_Dev>(font_desc.lfCharSet);
127 // To get the face name, select the font and query for the name. GetObject
128 // doesn't fill in the name field of the LOGFONT structure.
129 base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
131 base::win::ScopedSelectObject select_object(hdc, font_);
132 WCHAR name[LF_FACESIZE];
133 GetTextFace(hdc, LF_FACESIZE, name);
134 desc->family = UTF16ToUTF8(name);
139 DWORD PepperTrueTypeFontWin::GetFontData(HDC hdc,
144 // If this is a zero byte read, return a successful result.
145 if (buffer && !length)
148 DWORD result = ::GetFontData(hdc, table, offset, buffer, length);
149 if (result == GDI_ERROR) {
150 // The font may not be cached by the OS, causing an attempt to read it in
151 // the renderer process to fail. Attempt to pre-cache it.
153 if (!::GetObject(font_, sizeof(LOGFONTW), &logfont))
155 RenderThread* render_thread = RenderThread::Get();
158 render_thread->PreCacheFont(logfont);
160 result = ::GetFontData(hdc, table, offset, buffer, length);
165 int32_t PepperTrueTypeFontWin::GetTableTags(std::vector<uint32_t>* tags) {
166 base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
168 return PP_ERROR_FAILED;
170 base::win::ScopedSelectObject select_object(hdc, font_);
172 // Get the whole font header.
173 static const DWORD kFontHeaderSize = 12;
174 uint8_t header_buf[kFontHeaderSize];
175 if (GetFontData(hdc, 0, 0, header_buf, kFontHeaderSize) == GDI_ERROR)
176 return PP_ERROR_FAILED;
178 // The numTables follows a 4 byte scalerType tag. Font data is stored in
180 DWORD num_tables = (header_buf[4] << 8) | header_buf[5];
182 // The size in bytes of an entry in the table directory.
183 static const DWORD kDirectoryEntrySize = 16;
184 DWORD directory_size = num_tables * kDirectoryEntrySize;
185 scoped_ptr<uint8_t[]> directory(new uint8_t[directory_size]);
186 // Get the table directory entries after the font header.
187 if (GetFontData(hdc, 0 /* tag */, kFontHeaderSize,
189 directory_size) == GDI_ERROR)
190 return PP_ERROR_FAILED;
192 tags->resize(num_tables);
193 for (DWORD i = 0; i < num_tables; i++) {
194 const uint8_t* entry = directory.get() + i * kDirectoryEntrySize;
195 uint32_t tag = static_cast<uint32_t>(entry[0]) << 24 |
196 static_cast<uint32_t>(entry[1]) << 16 |
197 static_cast<uint32_t>(entry[2]) << 8 |
198 static_cast<uint32_t>(entry[3]);
205 int32_t PepperTrueTypeFontWin::GetTable(uint32_t table_tag,
207 int32_t max_data_length,
209 base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
211 return PP_ERROR_FAILED;
213 base::win::ScopedSelectObject select_object(hdc, font_);
215 // Tags are byte swapped on Windows.
216 table_tag = base::ByteSwap(table_tag);
217 // Get the size of the font table first.
218 DWORD table_size = GetFontData(hdc, table_tag, 0, NULL, 0);
219 if (table_size == GDI_ERROR)
220 return PP_ERROR_FAILED;
222 DWORD safe_offset = std::min(static_cast<DWORD>(offset), table_size);
223 DWORD safe_length = std::min(table_size - safe_offset,
224 static_cast<DWORD>(max_data_length));
225 data->resize(safe_length);
226 if (safe_length == 0) {
229 table_size = GetFontData(hdc, table_tag, safe_offset,
230 reinterpret_cast<uint8_t*>(&(*data)[0]),
232 if (table_size == GDI_ERROR)
233 return PP_ERROR_FAILED;
235 return static_cast<int32_t>(table_size);
241 PepperTrueTypeFont* PepperTrueTypeFont::Create(
242 const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
243 return new PepperTrueTypeFontWin(desc);
246 } // namespace content