Home | History | Annotate | Download | only in mouse_cursor
      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