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 "../../../include/fxcodec/fx_codec.h" 8#include "codec_int.h" 9CCodec_ModuleMgr::CCodec_ModuleMgr() 10{ 11 m_pBasicModule = new CCodec_BasicModule; 12 m_pFaxModule = new CCodec_FaxModule; 13 m_pJpegModule = new CCodec_JpegModule; 14 m_pJpxModule = new CCodec_JpxModule; 15 m_pJbig2Module = new CCodec_Jbig2Module; 16 m_pIccModule = new CCodec_IccModule; 17 m_pFlateModule = new CCodec_FlateModule; 18} 19CCodec_ModuleMgr::~CCodec_ModuleMgr() 20{ 21 delete m_pBasicModule; 22 delete m_pFaxModule; 23 delete m_pJpegModule; 24 delete m_pFlateModule; 25 delete m_pJpxModule; 26 delete m_pJbig2Module; 27 delete m_pIccModule; 28} 29void CCodec_ModuleMgr::InitJbig2Decoder() 30{ 31} 32void CCodec_ModuleMgr::InitJpxDecoder() 33{ 34} 35void CCodec_ModuleMgr::InitIccDecoder() 36{ 37} 38CCodec_ScanlineDecoder::CCodec_ScanlineDecoder() 39{ 40 m_NextLine = -1; 41 m_pDataCache = NULL; 42 m_pLastScanline = NULL; 43} 44CCodec_ScanlineDecoder::~CCodec_ScanlineDecoder() 45{ 46 if (m_pDataCache) { 47 FX_Free(m_pDataCache); 48 } 49} 50FX_LPBYTE CCodec_ScanlineDecoder::GetScanline(int line) 51{ 52 if (m_pDataCache && line < m_pDataCache->m_nCachedLines) { 53 return &m_pDataCache->m_Data + line * m_Pitch; 54 } 55 if (m_NextLine == line + 1) { 56 return m_pLastScanline; 57 } 58 if (m_NextLine < 0 || m_NextLine > line) { 59 if (!v_Rewind()) { 60 return NULL; 61 } 62 m_NextLine = 0; 63 } 64 while (m_NextLine < line) { 65 ReadNextLine(); 66 m_NextLine ++; 67 } 68 m_pLastScanline = ReadNextLine(); 69 m_NextLine ++; 70 return m_pLastScanline; 71} 72FX_BOOL CCodec_ScanlineDecoder::SkipToScanline(int line, IFX_Pause* pPause) 73{ 74 if (m_pDataCache && line < m_pDataCache->m_nCachedLines) { 75 return FALSE; 76 } 77 if (m_NextLine == line || m_NextLine == line + 1) { 78 return FALSE; 79 } 80 if (m_NextLine < 0 || m_NextLine > line) { 81 v_Rewind(); 82 m_NextLine = 0; 83 } 84 m_pLastScanline = NULL; 85 while (m_NextLine < line) { 86 m_pLastScanline = ReadNextLine(); 87 m_NextLine ++; 88 if (pPause && pPause->NeedToPauseNow()) { 89 return TRUE; 90 } 91 } 92 return FALSE; 93} 94FX_LPBYTE CCodec_ScanlineDecoder::ReadNextLine() 95{ 96 FX_LPBYTE pLine = v_GetNextLine(); 97 if (pLine == NULL) { 98 return NULL; 99 } 100 if (m_pDataCache && m_NextLine == m_pDataCache->m_nCachedLines) { 101 FXSYS_memcpy32(&m_pDataCache->m_Data + m_NextLine * m_Pitch, pLine, m_Pitch); 102 m_pDataCache->m_nCachedLines ++; 103 } 104 return pLine; 105} 106void CCodec_ScanlineDecoder::DownScale(int dest_width, int dest_height) 107{ 108 if (dest_width < 0) { 109 dest_width = -dest_width; 110 } 111 if (dest_height < 0) { 112 dest_height = -dest_height; 113 } 114 v_DownScale(dest_width, dest_height); 115 if (m_pDataCache) { 116 if (m_pDataCache->m_Height == m_OutputHeight && m_pDataCache->m_Width == m_OutputWidth) { 117 return; 118 } 119 FX_Free(m_pDataCache); 120 m_pDataCache = NULL; 121 } 122 m_pDataCache = (CCodec_ImageDataCache*)FX_TryAlloc(FX_BYTE, sizeof(CCodec_ImageDataCache) + m_Pitch * m_OutputHeight); 123 if (m_pDataCache == NULL) { 124 return; 125 } 126 m_pDataCache->m_Height = m_OutputHeight; 127 m_pDataCache->m_Width = m_OutputWidth; 128 m_pDataCache->m_nCachedLines = 0; 129} 130FX_BOOL CCodec_BasicModule::RunLengthEncode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, 131 FX_DWORD& dest_size) 132{ 133 return FALSE; 134} 135extern "C" double FXstrtod(const char* nptr, char** endptr) 136{ 137 double ret = 0.0; 138 const char* ptr = nptr; 139 const char* exp_ptr = NULL; 140 int e_number = 0, 141 e_signal = 0, 142 e_point = 0, 143 is_negative = 0; 144 int exp_ret = 0, exp_sig = 1, 145 fra_ret = 0, fra_count = 0, fra_base = 1; 146 if(nptr == NULL) { 147 return 0.0; 148 } 149 for (;; ptr++) { 150 if(!e_number && !e_point && (*ptr == '\t' || *ptr == ' ')) { 151 continue; 152 } 153 if(*ptr >= '0' && *ptr <= '9') { 154 if(!e_number) { 155 e_number = 1; 156 } 157 if(!e_point) { 158 ret *= 10; 159 ret += (*ptr - '0'); 160 } else { 161 fra_count++; 162 fra_ret *= 10; 163 fra_ret += (*ptr - '0'); 164 } 165 continue; 166 } 167 if(!e_point && *ptr == '.') { 168 e_point = 1; 169 continue; 170 } 171 if(!e_number && !e_point && !e_signal) { 172 switch(*ptr) { 173 case '-': 174 is_negative = 1; 175 case '+': 176 e_signal = 1; 177 continue; 178 } 179 } 180 if(e_number && (*ptr == 'e' || *ptr == 'E')) { 181#define EXPONENT_DETECT(ptr) \ 182 for(;;ptr++){ \ 183 if(*ptr < '0' || *ptr > '9'){ \ 184 if(endptr) *endptr = (char*)ptr; \ 185 break; \ 186 }else{ \ 187 exp_ret *= 10; \ 188 exp_ret += (*ptr - '0'); \ 189 continue; \ 190 } \ 191 } 192 exp_ptr = ptr++; 193 if(*ptr == '+' || *ptr == '-') { 194 exp_sig = (*ptr++ == '+') ? 1 : -1; 195 if(*ptr < '0' || *ptr > '9') { 196 if(endptr) { 197 *endptr = (char*)exp_ptr; 198 } 199 break; 200 } 201 EXPONENT_DETECT(ptr); 202 } else if(*ptr >= '0' && *ptr <= '9') { 203 EXPONENT_DETECT(ptr); 204 } else { 205 if(endptr) { 206 *endptr = (char*)exp_ptr; 207 } 208 break; 209 } 210#undef EXPONENT_DETECT 211 break; 212 } 213 if(ptr != nptr && !e_number) { 214 if(endptr) { 215 *endptr = (char*)nptr; 216 } 217 break; 218 } 219 if(endptr) { 220 *endptr = (char*)ptr; 221 } 222 break; 223 } 224 while(fra_count--) { 225 fra_base *= 10; 226 } 227 ret += (double)fra_ret / (double)fra_base; 228 if(exp_sig == 1) { 229 while(exp_ret--) { 230 ret *= 10.0; 231 } 232 } else { 233 while(exp_ret--) { 234 ret /= 10.0; 235 } 236 } 237 return is_negative ? -ret : ret; 238} 239FX_BOOL CCodec_BasicModule::A85Encode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, 240 FX_DWORD& dest_size) 241{ 242 return FALSE; 243} 244CCodec_ModuleMgr* CCodec_ModuleMgr::Create() 245{ 246 return new CCodec_ModuleMgr; 247} 248void CCodec_ModuleMgr::Destroy() 249{ 250 delete this; 251} 252class CCodec_RLScanlineDecoder : public CCodec_ScanlineDecoder 253{ 254public: 255 CCodec_RLScanlineDecoder(); 256 virtual ~CCodec_RLScanlineDecoder(); 257 FX_BOOL Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, int nComps, int bpc); 258 virtual void v_DownScale(int dest_width, int dest_height) {} 259 virtual FX_BOOL v_Rewind(); 260 virtual FX_LPBYTE v_GetNextLine(); 261 virtual FX_DWORD GetSrcOffset() 262 { 263 return m_SrcOffset; 264 } 265protected: 266 FX_BOOL CheckDestSize(); 267 void GetNextOperator(); 268 void UpdateOperator(FX_BYTE used_bytes); 269 270 FX_LPBYTE m_pScanline; 271 FX_LPCBYTE m_pSrcBuf; 272 FX_DWORD m_SrcSize; 273 FX_DWORD m_dwLineBytes; 274 FX_DWORD m_SrcOffset; 275 FX_BOOL m_bEOD; 276 FX_BYTE m_Operator; 277}; 278CCodec_RLScanlineDecoder::CCodec_RLScanlineDecoder() 279 : m_pScanline(NULL) 280 , m_pSrcBuf(NULL) 281 , m_SrcSize(0) 282 , m_dwLineBytes(0) 283 , m_SrcOffset(0) 284 , m_bEOD(FALSE) 285 , m_Operator(0) 286{ 287} 288CCodec_RLScanlineDecoder::~CCodec_RLScanlineDecoder() 289{ 290 if (m_pScanline) { 291 FX_Free(m_pScanline); 292 } 293} 294FX_BOOL CCodec_RLScanlineDecoder::CheckDestSize() 295{ 296 FX_DWORD i = 0; 297 FX_DWORD old_size = 0; 298 FX_DWORD dest_size = 0; 299 while (i < m_SrcSize) { 300 if (m_pSrcBuf[i] < 128) { 301 old_size = dest_size; 302 dest_size += m_pSrcBuf[i] + 1; 303 if (dest_size < old_size) { 304 return FALSE; 305 } 306 i += m_pSrcBuf[i] + 2; 307 } else if (m_pSrcBuf[i] > 128) { 308 old_size = dest_size; 309 dest_size += 257 - m_pSrcBuf[i]; 310 if (dest_size < old_size) { 311 return FALSE; 312 } 313 i += 2; 314 } else { 315 break; 316 } 317 } 318 if (((FX_DWORD)m_OrigWidth * m_nComps * m_bpc * m_OrigHeight + 7) / 8 > dest_size) { 319 return FALSE; 320 } 321 return TRUE; 322} 323FX_BOOL CCodec_RLScanlineDecoder::Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, int nComps, int bpc) 324{ 325 m_pSrcBuf = src_buf; 326 m_SrcSize = src_size; 327 m_OutputWidth = m_OrigWidth = width; 328 m_OutputHeight = m_OrigHeight = height; 329 m_nComps = nComps; 330 m_bpc = bpc; 331 m_bColorTransformed = FALSE; 332 m_DownScale = 1; 333 m_Pitch = (width * nComps * bpc + 31) / 32 * 4; 334 m_dwLineBytes = (width * nComps * bpc + 7) / 8; 335 m_pScanline = FX_Alloc(FX_BYTE, m_Pitch); 336 return CheckDestSize(); 337} 338FX_BOOL CCodec_RLScanlineDecoder::v_Rewind() 339{ 340 FXSYS_memset32(m_pScanline, 0, m_Pitch); 341 m_SrcOffset = 0; 342 m_bEOD = FALSE; 343 m_Operator = 0; 344 return TRUE; 345} 346FX_LPBYTE CCodec_RLScanlineDecoder::v_GetNextLine() 347{ 348 if (m_SrcOffset == 0) { 349 GetNextOperator(); 350 } else { 351 if (m_bEOD) { 352 return NULL; 353 } 354 } 355 FXSYS_memset32(m_pScanline, 0, m_Pitch); 356 FX_DWORD col_pos = 0; 357 FX_BOOL eol = FALSE; 358 while (m_SrcOffset < m_SrcSize && !eol) { 359 if (m_Operator < 128) { 360 FX_DWORD copy_len = m_Operator + 1; 361 if (col_pos + copy_len >= m_dwLineBytes) { 362 copy_len = m_dwLineBytes - col_pos; 363 eol = TRUE; 364 } 365 if (copy_len >= m_SrcSize - m_SrcOffset) { 366 copy_len = m_SrcSize - m_SrcOffset; 367 m_bEOD = TRUE; 368 } 369 FXSYS_memcpy32(m_pScanline + col_pos, m_pSrcBuf + m_SrcOffset, copy_len); 370 col_pos += copy_len; 371 UpdateOperator((FX_BYTE)copy_len); 372 } else if (m_Operator > 128) { 373 int fill = 0; 374 if (m_SrcOffset - 1 < m_SrcSize - 1) { 375 fill = m_pSrcBuf[m_SrcOffset]; 376 } 377 FX_DWORD duplicate_len = 257 - m_Operator; 378 if (col_pos + duplicate_len >= m_dwLineBytes) { 379 duplicate_len = m_dwLineBytes - col_pos; 380 eol = TRUE; 381 } 382 FXSYS_memset8(m_pScanline + col_pos, fill, duplicate_len); 383 col_pos += duplicate_len; 384 UpdateOperator((FX_BYTE)duplicate_len); 385 } else { 386 m_bEOD = TRUE; 387 break; 388 } 389 } 390 return m_pScanline; 391} 392void CCodec_RLScanlineDecoder::GetNextOperator() 393{ 394 if (m_SrcOffset >= m_SrcSize) { 395 m_Operator = 128; 396 return; 397 } 398 m_Operator = m_pSrcBuf[m_SrcOffset]; 399 m_SrcOffset ++; 400} 401void CCodec_RLScanlineDecoder::UpdateOperator(FX_BYTE used_bytes) 402{ 403 if (used_bytes == 0) { 404 return; 405 } 406 if (m_Operator < 128) { 407 FXSYS_assert((FX_DWORD)m_Operator + 1 >= used_bytes); 408 if (used_bytes == m_Operator + 1) { 409 m_SrcOffset += used_bytes; 410 GetNextOperator(); 411 return; 412 } 413 m_Operator -= used_bytes; 414 m_SrcOffset += used_bytes; 415 if (m_SrcOffset >= m_SrcSize) { 416 m_Operator = 128; 417 } 418 return; 419 } 420 FX_BYTE count = 257 - m_Operator; 421 FXSYS_assert((FX_DWORD)count >= used_bytes); 422 if (used_bytes == count) { 423 m_SrcOffset ++; 424 GetNextOperator(); 425 return; 426 } 427 count -= used_bytes; 428 m_Operator = 257 - count; 429} 430ICodec_ScanlineDecoder* CCodec_BasicModule::CreateRunLengthDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, 431 int nComps, int bpc) 432{ 433 CCodec_RLScanlineDecoder* pRLScanlineDecoder = new CCodec_RLScanlineDecoder; 434 if (!pRLScanlineDecoder->Create(src_buf, src_size, width, height, nComps, bpc)) { 435 delete pRLScanlineDecoder; 436 return NULL; 437 } 438 return pRLScanlineDecoder; 439} 440