OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "pdf/draw_utils.h" | 5 #include "pdf/draw_utils.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 23 matching lines...) Expand all Loading... |
34 inline uint32_t MakePixel(uint8_t red, | 34 inline uint32_t MakePixel(uint8_t red, |
35 uint8_t green, | 35 uint8_t green, |
36 uint8_t blue, | 36 uint8_t blue, |
37 uint8_t alpha) { | 37 uint8_t alpha) { |
38 return (static_cast<uint32_t>(alpha) << 24) | | 38 return (static_cast<uint32_t>(alpha) << 24) | |
39 (static_cast<uint32_t>(red) << 16) | | 39 (static_cast<uint32_t>(red) << 16) | |
40 (static_cast<uint32_t>(green) << 8) | | 40 (static_cast<uint32_t>(green) << 8) | |
41 static_cast<uint32_t>(blue); | 41 static_cast<uint32_t>(blue); |
42 } | 42 } |
43 | 43 |
44 inline uint8_t GradientChannel(uint8_t start, uint8_t end, double ratio) { | |
45 double new_channel = start - (static_cast<double>(start) - end) * ratio; | |
46 if (new_channel < 0) | |
47 return 0; | |
48 if (new_channel > 255) | |
49 return 255; | |
50 return static_cast<uint8_t>(new_channel + 0.5); | |
51 } | |
52 | |
53 inline uint8_t ProcessColor(uint8_t src_color, | 44 inline uint8_t ProcessColor(uint8_t src_color, |
54 uint8_t dest_color, | 45 uint8_t dest_color, |
55 uint8_t alpha) { | 46 uint8_t alpha) { |
56 uint32_t processed = static_cast<uint32_t>(src_color) * alpha + | 47 uint32_t processed = static_cast<uint32_t>(src_color) * alpha + |
57 static_cast<uint32_t>(dest_color) * (0xFF - alpha); | 48 static_cast<uint32_t>(dest_color) * (0xFF - alpha); |
58 return static_cast<uint8_t>((processed / 0xFF) & 0xFF); | 49 return static_cast<uint8_t>((processed / 0xFF) & 0xFF); |
59 } | 50 } |
60 | 51 |
61 inline bool ImageDataContainsRect(const pp::ImageData& image_data, | |
62 const pp::Rect& rect) { | |
63 return rect.width() >= 0 && rect.height() >= 0 && | |
64 pp::Rect(image_data.size()).Contains(rect); | |
65 } | |
66 | |
67 void AlphaBlend(const pp::ImageData& src, | |
68 const pp::Rect& src_rc, | |
69 pp::ImageData* dest, | |
70 const pp::Point& dest_origin, | |
71 uint8_t alpha_adjustment) { | |
72 if (src_rc.IsEmpty() || !ImageDataContainsRect(src, src_rc)) | |
73 return; | |
74 | |
75 pp::Rect dest_rc(dest_origin, src_rc.size()); | |
76 if (dest_rc.IsEmpty() || !ImageDataContainsRect(*dest, dest_rc)) | |
77 return; | |
78 | |
79 const uint32_t* src_origin_pixel = src.GetAddr32(src_rc.point()); | |
80 uint32_t* dest_origin_pixel = dest->GetAddr32(dest_origin); | |
81 | |
82 int height = src_rc.height(); | |
83 int width = src_rc.width(); | |
84 for (int y = 0; y < height; y++) { | |
85 const uint32_t* src_pixel = src_origin_pixel; | |
86 uint32_t* dest_pixel = dest_origin_pixel; | |
87 for (int x = 0; x < width; x++) { | |
88 uint8_t alpha = | |
89 static_cast<uint8_t>(static_cast<uint32_t>(alpha_adjustment) * | |
90 GetAlpha(*src_pixel) / 0xFF); | |
91 uint8_t red = | |
92 ProcessColor(GetRed(*src_pixel), GetRed(*dest_pixel), alpha); | |
93 uint8_t green = | |
94 ProcessColor(GetGreen(*src_pixel), GetGreen(*dest_pixel), alpha); | |
95 uint8_t blue = | |
96 ProcessColor(GetBlue(*src_pixel), GetBlue(*dest_pixel), alpha); | |
97 *dest_pixel = MakePixel(red, green, blue, GetAlpha(*dest_pixel)); | |
98 | |
99 src_pixel++; | |
100 dest_pixel++; | |
101 } | |
102 src_origin_pixel = reinterpret_cast<const uint32_t*>( | |
103 reinterpret_cast<const char*>(src_origin_pixel) + src.stride()); | |
104 dest_origin_pixel = reinterpret_cast<uint32_t*>( | |
105 reinterpret_cast<char*>(dest_origin_pixel) + dest->stride()); | |
106 } | |
107 } | |
108 | |
109 void GradientFill(pp::ImageData* image, | |
110 const pp::Rect& rc, | |
111 uint32_t start_color, | |
112 uint32_t end_color, | |
113 bool horizontal) { | |
114 std::vector<uint32_t> colors; | |
115 colors.resize(horizontal ? rc.width() : rc.height()); | |
116 for (size_t i = 0; i < colors.size(); ++i) { | |
117 double ratio = static_cast<double>(i) / colors.size(); | |
118 colors[i] = MakePixel( | |
119 GradientChannel(GetRed(start_color), GetRed(end_color), ratio), | |
120 GradientChannel(GetGreen(start_color), GetGreen(end_color), ratio), | |
121 GradientChannel(GetBlue(start_color), GetBlue(end_color), ratio), | |
122 GradientChannel(GetAlpha(start_color), GetAlpha(end_color), ratio)); | |
123 } | |
124 | |
125 if (horizontal) { | |
126 const void* data = &(colors[0]); | |
127 size_t size = colors.size() * 4; | |
128 uint32_t* origin_pixel = image->GetAddr32(rc.point()); | |
129 for (int y = 0; y < rc.height(); y++) { | |
130 memcpy(origin_pixel, data, size); | |
131 origin_pixel = reinterpret_cast<uint32_t*>( | |
132 reinterpret_cast<char*>(origin_pixel) + image->stride()); | |
133 } | |
134 } else { | |
135 uint32_t* origin_pixel = image->GetAddr32(rc.point()); | |
136 for (int y = 0; y < rc.height(); y++) { | |
137 uint32_t* pixel = origin_pixel; | |
138 for (int x = 0; x < rc.width(); x++) { | |
139 *pixel = colors[y]; | |
140 pixel++; | |
141 } | |
142 origin_pixel = reinterpret_cast<uint32_t*>( | |
143 reinterpret_cast<char*>(origin_pixel) + image->stride()); | |
144 } | |
145 } | |
146 } | |
147 | |
148 void GradientFill(pp::Instance* instance, | |
149 pp::ImageData* image, | |
150 const pp::Rect& dirty_rc, | |
151 const pp::Rect& gradient_rc, | |
152 uint32_t start_color, | |
153 uint32_t end_color, | |
154 bool horizontal, | |
155 uint8_t transparency) { | |
156 pp::Rect draw_rc = gradient_rc.Intersect(dirty_rc); | |
157 if (draw_rc.IsEmpty()) | |
158 return; | |
159 | |
160 pp::ImageData gradient(instance, PP_IMAGEDATAFORMAT_BGRA_PREMUL, | |
161 gradient_rc.size(), false); | |
162 | |
163 GradientFill(&gradient, pp::Rect(pp::Point(), gradient_rc.size()), | |
164 start_color, end_color, horizontal); | |
165 | |
166 pp::Rect copy_rc(draw_rc); | |
167 copy_rc.Offset(-gradient_rc.x(), -gradient_rc.y()); | |
168 AlphaBlend(gradient, copy_rc, image, draw_rc.point(), transparency); | |
169 } | |
170 | |
171 void CopyImage(const pp::ImageData& src, const pp::Rect& src_rc, | |
172 pp::ImageData* dest, const pp::Rect& dest_rc, | |
173 bool stretch) { | |
174 if (src_rc.IsEmpty() || !ImageDataContainsRect(src, src_rc)) | |
175 return; | |
176 | |
177 pp::Rect stretched_rc(dest_rc.point(), | |
178 stretch ? dest_rc.size() : src_rc.size()); | |
179 if (stretched_rc.IsEmpty() || !ImageDataContainsRect(*dest, stretched_rc)) | |
180 return; | |
181 | |
182 const uint32_t* src_origin_pixel = src.GetAddr32(src_rc.point()); | |
183 uint32_t* dest_origin_pixel = dest->GetAddr32(dest_rc.point()); | |
184 if (stretch) { | |
185 double x_ratio = static_cast<double>(src_rc.width()) / dest_rc.width(); | |
186 double y_ratio = static_cast<double>(src_rc.height()) / dest_rc.height(); | |
187 int32_t height = dest_rc.height(); | |
188 int32_t width = dest_rc.width(); | |
189 for (int32_t y = 0; y < height; ++y) { | |
190 uint32_t* dest_pixel = dest_origin_pixel; | |
191 for (int32_t x = 0; x < width; ++x) { | |
192 uint32_t src_x = static_cast<uint32_t>(x * x_ratio); | |
193 uint32_t src_y = static_cast<uint32_t>(y * y_ratio); | |
194 const uint32_t* src_pixel = src.GetAddr32( | |
195 pp::Point(src_rc.x() + src_x, src_rc.y() + src_y)); | |
196 *dest_pixel = *src_pixel; | |
197 dest_pixel++; | |
198 } | |
199 dest_origin_pixel = reinterpret_cast<uint32_t*>( | |
200 reinterpret_cast<char*>(dest_origin_pixel) + dest->stride()); | |
201 } | |
202 } else { | |
203 int32_t height = src_rc.height(); | |
204 base::CheckedNumeric<int32_t> width_bytes = src_rc.width(); | |
205 width_bytes *= 4; | |
206 for (int32_t y = 0; y < height; ++y) { | |
207 memcpy(dest_origin_pixel, src_origin_pixel, width_bytes.ValueOrDie()); | |
208 src_origin_pixel = reinterpret_cast<const uint32_t*>( | |
209 reinterpret_cast<const char*>(src_origin_pixel) + src.stride()); | |
210 dest_origin_pixel = reinterpret_cast<uint32_t*>( | |
211 reinterpret_cast<char*>(dest_origin_pixel) + dest->stride()); | |
212 } | |
213 } | |
214 } | |
215 | |
216 void FillRect(pp::ImageData* image, const pp::Rect& rc, uint32_t color) { | |
217 int height = rc.height(); | |
218 if (height == 0) | |
219 return; | |
220 | |
221 // Fill in first row. | |
222 uint32_t* top_line = image->GetAddr32(rc.point()); | |
223 int width = rc.width(); | |
224 for (int x = 0; x < width; x++) | |
225 top_line[x] = color; | |
226 | |
227 // Fill in the rest of the rectangle. | |
228 int byte_width = width * 4; | |
229 uint32_t* cur_line = reinterpret_cast<uint32_t*>( | |
230 reinterpret_cast<char*>(top_line) + image->stride()); | |
231 for (int y = 1; y < height; y++) { | |
232 memcpy(cur_line, top_line, byte_width); | |
233 cur_line = reinterpret_cast<uint32_t*>( | |
234 reinterpret_cast<char*>(cur_line) + image->stride()); | |
235 } | |
236 } | |
237 | |
238 ShadowMatrix::ShadowMatrix(uint32_t depth, double factor, uint32_t background) | 52 ShadowMatrix::ShadowMatrix(uint32_t depth, double factor, uint32_t background) |
239 : depth_(depth), factor_(factor), background_(background) { | 53 : depth_(depth), factor_(factor), background_(background) { |
240 DCHECK(depth_ > 0); | 54 DCHECK(depth_ > 0); |
241 matrix_.resize(depth_ * depth_); | 55 matrix_.resize(depth_ * depth_); |
242 | 56 |
243 // pv - is a rounding power factor for smoothing corners. | 57 // pv - is a rounding power factor for smoothing corners. |
244 // pv = 2.0 will make corners completely round. | 58 // pv = 2.0 will make corners completely round. |
245 const double pv = 4.0; | 59 const double pv = 4.0; |
246 // pow_pv - cache to avoid recalculating pow(x, pv) every time. | 60 // pow_pv - cache to avoid recalculating pow(x, pv) every time. |
247 std::vector<double> pow_pv(depth_, 0.0); | 61 std::vector<double> pow_pv(depth_, 0.0); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix); | 162 PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix); |
349 | 163 |
350 // Fill right part. | 164 // Fill right part. |
351 rc = pp::Rect(object_rc.right(), object_rc.y(), | 165 rc = pp::Rect(object_rc.right(), object_rc.y(), |
352 shadow_rc.right() - object_rc.right(), object_rc.height()); | 166 shadow_rc.right() - object_rc.right(), object_rc.height()); |
353 PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix); | 167 PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix); |
354 } | 168 } |
355 | 169 |
356 } // namespace chrome_pdf | 170 } // namespace chrome_pdf |
357 | 171 |
OLD | NEW |