7#include "core/fxcodec/jbig2/JBig2_Image.h"
15#include "core/fxcrt/check.h"
16#include "core/fxcrt/compiler_specific.h"
17#include "core/fxcrt/fx_2d_size.h"
18#include "core/fxcrt/fx_coordinates.h"
19#include "core/fxcrt/fx_memcpy_wrappers.h"
20#include "core/fxcrt/fx_memory.h"
21#include "core/fxcrt/fx_safe_types.h"
23#define JBIG2_GETDWORD(buf)
24 ((static_cast<uint32_t>((buf)[0
]) << 24
) |
25 (static_cast<uint32_t>((buf)[1
]) << 16
) |
26 (static_cast<uint32_t>((buf)[2
]) << 8
) |
27 (static_cast<uint32_t>((buf)[3
]) << 0
))
29#define JBIG2_PUTDWORD(buf, val)
30 ((buf)[0
] = static_cast<uint8_t>((val) >> 24
),
31 (buf)[1
] = static_cast<uint8_t>((val) >> 16
),
32 (buf)[2
] = static_cast<uint8_t>((val) >> 8
),
33 (buf)[3
] = static_cast<uint8_t>((val) >> 0
))
37const int kMaxImagePixels = INT_MAX - 31;
38const int kMaxImageBytes = kMaxImagePixels / 8;
40int BitIndexToByte(
int index) {
44int BitIndexToAlignedByte(
int index) {
45 return index / 32 * 4;
51 if (w <= 0 || h <= 0 || w > kMaxImagePixels)
54 int32_t stride_pixels = FxAlignToBoundary<32>(w);
55 if (h > kMaxImagePixels / stride_pixels)
60 m_nStride = stride_pixels / 8;
61 m_pData.Reset(std::unique_ptr<uint8_t, FxFreeDeleter>(
62 FX_Alloc2D(uint8_t, m_nStride, m_nHeight)));
68 pdfium::span<uint8_t> pBuf) {
73 if (stride < 0 || stride > kMaxImageBytes || stride % 4 != 0)
76 int32_t stride_pixels = 8 * stride;
77 if (stride_pixels < w || h > kMaxImagePixels / stride_pixels)
83 m_pData.Reset(pBuf.data());
87 : m_nWidth(other.m_nWidth),
88 m_nHeight(other.m_nHeight),
89 m_nStride(other.m_nStride) {
91 m_pData.Reset(std::unique_ptr<uint8_t, FxFreeDeleter>(
92 FX_Alloc2D(uint8_t, m_nStride, m_nHeight)));
108 if (x < 0 || x >= m_nWidth)
115 int32_t m = BitIndexToByte(x);
124 if (x < 0 || x >= m_nWidth)
131 int32_t m = BitIndexToByte(x);
132 int32_t n = 1 << (7 - (x & 7));
163 FXSYS_memset(
data(), v ? 0xff : 0, Fx2DSizeOrDie(m_nStride, m_nHeight)));
171 ComposeToInternal(pDst, x, y, op, FX_RECT(0, 0, m_nWidth, m_nHeight));
179 return m_pData && ComposeToInternal(pDst, x, y, op, rtSrc);
186 return m_pData && pSrc->ComposeTo(
this, x, y, op);
194 return m_pData && pSrc->ComposeToWithRect(
this, x, y, rtSrc, op);
202 if (!pImage->data() || !m_pData)
205 if (x < 0 || x >= m_nWidth || y < 0 || y >= m_nHeight)
210 SubImageFast(x, y, w, h, pImage.get());
212 SubImageSlow(x, y, w, h, pImage.get());
222 int32_t m = BitIndexToByte(x);
223 int32_t bytes_to_copy =
std::min(pImage->m_nStride, m_nStride - m);
224 int32_t lines_to_copy =
std::min(pImage->m_nHeight, m_nHeight - y);
225 for (int32_t j = 0; j < lines_to_copy; j++) {
236 int32_t m = BitIndexToAlignedByte(x);
238 int32_t bytes_to_copy =
std::min(pImage->m_nStride, m_nStride - m);
239 int32_t lines_to_copy =
std::min(pImage->m_nHeight, m_nHeight - y);
241 for (int32_t j = 0; j < lines_to_copy; j++) {
244 const uint8_t* pSrc = pLineSrc + m;
245 const uint8_t* pSrcEnd = pLineSrc + m_nStride;
246 uint8_t* pDstEnd = pLineDst + bytes_to_copy;
247 for (uint8_t* pDst = pLineDst; pDst < pDstEnd; pSrc += 4, pDst += 4) {
249 if (pSrc + 4 < pSrcEnd) {
259 if (!m_pData || h <= m_nHeight || h > kMaxImageBytes / m_nStride)
263 const size_t current_size = Fx2DSizeOrDie(m_nHeight, m_nStride);
264 const size_t desired_size = Fx2DSizeOrDie(h, m_nStride);
266 if (m_pData.IsOwned()) {
267 m_pData.Reset(std::unique_ptr<uint8_t, FxFreeDeleter>(FX_Realloc(
268 uint8_t, m_pData.ReleaseAndClear().release(), desired_size)));
270 uint8_t* pExternalBuffer =
data();
271 m_pData.Reset(std::unique_ptr<uint8_t, FxFreeDeleter>(
272 FX_Alloc(uint8_t, desired_size)));
276 desired_size - current_size));
288 if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576)
294 int32_t xs0 = x < 0 ? -x : 0;
298 if (iChecked.IsValid() && sw > iChecked.ValueOrDie())
299 xs1 = iChecked.ValueOrDie();
303 int32_t ys0 = y < 0 ? -y : 0;
305 iChecked = pDst->m_nHeight;
307 if (iChecked.IsValid() && sh > iChecked.ValueOrDie())
308 ys1 = iChecked.ValueOrDie();
312 if (ys0 >= ys1 || xs0 >= xs1)
315 int32_t xd0 =
std::max(x, 0);
316 int32_t yd0 =
std::max(y, 0);
317 int32_t w = xs1 - xs0;
318 int32_t h = ys1 - ys0;
319 int32_t xd1 = xd0 + w;
320 int32_t yd1 = yd0 + h;
321 uint32_t d1 = xd0 & 31;
322 uint32_t d2 = xd1 & 31;
323 uint32_t s1 = xs0 & 31;
324 uint32_t maskL = 0xffffffff >> d1;
325 uint32_t maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32);
326 uint32_t maskM = maskL & maskR;
329 BitIndexToAlignedByte(xs0 + rtSrc
.left);
330 const uint8_t* lineSrcEnd =
data() + Fx2DSizeOrDie(m_nHeight, m_nStride);
331 int32_t lineLeft = m_nStride - BitIndexToAlignedByte(xs0);
333 if ((xd0 & ~31) == ((xd1 - 1) & ~31)) {
334 if ((xs0 & ~31) == ((xs1 - 1) & ~31)) {
336 uint32_t shift = s1 - d1;
337 for (int32_t yy = yd0; yy < yd1; yy++) {
338 if (lineSrc >= lineSrcEnd) {
346 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
349 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
352 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
355 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
358 tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
362 lineSrc += m_nStride;
363 lineDst += pDst->m_nStride;
366 uint32_t shift = d1 - s1;
367 for (int32_t yy = yd0; yy < yd1; yy++) {
368 if (lineSrc >= lineSrcEnd) {
376 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
379 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
382 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
385 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
388 tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
392 lineSrc += m_nStride;
393 lineDst += pDst->m_nStride;
397 uint32_t shift1 = s1 - d1;
398 uint32_t shift2 = 32 - shift1;
399 for (int32_t yy = yd0; yy < yd1; yy++) {
400 if (lineSrc >= lineSrcEnd)
408 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
411 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
414 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
417 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
420 tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
424 lineSrc += m_nStride;
425 lineDst += pDst->m_nStride;
430 uint32_t shift1 = s1 - d1;
431 uint32_t shift2 = 32 - shift1;
432 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
433 for (int32_t yy = yd0; yy < yd1; yy++) {
434 if (lineSrc >= lineSrcEnd) {
437 const uint8_t* sp = lineSrc;
438 uint8_t* dp = lineDst;
446 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
449 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
452 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
455 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
458 tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
465 for (int32_t xx = 0; xx < middleDwords; xx++) {
481 tmp = ~(tmp1 ^ tmp2);
500 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
503 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
506 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
509 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
512 tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
517 lineSrc += m_nStride;
518 lineDst += pDst->m_nStride;
520 }
else if (s1 == d1) {
521 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
522 for (int32_t yy = yd0; yy < yd1; yy++) {
523 if (lineSrc >= lineSrcEnd) {
526 const uint8_t* sp = lineSrc;
527 uint8_t* dp = lineDst;
534 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
537 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
540 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
543 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
546 tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
553 for (int32_t xx = 0; xx < middleDwords; xx++) {
568 tmp = ~(tmp1 ^ tmp2);
584 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
587 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
590 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
593 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
596 tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
601 lineSrc += m_nStride;
602 lineDst += pDst->m_nStride;
605 uint32_t shift1 = d1 - s1;
606 uint32_t shift2 = 32 - shift1;
607 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
608 for (int32_t yy = yd0; yy < yd1; yy++) {
609 if (lineSrc >= lineSrcEnd) {
612 const uint8_t* sp = lineSrc;
613 uint8_t* dp = lineDst;
620 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
623 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
626 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
629 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
632 tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
638 for (int32_t xx = 0; xx < middleDwords; xx++) {
654 tmp = ~(tmp1 ^ tmp2);
673 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
676 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
679 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
682 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
685 tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
690 lineSrc += m_nStride;
691 lineDst += pDst->m_nStride;
constexpr int32_t kJBig2MaxImageSize
#define JBIG2_PUTDWORD(buf, val)
#define JBIG2_GETDWORD(buf)
CJBig2_Image(int32_t w, int32_t h, int32_t stride, pdfium::span< uint8_t > pBuf)
bool ComposeFrom(int32_t x, int32_t y, CJBig2_Image *pSrc, JBig2ComposeOp op)
void SetPixel(int32_t x, int32_t y, int v)
std::unique_ptr< CJBig2_Image > SubImage(int32_t x, int32_t y, int32_t w, int32_t h)
CJBig2_Image(int32_t w, int32_t h)
uint8_t * GetLine(int32_t y) const
void CopyLine(int32_t hTo, int32_t hFrom)
CJBig2_Image(const CJBig2_Image &other)
bool ComposeToWithRect(CJBig2_Image *pDst, int32_t x, int32_t y, const FX_RECT &rtSrc, JBig2ComposeOp op)
static bool IsValidImageSize(int32_t w, int32_t h)
int GetPixel(int32_t x, int32_t y) const
bool ComposeTo(CJBig2_Image *pDst, int32_t x, int32_t y, JBig2ComposeOp op)
UNSAFE_BUFFER_USAGE uint8_t * GetLineUnsafe(int32_t y) const
void Expand(int32_t h, bool v)
bool ComposeFromWithRect(int32_t x, int32_t y, CJBig2_Image *pSrc, const FX_RECT &rtSrc, JBig2ComposeOp op)
UNSAFE_BUFFER_USAGE void * FXSYS_memset(void *ptr1, int val, size_t len)
UNSAFE_BUFFER_USAGE void * FXSYS_memcpy(void *ptr1, const void *ptr2, size_t len)
pdfium::CheckedNumeric< int32_t > FX_SAFE_INT32