OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "build/build_config.h" | |
6 | |
7 #include "webkit/glue/plugins/pepper_font.h" | 5 #include "webkit/glue/plugins/pepper_font.h" |
8 | 6 |
9 #if defined(OS_LINUX) | 7 #include "base/logging.h" |
10 #include <unistd.h> | 8 #include "base/utf_string_conversions.h" |
11 #endif | 9 #include "third_party/ppapi/c/pp_rect.h" |
| 10 #include "third_party/ppapi/c/ppb_font.h" |
| 11 #include "third_party/WebKit/WebKit/chromium/public/WebFont.h" |
| 12 #include "third_party/WebKit/WebKit/chromium/public/WebFontDescription.h" |
| 13 #include "third_party/WebKit/WebKit/chromium/public/WebRect.h" |
| 14 #include "third_party/WebKit/WebKit/chromium/public/WebFloatPoint.h" |
| 15 #include "third_party/WebKit/WebKit/chromium/public/WebFloatRect.h" |
| 16 #include "third_party/WebKit/WebKit/chromium/public/WebTextRun.h" |
| 17 #include "webkit/glue/plugins/pepper_image_data.h" |
| 18 #include "webkit/glue/plugins/pepper_plugin_module.h" |
| 19 #include "webkit/glue/plugins/pepper_string.h" |
| 20 #include "webkit/glue/plugins/pepper_var.h" |
| 21 #include "webkit/glue/webkit_glue.h" |
12 | 22 |
13 #include "base/logging.h" | 23 using WebKit::WebFloatPoint; |
14 #include "third_party/ppapi/c/ppb_font.h" | 24 using WebKit::WebFloatRect; |
15 #include "webkit/glue/plugins/pepper_plugin_module.h" | 25 using WebKit::WebFont; |
16 #include "webkit/glue/webkit_glue.h" | 26 using WebKit::WebFontDescription; |
| 27 using WebKit::WebRect; |
| 28 using WebKit::WebTextRun; |
17 | 29 |
18 namespace pepper { | 30 namespace pepper { |
19 | 31 |
20 namespace { | 32 namespace { |
21 | 33 |
22 PP_Resource MatchFontWithFallback(PP_Module module_id, | 34 bool IsPPFontDescriptionValid(const PP_FontDescription& desc) { |
23 const PP_FontDescription* description) { | 35 // Check validity of UTF-8. |
24 #if defined(OS_LINUX) | 36 if (desc.face.type != PP_VARTYPE_STRING && desc.face.type != PP_VARTYPE_VOID) |
| 37 return false; |
| 38 |
| 39 if (static_cast<int>(desc.family) < PP_FONTFAMILY_DEFAULT || |
| 40 static_cast<int>(desc.family) > PP_FONTFAMILY_MONOSPACE) |
| 41 return false; |
| 42 if (static_cast<int>(desc.weight) < PP_FONTWEIGHT_100 || |
| 43 static_cast<int>(desc.weight) > PP_FONTWEIGHT_900) |
| 44 return false; |
| 45 |
| 46 return true; |
| 47 } |
| 48 |
| 49 // The PP_* version lacks "None", so is just one value shifted from the |
| 50 // WebFontDescription version. These values are checked in |
| 51 // PPFontDescToWebFontDesc to make sure the conversion is correct. This is a |
| 52 // macro so it can also be used in the COMPILE_ASSERTS. |
| 53 #define PP_FONTFAMILY_TO_WEB_FONTFAMILY(f) \ |
| 54 static_cast<WebFontDescription::GenericFamily>(f + 1) |
| 55 |
| 56 // Assumes the given PP_FontDescription has been validated. |
| 57 WebFontDescription PPFontDescToWebFontDesc(const PP_FontDescription& font) { |
| 58 // Verify that the enums match so we can just static cast. |
| 59 COMPILE_ASSERT(static_cast<int>(WebFontDescription::Weight100) == |
| 60 static_cast<int>(PP_FONTWEIGHT_100), |
| 61 FontWeight100); |
| 62 COMPILE_ASSERT(static_cast<int>(WebFontDescription::Weight900) == |
| 63 static_cast<int>(PP_FONTWEIGHT_900), |
| 64 FontWeight900); |
| 65 COMPILE_ASSERT(WebFontDescription::GenericFamilyStandard == |
| 66 PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_DEFAULT), |
| 67 StandardFamily); |
| 68 COMPILE_ASSERT(WebFontDescription::GenericFamilySerif == |
| 69 PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_SERIF), |
| 70 SerifFamily); |
| 71 COMPILE_ASSERT(WebFontDescription::GenericFamilySansSerif == |
| 72 PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_SANSSERIF), |
| 73 SansSerifFamily); |
| 74 COMPILE_ASSERT(WebFontDescription::GenericFamilyMonospace == |
| 75 PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_MONOSPACE), |
| 76 MonospaceFamily); |
| 77 |
| 78 WebFontDescription result; |
| 79 String* face_name = GetString(font.face); |
| 80 if (face_name) |
| 81 result.family = UTF8ToUTF16(face_name->value()); |
| 82 result.genericFamily = PP_FONTFAMILY_TO_WEB_FONTFAMILY(font.family); |
| 83 result.size = static_cast<float>(font.size); |
| 84 result.italic = font.italic; |
| 85 result.smallCaps = font.small_caps; |
| 86 result.weight = static_cast<WebFontDescription::Weight>(font.weight); |
| 87 result.letterSpacing = static_cast<short>(font.letter_spacing); |
| 88 result.wordSpacing = static_cast<short>(font.word_spacing); |
| 89 return result; |
| 90 } |
| 91 |
| 92 // Converts the given PP_TextRun to a WebTextRun, returning true on success. |
| 93 // False means the input was invalid. |
| 94 bool PPTextRunToWebTextRun(const PP_TextRun* run, WebTextRun* output) { |
| 95 String* text_string = GetString(run->text); |
| 96 if (!text_string) |
| 97 return false; |
| 98 *output = WebTextRun(UTF8ToUTF16(text_string->value()), |
| 99 run->rtl, run->override_direction); |
| 100 return true; |
| 101 } |
| 102 |
| 103 PP_Resource Create(PP_Module module_id, |
| 104 const PP_FontDescription* description) { |
25 PluginModule* module = PluginModule::FromPPModule(module_id); | 105 PluginModule* module = PluginModule::FromPPModule(module_id); |
26 if (!module) | 106 if (!module) |
27 return 0; | 107 return 0; |
28 | 108 |
29 int fd = webkit_glue::MatchFontWithFallback(description->face, | 109 if (!IsPPFontDescriptionValid(*description)) |
30 description->weight >= 700, | |
31 description->italic, | |
32 description->charset); | |
33 if (fd == -1) | |
34 return 0; | 110 return 0; |
35 | 111 |
36 scoped_refptr<Font> font(new Font(module, fd)); | 112 scoped_refptr<Font> font(new Font(module, *description)); |
37 | |
38 return font->GetReference(); | 113 return font->GetReference(); |
39 #else | |
40 // For trusted pepper plugins, this is only needed in Linux since font loading | |
41 // on Windows and Mac works through the renderer sandbox. | |
42 return false; | |
43 #endif | |
44 } | 114 } |
45 | 115 |
46 bool IsFont(PP_Resource resource) { | 116 bool IsFont(PP_Resource resource) { |
47 return !!Resource::GetAs<Font>(resource); | 117 return !!Resource::GetAs<Font>(resource).get(); |
48 } | 118 } |
49 | 119 |
50 bool GetFontTable(PP_Resource font_id, | 120 bool Describe(PP_Resource font_id, |
51 uint32_t table, | 121 PP_FontDescription* description, |
52 void* output, | 122 PP_FontMetrics* metrics) { |
53 uint32_t* output_length) { | |
54 scoped_refptr<Font> font(Resource::GetAs<Font>(font_id)); | 123 scoped_refptr<Font> font(Resource::GetAs<Font>(font_id)); |
55 if (!font.get()) | 124 if (!font.get()) |
56 return false; | 125 return false; |
| 126 return font->Describe(description, metrics); |
| 127 } |
57 | 128 |
58 return font->GetFontTable(table, output, output_length); | 129 bool DrawTextAt(PP_Resource font_id, |
| 130 PP_Resource image_data, |
| 131 const PP_TextRun* text, |
| 132 const PP_Point* position, |
| 133 uint32_t color, |
| 134 const PP_Rect* clip, |
| 135 bool image_data_is_opaque) { |
| 136 scoped_refptr<Font> font(Resource::GetAs<Font>(font_id)); |
| 137 if (!font.get()) |
| 138 return false; |
| 139 return font->DrawTextAt(image_data, text, position, color, clip, |
| 140 image_data_is_opaque); |
| 141 } |
| 142 |
| 143 int32_t MeasureText(PP_Resource font_id, const PP_TextRun* text) { |
| 144 scoped_refptr<Font> font(Resource::GetAs<Font>(font_id)); |
| 145 if (!font.get()) |
| 146 return -1; |
| 147 return font->MeasureText(text); |
| 148 } |
| 149 |
| 150 uint32_t CharacterOffsetForPixel(PP_Resource font_id, |
| 151 const PP_TextRun* text, |
| 152 int32_t pixel_position) { |
| 153 scoped_refptr<Font> font(Resource::GetAs<Font>(font_id)); |
| 154 if (!font.get()) |
| 155 return false; |
| 156 return font->CharacterOffsetForPixel(text, pixel_position); |
| 157 } |
| 158 |
| 159 int32_t PixelOffsetForCharacter(PP_Resource font_id, |
| 160 const PP_TextRun* text, |
| 161 uint32_t char_offset) { |
| 162 scoped_refptr<Font> font(Resource::GetAs<Font>(font_id)); |
| 163 if (!font.get()) |
| 164 return false; |
| 165 return font->PixelOffsetForCharacter(text, char_offset); |
59 } | 166 } |
60 | 167 |
61 const PPB_Font ppb_font = { | 168 const PPB_Font ppb_font = { |
62 &MatchFontWithFallback, | 169 &Create, |
63 &IsFont, | 170 &IsFont, |
64 &GetFontTable, | 171 &Describe, |
| 172 &DrawTextAt, |
| 173 &MeasureText, |
| 174 &CharacterOffsetForPixel, |
| 175 &PixelOffsetForCharacter |
65 }; | 176 }; |
66 | 177 |
67 } // namespace | 178 } // namespace |
68 | 179 |
69 Font::Font(PluginModule* module, int fd) | 180 Font::Font(PluginModule* module, const PP_FontDescription& desc) |
70 : Resource(module), | 181 : Resource(module) { |
71 fd_(fd) { | 182 WebFontDescription web_font_desc = PPFontDescToWebFontDesc(desc); |
| 183 font_.reset(WebFont::create(web_font_desc)); |
72 } | 184 } |
73 | 185 |
74 Font::~Font() { | 186 Font::~Font() { |
75 #if defined (OS_LINUX) | |
76 close(fd_); | |
77 #endif | |
78 } | 187 } |
79 | 188 |
80 // static | 189 // static |
81 const PPB_Font* Font::GetInterface() { | 190 const PPB_Font* Font::GetInterface() { |
82 return &ppb_font; | 191 return &ppb_font; |
83 } | 192 } |
84 | 193 |
85 bool Font::GetFontTable(uint32_t table, | 194 bool Font::Describe(PP_FontDescription* description, |
86 void* output, | 195 PP_FontMetrics* metrics) { |
87 uint32_t* output_length) { | 196 if (description->face.type != PP_VARTYPE_VOID) |
88 #if defined(OS_LINUX) | 197 return false; |
89 size_t temp_size = static_cast<size_t>(*output_length); | 198 |
90 bool rv = webkit_glue::GetFontTable( | 199 WebFontDescription web_desc = font_->fontDescription(); |
91 fd_, table, static_cast<uint8_t*>(output), &temp_size); | 200 |
92 *output_length = static_cast<uint32_t>(temp_size); | 201 // While converting the other way in PPFontDescToWebFontDesc we validated |
93 return rv; | 202 // that the enums can be casted. |
94 #else | 203 description->face = StringToPPVar(UTF16ToUTF8(web_desc.family)); |
95 return false; | 204 description->family = static_cast<PP_FontFamily>(web_desc.genericFamily); |
96 #endif | 205 description->size = static_cast<uint32_t>(web_desc.size); |
| 206 description->weight = static_cast<PP_FontWeight>(web_desc.weight); |
| 207 description->italic = web_desc.italic; |
| 208 description->small_caps = web_desc.smallCaps; |
| 209 |
| 210 metrics->height = font_->height(); |
| 211 metrics->ascent = font_->ascent(); |
| 212 metrics->descent = font_->descent(); |
| 213 metrics->line_spacing = font_->lineSpacing(); |
| 214 metrics->x_height = static_cast<int32_t>(font_->xHeight()); |
| 215 |
| 216 return true; |
| 217 } |
| 218 |
| 219 bool Font::DrawTextAt(PP_Resource image_data, |
| 220 const PP_TextRun* text, |
| 221 const PP_Point* position, |
| 222 uint32_t color, |
| 223 const PP_Rect* clip, |
| 224 bool image_data_is_opaque) { |
| 225 WebTextRun run; |
| 226 if (!PPTextRunToWebTextRun(text, &run)) |
| 227 return false; |
| 228 |
| 229 // Get and map the image data we're painting to. |
| 230 scoped_refptr<ImageData> image_resource( |
| 231 Resource::GetAs<ImageData>(image_data)); |
| 232 if (!image_resource.get()) |
| 233 return false; |
| 234 ImageDataAutoMapper mapper(image_resource); |
| 235 if (!mapper.is_valid()) |
| 236 return false; |
| 237 |
| 238 // Convert position and clip. |
| 239 WebFloatPoint web_position(static_cast<float>(position->x), |
| 240 static_cast<float>(position->y)); |
| 241 WebRect web_clip; |
| 242 if (!clip) { |
| 243 // Use entire canvas. |
| 244 web_clip = WebRect(0, 0, image_resource->width(), image_resource->height()); |
| 245 } else { |
| 246 web_clip = WebRect(clip->point.x, clip->point.y, |
| 247 clip->size.width, clip->size.height); |
| 248 } |
| 249 |
| 250 font_->drawText(webkit_glue::ToWebCanvas(image_resource->mapped_canvas()), |
| 251 run, web_position, color, web_clip, image_data_is_opaque); |
| 252 return true; |
| 253 } |
| 254 |
| 255 int32_t Font::MeasureText(const PP_TextRun* text) { |
| 256 WebTextRun run; |
| 257 if (!PPTextRunToWebTextRun(text, &run)) |
| 258 return -1; |
| 259 return font_->calculateWidth(run); |
| 260 } |
| 261 |
| 262 uint32_t Font::CharacterOffsetForPixel(const PP_TextRun* text, |
| 263 int32_t pixel_position) { |
| 264 WebTextRun run; |
| 265 if (!PPTextRunToWebTextRun(text, &run)) |
| 266 return -1; |
| 267 |
| 268 return static_cast<uint32_t>(font_->offsetForPosition( |
| 269 run, static_cast<float>(pixel_position))); |
| 270 } |
| 271 |
| 272 int32_t Font::PixelOffsetForCharacter(const PP_TextRun* text, |
| 273 uint32_t char_offset) { |
| 274 WebTextRun run; |
| 275 if (!PPTextRunToWebTextRun(text, &run)) |
| 276 return -1; |
| 277 if (char_offset >= run.text.length()) |
| 278 return -1; |
| 279 |
| 280 WebFloatRect rect = font_->selectionRectForText( |
| 281 run, WebFloatPoint(0.0f, 0.0f), font_->height(), 0, char_offset); |
| 282 return rect.width; |
97 } | 283 } |
98 | 284 |
99 } // namespace pepper | 285 } // namespace pepper |
OLD | NEW |