1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <math.h>
6
7#include <algorithm>
8
9#include "ppapi/cpp/graphics_2d.h"
10#include "ppapi/cpp/image_data.h"
11#include "ppapi/cpp/instance.h"
12#include "ppapi/cpp/module.h"
13#include "ppapi/cpp/rect.h"
14#include "ppapi/cpp/var.h"
15#include "ppapi/utility/completion_callback_factory.h"
16#include "ppapi/utility/graphics/paint_manager.h"
17
18static const int kSquareSpacing = 98;
19static const int kSquareSize = 5;
20
21static const int kAdvanceXPerFrame = 0;
22static const int kAdvanceYPerFrame = -3;
23
24void FillRect(pp::ImageData* image, const pp::Rect& rect, uint32_t color) {
25  for (int y = std::max(0, rect.y());
26       y < std::min(image->size().height(), rect.bottom());
27       y++) {
28    for (int x = std::max(0, rect.x());
29         x < std::min(image->size().width(), rect.right());
30         x++)
31      *image->GetAddr32(pp::Point(x, y)) = color;
32  }
33}
34
35class MyInstance : public pp::Instance, public pp::PaintManager::Client {
36 public:
37  MyInstance(PP_Instance instance)
38      : pp::Instance(instance),
39        current_step_(0),
40        kicked_off_(false) {
41    factory_.Initialize(this);
42    paint_manager_.Initialize(this, this, false);
43  }
44
45  virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
46    paint_manager_.SetSize(position.size());
47  }
48
49  void OnTimer(int32_t) {
50    pp::Module::Get()->core()->CallOnMainThread(
51        16, factory_.NewCallback(&MyInstance::OnTimer), 0);
52    // The scroll and the invalidate will do the same thing in this example,
53    // but the invalidate will cause a large repaint, whereas the scroll will
54    // be faster and cause a smaller repaint.
55#if 1
56    paint_manager_.ScrollRect(pp::Rect(paint_manager_.graphics().size()),
57                              pp::Point(kAdvanceXPerFrame, kAdvanceYPerFrame));
58#else
59    paint_manager_.Invalidate();
60#endif
61    current_step_++;
62  }
63
64 private:
65  // PaintManager::Client implementation.
66  virtual bool OnPaint(pp::Graphics2D& graphics,
67                       const std::vector<pp::Rect>& paint_rects,
68                       const pp::Rect& paint_bounds) {
69    if (!kicked_off_) {
70      pp::Module::Get()->core()->CallOnMainThread(
71          16, factory_.NewCallback(&MyInstance::OnTimer), 0);
72      kicked_off_ = true;
73    }
74
75    // Paint the background.
76    pp::ImageData updated_image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
77                                paint_bounds.size(), false);
78    FillRect(&updated_image, pp::Rect(updated_image.size()), 0xFF8888FF);
79
80    int x_origin = current_step_ * kAdvanceXPerFrame;
81    int y_origin = current_step_ * kAdvanceYPerFrame;
82
83    int x_offset = x_origin % kSquareSpacing;
84    int y_offset = y_origin % kSquareSpacing;
85
86    for (int ys = 0; ys < graphics.size().height() / kSquareSpacing + 2; ys++) {
87      for (int xs = 0; xs < graphics.size().width() / kSquareSpacing + 2;
88           xs++) {
89        int x = xs * kSquareSpacing + x_offset - paint_bounds.x();
90        int y = ys * kSquareSpacing + y_offset - paint_bounds.y();
91        FillRect(&updated_image, pp::Rect(x, y, kSquareSize, kSquareSize),
92                 0xFF000000);
93      }
94    }
95    graphics.PaintImageData(updated_image, paint_bounds.point());
96    return true;
97  }
98
99  pp::CompletionCallbackFactory<MyInstance> factory_;
100
101  pp::PaintManager paint_manager_;
102
103  int current_step_;
104
105  bool kicked_off_;
106};
107
108class MyModule : public pp::Module {
109 public:
110  virtual pp::Instance* CreateInstance(PP_Instance instance) {
111    return new MyInstance(instance);
112  }
113};
114
115namespace pp {
116
117// Factory function for your specialization of the Module object.
118Module* CreateModule() {
119  return new MyModule();
120}
121
122}  // namespace pp
123