15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdarg.h>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/c/ppb_console.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_input_event.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/graphics_2d.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/image_data.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/input_event.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/instance.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/logging.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/module.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/mouse_lock.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/private/flash_fullscreen.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/rect.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/var.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/utility/completion_callback_factory.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MyInstance : public pp::Instance, public pp::MouseLock {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit MyInstance(PP_Instance instance)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : pp::Instance(instance),
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pp::MouseLock(this),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        width_(0),
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        height_(0),
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mouse_locked_(false),
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_paint_(false),
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        waiting_for_flush_completion_(false),
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback_factory_(this),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        console_(NULL),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        flash_fullscreen_(this) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MyInstance() {}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    console_ = reinterpret_cast<const PPB_Console*>(
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pp::Module::Get()->GetBrowserInterface(PPB_CONSOLE_INTERFACE));
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!console_)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE |
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       PP_INPUTEVENT_CLASS_KEYBOARD);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HandleInputEvent(const pp::InputEvent& event) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (event.GetType()) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pp::MouseInputEvent mouse_event(event);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT &&
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            !mouse_locked_) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          LockMouse(callback_factory_.NewCallback(&MyInstance::DidLockMouse));
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PP_INPUTEVENT_TYPE_MOUSEMOVE: {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pp::MouseInputEvent mouse_event(event);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mouse_movement_ = mouse_event.GetMovement();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static unsigned int i = 0;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Log(PP_LOGLEVEL_LOG, "[%d] movementX: %d; movementY: %d\n", i++,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mouse_movement_.x(), mouse_movement_.y());
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Paint();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PP_INPUTEVENT_TYPE_KEYDOWN: {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pp::KeyboardInputEvent key_event(event);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (key_event.GetKeyCode() == 13) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Lock the mouse when the Enter key is pressed.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (mouse_locked_)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            UnlockMouse();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          else
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            LockMouse(callback_factory_.NewCallback(&MyInstance::DidLockMouse));
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (key_event.GetKeyCode() == 70) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Enter Flash fullscreen mode when the 'f' key is pressed.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!flash_fullscreen_.IsFullscreen())
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            flash_fullscreen_.SetFullscreen(true);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (position.size().width() == width_ &&
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        position.size().height() == height_)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;  // We don't care about the position, only the size.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width_ = position.size().width();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    height_ = position.size().height();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device_context_ = pp::Graphics2D(this, pp::Size(width_, height_), false);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!BindGraphics(device_context_))
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Paint();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void MouseLockLost() {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mouse_locked_) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mouse_locked_ = false;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Paint();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_NOTREACHED();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DidLockMouse(int32_t result) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mouse_locked_ = result == PP_OK;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mouse_movement_.set_x(0);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mouse_movement_.set_y(0);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Paint();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DidFlush(int32_t result) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    waiting_for_flush_completion_ = false;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pending_paint_) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_paint_ = false;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Paint();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Paint() {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (waiting_for_flush_completion_) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_paint_ = true;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::ImageData image = PaintImage(width_, height_);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!image.is_null()) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device_context_.ReplaceContents(&image);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      waiting_for_flush_completion_ = true;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device_context_.Flush(
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          callback_factory_.NewCallback(&MyInstance::DidFlush));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::ImageData PaintImage(int width, int height) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        pp::Size(width, height), false);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (image.is_null())
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return image;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const static int kCenteralSpotRadius = 5;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const static uint32_t kBackgroundColor = 0xfff0f0f0;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const static uint32_t kLockedForegroundColor = 0xfff08080;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const static uint32_t kUnlockedForegroundColor = 0xff80f080;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int center_x = width / 2;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int center_y = height / 2;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::Point vertex(mouse_movement_.x() + center_x,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     mouse_movement_.y() + center_y);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::Point anchor_1;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::Point anchor_2;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LEFT = 0,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RIGHT = 1,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UP = 2,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DOWN = 3
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } direction = LEFT;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool draw_needle = GetDistance(mouse_movement_.x(), mouse_movement_.y(),
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   0, 0) > kCenteralSpotRadius;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (draw_needle) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (abs(mouse_movement_.x()) >= abs(mouse_movement_.y())) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         anchor_1.set_x(center_x);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         anchor_1.set_y(center_y - kCenteralSpotRadius);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         anchor_2.set_x(center_x);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         anchor_2.set_y(center_y + kCenteralSpotRadius);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         direction = (mouse_movement_.x() < 0) ? LEFT : RIGHT;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (direction == LEFT)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           anchor_1.swap(anchor_2);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         anchor_1.set_x(center_x + kCenteralSpotRadius);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         anchor_1.set_y(center_y);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         anchor_2.set_x(center_x - kCenteralSpotRadius);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         anchor_2.set_y(center_y);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         direction = (mouse_movement_.y() < 0) ? UP : DOWN;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (direction == UP)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           anchor_1.swap(anchor_2);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t foreground_color = mouse_locked_ ? kLockedForegroundColor :
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                kUnlockedForegroundColor;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int y = 0; y < image.size().height(); ++y) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int x = 0; x < image.size().width(); ++x) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (GetDistance(x, y, center_x, center_y) < kCenteralSpotRadius) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *image.GetAddr32(pp::Point(x, y)) = foreground_color;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (draw_needle) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          bool within_bound_1 =
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              ((y - anchor_1.y()) * (vertex.x() - anchor_1.x())) >
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              ((vertex.y() - anchor_1.y()) * (x - anchor_1.x()));
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          bool within_bound_2 =
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              ((y - anchor_2.y()) * (vertex.x() - anchor_2.x())) <
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              ((vertex.y() - anchor_2.y()) * (x - anchor_2.x()));
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          bool within_bound_3 =
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (direction == UP && y < center_y) ||
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (direction == DOWN && y > center_y) ||
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (direction == LEFT && x < center_x) ||
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (direction == RIGHT && x > center_x);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (within_bound_1 && within_bound_2 && within_bound_3) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *image.GetAddr32(pp::Point(x, y)) = foreground_color;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            continue;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *image.GetAddr32(pp::Point(x, y)) = kBackgroundColor;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return image;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double GetDistance(int point_1_x, int point_1_y,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     int point_2_x, int point_2_y) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sqrt(pow(static_cast<double>(point_1_x - point_2_x), 2) +
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                pow(static_cast<double>(point_1_y - point_2_y), 2));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Log(PP_LogLevel level, const char* format, ...) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    va_list args;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    va_start(args, format);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char buf[512];
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vsnprintf(buf, sizeof(buf) - 1, format, args);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buf[sizeof(buf) - 1] = '\0';
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    va_end(args);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::Var value(buf);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    console_->Log(pp_instance(), level, value.pp_var());
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width_;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int height_;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool mouse_locked_;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Point mouse_movement_;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pending_paint_;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool waiting_for_flush_completion_;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::CompletionCallbackFactory<MyInstance> callback_factory_;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const PPB_Console* console_;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FlashFullscreen flash_fullscreen_;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::Graphics2D device_context_;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This object is the global object representing this plugin library as long
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as it is loaded.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MyModule : public pp::Module {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MyModule() : pp::Module() {}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MyModule() {}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Override CreateInstance to create your customized Instance object.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual pp::Instance* CreateInstance(PP_Instance instance) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new MyInstance(instance);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace pp {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Factory function for your specialization of the Module object.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Module* CreateModule() {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new MyModule();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace pp
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
281