1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include <limits.h>
8
9 #include "core/fxcodec/jbig2/JBig2_Image.h"
10 #include "core/fxcrt/fx_coordinates.h"
11 #include "core/fxcrt/fx_safe_types.h"
12
13 namespace {
14
15 const int kMaxImagePixels = INT_MAX - 31;
16 const int kMaxImageBytes = kMaxImagePixels / 8;
17
18 } // namespace
19
CJBig2_Image(int32_t w,int32_t h)20 CJBig2_Image::CJBig2_Image(int32_t w, int32_t h)
21 : m_pData(nullptr),
22 m_nWidth(0),
23 m_nHeight(0),
24 m_nStride(0),
25 m_bOwnsBuffer(true) {
26 if (w <= 0 || h <= 0 || w > kMaxImagePixels)
27 return;
28
29 int32_t stride_pixels = (w + 31) & ~31;
30 if (h > kMaxImagePixels / stride_pixels)
31 return;
32
33 m_nWidth = w;
34 m_nHeight = h;
35 m_nStride = stride_pixels / 8;
36 m_pData = FX_Alloc2D(uint8_t, m_nStride, m_nHeight);
37 }
38
CJBig2_Image(int32_t w,int32_t h,int32_t stride,uint8_t * pBuf)39 CJBig2_Image::CJBig2_Image(int32_t w, int32_t h, int32_t stride, uint8_t* pBuf)
40 : m_pData(nullptr),
41 m_nWidth(0),
42 m_nHeight(0),
43 m_nStride(0),
44 m_bOwnsBuffer(false) {
45 if (w < 0 || h < 0 || stride < 0 || stride > kMaxImageBytes)
46 return;
47
48 int32_t stride_pixels = 8 * stride;
49 if (stride_pixels < w || h > kMaxImagePixels / stride_pixels)
50 return;
51
52 m_nWidth = w;
53 m_nHeight = h;
54 m_nStride = stride;
55 m_pData = pBuf;
56 }
57
CJBig2_Image(const CJBig2_Image & other)58 CJBig2_Image::CJBig2_Image(const CJBig2_Image& other)
59 : m_pData(nullptr),
60 m_nWidth(other.m_nWidth),
61 m_nHeight(other.m_nHeight),
62 m_nStride(other.m_nStride),
63 m_bOwnsBuffer(true) {
64 if (other.m_pData) {
65 m_pData = FX_Alloc2D(uint8_t, m_nStride, m_nHeight);
66 JBIG2_memcpy(m_pData, other.m_pData, m_nStride * m_nHeight);
67 }
68 }
69
~CJBig2_Image()70 CJBig2_Image::~CJBig2_Image() {
71 if (m_bOwnsBuffer) {
72 FX_Free(m_pData);
73 }
74 }
75
getPixel(int32_t x,int32_t y)76 int CJBig2_Image::getPixel(int32_t x, int32_t y) {
77 if (!m_pData)
78 return 0;
79
80 if (x < 0 || x >= m_nWidth)
81 return 0;
82
83 if (y < 0 || y >= m_nHeight)
84 return 0;
85
86 int32_t m = y * m_nStride + (x >> 3);
87 int32_t n = x & 7;
88 return ((m_pData[m] >> (7 - n)) & 1);
89 }
90
setPixel(int32_t x,int32_t y,int v)91 int32_t CJBig2_Image::setPixel(int32_t x, int32_t y, int v) {
92 if (!m_pData)
93 return 0;
94
95 if (x < 0 || x >= m_nWidth)
96 return 0;
97
98 if (y < 0 || y >= m_nHeight)
99 return 0;
100
101 int32_t m = y * m_nStride + (x >> 3);
102 int32_t n = x & 7;
103 if (v)
104 m_pData[m] |= 1 << (7 - n);
105 else
106 m_pData[m] &= ~(1 << (7 - n));
107
108 return 1;
109 }
110
copyLine(int32_t hTo,int32_t hFrom)111 void CJBig2_Image::copyLine(int32_t hTo, int32_t hFrom) {
112 if (!m_pData) {
113 return;
114 }
115 if (hFrom < 0 || hFrom >= m_nHeight) {
116 JBIG2_memset(m_pData + hTo * m_nStride, 0, m_nStride);
117 } else {
118 JBIG2_memcpy(m_pData + hTo * m_nStride, m_pData + hFrom * m_nStride,
119 m_nStride);
120 }
121 }
fill(bool v)122 void CJBig2_Image::fill(bool v) {
123 if (!m_pData) {
124 return;
125 }
126 JBIG2_memset(m_pData, v ? 0xff : 0, m_nStride * m_nHeight);
127 }
composeTo(CJBig2_Image * pDst,int32_t x,int32_t y,JBig2ComposeOp op)128 bool CJBig2_Image::composeTo(CJBig2_Image* pDst,
129 int32_t x,
130 int32_t y,
131 JBig2ComposeOp op) {
132 if (!m_pData) {
133 return false;
134 }
135 return composeTo_opt2(pDst, x, y, op);
136 }
composeTo(CJBig2_Image * pDst,int32_t x,int32_t y,JBig2ComposeOp op,const FX_RECT * pSrcRect)137 bool CJBig2_Image::composeTo(CJBig2_Image* pDst,
138 int32_t x,
139 int32_t y,
140 JBig2ComposeOp op,
141 const FX_RECT* pSrcRect) {
142 if (!m_pData)
143 return false;
144
145 if (!pSrcRect || *pSrcRect == FX_RECT(0, 0, m_nWidth, m_nHeight))
146 return composeTo_opt2(pDst, x, y, op);
147
148 return composeTo_opt2(pDst, x, y, op, pSrcRect);
149 }
150
composeFrom(int32_t x,int32_t y,CJBig2_Image * pSrc,JBig2ComposeOp op)151 bool CJBig2_Image::composeFrom(int32_t x,
152 int32_t y,
153 CJBig2_Image* pSrc,
154 JBig2ComposeOp op) {
155 if (!m_pData) {
156 return false;
157 }
158 return pSrc->composeTo(this, x, y, op);
159 }
composeFrom(int32_t x,int32_t y,CJBig2_Image * pSrc,JBig2ComposeOp op,const FX_RECT * pSrcRect)160 bool CJBig2_Image::composeFrom(int32_t x,
161 int32_t y,
162 CJBig2_Image* pSrc,
163 JBig2ComposeOp op,
164 const FX_RECT* pSrcRect) {
165 if (!m_pData) {
166 return false;
167 }
168 return pSrc->composeTo(this, x, y, op, pSrcRect);
169 }
170 #define JBIG2_GETDWORD(buf) \
171 ((uint32_t)(((buf)[0] << 24) | ((buf)[1] << 16) | ((buf)[2] << 8) | (buf)[3]))
subImage(int32_t x,int32_t y,int32_t w,int32_t h)172 CJBig2_Image* CJBig2_Image::subImage(int32_t x,
173 int32_t y,
174 int32_t w,
175 int32_t h) {
176 int32_t m, n, j;
177 uint8_t *pLineSrc, *pLineDst;
178 uint32_t wTmp;
179 uint8_t *pSrc, *pSrcEnd, *pDst, *pDstEnd;
180 if (w == 0 || h == 0) {
181 return nullptr;
182 }
183 CJBig2_Image* pImage = new CJBig2_Image(w, h);
184 if (!m_pData) {
185 pImage->fill(0);
186 return pImage;
187 }
188 if (!pImage->m_pData) {
189 return pImage;
190 }
191 pLineSrc = m_pData + m_nStride * y;
192 pLineDst = pImage->m_pData;
193 m = (x >> 5) << 2;
194 n = x & 31;
195 if (n == 0) {
196 for (j = 0; j < h; j++) {
197 pSrc = pLineSrc + m;
198 pSrcEnd = pLineSrc + m_nStride;
199 pDst = pLineDst;
200 pDstEnd = pLineDst + pImage->m_nStride;
201 for (; pDst < pDstEnd; pSrc += 4, pDst += 4) {
202 *((uint32_t*)pDst) = *((uint32_t*)pSrc);
203 }
204 pLineSrc += m_nStride;
205 pLineDst += pImage->m_nStride;
206 }
207 } else {
208 for (j = 0; j < h; j++) {
209 pSrc = pLineSrc + m;
210 pSrcEnd = pLineSrc + m_nStride;
211 pDst = pLineDst;
212 pDstEnd = pLineDst + pImage->m_nStride;
213 for (; pDst < pDstEnd; pSrc += 4, pDst += 4) {
214 if (pSrc + 4 < pSrcEnd) {
215 wTmp = (JBIG2_GETDWORD(pSrc) << n) |
216 (JBIG2_GETDWORD(pSrc + 4) >> (32 - n));
217 } else {
218 wTmp = JBIG2_GETDWORD(pSrc) << n;
219 }
220 pDst[0] = (uint8_t)(wTmp >> 24);
221 pDst[1] = (uint8_t)(wTmp >> 16);
222 pDst[2] = (uint8_t)(wTmp >> 8);
223 pDst[3] = (uint8_t)wTmp;
224 }
225 pLineSrc += m_nStride;
226 pLineDst += pImage->m_nStride;
227 }
228 }
229 return pImage;
230 }
231
expand(int32_t h,bool v)232 void CJBig2_Image::expand(int32_t h, bool v) {
233 if (!m_pData || h <= m_nHeight || h > kMaxImageBytes / m_nStride)
234 return;
235
236 if (m_bOwnsBuffer) {
237 m_pData = FX_Realloc(uint8_t, m_pData, h * m_nStride);
238 } else {
239 uint8_t* pExternalBuffer = m_pData;
240 m_pData = FX_Alloc(uint8_t, h * m_nStride);
241 JBIG2_memcpy(m_pData, pExternalBuffer, m_nHeight * m_nStride);
242 m_bOwnsBuffer = true;
243 }
244 JBIG2_memset(m_pData + m_nHeight * m_nStride, v ? 0xff : 0,
245 (h - m_nHeight) * m_nStride);
246 m_nHeight = h;
247 }
248
composeTo_opt2(CJBig2_Image * pDst,int32_t x,int32_t y,JBig2ComposeOp op)249 bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst,
250 int32_t x,
251 int32_t y,
252 JBig2ComposeOp op) {
253 int32_t xs0 = 0, ys0 = 0, xs1 = 0, ys1 = 0, xd0 = 0, yd0 = 0, xd1 = 0,
254 yd1 = 0, xx = 0, yy = 0, w = 0, h = 0, middleDwords = 0, lineLeft = 0;
255
256 uint32_t s1 = 0, d1 = 0, d2 = 0, shift = 0, shift1 = 0, shift2 = 0, tmp = 0,
257 tmp1 = 0, tmp2 = 0, maskL = 0, maskR = 0, maskM = 0;
258
259 if (!m_pData)
260 return false;
261
262 if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576)
263 return false;
264
265 if (y < 0) {
266 ys0 = -y;
267 }
268 if (y + m_nHeight > pDst->m_nHeight) {
269 ys1 = pDst->m_nHeight - y;
270 } else {
271 ys1 = m_nHeight;
272 }
273 if (x < 0) {
274 xs0 = -x;
275 }
276 if (x + m_nWidth > pDst->m_nWidth) {
277 xs1 = pDst->m_nWidth - x;
278 } else {
279 xs1 = m_nWidth;
280 }
281 if ((ys0 >= ys1) || (xs0 >= xs1)) {
282 return 0;
283 }
284 w = xs1 - xs0;
285 h = ys1 - ys0;
286 if (y >= 0) {
287 yd0 = y;
288 }
289 if (x >= 0) {
290 xd0 = x;
291 }
292 xd1 = xd0 + w;
293 yd1 = yd0 + h;
294 d1 = xd0 & 31;
295 d2 = xd1 & 31;
296 s1 = xs0 & 31;
297 maskL = 0xffffffff >> d1;
298 maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32);
299 maskM = maskL & maskR;
300 uint8_t* lineSrc = m_pData + ys0 * m_nStride + ((xs0 >> 5) << 2);
301 lineLeft = m_nStride - ((xs0 >> 5) << 2);
302 uint8_t* lineDst = pDst->m_pData + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2);
303 if ((xd0 & ~31) == ((xd1 - 1) & ~31)) {
304 if ((xs0 & ~31) == ((xs1 - 1) & ~31)) {
305 if (s1 > d1) {
306 shift = s1 - d1;
307 for (yy = yd0; yy < yd1; yy++) {
308 tmp1 = JBIG2_GETDWORD(lineSrc) << shift;
309 tmp2 = JBIG2_GETDWORD(lineDst);
310 switch (op) {
311 case JBIG2_COMPOSE_OR:
312 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
313 break;
314 case JBIG2_COMPOSE_AND:
315 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
316 break;
317 case JBIG2_COMPOSE_XOR:
318 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
319 break;
320 case JBIG2_COMPOSE_XNOR:
321 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
322 break;
323 case JBIG2_COMPOSE_REPLACE:
324 tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
325 break;
326 }
327 lineDst[0] = (uint8_t)(tmp >> 24);
328 lineDst[1] = (uint8_t)(tmp >> 16);
329 lineDst[2] = (uint8_t)(tmp >> 8);
330 lineDst[3] = (uint8_t)tmp;
331 lineSrc += m_nStride;
332 lineDst += pDst->m_nStride;
333 }
334 } else {
335 shift = d1 - s1;
336 for (yy = yd0; yy < yd1; yy++) {
337 tmp1 = JBIG2_GETDWORD(lineSrc) >> shift;
338 tmp2 = JBIG2_GETDWORD(lineDst);
339 switch (op) {
340 case JBIG2_COMPOSE_OR:
341 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
342 break;
343 case JBIG2_COMPOSE_AND:
344 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
345 break;
346 case JBIG2_COMPOSE_XOR:
347 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
348 break;
349 case JBIG2_COMPOSE_XNOR:
350 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
351 break;
352 case JBIG2_COMPOSE_REPLACE:
353 tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
354 break;
355 }
356 lineDst[0] = (uint8_t)(tmp >> 24);
357 lineDst[1] = (uint8_t)(tmp >> 16);
358 lineDst[2] = (uint8_t)(tmp >> 8);
359 lineDst[3] = (uint8_t)tmp;
360 lineSrc += m_nStride;
361 lineDst += pDst->m_nStride;
362 }
363 }
364 } else {
365 shift1 = s1 - d1;
366 shift2 = 32 - shift1;
367 for (yy = yd0; yy < yd1; yy++) {
368 tmp1 = (JBIG2_GETDWORD(lineSrc) << shift1) |
369 (JBIG2_GETDWORD(lineSrc + 4) >> shift2);
370 tmp2 = JBIG2_GETDWORD(lineDst);
371 switch (op) {
372 case JBIG2_COMPOSE_OR:
373 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
374 break;
375 case JBIG2_COMPOSE_AND:
376 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
377 break;
378 case JBIG2_COMPOSE_XOR:
379 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
380 break;
381 case JBIG2_COMPOSE_XNOR:
382 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
383 break;
384 case JBIG2_COMPOSE_REPLACE:
385 tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
386 break;
387 }
388 lineDst[0] = (uint8_t)(tmp >> 24);
389 lineDst[1] = (uint8_t)(tmp >> 16);
390 lineDst[2] = (uint8_t)(tmp >> 8);
391 lineDst[3] = (uint8_t)tmp;
392 lineSrc += m_nStride;
393 lineDst += pDst->m_nStride;
394 }
395 }
396 } else {
397 uint8_t* sp = nullptr;
398 uint8_t* dp = nullptr;
399
400 if (s1 > d1) {
401 shift1 = s1 - d1;
402 shift2 = 32 - shift1;
403 middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
404 for (yy = yd0; yy < yd1; yy++) {
405 sp = lineSrc;
406 dp = lineDst;
407 if (d1 != 0) {
408 tmp1 = (JBIG2_GETDWORD(sp) << shift1) |
409 (JBIG2_GETDWORD(sp + 4) >> shift2);
410 tmp2 = JBIG2_GETDWORD(dp);
411 switch (op) {
412 case JBIG2_COMPOSE_OR:
413 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
414 break;
415 case JBIG2_COMPOSE_AND:
416 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
417 break;
418 case JBIG2_COMPOSE_XOR:
419 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
420 break;
421 case JBIG2_COMPOSE_XNOR:
422 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
423 break;
424 case JBIG2_COMPOSE_REPLACE:
425 tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
426 break;
427 }
428 dp[0] = (uint8_t)(tmp >> 24);
429 dp[1] = (uint8_t)(tmp >> 16);
430 dp[2] = (uint8_t)(tmp >> 8);
431 dp[3] = (uint8_t)tmp;
432 sp += 4;
433 dp += 4;
434 }
435 for (xx = 0; xx < middleDwords; xx++) {
436 tmp1 = (JBIG2_GETDWORD(sp) << shift1) |
437 (JBIG2_GETDWORD(sp + 4) >> shift2);
438 tmp2 = JBIG2_GETDWORD(dp);
439 switch (op) {
440 case JBIG2_COMPOSE_OR:
441 tmp = tmp1 | tmp2;
442 break;
443 case JBIG2_COMPOSE_AND:
444 tmp = tmp1 & tmp2;
445 break;
446 case JBIG2_COMPOSE_XOR:
447 tmp = tmp1 ^ tmp2;
448 break;
449 case JBIG2_COMPOSE_XNOR:
450 tmp = ~(tmp1 ^ tmp2);
451 break;
452 case JBIG2_COMPOSE_REPLACE:
453 tmp = tmp1;
454 break;
455 }
456 dp[0] = (uint8_t)(tmp >> 24);
457 dp[1] = (uint8_t)(tmp >> 16);
458 dp[2] = (uint8_t)(tmp >> 8);
459 dp[3] = (uint8_t)tmp;
460 sp += 4;
461 dp += 4;
462 }
463 if (d2 != 0) {
464 tmp1 =
465 (JBIG2_GETDWORD(sp) << shift1) |
466 (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >>
467 shift2);
468 tmp2 = JBIG2_GETDWORD(dp);
469 switch (op) {
470 case JBIG2_COMPOSE_OR:
471 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
472 break;
473 case JBIG2_COMPOSE_AND:
474 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
475 break;
476 case JBIG2_COMPOSE_XOR:
477 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
478 break;
479 case JBIG2_COMPOSE_XNOR:
480 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
481 break;
482 case JBIG2_COMPOSE_REPLACE:
483 tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
484 break;
485 }
486 dp[0] = (uint8_t)(tmp >> 24);
487 dp[1] = (uint8_t)(tmp >> 16);
488 dp[2] = (uint8_t)(tmp >> 8);
489 dp[3] = (uint8_t)tmp;
490 }
491 lineSrc += m_nStride;
492 lineDst += pDst->m_nStride;
493 }
494 } else if (s1 == d1) {
495 middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
496 for (yy = yd0; yy < yd1; yy++) {
497 sp = lineSrc;
498 dp = lineDst;
499 if (d1 != 0) {
500 tmp1 = JBIG2_GETDWORD(sp);
501 tmp2 = JBIG2_GETDWORD(dp);
502 switch (op) {
503 case JBIG2_COMPOSE_OR:
504 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
505 break;
506 case JBIG2_COMPOSE_AND:
507 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
508 break;
509 case JBIG2_COMPOSE_XOR:
510 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
511 break;
512 case JBIG2_COMPOSE_XNOR:
513 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
514 break;
515 case JBIG2_COMPOSE_REPLACE:
516 tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
517 break;
518 }
519 dp[0] = (uint8_t)(tmp >> 24);
520 dp[1] = (uint8_t)(tmp >> 16);
521 dp[2] = (uint8_t)(tmp >> 8);
522 dp[3] = (uint8_t)tmp;
523 sp += 4;
524 dp += 4;
525 }
526 for (xx = 0; xx < middleDwords; xx++) {
527 tmp1 = JBIG2_GETDWORD(sp);
528 tmp2 = JBIG2_GETDWORD(dp);
529 switch (op) {
530 case JBIG2_COMPOSE_OR:
531 tmp = tmp1 | tmp2;
532 break;
533 case JBIG2_COMPOSE_AND:
534 tmp = tmp1 & tmp2;
535 break;
536 case JBIG2_COMPOSE_XOR:
537 tmp = tmp1 ^ tmp2;
538 break;
539 case JBIG2_COMPOSE_XNOR:
540 tmp = ~(tmp1 ^ tmp2);
541 break;
542 case JBIG2_COMPOSE_REPLACE:
543 tmp = tmp1;
544 break;
545 }
546 dp[0] = (uint8_t)(tmp >> 24);
547 dp[1] = (uint8_t)(tmp >> 16);
548 dp[2] = (uint8_t)(tmp >> 8);
549 dp[3] = (uint8_t)tmp;
550 sp += 4;
551 dp += 4;
552 }
553 if (d2 != 0) {
554 tmp1 = JBIG2_GETDWORD(sp);
555 tmp2 = JBIG2_GETDWORD(dp);
556 switch (op) {
557 case JBIG2_COMPOSE_OR:
558 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
559 break;
560 case JBIG2_COMPOSE_AND:
561 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
562 break;
563 case JBIG2_COMPOSE_XOR:
564 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
565 break;
566 case JBIG2_COMPOSE_XNOR:
567 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
568 break;
569 case JBIG2_COMPOSE_REPLACE:
570 tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
571 break;
572 }
573 dp[0] = (uint8_t)(tmp >> 24);
574 dp[1] = (uint8_t)(tmp >> 16);
575 dp[2] = (uint8_t)(tmp >> 8);
576 dp[3] = (uint8_t)tmp;
577 }
578 lineSrc += m_nStride;
579 lineDst += pDst->m_nStride;
580 }
581 } else {
582 shift1 = d1 - s1;
583 shift2 = 32 - shift1;
584 middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
585 for (yy = yd0; yy < yd1; yy++) {
586 sp = lineSrc;
587 dp = lineDst;
588 if (d1 != 0) {
589 tmp1 = JBIG2_GETDWORD(sp) >> shift1;
590 tmp2 = JBIG2_GETDWORD(dp);
591 switch (op) {
592 case JBIG2_COMPOSE_OR:
593 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
594 break;
595 case JBIG2_COMPOSE_AND:
596 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
597 break;
598 case JBIG2_COMPOSE_XOR:
599 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
600 break;
601 case JBIG2_COMPOSE_XNOR:
602 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
603 break;
604 case JBIG2_COMPOSE_REPLACE:
605 tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
606 break;
607 }
608 dp[0] = (uint8_t)(tmp >> 24);
609 dp[1] = (uint8_t)(tmp >> 16);
610 dp[2] = (uint8_t)(tmp >> 8);
611 dp[3] = (uint8_t)tmp;
612 dp += 4;
613 }
614 for (xx = 0; xx < middleDwords; xx++) {
615 tmp1 = (JBIG2_GETDWORD(sp) << shift2) |
616 ((JBIG2_GETDWORD(sp + 4)) >> shift1);
617 tmp2 = JBIG2_GETDWORD(dp);
618 switch (op) {
619 case JBIG2_COMPOSE_OR:
620 tmp = tmp1 | tmp2;
621 break;
622 case JBIG2_COMPOSE_AND:
623 tmp = tmp1 & tmp2;
624 break;
625 case JBIG2_COMPOSE_XOR:
626 tmp = tmp1 ^ tmp2;
627 break;
628 case JBIG2_COMPOSE_XNOR:
629 tmp = ~(tmp1 ^ tmp2);
630 break;
631 case JBIG2_COMPOSE_REPLACE:
632 tmp = tmp1;
633 break;
634 }
635 dp[0] = (uint8_t)(tmp >> 24);
636 dp[1] = (uint8_t)(tmp >> 16);
637 dp[2] = (uint8_t)(tmp >> 8);
638 dp[3] = (uint8_t)tmp;
639 sp += 4;
640 dp += 4;
641 }
642 if (d2 != 0) {
643 tmp1 =
644 (JBIG2_GETDWORD(sp) << shift2) |
645 (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >>
646 shift1);
647 tmp2 = JBIG2_GETDWORD(dp);
648 switch (op) {
649 case JBIG2_COMPOSE_OR:
650 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
651 break;
652 case JBIG2_COMPOSE_AND:
653 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
654 break;
655 case JBIG2_COMPOSE_XOR:
656 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
657 break;
658 case JBIG2_COMPOSE_XNOR:
659 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
660 break;
661 case JBIG2_COMPOSE_REPLACE:
662 tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
663 break;
664 }
665 dp[0] = (uint8_t)(tmp >> 24);
666 dp[1] = (uint8_t)(tmp >> 16);
667 dp[2] = (uint8_t)(tmp >> 8);
668 dp[3] = (uint8_t)tmp;
669 }
670 lineSrc += m_nStride;
671 lineDst += pDst->m_nStride;
672 }
673 }
674 }
675 return 1;
676 }
composeTo_opt2(CJBig2_Image * pDst,int32_t x,int32_t y,JBig2ComposeOp op,const FX_RECT * pSrcRect)677 bool CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst,
678 int32_t x,
679 int32_t y,
680 JBig2ComposeOp op,
681 const FX_RECT* pSrcRect) {
682 if (!m_pData) {
683 return false;
684 }
685 // TODO(weili): Check whether the range check is correct. Should x>=1048576?
686 if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576) {
687 return false;
688 }
689 int32_t sw = pSrcRect->Width();
690 int32_t sh = pSrcRect->Height();
691 int32_t ys0 = y < 0 ? -y : 0;
692 int32_t ys1 = y + sh > pDst->m_nHeight ? pDst->m_nHeight - y : sh;
693 int32_t xs0 = x < 0 ? -x : 0;
694 int32_t xs1 = x + sw > pDst->m_nWidth ? pDst->m_nWidth - x : sw;
695 if ((ys0 >= ys1) || (xs0 >= xs1)) {
696 return 0;
697 }
698 int32_t w = xs1 - xs0;
699 int32_t h = ys1 - ys0;
700 int32_t yd0 = y < 0 ? 0 : y;
701 int32_t xd0 = x < 0 ? 0 : x;
702 int32_t xd1 = xd0 + w;
703 int32_t yd1 = yd0 + h;
704 int32_t d1 = xd0 & 31;
705 int32_t d2 = xd1 & 31;
706 int32_t s1 = xs0 & 31;
707 int32_t maskL = 0xffffffff >> d1;
708 int32_t maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32);
709 int32_t maskM = maskL & maskR;
710 uint8_t* lineSrc = m_pData + (pSrcRect->top + ys0) * m_nStride +
711 (((xs0 + pSrcRect->left) >> 5) << 2);
712 int32_t lineLeft = m_nStride - ((xs0 >> 5) << 2);
713 uint8_t* lineDst = pDst->m_pData + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2);
714 if ((xd0 & ~31) == ((xd1 - 1) & ~31)) {
715 if ((xs0 & ~31) == ((xs1 - 1) & ~31)) {
716 if (s1 > d1) {
717 uint32_t shift = s1 - d1;
718 for (int32_t yy = yd0; yy < yd1; yy++) {
719 uint32_t tmp1 = JBIG2_GETDWORD(lineSrc) << shift;
720 uint32_t tmp2 = JBIG2_GETDWORD(lineDst);
721 uint32_t tmp = 0;
722 switch (op) {
723 case JBIG2_COMPOSE_OR:
724 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
725 break;
726 case JBIG2_COMPOSE_AND:
727 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
728 break;
729 case JBIG2_COMPOSE_XOR:
730 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
731 break;
732 case JBIG2_COMPOSE_XNOR:
733 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
734 break;
735 case JBIG2_COMPOSE_REPLACE:
736 tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
737 break;
738 }
739 lineDst[0] = (uint8_t)(tmp >> 24);
740 lineDst[1] = (uint8_t)(tmp >> 16);
741 lineDst[2] = (uint8_t)(tmp >> 8);
742 lineDst[3] = (uint8_t)tmp;
743 lineSrc += m_nStride;
744 lineDst += pDst->m_nStride;
745 }
746 } else {
747 uint32_t shift = d1 - s1;
748 for (int32_t yy = yd0; yy < yd1; yy++) {
749 uint32_t tmp1 = JBIG2_GETDWORD(lineSrc) >> shift;
750 uint32_t tmp2 = JBIG2_GETDWORD(lineDst);
751 uint32_t tmp = 0;
752 switch (op) {
753 case JBIG2_COMPOSE_OR:
754 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
755 break;
756 case JBIG2_COMPOSE_AND:
757 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
758 break;
759 case JBIG2_COMPOSE_XOR:
760 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
761 break;
762 case JBIG2_COMPOSE_XNOR:
763 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
764 break;
765 case JBIG2_COMPOSE_REPLACE:
766 tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
767 break;
768 }
769 lineDst[0] = (uint8_t)(tmp >> 24);
770 lineDst[1] = (uint8_t)(tmp >> 16);
771 lineDst[2] = (uint8_t)(tmp >> 8);
772 lineDst[3] = (uint8_t)tmp;
773 lineSrc += m_nStride;
774 lineDst += pDst->m_nStride;
775 }
776 }
777 } else {
778 uint32_t shift1 = s1 - d1;
779 uint32_t shift2 = 32 - shift1;
780 for (int32_t yy = yd0; yy < yd1; yy++) {
781 uint32_t tmp1 = (JBIG2_GETDWORD(lineSrc) << shift1) |
782 (JBIG2_GETDWORD(lineSrc + 4) >> shift2);
783 uint32_t tmp2 = JBIG2_GETDWORD(lineDst);
784 uint32_t tmp = 0;
785 switch (op) {
786 case JBIG2_COMPOSE_OR:
787 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
788 break;
789 case JBIG2_COMPOSE_AND:
790 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
791 break;
792 case JBIG2_COMPOSE_XOR:
793 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
794 break;
795 case JBIG2_COMPOSE_XNOR:
796 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
797 break;
798 case JBIG2_COMPOSE_REPLACE:
799 tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
800 break;
801 }
802 lineDst[0] = (uint8_t)(tmp >> 24);
803 lineDst[1] = (uint8_t)(tmp >> 16);
804 lineDst[2] = (uint8_t)(tmp >> 8);
805 lineDst[3] = (uint8_t)tmp;
806 lineSrc += m_nStride;
807 lineDst += pDst->m_nStride;
808 }
809 }
810 } else {
811 if (s1 > d1) {
812 uint32_t shift1 = s1 - d1;
813 uint32_t shift2 = 32 - shift1;
814 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
815 for (int32_t yy = yd0; yy < yd1; yy++) {
816 uint8_t* sp = lineSrc;
817 uint8_t* dp = lineDst;
818 if (d1 != 0) {
819 uint32_t tmp1 = (JBIG2_GETDWORD(sp) << shift1) |
820 (JBIG2_GETDWORD(sp + 4) >> shift2);
821 uint32_t tmp2 = JBIG2_GETDWORD(dp);
822 uint32_t tmp = 0;
823 switch (op) {
824 case JBIG2_COMPOSE_OR:
825 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
826 break;
827 case JBIG2_COMPOSE_AND:
828 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
829 break;
830 case JBIG2_COMPOSE_XOR:
831 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
832 break;
833 case JBIG2_COMPOSE_XNOR:
834 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
835 break;
836 case JBIG2_COMPOSE_REPLACE:
837 tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
838 break;
839 }
840 dp[0] = (uint8_t)(tmp >> 24);
841 dp[1] = (uint8_t)(tmp >> 16);
842 dp[2] = (uint8_t)(tmp >> 8);
843 dp[3] = (uint8_t)tmp;
844 sp += 4;
845 dp += 4;
846 }
847 for (int32_t xx = 0; xx < middleDwords; xx++) {
848 uint32_t tmp1 = (JBIG2_GETDWORD(sp) << shift1) |
849 (JBIG2_GETDWORD(sp + 4) >> shift2);
850 uint32_t tmp2 = JBIG2_GETDWORD(dp);
851 uint32_t tmp = 0;
852 switch (op) {
853 case JBIG2_COMPOSE_OR:
854 tmp = tmp1 | tmp2;
855 break;
856 case JBIG2_COMPOSE_AND:
857 tmp = tmp1 & tmp2;
858 break;
859 case JBIG2_COMPOSE_XOR:
860 tmp = tmp1 ^ tmp2;
861 break;
862 case JBIG2_COMPOSE_XNOR:
863 tmp = ~(tmp1 ^ tmp2);
864 break;
865 case JBIG2_COMPOSE_REPLACE:
866 tmp = tmp1;
867 break;
868 }
869 dp[0] = (uint8_t)(tmp >> 24);
870 dp[1] = (uint8_t)(tmp >> 16);
871 dp[2] = (uint8_t)(tmp >> 8);
872 dp[3] = (uint8_t)tmp;
873 sp += 4;
874 dp += 4;
875 }
876 if (d2 != 0) {
877 uint32_t tmp1 =
878 (JBIG2_GETDWORD(sp) << shift1) |
879 (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >>
880 shift2);
881 uint32_t tmp2 = JBIG2_GETDWORD(dp);
882 uint32_t tmp = 0;
883 switch (op) {
884 case JBIG2_COMPOSE_OR:
885 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
886 break;
887 case JBIG2_COMPOSE_AND:
888 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
889 break;
890 case JBIG2_COMPOSE_XOR:
891 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
892 break;
893 case JBIG2_COMPOSE_XNOR:
894 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
895 break;
896 case JBIG2_COMPOSE_REPLACE:
897 tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
898 break;
899 }
900 dp[0] = (uint8_t)(tmp >> 24);
901 dp[1] = (uint8_t)(tmp >> 16);
902 dp[2] = (uint8_t)(tmp >> 8);
903 dp[3] = (uint8_t)tmp;
904 }
905 lineSrc += m_nStride;
906 lineDst += pDst->m_nStride;
907 }
908 } else if (s1 == d1) {
909 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
910 for (int32_t yy = yd0; yy < yd1; yy++) {
911 uint8_t* sp = lineSrc;
912 uint8_t* dp = lineDst;
913 if (d1 != 0) {
914 uint32_t tmp1 = JBIG2_GETDWORD(sp);
915 uint32_t tmp2 = JBIG2_GETDWORD(dp);
916 uint32_t tmp = 0;
917 switch (op) {
918 case JBIG2_COMPOSE_OR:
919 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
920 break;
921 case JBIG2_COMPOSE_AND:
922 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
923 break;
924 case JBIG2_COMPOSE_XOR:
925 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
926 break;
927 case JBIG2_COMPOSE_XNOR:
928 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
929 break;
930 case JBIG2_COMPOSE_REPLACE:
931 tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
932 break;
933 }
934 dp[0] = (uint8_t)(tmp >> 24);
935 dp[1] = (uint8_t)(tmp >> 16);
936 dp[2] = (uint8_t)(tmp >> 8);
937 dp[3] = (uint8_t)tmp;
938 sp += 4;
939 dp += 4;
940 }
941 for (int32_t xx = 0; xx < middleDwords; xx++) {
942 uint32_t tmp1 = JBIG2_GETDWORD(sp);
943 uint32_t tmp2 = JBIG2_GETDWORD(dp);
944 uint32_t tmp = 0;
945 switch (op) {
946 case JBIG2_COMPOSE_OR:
947 tmp = tmp1 | tmp2;
948 break;
949 case JBIG2_COMPOSE_AND:
950 tmp = tmp1 & tmp2;
951 break;
952 case JBIG2_COMPOSE_XOR:
953 tmp = tmp1 ^ tmp2;
954 break;
955 case JBIG2_COMPOSE_XNOR:
956 tmp = ~(tmp1 ^ tmp2);
957 break;
958 case JBIG2_COMPOSE_REPLACE:
959 tmp = tmp1;
960 break;
961 }
962 dp[0] = (uint8_t)(tmp >> 24);
963 dp[1] = (uint8_t)(tmp >> 16);
964 dp[2] = (uint8_t)(tmp >> 8);
965 dp[3] = (uint8_t)tmp;
966 sp += 4;
967 dp += 4;
968 }
969 if (d2 != 0) {
970 uint32_t tmp1 = JBIG2_GETDWORD(sp);
971 uint32_t tmp2 = JBIG2_GETDWORD(dp);
972 uint32_t tmp = 0;
973 switch (op) {
974 case JBIG2_COMPOSE_OR:
975 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
976 break;
977 case JBIG2_COMPOSE_AND:
978 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
979 break;
980 case JBIG2_COMPOSE_XOR:
981 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
982 break;
983 case JBIG2_COMPOSE_XNOR:
984 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
985 break;
986 case JBIG2_COMPOSE_REPLACE:
987 tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
988 break;
989 }
990 dp[0] = (uint8_t)(tmp >> 24);
991 dp[1] = (uint8_t)(tmp >> 16);
992 dp[2] = (uint8_t)(tmp >> 8);
993 dp[3] = (uint8_t)tmp;
994 }
995 lineSrc += m_nStride;
996 lineDst += pDst->m_nStride;
997 }
998 } else {
999 uint32_t shift1 = d1 - s1;
1000 uint32_t shift2 = 32 - shift1;
1001 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
1002 for (int32_t yy = yd0; yy < yd1; yy++) {
1003 uint8_t* sp = lineSrc;
1004 uint8_t* dp = lineDst;
1005 if (d1 != 0) {
1006 uint32_t tmp1 = JBIG2_GETDWORD(sp) >> shift1;
1007 uint32_t tmp2 = JBIG2_GETDWORD(dp);
1008 uint32_t tmp = 0;
1009 switch (op) {
1010 case JBIG2_COMPOSE_OR:
1011 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
1012 break;
1013 case JBIG2_COMPOSE_AND:
1014 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
1015 break;
1016 case JBIG2_COMPOSE_XOR:
1017 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
1018 break;
1019 case JBIG2_COMPOSE_XNOR:
1020 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
1021 break;
1022 case JBIG2_COMPOSE_REPLACE:
1023 tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
1024 break;
1025 }
1026 dp[0] = (uint8_t)(tmp >> 24);
1027 dp[1] = (uint8_t)(tmp >> 16);
1028 dp[2] = (uint8_t)(tmp >> 8);
1029 dp[3] = (uint8_t)tmp;
1030 dp += 4;
1031 }
1032 for (int32_t xx = 0; xx < middleDwords; xx++) {
1033 uint32_t tmp1 = (JBIG2_GETDWORD(sp) << shift2) |
1034 ((JBIG2_GETDWORD(sp + 4)) >> shift1);
1035 uint32_t tmp2 = JBIG2_GETDWORD(dp);
1036 uint32_t tmp = 0;
1037 switch (op) {
1038 case JBIG2_COMPOSE_OR:
1039 tmp = tmp1 | tmp2;
1040 break;
1041 case JBIG2_COMPOSE_AND:
1042 tmp = tmp1 & tmp2;
1043 break;
1044 case JBIG2_COMPOSE_XOR:
1045 tmp = tmp1 ^ tmp2;
1046 break;
1047 case JBIG2_COMPOSE_XNOR:
1048 tmp = ~(tmp1 ^ tmp2);
1049 break;
1050 case JBIG2_COMPOSE_REPLACE:
1051 tmp = tmp1;
1052 break;
1053 }
1054 dp[0] = (uint8_t)(tmp >> 24);
1055 dp[1] = (uint8_t)(tmp >> 16);
1056 dp[2] = (uint8_t)(tmp >> 8);
1057 dp[3] = (uint8_t)tmp;
1058 sp += 4;
1059 dp += 4;
1060 }
1061 if (d2 != 0) {
1062 uint32_t tmp1 =
1063 (JBIG2_GETDWORD(sp) << shift2) |
1064 (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >>
1065 shift1);
1066 uint32_t tmp2 = JBIG2_GETDWORD(dp);
1067 uint32_t tmp = 0;
1068 switch (op) {
1069 case JBIG2_COMPOSE_OR:
1070 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
1071 break;
1072 case JBIG2_COMPOSE_AND:
1073 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
1074 break;
1075 case JBIG2_COMPOSE_XOR:
1076 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
1077 break;
1078 case JBIG2_COMPOSE_XNOR:
1079 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
1080 break;
1081 case JBIG2_COMPOSE_REPLACE:
1082 tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
1083 break;
1084 }
1085 dp[0] = (uint8_t)(tmp >> 24);
1086 dp[1] = (uint8_t)(tmp >> 16);
1087 dp[2] = (uint8_t)(tmp >> 8);
1088 dp[3] = (uint8_t)tmp;
1089 }
1090 lineSrc += m_nStride;
1091 lineDst += pDst->m_nStride;
1092 }
1093 }
1094 }
1095 return 1;
1096 }
1097