Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / pepper / pepper_truetype_font_win.cc
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
20 namespace content {
21
22 namespace {
23
24 class 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
51 PepperTrueTypeFontWin::PepperTrueTypeFontWin() {
52 }
53
54 PepperTrueTypeFontWin::~PepperTrueTypeFontWin() {
55 }
56
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;
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) {
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);
132   }
133
134   return PP_OK;
135 }
136
137 int32_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)
143     return PP_ERROR_FAILED;
144
145   base::win::ScopedSelectObject select_object(hdc, 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, 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(
163           hdc, 0 /* tag */, kFontHeaderSize, directory.get(), 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
180 int32_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)
189     return PP_ERROR_FAILED;
190
191   base::win::ScopedSelectObject select_object(hdc, 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, 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,
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
218 DWORD 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
233 PepperTrueTypeFont* PepperTrueTypeFont::Create() {
234   return new PepperTrueTypeFontWin();
235 }
236
237 }  // namespace content