This source file includes following definitions.
- histogram_
- HandleMessage
- MakeBlankImageData
- DrawBar
- PaintAndFlush
- DidFlush
- DidChangeView
- ComputeHistogram
- DrawHistogram
- CreateInstance
- CreateModule
#include <algorithm>
#include <deque>
#include <string>
#include "ppapi/cpp/graphics_2d.h"
#include "ppapi/cpp/image_data.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/var_array_buffer.h"
#include "ppapi/utility/completion_callback_factory.h"
#ifdef WIN32
#undef min
#undef max
#undef PostMessage
#pragma warning(disable : 4355)
#pragma warning(disable : 4351)
#endif
namespace {
const uint32_t kBlue = 0xff4040ffu;
const uint32_t kBlack = 0xff000000u;
const size_t kHistogramSize = 256u;
}
class VarArrayBufferInstance : public pp::Instance {
public:
explicit VarArrayBufferInstance(PP_Instance instance)
: pp::Instance(instance),
callback_factory_(this),
flushing_(false),
histogram_() {}
virtual ~VarArrayBufferInstance() {}
private:
virtual void HandleMessage(const pp::Var& var_message) {
if (var_message.is_array_buffer()) {
pp::VarArrayBuffer buffer(var_message);
ComputeHistogram(buffer);
DrawHistogram();
}
}
pp::ImageData MakeBlankImageData(const pp::Size& size) {
const bool init_to_zero = false;
pp::ImageData image_data =
pp::ImageData(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, init_to_zero);
uint32_t* image_buffer = static_cast<uint32_t*>(image_data.data());
for (int i = 0; i < size.GetArea(); ++i)
image_buffer[i] = kBlack;
return image_data;
}
void DrawBar(uint32_t column, double value, pp::ImageData* image_data) {
assert((value >= 0.0) && (value <= 1.0));
uint32_t* image_buffer = static_cast<uint32_t*>(image_data->data());
const uint32_t image_height = image_data->size().height();
const uint32_t image_width = image_data->size().width();
assert(column < image_width);
int bar_height = static_cast<int>(value * image_height);
for (int i = 0; i < bar_height; ++i) {
uint32_t row = image_height - 1 - i;
image_buffer[row * image_width + column] = kBlue;
}
}
void PaintAndFlush(pp::ImageData* image_data) {
assert(!flushing_);
graphics_2d_context_.ReplaceContents(image_data);
graphics_2d_context_.Flush(
callback_factory_.NewCallback(&VarArrayBufferInstance::DidFlush));
flushing_ = true;
}
void DidFlush(int32_t error_code) {
flushing_ = false;
if (paint_queue_.empty())
return;
pp::ImageData image_data = paint_queue_.front();
paint_queue_.pop_front();
PaintAndFlush(&image_data);
}
virtual void DidChangeView(const pp::View& view) {
if (size_ != view.GetRect().size()) {
size_ = view.GetRect().size();
const bool is_always_opaque = true;
graphics_2d_context_ =
pp::Graphics2D(this, view.GetRect().size(), is_always_opaque);
BindGraphics(graphics_2d_context_);
paint_queue_.clear();
DrawHistogram();
}
}
void ComputeHistogram(pp::VarArrayBuffer& buffer) {
std::fill_n(histogram_, kHistogramSize, 0.0);
uint32_t buffer_size = buffer.ByteLength();
if (buffer_size == 0)
return;
uint8_t* buffer_data = static_cast<uint8_t*>(buffer.Map());
for (uint32_t i = 0; i < buffer_size; ++i)
histogram_[buffer_data[i]] += 1.0;
double max = *std::max_element(histogram_, histogram_ + kHistogramSize);
for (uint32_t i = 0; i < kHistogramSize; ++i)
histogram_[i] /= max;
}
void DrawHistogram() {
pp::ImageData image_data = MakeBlankImageData(size_);
for (int i = 0; i < std::min(static_cast<int>(kHistogramSize),
image_data.size().width());
++i) {
DrawBar(i, histogram_[i], &image_data);
}
if (!flushing_)
PaintAndFlush(&image_data);
else
paint_queue_.push_back(image_data);
}
pp::Graphics2D graphics_2d_context_;
pp::CompletionCallbackFactory<VarArrayBufferInstance> callback_factory_;
std::deque<pp::ImageData> paint_queue_;
pp::Size size_;
bool flushing_;
double histogram_[kHistogramSize];
};
class VarArrayBufferModule : public pp::Module {
public:
VarArrayBufferModule() : pp::Module() {}
virtual ~VarArrayBufferModule() {}
virtual pp::Instance* CreateInstance(PP_Instance instance) {
return new VarArrayBufferInstance(instance);
}
};
namespace pp {
Module* CreateModule() { return new VarArrayBufferModule(); }
}