Upload upstream chromium 76.0.3809.146
[platform/framework/web/chromium-efl.git] / pdf / draw_utils.cc
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 "pdf/draw_utils.h"
6
7 #include <math.h>
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <algorithm>
11 #include <vector>
12
13 #include "base/logging.h"
14 #include "base/numerics/safe_math.h"
15
16 namespace chrome_pdf {
17
18 inline uint8_t GetBlue(const uint32_t& pixel) {
19   return static_cast<uint8_t>(pixel & 0xFF);
20 }
21
22 inline uint8_t GetGreen(const uint32_t& pixel) {
23   return static_cast<uint8_t>((pixel >> 8) & 0xFF);
24 }
25
26 inline uint8_t GetRed(const uint32_t& pixel) {
27   return static_cast<uint8_t>((pixel >> 16) & 0xFF);
28 }
29
30 inline uint8_t GetAlpha(const uint32_t& pixel) {
31   return static_cast<uint8_t>((pixel >> 24) & 0xFF);
32 }
33
34 inline uint32_t MakePixel(uint8_t red,
35                           uint8_t green,
36                           uint8_t blue,
37                           uint8_t alpha) {
38   return (static_cast<uint32_t>(alpha) << 24) |
39          (static_cast<uint32_t>(red) << 16) |
40          (static_cast<uint32_t>(green) << 8) | static_cast<uint32_t>(blue);
41 }
42
43 inline uint8_t ProcessColor(uint8_t src_color,
44                             uint8_t dest_color,
45                             uint8_t alpha) {
46   uint32_t processed = static_cast<uint32_t>(src_color) * alpha +
47                        static_cast<uint32_t>(dest_color) * (0xFF - alpha);
48   return static_cast<uint8_t>((processed / 0xFF) & 0xFF);
49 }
50
51 ShadowMatrix::ShadowMatrix(uint32_t depth, double factor, uint32_t background)
52     : depth_(depth) {
53   DCHECK_GT(depth_, 0U);
54   matrix_.resize(depth_ * depth_);
55
56   // pv - is a rounding power factor for smoothing corners.
57   // pv = 2.0 will make corners completely round.
58   constexpr double pv = 4.0;
59   // pow_pv - cache to avoid recalculating pow(x, pv) every time.
60   std::vector<double> pow_pv(depth_, 0.0);
61
62   double r = static_cast<double>(depth_);
63   double coef = 256.0 / pow(r, factor);
64
65   for (uint32_t y = 0; y < depth_; y++) {
66     // Since matrix is symmetrical, we can reduce the number of calculations
67     // by mirroring results.
68     for (uint32_t x = 0; x <= y; x++) {
69       // Fill cache if needed.
70       if (pow_pv[x] == 0.0)
71         pow_pv[x] = pow(x, pv);
72       if (pow_pv[y] == 0.0)
73         pow_pv[y] = pow(y, pv);
74
75       // v - is a value for the smoothing function.
76       // If x == 0 simplify calculations.
77       double v = (x == 0) ? y : pow(pow_pv[x] + pow_pv[y], 1 / pv);
78
79       // Smoothing function.
80       // If factor == 1, smoothing will be linear from 0 to the end,
81       // if 0 < factor < 1, smoothing will drop faster near 0.
82       // if factor > 1, smoothing will drop faster near the end (depth).
83       double f = 256.0 - coef * pow(v, factor);
84
85       uint8_t alpha = 0;
86       if (f > kOpaqueAlpha)
87         alpha = kOpaqueAlpha;
88       else if (f < kTransparentAlpha)
89         alpha = kTransparentAlpha;
90       else
91         alpha = static_cast<uint8_t>(f);
92
93       uint8_t red = ProcessColor(0, GetRed(background), alpha);
94       uint8_t green = ProcessColor(0, GetGreen(background), alpha);
95       uint8_t blue = ProcessColor(0, GetBlue(background), alpha);
96       uint32_t pixel = MakePixel(red, green, blue, GetAlpha(background));
97
98       // Mirror matrix.
99       matrix_[y * depth_ + x] = pixel;
100       matrix_[x * depth_ + y] = pixel;
101     }
102   }
103 }
104
105 ShadowMatrix::~ShadowMatrix() = default;
106
107 namespace {
108
109 void PaintShadow(pp::ImageData* image,
110                  const pp::Rect& clip_rc,
111                  const pp::Rect& shadow_rc,
112                  const ShadowMatrix& matrix) {
113   pp::Rect draw_rc = shadow_rc.Intersect(clip_rc);
114   if (draw_rc.IsEmpty())
115     return;
116
117   int32_t depth = static_cast<int32_t>(matrix.depth());
118   for (int32_t y = draw_rc.y(); y < draw_rc.bottom(); y++) {
119     for (int32_t x = draw_rc.x(); x < draw_rc.right(); x++) {
120       int32_t matrix_x = std::max(depth + shadow_rc.x() - x - 1,
121                                   depth - shadow_rc.right() + x);
122       int32_t matrix_y = std::max(depth + shadow_rc.y() - y - 1,
123                                   depth - shadow_rc.bottom() + y);
124       uint32_t* pixel = image->GetAddr32(pp::Point(x, y));
125
126       if (matrix_x < 0)
127         matrix_x = 0;
128       else if (matrix_x >= static_cast<int32_t>(depth))
129         matrix_x = depth - 1;
130
131       if (matrix_y < 0)
132         matrix_y = 0;
133       else if (matrix_y >= static_cast<int32_t>(depth))
134         matrix_y = depth - 1;
135
136       *pixel = matrix.GetValue(matrix_x, matrix_y);
137     }
138   }
139 }
140
141 }  // namespace
142
143 void DrawShadow(pp::ImageData* image,
144                 const pp::Rect& shadow_rc,
145                 const pp::Rect& object_rc,
146                 const pp::Rect& clip_rc,
147                 const ShadowMatrix& matrix) {
148   if (shadow_rc == object_rc)
149     return;  // Nothing to paint.
150
151   // Fill top part.
152   pp::Rect rc(shadow_rc.point(),
153               pp::Size(shadow_rc.width(), object_rc.y() - shadow_rc.y()));
154   PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix);
155
156   // Fill bottom part.
157   rc = pp::Rect(shadow_rc.x(), object_rc.bottom(), shadow_rc.width(),
158                 shadow_rc.bottom() - object_rc.bottom());
159   PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix);
160
161   // Fill left part.
162   rc = pp::Rect(shadow_rc.x(), object_rc.y(), object_rc.x() - shadow_rc.x(),
163                 object_rc.height());
164   PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix);
165
166   // Fill right part.
167   rc = pp::Rect(object_rc.right(), object_rc.y(),
168                 shadow_rc.right() - object_rc.right(), object_rc.height());
169   PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix);
170 }
171
172 }  // namespace chrome_pdf