1 // Copyright (c) 2013 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 <math.h> 6 #include <stdio.h> 7 8 #include "ppapi/c/ppb_mouse_cursor.h" 9 #include "ppapi/cpp/image_data.h" 10 #include "ppapi/cpp/instance.h" 11 #include "ppapi/cpp/module.h" 12 #include "ppapi/cpp/mouse_cursor.h" 13 #include "ppapi/cpp/size.h" 14 #include "ppapi/cpp/var.h" 15 #include "ppapi/utility/completion_callback_factory.h" 16 17 #ifdef WIN32 18 #undef PostMessage 19 // Allow 'this' in initializer list 20 #pragma warning(disable : 4355) 21 #endif 22 23 namespace { 24 25 uint32_t MakeColor(float r, float g, float b, float a) { 26 // Since we're using premultiplied alpha 27 // (PP_IMAGEDATAFORMAT_BGRA_PREMUL), we have to multiply each 28 // color component by the alpha value. 29 uint8_t a8 = static_cast<uint8_t>(255 * a); 30 uint8_t r8 = static_cast<uint8_t>(255 * r * a); 31 uint8_t g8 = static_cast<uint8_t>(255 * g * a); 32 uint8_t b8 = static_cast<uint8_t>(255 * b * a); 33 return (a8 << 24) | (r8 << 16) | (g8 << 8) | b8; 34 } 35 36 } 37 38 class MouseCursorInstance : public pp::Instance { 39 public: 40 explicit MouseCursorInstance(PP_Instance instance) 41 : pp::Instance(instance) {} 42 43 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { 44 MakeCustomCursor(); 45 return true; 46 } 47 48 private: 49 virtual void HandleMessage(const pp::Var& var_message) { 50 if (!var_message.is_number()) { 51 fprintf(stderr, "Unexpected message.\n"); 52 return; 53 } 54 55 PP_MouseCursor_Type cursor = 56 static_cast<PP_MouseCursor_Type>(var_message.AsInt()); 57 if (cursor == PP_MOUSECURSOR_TYPE_CUSTOM) { 58 pp::Point hot_spot(16, 16); 59 pp::MouseCursor::SetCursor(this, cursor, custom_cursor_, hot_spot); 60 } else { 61 pp::MouseCursor::SetCursor(this, cursor); 62 } 63 } 64 65 void MakeCustomCursor() { 66 pp::Size size(32, 32); 67 custom_cursor_ = 68 pp::ImageData(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, true); 69 DrawCircle(16, 16, 9, 14, 0.8f, 0.8f, 0); 70 DrawCircle(11, 12, 2, 3, 0, 0, 0); 71 DrawCircle(21, 12, 2, 3, 0, 0, 0); 72 DrawHorizontalLine(12, 20, 21, 0.5f, 0, 0, 1.0f); 73 } 74 75 void DrawCircle(int cx, int cy, float alpha_radius, float radius, 76 float r, float g, float b) { 77 pp::Size size = custom_cursor_.size(); 78 uint32_t* data = static_cast<uint32_t*>(custom_cursor_.data()); 79 // It's less efficient to loop over the entire image this way, but the 80 // image is small, and this is simpler. 81 for (int y = 0; y < size.width(); ++y) { 82 for (int x = 0; x < size.width(); ++x) { 83 int dx = (x - cx); 84 int dy = (y - cy); 85 float dist = sqrtf(dx * dx + dy * dy); 86 87 if (dist < radius) { 88 float a; 89 if (dist > alpha_radius) { 90 a = 1.f - (dist - alpha_radius) / (radius - alpha_radius); 91 } else { 92 a = 1.f; 93 } 94 95 data[y * size.width() + x] = MakeColor(r, g, b, a); 96 } 97 } 98 } 99 } 100 101 void DrawHorizontalLine(int x1, int x2, int y, 102 float r, float g, float b, float a) { 103 pp::Size size = custom_cursor_.size(); 104 uint32_t* data = static_cast<uint32_t*>(custom_cursor_.data()); 105 for (int x = x1; x <= x2; ++x) { 106 data[y * size.width() + x] = MakeColor(r, g, b, a); 107 } 108 } 109 110 pp::ImageData custom_cursor_; 111 }; 112 113 class MouseCursorModule : public pp::Module { 114 public: 115 MouseCursorModule() : pp::Module() {} 116 virtual ~MouseCursorModule() {} 117 118 virtual pp::Instance* CreateInstance(PP_Instance instance) { 119 return new MouseCursorInstance(instance); 120 } 121 }; 122 123 namespace pp { 124 Module* CreateModule() { return new MouseCursorModule(); } 125 } // namespace pp 126