OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium 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 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "../../../include/fpdfapi/fpdf_render.h" | 7 #include "../../../include/fpdfapi/fpdf_render.h" |
8 #include "../../../include/fpdfapi/fpdf_pageobj.h" | 8 #include "../../../include/fpdfapi/fpdf_pageobj.h" |
9 #include "../../../include/fxge/fx_ge.h" | 9 #include "../../../include/fxge/fx_ge.h" |
10 #include "../fpdf_page/pageint.h" | 10 #include "../fpdf_page/pageint.h" |
11 #include "render_int.h" | 11 #include "render_int.h" |
12 #define SHADING_STEPS 256 | 12 #define SHADING_STEPS 256 |
13 static void _DrawAxialShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2B
itmap, | 13 static void _DrawAxialShading(CFX_DIBitmap* pBitmap, |
14 CPDF_Dictionary* pDict, CPDF_Function** pFuncs, in
t nFuncs, | 14 CFX_AffineMatrix* pObject2Bitmap, |
15 CPDF_ColorSpace* pCS, int alpha) | 15 CPDF_Dictionary* pDict, |
16 { | 16 CPDF_Function** pFuncs, |
17 ASSERT(pBitmap->GetFormat() == FXDIB_Argb); | 17 int nFuncs, |
18 CPDF_Array* pCoords = pDict->GetArray(FX_BSTRC("Coords")); | 18 CPDF_ColorSpace* pCS, |
19 if (pCoords == NULL) { | 19 int alpha) { |
20 return; | 20 ASSERT(pBitmap->GetFormat() == FXDIB_Argb); |
21 } | 21 CPDF_Array* pCoords = pDict->GetArray(FX_BSTRC("Coords")); |
22 FX_FLOAT start_x = pCoords->GetNumber(0); | 22 if (pCoords == NULL) { |
23 FX_FLOAT start_y = pCoords->GetNumber(1); | 23 return; |
24 FX_FLOAT end_x = pCoords->GetNumber(2); | 24 } |
25 FX_FLOAT end_y = pCoords->GetNumber(3); | 25 FX_FLOAT start_x = pCoords->GetNumber(0); |
26 FX_FLOAT t_min = 0, t_max = 1.0f; | 26 FX_FLOAT start_y = pCoords->GetNumber(1); |
27 CPDF_Array* pArray = pDict->GetArray(FX_BSTRC("Domain")); | 27 FX_FLOAT end_x = pCoords->GetNumber(2); |
28 if (pArray) { | 28 FX_FLOAT end_y = pCoords->GetNumber(3); |
29 t_min = pArray->GetNumber(0); | 29 FX_FLOAT t_min = 0, t_max = 1.0f; |
30 t_max = pArray->GetNumber(1); | 30 CPDF_Array* pArray = pDict->GetArray(FX_BSTRC("Domain")); |
31 } | 31 if (pArray) { |
32 FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE; | 32 t_min = pArray->GetNumber(0); |
33 pArray = pDict->GetArray(FX_BSTRC("Extend")); | 33 t_max = pArray->GetNumber(1); |
34 if (pArray) { | 34 } |
35 bStartExtend = pArray->GetInteger(0); | 35 FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE; |
36 bEndExtend = pArray->GetInteger(1); | 36 pArray = pDict->GetArray(FX_BSTRC("Extend")); |
37 } | 37 if (pArray) { |
38 int width = pBitmap->GetWidth(); | 38 bStartExtend = pArray->GetInteger(0); |
39 int height = pBitmap->GetHeight(); | 39 bEndExtend = pArray->GetInteger(1); |
40 FX_FLOAT x_span = end_x - start_x; | 40 } |
41 FX_FLOAT y_span = end_y - start_y; | 41 int width = pBitmap->GetWidth(); |
42 FX_FLOAT axis_len_square = FXSYS_Mul(x_span, x_span) + FXSYS_Mul(y_span, y_s
pan); | 42 int height = pBitmap->GetHeight(); |
43 CFX_AffineMatrix matrix; | 43 FX_FLOAT x_span = end_x - start_x; |
44 matrix.SetReverse(*pObject2Bitmap); | 44 FX_FLOAT y_span = end_y - start_y; |
45 int total_results = 0; | 45 FX_FLOAT axis_len_square = |
46 for (int j = 0; j < nFuncs; j ++) { | 46 FXSYS_Mul(x_span, x_span) + FXSYS_Mul(y_span, y_span); |
| 47 CFX_AffineMatrix matrix; |
| 48 matrix.SetReverse(*pObject2Bitmap); |
| 49 int total_results = 0; |
| 50 for (int j = 0; j < nFuncs; j++) { |
| 51 if (pFuncs[j]) { |
| 52 total_results += pFuncs[j]->CountOutputs(); |
| 53 } |
| 54 } |
| 55 if (pCS->CountComponents() > total_results) { |
| 56 total_results = pCS->CountComponents(); |
| 57 } |
| 58 CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results); |
| 59 FX_FLOAT* pResults = result_array; |
| 60 FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT)); |
| 61 FX_DWORD rgb_array[SHADING_STEPS]; |
| 62 for (int i = 0; i < SHADING_STEPS; i++) { |
| 63 FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min; |
| 64 int offset = 0; |
| 65 for (int j = 0; j < nFuncs; j++) { |
| 66 if (pFuncs[j]) { |
| 67 int nresults = 0; |
| 68 if (pFuncs[j]->Call(&input, 1, pResults + offset, nresults)) { |
| 69 offset += nresults; |
| 70 } |
| 71 } |
| 72 } |
| 73 FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; |
| 74 pCS->GetRGB(pResults, R, G, B); |
| 75 rgb_array[i] = |
| 76 FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255), |
| 77 FXSYS_round(G * 255), FXSYS_round(B * 255))); |
| 78 } |
| 79 int pitch = pBitmap->GetPitch(); |
| 80 for (int row = 0; row < height; row++) { |
| 81 FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch); |
| 82 for (int column = 0; column < width; column++) { |
| 83 FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row; |
| 84 matrix.Transform(x, y); |
| 85 FX_FLOAT scale = FXSYS_Div( |
| 86 FXSYS_Mul(x - start_x, x_span) + FXSYS_Mul(y - start_y, y_span), |
| 87 axis_len_square); |
| 88 int index = (int32_t)(scale * (SHADING_STEPS - 1)); |
| 89 if (index < 0) { |
| 90 if (!bStartExtend) { |
| 91 continue; |
| 92 } |
| 93 index = 0; |
| 94 } else if (index >= SHADING_STEPS) { |
| 95 if (!bEndExtend) { |
| 96 continue; |
| 97 } |
| 98 index = SHADING_STEPS - 1; |
| 99 } |
| 100 dib_buf[column] = rgb_array[index]; |
| 101 } |
| 102 } |
| 103 } |
| 104 static void _DrawRadialShading(CFX_DIBitmap* pBitmap, |
| 105 CFX_AffineMatrix* pObject2Bitmap, |
| 106 CPDF_Dictionary* pDict, |
| 107 CPDF_Function** pFuncs, |
| 108 int nFuncs, |
| 109 CPDF_ColorSpace* pCS, |
| 110 int alpha) { |
| 111 ASSERT(pBitmap->GetFormat() == FXDIB_Argb); |
| 112 CPDF_Array* pCoords = pDict->GetArray(FX_BSTRC("Coords")); |
| 113 if (pCoords == NULL) { |
| 114 return; |
| 115 } |
| 116 FX_FLOAT start_x = pCoords->GetNumber(0); |
| 117 FX_FLOAT start_y = pCoords->GetNumber(1); |
| 118 FX_FLOAT start_r = pCoords->GetNumber(2); |
| 119 FX_FLOAT end_x = pCoords->GetNumber(3); |
| 120 FX_FLOAT end_y = pCoords->GetNumber(4); |
| 121 FX_FLOAT end_r = pCoords->GetNumber(5); |
| 122 CFX_AffineMatrix matrix; |
| 123 matrix.SetReverse(*pObject2Bitmap); |
| 124 FX_FLOAT t_min = 0, t_max = 1.0f; |
| 125 CPDF_Array* pArray = pDict->GetArray(FX_BSTRC("Domain")); |
| 126 if (pArray) { |
| 127 t_min = pArray->GetNumber(0); |
| 128 t_max = pArray->GetNumber(1); |
| 129 } |
| 130 FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE; |
| 131 pArray = pDict->GetArray(FX_BSTRC("Extend")); |
| 132 if (pArray) { |
| 133 bStartExtend = pArray->GetInteger(0); |
| 134 bEndExtend = pArray->GetInteger(1); |
| 135 } |
| 136 int total_results = 0; |
| 137 for (int j = 0; j < nFuncs; j++) { |
| 138 if (pFuncs[j]) { |
| 139 total_results += pFuncs[j]->CountOutputs(); |
| 140 } |
| 141 } |
| 142 if (pCS->CountComponents() > total_results) { |
| 143 total_results = pCS->CountComponents(); |
| 144 } |
| 145 CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results); |
| 146 FX_FLOAT* pResults = result_array; |
| 147 FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT)); |
| 148 FX_DWORD rgb_array[SHADING_STEPS]; |
| 149 for (int i = 0; i < SHADING_STEPS; i++) { |
| 150 FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min; |
| 151 int offset = 0; |
| 152 for (int j = 0; j < nFuncs; j++) { |
| 153 if (pFuncs[j]) { |
| 154 int nresults; |
| 155 if (pFuncs[j]->Call(&input, 1, pResults + offset, nresults)) { |
| 156 offset += nresults; |
| 157 } |
| 158 } |
| 159 } |
| 160 FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; |
| 161 pCS->GetRGB(pResults, R, G, B); |
| 162 rgb_array[i] = |
| 163 FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255), |
| 164 FXSYS_round(G * 255), FXSYS_round(B * 255))); |
| 165 } |
| 166 FX_FLOAT a = FXSYS_Mul(start_x - end_x, start_x - end_x) + |
| 167 FXSYS_Mul(start_y - end_y, start_y - end_y) - |
| 168 FXSYS_Mul(start_r - end_r, start_r - end_r); |
| 169 int width = pBitmap->GetWidth(); |
| 170 int height = pBitmap->GetHeight(); |
| 171 int pitch = pBitmap->GetPitch(); |
| 172 FX_BOOL bDecreasing = FALSE; |
| 173 if (start_r > end_r) { |
| 174 int length = (int)FXSYS_sqrt((FXSYS_Mul(start_x - end_x, start_x - end_x) + |
| 175 FXSYS_Mul(start_y - end_y, start_y - end_y))); |
| 176 if (length < start_r - end_r) { |
| 177 bDecreasing = TRUE; |
| 178 } |
| 179 } |
| 180 for (int row = 0; row < height; row++) { |
| 181 FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch); |
| 182 for (int column = 0; column < width; column++) { |
| 183 FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row; |
| 184 matrix.Transform(x, y); |
| 185 FX_FLOAT b = -2 * (FXSYS_Mul(x - start_x, end_x - start_x) + |
| 186 FXSYS_Mul(y - start_y, end_y - start_y) + |
| 187 FXSYS_Mul(start_r, end_r - start_r)); |
| 188 FX_FLOAT c = FXSYS_Mul(x - start_x, x - start_x) + |
| 189 FXSYS_Mul(y - start_y, y - start_y) - |
| 190 FXSYS_Mul(start_r, start_r); |
| 191 FX_FLOAT s; |
| 192 if (a == 0) { |
| 193 s = FXSYS_Div(-c, b); |
| 194 } else { |
| 195 FX_FLOAT b2_4ac = FXSYS_Mul(b, b) - 4 * FXSYS_Mul(a, c); |
| 196 if (b2_4ac < 0) { |
| 197 continue; |
| 198 } |
| 199 FX_FLOAT root = FXSYS_sqrt(b2_4ac); |
| 200 FX_FLOAT s1, s2; |
| 201 if (a > 0) { |
| 202 s1 = FXSYS_Div(-b - root, 2 * a); |
| 203 s2 = FXSYS_Div(-b + root, 2 * a); |
| 204 } else { |
| 205 s2 = FXSYS_Div(-b - root, 2 * a); |
| 206 s1 = FXSYS_Div(-b + root, 2 * a); |
| 207 } |
| 208 if (bDecreasing) { |
| 209 if (s1 >= 0 || bStartExtend) { |
| 210 s = s1; |
| 211 } else { |
| 212 s = s2; |
| 213 } |
| 214 } else { |
| 215 if (s2 <= 1.0f || bEndExtend) { |
| 216 s = s2; |
| 217 } else { |
| 218 s = s1; |
| 219 } |
| 220 } |
| 221 if ((start_r + s * (end_r - start_r)) < 0) { |
| 222 continue; |
| 223 } |
| 224 } |
| 225 int index = (int32_t)(s * (SHADING_STEPS - 1)); |
| 226 if (index < 0) { |
| 227 if (!bStartExtend) { |
| 228 continue; |
| 229 } |
| 230 index = 0; |
| 231 } |
| 232 if (index >= SHADING_STEPS) { |
| 233 if (!bEndExtend) { |
| 234 continue; |
| 235 } |
| 236 index = SHADING_STEPS - 1; |
| 237 } |
| 238 dib_buf[column] = rgb_array[index]; |
| 239 } |
| 240 } |
| 241 } |
| 242 static void _DrawFuncShading(CFX_DIBitmap* pBitmap, |
| 243 CFX_AffineMatrix* pObject2Bitmap, |
| 244 CPDF_Dictionary* pDict, |
| 245 CPDF_Function** pFuncs, |
| 246 int nFuncs, |
| 247 CPDF_ColorSpace* pCS, |
| 248 int alpha) { |
| 249 ASSERT(pBitmap->GetFormat() == FXDIB_Argb); |
| 250 CPDF_Array* pDomain = pDict->GetArray(FX_BSTRC("Domain")); |
| 251 FX_FLOAT xmin = 0, ymin = 0, xmax = 1.0f, ymax = 1.0f; |
| 252 if (pDomain) { |
| 253 xmin = pDomain->GetNumber(0); |
| 254 xmax = pDomain->GetNumber(1); |
| 255 ymin = pDomain->GetNumber(2); |
| 256 ymax = pDomain->GetNumber(3); |
| 257 } |
| 258 CFX_AffineMatrix mtDomain2Target = pDict->GetMatrix(FX_BSTRC("Matrix")); |
| 259 CFX_AffineMatrix matrix, reverse_matrix; |
| 260 matrix.SetReverse(*pObject2Bitmap); |
| 261 reverse_matrix.SetReverse(mtDomain2Target); |
| 262 matrix.Concat(reverse_matrix); |
| 263 int width = pBitmap->GetWidth(); |
| 264 int height = pBitmap->GetHeight(); |
| 265 int pitch = pBitmap->GetPitch(); |
| 266 int total_results = 0; |
| 267 for (int j = 0; j < nFuncs; j++) { |
| 268 if (pFuncs[j]) { |
| 269 total_results += pFuncs[j]->CountOutputs(); |
| 270 } |
| 271 } |
| 272 if (pCS->CountComponents() > total_results) { |
| 273 total_results = pCS->CountComponents(); |
| 274 } |
| 275 CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results); |
| 276 FX_FLOAT* pResults = result_array; |
| 277 FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT)); |
| 278 for (int row = 0; row < height; row++) { |
| 279 FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch); |
| 280 for (int column = 0; column < width; column++) { |
| 281 FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row; |
| 282 matrix.Transform(x, y); |
| 283 if (x < xmin || x > xmax || y < ymin || y > ymax) { |
| 284 continue; |
| 285 } |
| 286 FX_FLOAT input[2]; |
| 287 int offset = 0; |
| 288 input[0] = x; |
| 289 input[1] = y; |
| 290 for (int j = 0; j < nFuncs; j++) { |
47 if (pFuncs[j]) { | 291 if (pFuncs[j]) { |
48 total_results += pFuncs[j]->CountOutputs(); | 292 int nresults; |
49 } | 293 if (pFuncs[j]->Call(input, 2, pResults + offset, nresults)) { |
50 } | 294 offset += nresults; |
51 if (pCS->CountComponents() > total_results) { | 295 } |
52 total_results = pCS->CountComponents(); | 296 } |
53 } | 297 } |
54 CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results); | 298 FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; |
55 FX_FLOAT* pResults = result_array; | 299 pCS->GetRGB(pResults, R, G, B); |
56 FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT)); | 300 dib_buf[column] = FXARGB_TODIB(FXARGB_MAKE( |
57 FX_DWORD rgb_array[SHADING_STEPS]; | 301 alpha, (int32_t)(R * 255), (int32_t)(G * 255), (int32_t)(B * 255))); |
58 for (int i = 0; i < SHADING_STEPS; i ++) { | 302 } |
59 FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min; | 303 } |
60 int offset = 0; | 304 } |
61 for (int j = 0; j < nFuncs; j ++) { | 305 FX_BOOL _GetScanlineIntersect(int y, |
62 if (pFuncs[j]) { | 306 FX_FLOAT x1, |
63 int nresults = 0; | 307 FX_FLOAT y1, |
64 if (pFuncs[j]->Call(&input, 1, pResults + offset, nresults)) { | 308 FX_FLOAT x2, |
65 offset += nresults; | 309 FX_FLOAT y2, |
66 } | 310 FX_FLOAT& x) { |
67 } | 311 if (y1 == y2) { |
68 } | 312 return FALSE; |
69 FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; | 313 } |
70 pCS->GetRGB(pResults, R, G, B); | 314 if (y1 < y2) { |
71 rgb_array[i] = FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255), FXS
YS_round(G * 255), FXSYS_round(B * 255))); | 315 if (y < y1 || y > y2) { |
72 } | 316 return FALSE; |
73 int pitch = pBitmap->GetPitch(); | 317 } |
74 for (int row = 0; row < height; row ++) { | 318 } else { |
75 FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch); | 319 if (y < y2 || y > y1) { |
76 for (int column = 0; column < width; column ++) { | 320 return FALSE; |
77 FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row; | 321 } |
78 matrix.Transform(x, y); | 322 } |
79 FX_FLOAT scale = FXSYS_Div(FXSYS_Mul(x - start_x, x_span) + FXSYS_Mu
l(y - start_y, y_span), axis_len_square); | 323 x = x1 + FXSYS_MulDiv(x2 - x1, y - y1, y2 - y1); |
80 int index = (int32_t)(scale * (SHADING_STEPS - 1)); | 324 return TRUE; |
81 if (index < 0) { | 325 } |
82 if (!bStartExtend) { | 326 static void _DrawGouraud(CFX_DIBitmap* pBitmap, |
83 continue; | 327 int alpha, |
84 } | 328 CPDF_MeshVertex triangle[3]) { |
85 index = 0; | 329 FX_FLOAT min_y = triangle[0].y, max_y = triangle[0].y; |
86 } else if (index >= SHADING_STEPS) { | 330 for (int i = 1; i < 3; i++) { |
87 if (!bEndExtend) { | 331 if (min_y > triangle[i].y) { |
88 continue; | 332 min_y = triangle[i].y; |
89 } | 333 } |
90 index = SHADING_STEPS - 1; | 334 if (max_y < triangle[i].y) { |
91 } | 335 max_y = triangle[i].y; |
92 dib_buf[column] = rgb_array[index]; | 336 } |
93 } | 337 } |
94 } | 338 if (min_y == max_y) { |
95 } | 339 return; |
96 static void _DrawRadialShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2
Bitmap, | 340 } |
97 CPDF_Dictionary* pDict, CPDF_Function** pFuncs, i
nt nFuncs, | 341 int min_yi = (int)FXSYS_floor(min_y), max_yi = (int)FXSYS_ceil(max_y); |
98 CPDF_ColorSpace* pCS, int alpha) | 342 if (min_yi < 0) { |
99 { | 343 min_yi = 0; |
100 ASSERT(pBitmap->GetFormat() == FXDIB_Argb); | 344 } |
101 CPDF_Array* pCoords = pDict->GetArray(FX_BSTRC("Coords")); | 345 if (max_yi >= pBitmap->GetHeight()) { |
102 if (pCoords == NULL) { | 346 max_yi = pBitmap->GetHeight() - 1; |
103 return; | 347 } |
104 } | 348 for (int y = min_yi; y <= max_yi; y++) { |
105 FX_FLOAT start_x = pCoords->GetNumber(0); | 349 int nIntersects = 0; |
106 FX_FLOAT start_y = pCoords->GetNumber(1); | 350 FX_FLOAT inter_x[3], r[3], g[3], b[3]; |
107 FX_FLOAT start_r = pCoords->GetNumber(2); | 351 for (int i = 0; i < 3; i++) { |
108 FX_FLOAT end_x = pCoords->GetNumber(3); | 352 CPDF_MeshVertex& vertex1 = triangle[i]; |
109 FX_FLOAT end_y = pCoords->GetNumber(4); | 353 CPDF_MeshVertex& vertex2 = triangle[(i + 1) % 3]; |
110 FX_FLOAT end_r = pCoords->GetNumber(5); | 354 FX_BOOL bIntersect = _GetScanlineIntersect( |
111 CFX_AffineMatrix matrix; | 355 y, vertex1.x, vertex1.y, vertex2.x, vertex2.y, inter_x[nIntersects]); |
112 matrix.SetReverse(*pObject2Bitmap); | 356 if (!bIntersect) { |
113 FX_FLOAT t_min = 0, t_max = 1.0f; | 357 continue; |
114 CPDF_Array* pArray = pDict->GetArray(FX_BSTRC("Domain")); | 358 } |
115 if (pArray) { | 359 r[nIntersects] = |
116 t_min = pArray->GetNumber(0); | 360 vertex1.r + FXSYS_MulDiv(vertex2.r - vertex1.r, y - vertex1.y, |
117 t_max = pArray->GetNumber(1); | 361 vertex2.y - vertex1.y); |
118 } | 362 g[nIntersects] = |
119 FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE; | 363 vertex1.g + FXSYS_MulDiv(vertex2.g - vertex1.g, y - vertex1.y, |
120 pArray = pDict->GetArray(FX_BSTRC("Extend")); | 364 vertex2.y - vertex1.y); |
121 if (pArray) { | 365 b[nIntersects] = |
122 bStartExtend = pArray->GetInteger(0); | 366 vertex1.b + FXSYS_MulDiv(vertex2.b - vertex1.b, y - vertex1.y, |
123 bEndExtend = pArray->GetInteger(1); | 367 vertex2.y - vertex1.y); |
124 } | 368 nIntersects++; |
125 int total_results = 0; | 369 } |
126 for (int j = 0; j < nFuncs; j ++) { | 370 if (nIntersects != 2) { |
127 if (pFuncs[j]) { | 371 continue; |
128 total_results += pFuncs[j]->CountOutputs(); | 372 } |
129 } | 373 int min_x, max_x, start_index, end_index; |
130 } | 374 if (inter_x[0] < inter_x[1]) { |
131 if (pCS->CountComponents() > total_results) { | 375 min_x = (int)FXSYS_floor(inter_x[0]); |
132 total_results = pCS->CountComponents(); | 376 max_x = (int)FXSYS_ceil(inter_x[1]); |
133 } | 377 start_index = 0; |
134 CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results); | 378 end_index = 1; |
135 FX_FLOAT* pResults = result_array; | |
136 FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT)); | |
137 FX_DWORD rgb_array[SHADING_STEPS]; | |
138 for (int i = 0; i < SHADING_STEPS; i ++) { | |
139 FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min; | |
140 int offset = 0; | |
141 for (int j = 0; j < nFuncs; j ++) { | |
142 if (pFuncs[j]) { | |
143 int nresults; | |
144 if (pFuncs[j]->Call(&input, 1, pResults + offset, nresults)) { | |
145 offset += nresults; | |
146 } | |
147 } | |
148 } | |
149 FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; | |
150 pCS->GetRGB(pResults, R, G, B); | |
151 rgb_array[i] = FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255), FXS
YS_round(G * 255), FXSYS_round(B * 255))); | |
152 } | |
153 FX_FLOAT a = FXSYS_Mul(start_x - end_x, start_x - end_x) + | |
154 FXSYS_Mul(start_y - end_y, start_y - end_y) - FXSYS_Mul(start_r
- end_r, start_r - end_r); | |
155 int width = pBitmap->GetWidth(); | |
156 int height = pBitmap->GetHeight(); | |
157 int pitch = pBitmap->GetPitch(); | |
158 FX_BOOL bDecreasing = FALSE; | |
159 if (start_r > end_r) { | |
160 int length = (int)FXSYS_sqrt((FXSYS_Mul(start_x - end_x, start_x - end_x
) + FXSYS_Mul(start_y - end_y, start_y - end_y))); | |
161 if (length < start_r - end_r) { | |
162 bDecreasing = TRUE; | |
163 } | |
164 } | |
165 for (int row = 0; row < height; row ++) { | |
166 FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch); | |
167 for (int column = 0; column < width; column ++) { | |
168 FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row; | |
169 matrix.Transform(x, y); | |
170 FX_FLOAT b = -2 * (FXSYS_Mul(x - start_x, end_x - start_x) + FXSYS_M
ul(y - start_y, end_y - start_y) + | |
171 FXSYS_Mul(start_r, end_r - start_r)); | |
172 FX_FLOAT c = FXSYS_Mul(x - start_x, x - start_x) + FXSYS_Mul(y - sta
rt_y, y - start_y) - | |
173 FXSYS_Mul(start_r, start_r); | |
174 FX_FLOAT s; | |
175 if (a == 0) { | |
176 s = FXSYS_Div(-c, b); | |
177 } else { | |
178 FX_FLOAT b2_4ac = FXSYS_Mul(b, b) - 4 * FXSYS_Mul(a, c); | |
179 if (b2_4ac < 0) { | |
180 continue; | |
181 } | |
182 FX_FLOAT root = FXSYS_sqrt(b2_4ac); | |
183 FX_FLOAT s1, s2; | |
184 if (a > 0) { | |
185 s1 = FXSYS_Div(-b - root, 2 * a); | |
186 s2 = FXSYS_Div(-b + root, 2 * a); | |
187 } else { | |
188 s2 = FXSYS_Div(-b - root, 2 * a); | |
189 s1 = FXSYS_Div(-b + root, 2 * a); | |
190 } | |
191 if (bDecreasing) { | |
192 if (s1 >= 0 || bStartExtend) { | |
193 s = s1; | |
194 } else { | |
195 s = s2; | |
196 } | |
197 } else { | |
198 if (s2 <= 1.0f || bEndExtend) { | |
199 s = s2; | |
200 } else { | |
201 s = s1; | |
202 } | |
203 } | |
204 if ((start_r + s * (end_r - start_r)) < 0) { | |
205 continue; | |
206 } | |
207 } | |
208 int index = (int32_t)(s * (SHADING_STEPS - 1)); | |
209 if (index < 0) { | |
210 if (!bStartExtend) { | |
211 continue; | |
212 } | |
213 index = 0; | |
214 } | |
215 if (index >= SHADING_STEPS) { | |
216 if (!bEndExtend) { | |
217 continue; | |
218 } | |
219 index = SHADING_STEPS - 1; | |
220 } | |
221 dib_buf[column] = rgb_array[index]; | |
222 } | |
223 } | |
224 } | |
225 static void _DrawFuncShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pObject2Bi
tmap, | |
226 CPDF_Dictionary* pDict, CPDF_Function** pFuncs, int
nFuncs, | |
227 CPDF_ColorSpace* pCS, int alpha) | |
228 { | |
229 ASSERT(pBitmap->GetFormat() == FXDIB_Argb); | |
230 CPDF_Array* pDomain = pDict->GetArray(FX_BSTRC("Domain")); | |
231 FX_FLOAT xmin = 0, ymin = 0, xmax = 1.0f, ymax = 1.0f; | |
232 if (pDomain) { | |
233 xmin = pDomain->GetNumber(0); | |
234 xmax = pDomain->GetNumber(1); | |
235 ymin = pDomain->GetNumber(2); | |
236 ymax = pDomain->GetNumber(3); | |
237 } | |
238 CFX_AffineMatrix mtDomain2Target = pDict->GetMatrix(FX_BSTRC("Matrix")); | |
239 CFX_AffineMatrix matrix, reverse_matrix; | |
240 matrix.SetReverse(*pObject2Bitmap); | |
241 reverse_matrix.SetReverse(mtDomain2Target); | |
242 matrix.Concat(reverse_matrix); | |
243 int width = pBitmap->GetWidth(); | |
244 int height = pBitmap->GetHeight(); | |
245 int pitch = pBitmap->GetPitch(); | |
246 int total_results = 0; | |
247 for (int j = 0; j < nFuncs; j ++) { | |
248 if (pFuncs[j]) { | |
249 total_results += pFuncs[j]->CountOutputs(); | |
250 } | |
251 } | |
252 if (pCS->CountComponents() > total_results) { | |
253 total_results = pCS->CountComponents(); | |
254 } | |
255 CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results); | |
256 FX_FLOAT* pResults = result_array; | |
257 FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT)); | |
258 for (int row = 0; row < height; row ++) { | |
259 FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch); | |
260 for (int column = 0; column < width; column ++) { | |
261 FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row; | |
262 matrix.Transform(x, y); | |
263 if (x < xmin || x > xmax || y < ymin || y > ymax) { | |
264 continue; | |
265 } | |
266 FX_FLOAT input[2]; | |
267 int offset = 0; | |
268 input[0] = x; | |
269 input[1] = y; | |
270 for (int j = 0; j < nFuncs; j ++) { | |
271 if (pFuncs[j]) { | |
272 int nresults; | |
273 if (pFuncs[j]->Call(input, 2, pResults + offset, nresults))
{ | |
274 offset += nresults; | |
275 } | |
276 } | |
277 } | |
278 FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; | |
279 pCS->GetRGB(pResults, R, G, B); | |
280 dib_buf[column] = FXARGB_TODIB(FXARGB_MAKE(alpha, (int32_t)(R * 255)
, (int32_t)(G * 255), (int32_t)(B * 255))); | |
281 } | |
282 } | |
283 } | |
284 FX_BOOL _GetScanlineIntersect(int y, FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_F
LOAT y2, FX_FLOAT& x) | |
285 { | |
286 if (y1 == y2) { | |
287 return FALSE; | |
288 } | |
289 if (y1 < y2) { | |
290 if (y < y1 || y > y2) { | |
291 return FALSE; | |
292 } | |
293 } else { | 379 } else { |
294 if (y < y2 || y > y1) { | 380 min_x = (int)FXSYS_floor(inter_x[1]); |
295 return FALSE; | 381 max_x = (int)FXSYS_ceil(inter_x[0]); |
296 } | 382 start_index = 1; |
297 } | 383 end_index = 0; |
298 x = x1 + FXSYS_MulDiv(x2 - x1, y - y1, y2 - y1); | 384 } |
299 return TRUE; | 385 int start_x = min_x, end_x = max_x; |
300 } | 386 if (start_x < 0) { |
301 static void _DrawGouraud(CFX_DIBitmap* pBitmap, int alpha, CPDF_MeshVertex trian
gle[3]) | 387 start_x = 0; |
302 { | 388 } |
303 FX_FLOAT min_y = triangle[0].y, max_y = triangle[0].y; | 389 if (end_x > pBitmap->GetWidth()) { |
304 for (int i = 1; i < 3; i ++) { | 390 end_x = pBitmap->GetWidth(); |
305 if (min_y > triangle[i].y) { | 391 } |
306 min_y = triangle[i].y; | 392 uint8_t* dib_buf = |
307 } | 393 pBitmap->GetBuffer() + y * pBitmap->GetPitch() + start_x * 4; |
308 if (max_y < triangle[i].y) { | 394 FX_FLOAT r_unit = (r[end_index] - r[start_index]) / (max_x - min_x); |
309 max_y = triangle[i].y; | 395 FX_FLOAT g_unit = (g[end_index] - g[start_index]) / (max_x - min_x); |
310 } | 396 FX_FLOAT b_unit = (b[end_index] - b[start_index]) / (max_x - min_x); |
311 } | 397 FX_FLOAT R = r[start_index] + (start_x - min_x) * r_unit; |
312 if (min_y == max_y) { | 398 FX_FLOAT G = g[start_index] + (start_x - min_x) * g_unit; |
313 return; | 399 FX_FLOAT B = b[start_index] + (start_x - min_x) * b_unit; |
314 } | 400 for (int x = start_x; x < end_x; x++) { |
315 int min_yi = (int)FXSYS_floor(min_y), max_yi = (int)FXSYS_ceil(max_y); | 401 R += r_unit; |
316 if (min_yi < 0) { | 402 G += g_unit; |
317 min_yi = 0; | 403 B += b_unit; |
318 } | 404 FXARGB_SETDIB(dib_buf, |
319 if (max_yi >= pBitmap->GetHeight()) { | 405 FXARGB_MAKE(alpha, (int32_t)(R * 255), (int32_t)(G * 255), |
320 max_yi = pBitmap->GetHeight() - 1; | 406 (int32_t)(B * 255))); |
321 } | 407 dib_buf += 4; |
322 for (int y = min_yi; y <= max_yi; y ++) { | 408 } |
323 int nIntersects = 0; | 409 } |
324 FX_FLOAT inter_x[3], r[3], g[3], b[3]; | 410 } |
325 for (int i = 0; i < 3; i ++) { | 411 static void _DrawFreeGouraudShading(CFX_DIBitmap* pBitmap, |
326 CPDF_MeshVertex& vertex1 = triangle[i]; | 412 CFX_AffineMatrix* pObject2Bitmap, |
327 CPDF_MeshVertex& vertex2 = triangle[(i + 1) % 3]; | 413 CPDF_Stream* pShadingStream, |
328 FX_BOOL bIntersect = _GetScanlineIntersect(y, vertex1.x, vertex1.y, | 414 CPDF_Function** pFuncs, |
329 vertex2.x, vertex2.y, inter_x[nIntersects]); | 415 int nFuncs, |
330 if (!bIntersect) { | 416 CPDF_ColorSpace* pCS, |
331 continue; | 417 int alpha) { |
332 } | 418 ASSERT(pBitmap->GetFormat() == FXDIB_Argb); |
333 r[nIntersects] = vertex1.r + FXSYS_MulDiv(vertex2.r - vertex1.r, y -
vertex1.y, vertex2.y - vertex1.y); | 419 if (pShadingStream->GetType() != PDFOBJ_STREAM) { |
334 g[nIntersects] = vertex1.g + FXSYS_MulDiv(vertex2.g - vertex1.g, y -
vertex1.y, vertex2.y - vertex1.y); | 420 return; |
335 b[nIntersects] = vertex1.b + FXSYS_MulDiv(vertex2.b - vertex1.b, y -
vertex1.y, vertex2.y - vertex1.y); | 421 } |
336 nIntersects ++; | 422 CPDF_MeshStream stream; |
337 } | 423 if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS)) { |
338 if (nIntersects != 2) { | 424 return; |
339 continue; | 425 } |
340 } | 426 CPDF_MeshVertex triangle[3]; |
341 int min_x, max_x, start_index, end_index; | 427 FXSYS_memset(triangle, 0, sizeof(triangle)); |
342 if (inter_x[0] < inter_x[1]) { | 428 |
343 min_x = (int)FXSYS_floor(inter_x[0]); | 429 while (!stream.m_BitStream.IsEOF()) { |
344 max_x = (int)FXSYS_ceil(inter_x[1]); | 430 CPDF_MeshVertex vertex; |
345 start_index = 0; | 431 FX_DWORD flag = stream.GetVertex(vertex, pObject2Bitmap); |
346 end_index = 1; | 432 if (flag == 0) { |
347 } else { | 433 triangle[0] = vertex; |
348 min_x = (int)FXSYS_floor(inter_x[1]); | 434 for (int j = 1; j < 3; j++) { |
349 max_x = (int)FXSYS_ceil(inter_x[0]); | 435 stream.GetVertex(triangle[j], pObject2Bitmap); |
350 start_index = 1; | 436 } |
351 end_index = 0; | 437 } else { |
352 } | 438 if (flag == 1) { |
353 int start_x = min_x, end_x = max_x; | 439 triangle[0] = triangle[1]; |
354 if (start_x < 0) { | 440 } |
355 start_x = 0; | 441 triangle[1] = triangle[2]; |
356 } | 442 triangle[2] = vertex; |
357 if (end_x > pBitmap->GetWidth()) { | 443 } |
358 end_x = pBitmap->GetWidth(); | 444 _DrawGouraud(pBitmap, alpha, triangle); |
359 } | 445 } |
360 uint8_t* dib_buf = pBitmap->GetBuffer() + y * pBitmap->GetPitch() + star
t_x * 4; | 446 } |
361 FX_FLOAT r_unit = (r[end_index] - r[start_index]) / (max_x - min_x); | 447 static void _DrawLatticeGouraudShading(CFX_DIBitmap* pBitmap, |
362 FX_FLOAT g_unit = (g[end_index] - g[start_index]) / (max_x - min_x); | 448 CFX_AffineMatrix* pObject2Bitmap, |
363 FX_FLOAT b_unit = (b[end_index] - b[start_index]) / (max_x - min_x); | 449 CPDF_Stream* pShadingStream, |
364 FX_FLOAT R = r[start_index] + (start_x - min_x) * r_unit; | 450 CPDF_Function** pFuncs, |
365 FX_FLOAT G = g[start_index] + (start_x - min_x) * g_unit; | 451 int nFuncs, |
366 FX_FLOAT B = b[start_index] + (start_x - min_x) * b_unit; | 452 CPDF_ColorSpace* pCS, |
367 for (int x = start_x; x < end_x; x ++) { | 453 int alpha) { |
368 R += r_unit; | 454 ASSERT(pBitmap->GetFormat() == FXDIB_Argb); |
369 G += g_unit; | 455 if (pShadingStream->GetType() != PDFOBJ_STREAM) { |
370 B += b_unit; | 456 return; |
371 FXARGB_SETDIB(dib_buf, FXARGB_MAKE(alpha, (int32_t)(R * 255), (int32
_t)(G * 255), (int32_t)(B * 255))); | 457 } |
372 dib_buf += 4; | 458 int row_verts = pShadingStream->GetDict()->GetInteger("VerticesPerRow"); |
373 } | 459 if (row_verts < 2) { |
374 } | 460 return; |
375 } | 461 } |
376 static void _DrawFreeGouraudShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix* pOb
ject2Bitmap, | 462 CPDF_MeshStream stream; |
377 CPDF_Stream* pShadingStream, CPDF_Function**
pFuncs, int nFuncs, | 463 if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS)) { |
378 CPDF_ColorSpace* pCS, int alpha) | 464 return; |
379 { | 465 } |
380 ASSERT(pBitmap->GetFormat() == FXDIB_Argb); | 466 CPDF_MeshVertex* vertex = FX_Alloc2D(CPDF_MeshVertex, row_verts, 2); |
381 if (pShadingStream->GetType() != PDFOBJ_STREAM) { | 467 if (!stream.GetVertexRow(vertex, row_verts, pObject2Bitmap)) { |
382 return; | 468 FX_Free(vertex); |
383 } | 469 return; |
384 CPDF_MeshStream stream; | 470 } |
385 if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS)) { | 471 int last_index = 0; |
386 return; | 472 while (1) { |
| 473 CPDF_MeshVertex* last_row = vertex + last_index * row_verts; |
| 474 CPDF_MeshVertex* this_row = vertex + (1 - last_index) * row_verts; |
| 475 if (!stream.GetVertexRow(this_row, row_verts, pObject2Bitmap)) { |
| 476 FX_Free(vertex); |
| 477 return; |
387 } | 478 } |
388 CPDF_MeshVertex triangle[3]; | 479 CPDF_MeshVertex triangle[3]; |
389 FXSYS_memset(triangle, 0, sizeof(triangle)); | 480 for (int i = 1; i < row_verts; i++) { |
390 | 481 triangle[0] = last_row[i]; |
391 while (!stream.m_BitStream.IsEOF()) { | 482 triangle[1] = this_row[i - 1]; |
392 CPDF_MeshVertex vertex; | 483 triangle[2] = last_row[i - 1]; |
393 FX_DWORD flag = stream.GetVertex(vertex, pObject2Bitmap); | 484 _DrawGouraud(pBitmap, alpha, triangle); |
394 if (flag == 0) { | 485 triangle[2] = this_row[i]; |
395 triangle[0] = vertex; | 486 _DrawGouraud(pBitmap, alpha, triangle); |
396 for (int j = 1; j < 3; j ++) { | 487 } |
397 stream.GetVertex(triangle[j], pObject2Bitmap); | 488 last_index = 1 - last_index; |
398 } | 489 } |
399 } else { | 490 FX_Free(vertex); |
400 if (flag == 1) { | |
401 triangle[0] = triangle[1]; | |
402 } | |
403 triangle[1] = triangle[2]; | |
404 triangle[2] = vertex; | |
405 } | |
406 _DrawGouraud(pBitmap, alpha, triangle); | |
407 } | |
408 } | |
409 static void _DrawLatticeGouraudShading(CFX_DIBitmap* pBitmap, CFX_AffineMatrix*
pObject2Bitmap, | |
410 CPDF_Stream* pShadingStream, CPDF_Functio
n** pFuncs, int nFuncs, | |
411 CPDF_ColorSpace* pCS, int alpha) | |
412 { | |
413 ASSERT(pBitmap->GetFormat() == FXDIB_Argb); | |
414 if (pShadingStream->GetType() != PDFOBJ_STREAM) { | |
415 return; | |
416 } | |
417 int row_verts = pShadingStream->GetDict()->GetInteger("VerticesPerRow"); | |
418 if (row_verts < 2) { | |
419 return; | |
420 } | |
421 CPDF_MeshStream stream; | |
422 if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS)) { | |
423 return; | |
424 } | |
425 CPDF_MeshVertex* vertex = FX_Alloc2D(CPDF_MeshVertex, row_verts, 2); | |
426 if (!stream.GetVertexRow(vertex, row_verts, pObject2Bitmap)) { | |
427 FX_Free(vertex); | |
428 return; | |
429 } | |
430 int last_index = 0; | |
431 while (1) { | |
432 CPDF_MeshVertex* last_row = vertex + last_index * row_verts; | |
433 CPDF_MeshVertex* this_row = vertex + (1 - last_index) * row_verts; | |
434 if (!stream.GetVertexRow(this_row, row_verts, pObject2Bitmap)) { | |
435 FX_Free(vertex); | |
436 return; | |
437 } | |
438 CPDF_MeshVertex triangle[3]; | |
439 for (int i = 1; i < row_verts; i ++) { | |
440 triangle[0] = last_row[i]; | |
441 triangle[1] = this_row[i - 1]; | |
442 triangle[2] = last_row[i - 1]; | |
443 _DrawGouraud(pBitmap, alpha, triangle); | |
444 triangle[2] = this_row[i]; | |
445 _DrawGouraud(pBitmap, alpha, triangle); | |
446 } | |
447 last_index = 1 - last_index; | |
448 } | |
449 FX_Free(vertex); | |
450 } | 491 } |
451 struct Coon_BezierCoeff { | 492 struct Coon_BezierCoeff { |
452 float a, b, c, d; | 493 float a, b, c, d; |
453 void FromPoints(float p0, float p1, float p2, float p3) | 494 void FromPoints(float p0, float p1, float p2, float p3) { |
454 { | 495 a = -p0 + 3 * p1 - 3 * p2 + p3; |
455 a = -p0 + 3 * p1 - 3 * p2 + p3; | 496 b = 3 * p0 - 6 * p1 + 3 * p2; |
456 b = 3 * p0 - 6 * p1 + 3 * p2; | 497 c = -3 * p0 + 3 * p1; |
457 c = -3 * p0 + 3 * p1; | 498 d = p0; |
458 d = p0; | 499 } |
459 } | 500 Coon_BezierCoeff first_half() { |
460 Coon_BezierCoeff first_half() | 501 Coon_BezierCoeff result; |
461 { | 502 result.a = a / 8; |
462 Coon_BezierCoeff result; | 503 result.b = b / 4; |
463 result.a = a / 8; | 504 result.c = c / 2; |
464 result.b = b / 4; | 505 result.d = d; |
465 result.c = c / 2; | 506 return result; |
466 result.d = d; | 507 } |
467 return result; | 508 Coon_BezierCoeff second_half() { |
468 } | 509 Coon_BezierCoeff result; |
469 Coon_BezierCoeff second_half() | 510 result.a = a / 8; |
470 { | 511 result.b = 3 * a / 8 + b / 4; |
471 Coon_BezierCoeff result; | 512 result.c = 3 * a / 8 + b / 2 + c / 2; |
472 result.a = a / 8; | 513 result.d = a / 8 + b / 4 + c / 2 + d; |
473 result.b = 3 * a / 8 + b / 4; | 514 return result; |
474 result.c = 3 * a / 8 + b / 2 + c / 2; | 515 } |
475 result.d = a / 8 + b / 4 + c / 2 + d; | 516 void GetPoints(float p[4]) { |
476 return result; | 517 p[0] = d; |
477 } | 518 p[1] = c / 3 + p[0]; |
478 void GetPoints(float p[4]) | 519 p[2] = b / 3 - p[0] + 2 * p[1]; |
479 { | 520 p[3] = a + p[0] - 3 * p[1] + 3 * p[2]; |
480 p[0] = d; | 521 } |
481 p[1] = c / 3 + p[0]; | 522 void GetPointsReverse(float p[4]) { |
482 p[2] = b / 3 - p[0] + 2 * p[1]; | 523 p[3] = d; |
483 p[3] = a + p[0] - 3 * p[1] + 3 * p[2]; | 524 p[2] = c / 3 + p[3]; |
484 } | 525 p[1] = b / 3 - p[3] + 2 * p[2]; |
485 void GetPointsReverse(float p[4]) | 526 p[0] = a + p[3] - 3 * p[2] + 3 * p[1]; |
486 { | 527 } |
487 p[3] = d; | 528 void BezierInterpol(Coon_BezierCoeff& C1, |
488 p[2] = c / 3 + p[3]; | 529 Coon_BezierCoeff& C2, |
489 p[1] = b / 3 - p[3] + 2 * p[2]; | 530 Coon_BezierCoeff& D1, |
490 p[0] = a + p[3] - 3 * p[2] + 3 * p[1]; | 531 Coon_BezierCoeff& D2) { |
491 } | 532 a = (D1.a + D2.a) / 2; |
492 void BezierInterpol(Coon_BezierCoeff& C1, Coon_BezierCoeff& C2, Coon_BezierC
oeff& D1, Coon_BezierCoeff& D2) | 533 b = (D1.b + D2.b) / 2; |
493 { | 534 c = (D1.c + D2.c) / 2 - (C1.a / 8 + C1.b / 4 + C1.c / 2) + |
494 a = (D1.a + D2.a) / 2; | 535 (C2.a / 8 + C2.b / 4) + (-C1.d + D2.d) / 2 - (C2.a + C2.b) / 2; |
495 b = (D1.b + D2.b) / 2; | 536 d = C1.a / 8 + C1.b / 4 + C1.c / 2 + C1.d; |
496 c = (D1.c + D2.c) / 2 - (C1.a / 8 + C1.b / 4 + C1.c / 2) + (C2.a / 8 + C
2.b / 4) + (-C1.d + D2.d) / 2 - (C2.a + C2.b) / 2; | 537 } |
497 d = C1.a / 8 + C1.b / 4 + C1.c / 2 + C1.d; | 538 float Distance() { |
498 } | 539 float dis = a + b + c; |
499 float Distance() | 540 return dis < 0 ? -dis : dis; |
500 { | 541 } |
501 float dis = a + b + c; | |
502 return dis < 0 ? -dis : dis; | |
503 } | |
504 }; | 542 }; |
505 struct Coon_Bezier { | 543 struct Coon_Bezier { |
506 Coon_BezierCoeff x, y; | 544 Coon_BezierCoeff x, y; |
507 void FromPoints(float x0, float y0, float x1, float y1, float x2, float y2,
float x3, float y3) | 545 void FromPoints(float x0, |
508 { | 546 float y0, |
509 x.FromPoints(x0, x1, x2, x3); | 547 float x1, |
510 y.FromPoints(y0, y1, y2, y3); | 548 float y1, |
511 } | 549 float x2, |
512 Coon_Bezier first_half() | 550 float y2, |
513 { | 551 float x3, |
514 Coon_Bezier result; | 552 float y3) { |
515 result.x = x.first_half(); | 553 x.FromPoints(x0, x1, x2, x3); |
516 result.y = y.first_half(); | 554 y.FromPoints(y0, y1, y2, y3); |
517 return result; | 555 } |
518 } | 556 Coon_Bezier first_half() { |
519 Coon_Bezier second_half() | 557 Coon_Bezier result; |
520 { | 558 result.x = x.first_half(); |
521 Coon_Bezier result; | 559 result.y = y.first_half(); |
522 result.x = x.second_half(); | 560 return result; |
523 result.y = y.second_half(); | 561 } |
524 return result; | 562 Coon_Bezier second_half() { |
525 } | 563 Coon_Bezier result; |
526 void BezierInterpol(Coon_Bezier& C1, Coon_Bezier& C2, Coon_Bezier& D1, Coon_
Bezier& D2) | 564 result.x = x.second_half(); |
527 { | 565 result.y = y.second_half(); |
528 x.BezierInterpol(C1.x, C2.x, D1.x, D2.x); | 566 return result; |
529 y.BezierInterpol(C1.y, C2.y, D1.y, D2.y); | 567 } |
530 } | 568 void BezierInterpol(Coon_Bezier& C1, |
531 void GetPoints(FX_PATHPOINT* pPoints) | 569 Coon_Bezier& C2, |
532 { | 570 Coon_Bezier& D1, |
533 float p[4]; | 571 Coon_Bezier& D2) { |
534 int i; | 572 x.BezierInterpol(C1.x, C2.x, D1.x, D2.x); |
535 x.GetPoints(p); | 573 y.BezierInterpol(C1.y, C2.y, D1.y, D2.y); |
536 for (i = 0; i < 4; i ++) { | 574 } |
537 pPoints[i].m_PointX = p[i]; | 575 void GetPoints(FX_PATHPOINT* pPoints) { |
538 } | 576 float p[4]; |
539 y.GetPoints(p); | 577 int i; |
540 for (i = 0; i < 4; i ++) { | 578 x.GetPoints(p); |
541 pPoints[i].m_PointY = p[i]; | 579 for (i = 0; i < 4; i++) { |
542 } | 580 pPoints[i].m_PointX = p[i]; |
543 } | 581 } |
544 void GetPointsReverse(FX_PATHPOINT* pPoints) | 582 y.GetPoints(p); |
545 { | 583 for (i = 0; i < 4; i++) { |
546 float p[4]; | 584 pPoints[i].m_PointY = p[i]; |
547 int i; | 585 } |
548 x.GetPointsReverse(p); | 586 } |
549 for (i = 0; i < 4; i ++) { | 587 void GetPointsReverse(FX_PATHPOINT* pPoints) { |
550 pPoints[i].m_PointX = p[i]; | 588 float p[4]; |
551 } | 589 int i; |
552 y.GetPointsReverse(p); | 590 x.GetPointsReverse(p); |
553 for (i = 0; i < 4; i ++) { | 591 for (i = 0; i < 4; i++) { |
554 pPoints[i].m_PointY = p[i]; | 592 pPoints[i].m_PointX = p[i]; |
555 } | 593 } |
556 } | 594 y.GetPointsReverse(p); |
557 float Distance() | 595 for (i = 0; i < 4; i++) { |
558 { | 596 pPoints[i].m_PointY = p[i]; |
559 return x.Distance() + y.Distance(); | 597 } |
560 } | 598 } |
| 599 float Distance() { return x.Distance() + y.Distance(); } |
561 }; | 600 }; |
562 static int _BiInterpol(int c0, int c1, int c2, int c3, int x, int y, int x_scale
, int y_scale) | 601 static int _BiInterpol(int c0, |
563 { | 602 int c1, |
564 int x1 = c0 + (c3 - c0) * x / x_scale; | 603 int c2, |
565 int x2 = c1 + (c2 - c1) * x / x_scale; | 604 int c3, |
566 return x1 + (x2 - x1) * y / y_scale; | 605 int x, |
| 606 int y, |
| 607 int x_scale, |
| 608 int y_scale) { |
| 609 int x1 = c0 + (c3 - c0) * x / x_scale; |
| 610 int x2 = c1 + (c2 - c1) * x / x_scale; |
| 611 return x1 + (x2 - x1) * y / y_scale; |
567 } | 612 } |
568 struct Coon_Color { | 613 struct Coon_Color { |
569 Coon_Color() | 614 Coon_Color() { FXSYS_memset(comp, 0, sizeof(int) * 3); } |
570 { | 615 int comp[3]; |
571 FXSYS_memset(comp, 0, sizeof(int) * 3); | 616 void BiInterpol(Coon_Color colors[4], |
572 } | 617 int x, |
573 int»» comp[3]; | 618 int y, |
574 void» BiInterpol(Coon_Color colors[4], int x, int y, int x_scale, int
y_scale) | 619 int x_scale, |
575 { | 620 int y_scale) { |
576 for (int i = 0; i < 3; i ++) | 621 for (int i = 0; i < 3; i++) |
577 comp[i] = _BiInterpol(colors[0].comp[i], colors[1].comp[i], colors[2
].comp[i], colors[3].comp[i], | 622 comp[i] = |
578 x, y, x_scale, y_scale); | 623 _BiInterpol(colors[0].comp[i], colors[1].comp[i], colors[2].comp[i], |
579 } | 624 colors[3].comp[i], x, y, x_scale, y_scale); |
580 int»» Distance(Coon_Color& o) | 625 } |
581 { | 626 int Distance(Coon_Color& o) { |
582 int max, diff; | 627 int max, diff; |
583 max = FXSYS_abs(comp[0] - o.comp[0]); | 628 max = FXSYS_abs(comp[0] - o.comp[0]); |
584 diff = FXSYS_abs(comp[1] - o.comp[1]); | 629 diff = FXSYS_abs(comp[1] - o.comp[1]); |
585 if (max < diff) { | 630 if (max < diff) { |
586 max = diff; | 631 max = diff; |
587 } | 632 } |
588 diff = FXSYS_abs(comp[2] - o.comp[2]); | 633 diff = FXSYS_abs(comp[2] - o.comp[2]); |
589 if (max < diff) { | 634 if (max < diff) { |
590 max = diff; | 635 max = diff; |
591 } | 636 } |
592 return max; | 637 return max; |
593 } | 638 } |
594 }; | 639 }; |
595 struct CPDF_PatchDrawer { | 640 struct CPDF_PatchDrawer { |
596 Coon_Color» » » patch_colors[4]; | 641 Coon_Color patch_colors[4]; |
597 int»» » » » max_delta; | 642 int max_delta; |
598 CFX_PathData» » path; | 643 CFX_PathData path; |
599 CFX_RenderDevice*» pDevice; | 644 CFX_RenderDevice* pDevice; |
600 int»» » » » fill_mode; | 645 int fill_mode; |
601 int»» » » » alpha; | 646 int alpha; |
602 void Draw(int x_scale, int y_scale, int left, int bottom, Coon_Bezier C1, Co
on_Bezier C2, Coon_Bezier D1, Coon_Bezier D2) | 647 void Draw(int x_scale, |
603 { | 648 int y_scale, |
604 FX_BOOL bSmall = C1.Distance() < 2 && C2.Distance() < 2 && D1.Distance()
< 2 && D2.Distance() < 2; | 649 int left, |
605 Coon_Color div_colors[4]; | 650 int bottom, |
606 int d_bottom, d_left, d_top, d_right; | 651 Coon_Bezier C1, |
607 div_colors[0].BiInterpol(patch_colors, left, bottom, x_scale, y_scale); | 652 Coon_Bezier C2, |
608 if (!bSmall) { | 653 Coon_Bezier D1, |
609 div_colors[1].BiInterpol(patch_colors, left, bottom + 1, x_scale, y_
scale); | 654 Coon_Bezier D2) { |
610 div_colors[2].BiInterpol(patch_colors, left + 1, bottom + 1, x_scale
, y_scale); | 655 FX_BOOL bSmall = C1.Distance() < 2 && C2.Distance() < 2 && |
611 div_colors[3].BiInterpol(patch_colors, left + 1, bottom, x_scale, y_
scale); | 656 D1.Distance() < 2 && D2.Distance() < 2; |
612 d_bottom = div_colors[3].Distance(div_colors[0]); | 657 Coon_Color div_colors[4]; |
613 d_left = div_colors[1].Distance(div_colors[0]); | 658 int d_bottom, d_left, d_top, d_right; |
614 d_top = div_colors[1].Distance(div_colors[2]); | 659 div_colors[0].BiInterpol(patch_colors, left, bottom, x_scale, y_scale); |
615 d_right = div_colors[2].Distance(div_colors[3]); | 660 if (!bSmall) { |
616 } | 661 div_colors[1].BiInterpol(patch_colors, left, bottom + 1, x_scale, |
| 662 y_scale); |
| 663 div_colors[2].BiInterpol(patch_colors, left + 1, bottom + 1, x_scale, |
| 664 y_scale); |
| 665 div_colors[3].BiInterpol(patch_colors, left + 1, bottom, x_scale, |
| 666 y_scale); |
| 667 d_bottom = div_colors[3].Distance(div_colors[0]); |
| 668 d_left = div_colors[1].Distance(div_colors[0]); |
| 669 d_top = div_colors[1].Distance(div_colors[2]); |
| 670 d_right = div_colors[2].Distance(div_colors[3]); |
| 671 } |
617 #define COONCOLOR_THRESHOLD 4 | 672 #define COONCOLOR_THRESHOLD 4 |
618 if (bSmall || (d_bottom < COONCOLOR_THRESHOLD && d_left < COONCOLOR_THRE
SHOLD && | 673 if (bSmall || |
619 d_top < COONCOLOR_THRESHOLD && d_right < COONCOLOR_THRESH
OLD)) { | 674 (d_bottom < COONCOLOR_THRESHOLD && d_left < COONCOLOR_THRESHOLD && |
620 FX_PATHPOINT* pPoints = path.GetPoints(); | 675 d_top < COONCOLOR_THRESHOLD && d_right < COONCOLOR_THRESHOLD)) { |
621 C1.GetPoints(pPoints); | 676 FX_PATHPOINT* pPoints = path.GetPoints(); |
622 D2.GetPoints(pPoints + 3); | 677 C1.GetPoints(pPoints); |
623 C2.GetPointsReverse(pPoints + 6); | 678 D2.GetPoints(pPoints + 3); |
624 D1.GetPointsReverse(pPoints + 9); | 679 C2.GetPointsReverse(pPoints + 6); |
625 int fillFlags = FXFILL_WINDING | FXFILL_FULLCOVER; | 680 D1.GetPointsReverse(pPoints + 9); |
626 if (fill_mode & RENDER_NOPATHSMOOTH) { | 681 int fillFlags = FXFILL_WINDING | FXFILL_FULLCOVER; |
627 fillFlags |= FXFILL_NOPATHSMOOTH; | 682 if (fill_mode & RENDER_NOPATHSMOOTH) { |
628 } | 683 fillFlags |= FXFILL_NOPATHSMOOTH; |
629 pDevice->DrawPath(&path, NULL, NULL, FXARGB_MAKE(alpha, div_colors[0
].comp[0], div_colors[0].comp[1], div_colors[0].comp[2]), 0, fillFlags); | 684 } |
630 } else { | 685 pDevice->DrawPath( |
631 if (d_bottom < COONCOLOR_THRESHOLD && d_top < COONCOLOR_THRESHOLD) { | 686 &path, NULL, NULL, |
632 Coon_Bezier m1; | 687 FXARGB_MAKE(alpha, div_colors[0].comp[0], div_colors[0].comp[1], |
633 m1.BezierInterpol(D1, D2, C1, C2); | 688 div_colors[0].comp[2]), |
634 y_scale *= 2; | 689 0, fillFlags); |
635 bottom *= 2; | 690 } else { |
636 Draw(x_scale, y_scale, left, bottom, C1, m1, D1.first_half(), D2
.first_half()); | 691 if (d_bottom < COONCOLOR_THRESHOLD && d_top < COONCOLOR_THRESHOLD) { |
637 Draw(x_scale, y_scale, left, bottom + 1, m1, C2, D1.second_half(
), D2.second_half()); | 692 Coon_Bezier m1; |
638 } else if (d_left < COONCOLOR_THRESHOLD && d_right < COONCOLOR_THRES
HOLD) { | 693 m1.BezierInterpol(D1, D2, C1, C2); |
639 Coon_Bezier m2; | 694 y_scale *= 2; |
640 m2.BezierInterpol(C1, C2, D1, D2); | 695 bottom *= 2; |
641 x_scale *= 2; | 696 Draw(x_scale, y_scale, left, bottom, C1, m1, D1.first_half(), |
642 left *= 2; | 697 D2.first_half()); |
643 Draw(x_scale, y_scale, left, bottom, C1.first_half(), C2.first_h
alf(), D1, m2); | 698 Draw(x_scale, y_scale, left, bottom + 1, m1, C2, D1.second_half(), |
644 Draw(x_scale, y_scale, left + 1, bottom, C1.second_half(), C2.se
cond_half(), m2, D2); | 699 D2.second_half()); |
645 } else { | 700 } else if (d_left < COONCOLOR_THRESHOLD && |
646 Coon_Bezier m1, m2; | 701 d_right < COONCOLOR_THRESHOLD) { |
647 m1.BezierInterpol(D1, D2, C1, C2); | 702 Coon_Bezier m2; |
648 m2.BezierInterpol(C1, C2, D1, D2); | 703 m2.BezierInterpol(C1, C2, D1, D2); |
649 Coon_Bezier m1f = m1.first_half(); | 704 x_scale *= 2; |
650 Coon_Bezier m1s = m1.second_half(); | 705 left *= 2; |
651 Coon_Bezier m2f = m2.first_half(); | 706 Draw(x_scale, y_scale, left, bottom, C1.first_half(), C2.first_half(), |
652 Coon_Bezier m2s = m2.second_half(); | 707 D1, m2); |
653 x_scale *= 2; | 708 Draw(x_scale, y_scale, left + 1, bottom, C1.second_half(), |
654 y_scale *= 2; | 709 C2.second_half(), m2, D2); |
655 left *= 2; | 710 } else { |
656 bottom *= 2; | 711 Coon_Bezier m1, m2; |
657 Draw(x_scale, y_scale, left, bottom, C1.first_half(), m1f, D1.fi
rst_half(), m2f); | 712 m1.BezierInterpol(D1, D2, C1, C2); |
658 Draw(x_scale, y_scale, left, bottom + 1, m1f, C2.first_half(), D
1.second_half(), m2s); | 713 m2.BezierInterpol(C1, C2, D1, D2); |
659 Draw(x_scale, y_scale, left + 1, bottom, C1.second_half(), m1s,
m2f, D2.first_half()); | 714 Coon_Bezier m1f = m1.first_half(); |
660 Draw(x_scale, y_scale, left + 1, bottom + 1, m1s, C2.second_half
(), m2s, D2.second_half()); | 715 Coon_Bezier m1s = m1.second_half(); |
661 } | 716 Coon_Bezier m2f = m2.first_half(); |
662 } | 717 Coon_Bezier m2s = m2.second_half(); |
663 } | 718 x_scale *= 2; |
| 719 y_scale *= 2; |
| 720 left *= 2; |
| 721 bottom *= 2; |
| 722 Draw(x_scale, y_scale, left, bottom, C1.first_half(), m1f, |
| 723 D1.first_half(), m2f); |
| 724 Draw(x_scale, y_scale, left, bottom + 1, m1f, C2.first_half(), |
| 725 D1.second_half(), m2s); |
| 726 Draw(x_scale, y_scale, left + 1, bottom, C1.second_half(), m1s, m2f, |
| 727 D2.first_half()); |
| 728 Draw(x_scale, y_scale, left + 1, bottom + 1, m1s, C2.second_half(), m2s, |
| 729 D2.second_half()); |
| 730 } |
| 731 } |
| 732 } |
664 }; | 733 }; |
665 | 734 |
666 FX_BOOL _CheckCoonTensorPara(const CPDF_MeshStream &stream) | 735 FX_BOOL _CheckCoonTensorPara(const CPDF_MeshStream& stream) { |
667 { | 736 FX_BOOL bCoorBits = (stream.m_nCoordBits == 1 || stream.m_nCoordBits == 2 || |
668 FX_BOOL bCoorBits = ( stream.m_nCoordBits== 1 || | 737 stream.m_nCoordBits == 4 || stream.m_nCoordBits == 8 || |
669 stream.m_nCoordBits == 2 || | 738 stream.m_nCoordBits == 12 || stream.m_nCoordBits == 16 || |
670 stream.m_nCoordBits == 4 || | 739 stream.m_nCoordBits == 24 || stream.m_nCoordBits == 32); |
671 stream.m_nCoordBits == 8 || | |
672 stream.m_nCoordBits == 12 || | |
673 stream.m_nCoordBits == 16 || | |
674 stream.m_nCoordBits == 24 || | |
675 stream.m_nCoordBits == 32 ); | |
676 | 740 |
677 FX_BOOL bCompBits = ( stream.m_nCompBits == 1 || | 741 FX_BOOL bCompBits = (stream.m_nCompBits == 1 || stream.m_nCompBits == 2 || |
678 stream.m_nCompBits == 2 || | 742 stream.m_nCompBits == 4 || stream.m_nCompBits == 8 || |
679 stream.m_nCompBits == 4 || | 743 stream.m_nCompBits == 12 || stream.m_nCompBits == 16); |
680 stream.m_nCompBits == 8 || | |
681 stream.m_nCompBits == 12 || | |
682 stream.m_nCompBits == 16 ); | |
683 | 744 |
684 FX_BOOL bFlagBits = ( stream.m_nFlagBits == 2 || | 745 FX_BOOL bFlagBits = (stream.m_nFlagBits == 2 || stream.m_nFlagBits == 4 || |
685 stream.m_nFlagBits == 4 || | 746 stream.m_nFlagBits == 8); |
686 stream.m_nFlagBits == 8 ); | |
687 | 747 |
688 return bCoorBits && bCompBits && bFlagBits; | 748 return bCoorBits && bCompBits && bFlagBits; |
689 } | 749 } |
690 | 750 |
691 static void _DrawCoonPatchMeshes(FX_BOOL bTensor, CFX_DIBitmap* pBitmap, CFX_Aff
ineMatrix* pObject2Bitmap, | 751 static void _DrawCoonPatchMeshes(FX_BOOL bTensor, |
692 CPDF_Stream* pShadingStream, CPDF_Function** pF
uncs, int nFuncs, | 752 CFX_DIBitmap* pBitmap, |
693 CPDF_ColorSpace* pCS, int fill_mode, int alpha) | 753 CFX_AffineMatrix* pObject2Bitmap, |
694 { | 754 CPDF_Stream* pShadingStream, |
695 ASSERT(pBitmap->GetFormat() == FXDIB_Argb); | 755 CPDF_Function** pFuncs, |
696 if (pShadingStream->GetType() != PDFOBJ_STREAM) { | 756 int nFuncs, |
697 return; | 757 CPDF_ColorSpace* pCS, |
698 } | 758 int fill_mode, |
699 CFX_FxgeDevice device; | 759 int alpha) { |
700 device.Attach(pBitmap); | 760 ASSERT(pBitmap->GetFormat() == FXDIB_Argb); |
701 CPDF_MeshStream stream; | 761 if (pShadingStream->GetType() != PDFOBJ_STREAM) { |
702 if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS)) { | 762 return; |
703 return; | 763 } |
704 } | 764 CFX_FxgeDevice device; |
| 765 device.Attach(pBitmap); |
| 766 CPDF_MeshStream stream; |
| 767 if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS)) { |
| 768 return; |
| 769 } |
705 | 770 |
706 if (!_CheckCoonTensorPara(stream)) { | 771 if (!_CheckCoonTensorPara(stream)) { |
707 return; | 772 return; |
708 } | 773 } |
709 | 774 |
710 CPDF_PatchDrawer patch; | 775 CPDF_PatchDrawer patch; |
711 patch.alpha = alpha; | 776 patch.alpha = alpha; |
712 patch.pDevice = &device; | 777 patch.pDevice = &device; |
713 patch.fill_mode = fill_mode; | 778 patch.fill_mode = fill_mode; |
714 patch.path.SetPointCount(13); | 779 patch.path.SetPointCount(13); |
715 FX_PATHPOINT* pPoints = patch.path.GetPoints(); | 780 FX_PATHPOINT* pPoints = patch.path.GetPoints(); |
716 pPoints[0].m_Flag = FXPT_MOVETO; | 781 pPoints[0].m_Flag = FXPT_MOVETO; |
717 for (int i = 1; i < 13; i ++) { | 782 for (int i = 1; i < 13; i++) { |
718 pPoints[i].m_Flag = FXPT_BEZIERTO; | 783 pPoints[i].m_Flag = FXPT_BEZIERTO; |
719 } | 784 } |
720 CFX_FloatPoint coords[16]; | 785 CFX_FloatPoint coords[16]; |
721 for (int i = 0; i < 16; i ++) { | 786 for (int i = 0; i < 16; i++) { |
722 coords[i].Set(0.0f, 0.0f); | 787 coords[i].Set(0.0f, 0.0f); |
723 } | 788 } |
724 | 789 |
725 int point_count = bTensor ? 16 : 12; | 790 int point_count = bTensor ? 16 : 12; |
726 while (!stream.m_BitStream.IsEOF()) { | 791 while (!stream.m_BitStream.IsEOF()) { |
727 FX_DWORD flag = stream.GetFlag(); | 792 FX_DWORD flag = stream.GetFlag(); |
728 int iStartPoint = 0, iStartColor = 0, i = 0; | 793 int iStartPoint = 0, iStartColor = 0, i = 0; |
729 if (flag) { | 794 if (flag) { |
730 iStartPoint = 4; | 795 iStartPoint = 4; |
731 iStartColor = 2; | 796 iStartColor = 2; |
732 CFX_FloatPoint tempCoords[4]; | 797 CFX_FloatPoint tempCoords[4]; |
733 for (i = 0; i < 4; i ++) { | 798 for (i = 0; i < 4; i++) { |
734 tempCoords[i] = coords[(flag * 3 + i) % 12]; | 799 tempCoords[i] = coords[(flag * 3 + i) % 12]; |
735 } | 800 } |
736 FXSYS_memcpy(coords, tempCoords, sizeof(CFX_FloatPoint) * 4); | 801 FXSYS_memcpy(coords, tempCoords, sizeof(CFX_FloatPoint) * 4); |
737 Coon_Color tempColors[2]; | 802 Coon_Color tempColors[2]; |
738 tempColors[0] = patch.patch_colors[flag]; | 803 tempColors[0] = patch.patch_colors[flag]; |
739 tempColors[1] = patch.patch_colors[(flag + 1) % 4]; | 804 tempColors[1] = patch.patch_colors[(flag + 1) % 4]; |
740 FXSYS_memcpy(patch.patch_colors, tempColors, sizeof(Coon_Color) * 2)
; | 805 FXSYS_memcpy(patch.patch_colors, tempColors, sizeof(Coon_Color) * 2); |
741 } | 806 } |
742 for (i = iStartPoint; i < point_count; i ++) { | 807 for (i = iStartPoint; i < point_count; i++) { |
743 stream.GetCoords(coords[i].x, coords[i].y); | 808 stream.GetCoords(coords[i].x, coords[i].y); |
744 pObject2Bitmap->Transform(coords[i].x, coords[i].y); | 809 pObject2Bitmap->Transform(coords[i].x, coords[i].y); |
745 } | 810 } |
746 for (i = iStartColor; i < 4; i ++) { | 811 for (i = iStartColor; i < 4; i++) { |
747 FX_FLOAT r=0.0f, g=0.0f, b=0.0f; | 812 FX_FLOAT r = 0.0f, g = 0.0f, b = 0.0f; |
748 stream.GetColor(r, g, b); | 813 stream.GetColor(r, g, b); |
749 patch.patch_colors[i].comp[0] = (int32_t)(r * 255); | 814 patch.patch_colors[i].comp[0] = (int32_t)(r * 255); |
750 patch.patch_colors[i].comp[1] = (int32_t)(g * 255); | 815 patch.patch_colors[i].comp[1] = (int32_t)(g * 255); |
751 patch.patch_colors[i].comp[2] = (int32_t)(b * 255); | 816 patch.patch_colors[i].comp[2] = (int32_t)(b * 255); |
752 } | 817 } |
753 CFX_FloatRect bbox = CFX_FloatRect::GetBBox(coords, point_count); | 818 CFX_FloatRect bbox = CFX_FloatRect::GetBBox(coords, point_count); |
754 if (bbox.right <= 0 || bbox.left >= (FX_FLOAT)pBitmap->GetWidth() || bbo
x.top <= 0 || | 819 if (bbox.right <= 0 || bbox.left >= (FX_FLOAT)pBitmap->GetWidth() || |
755 bbox.bottom >= (FX_FLOAT)pBitmap->GetHeight()) { | 820 bbox.top <= 0 || bbox.bottom >= (FX_FLOAT)pBitmap->GetHeight()) { |
756 continue; | 821 continue; |
757 } | 822 } |
758 Coon_Bezier C1, C2, D1, D2; | 823 Coon_Bezier C1, C2, D1, D2; |
759 C1.FromPoints(coords[0].x, coords[0].y, coords[11].x, coords[11].y, coor
ds[10].x, coords[10].y, | 824 C1.FromPoints(coords[0].x, coords[0].y, coords[11].x, coords[11].y, |
760 coords[9].x, coords[9].y); | 825 coords[10].x, coords[10].y, coords[9].x, coords[9].y); |
761 C2.FromPoints(coords[3].x, coords[3].y, coords[4].x, coords[4].y, coords
[5].x, coords[5].y, | 826 C2.FromPoints(coords[3].x, coords[3].y, coords[4].x, coords[4].y, |
762 coords[6].x, coords[6].y); | 827 coords[5].x, coords[5].y, coords[6].x, coords[6].y); |
763 D1.FromPoints(coords[0].x, coords[0].y, coords[1].x, coords[1].y, coords
[2].x, coords[2].y, | 828 D1.FromPoints(coords[0].x, coords[0].y, coords[1].x, coords[1].y, |
764 coords[3].x, coords[3].y); | 829 coords[2].x, coords[2].y, coords[3].x, coords[3].y); |
765 D2.FromPoints(coords[9].x, coords[9].y, coords[8].x, coords[8].y, coords
[7].x, coords[7].y, | 830 D2.FromPoints(coords[9].x, coords[9].y, coords[8].x, coords[8].y, |
766 coords[6].x, coords[6].y); | 831 coords[7].x, coords[7].y, coords[6].x, coords[6].y); |
767 patch.Draw(1, 1, 0, 0, C1, C2, D1, D2); | 832 patch.Draw(1, 1, 0, 0, C1, C2, D1, D2); |
768 } | 833 } |
769 } | 834 } |
770 void CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern* pPattern, CFX_AffineMat
rix* pMatrix, | 835 void CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern* pPattern, |
771 FX_RECT& clip_rect, int alpha, FX_BOOL bAlph
aMode) | 836 CFX_AffineMatrix* pMatrix, |
772 { | 837 FX_RECT& clip_rect, |
773 CPDF_Function** pFuncs = pPattern->m_pFunctions; | 838 int alpha, |
774 int nFuncs = pPattern->m_nFuncs; | 839 FX_BOOL bAlphaMode) { |
775 CPDF_Dictionary* pDict = pPattern->m_pShadingObj->GetDict(); | 840 CPDF_Function** pFuncs = pPattern->m_pFunctions; |
776 CPDF_ColorSpace* pColorSpace = pPattern->m_pCS; | 841 int nFuncs = pPattern->m_nFuncs; |
777 if (pColorSpace == NULL) { | 842 CPDF_Dictionary* pDict = pPattern->m_pShadingObj->GetDict(); |
778 return; | 843 CPDF_ColorSpace* pColorSpace = pPattern->m_pCS; |
779 } | 844 if (pColorSpace == NULL) { |
780 FX_ARGB background = 0; | 845 return; |
781 if (!pPattern->m_bShadingObj && pPattern->m_pShadingObj->GetDict()->KeyExist
(FX_BSTRC("Background"))) { | 846 } |
782 CPDF_Array* pBackColor = pPattern->m_pShadingObj->GetDict()->GetArray(FX
_BSTRC("Background")); | 847 FX_ARGB background = 0; |
783 if (pBackColor && pBackColor->GetCount() >= (FX_DWORD)pColorSpace->Count
Components()) { | 848 if (!pPattern->m_bShadingObj && |
784 CFX_FixedBufGrow<FX_FLOAT, 16> comps(pColorSpace->CountComponents())
; | 849 pPattern->m_pShadingObj->GetDict()->KeyExist(FX_BSTRC("Background"))) { |
785 for (int i = 0; i < pColorSpace->CountComponents(); i ++) { | 850 CPDF_Array* pBackColor = |
786 comps[i] = pBackColor->GetNumber(i); | 851 pPattern->m_pShadingObj->GetDict()->GetArray(FX_BSTRC("Background")); |
787 } | 852 if (pBackColor && |
788 FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; | 853 pBackColor->GetCount() >= (FX_DWORD)pColorSpace->CountComponents()) { |
789 pColorSpace->GetRGB(comps, R, G, B); | 854 CFX_FixedBufGrow<FX_FLOAT, 16> comps(pColorSpace->CountComponents()); |
790 background = ArgbEncode(255, (int32_t)(R * 255), (int32_t)(G * 255),
(int32_t)(B * 255)); | 855 for (int i = 0; i < pColorSpace->CountComponents(); i++) { |
791 } | 856 comps[i] = pBackColor->GetNumber(i); |
792 } | 857 } |
793 if (pDict->KeyExist(FX_BSTRC("BBox"))) { | 858 FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; |
794 CFX_FloatRect rect = pDict->GetRect(FX_BSTRC("BBox")); | 859 pColorSpace->GetRGB(comps, R, G, B); |
795 rect.Transform(pMatrix); | 860 background = ArgbEncode(255, (int32_t)(R * 255), (int32_t)(G * 255), |
796 clip_rect.Intersect(rect.GetOutterRect()); | 861 (int32_t)(B * 255)); |
797 } | 862 } |
798 CPDF_DeviceBuffer buffer; | 863 } |
799 buffer.Initialize(m_pContext, m_pDevice, &clip_rect, m_pCurObj, 150); | 864 if (pDict->KeyExist(FX_BSTRC("BBox"))) { |
800 CFX_AffineMatrix FinalMatrix = *pMatrix; | 865 CFX_FloatRect rect = pDict->GetRect(FX_BSTRC("BBox")); |
801 FinalMatrix.Concat(*buffer.GetMatrix()); | 866 rect.Transform(pMatrix); |
802 CFX_DIBitmap* pBitmap = buffer.GetBitmap(); | 867 clip_rect.Intersect(rect.GetOutterRect()); |
803 if (pBitmap->GetBuffer() == NULL) { | 868 } |
804 return; | 869 CPDF_DeviceBuffer buffer; |
805 } | 870 buffer.Initialize(m_pContext, m_pDevice, &clip_rect, m_pCurObj, 150); |
806 pBitmap->Clear(background); | 871 CFX_AffineMatrix FinalMatrix = *pMatrix; |
807 int fill_mode = m_Options.m_Flags; | 872 FinalMatrix.Concat(*buffer.GetMatrix()); |
808 switch (pPattern->m_ShadingType) { | 873 CFX_DIBitmap* pBitmap = buffer.GetBitmap(); |
809 case 1: | 874 if (pBitmap->GetBuffer() == NULL) { |
810 _DrawFuncShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, pColo
rSpace, alpha); | 875 return; |
811 break; | 876 } |
812 case 2: | 877 pBitmap->Clear(background); |
813 _DrawAxialShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, pCol
orSpace, alpha); | 878 int fill_mode = m_Options.m_Flags; |
814 break; | 879 switch (pPattern->m_ShadingType) { |
815 case 3: | 880 case 1: |
816 _DrawRadialShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, pCo
lorSpace, alpha); | 881 _DrawFuncShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, |
817 break; | 882 pColorSpace, alpha); |
818 case 4: { | 883 break; |
819 _DrawFreeGouraudShading(pBitmap, &FinalMatrix, (CPDF_Stream*)pPa
ttern->m_pShadingObj, | 884 case 2: |
820 pFuncs, nFuncs, pColorSpace, alpha); | 885 _DrawAxialShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, |
821 } | 886 pColorSpace, alpha); |
822 break; | 887 break; |
823 case 5: { | 888 case 3: |
824 _DrawLatticeGouraudShading(pBitmap, &FinalMatrix, (CPDF_Stream*)
pPattern->m_pShadingObj, | 889 _DrawRadialShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, |
825 pFuncs, nFuncs, pColorSpace, alpha); | 890 pColorSpace, alpha); |
826 } | 891 break; |
827 break; | 892 case 4: { |
828 case 6: | 893 _DrawFreeGouraudShading(pBitmap, &FinalMatrix, |
829 case 7: { | 894 (CPDF_Stream*)pPattern->m_pShadingObj, pFuncs, |
830 _DrawCoonPatchMeshes(pPattern->m_ShadingType - 6, pBitmap, &Fina
lMatrix, (CPDF_Stream*)pPattern->m_pShadingObj, | 895 nFuncs, pColorSpace, alpha); |
831 pFuncs, nFuncs, pColorSpace, fill_mode, alp
ha); | 896 } break; |
832 } | 897 case 5: { |
833 break; | 898 _DrawLatticeGouraudShading(pBitmap, &FinalMatrix, |
834 } | 899 (CPDF_Stream*)pPattern->m_pShadingObj, pFuncs, |
835 if (bAlphaMode) { | 900 nFuncs, pColorSpace, alpha); |
836 pBitmap->LoadChannel(FXDIB_Red, pBitmap, FXDIB_Alpha); | 901 } break; |
837 } | 902 case 6: |
838 if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) { | 903 case 7: { |
839 pBitmap->ConvertColorScale(m_Options.m_ForeColor, m_Options.m_BackColor)
; | 904 _DrawCoonPatchMeshes(pPattern->m_ShadingType - 6, pBitmap, &FinalMatrix, |
840 } | 905 (CPDF_Stream*)pPattern->m_pShadingObj, pFuncs, |
841 buffer.OutputToDevice(); | 906 nFuncs, pColorSpace, fill_mode, alpha); |
842 } | 907 } break; |
843 void CPDF_RenderStatus::DrawShadingPattern(CPDF_ShadingPattern* pattern, CPDF_Pa
geObject* pPageObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke) | 908 } |
844 { | 909 if (bAlphaMode) { |
845 if (!pattern->Load()) { | 910 pBitmap->LoadChannel(FXDIB_Red, pBitmap, FXDIB_Alpha); |
846 return; | 911 } |
847 } | 912 if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) { |
848 m_pDevice->SaveState(); | 913 pBitmap->ConvertColorScale(m_Options.m_ForeColor, m_Options.m_BackColor); |
849 if (pPageObj->m_Type == PDFPAGE_PATH) { | 914 } |
850 if (!SelectClipPath((CPDF_PathObject*)pPageObj, pObj2Device, bStroke)) { | 915 buffer.OutputToDevice(); |
851 m_pDevice->RestoreState(); | 916 } |
852 return; | 917 void CPDF_RenderStatus::DrawShadingPattern(CPDF_ShadingPattern* pattern, |
853 } | 918 CPDF_PageObject* pPageObj, |
854 } else if (pPageObj->m_Type == PDFPAGE_IMAGE) { | 919 const CFX_AffineMatrix* pObj2Device, |
855 FX_RECT rect = pPageObj->GetBBox(pObj2Device); | 920 FX_BOOL bStroke) { |
856 m_pDevice->SetClip_Rect(&rect); | 921 if (!pattern->Load()) { |
857 } else { | 922 return; |
858 return; | 923 } |
859 } | 924 m_pDevice->SaveState(); |
860 FX_RECT rect; | 925 if (pPageObj->m_Type == PDFPAGE_PATH) { |
861 if (GetObjectClippedRect(pPageObj, pObj2Device, FALSE, rect)) { | 926 if (!SelectClipPath((CPDF_PathObject*)pPageObj, pObj2Device, bStroke)) { |
| 927 m_pDevice->RestoreState(); |
| 928 return; |
| 929 } |
| 930 } else if (pPageObj->m_Type == PDFPAGE_IMAGE) { |
| 931 FX_RECT rect = pPageObj->GetBBox(pObj2Device); |
| 932 m_pDevice->SetClip_Rect(&rect); |
| 933 } else { |
| 934 return; |
| 935 } |
| 936 FX_RECT rect; |
| 937 if (GetObjectClippedRect(pPageObj, pObj2Device, FALSE, rect)) { |
| 938 m_pDevice->RestoreState(); |
| 939 return; |
| 940 } |
| 941 CFX_AffineMatrix matrix = pattern->m_Pattern2Form; |
| 942 matrix.Concat(*pObj2Device); |
| 943 GetScaledMatrix(matrix); |
| 944 int alpha = pPageObj->m_GeneralState.GetAlpha(bStroke); |
| 945 DrawShading(pattern, &matrix, rect, alpha, |
| 946 m_Options.m_ColorMode == RENDER_COLOR_ALPHA); |
| 947 m_pDevice->RestoreState(); |
| 948 } |
| 949 FX_BOOL CPDF_RenderStatus::ProcessShading(CPDF_ShadingObject* pShadingObj, |
| 950 const CFX_AffineMatrix* pObj2Device) { |
| 951 FX_RECT rect = pShadingObj->GetBBox(pObj2Device); |
| 952 FX_RECT clip_box = m_pDevice->GetClipBox(); |
| 953 rect.Intersect(clip_box); |
| 954 if (rect.IsEmpty()) { |
| 955 return TRUE; |
| 956 } |
| 957 CFX_AffineMatrix matrix = pShadingObj->m_Matrix; |
| 958 matrix.Concat(*pObj2Device); |
| 959 DrawShading(pShadingObj->m_pShading, &matrix, rect, |
| 960 pShadingObj->m_GeneralState.GetAlpha(FALSE), |
| 961 m_Options.m_ColorMode == RENDER_COLOR_ALPHA); |
| 962 return TRUE; |
| 963 } |
| 964 static CFX_DIBitmap* DrawPatternBitmap(CPDF_Document* pDoc, |
| 965 CPDF_PageRenderCache* pCache, |
| 966 CPDF_TilingPattern* pPattern, |
| 967 const CFX_AffineMatrix* pObject2Device, |
| 968 int width, |
| 969 int height, |
| 970 int flags) { |
| 971 CFX_DIBitmap* pBitmap = new CFX_DIBitmap; |
| 972 if (!pBitmap->Create(width, height, |
| 973 pPattern->m_bColored ? FXDIB_Argb : FXDIB_8bppMask)) { |
| 974 delete pBitmap; |
| 975 return NULL; |
| 976 } |
| 977 CFX_FxgeDevice bitmap_device; |
| 978 bitmap_device.Attach(pBitmap); |
| 979 pBitmap->Clear(0); |
| 980 CFX_FloatRect cell_bbox = pPattern->m_BBox; |
| 981 pPattern->m_Pattern2Form.TransformRect(cell_bbox); |
| 982 pObject2Device->TransformRect(cell_bbox); |
| 983 CFX_FloatRect bitmap_rect(0.0f, 0.0f, (FX_FLOAT)width, (FX_FLOAT)height); |
| 984 CFX_AffineMatrix mtAdjust; |
| 985 mtAdjust.MatchRect(bitmap_rect, cell_bbox); |
| 986 CFX_AffineMatrix mtPattern2Bitmap = *pObject2Device; |
| 987 mtPattern2Bitmap.Concat(mtAdjust); |
| 988 CPDF_RenderOptions options; |
| 989 if (!pPattern->m_bColored) { |
| 990 options.m_ColorMode = RENDER_COLOR_ALPHA; |
| 991 } |
| 992 flags |= RENDER_FORCE_HALFTONE; |
| 993 options.m_Flags = flags; |
| 994 CPDF_RenderContext context; |
| 995 context.Create(pDoc, pCache, NULL); |
| 996 context.DrawObjectList(&bitmap_device, pPattern->m_pForm, &mtPattern2Bitmap, |
| 997 &options); |
| 998 return pBitmap; |
| 999 } |
| 1000 void CPDF_RenderStatus::DrawTilingPattern(CPDF_TilingPattern* pPattern, |
| 1001 CPDF_PageObject* pPageObj, |
| 1002 const CFX_AffineMatrix* pObj2Device, |
| 1003 FX_BOOL bStroke) { |
| 1004 if (!pPattern->Load()) { |
| 1005 return; |
| 1006 } |
| 1007 m_pDevice->SaveState(); |
| 1008 if (pPageObj->m_Type == PDFPAGE_PATH) { |
| 1009 if (!SelectClipPath((CPDF_PathObject*)pPageObj, pObj2Device, bStroke)) { |
| 1010 m_pDevice->RestoreState(); |
| 1011 return; |
| 1012 } |
| 1013 } else if (pPageObj->m_Type == PDFPAGE_IMAGE) { |
| 1014 FX_RECT rect = pPageObj->GetBBox(pObj2Device); |
| 1015 m_pDevice->SetClip_Rect(&rect); |
| 1016 } else { |
| 1017 return; |
| 1018 } |
| 1019 FX_RECT clip_box = m_pDevice->GetClipBox(); |
| 1020 if (clip_box.IsEmpty()) { |
| 1021 m_pDevice->RestoreState(); |
| 1022 return; |
| 1023 } |
| 1024 CFX_Matrix dCTM = m_pDevice->GetCTM(); |
| 1025 FX_FLOAT sa = FXSYS_fabs(dCTM.a); |
| 1026 FX_FLOAT sd = FXSYS_fabs(dCTM.d); |
| 1027 clip_box.right = clip_box.left + (int32_t)FXSYS_ceil(clip_box.Width() * sa); |
| 1028 clip_box.bottom = clip_box.top + (int32_t)FXSYS_ceil(clip_box.Height() * sd); |
| 1029 CFX_AffineMatrix mtPattern2Device = pPattern->m_Pattern2Form; |
| 1030 mtPattern2Device.Concat(*pObj2Device); |
| 1031 GetScaledMatrix(mtPattern2Device); |
| 1032 FX_BOOL bAligned = FALSE; |
| 1033 if (pPattern->m_BBox.left == 0 && pPattern->m_BBox.bottom == 0 && |
| 1034 pPattern->m_BBox.right == pPattern->m_XStep && |
| 1035 pPattern->m_BBox.top == pPattern->m_YStep && |
| 1036 (mtPattern2Device.IsScaled() || mtPattern2Device.Is90Rotated())) { |
| 1037 bAligned = TRUE; |
| 1038 } |
| 1039 CFX_FloatRect cell_bbox = pPattern->m_BBox; |
| 1040 mtPattern2Device.TransformRect(cell_bbox); |
| 1041 int width = (int)FXSYS_ceil(cell_bbox.Width()); |
| 1042 int height = (int)FXSYS_ceil(cell_bbox.Height()); |
| 1043 if (width == 0) { |
| 1044 width = 1; |
| 1045 } |
| 1046 if (height == 0) { |
| 1047 height = 1; |
| 1048 } |
| 1049 int min_col, max_col, min_row, max_row; |
| 1050 CFX_AffineMatrix mtDevice2Pattern; |
| 1051 mtDevice2Pattern.SetReverse(mtPattern2Device); |
| 1052 CFX_FloatRect clip_box_p(clip_box); |
| 1053 clip_box_p.Transform(&mtDevice2Pattern); |
| 1054 min_col = (int)FXSYS_ceil( |
| 1055 FXSYS_Div(clip_box_p.left - pPattern->m_BBox.right, pPattern->m_XStep)); |
| 1056 max_col = (int)FXSYS_floor( |
| 1057 FXSYS_Div(clip_box_p.right - pPattern->m_BBox.left, pPattern->m_XStep)); |
| 1058 min_row = (int)FXSYS_ceil( |
| 1059 FXSYS_Div(clip_box_p.bottom - pPattern->m_BBox.top, pPattern->m_YStep)); |
| 1060 max_row = (int)FXSYS_floor( |
| 1061 FXSYS_Div(clip_box_p.top - pPattern->m_BBox.bottom, pPattern->m_YStep)); |
| 1062 if (width > clip_box.Width() || height > clip_box.Height() || |
| 1063 width * height > clip_box.Width() * clip_box.Height()) { |
| 1064 CPDF_GraphicStates* pStates = NULL; |
| 1065 if (!pPattern->m_bColored) { |
| 1066 pStates = CloneObjStates(pPageObj, bStroke); |
| 1067 } |
| 1068 CPDF_Dictionary* pFormResource = NULL; |
| 1069 if (pPattern->m_pForm->m_pFormDict) { |
| 1070 pFormResource = |
| 1071 pPattern->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources")); |
| 1072 } |
| 1073 for (int col = min_col; col <= max_col; col++) |
| 1074 for (int row = min_row; row <= max_row; row++) { |
| 1075 FX_FLOAT orig_x, orig_y; |
| 1076 orig_x = col * pPattern->m_XStep; |
| 1077 orig_y = row * pPattern->m_YStep; |
| 1078 mtPattern2Device.Transform(orig_x, orig_y); |
| 1079 CFX_AffineMatrix matrix = *pObj2Device; |
| 1080 matrix.Translate(orig_x - mtPattern2Device.e, |
| 1081 orig_y - mtPattern2Device.f); |
| 1082 m_pDevice->SaveState(); |
| 1083 CPDF_RenderStatus status; |
| 1084 status.Initialize(m_pContext, m_pDevice, NULL, NULL, this, pStates, |
| 1085 &m_Options, pPattern->m_pForm->m_Transparency, |
| 1086 m_bDropObjects, pFormResource); |
| 1087 status.RenderObjectList(pPattern->m_pForm, &matrix); |
862 m_pDevice->RestoreState(); | 1088 m_pDevice->RestoreState(); |
863 return; | 1089 } |
864 } | |
865 CFX_AffineMatrix matrix = pattern->m_Pattern2Form; | |
866 matrix.Concat(*pObj2Device); | |
867 GetScaledMatrix(matrix); | |
868 int alpha = pPageObj->m_GeneralState.GetAlpha(bStroke); | |
869 DrawShading(pattern, &matrix, rect, alpha, m_Options.m_ColorMode == RENDER_C
OLOR_ALPHA); | |
870 m_pDevice->RestoreState(); | 1090 m_pDevice->RestoreState(); |
871 } | 1091 delete pStates; |
872 FX_BOOL CPDF_RenderStatus::ProcessShading(CPDF_ShadingObject* pShadingObj, const
CFX_AffineMatrix* pObj2Device) | 1092 return; |
873 { | 1093 } |
874 FX_RECT rect = pShadingObj->GetBBox(pObj2Device); | 1094 if (bAligned) { |
875 FX_RECT clip_box = m_pDevice->GetClipBox(); | 1095 int orig_x = FXSYS_round(mtPattern2Device.e); |
876 rect.Intersect(clip_box); | 1096 int orig_y = FXSYS_round(mtPattern2Device.f); |
877 if (rect.IsEmpty()) { | 1097 min_col = (clip_box.left - orig_x) / width; |
878 return TRUE; | 1098 if (clip_box.left < orig_x) { |
879 } | 1099 min_col--; |
880 CFX_AffineMatrix matrix = pShadingObj->m_Matrix; | 1100 } |
881 matrix.Concat(*pObj2Device); | 1101 max_col = (clip_box.right - orig_x) / width; |
882 DrawShading(pShadingObj->m_pShading, &matrix, rect, pShadingObj->m_GeneralSt
ate.GetAlpha(FALSE), | 1102 if (clip_box.right <= orig_x) { |
883 m_Options.m_ColorMode == RENDER_COLOR_ALPHA); | 1103 max_col--; |
884 return TRUE; | 1104 } |
885 } | 1105 min_row = (clip_box.top - orig_y) / height; |
886 static CFX_DIBitmap* DrawPatternBitmap(CPDF_Document* pDoc, CPDF_PageRenderCache
* pCache, | 1106 if (clip_box.top < orig_y) { |
887 CPDF_TilingPattern* pPattern, const CFX_A
ffineMatrix* pObject2Device, | 1107 min_row--; |
888 int width, int height, int flags) | 1108 } |
889 { | 1109 max_row = (clip_box.bottom - orig_y) / height; |
890 CFX_DIBitmap* pBitmap = new CFX_DIBitmap; | 1110 if (clip_box.bottom <= orig_y) { |
891 if (!pBitmap->Create(width, height, pPattern->m_bColored ? FXDIB_Argb : FXDI
B_8bppMask)) { | 1111 max_row--; |
892 delete pBitmap; | 1112 } |
893 return NULL; | 1113 } |
894 } | 1114 FX_FLOAT left_offset = cell_bbox.left - mtPattern2Device.e; |
895 CFX_FxgeDevice bitmap_device; | 1115 FX_FLOAT top_offset = cell_bbox.bottom - mtPattern2Device.f; |
896 bitmap_device.Attach(pBitmap); | 1116 CFX_DIBitmap* pPatternBitmap = NULL; |
897 pBitmap->Clear(0); | 1117 if (width * height < 16) { |
898 CFX_FloatRect cell_bbox = pPattern->m_BBox; | 1118 CFX_DIBitmap* pEnlargedBitmap = |
899 pPattern->m_Pattern2Form.TransformRect(cell_bbox); | 1119 DrawPatternBitmap(m_pContext->m_pDocument, m_pContext->m_pPageCache, |
900 pObject2Device->TransformRect(cell_bbox); | 1120 pPattern, pObj2Device, 8, 8, m_Options.m_Flags); |
901 CFX_FloatRect bitmap_rect(0.0f, 0.0f, (FX_FLOAT)width, (FX_FLOAT)height); | 1121 pPatternBitmap = pEnlargedBitmap->StretchTo(width, height); |
902 CFX_AffineMatrix mtAdjust; | 1122 delete pEnlargedBitmap; |
903 mtAdjust.MatchRect(bitmap_rect, cell_bbox); | 1123 } else { |
904 CFX_AffineMatrix mtPattern2Bitmap = *pObject2Device; | 1124 pPatternBitmap = DrawPatternBitmap( |
905 mtPattern2Bitmap.Concat(mtAdjust); | 1125 m_pContext->m_pDocument, m_pContext->m_pPageCache, pPattern, |
906 CPDF_RenderOptions options; | 1126 pObj2Device, width, height, m_Options.m_Flags); |
907 if (!pPattern->m_bColored) { | 1127 } |
908 options.m_ColorMode = RENDER_COLOR_ALPHA; | 1128 if (pPatternBitmap == NULL) { |
909 } | |
910 flags |= RENDER_FORCE_HALFTONE; | |
911 options.m_Flags = flags; | |
912 CPDF_RenderContext context; | |
913 context.Create(pDoc, pCache, NULL); | |
914 context.DrawObjectList(&bitmap_device, pPattern->m_pForm, &mtPattern2Bitmap,
&options); | |
915 return pBitmap; | |
916 } | |
917 void CPDF_RenderStatus::DrawTilingPattern(CPDF_TilingPattern* pPattern, CPDF_Pag
eObject* pPageObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke) | |
918 { | |
919 if (!pPattern->Load()) { | |
920 return; | |
921 } | |
922 m_pDevice->SaveState(); | |
923 if (pPageObj->m_Type == PDFPAGE_PATH) { | |
924 if (!SelectClipPath((CPDF_PathObject*)pPageObj, pObj2Device, bStroke)) { | |
925 m_pDevice->RestoreState(); | |
926 return; | |
927 } | |
928 } else if (pPageObj->m_Type == PDFPAGE_IMAGE) { | |
929 FX_RECT rect = pPageObj->GetBBox(pObj2Device); | |
930 m_pDevice->SetClip_Rect(&rect); | |
931 } else { | |
932 return; | |
933 } | |
934 FX_RECT clip_box = m_pDevice->GetClipBox(); | |
935 if (clip_box.IsEmpty()) { | |
936 m_pDevice->RestoreState(); | |
937 return; | |
938 } | |
939 CFX_Matrix dCTM = m_pDevice->GetCTM(); | |
940 FX_FLOAT sa = FXSYS_fabs(dCTM.a); | |
941 FX_FLOAT sd = FXSYS_fabs(dCTM.d); | |
942 clip_box.right = clip_box.left + (int32_t)FXSYS_ceil(clip_box.Width() * sa); | |
943 clip_box.bottom = clip_box.top + (int32_t)FXSYS_ceil(clip_box.Height() * sd)
; | |
944 CFX_AffineMatrix mtPattern2Device = pPattern->m_Pattern2Form; | |
945 mtPattern2Device.Concat(*pObj2Device); | |
946 GetScaledMatrix(mtPattern2Device); | |
947 FX_BOOL bAligned = FALSE; | |
948 if (pPattern->m_BBox.left == 0 && pPattern->m_BBox.bottom == 0 && | |
949 pPattern->m_BBox.right == pPattern->m_XStep && pPattern->m_BBox.top
== pPattern->m_YStep && | |
950 (mtPattern2Device.IsScaled() || mtPattern2Device.Is90Rotated())) { | |
951 bAligned = TRUE; | |
952 } | |
953 CFX_FloatRect cell_bbox = pPattern->m_BBox; | |
954 mtPattern2Device.TransformRect(cell_bbox); | |
955 int width = (int)FXSYS_ceil(cell_bbox.Width()); | |
956 int height = (int)FXSYS_ceil(cell_bbox.Height()); | |
957 if (width == 0) { | |
958 width = 1; | |
959 } | |
960 if (height == 0) { | |
961 height = 1; | |
962 } | |
963 int min_col, max_col, min_row, max_row; | |
964 CFX_AffineMatrix mtDevice2Pattern; | |
965 mtDevice2Pattern.SetReverse(mtPattern2Device); | |
966 CFX_FloatRect clip_box_p(clip_box); | |
967 clip_box_p.Transform(&mtDevice2Pattern); | |
968 min_col = (int)FXSYS_ceil(FXSYS_Div(clip_box_p.left - pPattern->m_BBox.right
, pPattern->m_XStep)); | |
969 max_col = (int)FXSYS_floor(FXSYS_Div(clip_box_p.right - pPattern->m_BBox.lef
t, pPattern->m_XStep)); | |
970 min_row = (int)FXSYS_ceil(FXSYS_Div(clip_box_p.bottom - pPattern->m_BBox.top
, pPattern->m_YStep)); | |
971 max_row = (int)FXSYS_floor(FXSYS_Div(clip_box_p.top - pPattern->m_BBox.botto
m, pPattern->m_YStep)); | |
972 if (width > clip_box.Width() || height > clip_box.Height() || width * height
> clip_box.Width() * clip_box.Height()) { | |
973 CPDF_GraphicStates* pStates = NULL; | |
974 if (!pPattern->m_bColored) { | |
975 pStates = CloneObjStates(pPageObj, bStroke); | |
976 } | |
977 CPDF_Dictionary* pFormResource = NULL; | |
978 if (pPattern->m_pForm->m_pFormDict) { | |
979 pFormResource = pPattern->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Re
sources")); | |
980 } | |
981 for (int col = min_col; col <= max_col; col ++) | |
982 for (int row = min_row; row <= max_row; row ++) { | |
983 FX_FLOAT orig_x, orig_y; | |
984 orig_x = col * pPattern->m_XStep; | |
985 orig_y = row * pPattern->m_YStep; | |
986 mtPattern2Device.Transform(orig_x, orig_y); | |
987 CFX_AffineMatrix matrix = *pObj2Device; | |
988 matrix.Translate(orig_x - mtPattern2Device.e, orig_y - mtPattern
2Device.f); | |
989 m_pDevice->SaveState(); | |
990 CPDF_RenderStatus status; | |
991 status.Initialize(m_pContext, m_pDevice, NULL, NULL, this, pStat
es, &m_Options, | |
992 pPattern->m_pForm->m_Transparency, m_bDropObje
cts, pFormResource); | |
993 status.RenderObjectList(pPattern->m_pForm, &matrix); | |
994 m_pDevice->RestoreState(); | |
995 } | |
996 m_pDevice->RestoreState(); | |
997 delete pStates; | |
998 return; | |
999 } | |
1000 if (bAligned) { | |
1001 int orig_x = FXSYS_round(mtPattern2Device.e); | |
1002 int orig_y = FXSYS_round(mtPattern2Device.f); | |
1003 min_col = (clip_box.left - orig_x) / width; | |
1004 if (clip_box.left < orig_x) { | |
1005 min_col --; | |
1006 } | |
1007 max_col = (clip_box.right - orig_x) / width; | |
1008 if (clip_box.right <= orig_x) { | |
1009 max_col --; | |
1010 } | |
1011 min_row = (clip_box.top - orig_y) / height; | |
1012 if (clip_box.top < orig_y) { | |
1013 min_row --; | |
1014 } | |
1015 max_row = (clip_box.bottom - orig_y) / height; | |
1016 if (clip_box.bottom <= orig_y) { | |
1017 max_row --; | |
1018 } | |
1019 } | |
1020 FX_FLOAT left_offset = cell_bbox.left - mtPattern2Device.e; | |
1021 FX_FLOAT top_offset = cell_bbox.bottom - mtPattern2Device.f; | |
1022 CFX_DIBitmap* pPatternBitmap = NULL; | |
1023 if (width * height < 16) { | |
1024 CFX_DIBitmap* pEnlargedBitmap = DrawPatternBitmap(m_pContext->m_pDocumen
t, m_pContext->m_pPageCache, pPattern, pObj2Device, 8, 8, m_Options.m_Flags); | |
1025 pPatternBitmap = pEnlargedBitmap->StretchTo(width, height); | |
1026 delete pEnlargedBitmap; | |
1027 } else { | |
1028 pPatternBitmap = DrawPatternBitmap(m_pContext->m_pDocument, m_pContext->
m_pPageCache, pPattern, pObj2Device, width, height, m_Options.m_Flags); | |
1029 } | |
1030 if (pPatternBitmap == NULL) { | |
1031 m_pDevice->RestoreState(); | |
1032 return; | |
1033 } | |
1034 if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) { | |
1035 pPatternBitmap->ConvertColorScale(m_Options.m_ForeColor, m_Options.m_Bac
kColor); | |
1036 } | |
1037 FX_ARGB fill_argb = GetFillArgb(pPageObj); | |
1038 int clip_width = clip_box.right - clip_box.left; | |
1039 int clip_height = clip_box.bottom - clip_box.top; | |
1040 CFX_DIBitmap screen; | |
1041 if (!screen.Create(clip_width, clip_height, FXDIB_Argb)) { | |
1042 return; | |
1043 } | |
1044 screen.Clear(0); | |
1045 FX_DWORD* src_buf = (FX_DWORD*)pPatternBitmap->GetBuffer(); | |
1046 for (int col = min_col; col <= max_col; col ++) { | |
1047 for (int row = min_row; row <= max_row; row ++) { | |
1048 int start_x, start_y; | |
1049 if (bAligned) { | |
1050 start_x = FXSYS_round(mtPattern2Device.e) + col * width - clip_b
ox.left; | |
1051 start_y = FXSYS_round(mtPattern2Device.f) + row * height - clip_
box.top; | |
1052 } else { | |
1053 FX_FLOAT orig_x = col * pPattern->m_XStep; | |
1054 FX_FLOAT orig_y = row * pPattern->m_YStep; | |
1055 mtPattern2Device.Transform(orig_x, orig_y); | |
1056 start_x = FXSYS_round(orig_x + left_offset) - clip_box.left; | |
1057 start_y = FXSYS_round(orig_y + top_offset) - clip_box.top; | |
1058 } | |
1059 if (width == 1 && height == 1) { | |
1060 if (start_x < 0 || start_x >= clip_box.Width() || start_y < 0 ||
start_y >= clip_box.Height()) { | |
1061 continue; | |
1062 } | |
1063 FX_DWORD* dest_buf = (FX_DWORD*)(screen.GetBuffer() + screen.Get
Pitch() * start_y + start_x * 4); | |
1064 if (pPattern->m_bColored) { | |
1065 *dest_buf = *src_buf; | |
1066 } else { | |
1067 *dest_buf = (*(uint8_t*)src_buf << 24) | (fill_argb & 0xffff
ff); | |
1068 } | |
1069 } else { | |
1070 if (pPattern->m_bColored) { | |
1071 screen.CompositeBitmap(start_x, start_y, width, height, pPat
ternBitmap, 0, 0); | |
1072 } else { | |
1073 screen.CompositeMask(start_x, start_y, width, height, pPatte
rnBitmap, fill_argb, 0, 0); | |
1074 } | |
1075 } | |
1076 } | |
1077 } | |
1078 CompositeDIBitmap(&screen, clip_box.left, clip_box.top, 0, 255, FXDIB_BLEND_
NORMAL, FALSE); | |
1079 m_pDevice->RestoreState(); | 1129 m_pDevice->RestoreState(); |
1080 delete pPatternBitmap; | 1130 return; |
1081 } | 1131 } |
1082 void CPDF_RenderStatus::DrawPathWithPattern(CPDF_PathObject* pPathObj, const CFX
_AffineMatrix* pObj2Device, CPDF_Color* pColor, FX_BOOL bStroke) | 1132 if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) { |
1083 { | 1133 pPatternBitmap->ConvertColorScale(m_Options.m_ForeColor, |
1084 CPDF_Pattern* pattern = pColor->GetPattern(); | 1134 m_Options.m_BackColor); |
1085 if (pattern == NULL) { | 1135 } |
1086 return; | 1136 FX_ARGB fill_argb = GetFillArgb(pPageObj); |
1087 } | 1137 int clip_width = clip_box.right - clip_box.left; |
1088 if(pattern->m_PatternType == PATTERN_TILING) { | 1138 int clip_height = clip_box.bottom - clip_box.top; |
1089 DrawTilingPattern((CPDF_TilingPattern*)pattern, pPathObj, pObj2Device, b
Stroke); | 1139 CFX_DIBitmap screen; |
1090 } else { | 1140 if (!screen.Create(clip_width, clip_height, FXDIB_Argb)) { |
1091 DrawShadingPattern((CPDF_ShadingPattern*)pattern, pPathObj, pObj2Device,
bStroke); | 1141 return; |
1092 } | 1142 } |
1093 } | 1143 screen.Clear(0); |
1094 void CPDF_RenderStatus::ProcessPathPattern(CPDF_PathObject* pPathObj, const CFX_
AffineMatrix* pObj2Device, int& filltype, FX_BOOL& bStroke) | 1144 FX_DWORD* src_buf = (FX_DWORD*)pPatternBitmap->GetBuffer(); |
1095 { | 1145 for (int col = min_col; col <= max_col; col++) { |
1096 if(filltype) { | 1146 for (int row = min_row; row <= max_row; row++) { |
1097 CPDF_Color& FillColor = *pPathObj->m_ColorState.GetFillColor(); | 1147 int start_x, start_y; |
1098 if(FillColor.m_pCS && FillColor.m_pCS->GetFamily() == PDFCS_PATTERN) { | 1148 if (bAligned) { |
1099 DrawPathWithPattern(pPathObj, pObj2Device, &FillColor, FALSE); | 1149 start_x = FXSYS_round(mtPattern2Device.e) + col * width - clip_box.left; |
1100 filltype = 0; | 1150 start_y = FXSYS_round(mtPattern2Device.f) + row * height - clip_box.top; |
1101 } | 1151 } else { |
1102 } | 1152 FX_FLOAT orig_x = col * pPattern->m_XStep; |
1103 if(bStroke) { | 1153 FX_FLOAT orig_y = row * pPattern->m_YStep; |
1104 CPDF_Color& StrokeColor = *pPathObj->m_ColorState.GetStrokeColor(); | 1154 mtPattern2Device.Transform(orig_x, orig_y); |
1105 if(StrokeColor.m_pCS && StrokeColor.m_pCS->GetFamily() == PDFCS_PATTERN)
{ | 1155 start_x = FXSYS_round(orig_x + left_offset) - clip_box.left; |
1106 DrawPathWithPattern(pPathObj, pObj2Device, &StrokeColor, TRUE); | 1156 start_y = FXSYS_round(orig_y + top_offset) - clip_box.top; |
1107 bStroke = FALSE; | 1157 } |
1108 } | 1158 if (width == 1 && height == 1) { |
1109 } | 1159 if (start_x < 0 || start_x >= clip_box.Width() || start_y < 0 || |
1110 } | 1160 start_y >= clip_box.Height()) { |
| 1161 continue; |
| 1162 } |
| 1163 FX_DWORD* dest_buf = |
| 1164 (FX_DWORD*)(screen.GetBuffer() + screen.GetPitch() * start_y + |
| 1165 start_x * 4); |
| 1166 if (pPattern->m_bColored) { |
| 1167 *dest_buf = *src_buf; |
| 1168 } else { |
| 1169 *dest_buf = (*(uint8_t*)src_buf << 24) | (fill_argb & 0xffffff); |
| 1170 } |
| 1171 } else { |
| 1172 if (pPattern->m_bColored) { |
| 1173 screen.CompositeBitmap(start_x, start_y, width, height, |
| 1174 pPatternBitmap, 0, 0); |
| 1175 } else { |
| 1176 screen.CompositeMask(start_x, start_y, width, height, pPatternBitmap, |
| 1177 fill_argb, 0, 0); |
| 1178 } |
| 1179 } |
| 1180 } |
| 1181 } |
| 1182 CompositeDIBitmap(&screen, clip_box.left, clip_box.top, 0, 255, |
| 1183 FXDIB_BLEND_NORMAL, FALSE); |
| 1184 m_pDevice->RestoreState(); |
| 1185 delete pPatternBitmap; |
| 1186 } |
| 1187 void CPDF_RenderStatus::DrawPathWithPattern(CPDF_PathObject* pPathObj, |
| 1188 const CFX_AffineMatrix* pObj2Device, |
| 1189 CPDF_Color* pColor, |
| 1190 FX_BOOL bStroke) { |
| 1191 CPDF_Pattern* pattern = pColor->GetPattern(); |
| 1192 if (pattern == NULL) { |
| 1193 return; |
| 1194 } |
| 1195 if (pattern->m_PatternType == PATTERN_TILING) { |
| 1196 DrawTilingPattern((CPDF_TilingPattern*)pattern, pPathObj, pObj2Device, |
| 1197 bStroke); |
| 1198 } else { |
| 1199 DrawShadingPattern((CPDF_ShadingPattern*)pattern, pPathObj, pObj2Device, |
| 1200 bStroke); |
| 1201 } |
| 1202 } |
| 1203 void CPDF_RenderStatus::ProcessPathPattern(CPDF_PathObject* pPathObj, |
| 1204 const CFX_AffineMatrix* pObj2Device, |
| 1205 int& filltype, |
| 1206 FX_BOOL& bStroke) { |
| 1207 if (filltype) { |
| 1208 CPDF_Color& FillColor = *pPathObj->m_ColorState.GetFillColor(); |
| 1209 if (FillColor.m_pCS && FillColor.m_pCS->GetFamily() == PDFCS_PATTERN) { |
| 1210 DrawPathWithPattern(pPathObj, pObj2Device, &FillColor, FALSE); |
| 1211 filltype = 0; |
| 1212 } |
| 1213 } |
| 1214 if (bStroke) { |
| 1215 CPDF_Color& StrokeColor = *pPathObj->m_ColorState.GetStrokeColor(); |
| 1216 if (StrokeColor.m_pCS && StrokeColor.m_pCS->GetFamily() == PDFCS_PATTERN) { |
| 1217 DrawPathWithPattern(pPathObj, pObj2Device, &StrokeColor, TRUE); |
| 1218 bStroke = FALSE; |
| 1219 } |
| 1220 } |
| 1221 } |
OLD | NEW |