Chromium Code Reviews| 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; | |
| 11 | 17 |
| 12 namespace pp { | 18 namespace pp { |
| 13 namespace proxy { | 19 namespace proxy { |
| 14 | 20 |
| 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 { | 21 namespace { |
| 45 | 22 |
| 46 PP_Resource Create(PP_Instance instance, | 23 bool PPTextRunToTextRun(const PP_TextRun_Dev* run, |
| 47 const PP_FontDescription_Dev* description) { | 24 Font::TextRun* output) { |
| 48 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); | 25 const std::string* str = PluginVarTracker::GetInstance()->GetExistingString( |
| 49 if (!dispatcher) | 26 run->text); |
| 50 return 0; | 27 if (!str) |
| 28 return false; | |
| 51 | 29 |
| 52 SerializedFontDescription in_description; | 30 output->text = *str; |
| 53 in_description.SetFromPPFontDescription(dispatcher, *description, true); | 31 output->rtl = PPBoolToBool(run->rtl); |
| 54 | 32 output->override_direction = PPBoolToBool(run->override_direction); |
| 55 HostResource result; | 33 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 } | 34 } |
| 75 | 35 |
| 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, | 36 InterfaceProxy* CreateFontProxy(Dispatcher* dispatcher, |
| 205 const void* target_interface) { | 37 const void* target_interface) { |
| 206 return new PPB_Font_Proxy(dispatcher, target_interface); | 38 return new PPB_Font_Proxy(dispatcher, target_interface); |
| 207 } | 39 } |
| 208 | 40 |
| 209 } // namespace | 41 } // namespace |
| 210 | 42 |
| 211 PPB_Font_Proxy::PPB_Font_Proxy(Dispatcher* dispatcher, | 43 PPB_Font_Proxy::PPB_Font_Proxy(Dispatcher* dispatcher, |
| 212 const void* target_interface) | 44 const void* target_interface) |
| 213 : InterfaceProxy(dispatcher, target_interface) { | 45 : InterfaceProxy(dispatcher, target_interface) { |
| 214 } | 46 } |
| 215 | 47 |
| 216 PPB_Font_Proxy::~PPB_Font_Proxy() { | 48 PPB_Font_Proxy::~PPB_Font_Proxy() { |
| 217 } | 49 } |
| 218 | 50 |
| 219 // static | 51 // static |
| 220 const InterfaceProxy::Info* PPB_Font_Proxy::GetInfo() { | 52 const InterfaceProxy::Info* PPB_Font_Proxy::GetInfo() { |
| 221 static const Info info = { | 53 static const Info info = { |
| 222 &font_interface, | 54 ::ppapi::thunk::GetPPB_Font_Thunk(), |
| 223 PPB_FONT_DEV_INTERFACE, | 55 PPB_FONT_DEV_INTERFACE, |
| 224 INTERFACE_ID_PPB_FONT, | 56 INTERFACE_ID_PPB_FONT, |
| 225 false, | 57 false, |
| 226 &CreateFontProxy, | 58 &CreateFontProxy, |
| 227 }; | 59 }; |
| 228 return &info; | 60 return &info; |
| 229 } | 61 } |
| 230 | 62 |
| 231 bool PPB_Font_Proxy::OnMessageReceived(const IPC::Message& msg) { | 63 bool PPB_Font_Proxy::OnMessageReceived(const IPC::Message& msg) { |
| 232 bool handled = true; | 64 // There aren't any font messages. |
| 233 IPC_BEGIN_MESSAGE_MAP(PPB_Font_Proxy, msg) | 65 NOTREACHED(); |
| 234 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFont_Create, | 66 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 } | 67 } |
| 248 | 68 |
| 249 void PPB_Font_Proxy::OnMsgCreate( | 69 Font::Font(const HostResource& resource, |
| 250 PP_Instance instance, | 70 const PP_FontDescription_Dev& desc) |
| 251 const SerializedFontDescription& in_description, | 71 : PluginResource(resource), |
| 252 HostResource* result, | 72 webkit_event_(false, false) { |
| 253 SerializedFontDescription* out_description, | 73 const std::string* face = PluginVarTracker::GetInstance()->GetExistingString( |
| 254 std::string* out_metrics) { | 74 desc.face); |
| 255 // Convert the face name in the input description. | 75 RunOnWebKitThread(base::Bind(&Font::DoCreate, base::Unretained(this), |
| 256 PP_FontDescription_Dev in_pp_desc; | 76 &webkit_event_, desc, |
| 257 in_description.SetToPPFontDescription(dispatcher(), &in_pp_desc, false); | 77 face ? *face : std::string())); |
| 78 } | |
| 258 | 79 |
| 259 // Make sure the output is always defined so we can still serialize it back | 80 Font::~Font() { |
| 260 // to the plugin below. | 81 } |
| 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 | 82 |
| 265 result->SetHostResource(instance, | 83 ppapi::thunk::PPB_Font_API* Font::AsFont_API() { |
| 266 ppb_font_target()->Create(instance, &in_pp_desc)); | 84 return this; |
| 267 if (!result->is_null()) { | 85 } |
| 268 // Get the metrics and resulting description to return to the browser. | 86 |
| 269 PP_FontMetrics_Dev metrics; | 87 Font* Font::AsFont() { |
| 270 if (ppb_font_target()->Describe(result->host_resource(), &out_pp_desc, | 88 return this; |
| 271 &metrics)) { | 89 } |
| 272 out_metrics->assign(reinterpret_cast<const char*>(&metrics), | 90 |
| 273 sizeof(PP_FontMetrics_Dev)); | 91 PP_Bool Font::Describe(PP_FontDescription_Dev* description, |
| 274 } | 92 PP_FontMetrics_Dev* metrics) { |
| 93 std::string face; | |
| 94 PP_Bool result = PP_FALSE; | |
| 95 RunOnWebKitThread(base::Bind(&Font::DoDescribe, base::Unretained(this), | |
| 96 &webkit_event_, description, &face, metrics, | |
| 97 &result)); | |
| 98 | |
| 99 if (result == PP_TRUE) { | |
| 100 description->face.type = PP_VARTYPE_STRING; | |
| 101 description->face.value.as_id = | |
| 102 PluginVarTracker::GetInstance()->MakeString(face); | |
| 103 } else { | |
| 104 description->face.type = PP_VARTYPE_UNDEFINED; | |
| 105 } | |
| 106 return result; | |
| 107 } | |
| 108 | |
| 109 PP_Bool Font::DrawTextAt(PP_Resource pp_image_data, | |
| 110 const PP_TextRun_Dev* text, | |
| 111 const PP_Point* position, | |
| 112 uint32_t color, | |
| 113 const PP_Rect* clip, | |
| 114 PP_Bool image_data_is_opaque) { | |
| 115 // Convert to an ImageData object. | |
| 116 ppapi::shared_impl::ResourceObjectBase* image_base = | |
| 117 ppapi::shared_impl::TrackerBase::Get()->GetResourceAPI(pp_image_data); | |
| 118 if (!image_base) | |
| 119 return PP_FALSE; | |
| 120 PPB_ImageData_API* image_api = image_base->GetAs<PPB_ImageData_API>(); | |
| 121 if (!image_api) | |
| 122 return PP_FALSE; | |
| 123 ImageData* image_data = static_cast<ImageData*>(image_api); | |
| 124 | |
| 125 skia::PlatformCanvas* canvas = image_data->mapped_canvas(); | |
| 126 bool needs_unmapping = false; | |
| 127 if (!canvas) { | |
| 128 needs_unmapping = true; | |
| 129 image_data->Map(); | |
| 130 canvas = image_data->mapped_canvas(); | |
| 131 if (!canvas) | |
| 132 return PP_FALSE; // Failure mapping. | |
| 275 } | 133 } |
| 276 | 134 |
| 277 // This must always get called or it will assert when trying to serialize | 135 TextRun run; |
| 278 // the un-filled-in SerializedFontDescription as the return value. | 136 if (!PPTextRunToTextRun(text, &run)) |
| 279 out_description->SetFromPPFontDescription(dispatcher(), out_pp_desc, false); | 137 return PP_FALSE; |
|
piman
2011/05/09 20:13:44
also image_data->Unmap() here - I know it's a noop
| |
| 138 RunOnWebKitThread(base::Bind(&Font::DoDrawTextAt, base::Unretained(this), | |
| 139 &webkit_event_, | |
| 140 DrawTextParams(canvas, run, position, color, | |
| 141 clip, image_data_is_opaque))); | |
| 142 | |
| 143 if (needs_unmapping) | |
| 144 image_data->Unmap(); | |
| 145 return PP_TRUE; | |
| 280 } | 146 } |
| 281 | 147 |
| 282 void PPB_Font_Proxy::OnMsgDrawTextAt(SerializedVarReceiveInput text, | 148 int32_t Font::MeasureText(const PP_TextRun_Dev* text) { |
| 283 const PPBFont_DrawTextAt_Params& params, | 149 TextRun run; |
| 284 PP_Bool* result) { | 150 if (!PPTextRunToTextRun(text, &run)) |
| 285 PP_TextRun_Dev run; | 151 return -1; |
| 286 run.text = text.Get(dispatcher()); | 152 int32_t result = -1; |
| 287 run.rtl = params.text_is_rtl; | 153 RunOnWebKitThread(base::Bind(&Font::DoMeasureText, base::Unretained(this), |
| 288 run.override_direction = params.override_direction; | 154 &webkit_event_, run, &result)); |
| 289 | 155 return result; |
| 290 *result = ppb_font_target()->DrawTextAt(params.font.host_resource(), | |
| 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 } | 156 } |
| 294 | 157 |
| 295 void PPB_Font_Proxy::OnMsgMeasureText(HostResource font, | 158 uint32_t Font::CharacterOffsetForPixel(const PP_TextRun_Dev* text, |
| 296 SerializedVarReceiveInput text, | 159 int32_t pixel_position) { |
| 297 PP_Bool text_is_rtl, | 160 TextRun run; |
| 298 PP_Bool override_direction, | 161 if (!PPTextRunToTextRun(text, &run)) |
| 299 int32_t* result) { | 162 return -1; |
| 300 PP_TextRun_Dev run; | 163 uint32_t result = -1; |
| 301 run.text = text.Get(dispatcher()); | 164 RunOnWebKitThread(base::Bind(&Font::DoCharacterOffsetForPixel, |
| 302 run.rtl = text_is_rtl; | 165 base::Unretained(this), |
| 303 run.override_direction = override_direction; | 166 &webkit_event_, run, pixel_position, &result)); |
| 304 | 167 return result; |
| 305 *result = ppb_font_target()->MeasureText(font.host_resource(), &run); | |
| 306 } | 168 } |
| 307 | 169 |
| 308 void PPB_Font_Proxy::OnMsgCharacterOffsetForPixel( | 170 int32_t Font::PixelOffsetForCharacter(const PP_TextRun_Dev* text, |
| 309 HostResource font, | 171 uint32_t char_offset) { |
| 310 SerializedVarReceiveInput text, | 172 TextRun run; |
| 311 PP_Bool text_is_rtl, | 173 if (!PPTextRunToTextRun(text, &run)) |
| 312 PP_Bool override_direction, | 174 return -1; |
| 313 int32_t pixel_pos, | 175 int32_t result = -1; |
| 314 uint32_t* result) { | 176 RunOnWebKitThread(base::Bind(&Font::DoPixelOffsetForCharacter, |
| 315 PP_TextRun_Dev run; | 177 base::Unretained(this), |
| 316 run.text = text.Get(dispatcher()); | 178 &webkit_event_, run, char_offset, &result)); |
| 317 run.rtl = text_is_rtl; | 179 return result; |
| 318 run.override_direction = override_direction; | |
| 319 | |
| 320 *result = ppb_font_target()->CharacterOffsetForPixel(font.host_resource(), | |
| 321 &run, pixel_pos); | |
| 322 } | 180 } |
| 323 | 181 |
| 324 void PPB_Font_Proxy::OnMsgPixelOffsetForCharacter( | 182 void Font::RunOnWebKitThread(const base::Closure& task) { |
| 325 HostResource font, | 183 GetDispatcher()->PostToWebKitThread(FROM_HERE, task); |
| 326 SerializedVarReceiveInput text, | 184 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 } | 185 } |
| 339 | 186 |
| 340 } // namespace proxy | 187 } // namespace proxy |
| 341 } // namespace pp | 188 } // namespace pp |
| OLD | NEW |