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