Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012 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 "ppapi/shared_impl/private/ppb_browser_font_trusted_shared.h" | |
| 6 | |
| 7 #include "base/debug/trace_event.h" | |
| 8 #include "base/string_util.h" | |
| 9 #include "base/utf_string_conversions.h" | |
| 10 #include "ppapi/c/dev/ppb_font_dev.h" | |
| 11 #include "ppapi/shared_impl/ppapi_preferences.h" | |
| 12 #include "ppapi/shared_impl/var.h" | |
| 13 #include "ppapi/thunk/enter.h" | |
| 14 #include "ppapi/thunk/ppb_image_data_api.h" | |
| 15 #include "ppapi/thunk/thunk.h" | |
| 16 #include "skia/ext/platform_canvas.h" | |
| 17 #include "third_party/skia/include/core/SkRect.h" | |
| 18 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCanvas.h" | |
| 19 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFloatPoin t.h" | |
| 20 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebFloatRect .h" | |
| 21 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h" | |
| 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFont.h" | |
| 23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFontDescription.h" | |
| 24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebTextRun.h" | |
| 25 | |
| 26 using ppapi::StringVar; | |
| 27 using ppapi::thunk::EnterResource; | |
| 28 using ppapi::thunk::EnterResourceNoLock; | |
| 29 using ppapi::thunk::PPB_ImageData_API; | |
| 30 using WebKit::WebFloatPoint; | |
| 31 using WebKit::WebFloatRect; | |
| 32 using WebKit::WebFont; | |
| 33 using WebKit::WebFontDescription; | |
| 34 using WebKit::WebRect; | |
| 35 using WebKit::WebTextRun; | |
| 36 using WebKit::WebCanvas; | |
| 37 | |
| 38 namespace ppapi { | |
| 39 | |
| 40 namespace { | |
| 41 | |
| 42 bool PPTextRunToWebTextRun(const PP_BrowserFont_Trusted_TextRun& text, | |
| 43 WebTextRun* run) { | |
| 44 StringVar* text_string = StringVar::FromPPVar(text.text); | |
| 45 if (!text_string) | |
| 46 return false; | |
| 47 | |
| 48 *run = WebTextRun(UTF8ToUTF16(text_string->value()), | |
| 49 PP_ToBool(text.rtl), | |
| 50 PP_ToBool(text.override_direction)); | |
| 51 return true; | |
| 52 } | |
| 53 | |
| 54 // The PP_* version lacks "None", so is just one value shifted from the | |
| 55 // WebFontDescription version. These values are checked in | |
| 56 // PPFontDescToWebFontDesc to make sure the conversion is correct. This is a | |
| 57 // macro so it can also be used in the COMPILE_ASSERTS. | |
| 58 #define PP_FAMILY_TO_WEB_FAMILY(f) \ | |
| 59 static_cast<WebFontDescription::GenericFamily>(f + 1) | |
| 60 | |
| 61 // Assumes the given PP_FontDescription has been validated. | |
| 62 WebFontDescription PPFontDescToWebFontDesc( | |
| 63 const PP_BrowserFont_Trusted_Description& font, | |
| 64 const Preferences& prefs) { | |
| 65 // Verify that the enums match so we can just static cast. | |
| 66 COMPILE_ASSERT(static_cast<int>(WebFontDescription::Weight100) == | |
| 67 static_cast<int>(PP_BROWSERFONT_TRUSTED_WEIGHT_100), | |
| 68 FontWeight100); | |
| 69 COMPILE_ASSERT(static_cast<int>(WebFontDescription::Weight900) == | |
| 70 static_cast<int>(PP_BROWSERFONT_TRUSTED_WEIGHT_900), | |
| 71 FontWeight900); | |
| 72 COMPILE_ASSERT(WebFontDescription::GenericFamilyStandard == | |
| 73 PP_FAMILY_TO_WEB_FAMILY(PP_FONTFAMILY_DEFAULT), | |
| 74 StandardFamily); | |
| 75 COMPILE_ASSERT(WebFontDescription::GenericFamilySerif == | |
| 76 PP_FAMILY_TO_WEB_FAMILY(PP_FONTFAMILY_SERIF), | |
| 77 SerifFamily); | |
| 78 COMPILE_ASSERT(WebFontDescription::GenericFamilySansSerif == | |
| 79 PP_FAMILY_TO_WEB_FAMILY(PP_FONTFAMILY_SANSSERIF), | |
| 80 SansSerifFamily); | |
| 81 COMPILE_ASSERT(WebFontDescription::GenericFamilyMonospace == | |
| 82 PP_FAMILY_TO_WEB_FAMILY(PP_FONTFAMILY_MONOSPACE), | |
| 83 MonospaceFamily); | |
| 84 | |
| 85 StringVar* face_name = StringVar::FromPPVar(font.face); // Possibly null. | |
| 86 | |
| 87 WebFontDescription result; | |
| 88 string16 resolved_family; | |
| 89 if (!face_name || face_name->value().empty()) { | |
| 90 // Resolve the generic family. | |
| 91 switch (font.family) { | |
| 92 case PP_BROWSERFONT_TRUSTED_FAMILY_SERIF: | |
| 93 resolved_family = prefs.serif_font_family; | |
| 94 break; | |
| 95 case PP_BROWSERFONT_TRUSTED_FAMILY_SANSSERIF: | |
| 96 resolved_family = prefs.sans_serif_font_family; | |
| 97 break; | |
| 98 case PP_BROWSERFONT_TRUSTED_FAMILY_MONOSPACE: | |
| 99 resolved_family = prefs.fixed_font_family; | |
| 100 break; | |
| 101 case PP_BROWSERFONT_TRUSTED_FAMILY_DEFAULT: | |
| 102 default: | |
| 103 resolved_family = prefs.standard_font_family; | |
| 104 break; | |
| 105 } | |
| 106 } else { | |
| 107 // Use the exact font. | |
| 108 resolved_family = UTF8ToUTF16(face_name->value()); | |
| 109 } | |
| 110 result.family = resolved_family; | |
| 111 | |
| 112 result.genericFamily = PP_FAMILY_TO_WEB_FAMILY(font.family); | |
| 113 | |
| 114 if (font.size == 0) { | |
| 115 // Resolve the default font size, using the resolved family to see if | |
| 116 // we should use the fixed or regular font size. It's difficult at this | |
| 117 // level to detect if the requested font is fixed width, so we only apply | |
| 118 // the alternate font size to the default fixed font family. | |
| 119 if (StringToLowerASCII(resolved_family) == | |
| 120 StringToLowerASCII(prefs.fixed_font_family)) | |
| 121 result.size = static_cast<float>(prefs.default_fixed_font_size); | |
| 122 else | |
| 123 result.size = static_cast<float>(prefs.default_font_size); | |
| 124 } else { | |
| 125 // Use the exact size. | |
| 126 result.size = static_cast<float>(font.size); | |
| 127 } | |
| 128 | |
| 129 result.italic = font.italic != PP_FALSE; | |
| 130 result.smallCaps = font.small_caps != PP_FALSE; | |
| 131 result.weight = static_cast<WebFontDescription::Weight>(font.weight); | |
| 132 result.letterSpacing = static_cast<short>(font.letter_spacing); | |
| 133 result.wordSpacing = static_cast<short>(font.word_spacing); | |
| 134 return result; | |
| 135 } | |
| 136 | |
| 137 } // namespace | |
| 138 | |
| 139 // static | |
| 140 bool PPB_BrowserFont_Trusted_Shared::IsPPFontDescriptionValid( | |
| 141 const PP_BrowserFont_Trusted_Description& desc) { | |
| 142 // Check validity of string. We can't check the actual text since we could | |
| 143 // be on the wrong thread and don't know if we're in the plugin or the host. | |
| 144 if (desc.face.type != PP_VARTYPE_STRING && | |
| 145 desc.face.type != PP_VARTYPE_UNDEFINED) | |
| 146 return false; | |
| 147 | |
| 148 // Check enum ranges. | |
| 149 if (static_cast<int>(desc.family) < PP_BROWSERFONT_TRUSTED_FAMILY_DEFAULT || | |
| 150 static_cast<int>(desc.family) > PP_BROWSERFONT_TRUSTED_FAMILY_MONOSPACE) | |
| 151 return false; | |
| 152 if (static_cast<int>(desc.weight) < PP_BROWSERFONT_TRUSTED_WEIGHT_100 || | |
| 153 static_cast<int>(desc.weight) > PP_BROWSERFONT_TRUSTED_WEIGHT_900) | |
| 154 return false; | |
| 155 | |
| 156 // Check for excessive sizes which may cause layout to get confused. | |
| 157 if (desc.size > 200) | |
| 158 return false; | |
| 159 | |
| 160 return true; | |
| 161 } | |
| 162 | |
| 163 // static | |
| 164 PP_Resource PPB_BrowserFont_Trusted_Shared::Create( | |
| 165 ResourceObjectType type, | |
| 166 PP_Instance instance, | |
| 167 const PP_BrowserFont_Trusted_Description& description, | |
| 168 const Preferences& prefs) { | |
| 169 if (!PPB_BrowserFont_Trusted_Shared::IsPPFontDescriptionValid(description)) | |
| 170 return 0; | |
| 171 return (new PPB_BrowserFont_Trusted_Shared(type, instance, | |
| 172 description, | |
| 173 prefs))->GetReference(); | |
| 174 } | |
| 175 | |
| 176 PPB_BrowserFont_Trusted_Shared::PPB_BrowserFont_Trusted_Shared( | |
| 177 ResourceObjectType type, | |
| 178 PP_Instance instance, | |
| 179 const PP_BrowserFont_Trusted_Description& desc, | |
| 180 const Preferences& prefs) | |
| 181 : Resource(type, instance), | |
| 182 font_(WebFont::create(PPFontDescToWebFontDesc(desc, prefs))) { | |
| 183 } | |
| 184 | |
| 185 PPB_BrowserFont_Trusted_Shared::~PPB_BrowserFont_Trusted_Shared() { | |
| 186 } | |
| 187 | |
| 188 thunk::PPB_BrowserFont_Trusted_API* | |
| 189 PPB_BrowserFont_Trusted_Shared::AsPPB_BrowserFont_Trusted_API() { | |
| 190 return this; | |
| 191 } | |
| 192 | |
| 193 PP_Bool PPB_BrowserFont_Trusted_Shared::Describe( | |
| 194 PP_BrowserFont_Trusted_Description* description, | |
| 195 PP_BrowserFont_Trusted_Metrics* metrics) { | |
| 196 TRACE_EVENT0("ppapi WebKit thread", "FontImpl::Describe"); | |
| 197 if (description->face.type != PP_VARTYPE_UNDEFINED) | |
| 198 return PP_FALSE; | |
| 199 | |
| 200 // While converting the other way in PPFontDescToWebFontDesc we validated | |
| 201 // that the enums can be casted. | |
| 202 WebFontDescription web_desc = font_->fontDescription(); | |
| 203 description->face = StringVar::StringToPPVar(UTF16ToUTF8(web_desc.family)); | |
| 204 description->family = | |
| 205 static_cast<PP_BrowserFont_Trusted_Family>(web_desc.genericFamily); | |
| 206 description->size = static_cast<uint32_t>(web_desc.size); | |
| 207 description->weight = static_cast<PP_BrowserFont_Trusted_Weight>( | |
| 208 web_desc.weight); | |
| 209 description->italic = web_desc.italic ? PP_TRUE : PP_FALSE; | |
| 210 description->small_caps = web_desc.smallCaps ? PP_TRUE : PP_FALSE; | |
| 211 description->letter_spacing = static_cast<int32_t>(web_desc.letterSpacing); | |
| 212 description->word_spacing = static_cast<int32_t>(web_desc.wordSpacing); | |
| 213 | |
| 214 metrics->height = font_->height(); | |
| 215 metrics->ascent = font_->ascent(); | |
| 216 metrics->descent = font_->descent(); | |
| 217 metrics->line_spacing = font_->lineSpacing(); | |
| 218 metrics->x_height = static_cast<int32_t>(font_->xHeight()); | |
| 219 | |
| 220 // Convert the string. | |
| 221 return PP_TRUE; | |
| 222 } | |
| 223 | |
| 224 PP_Bool PPB_BrowserFont_Trusted_Shared::DrawTextAt( | |
| 225 PP_Resource image_data, | |
| 226 const PP_BrowserFont_Trusted_TextRun* text, | |
| 227 const PP_Point* position, | |
| 228 uint32_t color, | |
| 229 const PP_Rect* clip, | |
| 230 PP_Bool image_data_is_opaque) { | |
| 231 PP_Bool result = PP_FALSE; | |
| 232 // Get and map the image data we're painting to. | |
| 233 EnterResource<PPB_ImageData_API> enter(image_data, true); | |
| 234 if (enter.failed()) | |
| 235 return result; | |
| 236 | |
| 237 PPB_ImageData_API* image = static_cast<PPB_ImageData_API*>( | |
| 238 enter.object()); | |
| 239 skia::PlatformCanvas* canvas = image->GetPlatformCanvas(); | |
| 240 bool needs_unmapping = false; | |
| 241 if (!canvas) { | |
| 242 needs_unmapping = true; | |
| 243 image->Map(); | |
| 244 canvas = image->GetPlatformCanvas(); | |
| 245 if (!canvas) | |
| 246 return result; // Failure mapping. | |
| 247 } | |
| 248 | |
| 249 DrawTextToCanvas(canvas, *text, position, color, clip, image_data_is_opaque); | |
| 250 | |
| 251 if (needs_unmapping) | |
| 252 image->Unmap(); | |
| 253 return PP_TRUE; | |
| 254 } | |
| 255 | |
| 256 int32_t PPB_BrowserFont_Trusted_Shared::MeasureText( | |
| 257 const PP_BrowserFont_Trusted_TextRun* text) { | |
| 258 WebTextRun run; | |
| 259 if (!PPTextRunToWebTextRun(*text, &run)) | |
| 260 return -1; | |
| 261 return font_->calculateWidth(run); | |
| 262 } | |
| 263 | |
| 264 uint32_t PPB_BrowserFont_Trusted_Shared::CharacterOffsetForPixel( | |
| 265 const PP_BrowserFont_Trusted_TextRun* text, | |
| 266 int32_t pixel_position) { | |
| 267 WebTextRun run; | |
| 268 if (!PPTextRunToWebTextRun(*text, &run)) | |
| 269 return -1; | |
| 270 return static_cast<uint32_t>(font_->offsetForPosition( | |
| 271 run, static_cast<float>(pixel_position))); | |
| 272 } | |
| 273 | |
| 274 int32_t PPB_BrowserFont_Trusted_Shared::PixelOffsetForCharacter( | |
| 275 const PP_BrowserFont_Trusted_TextRun* text, | |
| 276 uint32_t char_offset) { | |
| 277 WebTextRun run; | |
| 278 if (!PPTextRunToWebTextRun(*text, &run)) | |
| 279 return -1; | |
| 280 if (char_offset >= run.text.length()) | |
| 281 return -1; | |
| 282 | |
| 283 WebFloatRect rect = font_->selectionRectForText( | |
| 284 run, WebFloatPoint(0.0f, 0.0f), font_->height(), 0, char_offset); | |
| 285 return static_cast<int>(rect.width); | |
| 286 } | |
| 287 | |
| 288 void PPB_BrowserFont_Trusted_Shared::DrawTextToCanvas( | |
| 289 skia::PlatformCanvas* destination, | |
| 290 const PP_BrowserFont_Trusted_TextRun& text, | |
| 291 const PP_Point* position, | |
| 292 uint32_t color, | |
| 293 const PP_Rect* clip, | |
| 294 PP_Bool image_data_is_opaque) { | |
| 295 TRACE_EVENT0("ppapi WebKit thread", "FontImpl::DrawTextAt"); | |
|
viettrungluu
2012/02/15 04:42:46
eh?
brettw
2012/02/16 19:19:26
Just copied from the old code, I removed these.
| |
| 296 WebTextRun run; | |
| 297 if (!PPTextRunToWebTextRun(text, &run)) | |
| 298 return; | |
| 299 | |
| 300 // Convert position and clip. | |
| 301 WebFloatPoint web_position(static_cast<float>(position->x), | |
| 302 static_cast<float>(position->y)); | |
| 303 WebRect web_clip; | |
| 304 if (!clip) { | |
| 305 // Use entire canvas. SkCanvas doesn't have a size on it, so we just use | |
| 306 // the current clip bounds. | |
| 307 SkRect skclip; | |
| 308 destination->getClipBounds(&skclip); | |
| 309 web_clip = WebRect(skclip.fLeft, skclip.fTop, skclip.fRight - skclip.fLeft, | |
| 310 skclip.fBottom - skclip.fTop); | |
| 311 } else { | |
| 312 web_clip = WebRect(clip->point.x, clip->point.y, | |
| 313 clip->size.width, clip->size.height); | |
| 314 } | |
| 315 | |
| 316 #if WEBKIT_USING_SKIA | |
| 317 WebCanvas* canvas = destination; | |
| 318 #elif WEBKIT_USING_CG | |
| 319 WebCanvas* canvas = skia::GetBitmapContext(skia::GetTopDevice(*destination)); | |
| 320 #else | |
| 321 NOTIMPLEMENTED(); | |
| 322 return; | |
| 323 #endif | |
| 324 font_->drawText(canvas, run, web_position, color, web_clip, | |
| 325 PP_ToBool(image_data_is_opaque)); | |
| 326 } | |
| 327 | |
| 328 } // namespace ppapi | |
| 329 | |
| OLD | NEW |