| 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 |
| 5 #include "webkit/glue/plugins/pepper_font.h" | 7 #include "webkit/glue/plugins/pepper_font.h" |
| 6 | 8 |
| 9 #if defined(OS_LINUX) |
| 10 #include <unistd.h> |
| 11 #endif |
| 12 |
| 7 #include "base/logging.h" | 13 #include "base/logging.h" |
| 8 #include "base/utf_string_conversions.h" | |
| 9 #include "third_party/ppapi/c/pp_rect.h" | |
| 10 #include "third_party/ppapi/c/ppb_font.h" | 14 #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" | 15 #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" | 16 #include "webkit/glue/webkit_glue.h" |
| 22 | 17 |
| 23 using WebKit::WebFloatPoint; | |
| 24 using WebKit::WebFloatRect; | |
| 25 using WebKit::WebFont; | |
| 26 using WebKit::WebFontDescription; | |
| 27 using WebKit::WebRect; | |
| 28 using WebKit::WebTextRun; | |
| 29 | |
| 30 namespace pepper { | 18 namespace pepper { |
| 31 | 19 |
| 32 namespace { | 20 namespace { |
| 33 | 21 |
| 34 bool IsPPFontDescriptionValid(const PP_FontDescription& desc) { | 22 PP_Resource MatchFontWithFallback(PP_Module module_id, |
| 35 // Check validity of UTF-8. | 23 const PP_FontDescription* description) { |
| 36 if (desc.face.type != PP_VARTYPE_STRING && desc.face.type != PP_VARTYPE_VOID) | 24 #if defined(OS_LINUX) |
| 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) { | |
| 105 PluginModule* module = PluginModule::FromPPModule(module_id); | 25 PluginModule* module = PluginModule::FromPPModule(module_id); |
| 106 if (!module) | 26 if (!module) |
| 107 return 0; | 27 return 0; |
| 108 | 28 |
| 109 if (!IsPPFontDescriptionValid(*description)) | 29 int fd = webkit_glue::MatchFontWithFallback(description->face, |
| 30 description->weight >= 700, |
| 31 description->italic, |
| 32 description->charset); |
| 33 if (fd == -1) |
| 110 return 0; | 34 return 0; |
| 111 | 35 |
| 112 scoped_refptr<Font> font(new Font(module, *description)); | 36 scoped_refptr<Font> font(new Font(module, fd)); |
| 37 |
| 113 return font->GetReference(); | 38 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 |
| 114 } | 44 } |
| 115 | 45 |
| 116 bool IsFont(PP_Resource resource) { | 46 bool IsFont(PP_Resource resource) { |
| 117 return !!Resource::GetAs<Font>(resource).get(); | 47 return !!Resource::GetAs<Font>(resource); |
| 118 } | 48 } |
| 119 | 49 |
| 120 bool Describe(PP_Resource font_id, | 50 bool GetFontTable(PP_Resource font_id, |
| 121 PP_FontDescription* description, | 51 uint32_t table, |
| 122 PP_FontMetrics* metrics) { | 52 void* output, |
| 53 uint32_t* output_length) { |
| 123 scoped_refptr<Font> font(Resource::GetAs<Font>(font_id)); | 54 scoped_refptr<Font> font(Resource::GetAs<Font>(font_id)); |
| 124 if (!font.get()) | 55 if (!font.get()) |
| 125 return false; | 56 return false; |
| 126 return font->Describe(description, metrics); | |
| 127 } | |
| 128 | 57 |
| 129 bool DrawTextAt(PP_Resource font_id, | 58 return font->GetFontTable(table, output, output_length); |
| 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); | |
| 166 } | 59 } |
| 167 | 60 |
| 168 const PPB_Font ppb_font = { | 61 const PPB_Font ppb_font = { |
| 169 &Create, | 62 &MatchFontWithFallback, |
| 170 &IsFont, | 63 &IsFont, |
| 171 &Describe, | 64 &GetFontTable, |
| 172 &DrawTextAt, | |
| 173 &MeasureText, | |
| 174 &CharacterOffsetForPixel, | |
| 175 &PixelOffsetForCharacter | |
| 176 }; | 65 }; |
| 177 | 66 |
| 178 } // namespace | 67 } // namespace |
| 179 | 68 |
| 180 Font::Font(PluginModule* module, const PP_FontDescription& desc) | 69 Font::Font(PluginModule* module, int fd) |
| 181 : Resource(module) { | 70 : Resource(module), |
| 182 WebFontDescription web_font_desc = PPFontDescToWebFontDesc(desc); | 71 fd_(fd) { |
| 183 font_.reset(WebFont::create(web_font_desc)); | |
| 184 } | 72 } |
| 185 | 73 |
| 186 Font::~Font() { | 74 Font::~Font() { |
| 75 #if defined (OS_LINUX) |
| 76 close(fd_); |
| 77 #endif |
| 187 } | 78 } |
| 188 | 79 |
| 189 // static | 80 // static |
| 190 const PPB_Font* Font::GetInterface() { | 81 const PPB_Font* Font::GetInterface() { |
| 191 return &ppb_font; | 82 return &ppb_font; |
| 192 } | 83 } |
| 193 | 84 |
| 194 bool Font::Describe(PP_FontDescription* description, | 85 bool Font::GetFontTable(uint32_t table, |
| 195 PP_FontMetrics* metrics) { | 86 void* output, |
| 196 if (description->face.type != PP_VARTYPE_VOID) | 87 uint32_t* output_length) { |
| 197 return false; | 88 #if defined(OS_LINUX) |
| 198 | 89 size_t temp_size = static_cast<size_t>(*output_length); |
| 199 WebFontDescription web_desc = font_->fontDescription(); | 90 bool rv = webkit_glue::GetFontTable( |
| 200 | 91 fd_, table, static_cast<uint8_t*>(output), &temp_size); |
| 201 // While converting the other way in PPFontDescToWebFontDesc we validated | 92 *output_length = static_cast<uint32_t>(temp_size); |
| 202 // that the enums can be casted. | 93 return rv; |
| 203 description->face = StringToPPVar(UTF16ToUTF8(web_desc.family)); | 94 #else |
| 204 description->family = static_cast<PP_FontFamily>(web_desc.genericFamily); | 95 return false; |
| 205 description->size = static_cast<uint32_t>(web_desc.size); | 96 #endif |
| 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 static_cast<int>(rect.width); | |
| 283 } | 97 } |
| 284 | 98 |
| 285 } // namespace pepper | 99 } // namespace pepper |
| OLD | NEW |