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/fxge/fx_dib.h" | 7 #include "../../../include/fxge/fx_dib.h" |
8 #include "../../../include/fxge/fx_ge.h" | 8 #include "../../../include/fxge/fx_ge.h" |
9 #include "dib_int.h" | 9 #include "dib_int.h" |
10 #include <limits.h> | 10 #include <limits.h> |
11 extern int SDP_Table[513]; | 11 extern int SDP_Table[513]; |
12 void CWeightTable::Calc(int dest_len, int dest_min, int dest_max, int src_len, i
nt src_min, int src_max, int flags) | 12 void CWeightTable::Calc(int dest_len, |
13 { | 13 int dest_min, |
14 if (m_pWeightTables) { | 14 int dest_max, |
15 FX_Free(m_pWeightTables); | 15 int src_len, |
16 m_pWeightTables = NULL; | 16 int src_min, |
17 } | 17 int src_max, |
18 double scale, base; | 18 int flags) { |
19 scale = FXSYS_Div((FX_FLOAT)(src_len), (FX_FLOAT)(dest_len)); | 19 if (m_pWeightTables) { |
20 if (dest_len < 0) { | 20 FX_Free(m_pWeightTables); |
21 base = (FX_FLOAT)(src_len); | 21 m_pWeightTables = NULL; |
| 22 } |
| 23 double scale, base; |
| 24 scale = FXSYS_Div((FX_FLOAT)(src_len), (FX_FLOAT)(dest_len)); |
| 25 if (dest_len < 0) { |
| 26 base = (FX_FLOAT)(src_len); |
| 27 } else { |
| 28 base = 0; |
| 29 } |
| 30 int ext_size = flags & FXDIB_BICUBIC_INTERPOL ? 3 : 1; |
| 31 m_ItemSize = |
| 32 sizeof(int) * 2 + |
| 33 (int)(sizeof(int) * (FXSYS_ceil(FXSYS_fabs((FX_FLOAT)scale)) + ext_size)); |
| 34 m_DestMin = dest_min; |
| 35 if ((dest_max - dest_min) > (int)((1U << 30) - 4) / m_ItemSize) { |
| 36 return; |
| 37 } |
| 38 m_pWeightTables = |
| 39 FX_TryAlloc(uint8_t, (dest_max - dest_min) * m_ItemSize + 4); |
| 40 if (m_pWeightTables == NULL) { |
| 41 return; |
| 42 } |
| 43 if ((flags & FXDIB_NOSMOOTH) != 0 || FXSYS_fabs((FX_FLOAT)scale) < 1.0f) { |
| 44 for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) { |
| 45 PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); |
| 46 double src_pos = dest_pixel * scale + scale / 2 + base; |
| 47 if (flags & FXDIB_INTERPOL) { |
| 48 pixel_weights.m_SrcStart = |
| 49 (int)FXSYS_floor((FX_FLOAT)src_pos - 1.0f / 2); |
| 50 pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.0f / 2); |
| 51 if (pixel_weights.m_SrcStart < src_min) { |
| 52 pixel_weights.m_SrcStart = src_min; |
| 53 } |
| 54 if (pixel_weights.m_SrcEnd >= src_max) { |
| 55 pixel_weights.m_SrcEnd = src_max - 1; |
| 56 } |
| 57 if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { |
| 58 pixel_weights.m_Weights[0] = 65536; |
| 59 } else { |
| 60 pixel_weights.m_Weights[1] = FXSYS_round( |
| 61 (FX_FLOAT)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * |
| 62 65536); |
| 63 pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1]; |
| 64 } |
| 65 } else if (flags & FXDIB_BICUBIC_INTERPOL) { |
| 66 pixel_weights.m_SrcStart = |
| 67 (int)FXSYS_floor((FX_FLOAT)src_pos - 1.0f / 2); |
| 68 pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.0f / 2); |
| 69 int start = pixel_weights.m_SrcStart - 1; |
| 70 int end = pixel_weights.m_SrcEnd + 1; |
| 71 if (start < src_min) { |
| 72 start = src_min; |
| 73 } |
| 74 if (end >= src_max) { |
| 75 end = src_max - 1; |
| 76 } |
| 77 if (pixel_weights.m_SrcStart < src_min) { |
| 78 src_pos += src_min - pixel_weights.m_SrcStart; |
| 79 pixel_weights.m_SrcStart = src_min; |
| 80 } |
| 81 if (pixel_weights.m_SrcEnd >= src_max) { |
| 82 pixel_weights.m_SrcEnd = src_max - 1; |
| 83 } |
| 84 int weight; |
| 85 weight = FXSYS_round( |
| 86 (FX_FLOAT)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * 256); |
| 87 if (start == end) { |
| 88 pixel_weights.m_Weights[0] = |
| 89 (SDP_Table[256 + weight] + SDP_Table[weight] + |
| 90 SDP_Table[256 - weight] + SDP_Table[512 - weight]) |
| 91 << 8; |
| 92 } else if ((start == pixel_weights.m_SrcStart && |
| 93 (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd || |
| 94 end == pixel_weights.m_SrcEnd) && |
| 95 start < end) || |
| 96 (start < pixel_weights.m_SrcStart && |
| 97 pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd && |
| 98 end == pixel_weights.m_SrcEnd)) { |
| 99 if (start < pixel_weights.m_SrcStart) { |
| 100 pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; |
| 101 pixel_weights.m_Weights[1] = |
| 102 (SDP_Table[weight] + SDP_Table[256 - weight] + |
| 103 SDP_Table[512 - weight]) |
| 104 << 8; |
| 105 } else { |
| 106 if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { |
| 107 pixel_weights.m_Weights[0] = |
| 108 (SDP_Table[256 + weight] + SDP_Table[weight] + |
| 109 SDP_Table[256 - weight]) |
| 110 << 8; |
| 111 pixel_weights.m_Weights[1] = SDP_Table[512 - weight] << 8; |
| 112 } else { |
| 113 pixel_weights.m_Weights[0] = |
| 114 (SDP_Table[256 + weight] + SDP_Table[weight]) << 8; |
| 115 pixel_weights.m_Weights[1] = |
| 116 (SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; |
| 117 } |
| 118 } |
| 119 if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { |
| 120 pixel_weights.m_SrcEnd = end; |
| 121 } |
| 122 if (start < pixel_weights.m_SrcStart) { |
| 123 pixel_weights.m_SrcStart = start; |
| 124 } |
| 125 } else if (start == pixel_weights.m_SrcStart && |
| 126 start < pixel_weights.m_SrcEnd && |
| 127 pixel_weights.m_SrcEnd < end) { |
| 128 pixel_weights.m_Weights[0] = |
| 129 (SDP_Table[256 + weight] + SDP_Table[weight]) << 8; |
| 130 pixel_weights.m_Weights[1] = SDP_Table[256 - weight] << 8; |
| 131 pixel_weights.m_Weights[2] = SDP_Table[512 - weight] << 8; |
| 132 pixel_weights.m_SrcEnd = end; |
| 133 } else if (start < pixel_weights.m_SrcStart && |
| 134 pixel_weights.m_SrcStart < pixel_weights.m_SrcEnd && |
| 135 pixel_weights.m_SrcEnd == end) { |
| 136 pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; |
| 137 pixel_weights.m_Weights[1] = SDP_Table[weight] << 8; |
| 138 pixel_weights.m_Weights[2] = |
| 139 (SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; |
| 140 pixel_weights.m_SrcStart = start; |
| 141 } else { |
| 142 pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; |
| 143 pixel_weights.m_Weights[1] = SDP_Table[weight] << 8; |
| 144 pixel_weights.m_Weights[2] = SDP_Table[256 - weight] << 8; |
| 145 pixel_weights.m_Weights[3] = SDP_Table[512 - weight] << 8; |
| 146 pixel_weights.m_SrcStart = start; |
| 147 pixel_weights.m_SrcEnd = end; |
| 148 } |
| 149 } else { |
| 150 pixel_weights.m_SrcStart = pixel_weights.m_SrcEnd = |
| 151 (int)FXSYS_floor((FX_FLOAT)src_pos); |
| 152 if (pixel_weights.m_SrcStart < src_min) { |
| 153 pixel_weights.m_SrcStart = src_min; |
| 154 } |
| 155 if (pixel_weights.m_SrcEnd >= src_max) { |
| 156 pixel_weights.m_SrcEnd = src_max - 1; |
| 157 } |
| 158 pixel_weights.m_Weights[0] = 65536; |
| 159 } |
| 160 } |
| 161 return; |
| 162 } |
| 163 for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) { |
| 164 PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); |
| 165 double src_start = dest_pixel * scale + base; |
| 166 double src_end = src_start + scale; |
| 167 int start_i, end_i; |
| 168 if (src_start < src_end) { |
| 169 start_i = (int)FXSYS_floor((FX_FLOAT)src_start); |
| 170 end_i = (int)FXSYS_ceil((FX_FLOAT)src_end); |
22 } else { | 171 } else { |
23 base = 0; | 172 start_i = (int)FXSYS_floor((FX_FLOAT)src_end); |
24 } | 173 end_i = (int)FXSYS_ceil((FX_FLOAT)src_start); |
25 int ext_size = flags & FXDIB_BICUBIC_INTERPOL ? 3 : 1; | 174 } |
26 m_ItemSize = sizeof(int) * 2 + (int)(sizeof(int) * (FXSYS_ceil(FXSYS_fabs((F
X_FLOAT)scale)) + ext_size)); | 175 if (start_i < src_min) { |
27 m_DestMin = dest_min; | 176 start_i = src_min; |
28 if ((dest_max - dest_min) > (int)((1U << 30) - 4) / m_ItemSize) { | 177 } |
29 return; | 178 if (end_i >= src_max) { |
30 } | 179 end_i = src_max - 1; |
31 m_pWeightTables = FX_TryAlloc(uint8_t, (dest_max - dest_min) * m_ItemSize +
4); | 180 } |
32 if (m_pWeightTables == NULL) { | 181 if (start_i > end_i) { |
33 return; | 182 if (start_i >= src_max) { |
34 } | 183 start_i = src_max - 1; |
35 if ((flags & FXDIB_NOSMOOTH) != 0 || FXSYS_fabs((FX_FLOAT)scale) < 1.0f) { | 184 } |
36 for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel ++) { | 185 pixel_weights.m_SrcStart = start_i; |
37 PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); | 186 pixel_weights.m_SrcEnd = start_i; |
38 double src_pos = dest_pixel * scale + scale / 2 + base; | 187 continue; |
39 if (flags & FXDIB_INTERPOL) { | 188 } |
40 pixel_weights.m_SrcStart = (int)FXSYS_floor((FX_FLOAT)src_pos -
1.0f / 2); | 189 pixel_weights.m_SrcStart = start_i; |
41 pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.
0f / 2); | 190 pixel_weights.m_SrcEnd = end_i; |
42 if (pixel_weights.m_SrcStart < src_min) { | 191 for (int j = start_i; j <= end_i; j++) { |
43 pixel_weights.m_SrcStart = src_min; | 192 double dest_start = FXSYS_Div((FX_FLOAT)(j)-base, scale); |
44 } | 193 double dest_end = FXSYS_Div((FX_FLOAT)(j + 1) - base, scale); |
45 if (pixel_weights.m_SrcEnd >= src_max) { | 194 if (dest_start > dest_end) { |
46 pixel_weights.m_SrcEnd = src_max - 1; | 195 double temp = dest_start; |
47 } | 196 dest_start = dest_end; |
48 if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { | 197 dest_end = temp; |
49 pixel_weights.m_Weights[0] = 65536; | 198 } |
50 } else { | 199 double area_start = dest_start > (FX_FLOAT)(dest_pixel) |
51 pixel_weights.m_Weights[1] = FXSYS_round((FX_FLOAT)(src_pos
- pixel_weights.m_SrcStart - 1.0f / 2) * 65536); | 200 ? dest_start |
52 pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights
[1]; | 201 : (FX_FLOAT)(dest_pixel); |
53 } | 202 double area_end = dest_end > (FX_FLOAT)(dest_pixel + 1) |
54 } else if (flags & FXDIB_BICUBIC_INTERPOL) { | 203 ? (FX_FLOAT)(dest_pixel + 1) |
55 pixel_weights.m_SrcStart = (int)FXSYS_floor((FX_FLOAT)src_pos -
1.0f / 2); | 204 : dest_end; |
56 pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.
0f / 2); | 205 double weight = area_start >= area_end ? 0.0f : area_end - area_start; |
57 int start = pixel_weights.m_SrcStart - 1; | 206 if (weight == 0 && j == end_i) { |
58 int end = pixel_weights.m_SrcEnd + 1; | 207 pixel_weights.m_SrcEnd--; |
59 if (start < src_min) { | 208 break; |
60 start = src_min; | 209 } |
61 } | 210 pixel_weights.m_Weights[j - start_i] = |
62 if (end >= src_max) { | 211 FXSYS_round((FX_FLOAT)(weight * 65536)); |
63 end = src_max - 1; | 212 } |
64 } | 213 } |
65 if (pixel_weights.m_SrcStart < src_min) { | 214 } |
66 src_pos += src_min - pixel_weights.m_SrcStart; | 215 CStretchEngine::CStretchEngine(IFX_ScanlineComposer* pDestBitmap, |
67 pixel_weights.m_SrcStart = src_min; | 216 FXDIB_Format dest_format, |
68 } | 217 int dest_width, |
69 if (pixel_weights.m_SrcEnd >= src_max) { | 218 int dest_height, |
70 pixel_weights.m_SrcEnd = src_max - 1; | 219 const FX_RECT& clip_rect, |
71 } | 220 const CFX_DIBSource* pSrcBitmap, |
72 int weight; | 221 int flags) { |
73 weight = FXSYS_round((FX_FLOAT)(src_pos - pixel_weights.m_SrcSta
rt - 1.0f / 2) * 256); | 222 m_State = 0; |
74 if (start == end) { | 223 m_DestFormat = dest_format; |
75 pixel_weights.m_Weights[0] = (SDP_Table[256 + weight] + SDP_
Table[weight] + SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; | 224 m_DestBpp = dest_format & 0xff; |
76 } else if ((start == pixel_weights.m_SrcStart && (pixel_weights.
m_SrcStart == pixel_weights.m_SrcEnd || | 225 m_SrcBpp = pSrcBitmap->GetFormat() & 0xff; |
77 end == pixel_weights.m_SrcEnd) && start < end) || (s
tart < pixel_weights.m_SrcStart && pixel_weights.m_SrcStart == pixel_weights.m_S
rcEnd && end == pixel_weights.m_SrcEnd)) { | 226 m_bHasAlpha = pSrcBitmap->GetFormat() & 0x200; |
78 if (start < pixel_weights.m_SrcStart) { | 227 m_pSrcPalette = pSrcBitmap->GetPalette(); |
79 pixel_weights.m_Weights[0] = SDP_Table[256 + weight] <<
8; | 228 m_pDestBitmap = pDestBitmap; |
80 pixel_weights.m_Weights[1] = (SDP_Table[weight] + SDP_Ta
ble[256 - weight] + SDP_Table[512 - weight]) << 8; | 229 m_DestWidth = dest_width; |
81 } else { | 230 m_DestHeight = dest_height; |
82 if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd)
{ | 231 m_pInterBuf = NULL; |
83 pixel_weights.m_Weights[0] = (SDP_Table[256 + weight
] + SDP_Table[weight] + SDP_Table[256 - weight]) << 8; | 232 m_pExtraAlphaBuf = NULL; |
84 pixel_weights.m_Weights[1] = SDP_Table[512 - weight]
<< 8; | 233 m_pDestMaskScanline = NULL; |
85 } else { | 234 m_DestClip = clip_rect; |
86 pixel_weights.m_Weights[0] = (SDP_Table[256 + weight
] + SDP_Table[weight]) << 8; | 235 FX_DWORD size = clip_rect.Width(); |
87 pixel_weights.m_Weights[1] = (SDP_Table[256 - weight
] + SDP_Table[512 - weight]) << 8; | 236 if (size && m_DestBpp > (int)(INT_MAX / size)) { |
88 } | 237 return; |
89 } | 238 } |
90 if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { | 239 size *= m_DestBpp; |
91 pixel_weights.m_SrcEnd = end; | 240 if (size > INT_MAX - 31) { |
92 } | 241 return; |
93 if (start < pixel_weights.m_SrcStart) { | 242 } |
94 pixel_weights.m_SrcStart = start; | 243 size += 31; |
95 } | 244 size = size / 32 * 4; |
96 } else if (start == pixel_weights.m_SrcStart && | 245 m_pDestScanline = FX_TryAlloc(uint8_t, size); |
97 start < pixel_weights.m_SrcEnd && | 246 if (m_pDestScanline == NULL) { |
98 pixel_weights.m_SrcEnd < end) { | 247 return; |
99 pixel_weights.m_Weights[0] = (SDP_Table[256 + weight] + SDP_
Table[weight]) << 8; | 248 } |
100 pixel_weights.m_Weights[1] = SDP_Table[256 - weight] << 8; | 249 if (dest_format == FXDIB_Rgb32) { |
101 pixel_weights.m_Weights[2] = SDP_Table[512 - weight] << 8; | 250 FXSYS_memset(m_pDestScanline, 255, size); |
102 pixel_weights.m_SrcEnd = end; | 251 } |
103 } else if (start < pixel_weights.m_SrcStart && | 252 m_InterPitch = (m_DestClip.Width() * m_DestBpp + 31) / 32 * 4; |
104 pixel_weights.m_SrcStart < pixel_weights.m_SrcEnd && | 253 m_ExtraMaskPitch = (m_DestClip.Width() * 8 + 31) / 32 * 4; |
105 pixel_weights.m_SrcEnd == end) { | 254 m_pInterBuf = NULL; |
106 pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; | 255 m_pSource = pSrcBitmap; |
107 pixel_weights.m_Weights[1] = SDP_Table[weight] << 8; | 256 m_SrcWidth = pSrcBitmap->GetWidth(); |
108 pixel_weights.m_Weights[2] = (SDP_Table[256 - weight] + SDP_
Table[512 - weight]) << 8; | 257 m_SrcHeight = pSrcBitmap->GetHeight(); |
109 pixel_weights.m_SrcStart = start; | 258 m_SrcPitch = (m_SrcWidth * m_SrcBpp + 31) / 32 * 4; |
110 } else { | 259 if ((flags & FXDIB_NOSMOOTH) == 0) { |
111 pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; | 260 FX_BOOL bInterpol = |
112 pixel_weights.m_Weights[1] = SDP_Table[weight] << 8; | 261 flags & FXDIB_INTERPOL || flags & FXDIB_BICUBIC_INTERPOL; |
113 pixel_weights.m_Weights[2] = SDP_Table[256 - weight] << 8; | 262 if (!bInterpol && FXSYS_abs(dest_width) != 0 && |
114 pixel_weights.m_Weights[3] = SDP_Table[512 - weight] << 8; | 263 FXSYS_abs(dest_height) < |
115 pixel_weights.m_SrcStart = start; | 264 m_SrcWidth * m_SrcHeight * 8 / FXSYS_abs(dest_width)) { |
116 pixel_weights.m_SrcEnd = end; | 265 flags = FXDIB_INTERPOL; |
117 } | 266 } |
| 267 m_Flags = flags; |
| 268 } else { |
| 269 m_Flags = FXDIB_NOSMOOTH; |
| 270 if (flags & FXDIB_DOWNSAMPLE) { |
| 271 m_Flags |= FXDIB_DOWNSAMPLE; |
| 272 } |
| 273 } |
| 274 double scale_x = FXSYS_Div((FX_FLOAT)(m_SrcWidth), (FX_FLOAT)(m_DestWidth)); |
| 275 double scale_y = FXSYS_Div((FX_FLOAT)(m_SrcHeight), (FX_FLOAT)(m_DestHeight)); |
| 276 double base_x = m_DestWidth > 0 ? 0.0f : (FX_FLOAT)(m_DestWidth); |
| 277 double base_y = m_DestHeight > 0 ? 0.0f : (FX_FLOAT)(m_DestHeight); |
| 278 double src_left = FXSYS_Mul(scale_x, (FX_FLOAT)(clip_rect.left) + base_x); |
| 279 double src_right = FXSYS_Mul(scale_x, (FX_FLOAT)(clip_rect.right) + base_x); |
| 280 double src_top = FXSYS_Mul(scale_y, (FX_FLOAT)(clip_rect.top) + base_y); |
| 281 double src_bottom = FXSYS_Mul(scale_y, (FX_FLOAT)(clip_rect.bottom) + base_y); |
| 282 if (src_left > src_right) { |
| 283 double temp = src_left; |
| 284 src_left = src_right; |
| 285 src_right = temp; |
| 286 } |
| 287 if (src_top > src_bottom) { |
| 288 double temp = src_top; |
| 289 src_top = src_bottom; |
| 290 src_bottom = temp; |
| 291 } |
| 292 m_SrcClip.left = (int)FXSYS_floor((FX_FLOAT)src_left); |
| 293 m_SrcClip.right = (int)FXSYS_ceil((FX_FLOAT)src_right); |
| 294 m_SrcClip.top = (int)FXSYS_floor((FX_FLOAT)src_top); |
| 295 m_SrcClip.bottom = (int)FXSYS_ceil((FX_FLOAT)src_bottom); |
| 296 FX_RECT src_rect(0, 0, m_SrcWidth, m_SrcHeight); |
| 297 m_SrcClip.Intersect(src_rect); |
| 298 if (m_SrcBpp == 1) { |
| 299 if (m_DestBpp == 8) { |
| 300 m_TransMethod = 1; |
| 301 } else { |
| 302 m_TransMethod = 2; |
| 303 } |
| 304 } else if (m_SrcBpp == 8) { |
| 305 if (m_DestBpp == 8) { |
| 306 if (!m_bHasAlpha) { |
| 307 m_TransMethod = 3; |
| 308 } else { |
| 309 m_TransMethod = 4; |
| 310 } |
| 311 } else { |
| 312 if (!m_bHasAlpha) { |
| 313 m_TransMethod = 5; |
| 314 } else { |
| 315 m_TransMethod = 6; |
| 316 } |
| 317 } |
| 318 } else { |
| 319 if (!m_bHasAlpha) { |
| 320 m_TransMethod = 7; |
| 321 } else { |
| 322 m_TransMethod = 8; |
| 323 } |
| 324 } |
| 325 } |
| 326 FX_BOOL CStretchEngine::Continue(IFX_Pause* pPause) { |
| 327 while (m_State == 1) { |
| 328 if (ContinueStretchHorz(pPause)) { |
| 329 return TRUE; |
| 330 } |
| 331 m_State = 2; |
| 332 StretchVert(); |
| 333 } |
| 334 return FALSE; |
| 335 } |
| 336 CStretchEngine::~CStretchEngine() { |
| 337 if (m_pDestScanline) { |
| 338 FX_Free(m_pDestScanline); |
| 339 } |
| 340 if (m_pInterBuf) { |
| 341 FX_Free(m_pInterBuf); |
| 342 } |
| 343 if (m_pExtraAlphaBuf) { |
| 344 FX_Free(m_pExtraAlphaBuf); |
| 345 } |
| 346 if (m_pDestMaskScanline) { |
| 347 FX_Free(m_pDestMaskScanline); |
| 348 } |
| 349 } |
| 350 FX_BOOL CStretchEngine::StartStretchHorz() { |
| 351 if (m_DestWidth == 0 || m_pDestScanline == NULL || |
| 352 m_SrcClip.Height() > (int)((1U << 29) / m_InterPitch) || |
| 353 m_SrcClip.Height() == 0) { |
| 354 return FALSE; |
| 355 } |
| 356 m_pInterBuf = FX_TryAlloc(unsigned char, m_SrcClip.Height() * m_InterPitch); |
| 357 if (m_pInterBuf == NULL) { |
| 358 return FALSE; |
| 359 } |
| 360 if (m_pSource && m_bHasAlpha && m_pSource->m_pAlphaMask) { |
| 361 m_pExtraAlphaBuf = |
| 362 FX_Alloc2D(unsigned char, m_SrcClip.Height(), m_ExtraMaskPitch); |
| 363 FX_DWORD size = (m_DestClip.Width() * 8 + 31) / 32 * 4; |
| 364 m_pDestMaskScanline = FX_TryAlloc(unsigned char, size); |
| 365 if (!m_pDestMaskScanline) { |
| 366 return FALSE; |
| 367 } |
| 368 } |
| 369 m_WeightTable.Calc(m_DestWidth, m_DestClip.left, m_DestClip.right, m_SrcWidth, |
| 370 m_SrcClip.left, m_SrcClip.right, m_Flags); |
| 371 if (m_WeightTable.m_pWeightTables == NULL) { |
| 372 return FALSE; |
| 373 } |
| 374 m_CurRow = m_SrcClip.top; |
| 375 m_State = 1; |
| 376 return TRUE; |
| 377 } |
| 378 #define FX_STRECH_PAUSE_ROWS 10 |
| 379 FX_BOOL CStretchEngine::ContinueStretchHorz(IFX_Pause* pPause) { |
| 380 if (!m_DestWidth) { |
| 381 return 0; |
| 382 } |
| 383 if (m_pSource->SkipToScanline(m_CurRow, pPause)) { |
| 384 return TRUE; |
| 385 } |
| 386 int Bpp = m_DestBpp / 8; |
| 387 int rows_to_go = FX_STRECH_PAUSE_ROWS; |
| 388 for (; m_CurRow < m_SrcClip.bottom; m_CurRow++) { |
| 389 if (rows_to_go == 0) { |
| 390 if (pPause && pPause->NeedToPauseNow()) { |
| 391 return TRUE; |
| 392 } |
| 393 rows_to_go = FX_STRECH_PAUSE_ROWS; |
| 394 } |
| 395 const uint8_t* src_scan = m_pSource->GetScanline(m_CurRow); |
| 396 uint8_t* dest_scan = |
| 397 m_pInterBuf + (m_CurRow - m_SrcClip.top) * m_InterPitch; |
| 398 const uint8_t* src_scan_mask = NULL; |
| 399 uint8_t* dest_scan_mask = NULL; |
| 400 if (m_pExtraAlphaBuf) { |
| 401 src_scan_mask = m_pSource->m_pAlphaMask->GetScanline(m_CurRow); |
| 402 dest_scan_mask = |
| 403 m_pExtraAlphaBuf + (m_CurRow - m_SrcClip.top) * m_ExtraMaskPitch; |
| 404 } |
| 405 switch (m_TransMethod) { |
| 406 case 1: |
| 407 case 2: { |
| 408 for (int col = m_DestClip.left; col < m_DestClip.right; col++) { |
| 409 PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col); |
| 410 int dest_a = 0; |
| 411 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; |
| 412 j++) { |
| 413 int pixel_weight = |
| 414 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; |
| 415 if (src_scan[j / 8] & (1 << (7 - j % 8))) { |
| 416 dest_a += pixel_weight * 255; |
| 417 } |
| 418 } |
| 419 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { |
| 420 dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a; |
| 421 } |
| 422 *dest_scan++ = (uint8_t)(dest_a >> 16); |
| 423 } |
| 424 break; |
| 425 } |
| 426 case 3: { |
| 427 for (int col = m_DestClip.left; col < m_DestClip.right; col++) { |
| 428 PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col); |
| 429 int dest_a = 0; |
| 430 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; |
| 431 j++) { |
| 432 int pixel_weight = |
| 433 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; |
| 434 dest_a += pixel_weight * src_scan[j]; |
| 435 } |
| 436 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { |
| 437 dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a; |
| 438 } |
| 439 *dest_scan++ = (uint8_t)(dest_a >> 16); |
| 440 } |
| 441 break; |
| 442 } |
| 443 case 4: { |
| 444 for (int col = m_DestClip.left; col < m_DestClip.right; col++) { |
| 445 PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col); |
| 446 int dest_a = 0, dest_r = 0; |
| 447 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; |
| 448 j++) { |
| 449 int pixel_weight = |
| 450 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; |
| 451 pixel_weight = pixel_weight * src_scan_mask[j] / 255; |
| 452 dest_r += pixel_weight * src_scan[j]; |
| 453 dest_a += pixel_weight; |
| 454 } |
| 455 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { |
| 456 dest_r = dest_r < 0 ? 0 : dest_r > 16711680 ? 16711680 : dest_r; |
| 457 dest_a = dest_a < 0 ? 0 : dest_a > 65536 ? 65536 : dest_a; |
| 458 } |
| 459 *dest_scan++ = (uint8_t)(dest_r >> 16); |
| 460 *dest_scan_mask++ = (uint8_t)((dest_a * 255) >> 16); |
| 461 } |
| 462 break; |
| 463 } |
| 464 case 5: { |
| 465 for (int col = m_DestClip.left; col < m_DestClip.right; col++) { |
| 466 PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col); |
| 467 int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; |
| 468 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; |
| 469 j++) { |
| 470 int pixel_weight = |
| 471 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; |
| 472 unsigned long argb_cmyk = m_pSrcPalette[src_scan[j]]; |
| 473 if (m_DestFormat == FXDIB_Rgb) { |
| 474 dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >> 16); |
| 475 dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >> 8); |
| 476 dest_b_c += pixel_weight * (uint8_t)argb_cmyk; |
118 } else { | 477 } else { |
119 pixel_weights.m_SrcStart = pixel_weights.m_SrcEnd = (int)FXSYS_f
loor((FX_FLOAT)src_pos); | 478 dest_b_c += pixel_weight * (uint8_t)(argb_cmyk >> 24); |
120 if (pixel_weights.m_SrcStart < src_min) { | 479 dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >> 16); |
121 pixel_weights.m_SrcStart = src_min; | 480 dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >> 8); |
122 } | |
123 if (pixel_weights.m_SrcEnd >= src_max) { | |
124 pixel_weights.m_SrcEnd = src_max - 1; | |
125 } | |
126 pixel_weights.m_Weights[0] = 65536; | |
127 } | 481 } |
128 } | 482 } |
129 return; | 483 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { |
130 } | 484 dest_r_y = |
131 for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel ++) { | 485 dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y; |
132 PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); | 486 dest_g_m = |
133 double src_start = dest_pixel * scale + base; | 487 dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m; |
134 double src_end = src_start + scale; | 488 dest_b_c = |
135 int start_i, end_i; | 489 dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c; |
136 if (src_start < src_end) { | 490 } |
137 start_i = (int)FXSYS_floor((FX_FLOAT)src_start); | 491 *dest_scan++ = (uint8_t)(dest_b_c >> 16); |
138 end_i = (int)FXSYS_ceil((FX_FLOAT)src_end); | 492 *dest_scan++ = (uint8_t)(dest_g_m >> 16); |
139 } else { | 493 *dest_scan++ = (uint8_t)(dest_r_y >> 16); |
140 start_i = (int)FXSYS_floor((FX_FLOAT)src_end); | 494 } |
141 end_i = (int)FXSYS_ceil((FX_FLOAT)src_start); | 495 break; |
142 } | 496 } |
143 if (start_i < src_min) { | 497 case 6: { |
144 start_i = src_min; | 498 for (int col = m_DestClip.left; col < m_DestClip.right; col++) { |
145 } | 499 PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col); |
146 if (end_i >= src_max) { | 500 int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; |
147 end_i = src_max - 1; | 501 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; |
148 } | 502 j++) { |
149 if (start_i > end_i) { | 503 int pixel_weight = |
150 if (start_i >= src_max) { | 504 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; |
151 start_i = src_max - 1; | 505 pixel_weight = pixel_weight * src_scan_mask[j] / 255; |
| 506 unsigned long argb_cmyk = m_pSrcPalette[src_scan[j]]; |
| 507 if (m_DestFormat == FXDIB_Rgba) { |
| 508 dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >> 16); |
| 509 dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >> 8); |
| 510 dest_b_c += pixel_weight * (uint8_t)argb_cmyk; |
| 511 } else { |
| 512 dest_b_c += pixel_weight * (uint8_t)(argb_cmyk >> 24); |
| 513 dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >> 16); |
| 514 dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >> 8); |
152 } | 515 } |
153 pixel_weights.m_SrcStart = start_i; | 516 dest_a += pixel_weight; |
154 pixel_weights.m_SrcEnd = start_i; | 517 } |
155 continue; | 518 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { |
156 } | 519 dest_b_c = |
157 pixel_weights.m_SrcStart = start_i; | 520 dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c; |
158 pixel_weights.m_SrcEnd = end_i; | 521 dest_g_m = |
159 for (int j = start_i; j <= end_i; j ++) { | 522 dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m; |
160 double dest_start = FXSYS_Div((FX_FLOAT)(j) - base, scale); | 523 dest_r_y = |
161 double dest_end = FXSYS_Div((FX_FLOAT)(j + 1) - base, scale); | 524 dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y; |
162 if (dest_start > dest_end) { | 525 dest_a = dest_a < 0 ? 0 : dest_a > 65536 ? 65536 : dest_a; |
163 double temp = dest_start; | 526 } |
164 dest_start = dest_end; | 527 *dest_scan++ = (uint8_t)(dest_b_c >> 16); |
165 dest_end = temp; | 528 *dest_scan++ = (uint8_t)(dest_g_m >> 16); |
| 529 *dest_scan++ = (uint8_t)(dest_r_y >> 16); |
| 530 *dest_scan_mask++ = (uint8_t)((dest_a * 255) >> 16); |
| 531 } |
| 532 break; |
| 533 } |
| 534 case 7: { |
| 535 for (int col = m_DestClip.left; col < m_DestClip.right; col++) { |
| 536 PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col); |
| 537 int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; |
| 538 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; |
| 539 j++) { |
| 540 int pixel_weight = |
| 541 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; |
| 542 const uint8_t* src_pixel = src_scan + j * Bpp; |
| 543 dest_b_c += pixel_weight * (*src_pixel++); |
| 544 dest_g_m += pixel_weight * (*src_pixel++); |
| 545 dest_r_y += pixel_weight * (*src_pixel); |
| 546 } |
| 547 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { |
| 548 dest_b_c = |
| 549 dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c; |
| 550 dest_g_m = |
| 551 dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m; |
| 552 dest_r_y = |
| 553 dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y; |
| 554 } |
| 555 *dest_scan++ = (uint8_t)((dest_b_c) >> 16); |
| 556 *dest_scan++ = (uint8_t)((dest_g_m) >> 16); |
| 557 *dest_scan++ = (uint8_t)((dest_r_y) >> 16); |
| 558 dest_scan += Bpp - 3; |
| 559 } |
| 560 break; |
| 561 } |
| 562 case 8: { |
| 563 for (int col = m_DestClip.left; col < m_DestClip.right; col++) { |
| 564 PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col); |
| 565 int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; |
| 566 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; |
| 567 j++) { |
| 568 int pixel_weight = |
| 569 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; |
| 570 const uint8_t* src_pixel = src_scan + j * Bpp; |
| 571 if (m_DestFormat == FXDIB_Argb) { |
| 572 pixel_weight = pixel_weight * src_pixel[3] / 255; |
| 573 } else { |
| 574 pixel_weight = pixel_weight * src_scan_mask[j] / 255; |
166 } | 575 } |
167 double area_start = dest_start > (FX_FLOAT)(dest_pixel) ? dest_start
: (FX_FLOAT)(dest_pixel); | 576 dest_b_c += pixel_weight * (*src_pixel++); |
168 double area_end = dest_end > (FX_FLOAT)(dest_pixel + 1) ? (FX_FLOAT)
(dest_pixel + 1) : dest_end; | 577 dest_g_m += pixel_weight * (*src_pixel++); |
169 double weight = area_start >= area_end ? 0.0f : area_end - area_star
t; | 578 dest_r_y += pixel_weight * (*src_pixel); |
170 if (weight == 0 && j == end_i) { | 579 dest_a += pixel_weight; |
171 pixel_weights.m_SrcEnd --; | 580 } |
172 break; | 581 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { |
| 582 dest_r_y = |
| 583 dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y; |
| 584 dest_g_m = |
| 585 dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m; |
| 586 dest_b_c = |
| 587 dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c; |
| 588 dest_a = dest_a < 0 ? 0 : dest_a > 65536 ? 65536 : dest_a; |
| 589 } |
| 590 *dest_scan++ = (uint8_t)((dest_b_c) >> 16); |
| 591 *dest_scan++ = (uint8_t)((dest_g_m) >> 16); |
| 592 *dest_scan++ = (uint8_t)((dest_r_y) >> 16); |
| 593 if (m_DestFormat == FXDIB_Argb) { |
| 594 *dest_scan = (uint8_t)((dest_a * 255) >> 16); |
| 595 } |
| 596 if (dest_scan_mask) { |
| 597 *dest_scan_mask++ = (uint8_t)((dest_a * 255) >> 16); |
| 598 } |
| 599 dest_scan += Bpp - 3; |
| 600 } |
| 601 break; |
| 602 } |
| 603 } |
| 604 rows_to_go--; |
| 605 } |
| 606 return FALSE; |
| 607 } |
| 608 void CStretchEngine::StretchVert() { |
| 609 if (m_DestHeight == 0) { |
| 610 return; |
| 611 } |
| 612 CWeightTable table; |
| 613 table.Calc(m_DestHeight, m_DestClip.top, m_DestClip.bottom, m_SrcHeight, |
| 614 m_SrcClip.top, m_SrcClip.bottom, m_Flags); |
| 615 if (table.m_pWeightTables == NULL) { |
| 616 return; |
| 617 } |
| 618 int DestBpp = m_DestBpp / 8; |
| 619 for (int row = m_DestClip.top; row < m_DestClip.bottom; row++) { |
| 620 unsigned char* dest_scan = m_pDestScanline; |
| 621 unsigned char* dest_sacn_mask = m_pDestMaskScanline; |
| 622 PixelWeight* pPixelWeights = table.GetPixelWeight(row); |
| 623 switch (m_TransMethod) { |
| 624 case 1: |
| 625 case 2: |
| 626 case 3: { |
| 627 for (int col = m_DestClip.left; col < m_DestClip.right; col++) { |
| 628 unsigned char* src_scan = |
| 629 m_pInterBuf + (col - m_DestClip.left) * DestBpp; |
| 630 int dest_a = 0; |
| 631 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; |
| 632 j++) { |
| 633 int pixel_weight = |
| 634 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; |
| 635 dest_a += |
| 636 pixel_weight * src_scan[(j - m_SrcClip.top) * m_InterPitch]; |
| 637 } |
| 638 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { |
| 639 dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a; |
| 640 } |
| 641 *dest_scan = (uint8_t)(dest_a >> 16); |
| 642 dest_scan += DestBpp; |
| 643 } |
| 644 break; |
| 645 } |
| 646 case 4: { |
| 647 for (int col = m_DestClip.left; col < m_DestClip.right; col++) { |
| 648 unsigned char* src_scan = |
| 649 m_pInterBuf + (col - m_DestClip.left) * DestBpp; |
| 650 unsigned char* src_scan_mask = |
| 651 m_pExtraAlphaBuf + (col - m_DestClip.left); |
| 652 int dest_a = 0, dest_k = 0; |
| 653 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; |
| 654 j++) { |
| 655 int pixel_weight = |
| 656 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; |
| 657 dest_k += |
| 658 pixel_weight * src_scan[(j - m_SrcClip.top) * m_InterPitch]; |
| 659 dest_a += pixel_weight * |
| 660 src_scan_mask[(j - m_SrcClip.top) * m_ExtraMaskPitch]; |
| 661 } |
| 662 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { |
| 663 dest_k = dest_k < 0 ? 0 : dest_k > 16711680 ? 16711680 : dest_k; |
| 664 dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a; |
| 665 } |
| 666 *dest_scan = (uint8_t)(dest_k >> 16); |
| 667 dest_scan += DestBpp; |
| 668 *dest_sacn_mask++ = (uint8_t)(dest_a >> 16); |
| 669 } |
| 670 break; |
| 671 } |
| 672 case 5: |
| 673 case 7: { |
| 674 for (int col = m_DestClip.left; col < m_DestClip.right; col++) { |
| 675 unsigned char* src_scan = |
| 676 m_pInterBuf + (col - m_DestClip.left) * DestBpp; |
| 677 int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; |
| 678 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; |
| 679 j++) { |
| 680 int pixel_weight = |
| 681 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; |
| 682 const uint8_t* src_pixel = |
| 683 src_scan + (j - m_SrcClip.top) * m_InterPitch; |
| 684 dest_b_c += pixel_weight * (*src_pixel++); |
| 685 dest_g_m += pixel_weight * (*src_pixel++); |
| 686 dest_r_y += pixel_weight * (*src_pixel); |
| 687 } |
| 688 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { |
| 689 dest_r_y = |
| 690 dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y; |
| 691 dest_g_m = |
| 692 dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m; |
| 693 dest_b_c = |
| 694 dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c; |
| 695 } |
| 696 dest_scan[0] = (uint8_t)((dest_b_c) >> 16); |
| 697 dest_scan[1] = (uint8_t)((dest_g_m) >> 16); |
| 698 dest_scan[2] = (uint8_t)((dest_r_y) >> 16); |
| 699 dest_scan += DestBpp; |
| 700 } |
| 701 break; |
| 702 } |
| 703 case 6: |
| 704 case 8: { |
| 705 for (int col = m_DestClip.left; col < m_DestClip.right; col++) { |
| 706 unsigned char* src_scan = |
| 707 m_pInterBuf + (col - m_DestClip.left) * DestBpp; |
| 708 unsigned char* src_scan_mask = NULL; |
| 709 if (m_DestFormat != FXDIB_Argb) { |
| 710 src_scan_mask = m_pExtraAlphaBuf + (col - m_DestClip.left); |
| 711 } |
| 712 int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; |
| 713 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; |
| 714 j++) { |
| 715 int pixel_weight = |
| 716 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; |
| 717 const uint8_t* src_pixel = |
| 718 src_scan + (j - m_SrcClip.top) * m_InterPitch; |
| 719 int mask_v = 255; |
| 720 if (src_scan_mask) { |
| 721 mask_v = src_scan_mask[(j - m_SrcClip.top) * m_ExtraMaskPitch]; |
173 } | 722 } |
174 pixel_weights.m_Weights[j - start_i] = FXSYS_round((FX_FLOAT)(weight
* 65536)); | 723 dest_b_c += pixel_weight * (*src_pixel++); |
175 } | 724 dest_g_m += pixel_weight * (*src_pixel++); |
176 } | 725 dest_r_y += pixel_weight * (*src_pixel); |
177 } | 726 if (m_DestFormat == FXDIB_Argb) { |
178 CStretchEngine::CStretchEngine(IFX_ScanlineComposer* pDestBitmap, FXDIB_Format d
est_format, | 727 dest_a += pixel_weight * (*(src_pixel + 1)); |
179 int dest_width, int dest_height, const FX_RECT& c
lip_rect, | 728 } else { |
180 const CFX_DIBSource* pSrcBitmap, int flags) | 729 dest_a += pixel_weight * mask_v; |
181 { | 730 } |
182 m_State = 0; | 731 } |
183 m_DestFormat = dest_format; | 732 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { |
184 m_DestBpp = dest_format & 0xff; | 733 dest_r_y = |
185 m_SrcBpp = pSrcBitmap->GetFormat() & 0xff; | 734 dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y; |
186 m_bHasAlpha = pSrcBitmap->GetFormat() & 0x200; | 735 dest_g_m = |
187 m_pSrcPalette = pSrcBitmap->GetPalette(); | 736 dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m; |
188 m_pDestBitmap = pDestBitmap; | 737 dest_b_c = |
189 m_DestWidth = dest_width; | 738 dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c; |
190 m_DestHeight = dest_height; | 739 dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a; |
191 m_pInterBuf = NULL; | 740 } |
192 m_pExtraAlphaBuf = NULL; | 741 if (dest_a) { |
193 m_pDestMaskScanline = NULL; | 742 int r = ((FX_DWORD)dest_r_y) * 255 / dest_a; |
194 m_DestClip = clip_rect; | 743 int g = ((FX_DWORD)dest_g_m) * 255 / dest_a; |
195 FX_DWORD size = clip_rect.Width(); | 744 int b = ((FX_DWORD)dest_b_c) * 255 / dest_a; |
196 if (size && m_DestBpp > (int)(INT_MAX / size)) { | 745 dest_scan[0] = b > 255 ? 255 : b < 0 ? 0 : b; |
197 return; | 746 dest_scan[1] = g > 255 ? 255 : g < 0 ? 0 : g; |
198 } | 747 dest_scan[2] = r > 255 ? 255 : r < 0 ? 0 : r; |
199 size *= m_DestBpp; | 748 } |
200 if (size > INT_MAX - 31) { | 749 if (m_DestFormat == FXDIB_Argb) { |
201 return; | 750 dest_scan[3] = (uint8_t)((dest_a) >> 16); |
202 } | 751 } else { |
203 size += 31; | 752 *dest_sacn_mask = (uint8_t)((dest_a) >> 16); |
204 size = size / 32 * 4; | 753 } |
205 m_pDestScanline = FX_TryAlloc(uint8_t, size); | 754 dest_scan += DestBpp; |
206 if (m_pDestScanline == NULL) { | 755 if (dest_sacn_mask) { |
207 return; | 756 dest_sacn_mask++; |
208 } | 757 } |
209 if (dest_format == FXDIB_Rgb32) { | 758 } |
210 FXSYS_memset(m_pDestScanline, 255, size); | 759 break; |
211 } | 760 } |
212 m_InterPitch = (m_DestClip.Width() * m_DestBpp + 31) / 32 * 4; | 761 } |
213 m_ExtraMaskPitch = (m_DestClip.Width() * 8 + 31) / 32 * 4; | 762 m_pDestBitmap->ComposeScanline(row - m_DestClip.top, m_pDestScanline, |
214 m_pInterBuf = NULL; | 763 m_pDestMaskScanline); |
215 m_pSource = pSrcBitmap; | 764 } |
216 m_SrcWidth = pSrcBitmap->GetWidth(); | 765 } |
217 m_SrcHeight = pSrcBitmap->GetHeight(); | 766 CFX_ImageStretcher::CFX_ImageStretcher() { |
218 m_SrcPitch = (m_SrcWidth * m_SrcBpp + 31) / 32 * 4; | 767 m_pScanline = NULL; |
219 if ((flags & FXDIB_NOSMOOTH) == 0) { | 768 m_pStretchEngine = NULL; |
220 FX_BOOL bInterpol = flags & FXDIB_INTERPOL || flags & FXDIB_BICUBIC_INTE
RPOL; | 769 m_pMaskScanline = NULL; |
221 if (!bInterpol && FXSYS_abs(dest_width) != 0 && FXSYS_abs(dest_height) <
m_SrcWidth * m_SrcHeight * 8 / FXSYS_abs(dest_width)) { | 770 } |
222 flags = FXDIB_INTERPOL; | 771 CFX_ImageStretcher::~CFX_ImageStretcher() { |
223 } | 772 if (m_pScanline) { |
224 m_Flags = flags; | 773 FX_Free(m_pScanline); |
| 774 } |
| 775 delete m_pStretchEngine; |
| 776 if (m_pMaskScanline) { |
| 777 FX_Free(m_pMaskScanline); |
| 778 } |
| 779 } |
| 780 FXDIB_Format _GetStretchedFormat(const CFX_DIBSource* pSrc) { |
| 781 FXDIB_Format format = pSrc->GetFormat(); |
| 782 if (format == FXDIB_1bppMask) { |
| 783 format = FXDIB_8bppMask; |
| 784 } else if (format == FXDIB_1bppRgb) { |
| 785 format = FXDIB_8bppRgb; |
| 786 } else if (format == FXDIB_8bppRgb) { |
| 787 if (pSrc->GetPalette()) { |
| 788 format = FXDIB_Rgb; |
| 789 } |
| 790 } |
| 791 return format; |
| 792 } |
| 793 FX_BOOL CFX_ImageStretcher::Start(IFX_ScanlineComposer* pDest, |
| 794 const CFX_DIBSource* pSource, |
| 795 int dest_width, |
| 796 int dest_height, |
| 797 const FX_RECT& rect, |
| 798 FX_DWORD flags) { |
| 799 m_DestFormat = _GetStretchedFormat(pSource); |
| 800 m_DestBPP = m_DestFormat & 0xff; |
| 801 m_pDest = pDest; |
| 802 m_pSource = pSource; |
| 803 m_DestWidth = dest_width; |
| 804 m_DestHeight = dest_height; |
| 805 m_ClipRect = rect; |
| 806 m_Flags = flags; |
| 807 if (pSource->GetFormat() == FXDIB_1bppRgb && pSource->GetPalette()) { |
| 808 FX_ARGB pal[256]; |
| 809 int a0, r0, g0, b0, a1, r1, g1, b1; |
| 810 ArgbDecode(pSource->GetPaletteEntry(0), a0, r0, g0, b0); |
| 811 ArgbDecode(pSource->GetPaletteEntry(1), a1, r1, g1, b1); |
| 812 for (int i = 0; i < 256; i++) { |
| 813 int a = a0 + (a1 - a0) * i / 255; |
| 814 int r = r0 + (r1 - r0) * i / 255; |
| 815 int g = g0 + (g1 - g0) * i / 255; |
| 816 int b = b0 + (b1 - b0) * i / 255; |
| 817 pal[i] = ArgbEncode(a, r, g, b); |
| 818 } |
| 819 if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, pal)) { |
| 820 return FALSE; |
| 821 } |
| 822 } else if (pSource->GetFormat() == FXDIB_1bppCmyk && pSource->GetPalette()) { |
| 823 FX_CMYK pal[256]; |
| 824 int c0, m0, y0, k0, c1, m1, y1, k1; |
| 825 CmykDecode(pSource->GetPaletteEntry(0), c0, m0, y0, k0); |
| 826 CmykDecode(pSource->GetPaletteEntry(1), c1, m1, y1, k1); |
| 827 for (int i = 0; i < 256; i++) { |
| 828 int c = c0 + (c1 - c0) * i / 255; |
| 829 int m = m0 + (m1 - m0) * i / 255; |
| 830 int y = y0 + (y1 - y0) * i / 255; |
| 831 int k = k0 + (k1 - k0) * i / 255; |
| 832 pal[i] = CmykEncode(c, m, y, k); |
| 833 } |
| 834 if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, pal)) { |
| 835 return FALSE; |
| 836 } |
| 837 } else if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, NULL)) { |
| 838 return FALSE; |
| 839 } |
| 840 if (flags & FXDIB_DOWNSAMPLE) { |
| 841 return StartQuickStretch(); |
| 842 } |
| 843 return StartStretch(); |
| 844 } |
| 845 FX_BOOL CFX_ImageStretcher::Continue(IFX_Pause* pPause) { |
| 846 if (m_Flags & FXDIB_DOWNSAMPLE) { |
| 847 return ContinueQuickStretch(pPause); |
| 848 } |
| 849 return ContinueStretch(pPause); |
| 850 } |
| 851 #define MAX_PROGRESSIVE_STRETCH_PIXELS 1000000 |
| 852 FX_BOOL CFX_ImageStretcher::StartStretch() { |
| 853 m_pStretchEngine = |
| 854 new CStretchEngine(m_pDest, m_DestFormat, m_DestWidth, m_DestHeight, |
| 855 m_ClipRect, m_pSource, m_Flags); |
| 856 m_pStretchEngine->StartStretchHorz(); |
| 857 if (m_pSource->GetWidth() * m_pSource->GetHeight() < |
| 858 MAX_PROGRESSIVE_STRETCH_PIXELS) { |
| 859 m_pStretchEngine->Continue(NULL); |
| 860 return FALSE; |
| 861 } |
| 862 return TRUE; |
| 863 } |
| 864 FX_BOOL CFX_ImageStretcher::ContinueStretch(IFX_Pause* pPause) { |
| 865 if (m_pStretchEngine == NULL) { |
| 866 return FALSE; |
| 867 } |
| 868 return m_pStretchEngine->Continue(pPause); |
| 869 } |
| 870 FX_BOOL CFX_ImageStretcher::StartQuickStretch() { |
| 871 m_bFlipX = FALSE; |
| 872 m_bFlipY = FALSE; |
| 873 if (m_DestWidth < 0) { |
| 874 m_bFlipX = TRUE; |
| 875 m_DestWidth = -m_DestWidth; |
| 876 } |
| 877 if (m_DestHeight < 0) { |
| 878 m_bFlipY = TRUE; |
| 879 m_DestHeight = -m_DestHeight; |
| 880 } |
| 881 m_LineIndex = 0; |
| 882 FX_DWORD size = m_ClipRect.Width(); |
| 883 if (size && m_DestBPP > (int)(INT_MAX / size)) { |
| 884 return FALSE; |
| 885 } |
| 886 size *= m_DestBPP; |
| 887 m_pScanline = FX_Alloc(uint8_t, (size / 8 + 3) / 4 * 4); |
| 888 if (m_pSource->m_pAlphaMask) { |
| 889 m_pMaskScanline = FX_Alloc(uint8_t, (m_ClipRect.Width() + 3) / 4 * 4); |
| 890 } |
| 891 if (m_pSource->GetWidth() * m_pSource->GetHeight() < |
| 892 MAX_PROGRESSIVE_STRETCH_PIXELS) { |
| 893 ContinueQuickStretch(NULL); |
| 894 return FALSE; |
| 895 } |
| 896 return TRUE; |
| 897 } |
| 898 FX_BOOL CFX_ImageStretcher::ContinueQuickStretch(IFX_Pause* pPause) { |
| 899 if (m_pScanline == NULL) { |
| 900 return FALSE; |
| 901 } |
| 902 int result_width = m_ClipRect.Width(), result_height = m_ClipRect.Height(); |
| 903 int src_height = m_pSource->GetHeight(); |
| 904 for (; m_LineIndex < result_height; m_LineIndex++) { |
| 905 int dest_y, src_y; |
| 906 if (m_bFlipY) { |
| 907 dest_y = result_height - m_LineIndex - 1; |
| 908 src_y = (m_DestHeight - (dest_y + m_ClipRect.top) - 1) * src_height / |
| 909 m_DestHeight; |
225 } else { | 910 } else { |
226 m_Flags = FXDIB_NOSMOOTH; | 911 dest_y = m_LineIndex; |
227 if (flags & FXDIB_DOWNSAMPLE) { | 912 src_y = (dest_y + m_ClipRect.top) * src_height / m_DestHeight; |
228 m_Flags |= FXDIB_DOWNSAMPLE; | 913 } |
229 } | 914 if (src_y >= src_height) { |
230 } | 915 src_y = src_height - 1; |
231 double scale_x = FXSYS_Div((FX_FLOAT)(m_SrcWidth), (FX_FLOAT)(m_DestWidth)); | 916 } |
232 double scale_y = FXSYS_Div((FX_FLOAT)(m_SrcHeight), (FX_FLOAT)(m_DestHeight)
); | 917 if (src_y < 0) { |
233 double base_x = m_DestWidth > 0 ? 0.0f : (FX_FLOAT)(m_DestWidth); | 918 src_y = 0; |
234 double base_y = m_DestHeight > 0 ? 0.0f : (FX_FLOAT)(m_DestHeight); | 919 } |
235 double src_left = FXSYS_Mul(scale_x, (FX_FLOAT)(clip_rect.left) + base_x); | 920 if (m_pSource->SkipToScanline(src_y, pPause)) { |
236 double src_right = FXSYS_Mul(scale_x, (FX_FLOAT)(clip_rect.right) + base_x); | 921 return TRUE; |
237 double src_top = FXSYS_Mul(scale_y, (FX_FLOAT)(clip_rect.top) + base_y); | 922 } |
238 double src_bottom = FXSYS_Mul(scale_y, (FX_FLOAT)(clip_rect.bottom) + base_y
); | 923 m_pSource->DownSampleScanline(src_y, m_pScanline, m_DestBPP, m_DestWidth, |
239 if (src_left > src_right) { | 924 m_bFlipX, m_ClipRect.left, result_width); |
240 double temp = src_left; | |
241 src_left = src_right; | |
242 src_right = temp; | |
243 } | |
244 if (src_top > src_bottom) { | |
245 double temp = src_top; | |
246 src_top = src_bottom; | |
247 src_bottom = temp; | |
248 } | |
249 m_SrcClip.left = (int)FXSYS_floor((FX_FLOAT)src_left); | |
250 m_SrcClip.right = (int)FXSYS_ceil((FX_FLOAT)src_right); | |
251 m_SrcClip.top = (int)FXSYS_floor((FX_FLOAT)src_top); | |
252 m_SrcClip.bottom = (int)FXSYS_ceil((FX_FLOAT)src_bottom); | |
253 FX_RECT src_rect(0, 0, m_SrcWidth, m_SrcHeight); | |
254 m_SrcClip.Intersect(src_rect); | |
255 if (m_SrcBpp == 1) { | |
256 if (m_DestBpp == 8) { | |
257 m_TransMethod = 1; | |
258 } else { | |
259 m_TransMethod = 2; | |
260 } | |
261 } else if (m_SrcBpp == 8) { | |
262 if (m_DestBpp == 8) { | |
263 if (!m_bHasAlpha) { | |
264 m_TransMethod = 3; | |
265 } else { | |
266 m_TransMethod = 4; | |
267 } | |
268 } else { | |
269 if (!m_bHasAlpha) { | |
270 m_TransMethod = 5; | |
271 } else { | |
272 m_TransMethod = 6; | |
273 } | |
274 } | |
275 } else { | |
276 if (!m_bHasAlpha) { | |
277 m_TransMethod = 7; | |
278 } else { | |
279 m_TransMethod = 8; | |
280 } | |
281 } | |
282 } | |
283 FX_BOOL CStretchEngine::Continue(IFX_Pause* pPause) | |
284 { | |
285 while (m_State == 1) { | |
286 if (ContinueStretchHorz(pPause)) { | |
287 return TRUE; | |
288 } | |
289 m_State = 2; | |
290 StretchVert(); | |
291 } | |
292 return FALSE; | |
293 } | |
294 CStretchEngine::~CStretchEngine() | |
295 { | |
296 if (m_pDestScanline) { | |
297 FX_Free(m_pDestScanline); | |
298 } | |
299 if (m_pInterBuf) { | |
300 FX_Free(m_pInterBuf); | |
301 } | |
302 if (m_pExtraAlphaBuf) { | |
303 FX_Free(m_pExtraAlphaBuf); | |
304 } | |
305 if (m_pDestMaskScanline) { | |
306 FX_Free(m_pDestMaskScanline); | |
307 } | |
308 } | |
309 FX_BOOL CStretchEngine::StartStretchHorz() | |
310 { | |
311 if (m_DestWidth == 0 || m_pDestScanline == NULL || m_SrcClip.Height() > (int
)((1U << 29) / m_InterPitch) || m_SrcClip.Height() == 0) { | |
312 return FALSE; | |
313 } | |
314 m_pInterBuf = FX_TryAlloc(unsigned char, m_SrcClip.Height() * m_InterPitch); | |
315 if (m_pInterBuf == NULL) { | |
316 return FALSE; | |
317 } | |
318 if (m_pSource && m_bHasAlpha && m_pSource->m_pAlphaMask) { | |
319 m_pExtraAlphaBuf = FX_Alloc2D(unsigned char, m_SrcClip.Height(), m_Extra
MaskPitch); | |
320 FX_DWORD size = (m_DestClip.Width() * 8 + 31) / 32 * 4; | |
321 m_pDestMaskScanline = FX_TryAlloc(unsigned char, size); | |
322 if (!m_pDestMaskScanline) { | |
323 return FALSE; | |
324 } | |
325 } | |
326 m_WeightTable.Calc(m_DestWidth, m_DestClip.left, m_DestClip.right, m_SrcWidt
h, m_SrcClip.left, m_SrcClip.right, m_Flags); | |
327 if (m_WeightTable.m_pWeightTables == NULL) { | |
328 return FALSE; | |
329 } | |
330 m_CurRow = m_SrcClip.top; | |
331 m_State = 1; | |
332 return TRUE; | |
333 } | |
334 #define FX_STRECH_PAUSE_ROWS 10 | |
335 FX_BOOL CStretchEngine::ContinueStretchHorz(IFX_Pause* pPause) | |
336 { | |
337 if (!m_DestWidth) { | |
338 return 0; | |
339 } | |
340 if (m_pSource->SkipToScanline(m_CurRow, pPause)) { | |
341 return TRUE; | |
342 } | |
343 int Bpp = m_DestBpp / 8; | |
344 int rows_to_go = FX_STRECH_PAUSE_ROWS; | |
345 for (; m_CurRow < m_SrcClip.bottom; m_CurRow ++) { | |
346 if (rows_to_go == 0) { | |
347 if (pPause && pPause->NeedToPauseNow()) { | |
348 return TRUE; | |
349 } | |
350 rows_to_go = FX_STRECH_PAUSE_ROWS; | |
351 } | |
352 const uint8_t* src_scan = m_pSource->GetScanline(m_CurRow); | |
353 uint8_t* dest_scan = m_pInterBuf + (m_CurRow - m_SrcClip.top) * m_InterP
itch; | |
354 const uint8_t* src_scan_mask = NULL; | |
355 uint8_t* dest_scan_mask = NULL; | |
356 if (m_pExtraAlphaBuf) { | |
357 src_scan_mask = m_pSource->m_pAlphaMask->GetScanline(m_CurRow); | |
358 dest_scan_mask = m_pExtraAlphaBuf + (m_CurRow - m_SrcClip.top) * m_E
xtraMaskPitch; | |
359 } | |
360 switch (m_TransMethod) { | |
361 case 1: | |
362 case 2: { | |
363 for (int col = m_DestClip.left; col < m_DestClip.right; col
++) { | |
364 PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeigh
t(col); | |
365 int dest_a = 0; | |
366 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeigh
ts->m_SrcEnd; j ++) { | |
367 int pixel_weight = pPixelWeights->m_Weights[j - pPix
elWeights->m_SrcStart]; | |
368 if (src_scan[j / 8] & (1 << (7 - j % 8))) { | |
369 dest_a += pixel_weight * 255; | |
370 } | |
371 } | |
372 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { | |
373 dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 167116
80 : dest_a; | |
374 } | |
375 *dest_scan++ = (uint8_t)(dest_a >> 16); | |
376 } | |
377 break; | |
378 } | |
379 case 3: { | |
380 for (int col = m_DestClip.left; col < m_DestClip.right; col
++) { | |
381 PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeigh
t(col); | |
382 int dest_a = 0; | |
383 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeigh
ts->m_SrcEnd; j ++) { | |
384 int pixel_weight = pPixelWeights->m_Weights[j - pPix
elWeights->m_SrcStart]; | |
385 dest_a += pixel_weight * src_scan[j]; | |
386 } | |
387 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { | |
388 dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 167116
80 : dest_a; | |
389 } | |
390 *dest_scan++ = (uint8_t)(dest_a >> 16); | |
391 } | |
392 break; | |
393 } | |
394 case 4: { | |
395 for (int col = m_DestClip.left; col < m_DestClip.right; col
++) { | |
396 PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeigh
t(col); | |
397 int dest_a = 0, dest_r = 0; | |
398 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeigh
ts->m_SrcEnd; j ++) { | |
399 int pixel_weight = pPixelWeights->m_Weights[j - pPix
elWeights->m_SrcStart]; | |
400 pixel_weight = pixel_weight * src_scan_mask[j] / 255
; | |
401 dest_r += pixel_weight * src_scan[j]; | |
402 dest_a += pixel_weight; | |
403 } | |
404 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { | |
405 dest_r = dest_r < 0 ? 0 : dest_r > 16711680 ? 167116
80 : dest_r; | |
406 dest_a = dest_a < 0 ? 0 : dest_a > 65536 ? 65536 : d
est_a; | |
407 } | |
408 *dest_scan++ = (uint8_t)(dest_r >> 16); | |
409 *dest_scan_mask++ = (uint8_t)((dest_a * 255) >> 16); | |
410 } | |
411 break; | |
412 } | |
413 case 5: { | |
414 for (int col = m_DestClip.left; col < m_DestClip.right; col
++) { | |
415 PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeigh
t(col); | |
416 int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; | |
417 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeigh
ts->m_SrcEnd; j ++) { | |
418 int pixel_weight = pPixelWeights->m_Weights[j - pPix
elWeights->m_SrcStart]; | |
419 unsigned long argb_cmyk = m_pSrcPalette[src_scan[j]]
; | |
420 if (m_DestFormat == FXDIB_Rgb) { | |
421 dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >
> 16); | |
422 dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >
> 8); | |
423 dest_b_c += pixel_weight * (uint8_t)argb_cmyk; | |
424 } else { | |
425 dest_b_c += pixel_weight * (uint8_t)(argb_cmyk >
> 24); | |
426 dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >
> 16); | |
427 dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >
> 8); | |
428 } | |
429 } | |
430 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { | |
431 dest_r_y = dest_r_y < 0 ? 0 : dest_r_y > 16711680 ?
16711680 : dest_r_y; | |
432 dest_g_m = dest_g_m < 0 ? 0 : dest_g_m > 16711680 ?
16711680 : dest_g_m; | |
433 dest_b_c = dest_b_c < 0 ? 0 : dest_b_c > 16711680 ?
16711680 : dest_b_c; | |
434 } | |
435 *dest_scan++ = (uint8_t)(dest_b_c >> 16); | |
436 *dest_scan++ = (uint8_t)(dest_g_m >> 16); | |
437 *dest_scan++ = (uint8_t)(dest_r_y >> 16); | |
438 } | |
439 break; | |
440 } | |
441 case 6: { | |
442 for (int col = m_DestClip.left; col < m_DestClip.right; col
++) { | |
443 PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeigh
t(col); | |
444 int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0
; | |
445 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeigh
ts->m_SrcEnd; j ++) { | |
446 int pixel_weight = pPixelWeights->m_Weights[j - pPix
elWeights->m_SrcStart]; | |
447 pixel_weight = pixel_weight * src_scan_mask[j] / 255
; | |
448 unsigned long argb_cmyk = m_pSrcPalette[src_scan[j]]
; | |
449 if (m_DestFormat == FXDIB_Rgba) { | |
450 dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >
> 16); | |
451 dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >
> 8); | |
452 dest_b_c += pixel_weight * (uint8_t)argb_cmyk; | |
453 } else { | |
454 dest_b_c += pixel_weight * (uint8_t)(argb_cmyk >
> 24); | |
455 dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >
> 16); | |
456 dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >
> 8); | |
457 } | |
458 dest_a += pixel_weight; | |
459 } | |
460 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { | |
461 dest_b_c = dest_b_c < 0 ? 0 : dest_b_c > 16711680 ?
16711680 : dest_b_c; | |
462 dest_g_m = dest_g_m < 0 ? 0 : dest_g_m > 16711680 ?
16711680 : dest_g_m; | |
463 dest_r_y = dest_r_y < 0 ? 0 : dest_r_y > 16711680 ?
16711680 : dest_r_y; | |
464 dest_a = dest_a < 0 ? 0 : dest_a > 65536 ? 65536 : d
est_a; | |
465 } | |
466 *dest_scan++ = (uint8_t)(dest_b_c >> 16); | |
467 *dest_scan++ = (uint8_t)(dest_g_m >> 16); | |
468 *dest_scan++ = (uint8_t)(dest_r_y >> 16); | |
469 *dest_scan_mask++ = (uint8_t)((dest_a * 255) >> 16); | |
470 } | |
471 break; | |
472 } | |
473 case 7: { | |
474 for (int col = m_DestClip.left; col < m_DestClip.right; col
++) { | |
475 PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeigh
t(col); | |
476 int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; | |
477 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeigh
ts->m_SrcEnd; j ++) { | |
478 int pixel_weight = pPixelWeights->m_Weights[j - pPix
elWeights->m_SrcStart]; | |
479 const uint8_t* src_pixel = src_scan + j * Bpp; | |
480 dest_b_c += pixel_weight * (*src_pixel++); | |
481 dest_g_m += pixel_weight * (*src_pixel++); | |
482 dest_r_y += pixel_weight * (*src_pixel); | |
483 } | |
484 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { | |
485 dest_b_c = dest_b_c < 0 ? 0 : dest_b_c > 16711680 ?
16711680 : dest_b_c; | |
486 dest_g_m = dest_g_m < 0 ? 0 : dest_g_m > 16711680 ?
16711680 : dest_g_m; | |
487 dest_r_y = dest_r_y < 0 ? 0 : dest_r_y > 16711680 ?
16711680 : dest_r_y; | |
488 } | |
489 *dest_scan++ = (uint8_t)((dest_b_c) >> 16); | |
490 *dest_scan++ = (uint8_t)((dest_g_m) >> 16); | |
491 *dest_scan++ = (uint8_t)((dest_r_y) >> 16); | |
492 dest_scan += Bpp - 3; | |
493 } | |
494 break; | |
495 } | |
496 case 8: { | |
497 for (int col = m_DestClip.left; col < m_DestClip.right; col
++) { | |
498 PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeigh
t(col); | |
499 int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0
; | |
500 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeigh
ts->m_SrcEnd; j ++) { | |
501 int pixel_weight = pPixelWeights->m_Weights[j - pPix
elWeights->m_SrcStart]; | |
502 const uint8_t* src_pixel = src_scan + j * Bpp; | |
503 if (m_DestFormat == FXDIB_Argb) { | |
504 pixel_weight = pixel_weight * src_pixel[3] / 255
; | |
505 } else { | |
506 pixel_weight = pixel_weight * src_scan_mask[j] /
255; | |
507 } | |
508 dest_b_c += pixel_weight * (*src_pixel++); | |
509 dest_g_m += pixel_weight * (*src_pixel++); | |
510 dest_r_y += pixel_weight * (*src_pixel); | |
511 dest_a += pixel_weight; | |
512 } | |
513 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { | |
514 dest_r_y = dest_r_y < 0 ? 0 : dest_r_y > 16711680 ?
16711680 : dest_r_y; | |
515 dest_g_m = dest_g_m < 0 ? 0 : dest_g_m > 16711680 ?
16711680 : dest_g_m; | |
516 dest_b_c = dest_b_c < 0 ? 0 : dest_b_c > 16711680 ?
16711680 : dest_b_c; | |
517 dest_a = dest_a < 0 ? 0 : dest_a > 65536 ? 65536 : d
est_a; | |
518 } | |
519 *dest_scan++ = (uint8_t)((dest_b_c) >> 16); | |
520 *dest_scan++ = (uint8_t)((dest_g_m) >> 16); | |
521 *dest_scan++ = (uint8_t)((dest_r_y) >> 16); | |
522 if (m_DestFormat == FXDIB_Argb) { | |
523 *dest_scan = (uint8_t)((dest_a * 255) >> 16); | |
524 } | |
525 if (dest_scan_mask) { | |
526 *dest_scan_mask++ = (uint8_t)((dest_a * 255) >> 16); | |
527 } | |
528 dest_scan += Bpp - 3; | |
529 } | |
530 break; | |
531 } | |
532 } | |
533 rows_to_go --; | |
534 } | |
535 return FALSE; | |
536 } | |
537 void CStretchEngine::StretchVert() | |
538 { | |
539 if (m_DestHeight == 0) { | |
540 return; | |
541 } | |
542 CWeightTable table; | |
543 table.Calc(m_DestHeight, m_DestClip.top, m_DestClip.bottom, m_SrcHeight, m_S
rcClip.top, m_SrcClip.bottom, m_Flags); | |
544 if (table.m_pWeightTables == NULL) { | |
545 return; | |
546 } | |
547 int DestBpp = m_DestBpp / 8; | |
548 for (int row = m_DestClip.top; row < m_DestClip.bottom; row ++) { | |
549 unsigned char* dest_scan = m_pDestScanline; | |
550 unsigned char* dest_sacn_mask = m_pDestMaskScanline; | |
551 PixelWeight* pPixelWeights = table.GetPixelWeight(row); | |
552 switch(m_TransMethod) { | |
553 case 1: | |
554 case 2: | |
555 case 3: { | |
556 for (int col = m_DestClip.left; col < m_DestClip.right; col
++) { | |
557 unsigned char* src_scan = m_pInterBuf + (col - m_DestCli
p.left) * DestBpp; | |
558 int dest_a = 0; | |
559 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeigh
ts->m_SrcEnd; j ++) { | |
560 int pixel_weight = pPixelWeights->m_Weights[j - pPix
elWeights->m_SrcStart]; | |
561 dest_a += pixel_weight * src_scan[(j - m_SrcClip.top
) * m_InterPitch]; | |
562 } | |
563 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { | |
564 dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 167116
80 : dest_a; | |
565 } | |
566 *dest_scan = (uint8_t)(dest_a >> 16); | |
567 dest_scan += DestBpp; | |
568 } | |
569 break; | |
570 } | |
571 case 4: { | |
572 for (int col = m_DestClip.left; col < m_DestClip.right; col
++) { | |
573 unsigned char* src_scan = m_pInterBuf + (col - m_DestCli
p.left) * DestBpp; | |
574 unsigned char* src_scan_mask = m_pExtraAlphaBuf + (col -
m_DestClip.left); | |
575 int dest_a = 0, dest_k = 0; | |
576 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeigh
ts->m_SrcEnd; j ++) { | |
577 int pixel_weight = pPixelWeights->m_Weights[j - pPix
elWeights->m_SrcStart]; | |
578 dest_k += pixel_weight * src_scan[(j - m_SrcClip.top
) * m_InterPitch]; | |
579 dest_a += pixel_weight * src_scan_mask[(j - m_SrcCli
p.top) * m_ExtraMaskPitch]; | |
580 } | |
581 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { | |
582 dest_k = dest_k < 0 ? 0 : dest_k > 16711680 ? 167116
80 : dest_k; | |
583 dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 167116
80 : dest_a; | |
584 } | |
585 *dest_scan = (uint8_t)(dest_k >> 16); | |
586 dest_scan += DestBpp; | |
587 *dest_sacn_mask++ = (uint8_t)(dest_a >> 16); | |
588 } | |
589 break; | |
590 } | |
591 case 5: | |
592 case 7: { | |
593 for (int col = m_DestClip.left; col < m_DestClip.right; col
++) { | |
594 unsigned char* src_scan = m_pInterBuf + (col - m_DestCli
p.left) * DestBpp; | |
595 int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0; | |
596 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeigh
ts->m_SrcEnd; j ++) { | |
597 int pixel_weight = pPixelWeights->m_Weights[j - pPix
elWeights->m_SrcStart]; | |
598 const uint8_t* src_pixel = src_scan + (j - m_SrcClip
.top) * m_InterPitch; | |
599 dest_b_c += pixel_weight * (*src_pixel++); | |
600 dest_g_m += pixel_weight * (*src_pixel++); | |
601 dest_r_y += pixel_weight * (*src_pixel); | |
602 } | |
603 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { | |
604 dest_r_y = dest_r_y < 0 ? 0 : dest_r_y > 16711680 ?
16711680 : dest_r_y; | |
605 dest_g_m = dest_g_m < 0 ? 0 : dest_g_m > 16711680 ?
16711680 : dest_g_m; | |
606 dest_b_c = dest_b_c < 0 ? 0 : dest_b_c > 16711680 ?
16711680 : dest_b_c; | |
607 } | |
608 dest_scan[0] = (uint8_t)((dest_b_c) >> 16); | |
609 dest_scan[1] = (uint8_t)((dest_g_m) >> 16); | |
610 dest_scan[2] = (uint8_t)((dest_r_y) >> 16); | |
611 dest_scan += DestBpp; | |
612 } | |
613 break; | |
614 } | |
615 case 6: | |
616 case 8: { | |
617 for (int col = m_DestClip.left; col < m_DestClip.right; col
++) { | |
618 unsigned char* src_scan = m_pInterBuf + (col - m_DestCli
p.left) * DestBpp; | |
619 unsigned char* src_scan_mask = NULL; | |
620 if (m_DestFormat != FXDIB_Argb) { | |
621 src_scan_mask = m_pExtraAlphaBuf + (col - m_DestClip
.left); | |
622 } | |
623 int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0
; | |
624 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeigh
ts->m_SrcEnd; j ++) { | |
625 int pixel_weight = pPixelWeights->m_Weights[j - pPix
elWeights->m_SrcStart]; | |
626 const uint8_t* src_pixel = src_scan + (j - m_SrcClip
.top) * m_InterPitch; | |
627 int mask_v = 255; | |
628 if (src_scan_mask) { | |
629 mask_v = src_scan_mask[(j - m_SrcClip.top) * m_E
xtraMaskPitch]; | |
630 } | |
631 dest_b_c += pixel_weight * (*src_pixel++); | |
632 dest_g_m += pixel_weight * (*src_pixel++); | |
633 dest_r_y += pixel_weight * (*src_pixel); | |
634 if (m_DestFormat == FXDIB_Argb) { | |
635 dest_a += pixel_weight * (*(src_pixel + 1)); | |
636 } else { | |
637 dest_a += pixel_weight * mask_v; | |
638 } | |
639 } | |
640 if (m_Flags & FXDIB_BICUBIC_INTERPOL) { | |
641 dest_r_y = dest_r_y < 0 ? 0 : dest_r_y > 16711680 ?
16711680 : dest_r_y; | |
642 dest_g_m = dest_g_m < 0 ? 0 : dest_g_m > 16711680 ?
16711680 : dest_g_m; | |
643 dest_b_c = dest_b_c < 0 ? 0 : dest_b_c > 16711680 ?
16711680 : dest_b_c; | |
644 dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 167116
80 : dest_a; | |
645 } | |
646 if (dest_a) { | |
647 int r = ((FX_DWORD)dest_r_y) * 255 / dest_a; | |
648 int g = ((FX_DWORD)dest_g_m) * 255 / dest_a; | |
649 int b = ((FX_DWORD)dest_b_c) * 255 / dest_a; | |
650 dest_scan[0] = b > 255 ? 255 : b < 0 ? 0 : b; | |
651 dest_scan[1] = g > 255 ? 255 : g < 0 ? 0 : g; | |
652 dest_scan[2] = r > 255 ? 255 : r < 0 ? 0 : r; | |
653 } | |
654 if (m_DestFormat == FXDIB_Argb) { | |
655 dest_scan[3] = (uint8_t)((dest_a) >> 16); | |
656 } else { | |
657 *dest_sacn_mask = (uint8_t)((dest_a) >> 16); | |
658 } | |
659 dest_scan += DestBpp; | |
660 if (dest_sacn_mask) { | |
661 dest_sacn_mask++; | |
662 } | |
663 } | |
664 break; | |
665 } | |
666 } | |
667 m_pDestBitmap->ComposeScanline(row - m_DestClip.top, m_pDestScanline, m_
pDestMaskScanline); | |
668 } | |
669 } | |
670 CFX_ImageStretcher::CFX_ImageStretcher() | |
671 { | |
672 m_pScanline = NULL; | |
673 m_pStretchEngine = NULL; | |
674 m_pMaskScanline = NULL; | |
675 } | |
676 CFX_ImageStretcher::~CFX_ImageStretcher() | |
677 { | |
678 if (m_pScanline) { | |
679 FX_Free(m_pScanline); | |
680 } | |
681 delete m_pStretchEngine; | |
682 if (m_pMaskScanline) { | 925 if (m_pMaskScanline) { |
683 FX_Free(m_pMaskScanline); | 926 m_pSource->m_pAlphaMask->DownSampleScanline( |
684 } | 927 src_y, m_pMaskScanline, 1, m_DestWidth, m_bFlipX, m_ClipRect.left, |
685 } | 928 result_width); |
686 FXDIB_Format _GetStretchedFormat(const CFX_DIBSource* pSrc) | 929 } |
687 { | 930 m_pDest->ComposeScanline(dest_y, m_pScanline, m_pMaskScanline); |
688 FXDIB_Format format = pSrc->GetFormat(); | 931 } |
689 if (format == FXDIB_1bppMask) { | 932 return FALSE; |
690 format = FXDIB_8bppMask; | 933 } |
691 } else if (format == FXDIB_1bppRgb) { | |
692 format = FXDIB_8bppRgb; | |
693 } else if (format == FXDIB_8bppRgb) { | |
694 if (pSrc->GetPalette()) { | |
695 format = FXDIB_Rgb; | |
696 } | |
697 } | |
698 return format; | |
699 } | |
700 FX_BOOL CFX_ImageStretcher::Start(IFX_ScanlineComposer* pDest, | |
701 const CFX_DIBSource* pSource, int dest_width,
int dest_height, | |
702 const FX_RECT& rect, FX_DWORD flags) | |
703 { | |
704 m_DestFormat = _GetStretchedFormat(pSource); | |
705 m_DestBPP = m_DestFormat & 0xff; | |
706 m_pDest = pDest; | |
707 m_pSource = pSource; | |
708 m_DestWidth = dest_width; | |
709 m_DestHeight = dest_height; | |
710 m_ClipRect = rect; | |
711 m_Flags = flags; | |
712 if (pSource->GetFormat() == FXDIB_1bppRgb && pSource->GetPalette()) { | |
713 FX_ARGB pal[256]; | |
714 int a0, r0, g0, b0, a1, r1, g1, b1; | |
715 ArgbDecode(pSource->GetPaletteEntry(0), a0, r0, g0, b0); | |
716 ArgbDecode(pSource->GetPaletteEntry(1), a1, r1, g1, b1); | |
717 for (int i = 0; i < 256; i ++) { | |
718 int a = a0 + (a1 - a0) * i / 255; | |
719 int r = r0 + (r1 - r0) * i / 255; | |
720 int g = g0 + (g1 - g0) * i / 255; | |
721 int b = b0 + (b1 - b0) * i / 255; | |
722 pal[i] = ArgbEncode(a, r, g, b); | |
723 } | |
724 if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, pal)) { | |
725 return FALSE; | |
726 } | |
727 } else if (pSource->GetFormat() == FXDIB_1bppCmyk && pSource->GetPalette())
{ | |
728 FX_CMYK pal[256]; | |
729 int c0, m0, y0, k0, c1, m1, y1, k1; | |
730 CmykDecode(pSource->GetPaletteEntry(0), c0, m0, y0, k0); | |
731 CmykDecode(pSource->GetPaletteEntry(1), c1, m1, y1, k1); | |
732 for (int i = 0; i < 256; i ++) { | |
733 int c = c0 + (c1 - c0) * i / 255; | |
734 int m = m0 + (m1 - m0) * i / 255; | |
735 int y = y0 + (y1 - y0) * i / 255; | |
736 int k = k0 + (k1 - k0) * i / 255; | |
737 pal[i] = CmykEncode(c, m, y, k); | |
738 } | |
739 if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, pal)) { | |
740 return FALSE; | |
741 } | |
742 } else if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, NULL))
{ | |
743 return FALSE; | |
744 } | |
745 if (flags & FXDIB_DOWNSAMPLE) { | |
746 return StartQuickStretch(); | |
747 } | |
748 return StartStretch(); | |
749 } | |
750 FX_BOOL CFX_ImageStretcher::Continue(IFX_Pause* pPause) | |
751 { | |
752 if (m_Flags & FXDIB_DOWNSAMPLE) { | |
753 return ContinueQuickStretch(pPause); | |
754 } | |
755 return ContinueStretch(pPause); | |
756 } | |
757 #define MAX_PROGRESSIVE_STRETCH_PIXELS» 1000000 | |
758 FX_BOOL CFX_ImageStretcher::StartStretch() | |
759 { | |
760 m_pStretchEngine = new CStretchEngine(m_pDest, m_DestFormat, m_DestWidth, m_
DestHeight, m_ClipRect, m_pSource, m_Flags); | |
761 m_pStretchEngine->StartStretchHorz(); | |
762 if (m_pSource->GetWidth() * m_pSource->GetHeight() < MAX_PROGRESSIVE_STRETCH
_PIXELS) { | |
763 m_pStretchEngine->Continue(NULL); | |
764 return FALSE; | |
765 } | |
766 return TRUE; | |
767 } | |
768 FX_BOOL CFX_ImageStretcher::ContinueStretch(IFX_Pause* pPause) | |
769 { | |
770 if (m_pStretchEngine == NULL) { | |
771 return FALSE; | |
772 } | |
773 return m_pStretchEngine->Continue(pPause); | |
774 } | |
775 FX_BOOL CFX_ImageStretcher::StartQuickStretch() | |
776 { | |
777 m_bFlipX = FALSE; | |
778 m_bFlipY = FALSE; | |
779 if (m_DestWidth < 0) { | |
780 m_bFlipX = TRUE; | |
781 m_DestWidth = -m_DestWidth; | |
782 } | |
783 if (m_DestHeight < 0) { | |
784 m_bFlipY = TRUE; | |
785 m_DestHeight = -m_DestHeight; | |
786 } | |
787 m_LineIndex = 0; | |
788 FX_DWORD size = m_ClipRect.Width(); | |
789 if (size && m_DestBPP > (int)(INT_MAX / size)) { | |
790 return FALSE; | |
791 } | |
792 size *= m_DestBPP; | |
793 m_pScanline = FX_Alloc(uint8_t, (size / 8 + 3) / 4 * 4); | |
794 if (m_pSource->m_pAlphaMask) { | |
795 m_pMaskScanline = FX_Alloc(uint8_t, (m_ClipRect.Width() + 3) / 4 * 4); | |
796 } | |
797 if (m_pSource->GetWidth() * m_pSource->GetHeight() < MAX_PROGRESSIVE_STRETCH
_PIXELS) { | |
798 ContinueQuickStretch(NULL); | |
799 return FALSE; | |
800 } | |
801 return TRUE; | |
802 } | |
803 FX_BOOL CFX_ImageStretcher::ContinueQuickStretch(IFX_Pause* pPause) | |
804 { | |
805 if (m_pScanline == NULL) { | |
806 return FALSE; | |
807 } | |
808 int result_width = m_ClipRect.Width(), result_height = m_ClipRect.Height(); | |
809 int src_height = m_pSource->GetHeight(); | |
810 for (; m_LineIndex < result_height; m_LineIndex ++) { | |
811 int dest_y, src_y; | |
812 if (m_bFlipY) { | |
813 dest_y = result_height - m_LineIndex - 1; | |
814 src_y = (m_DestHeight - (dest_y + m_ClipRect.top) - 1) * src_height
/ m_DestHeight; | |
815 } else { | |
816 dest_y = m_LineIndex; | |
817 src_y = (dest_y + m_ClipRect.top) * src_height / m_DestHeight; | |
818 } | |
819 if (src_y >= src_height) { | |
820 src_y = src_height - 1; | |
821 } | |
822 if (src_y < 0) { | |
823 src_y = 0; | |
824 } | |
825 if (m_pSource->SkipToScanline(src_y, pPause)) { | |
826 return TRUE; | |
827 } | |
828 m_pSource->DownSampleScanline(src_y, m_pScanline, m_DestBPP, m_DestWidth
, m_bFlipX, m_ClipRect.left, result_width); | |
829 if (m_pMaskScanline) { | |
830 m_pSource->m_pAlphaMask->DownSampleScanline(src_y, m_pMaskScanline,
1, m_DestWidth, m_bFlipX, m_ClipRect.left, result_width); | |
831 } | |
832 m_pDest->ComposeScanline(dest_y, m_pScanline, m_pMaskScanline); | |
833 } | |
834 return FALSE; | |
835 } | |
OLD | NEW |