1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "pdf/draw_utils.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <algorithm>
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <math.h>
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <vector>
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/logging.h"
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/numerics/safe_math.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace chrome_pdf {
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint8 GetBlue(const uint32& pixel) {
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return static_cast<uint8>(pixel & 0xFF);
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint8 GetGreen(const uint32& pixel) {
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return static_cast<uint8>((pixel >> 8) & 0xFF);
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint8 GetRed(const uint32& pixel) {
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return static_cast<uint8>((pixel >> 16) & 0xFF);
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint8 GetAlpha(const uint32& pixel) {
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return static_cast<uint8>((pixel >> 24) & 0xFF);
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint32_t MakePixel(uint8 red, uint8 green, uint8 blue, uint8 alpha) {
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return (static_cast<uint32_t>(alpha) << 24) |
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      (static_cast<uint32_t>(red) << 16) |
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      (static_cast<uint32_t>(green) << 8) |
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      static_cast<uint32_t>(blue);
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint8 GradientChannel(uint8 start, uint8 end, double ratio) {
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  double new_channel = start - (static_cast<double>(start) - end) * ratio;
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (new_channel < 0)
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return 0;
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (new_channel > 255)
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return 255;
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return static_cast<uint8>(new_channel + 0.5);
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline uint8 ProcessColor(uint8 src_color, uint8 dest_color, uint8 alpha) {
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  uint32 processed = static_cast<uint32>(src_color) * alpha +
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      static_cast<uint32>(dest_color) * (0xFF - alpha);
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return static_cast<uint8>((processed / 0xFF) & 0xFF);
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciinline bool ImageDataContainsRect(const pp::ImageData& image_data,
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  const pp::Rect& rect) {
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return rect.width() >= 0 && rect.height() >= 0 &&
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      pp::Rect(image_data.size()).Contains(rect);
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AlphaBlend(const pp::ImageData& src, const pp::Rect& src_rc,
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                pp::ImageData* dest, const pp::Point& dest_origin,
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                uint8 alpha_adjustment) {
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (src_rc.IsEmpty() || !ImageDataContainsRect(src, src_rc))
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  pp::Rect dest_rc(dest_origin, src_rc.size());
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (dest_rc.IsEmpty() || !ImageDataContainsRect(*dest, dest_rc))
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const uint32_t* src_origin_pixel = src.GetAddr32(src_rc.point());
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  uint32_t* dest_origin_pixel = dest->GetAddr32(dest_origin);
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int height = src_rc.height();
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int width = src_rc.width();
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (int y = 0; y < height; y++) {
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const uint32_t* src_pixel = src_origin_pixel;
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    uint32_t* dest_pixel = dest_origin_pixel;
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (int x = 0; x < width; x++) {
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      uint8 alpha = static_cast<uint8>(static_cast<uint32_t>(alpha_adjustment) *
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          GetAlpha(*src_pixel) / 0xFF);
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      uint8 red = ProcessColor(GetRed(*src_pixel), GetRed(*dest_pixel), alpha);
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      uint8 green = ProcessColor(GetGreen(*src_pixel),
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 GetGreen(*dest_pixel), alpha);
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      uint8 blue = ProcessColor(GetBlue(*src_pixel),
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                GetBlue(*dest_pixel), alpha);
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      *dest_pixel = MakePixel(red, green, blue, GetAlpha(*dest_pixel));
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      src_pixel++;
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      dest_pixel++;
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    src_origin_pixel = reinterpret_cast<const uint32_t*>(
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        reinterpret_cast<const char*>(src_origin_pixel) + src.stride());
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    dest_origin_pixel = reinterpret_cast<uint32_t*>(
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        reinterpret_cast<char*>(dest_origin_pixel) + dest->stride());
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void GradientFill(pp::ImageData* image, const pp::Rect& rc,
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  uint32 start_color, uint32 end_color, bool horizontal) {
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<uint32> colors;
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  colors.resize(horizontal ? rc.width() : rc.height());
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < colors.size(); ++i) {
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    double ratio = static_cast<double>(i) / colors.size();
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    colors[i] = MakePixel(
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        GradientChannel(GetRed(start_color), GetRed(end_color), ratio),
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        GradientChannel(GetGreen(start_color), GetGreen(end_color), ratio),
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        GradientChannel(GetBlue(start_color), GetBlue(end_color), ratio),
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        GradientChannel(GetAlpha(start_color), GetAlpha(end_color), ratio));
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (horizontal) {
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const void* data = &(colors[0]);
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    size_t size = colors.size() * 4;
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    uint32_t* origin_pixel = image->GetAddr32(rc.point());
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (int y = 0; y < rc.height(); y++) {
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      memcpy(origin_pixel, data, size);
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      origin_pixel = reinterpret_cast<uint32_t*>(
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          reinterpret_cast<char*>(origin_pixel) + image->stride());
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    uint32_t* origin_pixel = image->GetAddr32(rc.point());
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (int y = 0; y < rc.height(); y++) {
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      uint32_t* pixel = origin_pixel;
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      for (int x = 0; x < rc.width(); x++) {
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        *pixel = colors[y];
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        pixel++;
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      origin_pixel = reinterpret_cast<uint32_t*>(
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          reinterpret_cast<char*>(origin_pixel) + image->stride());
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void GradientFill(pp::Instance* instance,
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  pp::ImageData* image,
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  const pp::Rect& dirty_rc,
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  const pp::Rect& gradient_rc,
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  uint32 start_color,
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  uint32 end_color,
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  bool horizontal,
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                  uint8 transparency) {
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  pp::Rect draw_rc = gradient_rc.Intersect(dirty_rc);
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (draw_rc.IsEmpty())
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  pp::ImageData gradient(instance, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      gradient_rc.size(), false);
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GradientFill(&gradient, pp::Rect(pp::Point(), gradient_rc.size()),
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)               start_color, end_color, horizontal);
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  pp::Rect copy_rc(draw_rc);
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  copy_rc.Offset(-gradient_rc.x(), -gradient_rc.y());
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  AlphaBlend(gradient, copy_rc, image, draw_rc.point(), transparency);
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void CopyImage(const pp::ImageData& src, const pp::Rect& src_rc,
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)               pp::ImageData* dest, const pp::Rect& dest_rc,
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)               bool stretch) {
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (src_rc.IsEmpty() || !ImageDataContainsRect(src, src_rc))
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  pp::Rect stretched_rc(dest_rc.point(),
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        stretch ? dest_rc.size() : src_rc.size());
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (stretched_rc.IsEmpty() || !ImageDataContainsRect(*dest, stretched_rc))
16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return;
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const uint32_t* src_origin_pixel = src.GetAddr32(src_rc.point());
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  uint32_t* dest_origin_pixel = dest->GetAddr32(dest_rc.point());
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (stretch) {
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    double x_ratio = static_cast<double>(src_rc.width()) / dest_rc.width();
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    double y_ratio = static_cast<double>(src_rc.height()) / dest_rc.height();
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int32_t height = dest_rc.height();
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int32_t width = dest_rc.width();
175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (int32_t y = 0; y < height; ++y) {
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      uint32_t* dest_pixel = dest_origin_pixel;
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      for (int32_t x = 0; x < width; ++x) {
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        uint32 src_x = static_cast<uint32>(x * x_ratio);
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        uint32 src_y = static_cast<uint32>(y * y_ratio);
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        const uint32_t* src_pixel = src.GetAddr32(
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            pp::Point(src_rc.x() + src_x, src_rc.y() + src_y));
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        *dest_pixel = *src_pixel;
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        dest_pixel++;
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      dest_origin_pixel = reinterpret_cast<uint32_t*>(
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          reinterpret_cast<char*>(dest_origin_pixel) + dest->stride());
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int32_t height = src_rc.height();
190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    base::CheckedNumeric<int32_t> width_bytes = src_rc.width();
191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    width_bytes *= 4;
192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (int32_t y = 0; y < height; ++y) {
193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      memcpy(dest_origin_pixel, src_origin_pixel, width_bytes.ValueOrDie());
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      src_origin_pixel = reinterpret_cast<const uint32_t*>(
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          reinterpret_cast<const char*>(src_origin_pixel) + src.stride());
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      dest_origin_pixel = reinterpret_cast<uint32_t*>(
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          reinterpret_cast<char*>(dest_origin_pixel) + dest->stride());
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void FillRect(pp::ImageData* image, const pp::Rect& rc, uint32 color) {
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int height = rc.height();
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (height == 0)
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fill in first row.
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  uint32_t* top_line = image->GetAddr32(rc.point());
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int width = rc.width();
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (int x = 0; x < width; x++)
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    top_line[x] = color;
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fill in the rest of the rectangle.
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int byte_width = width * 4;
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  uint32_t* cur_line = reinterpret_cast<uint32_t*>(
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          reinterpret_cast<char*>(top_line) + image->stride());
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (int y = 1; y < height; y++) {
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    memcpy(cur_line, top_line, byte_width);
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    cur_line = reinterpret_cast<uint32_t*>(
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            reinterpret_cast<char*>(cur_line) + image->stride());
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ShadowMatrix::ShadowMatrix(uint32 depth, double factor, uint32 background)
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : depth_(depth), factor_(factor), background_(background) {
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(depth_ > 0);
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  matrix_.resize(depth_ * depth_);
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // pv - is a rounding power factor for smoothing corners.
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // pv = 2.0 will make corners completely round.
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const double pv = 4.0;
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // pow_pv - cache to avoid recalculating pow(x, pv) every time.
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<double> pow_pv(depth_, 0.0);
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  double r = static_cast<double>(depth_);
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  double coef = 256.0 / pow(r, factor);
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (uint32 y = 0; y < depth_; y++) {
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Since matrix is symmetrical, we can reduce the number of calculations
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // by mirroring results.
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (uint32 x = 0; x <= y; x++) {
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Fill cache if needed.
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (pow_pv[x] == 0.0)
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        pow_pv[x] =  pow(x, pv);
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (pow_pv[y] == 0.0)
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        pow_pv[y] =  pow(y, pv);
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // v - is a value for the smoothing function.
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // If x == 0 simplify calculations.
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      double v = (x == 0) ? y : pow(pow_pv[x] + pow_pv[y], 1 / pv);
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Smoothing function.
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // If factor == 1, smoothing will be linear from 0 to the end,
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // if 0 < factor < 1, smoothing will drop faster near 0.
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // if factor > 1, smoothing will drop faster near the end (depth).
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      double f = 256.0 - coef * pow(v, factor);
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      uint8 alpha = 0;
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (f > kOpaqueAlpha)
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        alpha = kOpaqueAlpha;
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      else if (f < kTransparentAlpha)
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        alpha = kTransparentAlpha;
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      else
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        alpha = static_cast<uint8>(f);
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      uint8 red = ProcessColor(0, GetRed(background), alpha);
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      uint8 green = ProcessColor(0, GetGreen(background), alpha);
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      uint8 blue = ProcessColor(0, GetBlue(background), alpha);
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      uint32 pixel = MakePixel(red, green, blue, GetAlpha(background));
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Mirror matrix.
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      matrix_[y * depth_ + x] = pixel;
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      matrix_[x * depth_ + y] = pixel;
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ShadowMatrix::~ShadowMatrix() {
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PaintShadow(pp::ImageData* image,
282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 const pp::Rect& clip_rc,
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 const pp::Rect& shadow_rc,
284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 const ShadowMatrix& matrix) {
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  pp::Rect draw_rc = shadow_rc.Intersect(clip_rc);
286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (draw_rc.IsEmpty())
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int32 depth = static_cast<int32>(matrix.depth());
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (int32_t y = draw_rc.y(); y < draw_rc.bottom(); y++) {
291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (int32_t x = draw_rc.x(); x < draw_rc.right(); x++) {
292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      int32_t matrix_x = std::max(depth + shadow_rc.x() - x - 1,
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  depth - shadow_rc.right() + x);
294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      int32_t matrix_y = std::max(depth + shadow_rc.y() - y - 1,
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  depth - shadow_rc.bottom() + y);
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      uint32_t* pixel = image->GetAddr32(pp::Point(x, y));
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (matrix_x < 0)
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        matrix_x = 0;
300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      else if (matrix_x >= static_cast<int32>(depth))
301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        matrix_x = depth - 1;
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (matrix_y < 0)
304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        matrix_y = 0;
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      else if (matrix_y >= static_cast<int32>(depth))
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        matrix_y = depth - 1;
307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      *pixel = matrix.GetValue(matrix_x, matrix_y);
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DrawShadow(pp::ImageData* image,
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                const pp::Rect& shadow_rc,
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                const pp::Rect& object_rc,
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                const pp::Rect& clip_rc,
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                const ShadowMatrix& matrix) {
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (shadow_rc == object_rc)
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;  // Nothing to paint.
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fill top part.
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  pp::Rect rc(shadow_rc.point(),
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              pp::Size(shadow_rc.width(), object_rc.y() - shadow_rc.y()));
324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix);
325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fill bottom part.
327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  rc = pp::Rect(shadow_rc.x(), object_rc.bottom(),
328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                shadow_rc.width(), shadow_rc.bottom() - object_rc.bottom());
329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix);
330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fill left part.
332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  rc = pp::Rect(shadow_rc.x(), object_rc.y(),
333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                object_rc.x() - shadow_rc.x(), object_rc.height());
334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix);
335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fill right part.
337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  rc = pp::Rect(object_rc.right(), object_rc.y(),
338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                shadow_rc.right() - object_rc.right(), object_rc.height());
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix);
340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace chrome_pdf
343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
344