18bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 28bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 38bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// found in the LICENSE file. 48bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 58bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include <stdio.h> 68bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include <stdlib.h> 78bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "ppapi/c/ppb_image_data.h" 98bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "ppapi/cpp/graphics_2d.h" 108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "ppapi/cpp/image_data.h" 118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "ppapi/cpp/input_event.h" 128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "ppapi/cpp/instance.h" 138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "ppapi/cpp/module.h" 148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "ppapi/cpp/point.h" 158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "ppapi/utility/completion_callback_factory.h" 168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#ifdef WIN32 188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#undef PostMessage 198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Allow 'this' in initializer list 208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#pragma warning(disable : 4355) 218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif 228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace { 248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)static const int kMouseRadius = 20; 268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)uint8_t RandUint8(uint8_t min, uint8_t max) { 288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) uint64_t r = rand(); 298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) uint8_t result = static_cast<uint8_t>(r * (max - min + 1) / RAND_MAX) + min; 308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return result; 318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)uint32_t MakeColor(uint8_t r, uint8_t g, uint8_t b) { 348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) uint8_t a = 255; 358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) PP_ImageDataFormat format = pp::ImageData::GetNativeImageDataFormat(); 368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (format == PP_IMAGEDATAFORMAT_BGRA_PREMUL) { 378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return (a << 24) | (r << 16) | (g << 8) | b; 388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } else { 398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return (a << 24) | (b << 16) | (g << 8) | r; 408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} // namespace 448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)class Graphics2DInstance : public pp::Instance { 468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) public: 478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) explicit Graphics2DInstance(PP_Instance instance) 488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : pp::Instance(instance), 498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) callback_factory_(this), 508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) mouse_down_(false), 518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) buffer_(NULL) {} 528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ~Graphics2DInstance() { delete[] buffer_; } 548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { 568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE); 578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) unsigned int seed = 1; 598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) srand(seed); 608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) CreatePalette(); 618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return true; 628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) virtual void DidChangeView(const pp::View& view) { 658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) pp::Size new_size = view.GetRect().size(); 668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!CreateContext(new_size)) 688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // When flush_context_ is null, it means there is no Flush callback in 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // flight. This may have happened if the context was not created 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // successfully, or if this is the first call to DidChangeView (when the 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // module first starts). In either case, start the main loop. 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (flush_context_.is_null()) 758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) MainLoop(0); 768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) virtual bool HandleInputEvent(const pp::InputEvent& event) { 798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!buffer_) 808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return true; 818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (event.GetType() == PP_INPUTEVENT_TYPE_MOUSEDOWN || 838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) event.GetType() == PP_INPUTEVENT_TYPE_MOUSEMOVE) { 848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) pp::MouseInputEvent mouse_event(event); 858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_NONE) 878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return true; 888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) mouse_ = mouse_event.GetPosition(); 908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) mouse_down_ = true; 918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (event.GetType() == PP_INPUTEVENT_TYPE_MOUSEUP) 948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) mouse_down_ = false; 958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return true; 978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) private: 1008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) void CreatePalette() { 1018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (int i = 0; i < 64; ++i) { 1028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Black -> Red 1038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) palette_[i] = MakeColor(i * 2, 0, 0); 1048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) palette_[i + 64] = MakeColor(128 + i * 2, 0, 0); 1058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Red -> Yellow 1068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) palette_[i + 128] = MakeColor(255, i * 4, 0); 1078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Yellow -> White 1088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) palette_[i + 192] = MakeColor(255, 255, i * 4); 1098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bool CreateContext(const pp::Size& new_size) { 1138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const bool kIsAlwaysOpaque = true; 1148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) context_ = pp::Graphics2D(this, new_size, kIsAlwaysOpaque); 1158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!BindGraphics(context_)) { 1168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) fprintf(stderr, "Unable to bind 2d context!\n"); 1178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) context_ = pp::Graphics2D(); 1188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 1198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Allocate a buffer of palette entries of the same size as the new context. 1228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) buffer_ = new uint8_t[new_size.width() * new_size.height()]; 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_ = new_size; 1248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return true; 1268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) void Update() { 1298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Old-school fire technique cribbed from 1308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // http://ionicsolutions.net/2011/12/30/demo-fire-effect/ 1318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UpdateCoals(); 1328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DrawMouse(); 1338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UpdateFlames(); 1348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) void UpdateCoals() { 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int width = size_.width(); 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int height = size_.height(); 1398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) size_t span = 0; 1408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Draw two rows of random values at the bottom. 1428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (int y = height - 2; y < height; ++y) { 1438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) size_t offset = y * width; 1448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (int x = 0; x < width; ++x) { 1458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // On a random chance, draw some longer strips of brighter colors. 1468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (span || RandUint8(1, 4) == 1) { 1478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!span) 1488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) span = RandUint8(10, 20); 1498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) buffer_[offset + x] = RandUint8(128, 255); 1508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) span--; 1518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } else { 1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) buffer_[offset + x] = RandUint8(32, 96); 1538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) void UpdateFlames() { 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int width = size_.width(); 160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int height = size_.height(); 1618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (int y = 1; y < height - 1; ++y) { 1628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) size_t offset = y * width; 1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (int x = 1; x < width - 1; ++x) { 1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int sum = 0; 1658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) sum += buffer_[offset - width + x - 1]; 1668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) sum += buffer_[offset - width + x + 1]; 167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) sum += buffer_[offset + x - 1]; 168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) sum += buffer_[offset + x + 1]; 1698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) sum += buffer_[offset + width + x - 1]; 1708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) sum += buffer_[offset + width + x]; 1718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) sum += buffer_[offset + width + x + 1]; 1728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) buffer_[offset - width + x] = sum / 7; 1738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) void DrawMouse() { 1788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!mouse_down_) 1798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return; 1808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int width = size_.width(); 182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int height = size_.height(); 1838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Draw a circle at the mouse position. 1858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int radius = kMouseRadius; 1868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int cx = mouse_.x(); 1878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int cy = mouse_.y(); 1888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int minx = cx - radius <= 0 ? 1 : cx - radius; 1898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int maxx = cx + radius >= width ? width - 1 : cx + radius; 1908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int miny = cy - radius <= 0 ? 1 : cy - radius; 1918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int maxy = cy + radius >= height ? height - 1 : cy + radius; 1928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (int y = miny; y < maxy; ++y) { 1938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (int x = minx; x < maxx; ++x) { 194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if ((x - cx) * (x - cx) + (y - cy) * (y - cy) < radius * radius) 1958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) buffer_[y * width + x] = RandUint8(192, 255); 1968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 1998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 2008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) void Paint() { 201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // See the comment above the call to ReplaceContents below. 202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PP_ImageDataFormat format = pp::ImageData::GetNativeImageDataFormat(); 203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const bool kDontInitToZero = false; 204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pp::ImageData image_data(this, format, size_, kDontInitToZero); 205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint32_t* data = static_cast<uint32_t*>(image_data.data()); 207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!data) 208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint32_t num_pixels = size_.width() * size_.height(); 2118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) size_t offset = 0; 2128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (uint32_t i = 0; i < num_pixels; ++i) { 2138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) data[offset] = palette_[buffer_[offset]]; 2148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) offset++; 2158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Using Graphics2D::ReplaceContents is the fastest way to update the 218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // entire canvas every frame. According to the documentation: 219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // 220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Normally, calling PaintImageData() requires that the browser copy 221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // the pixels out of the image and into the graphics context's backing 222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // store. This function replaces the graphics context's backing store 223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // with the given image, avoiding the copy. 224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // 225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // In the case of an animation, you will want to allocate a new image for 226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // the next frame. It is best if you wait until the flush callback has 227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // executed before allocating this bitmap. This gives the browser the 228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // option of caching the previous backing store and handing it back to 229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // you (assuming the sizes match). In the optimal case, this means no 230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // bitmaps are allocated during the animation, and the backing store and 231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // "front buffer" (which the module is painting into) are just being 232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // swapped back and forth. 233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // 234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) context_.ReplaceContents(&image_data); 2358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 2368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 2378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) void MainLoop(int32_t) { 238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (context_.is_null()) { 239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // The current Graphics2D context is null, so updating and rendering is 240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // pointless. Set flush_context_ to null as well, so if we get another 241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // DidChangeView call, the main loop is started again. 242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) flush_context_ = context_; 243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Update(); 2478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Paint(); 248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Store a reference to the context that is being flushed; this ensures 249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // the callback is called, even if context_ changes before the flush 250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // completes. 251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) flush_context_ = context_; 2528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) context_.Flush( 2538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) callback_factory_.NewCallback(&Graphics2DInstance::MainLoop)); 2548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 2558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 2568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) pp::CompletionCallbackFactory<Graphics2DInstance> callback_factory_; 2578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) pp::Graphics2D context_; 258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pp::Graphics2D flush_context_; 259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pp::Size size_; 2608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) pp::Point mouse_; 2618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bool mouse_down_; 2628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) uint8_t* buffer_; 2638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) uint32_t palette_[256]; 2648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}; 2658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 2668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)class Graphics2DModule : public pp::Module { 2678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) public: 2688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Graphics2DModule() : pp::Module() {} 2698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) virtual ~Graphics2DModule() {} 2708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 2718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) virtual pp::Instance* CreateInstance(PP_Instance instance) { 2728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return new Graphics2DInstance(instance); 2738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 2748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}; 2758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 2768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace pp { 2778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)Module* CreateModule() { return new Graphics2DModule(); } 2788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} // namespace pp 279