This source file includes following definitions.
- using_device_pixels_
- DidChangeView
- HandleInputEvent
- HandleMessage
- HandleMouseDown
- SetupGraphics
- Paint
- OnFlush
- CreateInstance
- CreateModule
#include <sstream>
#include "ppapi/c/pp_errors.h"
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/graphics_2d.h"
#include "ppapi/cpp/image_data.h"
#include "ppapi/cpp/input_event.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/rect.h"
#include "ppapi/cpp/var.h"
#include "ppapi/utility/completion_callback_factory.h"
#ifdef PostMessage
#undef PostMessage
#endif
class MyInstance : public pp::Instance {
public:
explicit MyInstance(PP_Instance instance)
: pp::Instance(instance),
width_(0),
height_(0),
pixel_width_(0),
pixel_height_(0),
device_scale_(1.0f),
css_scale_(1.0f),
using_device_pixels_(true) {
RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE |
PP_INPUTEVENT_CLASS_KEYBOARD);
}
virtual void DidChangeView(const pp::View& view) {
pp::Rect view_rect = view.GetRect();
if (view_rect.width() == width_ &&
view_rect.height() == height_ &&
view.GetDeviceScale() == device_scale_ &&
view.GetCSSScale() == css_scale_)
return;
width_ = view_rect.width();
height_ = view_rect.height();
device_scale_ = view.GetDeviceScale();
css_scale_ = view.GetCSSScale();
pixel_width_ = width_ * device_scale_;
pixel_height_ = height_ * device_scale_;
SetupGraphics();
}
virtual bool HandleInputEvent(const pp::InputEvent& event) {
switch (event.GetType()) {
case PP_INPUTEVENT_TYPE_MOUSEDOWN:
HandleMouseDown(event);
return true;
default:
return false;
}
}
virtual void HandleMessage(const pp::Var& message_data) {
if (message_data.is_string()) {
std::string str = message_data.AsString();
if (str == "dip") {
if (using_device_pixels_) {
using_device_pixels_ = false;
SetupGraphics();
}
} else if (str == "device") {
if (!using_device_pixels_) {
using_device_pixels_ = true;
SetupGraphics();
}
} else if (str == "metrics") {
std::stringstream stream;
stream << "DIP (" << width_ << ", " << height_ << "), device pixels=("
<< pixel_width_ << ", " << pixel_height_ <<"), device_scale="
<< device_scale_ <<", css_scale=" << css_scale_;
PostMessage(stream.str());
}
}
}
private:
void HandleMouseDown(const pp::InputEvent& event) {
pp::MouseInputEvent mouse_event(event);
pp::Point position(mouse_event.GetPosition());
pp::Point position_device(position.x() * device_scale_,
position.y() * device_scale_);
std::stringstream stream;
stream << "Mousedown at DIP (" << position.x() << ", " << position.y()
<< "), device pixel (" << position_device.x() << ", "
<< position_device.y() << ")";
if (css_scale_ > 0.0f) {
pp::Point position_css(position.x() / css_scale_,
position.y() / css_scale_);
stream << ", CSS pixel (" << position_css.x() << ", " << position_css.y()
<<")";
} else {
stream <<", unknown CSS pixel. css_scale_=" << css_scale_;
}
PostMessage(stream.str());
}
void SetupGraphics() {
if (using_device_pixels_) {
device_context_ = pp::Graphics2D(this,
pp::Size(pixel_width_, pixel_height_),
true);
if (device_scale_ > 0.0f) {
device_context_.SetScale(1.0f / device_scale_);
}
} else {
device_context_ = pp::Graphics2D(this, pp::Size(width_, height_), true);
}
BindGraphics(device_context_);
Paint();
}
void Paint() {
int width = using_device_pixels_ ? pixel_width_ : width_;
int height = using_device_pixels_ ? pixel_height_ : height_;
pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
pp::Size(width, height), false);
if (image.is_null())
return;
float circle_1_radius = 25;
if (using_device_pixels_)
circle_1_radius *= device_scale_;
float circle_2_radius = 50 * css_scale_;
if (using_device_pixels_)
circle_2_radius *= device_scale_;
for (int y = 0; y < height; ++y) {
char* row = static_cast<char*>(image.data()) + (y * image.stride());
uint32_t* pixel = reinterpret_cast<uint32_t*>(row);
for (int x = 0; x < width; ++x) {
int dx = (width / 2) - x;
int dy = (height / 2) - y;
float dist_squared = (dx * dx) + (dy * dy);
if (x == 0 || y == 0 || x == width - 1 || y == width - 1 || x == y ||
width - x - 1 == y) {
*pixel++ = 0xFF0000FF;
} else if (dist_squared < circle_1_radius * circle_1_radius) {
*pixel++ = 0xFF00FF00;
} else if (dist_squared < circle_2_radius * circle_2_radius) {
*pixel++ = 0xFFFF0000;
} else {
*pixel++ = 0xFF000000;
}
}
}
device_context_.ReplaceContents(&image);
device_context_.Flush(pp::CompletionCallback(&OnFlush, this));
}
static void OnFlush(void* user_data, int32_t result) {}
pp::Graphics2D device_context_;
int width_;
int height_;
int pixel_width_;
int pixel_height_;
float device_scale_;
float css_scale_;
bool using_device_pixels_;
};
class MyModule : public pp::Module {
public:
MyModule() : pp::Module() {}
virtual ~MyModule() {}
virtual pp::Instance* CreateInstance(PP_Instance instance) {
return new MyInstance(instance);
}
};
namespace pp {
Module* CreateModule() {
return new MyModule();
}
}