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 |