diff options
author | jhorwich@chromium.org <jhorwich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-09 15:39:22 +0000 |
---|---|---|
committer | jhorwich@chromium.org <jhorwich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-09 15:39:22 +0000 |
commit | f381e90d6f112bc395d7cf743cfa199737041541 (patch) | |
tree | 42507ef60f9021cee0f13971acdb54829434715c /ppapi/examples/scaling | |
parent | e20b88d661f2468003a38cbdaebb0ea3ef63474d (diff) | |
download | chromium_src-f381e90d6f112bc395d7cf743cfa199737041541.zip chromium_src-f381e90d6f112bc395d7cf743cfa199737041541.tar.gz chromium_src-f381e90d6f112bc395d7cf743cfa199737041541.tar.bz2 |
Move HiDPI-related Pepper interfaces to stable
This adds the APIs provided in PPB_View_Dev_0_1 and PP_Graphics2D_Dev_0_1 to
the public Pepper APIs for PPB_View and PPB_Graphics2D.
Includes:
- Change to IDL and generated C headers/shim
- Change to PPAPI to export the 1_1 interfaces
- C++ glue
- Example PPAPI plugin for using HiDPI Pepper APIs
BUG=144071
TEST=Existing (prebuilt) PDF plugin using 1.0 interfaces still works
Review URL: https://codereview.chromium.org/12989006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@193110 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/examples/scaling')
-rw-r--r-- | ppapi/examples/scaling/scaling.cc | 232 | ||||
-rw-r--r-- | ppapi/examples/scaling/scaling.html | 44 |
2 files changed, 276 insertions, 0 deletions
diff --git a/ppapi/examples/scaling/scaling.cc b/ppapi/examples/scaling/scaling.cc new file mode 100644 index 0000000..01d9265 --- /dev/null +++ b/ppapi/examples/scaling/scaling.cc @@ -0,0 +1,232 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#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" + +// When compiling natively on Windows, PostMessage can be #define-d to +// something else. +#ifdef PostMessage +#undef PostMessage +#endif + +// Example plugin to demonstrate usage of pp::View and pp::Graphics2D APIs for +// rendering 2D graphics at device resolution. See Paint() for more details. +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; // We don't care about the position, only the size and scale. + + 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_) { + // The plugin will treat 1 pixel in the device context as 1 device pixel. + // This will set up a properly-sized pp::Graphics2D, and tell Pepper + // to apply the correct scale so the resulting concatenated scale leaves + // each pixel in the device context as one on the display device. + device_context_ = pp::Graphics2D(this, + pp::Size(pixel_width_, pixel_height_), + true); + if (device_scale_ > 0.0f) { + // If SetScale is promoted to pp::Graphics2D, the dc_dev constructor + // can be removed, and this will become the following line instead. + // device_context_.SetScale(1.0f / device_scale_); + device_context_.SetScale(1.0f / device_scale_); + } + } else { + // The plugin will treat 1 pixel in the device context as one DIP. + 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; + + // Painting here will demonstrate a few techniques: + // - painting a thin blue box and cross-hatch to show the finest resolution + // available. + // - painting a 25 DIP (logical pixel) green circle to show how objects of a + // fixed size in DIPs should be scaled if using a high-resolution + // pp::Graphics2D. + // - paiting a 50 CSS pixel red circle to show how objects of a fixed size + // in CSS pixels should be scaled if using a high-resolution + // pp::Graphics2D, as well as how to use the GetCSSScale value properly. + + // Painting in "DIP resolution" mode (|using_device_pixels_| false) will + // demonstrate how unscaled graphics would look, even on a high-DPI device. + // Painting in "device resolution" mode (|using_device_pixels_| true) will + // show how scaled graphics would look crisper on a high-DPI device, in + // comparison to using unscaled graphics. Both modes should look identical + // when displayed on a non-high-DPI device (window.devicePixelRatio == 1). + // Toggling between "DIP resolution" mode and "device resolution" mode + // should not change the sizes of the circles. + + // Changing the browser zoom level should cause the CSS circle to zoom, but + // not the DIP-sized circle. + + // All painting here does not use any anti-aliasing. + 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_; +}; + +// This object is the global object representing this plugin library as long as +// it is loaded. +class MyModule : public pp::Module { + public: + MyModule() : pp::Module() {} + virtual ~MyModule() {} + + // Override CreateInstance to create your customized Instance object. + virtual pp::Instance* CreateInstance(PP_Instance instance) { + return new MyInstance(instance); + } +}; + +namespace pp { + +// Factory function for your specialization of the Module object. +Module* CreateModule() { + return new MyModule(); +} + +} // namespace pp diff --git a/ppapi/examples/scaling/scaling.html b/ppapi/examples/scaling/scaling.html new file mode 100644 index 0000000..983cbd6 --- /dev/null +++ b/ppapi/examples/scaling/scaling.html @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<html> + <!-- + Copyright (c) 2013 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. + --> +<head> + <title>Pepper 2D Scaling Example</title> + <script> + + function HandleMessage(message_event) { + if (message_event.data) { + console.log(message_event.data); + } + } + + function AddListener() { + var plugin = document.getElementById("plugin"); + plugin.addEventListener("message", HandleMessage, false); + } + document.addEventListener("DOMContentLoaded", AddListener, false); + </script> +</head> + +<body> + <script> + function SendString(str) { + var plugin = document.getElementById("plugin"); + plugin.postMessage(str); + } + </script> + + <button onclick="SendString('dip')">DIP Res</button> + <button onclick="SendString('device')">Device Res</button> + <button onclick="SendString('metrics')">Metrics</button> + <hr> + <object id="plugin" type="application/x-ppapi-example-2d-scaling" width="200" height="200" border="2px"></object><br> +Blue lines are one pixel thin, at either DIP or device resolution.<br> +Green circle is 25 DIPs in radius.<br> +Red circle is 50 CSS pixels in radius.<br> +Mouse clicks in the plugin will generate a message in the JS console.<br> + <hr> +</body> |