summaryrefslogtreecommitdiffstats
path: root/ppapi/examples/scaling
diff options
context:
space:
mode:
authorjhorwich@chromium.org <jhorwich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-09 15:39:22 +0000
committerjhorwich@chromium.org <jhorwich@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-09 15:39:22 +0000
commitf381e90d6f112bc395d7cf743cfa199737041541 (patch)
tree42507ef60f9021cee0f13971acdb54829434715c /ppapi/examples/scaling
parente20b88d661f2468003a38cbdaebb0ea3ef63474d (diff)
downloadchromium_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.cc232
-rw-r--r--ppapi/examples/scaling/scaling.html44
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>