<commit_before>// Copyright (c) 2011 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 "ppapi/tests/test_graphics_2d.h"

#include <stdlib.h>
#include <string.h>

#include "ppapi/c/dev/ppb_testing_dev.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_graphics_2d.h"
#include "ppapi/cpp/common.h"
#include "ppapi/cpp/completion_callback.h"
#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/rect.h"
#include "ppapi/tests/testing_instance.h"

REGISTER_TEST_CASE(Graphics2D);

namespace {

// A NOP flush callback for use in various tests.
void FlushCallbackNOP(void* data, int32_t result) {
}

void FlushCallbackQuitMessageLoop(void* data, int32_t result) {
  reinterpret_cast<TestGraphics2D*>(data)->QuitMessageLoop();
}

}  // namespace

bool TestGraphics2D::Init() {
  graphics_2d_interface_ = reinterpret_cast<PPB_Graphics2D const*>(
      pp::Module::Get()->GetBrowserInterface(PPB_GRAPHICS_2D_INTERFACE));
  image_data_interface_ = reinterpret_cast<PPB_ImageData const*>(
      pp::Module::Get()->GetBrowserInterface(PPB_IMAGEDATA_INTERFACE));
  return graphics_2d_interface_ && image_data_interface_ &&
         InitTestingInterface();
}

void TestGraphics2D::RunTest() {
  RUN_TEST(InvalidResource);
  RUN_TEST(InvalidSize);
  RUN_TEST(Humongous);
  RUN_TEST(InitToZero);
  RUN_TEST(Describe);
  RUN_TEST_FORCEASYNC_AND_NOT(Paint);
  // RUN_TEST_FORCEASYNC_AND_NOT(Scroll);  // TODO(brettw) implement.
  RUN_TEST_FORCEASYNC_AND_NOT(Replace);
  RUN_TEST_FORCEASYNC_AND_NOT(Flush);
}

void TestGraphics2D::QuitMessageLoop() {
  testing_interface_->QuitMessageLoop(instance_->pp_instance());
}

bool TestGraphics2D::ReadImageData(const pp::Graphics2D& dc,
                                   pp::ImageData* image,
                                   const pp::Point& top_left) const {
  return pp::PPBoolToBool(testing_interface_->ReadImageData(
      dc.pp_resource(),
      image->pp_resource(),
      &top_left.pp_point()));
}

bool TestGraphics2D::IsDCUniformColor(const pp::Graphics2D& dc,
                                      uint32_t color) const {
  pp::ImageData readback(instance_, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                         dc.size(), false);
  if (readback.is_null())
    return false;
  if (!ReadImageData(dc, &readback, pp::Point(0, 0)))
    return false;
  return IsSquareInImage(readback, 0, pp::Rect(dc.size()), color);
}

bool TestGraphics2D::FlushAndWaitForDone(pp::Graphics2D* context) {
  int32_t flags = (force_async_ ? 0 : PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
  pp::CompletionCallback cc(&FlushCallbackQuitMessageLoop, this, flags);
  int32_t rv = context->Flush(cc);
  if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
    return false;
  if (rv == PP_OK)
    return true;
  if (rv != PP_OK_COMPLETIONPENDING)
    return false;
  testing_interface_->RunMessageLoop(instance_->pp_instance());
  return true;
}

void TestGraphics2D::FillRectInImage(pp::ImageData* image,
                                     const pp::Rect& rect,
                                     uint32_t color) const {
  for (int y = rect.y(); y < rect.bottom(); y++) {
    uint32_t* row = image->GetAddr32(pp::Point(rect.x(), y));
    for (int pixel = 0; pixel < rect.width(); pixel++)
      row[pixel] = color;
  }
}

void TestGraphics2D::FillImageWithGradient(pp::ImageData* image) const {
  for (int y = 0; y < image->size().height(); y++) {
    uint32_t red = ((y * 256) / image->size().height()) & 0xFF;
    for (int x = 0; x < image->size().width(); x++) {
      uint32_t green = ((x * 256) / image->size().width()) & 0xFF;
      uint32_t blue = ((red + green) / 2) & 0xFF;
      uint32_t* pixel = image->GetAddr32(pp::Point(x, y));
      *pixel = (blue << 24) | (green << 16) | (red << 8);
    }
  }
}

bool TestGraphics2D::CompareImages(const pp::ImageData& image1,
                                   const pp::ImageData& image2) {
  return CompareImageRect(
      image1, pp::Rect(0, 0, image1.size().width(), image1.size().height()),
      image2, pp::Rect(0, 0, image2.size().width(), image2.size().height()));
}

bool TestGraphics2D::CompareImageRect(const pp::ImageData& image1,
                                      const pp::Rect& rc1,
                                      const pp::ImageData& image2,
                                      const pp::Rect& rc2) const {
  if (rc1.width() != rc2.width() || rc1.height() != rc2.height())
    return false;

  for (int y = 0; y < rc1.height(); y++) {
    for (int x = 0; x < rc1.width(); x++) {
      if (*(image1.GetAddr32(pp::Point(rc1.x() + x, rc1.y() + y))) !=
          *(image2.GetAddr32(pp::Point(rc2.x() + x, rc2.y() + y))))
        return false;
    }
  }
  return true;
}

bool TestGraphics2D::IsSquareInImage(const pp::ImageData& image_data,
                                     uint32_t background_color,
                                     const pp::Rect& square,
                                     uint32_t square_color) const {
  for (int y = 0; y < image_data.size().height(); y++) {
    for (int x = 0; x < image_data.size().width(); x++) {
      uint32_t pixel = *image_data.GetAddr32(pp::Point(x, y));
      uint32_t desired_color;
      if (square.Contains(x, y))
        desired_color = square_color;
      else
        desired_color = background_color;
      if (pixel != desired_color)
        return false;
    }
  }
  return true;
}

bool TestGraphics2D::IsSquareInDC(const pp::Graphics2D& dc,
                                  uint32_t background_color,
                                  const pp::Rect& square,
                                  uint32_t square_color) const {
  pp::ImageData readback(instance_, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                         dc.size(), false);
  if (readback.is_null())
    return false;
  if (!ReadImageData(dc, &readback, pp::Point(0, 0)))
    return false;
  return IsSquareInImage(readback, background_color, square, square_color);
}

// Test all the functions with an invalid handle. Most of these just check for
// a crash since the browser don't return a value.
std::string TestGraphics2D::TestInvalidResource() {
  pp::Graphics2D null_context;
  pp::ImageData image(instance_, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                      pp::Size(16, 16), true);

  // Describe.
  PP_Size size;
  PP_Bool opaque;
  graphics_2d_interface_->Describe(image.pp_resource(), &size, &opaque);
  graphics_2d_interface_->Describe(null_context.pp_resource(),
                                   &size, &opaque);

  // PaintImageData.
  PP_Point zero_zero;
  zero_zero.x = 0;
  zero_zero.y = 0;
  graphics_2d_interface_->PaintImageData(image.pp_resource(),
                                         image.pp_resource(),
                                         &zero_zero, NULL);
  graphics_2d_interface_->PaintImageData(null_context.pp_resource(),
                                         image.pp_resource(),
                                         &zero_zero, NULL);

  // Scroll.
  PP_Point zero_ten;
  zero_ten.x = 0;
  zero_ten.y = 10;
  graphics_2d_interface_->Scroll(image.pp_resource(), NULL, &zero_ten);
  graphics_2d_interface_->Scroll(null_context.pp_resource(),
                                 NULL, &zero_ten);

  // ReplaceContents.
  graphics_2d_interface_->ReplaceContents(image.pp_resource(),
                                          image.pp_resource());
  graphics_2d_interface_->ReplaceContents(null_context.pp_resource(),
                                          image.pp_resource());

  // Flush.
  if (graphics_2d_interface_->Flush(
          image.pp_resource(),
          PP_MakeOptionalCompletionCallback(&FlushCallbackNOP, NULL)) == PP_OK)
    return "Flush succeeded with a different resource";
  if (graphics_2d_interface_->Flush(
          null_context.pp_resource(),
          PP_MakeOptionalCompletionCallback(&FlushCallbackNOP, NULL)) == PP_OK)
    return "Flush succeeded with a NULL resource";

  // ReadImageData.
  if (testing_interface_->ReadImageData(image.pp_resource(),
                                        image.pp_resource(),
                                        &zero_zero))
    return "ReadImageData succeeded with a different resource";
  if (testing_interface_->ReadImageData(null_context.pp_resource(),
                                        image.pp_resource(),
                                        &zero_zero))
    return "ReadImageData succeeded with a NULL resource";

  PASS();
}

std::string TestGraphics2D::TestInvalidSize() {
  pp::Graphics2D a(instance_, pp::Size(16, 0), false);
  if (!a.is_null())
    return "0 height accepted";

  pp::Graphics2D b(instance_, pp::Size(0, 16), false);
  if (!b.is_null())
    return "0 width accepted";

  // Need to use the C API since pp::Size prevents negative sizes.
  PP_Size size;
  size.width = 16;
  size.height = -16;
  ASSERT_FALSE(!!graphics_2d_interface_->Create(
      instance_->pp_instance(), &size, PP_FALSE));

  size.width = -16;
  size.height = 16;
  ASSERT_FALSE(!!graphics_2d_interface_->Create(
      instance_->pp_instance(), &size, PP_FALSE));

  PASS();
}

std::string TestGraphics2D::TestHumongous() {
  pp::Graphics2D a(instance_, pp::Size(100000, 100000), false);
  if (!a.is_null())
    return "Humongous device created";
  PASS();
}

std::string TestGraphics2D::TestInitToZero() {
  const int w = 15, h = 17;
  pp::Graphics2D dc(instance_, pp::Size(w, h), false);
  if (dc.is_null())
    return "Failure creating a boring device";

  // Make an image with nonzero data in it (so we can test that zeros were
  // actually read versus ReadImageData being a NOP).
  pp::ImageData image(instance_, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                      pp::Size(w, h), true);
  if (image.is_null())
    return "Failure to allocate an image";
  memset(image.data(), 0xFF, image.stride() * image.size().height() * 4);

  // Read out the initial data from the device & check.
  if (!ReadImageData(dc, &image, pp::Point(0, 0)))
    return "Couldn't read image data";
  if (!IsSquareInImage(image, 0, pp::Rect(0, 0, w, h), 0))
    return "Got a nonzero pixel";

  PASS();
}

std::string TestGraphics2D::TestDescribe() {
  const int w = 15, h = 17;
  const bool always_opaque = ::rand() % 2 ? true : false;
  pp::Graphics2D dc(instance_, pp::Size(w, h), always_opaque);
  if (dc.is_null())
    return "Failure creating a boring device";

  PP_Size size;
  size.width = -1;
  size.height = -1;
  PP_Bool is_always_opaque = PP_FALSE;
  if (!graphics_2d_interface_->Describe(dc.pp_resource(), &size,
                                        &is_always_opaque))
    return "Describe failed";
  if (size.width != w || size.height != h ||
      is_always_opaque != pp::BoolToPPBool(always_opaque))
    return "Mismatch of data.";

  PASS();
}

std::string TestGraphics2D::TestPaint() {
  const int w = 15, h = 17;
  pp::Graphics2D dc(instance_, pp::Size(w, h), false);
  if (dc.is_null())
    return "Failure creating a boring device";

  // Make sure the device background is 0.
  if (!IsDCUniformColor(dc, 0))
    return "Bad initial color";

  // Fill the backing store with white.
  const uint32_t background_color = 0xFFFFFFFF;
  pp::ImageData background(instance_, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                           pp::Size(w, h), false);
  FillRectInImage(&background, pp::Rect(0, 0, w, h), background_color);
  dc.PaintImageData(background, pp::Point(0, 0));
  if (!FlushAndWaitForDone(&dc))
    return "Couldn't flush to fill backing store";

  // Make an image to paint with that's opaque white and enqueue a paint.
  const int fill_w = 2, fill_h = 3;
  pp::ImageData fill(instance_, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                     pp::Size(fill_w, fill_h), true);
  if (fill.is_null())
    return "Failure to allocate fill image";
  FillRectInImage(&fill, pp::Rect(fill.size()), background_color);<commit_msg>Fix some uses of PPBoolToBool and BoolToPPBool that I either missed in the previous pass or got added since then.<commit_after>// Copyright (c) 2011 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 "ppapi/tests/test_graphics_2d.h"

#include <stdlib.h>
#include <string.h>

#include "ppapi/c/dev/ppb_testing_dev.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_graphics_2d.h"
#include "ppapi/cpp/common.h"
#include "ppapi/cpp/completion_callback.h"
#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/rect.h"
#include "ppapi/tests/testing_instance.h"

REGISTER_TEST_CASE(Graphics2D);

namespace {

// A NOP flush callback for use in various tests.
void FlushCallbackNOP(void* data, int32_t result) {
}

void FlushCallbackQuitMessageLoop(void* data, int32_t result) {
  reinterpret_cast<TestGraphics2D*>(data)->QuitMessageLoop();
}

}  // namespace

bool TestGraphics2D::Init() {
  graphics_2d_interface_ = reinterpret_cast<PPB_Graphics2D const*>(
      pp::Module::Get()->GetBrowserInterface(PPB_GRAPHICS_2D_INTERFACE));
  image_data_interface_ = reinterpret_cast<PPB_ImageData const*>(
      pp::Module::Get()->GetBrowserInterface(PPB_IMAGEDATA_INTERFACE));
  return graphics_2d_interface_ && image_data_interface_ &&
         InitTestingInterface();
}

void TestGraphics2D::RunTest() {
  RUN_TEST(InvalidResource);
  RUN_TEST(InvalidSize);
  RUN_TEST(Humongous);
  RUN_TEST(InitToZero);
  RUN_TEST(Describe);
  RUN_TEST_FORCEASYNC_AND_NOT(Paint);
  // RUN_TEST_FORCEASYNC_AND_NOT(Scroll);  // TODO(brettw) implement.
  RUN_TEST_FORCEASYNC_AND_NOT(Replace);
  RUN_TEST_FORCEASYNC_AND_NOT(Flush);
}

void TestGraphics2D::QuitMessageLoop() {
  testing_interface_->QuitMessageLoop(instance_->pp_instance());
}

bool TestGraphics2D::ReadImageData(const pp::Graphics2D& dc,
                                   pp::ImageData* image,
                                   const pp::Point& top_left) const {
  return PP_ToBool(testing_interface_->ReadImageData(
      dc.pp_resource(),
      image->pp_resource(),
      &top_left.pp_point()));
}

bool TestGraphics2D::IsDCUniformColor(const pp::Graphics2D& dc,
                                      uint32_t color) const {
  pp::ImageData readback(instance_, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                         dc.size(), false);
  if (readback.is_null())
    return false;
  if (!ReadImageData(dc, &readback, pp::Point(0, 0)))
    return false;
  return IsSquareInImage(readback, 0, pp::Rect(dc.size()), color);
}

bool TestGraphics2D::FlushAndWaitForDone(pp::Graphics2D* context) {
  int32_t flags = (force_async_ ? 0 : PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
  pp::CompletionCallback cc(&FlushCallbackQuitMessageLoop, this, flags);
  int32_t rv = context->Flush(cc);
  if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
    return false;
  if (rv == PP_OK)
    return true;
  if (rv != PP_OK_COMPLETIONPENDING)
    return false;
  testing_interface_->RunMessageLoop(instance_->pp_instance());
  return true;
}

void TestGraphics2D::FillRectInImage(pp::ImageData* image,
                                     const pp::Rect& rect,
                                     uint32_t color) const {
  for (int y = rect.y(); y < rect.bottom(); y++) {
    uint32_t* row = image->GetAddr32(pp::Point(rect.x(), y));
    for (int pixel = 0; pixel < rect.width(); pixel++)
      row[pixel] = color;
  }
}

void TestGraphics2D::FillImageWithGradient(pp::ImageData* image) const {
  for (int y = 0; y < image->size().height(); y++) {
    uint32_t red = ((y * 256) / image->size().height()) & 0xFF;
    for (int x = 0; x < image->size().width(); x++) {
      uint32_t green = ((x * 256) / image->size().width()) & 0xFF;
      uint32_t blue = ((red + green) / 2) & 0xFF;
      uint32_t* pixel = image->GetAddr32(pp::Point(x, y));
      *pixel = (blue << 24) | (green << 16) | (red << 8);
    }
  }
}

bool TestGraphics2D::CompareImages(const pp::ImageData& image1,
                                   const pp::ImageData& image2) {
  return CompareImageRect(
      image1, pp::Rect(0, 0, image1.size().width(), image1.size().height()),
      image2, pp::Rect(0, 0, image2.size().width(), image2.size().height()));
}

bool TestGraphics2D::CompareImageRect(const pp::ImageData& image1,
                                      const pp::Rect& rc1,
                                      const pp::ImageData& image2,
                                      const pp::Rect& rc2) const {
  if (rc1.width() != rc2.width() || rc1.height() != rc2.height())
    return false;

  for (int y = 0; y < rc1.height(); y++) {
    for (int x = 0; x < rc1.width(); x++) {
      if (*(image1.GetAddr32(pp::Point(rc1.x() + x, rc1.y() + y))) !=
          *(image2.GetAddr32(pp::Point(rc2.x() + x, rc2.y() + y))))
        return false;
    }
  }
  return true;
}

bool TestGraphics2D::IsSquareInImage(const pp::ImageData& image_data,
                                     uint32_t background_color,
                                     const pp::Rect& square,
                                     uint32_t square_color) const {
  for (int y = 0; y < image_data.size().height(); y++) {
    for (int x = 0; x < image_data.size().width(); x++) {
      uint32_t pixel = *image_data.GetAddr32(pp::Point(x, y));
      uint32_t desired_color;
      if (square.Contains(x, y))
        desired_color = square_color;
      else
        desired_color = background_color;
      if (pixel != desired_color)
        return false;
    }
  }
  return true;
}

bool TestGraphics2D::IsSquareInDC(const pp::Graphics2D& dc,
                                  uint32_t background_color,
                                  const pp::Rect& square,
                                  uint32_t square_color) const {
  pp::ImageData readback(instance_, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                         dc.size(), false);
  if (readback.is_null())
    return false;
  if (!ReadImageData(dc, &readback, pp::Point(0, 0)))
    return false;
  return IsSquareInImage(readback, background_color, square, square_color);
}

// Test all the functions with an invalid handle. Most of these just check for
// a crash since the browser don't return a value.
std::string TestGraphics2D::TestInvalidResource() {
  pp::Graphics2D null_context;
  pp::ImageData image(instance_, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                      pp::Size(16, 16), true);

  // Describe.
  PP_Size size;
  PP_Bool opaque;
  graphics_2d_interface_->Describe(image.pp_resource(), &size, &opaque);
  graphics_2d_interface_->Describe(null_context.pp_resource(),
                                   &size, &opaque);

  // PaintImageData.
  PP_Point zero_zero;
  zero_zero.x = 0;
  zero_zero.y = 0;
  graphics_2d_interface_->PaintImageData(image.pp_resource(),
                                         image.pp_resource(),
                                         &zero_zero, NULL);
  graphics_2d_interface_->PaintImageData(null_context.pp_resource(),
                                         image.pp_resource(),
                                         &zero_zero, NULL);

  // Scroll.
  PP_Point zero_ten;
  zero_ten.x = 0;
  zero_ten.y = 10;
  graphics_2d_interface_->Scroll(image.pp_resource(), NULL, &zero_ten);
  graphics_2d_interface_->Scroll(null_context.pp_resource(),
                                 NULL, &zero_ten);

  // ReplaceContents.
  graphics_2d_interface_->ReplaceContents(image.pp_resource(),
                                          image.pp_resource());
  graphics_2d_interface_->ReplaceContents(null_context.pp_resource(),
                                          image.pp_resource());

  // Flush.
  if (graphics_2d_interface_->Flush(
          image.pp_resource(),
          PP_MakeOptionalCompletionCallback(&FlushCallbackNOP, NULL)) == PP_OK)
    return "Flush succeeded with a different resource";
  if (graphics_2d_interface_->Flush(
          null_context.pp_resource(),
          PP_MakeOptionalCompletionCallback(&FlushCallbackNOP, NULL)) == PP_OK)
    return "Flush succeeded with a NULL resource";

  // ReadImageData.
  if (testing_interface_->ReadImageData(image.pp_resource(),
                                        image.pp_resource(),
                                        &zero_zero))
    return "ReadImageData succeeded with a different resource";
  if (testing_interface_->ReadImageData(null_context.pp_resource(),
                                        image.pp_resource(),
                                        &zero_zero))
    return "ReadImageData succeeded with a NULL resource";

  PASS();
}

std::string TestGraphics2D::TestInvalidSize() {
  pp::Graphics2D a(instance_, pp::Size(16, 0), false);
  if (!a.is_null())
    return "0 height accepted";

  pp::Graphics2D b(instance_, pp::Size(0, 16), false);
  if (!b.is_null())
    return "0 width accepted";

  // Need to use the C API since pp::Size prevents negative sizes.
  PP_Size size;
  size.width = 16;
  size.height = -16;
  ASSERT_FALSE(!!graphics_2d_interface_->Create(
      instance_->pp_instance(), &size, PP_FALSE));

  size.width = -16;
  size.height = 16;
  ASSERT_FALSE(!!graphics_2d_interface_->Create(
      instance_->pp_instance(), &size, PP_FALSE));

  PASS();
}

std::string TestGraphics2D::TestHumongous() {
  pp::Graphics2D a(instance_, pp::Size(100000, 100000), false);
  if (!a.is_null())
    return "Humongous device created";
  PASS();
}

std::string TestGraphics2D::TestInitToZero() {
  const int w = 15, h = 17;
  pp::Graphics2D dc(instance_, pp::Size(w, h), false);
  if (dc.is_null())
    return "Failure creating a boring device";

  // Make an image with nonzero data in it (so we can test that zeros were
  // actually read versus ReadImageData being a NOP).
  pp::ImageData image(instance_, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                      pp::Size(w, h), true);
  if (image.is_null())
    return "Failure to allocate an image";
  memset(image.data(), 0xFF, image.stride() * image.size().height() * 4);

  // Read out the initial data from the device & check.
  if (!ReadImageData(dc, &image, pp::Point(0, 0)))
    return "Couldn't read image data";
  if (!IsSquareInImage(image, 0, pp::Rect(0, 0, w, h), 0))
    return "Got a nonzero pixel";

  PASS();
}

std::string TestGraphics2D::TestDescribe() {
  const int w = 15, h = 17;
  const bool always_opaque = ::rand() % 2 ? true : false;
  pp::Graphics2D dc(instance_, pp::Size(w, h), always_opaque);
  if (dc.is_null())
    return "Failure creating a boring device";

  PP_Size size;
  size.width = -1;
  size.height = -1;
  PP_Bool is_always_opaque = PP_FALSE;
  if (!graphics_2d_interface_->Describe(dc.pp_resource(), &size,
                                        &is_always_opaque))
    return "Describe failed";
  if (size.width != w || size.height != h ||
      is_always_opaque != PP_FromBool(always_opaque))
    return "Mismatch of data.";

  PASS();
}

std::string TestGraphics2D::TestPaint() {
  const int w = 15, h = 17;
  pp::Graphics2D dc(instance_, pp::Size(w, h), false);
  if (dc.is_null())
    return "Failure creating a boring device";

  // Make sure the device background is 0.
  if (!IsDCUniformColor(dc, 0))
    return "Bad initial color";

  // Fill the backing store with white.
  const uint32_t background_color = 0xFFFFFFFF;
  pp::ImageData background(instance_, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                           pp::Size(w, h), false);
  FillRectInImage(&background, pp::Rect(0, 0, w, h), background_color);
  dc.PaintImageData(background, pp::Point(0, 0));
  if (!FlushAndWaitForDone(&dc))
    return "Couldn't flush to fill backing store";

  // Make an image to paint with that's opaque white and enqueue a paint.
  const int fill_w = 2, fill_h = 3;
  pp::ImageData fill(instance_, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                     pp::Size(fill_w, fill_h), true);
  if (fill.is_null())
    return "Failure to allocate fill image";
  FillRectInImage(&fill, pp::Rect(fill.size()), background_color);
{'fraction_non_alphanumeric': 0.13086245538308292, 'fraction_numerical': 0.01875985722586536, 'mean_word_length': 2.8447423009414394, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 68, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4204918', 'n_tokens_mistral': 7955, 'n_tokens_neox': 7649, 'n_words': 1742}