- add sources.
[platform/framework/web/crosswalk.git] / src / content / renderer / pepper / pepper_truetype_font_win.cc
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.
4
5 #include "content/renderer/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_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"
19
20 namespace content {
21
22 namespace {
23
24 class PepperTrueTypeFontWin : public PepperTrueTypeFont {
25  public:
26   explicit PepperTrueTypeFontWin(
27       const ppapi::proxy::SerializedTrueTypeFontDesc& desc);
28   virtual ~PepperTrueTypeFontWin();
29
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,
36                            int32_t offset,
37                            int32_t max_data_length,
38                            std::string* data) OVERRIDE;
39  private:
40   DWORD GetFontData(HDC hdc,
41                     DWORD table,
42                     DWORD offset,
43                     LPVOID buffer,
44                     DWORD length);
45
46   HFONT font_;
47
48   DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontWin);
49 };
50
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;
57       break;
58     case PP_TRUETYPEFONTFAMILY_SANSSERIF:
59       pitch_and_family |= FF_SWISS;
60       break;
61     case PP_TRUETYPEFONTFAMILY_CURSIVE:
62       pitch_and_family |= FF_SCRIPT;
63       break;
64     case PP_TRUETYPEFONTFAMILY_FANTASY:
65       pitch_and_family |= FF_DECORATIVE;
66       break;
67     case PP_TRUETYPEFONTFAMILY_MONOSPACE:
68       pitch_and_family |= FF_MODERN;
69       break;
70   }
71   // TODO(bbudge) support widths (extended, condensed).
72
73   font_ = CreateFont(0  /* height */,
74                      0  /* width */,
75                      0  /* escapement */,
76                      0  /* orientation */,
77                      desc.weight,  // our weight enum matches Windows.
78                      (desc.style & PP_TRUETYPEFONTSTYLE_ITALIC) ? 1 : 0,
79                      0  /* underline */,
80                      0  /* strikeout */,
81                      desc.charset,  // our charset enum matches Windows.
82                      OUT_OUTLINE_PRECIS,  // truetype and other outline fonts
83                      CLIP_DEFAULT_PRECIS,
84                      DEFAULT_QUALITY,
85                      pitch_and_family,
86                      UTF8ToUTF16(desc.family).c_str());
87 }
88
89 PepperTrueTypeFontWin::~PepperTrueTypeFontWin() {
90 }
91
92 bool PepperTrueTypeFontWin::IsValid() {
93   return font_ != NULL;
94 }
95
96 int32_t PepperTrueTypeFontWin::Describe(
97       ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
98   LOGFONT font_desc;
99   if (!::GetObject(font_, sizeof(LOGFONT), &font_desc))
100     return PP_ERROR_FAILED;
101
102   switch (font_desc.lfPitchAndFamily & 0xF0) {  // Top 4 bits are family.
103     case FF_ROMAN:
104       desc->generic_family = PP_TRUETYPEFONTFAMILY_SERIF;
105       break;
106     case FF_SWISS:
107       desc->generic_family = PP_TRUETYPEFONTFAMILY_SANSSERIF;
108       break;
109     case FF_SCRIPT:
110       desc->generic_family = PP_TRUETYPEFONTFAMILY_CURSIVE;
111       break;
112     case FF_DECORATIVE:
113       desc->generic_family = PP_TRUETYPEFONTFAMILY_FANTASY;
114       break;
115     case FF_MODERN:
116       desc->generic_family = PP_TRUETYPEFONTFAMILY_MONOSPACE;
117       break;
118   }
119
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;
124   desc->charset =
125       static_cast<PP_TrueTypeFontCharset_Dev>(font_desc.lfCharSet);
126
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));
130   if (hdc) {
131     base::win::ScopedSelectObject select_object(hdc, font_);
132     WCHAR name[LF_FACESIZE];
133     GetTextFace(hdc, LF_FACESIZE, name);
134     desc->family = UTF16ToUTF8(name);
135   }
136   return PP_OK;
137 }
138
139 DWORD PepperTrueTypeFontWin::GetFontData(HDC hdc,
140                                          DWORD table,
141                                          DWORD offset,
142                                          void* buffer,
143                                          DWORD length) {
144   // If this is a zero byte read, return a successful result.
145   if (buffer && !length)
146     return 0;
147
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.
152     LOGFONTW logfont;
153     if (!::GetObject(font_, sizeof(LOGFONTW), &logfont))
154       return GDI_ERROR;
155     RenderThread* render_thread = RenderThread::Get();
156     if (!render_thread)
157       return GDI_ERROR;
158     render_thread->PreCacheFont(logfont);
159
160     result = ::GetFontData(hdc, table, offset, buffer, length);
161   }
162   return result;
163 }
164
165 int32_t PepperTrueTypeFontWin::GetTableTags(std::vector<uint32_t>* tags) {
166   base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
167   if (!hdc)
168     return PP_ERROR_FAILED;
169
170   base::win::ScopedSelectObject select_object(hdc, font_);
171
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;
177
178   // The numTables follows a 4 byte scalerType tag. Font data is stored in
179   // big-endian order.
180   DWORD num_tables = (header_buf[4] << 8) | header_buf[5];
181
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,
188                   directory.get(),
189                   directory_size) == GDI_ERROR)
190     return PP_ERROR_FAILED;
191
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]);
199     (*tags)[i] = tag;
200   }
201
202   return num_tables;
203 }
204
205 int32_t PepperTrueTypeFontWin::GetTable(uint32_t table_tag,
206                                         int32_t offset,
207                                         int32_t max_data_length,
208                                         std::string* data) {
209   base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
210   if (!hdc)
211     return PP_ERROR_FAILED;
212
213   base::win::ScopedSelectObject select_object(hdc, font_);
214
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;
221
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) {
227     table_size = 0;
228   } else {
229     table_size = GetFontData(hdc, table_tag, safe_offset,
230                              reinterpret_cast<uint8_t*>(&(*data)[0]),
231                              safe_length);
232     if (table_size == GDI_ERROR)
233       return PP_ERROR_FAILED;
234   }
235   return static_cast<int32_t>(table_size);
236 }
237
238 }  // namespace
239
240 // static
241 PepperTrueTypeFont* PepperTrueTypeFont::Create(
242     const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
243   return new PepperTrueTypeFontWin(desc);
244 }
245
246 }  // namespace content