OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "ppapi/proxy/ppb_font_proxy.h" | 5 #include "ppapi/proxy/ppb_font_proxy.h" |
6 | 6 |
| 7 #include "base/bind.h" |
7 #include "ppapi/c/dev/ppb_font_dev.h" | 8 #include "ppapi/c/dev/ppb_font_dev.h" |
8 #include "ppapi/proxy/plugin_dispatcher.h" | 9 #include "ppapi/proxy/plugin_dispatcher.h" |
9 #include "ppapi/proxy/plugin_resource.h" | |
10 #include "ppapi/proxy/ppapi_messages.h" | 10 #include "ppapi/proxy/ppapi_messages.h" |
| 11 #include "ppapi/proxy/ppb_image_data_proxy.h" |
| 12 #include "ppapi/shared_impl/resource_object_base.h" |
| 13 #include "ppapi/thunk/ppb_image_data_api.h" |
| 14 #include "ppapi/thunk/thunk.h" |
| 15 |
| 16 using ppapi::thunk::PPB_ImageData_API; |
| 17 using pp::shared_impl::WebKitForwarding; |
11 | 18 |
12 namespace pp { | 19 namespace pp { |
13 namespace proxy { | 20 namespace proxy { |
14 | 21 |
15 class Font : public PluginResource { | |
16 public: | |
17 Font(const HostResource& resource); | |
18 virtual ~Font(); | |
19 | |
20 // PluginResource overrides. | |
21 virtual Font* AsFont() { return this; } | |
22 | |
23 PP_FontDescription_Dev& desc() { return desc_; } | |
24 PP_FontDescription_Dev* desc_ptr() { return &desc_; } | |
25 PP_FontMetrics_Dev& metrics() { return metrics_; } | |
26 | |
27 private: | |
28 PP_FontDescription_Dev desc_; | |
29 PP_FontMetrics_Dev metrics_; | |
30 | |
31 DISALLOW_COPY_AND_ASSIGN(Font); | |
32 }; | |
33 | |
34 Font::Font(const HostResource& resource) : PluginResource(resource) { | |
35 memset(&desc_, 0, sizeof(PP_FontDescription_Dev)); | |
36 desc_.face.type = PP_VARTYPE_UNDEFINED; | |
37 memset(&metrics_, 0, sizeof(PP_FontMetrics_Dev)); | |
38 } | |
39 | |
40 Font::~Font() { | |
41 PluginVarTracker::GetInstance()->Release(desc_.face); | |
42 } | |
43 | |
44 namespace { | 22 namespace { |
45 | 23 |
46 PP_Resource Create(PP_Instance instance, | 24 bool PPTextRunToTextRun(const PP_TextRun_Dev* run, |
47 const PP_FontDescription_Dev* description) { | 25 WebKitForwarding::Font::TextRun* output) { |
48 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); | 26 const std::string* str = PluginVarTracker::GetInstance()->GetExistingString( |
49 if (!dispatcher) | 27 run->text); |
50 return 0; | 28 if (!str) |
| 29 return false; |
51 | 30 |
52 SerializedFontDescription in_description; | 31 output->text = *str; |
53 in_description.SetFromPPFontDescription(dispatcher, *description, true); | 32 output->rtl = PPBoolToBool(run->rtl); |
54 | 33 output->override_direction = PPBoolToBool(run->override_direction); |
55 HostResource result; | 34 return true; |
56 SerializedFontDescription out_description; | |
57 std::string out_metrics; | |
58 dispatcher->Send(new PpapiHostMsg_PPBFont_Create( | |
59 INTERFACE_ID_PPB_FONT, | |
60 instance, in_description, &result, &out_description, &out_metrics)); | |
61 | |
62 if (result.is_null()) | |
63 return 0; // Failure creating font. | |
64 | |
65 linked_ptr<Font> object(new Font(result)); | |
66 out_description.SetToPPFontDescription(dispatcher, object->desc_ptr(), true); | |
67 | |
68 // Convert the metrics, this is just serialized as a string of bytes. | |
69 if (out_metrics.size() != sizeof(PP_FontMetrics_Dev)) | |
70 return 0; | |
71 memcpy(&object->metrics(), out_metrics.data(), sizeof(PP_FontMetrics_Dev)); | |
72 | |
73 return PluginResourceTracker::GetInstance()->AddResource(object); | |
74 } | 35 } |
75 | 36 |
76 PP_Bool IsFont(PP_Resource resource) { | |
77 Font* object = PluginResource::GetAs<Font>(resource); | |
78 return BoolToPPBool(!!object); | |
79 } | |
80 | |
81 PP_Bool Describe(PP_Resource font_id, | |
82 PP_FontDescription_Dev* description, | |
83 PP_FontMetrics_Dev* metrics) { | |
84 Font* object = PluginResource::GetAs<Font>(font_id); | |
85 if (!object) | |
86 return PP_FALSE; | |
87 | |
88 // Copy the description, the caller expects its face PP_Var to have a ref | |
89 // added to it on its behalf. | |
90 memcpy(description, &object->desc(), sizeof(PP_FontDescription_Dev)); | |
91 PluginVarTracker::GetInstance()->AddRef(description->face); | |
92 | |
93 memcpy(metrics, &object->metrics(), sizeof(PP_FontMetrics_Dev)); | |
94 return PP_TRUE; | |
95 } | |
96 | |
97 PP_Bool DrawTextAt(PP_Resource font_id, | |
98 PP_Resource image_data, | |
99 const PP_TextRun_Dev* text, | |
100 const PP_Point* position, | |
101 uint32_t color, | |
102 const PP_Rect* clip, | |
103 PP_Bool image_data_is_opaque) { | |
104 Font* font_object = PluginResource::GetAs<Font>(font_id); | |
105 if (!font_object) | |
106 return PP_FALSE; | |
107 PluginResource* image_object = PluginResourceTracker::GetInstance()-> | |
108 GetResourceObject(image_data); | |
109 if (!image_object) | |
110 return PP_FALSE; | |
111 if (font_object->instance() != image_object->instance()) | |
112 return PP_FALSE; | |
113 | |
114 PPBFont_DrawTextAt_Params params; | |
115 params.font = font_object->host_resource(); | |
116 params.image_data = image_object->host_resource(); | |
117 params.text_is_rtl = text->rtl; | |
118 params.override_direction = text->override_direction; | |
119 params.position = *position; | |
120 params.color = color; | |
121 if (clip) { | |
122 params.clip = *clip; | |
123 params.clip_is_null = false; | |
124 } else { | |
125 params.clip = PP_MakeRectFromXYWH(0, 0, 0, 0); | |
126 params.clip_is_null = true; | |
127 } | |
128 params.image_data_is_opaque = image_data_is_opaque; | |
129 | |
130 Dispatcher* dispatcher = PluginDispatcher::GetForInstance( | |
131 image_object->instance()); | |
132 PP_Bool result = PP_FALSE; | |
133 if (dispatcher) { | |
134 dispatcher->Send(new PpapiHostMsg_PPBFont_DrawTextAt( | |
135 INTERFACE_ID_PPB_FONT, | |
136 SerializedVarSendInput(dispatcher, text->text), | |
137 params, &result)); | |
138 } | |
139 return result; | |
140 } | |
141 | |
142 int32_t MeasureText(PP_Resource font_id, const PP_TextRun_Dev* text) { | |
143 Font* object = PluginResource::GetAs<Font>(font_id); | |
144 if (!object) | |
145 return -1; | |
146 | |
147 Dispatcher* dispatcher = PluginDispatcher::GetForInstance(object->instance()); | |
148 int32_t result = 0; | |
149 if (dispatcher) { | |
150 dispatcher->Send(new PpapiHostMsg_PPBFont_MeasureText( | |
151 INTERFACE_ID_PPB_FONT, object->host_resource(), | |
152 SerializedVarSendInput(dispatcher, text->text), | |
153 text->rtl, text->override_direction, &result)); | |
154 } | |
155 return result; | |
156 } | |
157 | |
158 uint32_t CharacterOffsetForPixel(PP_Resource font_id, | |
159 const PP_TextRun_Dev* text, | |
160 int32_t pixel_position) { | |
161 Font* object = PluginResource::GetAs<Font>(font_id); | |
162 if (!object) | |
163 return -1; | |
164 | |
165 Dispatcher* dispatcher = PluginDispatcher::GetForInstance(object->instance()); | |
166 uint32_t result = 0; | |
167 if (dispatcher) { | |
168 dispatcher->Send(new PpapiHostMsg_PPBFont_CharacterOffsetForPixel( | |
169 INTERFACE_ID_PPB_FONT, object->host_resource(), | |
170 SerializedVarSendInput(dispatcher, text->text), | |
171 text->rtl, text->override_direction, pixel_position, &result)); | |
172 } | |
173 return result; | |
174 } | |
175 | |
176 int32_t PixelOffsetForCharacter(PP_Resource font_id, | |
177 const PP_TextRun_Dev* text, | |
178 uint32_t char_offset) { | |
179 Font* object = PluginResource::GetAs<Font>(font_id); | |
180 if (!object) | |
181 return -1; | |
182 | |
183 Dispatcher* dispatcher = PluginDispatcher::GetForInstance(object->instance()); | |
184 int32_t result = 0; | |
185 if (dispatcher) { | |
186 dispatcher->Send(new PpapiHostMsg_PPBFont_PixelOffsetForCharacter( | |
187 INTERFACE_ID_PPB_FONT, object->host_resource(), | |
188 SerializedVarSendInput(dispatcher, text->text), | |
189 text->rtl, text->override_direction, char_offset, &result)); | |
190 } | |
191 return result; | |
192 } | |
193 | |
194 const PPB_Font_Dev font_interface = { | |
195 &Create, | |
196 &IsFont, | |
197 &Describe, | |
198 &DrawTextAt, | |
199 &MeasureText, | |
200 &CharacterOffsetForPixel, | |
201 &PixelOffsetForCharacter | |
202 }; | |
203 | |
204 InterfaceProxy* CreateFontProxy(Dispatcher* dispatcher, | 37 InterfaceProxy* CreateFontProxy(Dispatcher* dispatcher, |
205 const void* target_interface) { | 38 const void* target_interface) { |
206 return new PPB_Font_Proxy(dispatcher, target_interface); | 39 return new PPB_Font_Proxy(dispatcher, target_interface); |
207 } | 40 } |
208 | 41 |
209 } // namespace | 42 } // namespace |
210 | 43 |
211 PPB_Font_Proxy::PPB_Font_Proxy(Dispatcher* dispatcher, | 44 PPB_Font_Proxy::PPB_Font_Proxy(Dispatcher* dispatcher, |
212 const void* target_interface) | 45 const void* target_interface) |
213 : InterfaceProxy(dispatcher, target_interface) { | 46 : InterfaceProxy(dispatcher, target_interface) { |
214 } | 47 } |
215 | 48 |
216 PPB_Font_Proxy::~PPB_Font_Proxy() { | 49 PPB_Font_Proxy::~PPB_Font_Proxy() { |
217 } | 50 } |
218 | 51 |
219 // static | 52 // static |
220 const InterfaceProxy::Info* PPB_Font_Proxy::GetInfo() { | 53 const InterfaceProxy::Info* PPB_Font_Proxy::GetInfo() { |
221 static const Info info = { | 54 static const Info info = { |
222 &font_interface, | 55 ::ppapi::thunk::GetPPB_Font_Thunk(), |
223 PPB_FONT_DEV_INTERFACE, | 56 PPB_FONT_DEV_INTERFACE, |
224 INTERFACE_ID_PPB_FONT, | 57 INTERFACE_ID_PPB_FONT, |
225 false, | 58 false, |
226 &CreateFontProxy, | 59 &CreateFontProxy, |
227 }; | 60 }; |
228 return &info; | 61 return &info; |
229 } | 62 } |
230 | 63 |
231 bool PPB_Font_Proxy::OnMessageReceived(const IPC::Message& msg) { | 64 bool PPB_Font_Proxy::OnMessageReceived(const IPC::Message& msg) { |
232 bool handled = true; | 65 // There aren't any font messages. |
233 IPC_BEGIN_MESSAGE_MAP(PPB_Font_Proxy, msg) | 66 NOTREACHED(); |
234 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFont_Create, | 67 return false; |
235 OnMsgCreate) | |
236 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFont_DrawTextAt, | |
237 OnMsgDrawTextAt) | |
238 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFont_MeasureText, | |
239 OnMsgMeasureText) | |
240 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFont_CharacterOffsetForPixel, | |
241 OnMsgCharacterOffsetForPixel) | |
242 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFont_PixelOffsetForCharacter, | |
243 OnMsgPixelOffsetForCharacter) | |
244 IPC_MESSAGE_UNHANDLED(handled = false) | |
245 IPC_END_MESSAGE_MAP() | |
246 return handled; | |
247 } | 68 } |
248 | 69 |
249 void PPB_Font_Proxy::OnMsgCreate( | 70 Font::Font(const HostResource& resource, |
250 PP_Instance instance, | 71 const PP_FontDescription_Dev& desc) |
251 const SerializedFontDescription& in_description, | 72 : PluginResource(resource), |
252 HostResource* result, | 73 webkit_event_(false, false) { |
253 SerializedFontDescription* out_description, | 74 const std::string* face = PluginVarTracker::GetInstance()->GetExistingString( |
254 std::string* out_metrics) { | 75 desc.face); |
255 // Convert the face name in the input description. | |
256 PP_FontDescription_Dev in_pp_desc; | |
257 in_description.SetToPPFontDescription(dispatcher(), &in_pp_desc, false); | |
258 | 76 |
259 // Make sure the output is always defined so we can still serialize it back | 77 WebKitForwarding* forwarding = GetDispatcher()->GetWebKitForwarding(); |
260 // to the plugin below. | |
261 PP_FontDescription_Dev out_pp_desc; | |
262 memset(&out_pp_desc, 0, sizeof(PP_FontDescription_Dev)); | |
263 out_pp_desc.face = PP_MakeUndefined(); | |
264 | 78 |
265 result->SetHostResource(instance, | 79 WebKitForwarding::Font* result = NULL; |
266 ppb_font_target()->Create(instance, &in_pp_desc)); | 80 RunOnWebKitThread(base::Bind(&WebKitForwarding::CreateFontForwarding, |
267 if (!result->is_null()) { | 81 base::Unretained(forwarding), |
268 // Get the metrics and resulting description to return to the browser. | 82 &webkit_event_, desc, |
269 PP_FontMetrics_Dev metrics; | 83 face ? *face : std::string(), &result)); |
270 if (ppb_font_target()->Describe(result->host_resource(), &out_pp_desc, | 84 font_forwarding_.reset(result); |
271 &metrics)) { | 85 } |
272 out_metrics->assign(reinterpret_cast<const char*>(&metrics), | 86 |
273 sizeof(PP_FontMetrics_Dev)); | 87 Font::~Font() { |
274 } | 88 } |
| 89 |
| 90 ppapi::thunk::PPB_Font_API* Font::AsFont_API() { |
| 91 return this; |
| 92 } |
| 93 |
| 94 Font* Font::AsFont() { |
| 95 return this; |
| 96 } |
| 97 |
| 98 PP_Bool Font::Describe(PP_FontDescription_Dev* description, |
| 99 PP_FontMetrics_Dev* metrics) { |
| 100 std::string face; |
| 101 PP_Bool result = PP_FALSE; |
| 102 RunOnWebKitThread(base::Bind(&WebKitForwarding::Font::Describe, |
| 103 base::Unretained(font_forwarding_.get()), |
| 104 &webkit_event_, description, &face, metrics, |
| 105 &result)); |
| 106 |
| 107 if (result == PP_TRUE) { |
| 108 description->face.type = PP_VARTYPE_STRING; |
| 109 description->face.value.as_id = |
| 110 PluginVarTracker::GetInstance()->MakeString(face); |
| 111 } else { |
| 112 description->face.type = PP_VARTYPE_UNDEFINED; |
| 113 } |
| 114 return result; |
| 115 } |
| 116 |
| 117 PP_Bool Font::DrawTextAt(PP_Resource pp_image_data, |
| 118 const PP_TextRun_Dev* text, |
| 119 const PP_Point* position, |
| 120 uint32_t color, |
| 121 const PP_Rect* clip, |
| 122 PP_Bool image_data_is_opaque) { |
| 123 // Convert to an ImageData object. |
| 124 ppapi::shared_impl::ResourceObjectBase* image_base = |
| 125 ppapi::shared_impl::TrackerBase::Get()->GetResourceAPI(pp_image_data); |
| 126 if (!image_base) |
| 127 return PP_FALSE; |
| 128 PPB_ImageData_API* image_api = image_base->GetAs<PPB_ImageData_API>(); |
| 129 if (!image_api) |
| 130 return PP_FALSE; |
| 131 ImageData* image_data = static_cast<ImageData*>(image_api); |
| 132 |
| 133 skia::PlatformCanvas* canvas = image_data->mapped_canvas(); |
| 134 bool needs_unmapping = false; |
| 135 if (!canvas) { |
| 136 needs_unmapping = true; |
| 137 image_data->Map(); |
| 138 canvas = image_data->mapped_canvas(); |
| 139 if (!canvas) |
| 140 return PP_FALSE; // Failure mapping. |
275 } | 141 } |
276 | 142 |
277 // This must always get called or it will assert when trying to serialize | 143 WebKitForwarding::Font::TextRun run; |
278 // the un-filled-in SerializedFontDescription as the return value. | 144 if (!PPTextRunToTextRun(text, &run)) { |
279 out_description->SetFromPPFontDescription(dispatcher(), out_pp_desc, false); | 145 if (needs_unmapping) |
| 146 image_data->Unmap(); |
| 147 return PP_FALSE; |
| 148 } |
| 149 RunOnWebKitThread(base::Bind( |
| 150 &WebKitForwarding::Font::DrawTextAt, |
| 151 base::Unretained(font_forwarding_.get()), |
| 152 &webkit_event_, |
| 153 WebKitForwarding::Font::DrawTextParams(canvas, run, position, color, |
| 154 clip, image_data_is_opaque))); |
| 155 |
| 156 if (needs_unmapping) |
| 157 image_data->Unmap(); |
| 158 return PP_TRUE; |
280 } | 159 } |
281 | 160 |
282 void PPB_Font_Proxy::OnMsgDrawTextAt(SerializedVarReceiveInput text, | 161 int32_t Font::MeasureText(const PP_TextRun_Dev* text) { |
283 const PPBFont_DrawTextAt_Params& params, | 162 WebKitForwarding::Font::TextRun run; |
284 PP_Bool* result) { | 163 if (!PPTextRunToTextRun(text, &run)) |
285 PP_TextRun_Dev run; | 164 return -1; |
286 run.text = text.Get(dispatcher()); | 165 int32_t result = -1; |
287 run.rtl = params.text_is_rtl; | 166 RunOnWebKitThread(base::Bind(&WebKitForwarding::Font::MeasureText, |
288 run.override_direction = params.override_direction; | 167 base::Unretained(font_forwarding_.get()), |
289 | 168 &webkit_event_, run, &result)); |
290 *result = ppb_font_target()->DrawTextAt(params.font.host_resource(), | 169 return result; |
291 params.image_data.host_resource(), &run, ¶ms.position, params.color, | |
292 params.clip_is_null ? NULL : ¶ms.clip, params.image_data_is_opaque); | |
293 } | 170 } |
294 | 171 |
295 void PPB_Font_Proxy::OnMsgMeasureText(HostResource font, | 172 uint32_t Font::CharacterOffsetForPixel(const PP_TextRun_Dev* text, |
296 SerializedVarReceiveInput text, | 173 int32_t pixel_position) { |
297 PP_Bool text_is_rtl, | 174 WebKitForwarding::Font::TextRun run; |
298 PP_Bool override_direction, | 175 if (!PPTextRunToTextRun(text, &run)) |
299 int32_t* result) { | 176 return -1; |
300 PP_TextRun_Dev run; | 177 uint32_t result = -1; |
301 run.text = text.Get(dispatcher()); | 178 RunOnWebKitThread(base::Bind(&WebKitForwarding::Font::CharacterOffsetForPixel, |
302 run.rtl = text_is_rtl; | 179 base::Unretained(font_forwarding_.get()), |
303 run.override_direction = override_direction; | 180 &webkit_event_, run, pixel_position, &result)); |
304 | 181 return result; |
305 *result = ppb_font_target()->MeasureText(font.host_resource(), &run); | |
306 } | 182 } |
307 | 183 |
308 void PPB_Font_Proxy::OnMsgCharacterOffsetForPixel( | 184 int32_t Font::PixelOffsetForCharacter(const PP_TextRun_Dev* text, |
309 HostResource font, | 185 uint32_t char_offset) { |
310 SerializedVarReceiveInput text, | 186 WebKitForwarding::Font::TextRun run; |
311 PP_Bool text_is_rtl, | 187 if (!PPTextRunToTextRun(text, &run)) |
312 PP_Bool override_direction, | 188 return -1; |
313 int32_t pixel_pos, | 189 int32_t result = -1; |
314 uint32_t* result) { | 190 RunOnWebKitThread(base::Bind(&WebKitForwarding::Font::PixelOffsetForCharacter, |
315 PP_TextRun_Dev run; | 191 base::Unretained(font_forwarding_.get()), |
316 run.text = text.Get(dispatcher()); | 192 &webkit_event_, run, char_offset, &result)); |
317 run.rtl = text_is_rtl; | 193 return result; |
318 run.override_direction = override_direction; | |
319 | |
320 *result = ppb_font_target()->CharacterOffsetForPixel(font.host_resource(), | |
321 &run, pixel_pos); | |
322 } | 194 } |
323 | 195 |
324 void PPB_Font_Proxy::OnMsgPixelOffsetForCharacter( | 196 void Font::RunOnWebKitThread(const base::Closure& task) { |
325 HostResource font, | 197 GetDispatcher()->PostToWebKitThread(FROM_HERE, task); |
326 SerializedVarReceiveInput text, | 198 webkit_event_.Wait(); |
327 PP_Bool text_is_rtl, | |
328 PP_Bool override_direction, | |
329 uint32_t char_offset, | |
330 int32_t* result) { | |
331 PP_TextRun_Dev run; | |
332 run.text = text.Get(dispatcher()); | |
333 run.rtl = text_is_rtl; | |
334 run.override_direction = override_direction; | |
335 | |
336 *result = ppb_font_target()->PixelOffsetForCharacter(font.host_resource(), | |
337 &run, char_offset); | |
338 } | 199 } |
339 | 200 |
340 } // namespace proxy | 201 } // namespace proxy |
341 } // namespace pp | 202 } // namespace pp |
OLD | NEW |