diff --git a/DesktopEditor/graphics/aggplustypes.h b/DesktopEditor/graphics/aggplustypes.h index 74b6f83e09..c6a231dc08 100644 --- a/DesktopEditor/graphics/aggplustypes.h +++ b/DesktopEditor/graphics/aggplustypes.h @@ -212,6 +212,8 @@ public: void Offset(const PointF_T& point) { Offset(point.X, point.Y); } void Offset(T dx, T dy) { X += dx; Y += dy; } + inline bool IsPositive() { return X >= 0 && Y >= 0 && Width > 0 && Height > 0; } + public: T X, Y, Width, Height; }; diff --git a/DesktopEditor/graphics/pro/raster.pri b/DesktopEditor/graphics/pro/raster.pri index 28d4b2d2d8..665f3a71d2 100644 --- a/DesktopEditor/graphics/pro/raster.pri +++ b/DesktopEditor/graphics/pro/raster.pri @@ -282,8 +282,7 @@ SOURCES += \ $$LIB_GRAPHICS_PRI_PATH/raster/JBig2/source/JBig2File.cpp SOURCES += \ - $$LIB_GRAPHICS_PRI_PATH/raster/PICT/PICFile.cpp \ - $$LIB_GRAPHICS_PRI_PATH/raster/PICT/pic.cpp + $$LIB_GRAPHICS_PRI_PATH/raster/PICT/PICFile.cpp SOURCES += \ $$LIB_GRAPHICS_PRI_PATH/cximage/jasper/base/jas_cm.c \ diff --git a/DesktopEditor/raster/BgraFrame.cpp b/DesktopEditor/raster/BgraFrame.cpp index d39f05fddd..e1229b708f 100644 --- a/DesktopEditor/raster/BgraFrame.cpp +++ b/DesktopEditor/raster/BgraFrame.cpp @@ -444,11 +444,11 @@ bool CBgraFrame::OpenFile(const std::wstring& strFileName, unsigned int nFileTyp #endif #if CXIMAGE_SUPPORT_PIC - if (CXIMAGE_FORMAR_PIC == m_nFileType) - { - PICT::CPictFile PIC; - return PIC.Open(this, strFileName, !m_bIsRGBA); - } + if (CXIMAGE_FORMAR_PIC == m_nFileType) + { + CPictFile pict_file; + return pict_file.Open(this, strFileName); + } #endif NSFile::CFileBinary oFile; @@ -529,8 +529,8 @@ bool CBgraFrame::Decode(BYTE* pBuffer, int nSize, unsigned int nFileType) #if CXIMAGE_SUPPORT_PIC if (CXIMAGE_FORMAR_PIC == m_nFileType) { - PICT::CPictFile PIC; - return PIC.Open(this, pBuffer, nSize, !m_bIsRGBA); + CPictFile pict_file; + return pict_file.Open(this, pBuffer, nSize); } #endif diff --git a/DesktopEditor/raster/PICT/PICFile.cpp b/DesktopEditor/raster/PICT/PICFile.cpp index 12b6ec2b7a..e372298981 100644 --- a/DesktopEditor/raster/PICT/PICFile.cpp +++ b/DesktopEditor/raster/PICT/PICFile.cpp @@ -30,109 +30,1659 @@ * */ #include "PICFile.h" -#include "pic.h" + #include "../../common/File.h" -namespace PICT { - -bool ImageToFrame(ImagePICT* pImage, CBgraFrame* pFrame, bool isRGBA) +CPictFile::CPictFile() { - int nWidth = pImage->m_nWidth; - int nHeight = pImage->m_nHeight; - int BufferSize = 4 * nWidth * nHeight; - - if (BufferSize < 1) - return false; - - pFrame->put_Height(nHeight); - pFrame->put_Width(nWidth); - pFrame->put_Stride(4 * nWidth); - - BYTE* pData = new BYTE[BufferSize]; - - if (!pData) - return false; - - pFrame->put_Data(pData); - - unsigned char* pBufferPtr = (unsigned char*)pData; - - unsigned int indR = isRGBA ? 2 : 0; - unsigned int indG = 1; - unsigned int indB = isRGBA ? 0 : 2; - - for (size_t i = 0; i < pImage->m_nHeight; i++) - { - unsigned char* q = pImage->ppixels + pImage->number_channels * (i * pImage->m_nWidth); - for (size_t j = 0; j < pImage->m_nWidth; j++) - { - pBufferPtr[indR] = * q; - pBufferPtr[indG] = * (q + 1); - pBufferPtr[indB] = * (q + 2); - pBufferPtr[3] = *(q + 3); - q += 4; - pBufferPtr += 4; - } - } - - return true; + m_pRenderer = NSGraphics::Create(); + m_pFontManager = NSFonts::NSFontManager::Create(); + m_pRenderer->SetFontManager(m_pFontManager); } -//////////////////////////////////////////////////////////////////////////////////////// - -bool CPictFile::Open(CBgraFrame *pFrame, const std::wstring &strFileName, bool isRGBA) +CPictFile::~CPictFile() { - NSFile::CFileBinary oFile; - if (!oFile.OpenFile(strFileName)) - return false; - - ImagePICT* pImage = new ImagePICT; - AquireImage(pImage); - - bool status = false; - if (DecodePICT(oFile.GetFileNative(), pImage)) - { - status = ImageToFrame(pImage, pFrame, isRGBA); - } - - DestroyImage(pImage); - oFile.CloseFile(); - - return status; + RELEASEINTERFACE(m_pFontManager); + RELEASEINTERFACE(m_pRenderer); } -bool CPictFile::Open(CBgraFrame *pFrame, BYTE *pBuffer, int nSize, bool isRGBA) +bool CPictFile::Open(CBgraFrame* frame, const std::wstring& fileName) { - NSFile::CFileBinary oFile; - std::wstring sTmpFile = NSFile::CFileBinary::CreateTempFileWithUniqueName(NSFile::CFileBinary::GetTempPath(), L"pct"); + NSFile::CFileBinary file; + if (!file.OpenFile(fileName)) + return false; - if (sTmpFile.empty()) - return false; + m_pFile = file.GetFileNative(); + auto status = Decode(); + file.CloseFile(); - if (!oFile.CreateFile(sTmpFile)) - return false; + BYTE* data = new BYTE[4 * m_oImgData.m_nWidth * m_oImgData.m_nHeight]; + frame->put_Data(data); + frame->put_Height(m_oImgData.m_nHeight); + frame->put_Width(m_oImgData.m_nWidth); + frame->put_Stride(4 * m_oImgData.m_nWidth); - ImagePICT* pImage = new ImagePICT; - AquireImage(pImage); + BYTE* buffer = data; - oFile.WriteFile(pBuffer, nSize); - oFile.CloseFile(); + for (size_t i = 0; i < m_oImgData.m_nHeight; i++) + { + BYTE* q = m_oImgData.m_pPixelData + 4 * i * m_oImgData.m_nWidth; + for (size_t j = 0; j < m_oImgData.m_nWidth; j++) + { + buffer[2] = * q; + buffer[1] = * (q + 1); + buffer[0] = * (q + 2); + buffer[3] = *(q + 3); + q += 4; + buffer += 4; + } + } - oFile.OpenFile(sTmpFile); - - bool status = false; - if (DecodePICT(oFile.GetFileNative(), pImage)) - { - status = ImageToFrame(pImage, pFrame, isRGBA); - } - - DestroyImage(pImage); - oFile.CloseFile(); - - if (NSFile::CFileBinary::Exists(sTmpFile)) - NSFile::CFileBinary::Remove(sTmpFile); - - return status; + return status; } + +bool CPictFile::Open(CBgraFrame* frame, BYTE* buffer, const size_t& size) +{ + NSFile::CFileBinary file; + auto tmp_file = NSFile::CFileBinary::CreateTempFileWithUniqueName(NSFile::CFileBinary::GetTempPath(), L"pct"); + + if (tmp_file.empty()) + return false; + + if (!file.CreateFile(tmp_file)) + return false; + + file.WriteFile(buffer, size); + file.CloseFile(); + + return Open(frame, tmp_file); +} + +bool CPictFile::Decode() +{ + if (m_pFile == nullptr) + return 0; + + if (!DecodeHeader()) + return false; + + if (feof(m_pFile) != 0) + return false; + + return DecodeData(); +} + +bool CPictFile::DecodeHeader() +{ + unsigned char header[4]; + + Aggplus::Rect rect; + + Read(4, header); + + if (!((header[0] == 0x50) && (header[1] == 0x49) && (header[2] == 0x43) && (header[3] == 0x54 ))) + { + rect.Y = (short) ((header[2] << 8) | header[3]); + rect.X = ReadShortValue(); + rect.Height = ReadShortValue() - rect.Y; + rect.Width = ReadShortValue() - rect.X; + + if (!rect.IsPositive()) + return false; + + m_oImgData.m_nWidth = rect.Width; + m_oImgData.m_nHeight = rect.Height; + + fseek(m_pFile, 1, SEEK_CUR); + if (fgetc(m_pFile) == 0x11) + { + if (fgetc(m_pFile) == 2) + { + if (fgetc(m_pFile) != 0xff) + return false; + m_nVersion = 2; + } + else + m_nVersion = 1; + + return true; + } + + fseek(m_pFile, 512, SEEK_SET); + fseek(m_pFile, 2, SEEK_CUR); + if (!ReadRectangle(&rect)) + return false; + + if (!rect.IsPositive()) + return false; + + m_oImgData.m_nWidth = rect.Width; + m_oImgData.m_nHeight = rect.Height; + + fseek(m_pFile, 1, SEEK_CUR); + if (fgetc(m_pFile) == 0x11) + { + int version = fgetc(m_pFile); + if (version == 2) + { + if (fgetc(m_pFile) != 0xff) + return false; + + m_nVersion = 2; + } + else if (version == 1) + m_nVersion = 1; + else + return false; + + return true; + } + } + + return false; +} + +bool CPictFile::DecodeData() +{ + int flag = 0; + + bool is_pix_data = false; + + for (int code = 0; feof(m_pFile) == 0; ) + { + if (m_nVersion == 1 || ftell(m_pFile) % 2 != 0) + code = fgetc(m_pFile); + if (m_nVersion == 2) + code = ReadSignedShortValue(); + code &= 0xffff; + if (code < 0) + break; + if (code == 0) + continue; + if (code <= 0xa1) + { + switch(code) + { + case 0x01: + { + size_t length = ReadShortValue(); + if (length > GetFileSize()) + return false; + + if (length != 0x000a) + { + for (size_t i = 0; i < length - 2; i++) + if (fgetc(m_pFile) == EOF) + break; + break; + } + + Aggplus::Rect frame; + if (ReadRectangle(&frame) == 0) + return false; + if (((frame.GetLeft() & 0x8000) != 0) || ((frame.GetTop() & 0x8000) != 0)) + break; + m_oImgData.m_nHeight = frame.Height; + m_oImgData.m_nWidth = frame.Width; + break; + } + case 0x11: + { + fseek(m_pFile, 1, SEEK_CUR); + break; + } + case 0x03: + case 0x05: + case 0x08: + case 0x15: + case 0x16: + case 0xa0: + { + fseek(m_pFile, 2, SEEK_CUR); + break; + } + case 0x1d: + case 0x1f: + { + fseek(m_pFile, 3, SEEK_CUR); + break; + } + case 0x06: + case 0x0b: + case 0x0c: + case 0x0f: + case 0x6d: + case 0x6e: + case 0x6f: + { + fseek(m_pFile, 4, SEEK_CUR); + break; + } + case 0x02: + case 0x09: + case 0x0a: + case 0x10: + case 0x35: + case 0x36: + case 0x37: + case 0x45: + case 0x46: + case 0x47: + case 0x55: + case 0x56: + case 0x57: + { + fseek(m_pFile, 8, SEEK_CUR); + break; + } + case 0x2d: + { + fseek(m_pFile, 10, SEEK_CUR); + break; + } + case 0x65: + case 0x66: + case 0x67: + { + fseek(m_pFile, 12, SEEK_CUR); + break; + } + case 0xa1: + { + fseek(m_pFile, 2, SEEK_CUR); + size_t length = ReadShortValue(); + if (length > GetFileSize()) + return false; + + fseek(m_pFile, length, SEEK_CUR); + break; + } + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x2e: + case 0x2f: + case 0x75: + case 0x76: + case 0x77: + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x9c: + case 0x9d: + case 0x9e: + case 0x9f: + { + size_t length = ReadShortValue(); + if (length > GetFileSize()) + return false; + + fseek(m_pFile, length - 2, SEEK_CUR); + break; + } + case 0x85: + case 0x86: + case 0x87: + { + size_t length = ReadShortValue(); + if (length > GetFileSize()) + return false; + + fseek(m_pFile, length - 4, SEEK_CUR); + break; + } + case 0x04: + { + char c = fgetc(m_pFile); + if ((c & 0x01) != 0) + m_nFontStyle |= 0x01; + if ((c & 0x02) != 0) + m_nFontStyle |= 0x02; + if ((c & 0x04) != 0) + m_nFontStyle |= 0x7c >> 2; + if ((c & 0x08) != 0) + m_nFontStyle |= 0x0180 >> 7; + break; + } + case 0x07: + { + m_nPenHeight = ReadShortValue(); + m_nPenWidth = ReadShortValue(); + break; + } + case 0x0d: + { + m_nFontSize = ReadShortValue(); + break; + } + case 0x0e: + { + long color = ReadLongValue(); + + switch(color) + { + case 33: m_pRenderer->put_BrushColor1(0x000000); break; + case 30: m_pRenderer->put_BrushColor1(0xFFFFFF); break; + case 205: m_pRenderer->put_BrushColor1(0xFF8080); break; //lightred + case 341: m_pRenderer->put_BrushColor1(0x90EE90); break; //lightgreen + case 409: m_pRenderer->put_BrushColor1(0xADD8E6); break; //lightblue + case 273: m_pRenderer->put_BrushColor1(0xE0FFFF); break; //lightcyan + case 137: m_pRenderer->put_BrushColor1(0xFF80FF); break; //lightmagenta + case 69: m_pRenderer->put_BrushColor1(0xFFFF00); break; //yellow + default: m_pRenderer->put_BrushColor1(0xD3D3D3); break; //lightgray + } + break; + } + case 0x12: + case 0x13: + case 0x14: + { + short pattern = ReadShortValue(); + for (size_t i = 0; i < 8; i++) + if (fgetc(m_pFile) == EOF) + break; + if (pattern == 2) + { + for (size_t i = 0; i < 5; i++) + if (fgetc(m_pFile) == EOF) + break; + break; + } + if (pattern != 1) + return false; + + size_t length = ReadShortValue(); + if (length > GetFileSize()) + return false; + + Aggplus::Rect frame; + if (ReadRectangle(&frame) == 0) + return false; + + fseek(m_pFile, 18, SEEK_CUR); + + short bits_per_pixel = ReadShortValue(); + short component_count = ReadShortValue(); + short component_size = ReadShortValue(); + + fseek(m_pFile, 12, SEEK_CUR); + + if (feof(m_pFile) != 0 || bits_per_pixel <= 0 || + bits_per_pixel > 32 || component_count <= 0 || + component_count > 4 || component_size <= 0) + return false; + + fseek(m_pFile, 4, SEEK_CUR); + flag = ReadShortValue(); + length = ReadShortValue(); + + if (length > GetFileSize()) + return false; + + for (size_t i = 0; i < length; i++) + fseek(m_pFile, 4, SEEK_CUR); + + size_t width = frame.Width; + size_t height = frame.Height; + + if (bits_per_pixel <= 8) + length &= 0x7fff; + + if (bits_per_pixel == 16) + width <<= 1; + + if (length == 0) + length = width; + + if (length < 8) + { + for (size_t i = 0; i < (length * height); i++) + if (fgetc(m_pFile) == EOF) + break; + } + else + { + for (size_t i = 0; i < height; i++) + { + size_t scanline_length; + + if (feof(m_pFile) != 0) + break; + + if (length > 200) + scanline_length = ReadShortValue(); + else + scanline_length = fgetc(m_pFile); + + if (scanline_length > GetFileSize()) + return false; + + for (size_t j = 0; j < scanline_length; j++) + if (fgetc(m_pFile) == EOF) + break; + } + } + break; + } + case 0x1a: + { + BYTE r = ReadShortValue() >> 8; + BYTE g = ReadShortValue() >> 8; + BYTE b = ReadShortValue() >> 8; + long c = r << 16 | g << 8 | b; + m_pRenderer->put_BrushColor1(c); + break; + } + case 0x1b: + { + fseek(m_pFile, 6, SEEK_CUR); + break; + } + case 0x20: + { + short y1 = ReadShortValue(); + short x1 = ReadShortValue(); + short y2 = ReadShortValue(); + short x2 = ReadShortValue(); + + m_oPenPoint = Aggplus::Point(x2, y2); + + if (m_nPenHeight == 0 && m_nPenWidth == 0) + break; + + DrawLine(Aggplus::Point(x1, y1), Aggplus::Point(x2, y2)); + break; + } + case 0x21: + { + short y1 = ReadShortValue(); + short x1 = ReadShortValue(); + + if (feof(m_pFile)) + break; + + if (m_nPenHeight == 0 && m_nPenWidth == 0) + break; + + DrawLine(Aggplus::Point(x1, y1), m_oPenPoint); + break; + } + case 0x22: + { + short y1 = ReadShortValue(); + short x1 = ReadShortValue(); + short y2 = static_cast(y1 + fgetc(m_pFile)); + short x2 = static_cast(x1 + fgetc(m_pFile)); + + if (m_nPenHeight == 0 && m_nPenWidth == 0) + break; + + DrawLine(Aggplus::Point(x1, y1), Aggplus::Point(x2, y2)); + break; + } + case 0x23: + { + short y2 = static_cast(m_oPenPoint.Y + fgetc(m_pFile)); + short x2 = static_cast(m_oPenPoint.X + fgetc(m_pFile)); + + if (m_nPenHeight == 0 && m_nPenWidth == 0) + break; + + DrawLine(m_oPenPoint, Aggplus::Point(x2, y2)); + break; + } + case 0x28: + { + short y = ReadShortValue(); + short x = ReadShortValue(); + + m_oTextPoint = Aggplus::Point(x, y); + ReadAndDrawText(x, y); + break; + } + case 0x29: + { + unsigned char h = static_cast(fgetc(m_pFile)); + ReadAndDrawText(m_oTextPoint.X + h, m_oTextPoint.Y); + break; + } + case 0x2a: + { + unsigned char v = static_cast(fgetc(m_pFile)); + ReadAndDrawText(m_oTextPoint.X, m_oTextPoint.Y + v); + break; + } + case 0x2b: + { + unsigned char h = static_cast(fgetc(m_pFile)); + unsigned char v = static_cast(fgetc(m_pFile)); + ReadAndDrawText(m_oTextPoint.X + h, m_oTextPoint.Y + v); + break; + } + case 0x2c: + { + fseek(m_pFile, 4, SEEK_CUR); + char byte_len = fgetc(m_pFile); + unsigned short len = static_cast(byte_len) & 0x00ff; + char f_name[256]; + Read(len, f_name); + f_name[len] = 0; + m_wsFontName = std::wstring(len, L'\0'); + std::mbstowcs(&m_wsFontName[0], f_name, len); + break; + } + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + { + if (!ReadRectangle(&m_oLastRect)) + return false; + + DrawRect(code == 0x30); + break; + } + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + case 0x3c: + { + DrawRect(code == 0x38); + break; + } + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + { + if (!ReadRectangle(&m_oLastRoundRect)) + return false; + + DrawRoundRect(code == 0x40); + break; + } + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + case 0x4c: + { + DrawRoundRect(code == 0x48); + break; + } + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + { + if (!ReadRectangle(&m_oLastOval)) + return false; + + DrawOval(code == 0x50); + break; + } + case 0x58: + case 0x59: + case 0x5a: + case 0x5b: + case 0x5c: + { + DrawOval(code == 0x58); + break; + } + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + { + if (!ReadRectangle(&m_oLastArc)) + return false; + + DrawArc(); + break; + } + case 0x68: + case 0x69: + case 0x6a: + case 0x6b: + case 0x6c: + { + DrawArc(); + break; + } + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + { + ReadPolygon(); + DrawPolygon(code == 0x70); + break; + } + case 0x78: + case 0x79: + case 0x7a: + case 0x7b: + case 0x7c: + { + DrawPolygon(code == 0x78); + break; + } + case 0x90: + case 0x91: + case 0x98: + case 0x99: + case 0x9a: + case 0x9b: + { + is_pix_data = true; + short bits_per_pixel = 0; + short component_count = 0; + + size_t bytes_per_line = 0; + if ((code != 0x9a) && (code != 0x9b)) + bytes_per_line = ReadShortValue(); + else + fseek(m_pFile, 6, SEEK_CUR); + + Aggplus::Rect frame; + if (ReadRectangle(&frame) == 0) + return false; + + Image tile_image(m_oImgData); + if (frame.Width != 0) + tile_image.m_nWidth = frame.Width; + if (frame.Height != 0) + tile_image.m_nHeight = frame.Height; + + tile_image.m_pPixelData = new BYTE[4 * tile_image.m_nWidth * tile_image.m_nHeight]; + + if ((code == 0x9a) || (code == 0x9b) || ((bytes_per_line & 0x8000) != 0)) + { + fseek(m_pFile, 18, SEEK_CUR); + + bits_per_pixel = ReadShortValue(); + component_count = ReadShortValue(); + short component_size = ReadShortValue(); + + fseek(m_pFile, 12, SEEK_CUR); + + if (feof(m_pFile) != 0 || bits_per_pixel <= 0 || + bits_per_pixel > 32 || component_count <= 0 || + component_count > 4 || component_size <= 0) + return false; + + tile_image.m_eAlphaTrait = component_count == 4 ? BlendPixelTrait : UndefinedPixelTrait; + if (component_count == 4) + SetImageAlpha(&tile_image, 255); + } + + if ((code != 0x9a) && (code != 0x9b)) + { + tile_image.m_nColors = 2; + + if ((bytes_per_line & 0x8000) != 0) + { + fseek(m_pFile, 4, SEEK_CUR); + flag = ReadShortValue(); + tile_image.m_nColors = 1UL * ReadShortValue() + 1; + } + + tile_image.m_pColormap = new PixelInfo[tile_image.m_nColors + 1]; + + for (size_t i = 0; i < tile_image.m_nColors; i++) + { + tile_image.m_pColormap[i].storage_class = tile_image.m_eStorageClass; + tile_image.m_pColormap[i].alpha_trait = tile_image.m_eAlphaTrait; + + double pixel; + if (tile_image.m_nColors - 1 > 1) + pixel = ((double) i * (255 / (tile_image.m_nColors - 1))); + else + pixel = ((double) i * 255); + + tile_image.m_pColormap[i].red = pixel; + tile_image.m_pColormap[i].green = pixel; + tile_image.m_pColormap[i].blue = pixel; + tile_image.m_pColormap[i].alpha = 255.0; + tile_image.m_pColormap[i].alpha_trait = BlendPixelTrait; + } + tile_image.m_eStorageClass = PseudoClass; + + if ((bytes_per_line & 0x8000) != 0) + { + for (size_t i = 0; i < tile_image.m_nColors; i++) + { + int k = ReadShortValue() % tile_image.m_nColors; + if ((flag & 0x8000) != 0) + k = (size_t) i; + + tile_image.m_pColormap[k].red = static_cast(ReadShortValue()); + tile_image.m_pColormap[k].green = static_cast(ReadShortValue()); + tile_image.m_pColormap[k].blue = static_cast(ReadShortValue()); + } + } + else + { + for (size_t i = 0; i < tile_image.m_nColors; i++) + { + tile_image.m_pColormap[i].red = 255.0 - tile_image.m_pColormap[i].blue; + tile_image.m_pColormap[i].green = 255.0 - tile_image.m_pColormap[i].green; + tile_image.m_pColormap[i].blue = 255.0 - tile_image.m_pColormap[i].red; + } + } + } + if (feof(m_pFile) != 0) + return false; + + Aggplus::Rect source; + if (ReadRectangle(&source) == 0) + return false; + + Aggplus::Rect destination; + if (ReadRectangle(&destination) == 0) + return false; + + fseek(m_pFile, 2, SEEK_CUR); + + if ((code == 0x91) || (code == 0x99) || (code == 0x9b)) + { + size_t length = ReadShortValue(); + if (length > GetFileSize()) + return false; + + for (size_t i = 0; i < length - 2; i++) + if (fgetc(m_pFile) == EOF) + break; + } + + size_t extent; + BYTE* pixels; + if ((code != 0x9a) && (code != 0x9b) && (bytes_per_line & 0x8000) == 0) + pixels = DecodeImage(tile_image, bytes_per_line, 1, &extent); + else + pixels = DecodeImage(tile_image, bytes_per_line, bits_per_pixel, &extent); + + if (pixels == (unsigned char*) nullptr) + { + delete[] pixels; + return false; + } + + BYTE* p = pixels; + for (size_t y = 0; y < tile_image.m_nHeight; y++) + { + if (p > (pixels + extent + m_oImgData.m_nWidth)) + { + delete[] pixels; + return 0; + } + + unsigned char* q = tile_image.m_pPixelData + 4 * y * frame.Width; + if (q == (unsigned char *) nullptr) + break; + + for (size_t x = 0; x < tile_image.m_nWidth; x++) + { + if (tile_image.m_eStorageClass == PseudoClass) + { + unsigned char index; + if (*p < 0 || *p >= tile_image.m_nColors) + index = 0; + else + index = *p; + + if (tile_image.m_pChannelMap[IndexPixelChannel].traits != UndefinedPixelTrait) + q[tile_image.m_pChannelMap[IndexPixelChannel].offset] = index; + + q[tile_image.m_pChannelMap[RedPixelChannel].offset] = tile_image.m_pColormap[index].red; + q[tile_image.m_pChannelMap[GreenPixelChannel].offset] = tile_image.m_pColormap[index].green; + q[tile_image.m_pChannelMap[BluePixelChannel].offset] = tile_image.m_pColormap[index].blue; + } + else + { + if (bits_per_pixel == 16) + { + size_t i = (size_t) (*p++); + int k = (*p); + + q[tile_image.m_pChannelMap[RedPixelChannel].offset] = (BYTE) ((i & 0x7c) << 1); + q[tile_image.m_pChannelMap[GreenPixelChannel].offset] = (BYTE) ((i & 0x03) << 6) |((k & 0xe0) >> 2); + q[tile_image.m_pChannelMap[BluePixelChannel].offset] = (BYTE) ((k & 0x1f) << 3); + } + else if (tile_image.m_eAlphaTrait == UndefinedPixelTrait) + { + if (p > (pixels + extent + 2 * m_oImgData.m_nWidth)) + { + delete[] pixels; + return false; + } + + q[tile_image.m_pChannelMap[RedPixelChannel].offset] = *p; + q[tile_image.m_pChannelMap[GreenPixelChannel].offset] = *(p + tile_image.m_nWidth); + q[tile_image.m_pChannelMap[BluePixelChannel].offset] = *(p + 2 * tile_image.m_nWidth); + } + else + { + if (p > (pixels + extent + 3 * m_oImgData.m_nWidth)) + { + delete[] pixels; + return false; + } + + if (tile_image.m_pChannelMap[AlphaPixelChannel].traits != UndefinedPixelTrait) + q[tile_image.m_pChannelMap[AlphaPixelChannel].offset] = *p; + + q[tile_image.m_pChannelMap[RedPixelChannel].offset] = *(p + 1 * tile_image.m_nWidth); + q[tile_image.m_pChannelMap[GreenPixelChannel].offset] = *(p + 2 * tile_image.m_nWidth); + q[tile_image.m_pChannelMap[BluePixelChannel].offset] = *(p + 3 * tile_image.m_nWidth); + } + } + p++; + q += 4; + } + if (tile_image.m_eStorageClass == DirectClass && bits_per_pixel != 16) + { + p += (component_count - 1) * tile_image.m_nWidth; + if (p < pixels) + break; + } + } + + if (tile_image.m_eStorageClass == PseudoClass || + bits_per_pixel == 16 || + tile_image.m_eAlphaTrait == UndefinedPixelTrait) + SetImageAlpha(&tile_image, 255); + + delete[] pixels; + if (feof(m_pFile) == 0) + if ((code == 0x9a) || (code == 0x9b) || ((bytes_per_line & 0x8000) != 0)) + { + m_oImgData = tile_image; + m_oImgData.m_pPixelData = new BYTE[4 * m_oImgData.m_nHeight * m_oImgData.m_nWidth]; + memcpy(m_oImgData.m_pPixelData, tile_image.m_pPixelData, 4 * m_oImgData.m_nHeight * m_oImgData.m_nWidth); + } + break; + } + default: + break; + } + } + + if (code == 0xc00) + { + for (size_t i = 0; i < 24; i++) + if (fgetc(m_pFile) == EOF) + break; + continue; + } + + if (((code >= 0xb0) && (code <= 0xcf)) || ((code >= 0x8000) && (code <= 0x80ff))) + continue; + + if ((code == 0xff) || (code == 0xffff)) + continue; + + if (((code >= 0xd0) && (code <= 0xfe)) || ((code >= 0x8100) && (code <= 0xffff))) + { + size_t length = ReadShortValue(); + if (length > GetFileSize()) + return false; + + for (size_t i = 0; i < length; i++) + if (fgetc(m_pFile) == EOF) + break; + continue; + } + + if ((code >= 0x100) && (code <= 0x7fff)) + { + size_t length = (size_t) ((code >> 7) & 0xff); + if (length > GetFileSize()) + return false; + + for (size_t i = 0; i < length; i++) + if (fgetc(m_pFile) == EOF) + break; + continue; + } + } + + if (!is_pix_data) + { + m_oImgData.m_pPixelData = new BYTE[4 * m_oImgData.m_nHeight * m_oImgData.m_nWidth]; + memcpy(m_oImgData.m_pPixelData, m_oFrame.get_Data(), 4 * m_oImgData.m_nHeight * m_oImgData.m_nWidth); + } + + return true; +} + +size_t CPictFile::GetFileSize() const +{ + struct stat st; + + long long file_discription = _fileno(m_pFile); + if (fstat(file_discription, &st) == 0) + return st.st_size; + + return 0; +} + +size_t CPictFile::Read(const size_t& length, void* data) +{ + if (!m_pFile) + return 0; + if (data == nullptr) + return 0; + + unsigned char* q = (unsigned char*) data; + return fread(q, 1, length, m_pFile); +} + +const void* CPictFile::ReadBlobStream(const size_t& length, void* data, size_t* count) +{ + *count = Read(length, (unsigned char*) data); + return data; +} + +unsigned short CPictFile::ReadShortValue() +{ + unsigned char buffer[2]; + size_t count; + *buffer='\0'; + + const unsigned char* p = (const unsigned char*) ReadBlobStream(2, buffer, &count); + if (count != 2) + return EOF; + + unsigned short value = (unsigned short) ((*p++) << 8); + value |= (unsigned short) (*p++); + return (unsigned short) (value & 0xffff); +} + +signed short CPictFile::ReadSignedShortValue() +{ + union + { + unsigned short unsigned_value; + signed short signed_value; + } Quantum; + + Quantum.unsigned_value = ReadShortValue(); + return (Quantum.signed_value); +} + +unsigned int CPictFile::ReadLongValue() +{ + unsigned char buffer[4]; + *buffer='\0'; + int count = Read(4, buffer); + + if (count != 4) + return EOF; + + const unsigned char* p = (const unsigned char*) buffer; + + unsigned int value = (unsigned int) (*p++) << 24; + value |= (unsigned int) (*p++) << 16; + value |= (unsigned int) (*p++) << 8; + value |= (unsigned int) (*p++); + + return value; +} + +bool CPictFile::ReadRectangle(Aggplus::Rect* rect) +{ + rect->Y = ReadShortValue(); + rect->X = ReadShortValue(); + rect->Height = ReadShortValue() - rect->Y; + rect->Width = ReadShortValue() - rect->X; + + if (feof(m_pFile) != 0) + return false; + + if (!rect->IsPositive()) + return false; + + return true; +} + +void CPictFile::SetImageAlpha(Image* img, const BYTE alpha) +{ + bool status = true; + + if (!img->m_pPixelData) + img->m_pPixelData = new BYTE[4 * img->m_nHeight * img->m_nWidth]; + + img->m_eAlphaTrait = BlendPixelTrait; + img->m_pChannelMap[AlphaPixelChannel].traits = UpdatePixelTrait; + for (int y = 0; y < img->m_nHeight; y++) + { + if (!status) + continue; + + unsigned char* q = img->m_pPixelData + 4 * (y * img->m_nWidth); + + if (q == nullptr) + { + status = false; + continue; + } + for (int x = 0; x < img->m_nWidth; x++) + { + int write_mask; + if (img->m_pChannelMap[WriteMaskPixelChannel].traits == UndefinedPixelTrait) + write_mask = 255; + else + write_mask = q[img->m_pChannelMap[WriteMaskPixelChannel].offset]; + + if (write_mask > (255 / 2)) + if (img->m_pChannelMap[AlphaPixelChannel].traits != UndefinedPixelTrait) + q[img->m_pChannelMap[AlphaPixelChannel].offset] = alpha; + + q += 4; + } + } +} + +BYTE* CPictFile::DecodeImage(const Image& img, size_t bytesPerLine, size_t bitsPerPixel, size_t* extent) +{ + bool status = true; + + if (bitsPerPixel <= 8) + bytesPerLine &= 0x7fff; + + size_t width = img.m_nWidth; + size_t bytes_per_pixel = 1; + + if (bitsPerPixel == 16) + { + bytes_per_pixel = 2; + width *= 2; + } + else if (bitsPerPixel == 32) + width *= img.m_eAlphaTrait ? 4 : 3; + + if (bytesPerLine == 0) + bytesPerLine = width; + + size_t row_bytes = (size_t) (img.m_nWidth | 0x8000); + + if (img.m_eStorageClass == DirectClass) + row_bytes = (size_t) ((4 * img.m_nWidth) | 0x8000); + + BYTE* pixels = new BYTE[img.m_nHeight * row_bytes]; + + if (pixels == nullptr) + return nullptr; + + *extent = row_bytes * img.m_nHeight; + memset(pixels, 0, *extent); + BYTE* scanline = new BYTE[row_bytes * 2]; + + if (scanline == nullptr) + { + delete[] pixels; + return nullptr; + } + + memset(scanline, 0, 2 * row_bytes * sizeof(*scanline)); + + BYTE unpack_buffer[8 * 256]; + memset(unpack_buffer, 0, sizeof(unpack_buffer)); + + if (bytesPerLine < 8) + { + for (size_t y = 0; y < img.m_nHeight; y++) + { + BYTE* q = pixels + y * (long long) width * 4; + int count = Read(bytesPerLine, scanline); + if (count != bytesPerLine) + { + status = false; + break; + } + + size_t number_pixels; + const unsigned char* p = UnpackScanline(scanline, bitsPerPixel, unpack_buffer, &number_pixels); + if (q + number_pixels > pixels + (*extent)) + { + status = false; + break; + } + memcpy(q, p, (size_t) number_pixels); + } + delete[] scanline; + if (!status) + delete[] pixels; + return pixels; + } + + for (size_t y = 0; y < img.m_nHeight; y++) + { + BYTE* q = pixels + y * width; + + size_t scanline_length; + if (bytesPerLine > 250) + scanline_length = ReadShortValue(); + else + scanline_length = fgetc(m_pFile); + + if ((scanline_length >= row_bytes) || (scanline_length == 0)) + { + status = false; + break; + } + + int count = Read(scanline_length,scanline); + if (count != scanline_length) + { + status = false; + break; + } + + for (size_t j = 0; j < scanline_length; ) + if ((scanline[j] & 0x80) == 0) + { + size_t length = (size_t) ((scanline[j] & 0xff) + 1); + size_t number_pixels = length * bytes_per_pixel; + const unsigned char* p = UnpackScanline(scanline + j + 1, bitsPerPixel, unpack_buffer, &number_pixels); + if ((q - pixels + number_pixels) <= *extent) + memcpy(q, p, number_pixels); + q += number_pixels; + j += length * bytes_per_pixel + 1; + } + else + { + size_t length = ((scanline[j] ^ 0xff) & 0xff) + 2; + size_t number_pixels = bytes_per_pixel; + const unsigned char* p = UnpackScanline(scanline + j + 1, bitsPerPixel, unpack_buffer, &number_pixels); + for (size_t i = 0; i < length; i++) + { + if ((q - pixels + number_pixels) <= *extent) + memcpy(q, p, (size_t) number_pixels); + q += number_pixels; + } + j += bytes_per_pixel + 1; + } + } + delete[] scanline; + + if (!status) + { + delete[] pixels; + pixels = nullptr; + } + + return pixels; +} + +const BYTE* CPictFile::UnpackScanline(const BYTE* pixels, const size_t& bitsPerPixel, BYTE* scanline, size_t* bytesPerLine) +{ + const unsigned char* p = pixels; + unsigned char* q = scanline; + switch (bitsPerPixel) + { + case 8: + case 16: + case 32: + return pixels; + case 4: + { + for (long long i = 0; i < (long long) *bytesPerLine; i++) + { + *q++ = (*p >> 4) & 0xff; + *q++ = (*p & 15); + p++; + } + *bytesPerLine *= 2; + break; + } + case 2: + { + for (long long i = 0; i < (long long) *bytesPerLine; i++) + { + *q++ = (*p >> 6) & 0x03; + *q++ = (*p >> 4) & 0x03; + *q++ = (*p >> 2) & 0x03; + *q++ = (*p & 3); + p++; + } + *bytesPerLine *= 4; + break; + } + case 1: + { + for (long long i = 0; i < (long long) *bytesPerLine; i++) + { + *q++ = (*p >> 7) & 0x01; + *q++ = (*p >> 6) & 0x01; + *q++ = (*p >> 5) & 0x01; + *q++ = (*p >> 4) & 0x01; + *q++ = (*p >> 3) & 0x01; + *q++ = (*p >> 2) & 0x01; + *q++ = (*p >> 1) & 0x01; + *q++ = (*p & 0x01); + p++; + } + *bytesPerLine *= 8; + break; + } + default: + break; + } + return scanline; +} + +void CPictFile::ReadPolygon() +{ + size_t size = ReadShortValue(); + fseek(m_pFile, 8, SEEK_CUR); + + size = (size - 10) / 4; + const size_t max_possible_points = GetFileSize() - ftell(m_pFile); + if (size > max_possible_points) + size = max_possible_points; + + m_arLastPolygon.resize(size); + + for (size_t i = 0; i < size; i++) + { + int y = ReadShortValue(); + int x = ReadShortValue(); + m_arLastPolygon[i] = Aggplus::Point(x, y); + if (feof(m_pFile)) + { + m_arLastPolygon.resize(i); + break; + } + } +} + +Aggplus::Rect CPictFile::ContractRect(const Aggplus::Rect& rect, bool isFrame) +{ + if (!isFrame) + return rect; + + int pen_size = (m_nPenWidth + m_nPenHeight) / 2; + + if (pen_size * 2 > rect.Width) + pen_size = (rect.Width + 1) / 2; + if (pen_size * 2 > rect.Height) + pen_size = (rect.Height + 1) / 2; + + const long X[2] = {rect.GetLeft() + pen_size / 2, rect.GetRight() - (pen_size + 1) / 2}; + const long Y[2] = {rect.GetTop() + pen_size / 2, rect.GetBottom() - (pen_size + 1) / 2}; + + return Aggplus::Rect(X[0], Y[0], X[1] - X[0], Y[1] - Y[0]); +} + +void CPictFile::DrawPolygon(bool isFrame) +{ + InitializeRenderer(); + + size_t pen_size = (m_nPenWidth + m_nPenHeight) / 2; + long deca1TL[2] = {0, 0}, deca1BR[2] = {static_cast(m_nPenWidth), static_cast(m_nPenWidth)}; + + if (isFrame) + { + deca1TL[0] += pen_size / 2; + deca1TL[1] += pen_size / 2; + deca1BR[0] -= (pen_size + 1) / 2; + deca1BR[1] -= (pen_size + 1) / 2; + } + else + deca1BR[0] = deca1BR[1] = 0; + + size_t points_count = m_arLastPolygon.size(); + if (points_count < 1) + return; + + double bary[2] = {0.0, 0.0}; + for (int i = 0; i < points_count; i++) + { + const Aggplus::Point& pt = m_arLastPolygon[i]; + bary[0] += double(pt.X); + bary[1] += double(pt.Y); + } + bary[0] /= double(points_count); + bary[1] /= double(points_count); + + + std::vector B2Dpoly; + B2Dpoly.resize(points_count); + for (int i = 0; i < points_count; i++) + { + const Aggplus::Point& pt = m_arLastPolygon[i]; + double x = (double(pt.X) < bary[0]) ? pt.X + deca1TL[0] : pt.X + deca1BR[0]; + double y = (double(pt.Y) < bary[1]) ? pt.Y + deca1TL[1] : pt.Y + deca1BR[1]; + B2Dpoly[i] = Aggplus::PointF(x, y); + } + + m_pRenderer->PathCommandStart(); + m_pRenderer->BeginCommand(c_nPathType); + m_pRenderer->PathCommandMoveTo(B2Dpoly[0].X, B2Dpoly[0].Y); + + for (int i = 1; i < points_count; i++) + m_pRenderer->PathCommandLineTo(B2Dpoly[i].X, B2Dpoly[i].Y); + + + if (!isFrame) + m_pRenderer->Fill(); + + m_pRenderer->DrawPath(c_nStroke); + m_pRenderer->EndCommand(c_nPathType); + m_pRenderer->PathCommandEnd(); +} + +void CPictFile::DrawLine(const Aggplus::Point& p1, const Aggplus::Point& p2) +{ + long dir[2] = {p2.X - p1.X, p2.Y - p1.Y}; + long X[2] = {p1.X, p2.X}; + long Y[2] = {p1.Y, p2.Y}; + + if (dir[0] == 0) + { + if (X[0] < X[1]) + X[1] += m_nPenWidth; + else + X[0] += m_nPenWidth; + Y[1] += m_nPenHeight; + + std::vector poly; + poly.resize(5); + poly[0] = Aggplus::Point(X[0], Y[0]); + poly[1] = Aggplus::Point(X[1], Y[0]); + poly[2] = Aggplus::Point(X[1], Y[1]); + poly[3] = Aggplus::Point(X[0], Y[1]); + poly[4] = Aggplus::Point(X[0], Y[0]); + std::vector tmp = m_arLastPolygon; + m_arLastPolygon = poly; + DrawPolygon(false); + m_arLastPolygon = tmp; + } + else if (dir[1] == 0) + { + if (Y[0] < Y[1]) + Y[1] += m_nPenHeight; + else + Y[0] += m_nPenHeight; + X[1] += m_nPenWidth; + + std::vector poly; + poly.resize(5); + poly[0] = Aggplus::Point(X[0], Y[0]); + poly[1] = Aggplus::Point(X[1], Y[0]); + poly[2] = Aggplus::Point(X[1], Y[1]); + poly[3] = Aggplus::Point(X[0], Y[1]); + poly[4] = Aggplus::Point(X[0], Y[0]); + std::vector tmp = m_arLastPolygon; + m_arLastPolygon = poly; + DrawPolygon(false); + m_arLastPolygon = tmp; + } + else if (dir[0] * dir[0] + dir[1] * dir[1] < 25) + { + long orig_pt[4][2] = {{p1.X, p1.Y}, + {p1.X + static_cast(m_nPenWidth), p1.Y}, + {p1.X + static_cast(m_nPenWidth), p1.Y + static_cast(m_nPenHeight)}, + {p1.X, p1.Y + static_cast(m_nPenHeight)}}; + int orig_avoid = dir[0] > 0 ? (dir[1] > 0 ? 2 : 1) : (dir[1] > 0 ? 3 : 0); + long dest_pt[4][2] = {{p2.X, p2.Y}, + {p2.X + static_cast(m_nPenWidth), p2.Y}, + {p2.X + static_cast(m_nPenWidth), p2.Y + static_cast(m_nPenHeight)}, + {p2.X, p2.Y + static_cast(m_nPenHeight)}}; + std::vector poly; + poly.resize(7); + for (int w = 1; w < 4; w++) + { + int wh = (w + orig_avoid) % 4; + poly[w - 1] = Aggplus::Point(orig_pt[wh][0], orig_pt[wh][1]); + } + + for (int w = 3; w < 6; w++) + { + int wh = (w + orig_avoid) % 4; + poly[w] = Aggplus::Point(dest_pt[wh][0], dest_pt[wh][1]); + } + + int wh = (orig_avoid + 1) % 4; + poly[6] = Aggplus::Point(orig_pt[wh][0], orig_pt[wh][1]); + std::vector tmp = m_arLastPolygon; + m_arLastPolygon = poly; + DrawPolygon(false); + m_arLastPolygon = tmp; + } + else + { + long decal[2] = {static_cast(m_nPenWidth / 2), static_cast(m_nPenHeight / 2)}; + std::vector poly; + poly.resize(2); + poly[0] = Aggplus::Point(p1.X + decal[0], p1.Y + decal[1]); + poly[1] = Aggplus::Point(p2.X + decal[0], p2.Y + decal[1]); + std::vector tmp = m_arLastPolygon; + m_arLastPolygon = poly; + DrawPolygon(false); + m_arLastPolygon = tmp; + } +} + +void CPictFile::DrawRect(bool isFrame) +{ + InitializeRenderer(); + + Aggplus::Rect new_rect = ContractRect(m_oLastRect, isFrame); + const long X[2] = {new_rect.GetLeft(), new_rect.GetRight()}; + const long Y[2] = {new_rect.GetTop(), new_rect.GetBottom()}; + + m_pRenderer->PathCommandStart(); + m_pRenderer->BeginCommand(c_nPathType); + Aggplus::CGraphicsPath path; + path.AddRectangle(X[0], Y[0], X[1] - X[0], Y[1] - Y[0]); + size_t points_count = path.GetPointCount(); + + Aggplus::PointF* points = new Aggplus::PointF[points_count]; + path.GetPathPoints(points, points_count); + + m_pRenderer->PathCommandMoveTo(points[0].X, points[0].Y); + + for (size_t i = 1; i < points_count; i++) + m_pRenderer->PathCommandLineTo(points[i].X, points[i].Y); + + if (!isFrame) + m_pRenderer->Fill(); + + m_pRenderer->DrawPath(c_nStroke); + m_pRenderer->EndCommand(c_nPathType); + m_pRenderer->PathCommandEnd(); + + delete[] points; +} + +void CPictFile::DrawRoundRect(bool isFrame) +{ + InitializeRenderer(); + + Aggplus::Rect oval = ContractRect(m_oLastRoundRect, isFrame); + int ovalW = m_nPenWidth; + int ovalH = m_nPenHeight; + const long X[2] = {oval.GetLeft(), oval.GetRight()}; + const long Y[2] = {oval.GetTop(), oval.GetBottom()}; + long width = X[1] - X[0]; + long height = Y[1] - Y[0]; + + if (ovalW > width) + ovalW = static_cast(width); + if (ovalH > height) + ovalH = static_cast(height); + + m_pRenderer->PathCommandStart(); + m_pRenderer->BeginCommand(c_nPathType); + Aggplus::CGraphicsPath path; + path.AddRoundRectangle(X[0], Y[0], X[1] - X[0], Y[1] - Y[0], width == 0.0 ? 0.0 : ovalW / width, height == 0.0 ? 0.0 : ovalH / height); + size_t points_count = path.GetPointCount(); + + Aggplus::PointF* points = new Aggplus::PointF[points_count]; + path.GetPathPoints(points, points_count); + + m_pRenderer->PathCommandMoveTo(points[0].X, points[0].Y); + + for (size_t i = 1; i < points_count; i++) + { + if (path.IsCurvePoint(i)) + { + m_pRenderer->PathCommandCurveTo(points[i].X, points[i].Y, + points[i + 1].X, points[i + 1].Y, + points[i + 2].X, points[i + 2].Y); + i += 2; + } + m_pRenderer->PathCommandLineTo(points[i].X, points[i].Y); + } + + + if (!isFrame) + m_pRenderer->Fill(); + + m_pRenderer->DrawPath(c_nStroke); + m_pRenderer->EndCommand(c_nPathType); + m_pRenderer->PathCommandEnd(); + + delete[] points; +} + +void CPictFile::DrawOval(bool isFrame) +{ + InitializeRenderer(); + + Aggplus::Rect rect = ContractRect(m_oLastOval, isFrame); + const long X[2] = {rect.GetLeft(), rect.GetRight()}; + const long Y[2] = {rect.GetTop(), rect.GetBottom()}; + + m_pRenderer->PathCommandStart(); + m_pRenderer->BeginCommand(c_nPathType); + Aggplus::CGraphicsPath path; + path.AddEllipse(X[0], Y[0], X[1] - X[0], Y[1] - Y[0]); + size_t points_count = path.GetPointCount(); + + Aggplus::PointF* points = new Aggplus::PointF[points_count]; + path.GetPathPoints(points, points_count); + + m_pRenderer->PathCommandMoveTo(points[0].X, points[0].Y); + + for (size_t i = 1; i < points_count; i += 3) + m_pRenderer->PathCommandCurveTo(points[i].X, points[i].Y, + points[i + 1].X, points[i + 1].Y, + points[i + 2].X, points[i + 2].Y); + + if (!isFrame) + m_pRenderer->Fill(); + + m_pRenderer->DrawPath(c_nStroke); + m_pRenderer->EndCommand(c_nPathType); + m_pRenderer->PathCommandEnd(); + + delete[] points; +} + +void CPictFile::DrawArc() +{ + InitializeRenderer(); + + short start_angle = ReadShortValue(); + short angle = ReadShortValue(); + if (feof(m_pFile) || (m_nPenWidth == 0 && m_nPenHeight == 0)) + return; + + if (angle < 0) + { + start_angle = start_angle + angle; + angle = -angle; + } + + double ang1 = agg::deg2rad(start_angle); + double ang2 = agg::deg2rad(angle); + + m_pRenderer->PathCommandStart(); + m_pRenderer->BeginCommand(c_nPathType); + Aggplus::CGraphicsPath path; + path.AddArc(m_oLastArc.GetLeft(), m_oLastArc.GetTop(), m_oLastArc.Width, m_oLastArc.Height, ang1, ang2); + + size_t points_count = path.GetPointCount(); + + Aggplus::PointF* points = new Aggplus::PointF[points_count]; + path.GetPathPoints(points, points_count); + + m_pRenderer->PathCommandMoveTo(points[0].X, points[0].Y); + + for (size_t i = 1; i < points_count; i += 3) + m_pRenderer->PathCommandCurveTo(points[i].X, points[i].Y, + points[i + 1].X, points[i + 1].Y, + points[i + 2].X, points[i + 2].Y); + + m_pRenderer->DrawPath(c_nStroke); + m_pRenderer->EndCommand(c_nPathType); + m_pRenderer->PathCommandEnd(); + + delete[] points; +} + +void CPictFile::ReadAndDrawText(int x, int y) +{ + InitializeRenderer(); + + char text[256]; + char byte_len = fgetc(m_pFile); + unsigned long len = static_cast(byte_len) & 0x000000ff; + len = Read(len, &text); + + if (m_nPenWidth == 0 && m_nPenHeight == 0) + return; + + while (len > 0 && static_cast(text[len - 1]) < 32) + len--; + text[len] = 0; + m_pRenderer->put_FontName(m_wsFontName); + m_pRenderer->put_FontSize(m_nFontSize); + m_pRenderer->put_FontStyle(m_nFontStyle); + + std::wstring ws_text(len, L'\0'); + std::mbstowcs(&ws_text[0], text, len); + + m_pRenderer->BeginCommand(c_nTextGraphicType); + m_pRenderer->CommandDrawText(ws_text, x, y, 0.0, 0.0); + m_pRenderer->EndCommand(c_nTextGraphicType); +} + +void CPictFile::InitializeRenderer() +{ + if (m_pFrameData) + return; + + m_pFrameData = new BYTE[4 * m_oImgData.m_nWidth * m_oImgData.m_nHeight]; + m_oFrame.put_Data(m_pFrameData); + m_oFrame.put_Width(m_oImgData.m_nWidth); + m_oFrame.put_Height(m_oImgData.m_nHeight); + m_oFrame.put_Stride(4 * m_oImgData.m_nWidth); + + m_pRenderer->CreateFromBgraFrame(&m_oFrame); + m_pRenderer->put_Width(m_oImgData.m_nWidth); + m_pRenderer->put_Height(m_oImgData.m_nHeight); + m_pRenderer->SetSwapRGB(false); + m_pRenderer->put_PenColor(0x000000); } diff --git a/DesktopEditor/raster/PICT/PICFile.h b/DesktopEditor/raster/PICT/PICFile.h index 40daae02f2..620047298a 100644 --- a/DesktopEditor/raster/PICT/PICFile.h +++ b/DesktopEditor/raster/PICT/PICFile.h @@ -32,14 +32,204 @@ #ifndef PICFILE_H #define PICFILE_H -#include "../BgraFrame.h" +#include "../pro/Graphics.h" -namespace PICT { - class GRAPHICS_DECL CPictFile { - public: - bool Open(CBgraFrame* pFrame, const std::wstring& strFileName, bool isRGBA); - bool Open(CBgraFrame* pFrame, BYTE* pBuffer, int nSize, bool isRGBA); - }; -} +enum PixelTrait +{ + UndefinedPixelTrait = 0x000000, + CopyPixelTrait = 0x000001, + UpdatePixelTrait = 0x000002, + BlendPixelTrait = 0x000004 +}; + +enum ClassType +{ + UndefinedClass, + DirectClass, + PseudoClass +}; + +enum PixelChannel +{ + UndefinedPixelChannel = 0, + RedPixelChannel = 0, + CyanPixelChannel = 0, + GrayPixelChannel = 0, + LPixelChannel = 0, + LabelPixelChannel = 0, + YPixelChannel = 0, + aPixelChannel = 1, + GreenPixelChannel = 1, + MagentaPixelChannel = 1, + CbPixelChannel = 1, + bPixelChannel = 2, + BluePixelChannel = 2, + YellowPixelChannel = 2, + CrPixelChannel = 2, + BlackPixelChannel = 3, + AlphaPixelChannel = 4, + IndexPixelChannel = 5, + ReadMaskPixelChannel = 6, + WriteMaskPixelChannel = 7, + MetaPixelChannel = 8, /* deprecated */ + CompositeMaskPixelChannel = 9, + MetaPixelChannels = 10, + IntensityPixelChannel = 64, /* ???? */ + CompositePixelChannel = 64, /* ???? */ + SyncPixelChannel = 65 /* not a real channel */ +}; + +struct PixelChannelMap +{ + PixelChannel channel{UndefinedPixelChannel}; + PixelTrait traits{UndefinedPixelTrait}; + size_t offset{0}; +}; + +struct PixelInfo +{ + ClassType storage_class{DirectClass}; + + PixelTrait alpha_trait{UndefinedPixelTrait}; + + double red{0.0}; + double green{0.0}; + double blue{0.0}; + double alpha{0.0}; + double index{0.0}; +}; + +struct Image +{ + ClassType m_eStorageClass{DirectClass}; + PixelTrait m_eAlphaTrait{UndefinedPixelTrait}; + + PixelInfo* m_pColormap{nullptr}; + PixelChannelMap* m_pChannelMap{nullptr}; + + size_t m_nColors{0}; + size_t m_nHeight{0}; + size_t m_nWidth{0}; + BYTE* m_pPixelData{nullptr}; + + Image() + { + m_pChannelMap = new PixelChannelMap[65]; + for (size_t i=0; i <= 64; i++) + m_pChannelMap[i].channel=(PixelChannel) i; + + m_pChannelMap[RedPixelChannel].offset = 0; + m_pChannelMap[GreenPixelChannel].offset = 1; + m_pChannelMap[BluePixelChannel].offset = 2; + m_pChannelMap[AlphaPixelChannel].offset = 3; + m_pChannelMap[IndexPixelChannel].offset = 5; + } + + Image(const Image& other) : Image() + { + *this = other; + } + + ~Image() + { + if (m_pChannelMap) + delete[] m_pChannelMap; + + if (m_pColormap) + delete[] m_pColormap; + + if (m_pPixelData) + delete[] m_pPixelData; + } + + Image& operator=(const Image& other) + { + if (this == &other) + return *this; + + m_eStorageClass = other.m_eStorageClass; + m_eAlphaTrait = other.m_eAlphaTrait; + + m_nColors = other.m_nColors; + m_nWidth = other.m_nWidth; + m_nHeight = other.m_nHeight; + + if (other.m_pColormap) + { + m_pColormap = new PixelInfo[m_nColors + 1]; + memcpy(m_pColormap, other.m_pColormap, m_nColors + 1); + } + + memcpy(m_pChannelMap, other.m_pChannelMap, 65); + return *this; + } +}; + +class CPictFile +{ +public: + CPictFile(); + ~CPictFile(); + + bool Open(CBgraFrame* frame, const std::wstring& fileName); + bool Open(CBgraFrame* frame, BYTE* buffer, const size_t& size); +private: + bool Decode(); + bool DecodeHeader(); + bool DecodeData(); + + size_t GetFileSize() const; + + size_t Read(const size_t& length, void* data); + const void* ReadBlobStream(const size_t& length, void* data, size_t* count); + unsigned short ReadShortValue(); + signed short ReadSignedShortValue(); + unsigned int ReadLongValue(); + bool ReadRectangle(Aggplus::Rect* rect); + + void SetImageAlpha(Image* img, const BYTE alpha); + BYTE* DecodeImage(const Image& img, size_t bytesPerLine, size_t bitsPerPixel, size_t* extent); + const BYTE* UnpackScanline(const BYTE* pixels, const size_t& bitsPerPixel, BYTE* scanline, size_t* bytesPerLine); + + void ReadPolygon(); + Aggplus::Rect ContractRect(const Aggplus::Rect& rect, bool isFrame); + void DrawPolygon(bool isFrame); + void DrawLine(const Aggplus::Point& p1, const Aggplus::Point& p2); + void DrawRect(bool isFrame); + void DrawRoundRect(bool isFrame); + void DrawOval(bool isFrame); + void DrawArc(); + void ReadAndDrawText(int x, int y); + + void InitializeRenderer(); + +private: + int m_nVersion{0}; + + FILE* m_pFile{nullptr}; + Image m_oImgData{}; + CBgraFrame m_oFrame{}; + BYTE* m_pFrameData{nullptr}; + + size_t m_nPenHeight{0}; + size_t m_nPenWidth{0}; + + int m_nFontStyle{0}; + int m_nFontSize{0}; + + std::wstring m_wsFontName{}; + + Aggplus::Point m_oPenPoint{}; + Aggplus::Point m_oTextPoint{}; + + Aggplus::Rect m_oLastRect{}; + Aggplus::Rect m_oLastRoundRect{}; + Aggplus::Rect m_oLastOval{}; + Aggplus::Rect m_oLastArc{}; + std::vector m_arLastPolygon{}; + + NSGraphics::IGraphicsRenderer* m_pRenderer{nullptr}; + NSFonts::IFontManager* m_pFontManager{nullptr}; +}; #endif // PICFILE_H diff --git a/DesktopEditor/raster/PICT/pic.cpp b/DesktopEditor/raster/PICT/pic.cpp deleted file mode 100644 index ae7cb62aa1..0000000000 --- a/DesktopEditor/raster/PICT/pic.cpp +++ /dev/null @@ -1,3063 +0,0 @@ -/* - * (c) Copyright Ascensio System SIA 2010-2023 - * - * This program is a free software product. You can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License (AGPL) - * version 3 as published by the Free Software Foundation. In accordance with - * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect - * that Ascensio System SIA expressly excludes the warranty of non-infringement - * of any third-party rights. - * - * This program is distributed WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For - * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html - * - * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish - * street, Riga, Latvia, EU, LV-1050. - * - * The interactive user interfaces in modified source and object code versions - * of the Program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU AGPL version 3. - * - * Pursuant to Section 7(b) of the License you must retain the original Product - * logo when distributing the program. Pursuant to Section 7(e) we decline to - * grant you any rights under trademark law for use of our trademarks. - * - * All the Product's GUI elements, including illustrations and icon sets, as - * well as technical writing content are licensed under the terms of the - * Creative Commons Attribution-ShareAlike 4.0 International. See the License - * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode - * - */ -#include "pic.h" -#include "../pro/Graphics.h" - -#define BackgroundColorRGBA 255,255,255,255 -#define TransparentAlpha ((unsigned char) 0) - -int LocaleToLowercase(const int c) -{ - if ((c == EOF) || (c != (unsigned char) c)) - return c; - return tolower((int) ((unsigned char) c)); -} - -int LocaleCompare(const char *p, const char *q) -{ - if (p == (char *) nullptr) - { - if (q == (char *) nullptr) - return 0; - return -1; - } - if (q == (char *) nullptr) - return 1; - const unsigned char - *r = (const unsigned char *) p, - *s = (const unsigned char *) q; - for ( ; (*r != '\0') && (*s != '\0') && ((*r == *s) || (LocaleToLowercase((int) *r) == LocaleToLowercase((int) *s))); r++, s++); - return(LocaleToLowercase((int) *r)-LocaleToLowercase((int) *s)); -} - -int LocaleNCompare(const char *p, const char *q, const size_t length) -{ - if (p == (char *) nullptr) - { - if (q == (char *) nullptr) - return 0; - return -1; - } - if (q == (char *) nullptr) - return 1; - if (length == 0) - return 0; - - const unsigned char - *s = (const unsigned char *) p, - *t = (const unsigned char *) q; - size_t n = length; - for (n--; (*s != '\0') && (*t != '\0') && (n != 0) && ((*s == *t) || (LocaleToLowercase((int) *s) == LocaleToLowercase((int) *t))); s++, t++, n--); - return(LocaleToLowercase((int) *s)-LocaleToLowercase((int) *t)); - -} - -char *ConstantString(const char *source) -{ - char *destination = nullptr; - size_t length = 0; - - if (source != nullptr) - length += strlen(source); - - if (~length >= 1UL) - destination=(char *) malloc(length+1UL*sizeof(*destination)); - - if (destination == nullptr) - return nullptr; - - if (source != nullptr) - (void) memcpy(destination,source,length*sizeof(*destination)); - - destination[length]='\0'; - return destination; -} - -int IsStringTrue(const char *value) -{ - if (value == nullptr) - return 0; - if (LocaleCompare(value,"true") == 0) - return 1; - if (LocaleCompare(value,"on") == 0) - return 1; - if (LocaleCompare(value,"yes") == 0) - return 1; - if (LocaleCompare(value,"1") == 0) - return 1; - return 0; -} - -size_t CopyMagickString(char *destination, const char *source, const size_t length) -{ - char* q = destination; - const char* p = source; - - size_t n; - for (n = length; n > 4; n -= 4) - { - if (((*q++) = (*p++)) == '\0') - return (size_t) (p - source - 1); - if (((*q++) = (*p++)) == '\0') - return (size_t) (p - source - 1); - if (((*q++) = (*p++)) == '\0') - return (size_t) (p - source - 1); - if (((*q++) = (*p++)) == '\0') - return (size_t) (p - source - 1); - } - if (length != 0) - { - while (--n != 0) - if (((*q++) = (*p++)) == '\0') - return (size_t) (p - source - 1); - *q = '\0'; - } - return (size_t) (p-source); -} - -StringInfo *AcquireStringInfo(const size_t length) -{ - StringInfo *string_info = (StringInfo *) malloc(sizeof(*string_info)); - (void) memset(string_info, 0, sizeof(*string_info)); - string_info->signature = 0xabacadabUL; - string_info->length = length; - - if (~string_info->length >= (4096-1)) - string_info->datum=(unsigned char *) malloc((string_info->length + 4096) * sizeof(*string_info->datum)); - if (string_info->datum == nullptr) - { - free(string_info); - return nullptr; - } - (void) memset(string_info->datum, 0, (length + 4096) * sizeof(*string_info->datum)); - return string_info; -} - -char *CloneString(char **destination, const char *source) -{ - size_t length; - if (source == nullptr) - { - if (*destination != nullptr) - free(*destination); - return nullptr; - } - if (*destination == nullptr) - { - *destination = (char*) malloc((strlen(source) + 4096)/* * sizeof (*destination)*/); - memcpy(*destination, source, strlen(source)/**sizeof(**destination)*/); - (*destination)[strlen(source)]='\0'; - - return *destination; - } - - length=strlen(source); - if (~length < 4096) - return nullptr; - - free(*destination); - *destination = (char*) malloc((length + 4096)/**sizeof (**destination)*/); - - if (*destination == nullptr) - return nullptr; - - if (length != 0) - memcpy(*destination, source, length/**sizeof(**destination)*/); - - (*destination)[length]='\0'; - return(*destination); -} - -StringInfo *CloneStringInfo(const StringInfo *string_info) -{ - StringInfo *clone_info = AcquireStringInfo(string_info->length); - - CloneString(&clone_info->path,string_info->path); - CloneString(&clone_info->name,string_info->name); - - if (string_info->length != 0) - memcpy(clone_info->datum, string_info->datum, string_info->length + 1); - - return clone_info; -} - -void DestroyStringInfo(StringInfo *string_info) -{ - if (string_info->datum != nullptr) - free(string_info->datum); - - if (string_info->name != nullptr) - free(string_info->name); - - if (string_info->path != nullptr) - free(string_info->path); - - string_info->signature = (~0xabacadabUL); - free(string_info); -} - -void DeletePixelsMemory(ImagePICT* image) -{ - if (image->ppixels != nullptr) - { - free(image->ppixels); - image->ppixels = nullptr; - image->m_nPixelsSize = 0; - } -} - -PixelChannelMap *AcquirePixelChannelMap() -{ - PixelChannelMap *channel_map = (PixelChannelMap *) malloc(65 * sizeof(*channel_map)); - - if (channel_map == nullptr) - return nullptr; - - (void) memset(channel_map,0,65*sizeof(*channel_map)); - for (size_t i=0; i <= 64; i++) - channel_map[i].channel=(PixelChannel) i; - - channel_map[RedPixelChannel].offset = 0; - channel_map[GreenPixelChannel].offset = 1; - channel_map[BluePixelChannel].offset = 2; - channel_map[AlphaPixelChannel].offset = 3; - channel_map[IndexPixelChannel].offset = 5; - - return channel_map; -} - -void GetPixelInfo(ImagePICT *image, PixelInfo *pixel) -{ - (void) memset(pixel, 0, sizeof(*pixel)); - pixel->storage_class=DirectClass; - pixel->colorspace=sRGBColorspace; - pixel->depth=8; - pixel->alpha_trait=UndefinedPixelTrait; - pixel->alpha=255.0; - - if (image == nullptr) - return; - - pixel->storage_class=image->storage_class; - pixel->colorspace=image->colorspace; - pixel->alpha_trait=image->alpha_trait; - pixel->depth=image->m_ndepth; - pixel->fuzz=image->fuzz; -} - -void GetPixelInfoRGBA(const unsigned char red, const unsigned char green, const unsigned char blue, const unsigned char alpha, PixelInfo *pixel) -{ - GetPixelInfo((ImagePICT *) nullptr, pixel); - pixel->red=red; - pixel->green=green; - pixel->blue=blue; - pixel->alpha=alpha; -} - -inline unsigned char GetPixelWriteMask(const ImagePICT *image, const unsigned char *pixel) -{ - if (image->channel_map[WriteMaskPixelChannel].traits == UndefinedPixelTrait) - return 255; - return pixel[image->channel_map[WriteMaskPixelChannel].offset]; -} - -inline bool IsValidOffset(const long long x, const size_t a) -{ - if (a == 0) - return false; - if ((x >= (LLONG_MAX / 64 / (long long) a)) || (x <= ((-LLONG_MAX - 1) / 64 / (long long) a))) - return false; - return true; -} - -bool ReadPixels(ImagePICT* image, const long long& x, const long long& y, const size_t width, const size_t height, unsigned char* pixels) -{ - if (IsValidOffset(y, image->m_nWidth) == 0) - return false; - - long long offset = y * (long long) image->m_nWidth; - if ((offset / (long long) image->m_nWidth) != y) - return false; - - offset += x; - size_t number_channels = image->number_channels; - size_t length = (size_t) number_channels * width * sizeof(unsigned char); - - if ((length / number_channels / sizeof(unsigned char)) != width) - return false; - - size_t rows = height; - size_t extent = length * rows; - - if ((extent == 0) || ((extent/length) != rows)) - return false; - - unsigned char* q = pixels; - if (image->m_nWidth == width) - { - length = extent; - rows = 1UL; - } - - size_t i; - unsigned char* p = image->ppixels + image->number_channels * offset; - for (i = 0; i < rows; i++) - { - (void) memcpy(q, p, length); - p += image->number_channels * image->m_nWidth; - q += image->number_channels * width; - } - - if (i < rows) - return false; - - return true; -} - -unsigned char* GetPixels(ImagePICT* image, const long long& x, const long long& y, const size_t width, const size_t height) -{ - unsigned char *pixels = image->ppixels + image->number_channels * (y * image->m_nWidth + x); - - if (pixels == nullptr) - return nullptr; - - if (ReadPixels(image, x, y, width, height, pixels) == 0) - return nullptr; - - return pixels; -} - -inline unsigned char GetPixelChannel(const ImagePICT *image, const PixelChannel& channel, const unsigned char *pixel) -{ - if ((size_t) channel >= 64) - return 0; - if (image->channel_map[channel].traits == UndefinedPixelTrait) - return 0; - return pixel[image->channel_map[channel].offset]; -} - -inline unsigned char GetPixelAlpha(const ImagePICT *image, const unsigned char *pixel) -{ - if (image->channel_map[AlphaPixelChannel].traits == UndefinedPixelTrait) - return 0; - return pixel[image->channel_map[AlphaPixelChannel].offset]; -} - -inline void SetPixelChannel(const ImagePICT *image, const PixelChannel& channel, const unsigned char Quantum, unsigned char *pixel) -{ - if ((size_t) channel >= 64) - return; - if (image->channel_map[channel].traits != UndefinedPixelTrait) - pixel[image->channel_map[channel].offset] = Quantum; -} - -inline PixelChannel GetPixelChannelChannel(const ImagePICT *image, const long long& offset) -{ - if ((offset < 0) || (offset >= 64)) - return UndefinedPixelChannel; - return image->channel_map[offset].channel; -} - -inline PixelTrait GetPixelChannelTraits(const ImagePICT *image, const PixelChannel& channel) -{ - if ((size_t) channel >= 64) - return UndefinedPixelTrait; - return image->channel_map[channel].traits; -} - -inline void SetPixelIndex(const ImagePICT *image, const unsigned char index, unsigned char *pixel) -{ - if (image->channel_map[IndexPixelChannel].traits != UndefinedPixelTrait) - pixel[image->channel_map[IndexPixelChannel].offset] = index; -} - -inline void SetPixelAlpha(const ImagePICT *image, const unsigned char alpha, unsigned char *pixel) -{ - if (image->channel_map[AlphaPixelChannel].traits != UndefinedPixelTrait) - pixel[image->channel_map[AlphaPixelChannel].offset] = alpha; -} - -inline void SetPixelRed(const ImagePICT *image, const unsigned char red, unsigned char *pixel) -{ - pixel[image->channel_map[RedPixelChannel].offset] = red; -} - -inline void SetPixelGreen(const ImagePICT *image, const unsigned char green, unsigned char *pixel) -{ - pixel[image->channel_map[GreenPixelChannel].offset] = green; -} - -inline void SetPixelBlue(const ImagePICT *image, const unsigned char blue, unsigned char *pixel) -{ - pixel[image->channel_map[BluePixelChannel].offset] = blue; -} - -bool AquirePixelsMemory(ImagePICT* image) -{ - if ((image->m_nHeight == 0) || (image->m_nWidth == 0)) - return false; - - image->m_nPixelsSize = image->m_nHeight * image->m_nWidth * image->number_channels; - - if (image->ppixels == nullptr) - image->ppixels = (unsigned char*) malloc(image->m_nPixelsSize); - else - image->ppixels = (unsigned char*) realloc(image->ppixels, image->m_nPixelsSize); - - return true; -} - -bool SetImageAlpha(ImagePICT* image, const unsigned char Alpha) -{ - bool status = true; - - if (AquirePixelsMemory(image) == 0) - return 0; - - image->alpha_trait = BlendPixelTrait; - image->channel_map[AlphaPixelChannel].traits = UpdatePixelTrait; - for (int y = 0; y < image->m_nHeight; y++) - { - if (!status) - continue; - - unsigned char* q = image->ppixels + image->number_channels * (y * image->m_nWidth); - - if (q == nullptr) - { - status = false; - continue; - } - for (int x = 0; x < image->m_nWidth; x++) - { - if (GetPixelWriteMask(image, q) > (255 / 2)) - SetPixelAlpha(image, Alpha, q); - q += image->number_channels; - } - } - - return status; -} - -bool AquireImageColormap(ImagePICT* image, const size_t colors) -{ - if (image == nullptr) - return false; - - if (colors > 256UL) - { - image->colors = 0; - image->storage_class = DirectClass; - return false; - } - - if (colors > 1) - image->colors = colors; - else - image->colors = 1; - if (image->colormap == nullptr) - image->colormap = (PixelInfo*) malloc((image->colors + 1) * sizeof(*image->colormap)); - else - image->colormap = (PixelInfo*) realloc(image->colormap, (image->colors + 1) * sizeof(*image->colormap)); - - if (image->colormap == nullptr) - { - image->colors = 0; - image->storage_class = DirectClass; - return false; - } - - for (size_t i = 0; i < image->colors; i++) - { - double pixel; - GetPixelInfo(image, image->colormap+i); - if (colors - 1 > 1) - pixel = ((double) i * (255 / (colors - 1))); - else - pixel = ((double) i * 255); - - image->colormap[i].red = pixel; - image->colormap[i].green = pixel; - image->colormap[i].blue = pixel; - image->colormap[i].alpha = 255.0; - image->colormap[i].alpha_trait = BlendPixelTrait; - } - image->storage_class=PseudoClass; - return true; -} - -inline bool IsRGBColorspace(const ColorspaceType& colorspace) -{ - if ((colorspace == RGBColorspace) || (colorspace == scRGBColorspace) || (colorspace == LinearGRAYColorspace)) - return true; - return false; -} - -inline bool IsGrayColorspace(const ColorspaceType& colorspace) -{ - if ((colorspace == LinearGRAYColorspace) || (colorspace == GRAYColorspace)) - return 1; - return 0; -} - -int SetImageColorspace(ImagePICT *image, const ColorspaceType& colorspace) -{ - if (image->colorspace == colorspace) - return 1; - - image->colorspace = colorspace; - image->gamma = 1.000 / 2.200; - (void) memset(&image->chromaticity, 0, sizeof(image->chromaticity)); - ImageType type=image->type; - if (IsGrayColorspace(colorspace) != 0) - { - if (colorspace == LinearGRAYColorspace) - image->gamma = 1.000; - - type=GrayscaleType; - } - else if ((IsRGBColorspace(colorspace) != 0) || (colorspace == XYZColorspace) || (colorspace == xyYColorspace)) - image->gamma=1.000; - else - { - image->chromaticity.red_primary.x=0.6400; - image->chromaticity.red_primary.y=0.3300; - image->chromaticity.red_primary.z=0.0300; - image->chromaticity.green_primary.x=0.3000; - image->chromaticity.green_primary.y=0.6000; - image->chromaticity.green_primary.z=0.1000; - image->chromaticity.blue_primary.x=0.1500; - image->chromaticity.blue_primary.y=0.0600; - image->chromaticity.blue_primary.z=0.7900; - image->chromaticity.white_point.x=0.3127; - image->chromaticity.white_point.y=0.3290; - image->chromaticity.white_point.z=0.3583; - } - - if (image->ppixels == nullptr) - return 0; - - image->type = type; - return 1; -} - -inline unsigned char ClampPixel(const double& pixel) -{ - if (pixel < 0.0) - return ((unsigned char) 0); - if (pixel >= 255.0) - return ((unsigned char) 255); - return (unsigned char) (pixel); -} - -inline unsigned char ClampToQuantum(const double& pixel) -{ - if ((isnan(pixel) != 0) || (pixel <= 0.0)) - return 0; - if (pixel >= 255.0) - return 255; - return (unsigned char) (pixel); -} - -int Clamp(const double& x, const double& min, const double& max) { - if (x < min) - return min; - else if (x > max) - return max; - else - return x; -} - -void AquireImage(ImagePICT* image) -{ - image->storage_class = DirectClass; - image->colorspace = sRGBColorspace; - image->gamma=1.000/2.200; - image->chromaticity.red_primary.x=0.6400; - image->chromaticity.red_primary.y=0.3300; - image->chromaticity.red_primary.z=0.0300; - image->chromaticity.green_primary.x=0.3000; - image->chromaticity.green_primary.y=0.6000; - image->chromaticity.green_primary.z=0.1000; - image->chromaticity.blue_primary.x=0.1500; - image->chromaticity.blue_primary.y=0.0600; - image->chromaticity.blue_primary.z=0.7900; - image->chromaticity.white_point.x=0.3127; - image->chromaticity.white_point.y=0.3290; - image->chromaticity.white_point.z=0.3583; - image->m_pctVersion = 0; - image->m_nHeight = 0; - image->m_nWidth = 0; - image->m_ndepth = 8; - image->colors = 0; - image->artifacts = nullptr; - image->fuzz = 0.0; - image->resolutionX = 0.0; - image->resolutionY = 0.0; - image->type = UndefinedType; - GetPixelInfoRGBA(BackgroundColorRGBA, &image->background_color); - image->alpha_trait = UndefinedPixelTrait; - image->ppixels = nullptr; - image->m_nPixelsSize = 0; - image->colormap = nullptr; - image->channel_map = AcquirePixelChannelMap(); - image->mask_trait = UndefinedPixelTrait; - image->taint = 0; - image->number_channels = 4; -} - -size_t GetSize(FILE* file) -{ - struct stat st; - - long long file_discription = _fileno(file); - if (fstat(file_discription, &st) == 0) - return st.st_size; - - return 0; -} - -void Skip(FILE* file, size_t size) -{ - if(!file) - return; - fread(nullptr, 1, size, file); -} - -int Read(FILE* file, const int length, void* data) -{ - if (!file) return 0; - if (data == nullptr) return 0; - unsigned char* q; - q = (unsigned char*) data; - return fread(q, 1, length, file); -} - -int ReadByte(FILE* file) -{ - return getc(file); -} - -const void *ReadBlobStream(FILE* file, const size_t length, void *data, long long* count) -{ - *count = Read(file, length, (unsigned char*) data); - return data; -} - -unsigned short ReadShortValue(FILE* file) -{ - unsigned char buffer[2]; - long long count; - *buffer='\0'; - - const unsigned char* p = (const unsigned char*) ReadBlobStream(file, 2, buffer, &count); - if (count != 2) - return EOF; - - unsigned short value = (unsigned short) ((*p++) << 8); - value |= (unsigned short) (*p++); - return (unsigned short) (value & 0xffff); -} - -signed short ReadSignedShortValue(FILE* file) -{ - union - { - unsigned short unsigned_value; - signed short signed_value; - } Quantum; - - Quantum.unsigned_value = ReadShortValue(file); - return (Quantum.signed_value); -} - -unsigned int ReadLongValue(FILE* file) -{ - unsigned char buffer[4]; - *buffer='\0'; - int count = Read(file, 4, buffer); - - if (count != 4) - return EOF; - - const unsigned char* p = (const unsigned char*) buffer; - - unsigned int value = (unsigned int) (*p++) << 24; - value |= (unsigned int) (*p++) << 16; - value |= (unsigned int) (*p++) << 8; - value |= (unsigned int) (*p++); - - return value; -} - -bool ReadRectangle(FILE* file, PICTrectangle *frame) -{ - frame->top = (short) ReadShortValue(file); - frame->left = (short) ReadShortValue(file); - frame->bottom = (short) ReadShortValue(file); - frame->right = (short) ReadShortValue(file); - - if (feof(file) != 0) - return false; - - if (frame->bottom < frame->top) - return false; - - if (frame->right < frame->left) - return false; - - return true; -} - -bool ReadPixmap(FILE* file,PICTPixmap *pixmap) -{ - pixmap->version = (short) ReadShortValue(file); - pixmap->pack_type = (short) ReadShortValue(file); - pixmap->pack_size = ReadLongValue(file); - pixmap->horizontal_resolution = 1UL * ReadShortValue(file); - (void) ReadShortValue(file); - pixmap->vertical_resolution = 1UL * ReadShortValue(file); - (void) ReadShortValue(file); - pixmap->pixel_type = (short) ReadShortValue(file); - pixmap->bits_per_pixel = (short) ReadShortValue(file); - pixmap->component_count = (short) ReadShortValue(file); - pixmap->component_size = (short) ReadShortValue(file); - pixmap->plane_bytes = ReadLongValue(file); - pixmap->table = ReadLongValue(file); - pixmap->reserved = ReadLongValue(file); - - if ((feof(file) != 0) || (pixmap->bits_per_pixel <= 0) || (pixmap->bits_per_pixel > 32) || (pixmap->component_count <= 0) || - (pixmap->component_count > 4) || (pixmap->component_size <= 0)) - return false; - - return true; -} - -void DestroySplayTree(SplayTreeInfo *splay_tree) -{ - NodeInfo *node, *active, *pend; - - if (splay_tree->root != nullptr) - { - for (pend=splay_tree->root; pend != nullptr; ) - { - active=pend; - for (pend = nullptr; active != nullptr; ) - { - if (active->left != nullptr) - { - free(active->left->key); - free(active->left->value); - pend=active->left; - } - if (active->right != nullptr) - { - free(active->right->key); - free(active->right->value); - pend = active->right; - } - node = active; - active = (NodeInfo *) node->key; - free(node); - } - } - } - - free(splay_tree); -} - -SplayTreeInfo *NewSplayTree(int (*compare)(const void *,const void *)) -{ - SplayTreeInfo *splay_tree = (SplayTreeInfo *) malloc(sizeof(*splay_tree)); - - (void) memset(splay_tree,0,sizeof(*splay_tree)); - splay_tree->root = nullptr; - splay_tree->compare = compare; - splay_tree->balance = 0; - splay_tree->key = nullptr; - splay_tree->next = nullptr; - splay_tree->nodes = 0; - splay_tree->signature = 0xabacadabUL; - - return splay_tree; -} - -inline void *GetFirstSplayTreeNode(SplayTreeInfo *splay_tree) -{ - NodeInfo *node = splay_tree->root; - if (splay_tree->root == nullptr) - return nullptr; - while (node->left != nullptr) - node = node->left; - return node->key; -} - -NodeInfo *Splay(SplayTreeInfo *splay_tree,const size_t depth,const void *key,NodeInfo **node,NodeInfo **parent,NodeInfo **grandparent) -{ - int compare; - NodeInfo **next; - NodeInfo *n, *p; - n = *node; - if (n == nullptr) - { - if (parent != nullptr) - return *parent; - else - return nullptr; - } - if (splay_tree->compare != (int (*)(const void *,const void *)) nullptr) - compare=splay_tree->compare(n->key,key); - else - compare=(n->key > key) ? 1 : ((n->key < key) ? -1 : 0); - - next = nullptr; - - if (compare > 0) - next = (&n->left); - else if (compare < 0) - next = (&n->right); - - if (next != nullptr) - { - if (depth >= 1024) - { - splay_tree->balance = 1; - return n; - } - - n = Splay(splay_tree,depth+1,key,next,node,parent); - if ((n != *node) || (splay_tree->balance != 0)) - return n; - } - if (parent == nullptr) - return n; - if (grandparent == nullptr) - { - if (n == (*parent)->left) - { - *node=n->right; - n->right=(*parent); - } - else - { - *node=n->left; - n->left=(*parent); - } - *parent=n; - return n; - } - if ((n == (*parent)->left) && (*parent == (*grandparent)->left)) - { - p = (*parent); - (*grandparent)->left = p->right; - p->right = (*grandparent); - p->left = n->right; - n->right = p; - *grandparent = n; - - return n; - } - if ((n == (*parent)->right) && (*parent == (*grandparent)->right)) - { - p = (*parent); - (*grandparent)->right = p->left; - p->left = (*grandparent); - p->right = n->left; - n->left = p; - *grandparent = n; - - return n; - } - if (n == (*parent)->left) - { - (*parent)->left = n->right; - n->right = (*parent); - (*grandparent)->right = n->left; - n->left = (*grandparent); - *grandparent = n; - - return n; - } - (*parent)->right = n->left; - n->left = (*parent); - (*grandparent)->left = n->right; - n->right = (*grandparent); - *grandparent = n; - - return n; -} - -bool IterateOverSplayTree(SplayTreeInfo *splay_tree, int (*method)(NodeInfo *,const void *), const void *value) -{ - typedef enum - { - LeftTransition, - RightTransition, - DownTransition, - UpTransition - } TransitionType; - - bool status = false; - - if (splay_tree->root == nullptr) - return false; - - NodeInfo** nodes = (NodeInfo **) malloc((size_t) splay_tree->nodes * sizeof(*nodes)); - unsigned char* transitions = (unsigned char *) malloc((size_t) splay_tree->nodes * sizeof(*transitions)); - if ((nodes == nullptr) || (transitions == nullptr)) - return false; - - int final_transition = 0; - nodes[0] = splay_tree->root; - transitions[0] = (unsigned char) LeftTransition; - for (size_t i = 0; final_transition == 0; ) - { - NodeInfo* node = nodes[i]; - TransitionType transition = (TransitionType) transitions[i]; - switch (transition) - { - case LeftTransition: - { - transitions[i] = (unsigned char) DownTransition; - if (node->left == nullptr) - break; - i++; - nodes[i] = node->left; - transitions[i] = (unsigned char) LeftTransition; - break; - } - case RightTransition: - { - transitions[i] = (unsigned char) UpTransition; - if (node->right == nullptr) - break; - i++; - nodes[i] = node->right; - transitions[i] = (unsigned char) LeftTransition; - break; - } - case DownTransition: - default: - { - transitions[i] = (unsigned char) RightTransition; - status = (*method)(node,value); - if (status != 0) - final_transition = 1; - break; - } - case UpTransition: - { - if (i == 0) - { - final_transition = 1; - break; - } - i--; - break; - } - } - } - - free(nodes); - free(transitions); - return status; -} - -NodeInfo *LinkSplayTreeNodes(NodeInfo **nodes,const size_t low,const size_t high) -{ - size_t bisect = low + (high - low) / 2; - NodeInfo* node = nodes[bisect]; - - if ((low + 1) > bisect) - node->left = nullptr; - else - node->left=LinkSplayTreeNodes(nodes, low, bisect - 1); - - if ((bisect + 1) > high) - node->right = nullptr; - else - node->right = LinkSplayTreeNodes(nodes, bisect + 1, high); - - return node; -} - -inline int SplayTreeToNodeArray(NodeInfo *node, const void *nodes) -{ - const NodeInfo*** p=(const NodeInfo ***) nodes; - *(*p)=node; - (*p)++; - return 0; -} - -void BalanceSplayTree(SplayTreeInfo *splay_tree) -{ - if (splay_tree->nodes <= 2) - { - splay_tree->balance=0; - return; - } - - NodeInfo** nodes = (NodeInfo **) malloc((size_t) splay_tree->nodes * sizeof(*nodes)); - - if (nodes == nullptr) - return; - - NodeInfo** node = nodes; - IterateOverSplayTree(splay_tree, SplayTreeToNodeArray, (const void *)&node); - splay_tree->root = LinkSplayTreeNodes(nodes, 0, splay_tree->nodes - 1); - splay_tree->balance = 0; - free(nodes); -} - -void SplaySplayTree(SplayTreeInfo *splay_tree,const void *key) -{ - if (splay_tree->root == nullptr) - return; - if (splay_tree->key != nullptr) - { - int compare; - - if (splay_tree->compare != (int (*)(const void *,const void *)) nullptr) - compare=splay_tree->compare(splay_tree->root->key,key); - else - compare=(splay_tree->key > key) ? 1 : ((splay_tree->key < key) ? -1 : 0); - if (compare == 0) - return; - } - Splay(splay_tree, 0UL, key, &splay_tree->root, nullptr, nullptr); - if (splay_tree->balance != 0) - { - BalanceSplayTree(splay_tree); - Splay(splay_tree, 0UL, key, &splay_tree->root, nullptr, nullptr); - if (splay_tree->balance != 0) - return; - } - splay_tree->key = (void *) key; -} - -bool AddValueToSplayTree(SplayTreeInfo *splay_tree,const void *key,const void *value) -{ - int compare = 0; - - SplaySplayTree(splay_tree,key); - - if (splay_tree->root != (NodeInfo *) nullptr) - { - if (splay_tree->compare != (int (*)(const void *,const void *)) nullptr) - compare=splay_tree->compare(splay_tree->root->key,key); - else - compare=(splay_tree->root->key > key) ? 1 : ((splay_tree->root->key < key) ? -1 : 0); - if (compare == 0) - { - splay_tree->root->key=(void *) key; - splay_tree->root->value=(void *) value; - return true; - } - } - - NodeInfo* node = (NodeInfo *) malloc(sizeof(*node)); - - if (node == nullptr) - return false; - - node->key = (void *) key; - node->value = (void *) value; - if (splay_tree->root == nullptr) - { - node->left = nullptr; - node->right = nullptr; - } - else if (compare < 0) - { - node->left = splay_tree->root; - node->right = node->left->right; - node->left->right = nullptr; - } - else - { - node->right = splay_tree->root; - node->left = node->right->left; - node->right->left = nullptr; - } - splay_tree->root = node; - splay_tree->key = nullptr; - splay_tree->nodes++; - return true; -} - -SplayTreeInfo *CloneSplayTree(SplayTreeInfo *splay_tree, void *(*clone_key)(void *), void *(*clone_value)(void *)) -{ - NodeInfo *node; - - SplayTreeInfo* clone_tree=NewSplayTree(splay_tree->compare); - if (splay_tree->root == nullptr) - { - return(clone_tree); - } - - NodeInfo* next = (NodeInfo *) GetFirstSplayTreeNode(splay_tree); - while (next != (NodeInfo *) nullptr) - { - SplaySplayTree(splay_tree,next); - AddValueToSplayTree(clone_tree, clone_key(splay_tree->root->key), clone_value(splay_tree->root->value)); - next = nullptr; - node = splay_tree->root->right; - if (node != nullptr) - { - while (node->left != nullptr) - node = node->left; - next = (NodeInfo *) node->key; - } - } - return clone_tree; -} - -const void *GetValueFromSplayTree(SplayTreeInfo *splay_tree, const void *key) -{ - int compare; - - if (splay_tree->root == nullptr) - return nullptr; - - SplaySplayTree(splay_tree,key); - if (splay_tree->compare != (int (*)(const void *,const void *)) nullptr) - compare = splay_tree->compare(splay_tree->root->key,key); - else - compare = (splay_tree->root->key > key) ? 1 : ((splay_tree->root->key < key) ? -1 : 0); - if (compare != 0) - return nullptr; - - return splay_tree->root->value; -} - -const void *GetRootValueFromSplayTree(SplayTreeInfo *splay_tree) -{ - const void* value = nullptr; - if (splay_tree->root != nullptr) - value = splay_tree->root->value; - - return value; -} - -const char *GetImageArtifact(const ImagePICT *image,const char *artifact) -{ - const char* p = nullptr; - if (image->artifacts != nullptr) - { - if (artifact == nullptr) - return (const char *) GetRootValueFromSplayTree((SplayTreeInfo *) image->artifacts); - p=(const char *) GetValueFromSplayTree((SplayTreeInfo *) image->artifacts, artifact); - if (p != nullptr) - return p; - } - - return p; -} - -void DestroyImage(ImagePICT *image) -{ - if (image->ppixels != nullptr) - free(image->ppixels); - if (image->channel_map != nullptr) - free(image->channel_map); - delete image; -} - -ImagePICT* CloneImage(const ImagePICT* image, const size_t colums, const size_t rows) -{ - if (image == nullptr) - return nullptr; - - ImagePICT* clone_image = new ImagePICT; - AquireImage(clone_image); - - clone_image->storage_class = image->storage_class; - clone_image->fuzz = image->fuzz; - clone_image->colorspace = image->colorspace; - clone_image->chromaticity.blue_primary = image->chromaticity.blue_primary; - clone_image->chromaticity.green_primary = image->chromaticity.green_primary; - clone_image->chromaticity.red_primary = image->chromaticity.red_primary; - clone_image->chromaticity.white_point = image->chromaticity.white_point; - clone_image->gamma = image->gamma; - clone_image->m_nHeight = image->m_nHeight; - - if (rows != 0) - clone_image->m_nHeight = rows; - clone_image->m_nWidth = image->m_nWidth; - if (colums != 0) - clone_image->m_nWidth = colums; - - clone_image->number_channels = image->number_channels; - clone_image->m_nPixelsSize = image->m_nPixelsSize; - clone_image->ppixels = nullptr; - clone_image->resolutionX = image->resolutionX; - clone_image->resolutionY = image->resolutionY; - clone_image->alpha_trait = image->alpha_trait; - clone_image->background_color.blue = image->background_color.blue; - clone_image->background_color.green = image->background_color.green; - clone_image->background_color.red = image->background_color.red; - clone_image->colors = image->colors; - - if (image->colormap != nullptr) - { - clone_image->colormap = (PixelInfo*) malloc((clone_image->colors + 1) * sizeof(*clone_image->colormap)); - memcpy(clone_image->colormap, image->colormap, clone_image->colors * sizeof(*clone_image->colormap)); - } - if (image->channel_map != nullptr) - { - clone_image->channel_map = (PixelChannelMap*) malloc(65 * sizeof (image->channel_map)); - memcpy(clone_image->channel_map, image->channel_map, 65 * sizeof (image->channel_map)); - } - - if (image->artifacts != nullptr) - clone_image->artifacts = CloneSplayTree(image->artifacts, (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo); - - clone_image->mask_trait = image->mask_trait; - clone_image->taint = image->taint; - - return clone_image; -} - -inline unsigned char GetPixelReadMask(const ImagePICT *image, const unsigned char *pixel) -{ - if (image->channel_map[ReadMaskPixelChannel].traits == UndefinedPixelTrait) - return 255; - return pixel[image->channel_map[ReadMaskPixelChannel].offset]; -} - -bool CompositeImage(ImagePICT *image, const ImagePICT *composite, const int clip_to_self, const long long& x_offset, const long long& y_offset) -{ - GeometryInfo geometry_info; - - bool status = false; - - image->storage_class = DirectClass; - - if (image->ppixels == (unsigned char*) nullptr) - return status; - - ImagePICT* source_image = CloneImage(composite, 0, 0); - if (!AquirePixelsMemory(source_image)) - { - DestroyImage(source_image); - return status; - } - - memcpy(source_image->ppixels, composite->ppixels, source_image->m_nPixelsSize); - if (source_image == nullptr) - return status; - - SetImageColorspace(source_image,image->colorspace); - ImagePICT* canvas_image = nullptr; - int clamp = 1; - const char* value = GetImageArtifact(image, "compose:clamp"); - if (value != nullptr) - clamp=IsStringTrue(value); - - value = GetImageArtifact(image, "compose:sync"); - if (value != nullptr) - memset(&geometry_info, 0, sizeof(geometry_info)); - - image->channel_map[RedPixelChannel].traits = UpdatePixelTrait; - image->channel_map[GreenPixelChannel].traits = UpdatePixelTrait; - image->channel_map[BluePixelChannel].traits = UpdatePixelTrait; - image->channel_map[AlphaPixelChannel].traits = UpdatePixelTrait; - - source_image->channel_map[RedPixelChannel].traits = CopyPixelTrait; - source_image->channel_map[GreenPixelChannel].traits = CopyPixelTrait; - source_image->channel_map[BluePixelChannel].traits = CopyPixelTrait; - source_image->channel_map[AlphaPixelChannel].traits = CopyPixelTrait; - - if (!((x_offset < 0) || (y_offset < 0)) && !((x_offset+(long long) source_image->m_nWidth) > (long long) image->m_nWidth) && !((y_offset+(long long) source_image->m_nHeight) > (long long) image->m_nHeight)) - { - if ((source_image->alpha_trait == UndefinedPixelTrait) && (image->alpha_trait != UndefinedPixelTrait)) - SetImageAlpha(source_image, (const unsigned char) 255); - status = true; - - for (long long y = 0; y < (long long) source_image->m_nHeight; y++) - { - if (!status) - continue; - const unsigned char* p = GetPixels(source_image, 0, y, source_image->m_nWidth, 1); - unsigned char* q = GetPixels(image, x_offset, y + y_offset, source_image->m_nWidth, 1); - if ((p == nullptr) || (q == nullptr)) - { - status = false; - continue; - } - for (long long x = 0; x < (long long) source_image->m_nWidth; x++) - { - if (GetPixelReadMask(source_image, p) <= (255.0 / 2.0)) - { - p += source_image->number_channels; - q += image->number_channels; - continue; - } - for (long long i=0; i < source_image->number_channels; i++) - { - PixelChannel channel = GetPixelChannelChannel(source_image,i); - PixelTrait source_traits = GetPixelChannelTraits(source_image, channel); - PixelTrait traits = GetPixelChannelTraits(image,channel); - if ((source_traits == UndefinedPixelTrait) || (traits == UndefinedPixelTrait)) - continue; - SetPixelChannel(image, channel, p[i], q); - } - p += source_image->number_channels; - q += image->number_channels; - } - } - DestroyImage(source_image); - return status; - } - - status = true; - for (long long y = 0; y < (long long) image->m_nHeight; y++) - { - if (!status) - continue; - - if (clip_to_self != 0) - { - if (y < y_offset) - continue; - if ((y-(double) y_offset) >= (double) source_image->m_nHeight) - continue; - } - - const unsigned char* pixels = nullptr; - const unsigned char* p = nullptr; - if ((y >= y_offset) && ((y-(double) y_offset) < (double) source_image->m_nHeight)) - { - p = GetPixels(source_image, 0, y - y_offset, source_image->m_nWidth, 1); - if (p == nullptr) - { - status = false; - continue; - } - pixels = p; - if (x_offset < 0) - p -= x_offset*source_image->number_channels; - } - - unsigned char* q = GetPixels(image, 0, y, image->m_nWidth, 1); - if (q == nullptr) - { - status = false; - continue; - } - - PixelInfo canvas_pixel, source_pixel; - GetPixelInfo(image, &canvas_pixel); - GetPixelInfo(source_image, &source_pixel); - - for (long long x = 0; x < (long long) image->m_nWidth; x++) - { - if (clip_to_self != 0) - { - if (x < x_offset) - { - q += image->number_channels; - continue; - } - if ((x - (double) x_offset) >= (double) source_image->m_nWidth) - break; - } - - if ((pixels == nullptr) || (x < x_offset) || ((x - (double) x_offset) >= (double) source_image->m_nWidth)) - { - for (long long i = 0; i < image->number_channels; i++) - { - double pixel = 0; - - PixelChannel channel = GetPixelChannelChannel(image, i); - PixelTrait traits = GetPixelChannelTraits(image, channel); - PixelTrait source_traits = GetPixelChannelTraits(source_image, channel); - if ((traits == UndefinedPixelTrait) || (source_traits == UndefinedPixelTrait)) - continue; - - if (channel == AlphaPixelChannel) - pixel = TransparentAlpha; - else - pixel=0; - - q[i]=clamp != 0 ? ClampPixel(pixel) : ClampToQuantum(pixel); - } - - q += image->number_channels; - continue; - } - - double Sa = (1.0/255.0)* GetPixelAlpha(source_image,p); - Sa = Sa == 0 ? 1 : Sa; - - for (long long i = 0; i < image->number_channels; i++) - { - double pixel = 0.0; - - PixelChannel channel = GetPixelChannelChannel(image, i); - PixelTrait traits = GetPixelChannelTraits(image, channel); - PixelTrait source_traits = GetPixelChannelTraits(source_image, channel); - - if (traits == UndefinedPixelTrait) - continue; - - if ((channel == AlphaPixelChannel) && ((traits & UpdatePixelTrait) != 0)) - { - pixel = 255.0 * Sa; - - q[i]=clamp != 0 ? ClampPixel(pixel) : - ClampToQuantum(pixel); - continue; - } - - if (source_traits == UndefinedPixelTrait) - continue; - - double Sc = GetPixelChannel(source_image, channel, p); - double Dc = q[i]; - - if ((traits & CopyPixelTrait) != 0) - { - q[i]=ClampToQuantum(Dc); - continue; - } - - double Sca = (1.0/255.0) * Sa * Sc; - pixel = Dc; - pixel = 255.0 * Sca; - q[i] = clamp != 0 ? ClampPixel(pixel) : ClampToQuantum(pixel); - } - p += source_image->number_channels; - size_t channels = source_image->number_channels; - - if (p >= (pixels+channels*source_image->m_nWidth)) - p=pixels; - - q += image->number_channels; - } - } - if (canvas_image != nullptr) - DestroyImage(canvas_image); - else - DestroyImage(source_image); - - return status; -} - -bool DecodeHeader(FILE* hFile, ImagePICT* image) -{ - unsigned char header[4]; - - unsigned char skip[1]; - - int c; - - PICTrectangle frame; - - Read(hFile, 4, header); - - if (!((header[0] == 0x50) && (header[1] == 0x49) && (header[2] == 0x43) && (header[3] == 0x54 ))) - { - frame.top = (short) ((header[2] << 8) | header[3]); - frame.left = (short) ReadShortValue(hFile); - frame.bottom = (short) ReadShortValue(hFile); - frame.right = (short) ReadShortValue(hFile); - - Read(hFile, 1, skip); - c = ReadByte(hFile); - if (c != 0x11) - { - fseek(hFile, 512, 0); - ReadShortValue(hFile); - if (ReadRectangle(hFile, &frame) == 0) - return false; - - Read(hFile, 1, skip); - c = ReadByte(hFile); - - if (c == 0x11) - { - int version = ReadByte(hFile); - if (version == 2) - { - int version2 = ReadByte(hFile); - if (version2 != 0xff) - return false; - - image->m_pctVersion = 2; - - if ((frame.left < 0) || (frame.right < 0) || (frame.top < 0) || (frame.bottom < 0) || (frame.left >= frame.right) || (frame.top >= frame.bottom)) - return false; - - image->m_nWidth = (size_t) (frame.right-frame.left); - image->m_nHeight = (size_t) (frame.bottom-frame.top); - - return true; - } - else if (version == 1) - { - image->m_pctVersion = 1; - if ((frame.left < 0) || (frame.right < 0) || (frame.top < 0) || (frame.bottom < 0) || (frame.left >= frame.right) || (frame.top >= frame.bottom)) - return false; - - image->m_nWidth = (size_t) (frame.right-frame.left); - image->m_nHeight = (size_t) (frame.bottom-frame.top); - - return true; - } - else - return 0; - } - else - return 0; - } - } - - int version = ReadByte(hFile); - if (version == 2) - { - int version2 = ReadByte(hFile); - if (version2 != 0xff) - return false; - image->m_pctVersion = 2; - - if ((frame.left < 0) || (frame.right < 0) || (frame.top < 0) || (frame.bottom < 0) || (frame.left >= frame.right) || (frame.top >= frame.bottom)) - return false; - - image->m_nWidth = (size_t) (frame.right - frame.left); - image->m_nHeight = (size_t) (frame.bottom-frame.top); - } - else - { - image->m_pctVersion = 1; - image->m_nWidth = (size_t) (frame.right - frame.left); - image->m_nHeight = (size_t) (frame.bottom - frame.top); - } - - return true; -} - -const unsigned char *UnpackScanline(const unsigned char *pixels, const unsigned int bits_per_pixel, unsigned char* scanline, size_t *bytes_per_line) -{ - const unsigned char* p = pixels; - unsigned char* q = scanline; - switch (bits_per_pixel) - { - case 8: - case 16: - case 32: - return pixels; - case 4: - { - for (long long i = 0; i < (long long) *bytes_per_line; i++) - { - *q++ = (*p >> 4) & 0xff; - *q++ = (*p & 15); - p++; - } - *bytes_per_line *= 2; - break; - } - case 2: - { - for (long long i = 0; i < (long long) *bytes_per_line; i++) - { - *q++ = (*p >> 6) & 0x03; - *q++ = (*p >> 4) & 0x03; - *q++ = (*p >> 2) & 0x03; - *q++ = (*p & 3); - p++; - } - *bytes_per_line *= 4; - break; - } - case 1: - { - for (long long i = 0; i < (long long) *bytes_per_line; i++) - { - *q++ = (*p >> 7) & 0x01; - *q++ = (*p >> 6) & 0x01; - *q++ = (*p >> 5) & 0x01; - *q++ = (*p >> 4) & 0x01; - *q++ = (*p >> 3) & 0x01; - *q++ = (*p >> 2) & 0x01; - *q++ = (*p >> 1) & 0x01; - *q++ = (*p & 0x01); - p++; - } - *bytes_per_line *= 8; - break; - } - default: - break; - } - return scanline; -} - -unsigned char *DecodeImage(FILE *blob,ImagePICT *image, size_t bytes_per_line, const unsigned int bits_per_pixel, size_t *extent) -{ - bool status = true; - - if (bits_per_pixel <= 8) - bytes_per_line &= 0x7fff; - - size_t width = image->m_nWidth; - size_t bytes_per_pixel = 1; - - if (bits_per_pixel == 16) - { - bytes_per_pixel = 2; - width *= 2; - } - else if (bits_per_pixel == 32) - width*=image->alpha_trait ? 4 : 3; - - if (bytes_per_line == 0) - bytes_per_line=width; - - size_t row_bytes = (size_t) (image->m_nWidth | 0x8000); - - if (image->storage_class == DirectClass) - row_bytes = (size_t) ((4*image->m_nWidth) | 0x8000); - - unsigned char* pixels = (unsigned char *) malloc(image->m_nHeight*row_bytes * sizeof(*pixels)); - if (pixels == nullptr) - return nullptr; - - *extent=row_bytes*image->m_nHeight * sizeof(*pixels); - memset(pixels, 0, *extent); - unsigned char* scanline = (unsigned char *) malloc(row_bytes * 2 * sizeof(*scanline)); - - if (scanline == nullptr) - { - free(pixels); - return nullptr; - } - - memset(scanline, 0, 2 * row_bytes * sizeof(*scanline)); - - unsigned char unpack_buffer[8*256]; - memset(unpack_buffer, 0, sizeof(unpack_buffer)); - - if (bytes_per_line < 8) - { - for (long long y = 0; y < (long long) image->m_nHeight; y++) - { - unsigned char* q = pixels + y * (long long) width * image->number_channels; - size_t number_pixels = bytes_per_line; - long long count = Read(blob, (size_t) number_pixels,scanline); - if (count != (long long) number_pixels) - { - status = false; - break; - } - const unsigned char* p = UnpackScanline(scanline, bits_per_pixel, unpack_buffer, &number_pixels); - if ((q+number_pixels) > (pixels+(*extent))) - { - status = false; - break; - } - memcpy(q, p, (size_t) number_pixels); - } - free(scanline); - if (!status) - free(pixels); - return pixels; - } - - for (long long y = 0; y < (long long) image->m_nHeight; y++) - { - unsigned char* q = pixels + y * (long long) width; - - size_t scanline_length; - if (bytes_per_line > 250) - scanline_length = ReadShortValue(blob); - else - scanline_length = (size_t) ReadByte(blob); - - if ((scanline_length >= row_bytes) || (scanline_length == 0)) - { - status = false; - break; - } - - long long count = Read(blob,scanline_length,scanline); - if (count != (long long) scanline_length) - { - status = false; - break; - } - - for (long long j = 0; j < (long long) scanline_length; ) - if ((scanline[j] & 0x80) == 0) - { - size_t length = (size_t) ((scanline[j] & 0xff) + 1); - size_t number_pixels = length * bytes_per_pixel; - const unsigned char* p = UnpackScanline(scanline + j + 1, bits_per_pixel, unpack_buffer, &number_pixels); - if ((size_t) (q-pixels+(long long) number_pixels) <= *extent) - memcpy(q,p,(size_t) number_pixels); - q += number_pixels; - j += (long long) (length*bytes_per_pixel+1); - } - else - { - size_t length = (size_t) (((scanline[j] ^ 0xff) & 0xff)+2); - size_t number_pixels = bytes_per_pixel; - const unsigned char* p = UnpackScanline(scanline + j + 1, bits_per_pixel, unpack_buffer, &number_pixels); - for (long long i = 0; i < (long long) length; i++) - { - if ((size_t) (q - pixels + (long long) number_pixels) <= *extent) - memcpy(q, p, (size_t) number_pixels); - q += number_pixels; - } - j += (long long) bytes_per_pixel + 1; - } - } - free(scanline); - - if (!status) - { - free(pixels); - pixels = nullptr; - } - - return pixels; -} - -void ReadPolygon(FILE* file, Polygon& poly) -{ - size_t size = static_cast(ReadShortValue(file)); - ReadShortValue(file); - ReadShortValue(file); - ReadShortValue(file); - ReadShortValue(file); - - size = (size - 10) / 4; - const size_t max_possible_points = GetSize(file) - ftell(file); - if (size > max_possible_points) - size = max_possible_points; - - poly.Size = size; - poly.Points = (Point*) malloc(size * sizeof(Point)); - - for (size_t i = 0; i < size; i++) - { - short y = ReadShortValue(file); - short x = ReadShortValue(file); - poly.Points[i] = Point(x, y); - if (feof(file)) - { - poly.Size = i; - break; - } - } -} - -PICTrectangle ContractRect(const PICTrectangle& rect, int penSize, bool isFrame) -{ - if (!isFrame) - return rect; - - if (penSize * 2 > rect.right - rect.left) - penSize = (rect.right - rect.left + 1) / 2; - if (penSize * 2 > rect.bottom - rect.top) - penSize = (rect.bottom - rect.top + 1) / 2; - - const long X[2] = {rect.left + penSize / 2, rect.right - (penSize + 1) / 2}; - const long Y[2] = {rect.top + penSize / 2, rect.bottom - (penSize + 1) / 2}; - - return PICTrectangle(Y[0], X[0], Y[1], X[1]); -} - -void DrawPolygon(NSGraphics::IGraphicsRenderer* renderer, const Polygon& poly, size_t penWidth, size_t penHeight, bool isFrame) -{ - size_t pen_size = (penWidth + penHeight) / 2; - long deca1TL[2] = {0, 0}, deca1BR[2] = {static_cast(penWidth), static_cast(penHeight)}; - - if (isFrame) - { - deca1TL[0] += pen_size / 2; - deca1TL[1] += pen_size / 2; - deca1BR[0] -= (pen_size + 1) / 2; - deca1BR[1] -= (pen_size + 1) / 2; - } - else - deca1BR[0] = deca1BR[1] = 0; - - size_t points_count = poly.Size; - if (points_count < 1) - return; - - double bary[2] = {0.0, 0.0}; - for (int i = 0; i < points_count; i++) - { - const Point& pt = poly.Points[i]; - bary[0] += double(pt.X); - bary[1] += double(pt.Y); - } - bary[0] /= double(points_count); - bary[1] /= double(points_count); - - - Polygon B2Dpoly; - B2Dpoly.Points = (Point*) malloc(points_count * sizeof(Point)); - for (int i = 0; i < points_count; i++) - { - const Point& pt = poly.Points[i]; - double x = (double(pt.X) < bary[0]) ? pt.X + deca1TL[0] : pt.X + deca1BR[0]; - double y = (double(pt.Y) < bary[1]) ? pt.Y + deca1TL[1] : pt.Y + deca1BR[1]; - B2Dpoly.Points[i] = Point(x, y); - } - - renderer->PathCommandStart(); - renderer->BeginCommand(c_nPathType); - renderer->PathCommandMoveTo(B2Dpoly.Points[0].X, B2Dpoly.Points[0].Y); - - for (int i = 1; i < points_count; i++) - renderer->PathCommandLineTo(B2Dpoly.Points[i].X, B2Dpoly.Points[i].Y); - - - if (!isFrame) - renderer->Fill(); - - renderer->DrawPath(c_nStroke); - renderer->EndCommand(c_nPathType); - renderer->PathCommandEnd(); -} - -void DrawLine(NSGraphics::IGraphicsRenderer* renderer, const Point& p1, const Point& p2, size_t penWidth, size_t penHeight) -{ - long dir[2] = {p2.X - p1.X, p2.Y - p1.Y}; - long X[2] = {p1.X, p2.X}; - long Y[2] = {p1.Y, p2.Y}; - - if (dir[0] == 0) - { - if (X[0] < X[1]) - X[1] += penWidth; - else - X[0] += penWidth; - Y[1] += penHeight; - - Polygon poly; - poly.Size = 5; - poly.Points = (Point*) malloc(5 * sizeof(Point)); - poly.Points[0] = Point(X[0], Y[0]); - poly.Points[1] = Point(X[1], Y[0]); - poly.Points[2] = Point(X[1], Y[1]); - poly.Points[3] = Point(X[0], Y[1]); - poly.Points[4] = Point(X[0], Y[0]); - DrawPolygon(renderer, poly, penWidth, penHeight, false); - } - else if (dir[1] == 0) - { - if (Y[0] < Y[1]) - Y[1] += penHeight; - else - Y[0] += penHeight; - X[1] += penWidth; - - Polygon poly; - poly.Size = 5; - poly.Points = (Point*) malloc(5 * sizeof(Point)); - poly.Points[0] = Point(X[0], Y[0]); - poly.Points[1] = Point(X[1], Y[0]); - poly.Points[2] = Point(X[1], Y[1]); - poly.Points[3] = Point(X[0], Y[1]); - poly.Points[4] = Point(X[0], Y[0]); - DrawPolygon(renderer, poly, penWidth, penHeight, false); - } - else if (dir[0] * dir[0] + dir[1] * dir[1] < 25) - { - long orig_pt[4][2] = {{p1.X, p1.Y}, - {p1.X + static_cast(penWidth), p1.Y}, - {p1.X + static_cast(penWidth), p1.Y + static_cast(penHeight)}, - {p1.X, p1.Y + static_cast(penHeight)}}; - int orig_avoid = dir[0] > 0 ? (dir[1] > 0 ? 2 : 1) : (dir[1] > 0 ? 3 : 0); - long dest_pt[4][2] = {{p2.X, p2.Y}, - {p2.X + static_cast(penWidth), p2.Y}, - {p2.X + static_cast(penWidth), p2.Y + static_cast(penHeight)}, - {p2.X, p2.Y + static_cast(penHeight)}}; - Polygon poly; - poly.Size = 7; - poly.Points = (Point*) malloc(7 * sizeof(Point)); - for (int w = 1; w < 4; w++) - { - int wh = (w + orig_avoid) % 4; - poly.Points[w - 1] = Point(orig_pt[wh][0], orig_pt[wh][1]); - } - - for (int w = 3; w < 6; w++) - { - int wh = (w + orig_avoid) % 4; - poly.Points[w] = Point(dest_pt[wh][0], dest_pt[wh][1]); - } - - int wh = (orig_avoid + 1) % 4; - poly.Points[6] = Point(orig_pt[wh][0], orig_pt[wh][1]); - DrawPolygon(renderer, poly, penWidth, penHeight, false); - } - else - { - long decal[2] = {static_cast(penWidth / 2), static_cast(penHeight / 2)}; - Polygon poly; - poly.Size = 2; - poly.Points = (Point*) malloc(2 + sizeof(Point)); - poly.Points[0] = Point(p1.X + decal[0], p1.Y + decal[1]); - poly.Points[1] = Point(p2.X + decal[0], p2.Y + decal[1]); - DrawPolygon(renderer, poly, penWidth, penHeight, true); - } -} - -void DrawRect(NSGraphics::IGraphicsRenderer* renderer, const PICTrectangle& rect, size_t penWidth, size_t penHeight, bool isFrame) -{ - int pen_size = (penWidth + penHeight) / 2; - PICTrectangle new_rect = ContractRect(rect, pen_size, isFrame); - const long X[2] = {new_rect.left, new_rect.right}; - const long Y[2] = {new_rect.top, new_rect.bottom}; - - renderer->PathCommandStart(); - renderer->BeginCommand(c_nPathType); - Aggplus::CGraphicsPath path; - path.AddRectangle(X[0], Y[0], X[1] - X[0], Y[1] - Y[0]); - size_t points_count = path.GetPointCount(); - - Aggplus::PointF* points = new Aggplus::PointF[points_count]; - path.GetPathPoints(points, points_count); - - renderer->PathCommandMoveTo(points[0].X, points[0].Y); - - for (size_t i = 1; i < points_count; i++) - renderer->PathCommandLineTo(points[i].X, points[i].Y); - - if (!isFrame) - renderer->Fill(); - - renderer->DrawPath(c_nStroke); - renderer->EndCommand(c_nPathType); - renderer->PathCommandEnd(); - - delete[] points; -} - -void DrawRoundRect(NSGraphics::IGraphicsRenderer* renderer, const PICTrectangle& roundRect, size_t penWidth, size_t penHeight, bool isFrame) -{ - int pen_size = (penWidth + penHeight) / 2; - - PICTrectangle oval = ContractRect(roundRect, pen_size, isFrame); - int ovalW = penWidth; - int ovalH = penHeight; - const long X[2] = {oval.left, oval.right}; - const long Y[2] = {oval.top, oval.bottom}; - long width = X[1] - X[0]; - long height = Y[1] - Y[0]; - - if (ovalW > width) - ovalW = static_cast(width); - if (ovalH > height) - ovalH = static_cast(height); - - renderer->PathCommandStart(); - renderer->BeginCommand(c_nPathType); - Aggplus::CGraphicsPath path; - path.AddRoundRectangle(X[0], Y[0], X[1] - X[0], Y[1] - Y[0], width == 0.0 ? 0.0 : ovalW / width, height == 0.0 ? 0.0 : ovalH / height); - size_t points_count = path.GetPointCount(); - - Aggplus::PointF* points = new Aggplus::PointF[points_count]; - path.GetPathPoints(points, points_count); - - renderer->PathCommandMoveTo(points[0].X, points[0].Y); - - for (size_t i = 1; i < points_count; i += 3) - renderer->PathCommandCurveTo(points[i].X, points[i].Y, - points[i + 1].X, points[i + 1].Y, - points[i + 2].X, points[i + 2].Y); - - if (!isFrame) - renderer->Fill(); - - renderer->DrawPath(c_nStroke); - renderer->EndCommand(c_nPathType); - renderer->PathCommandEnd(); - - delete[] points; -} - -void DrawOval(NSGraphics::IGraphicsRenderer* renderer, const PICTrectangle& oval, size_t penWidth, size_t penHeight, bool isFrame) -{ - int pen_size = (penWidth + penHeight) / 2; - - PICTrectangle rect = ContractRect(oval, pen_size, isFrame); - const long X[2] = {rect.left, rect.right}; - const long Y[2] = {rect.top, rect.bottom}; - - renderer->PathCommandStart(); - renderer->BeginCommand(c_nPathType); - Aggplus::CGraphicsPath path; - path.AddEllipse(X[0], Y[0], X[1] - X[0], Y[1] - Y[0]); - size_t points_count = path.GetPointCount(); - - Aggplus::PointF* points = new Aggplus::PointF[points_count]; - path.GetPathPoints(points, points_count); - - renderer->PathCommandMoveTo(points[0].X, points[0].Y); - - for (size_t i = 1; i < points_count; i += 3) - renderer->PathCommandCurveTo(points[i].X, points[i].Y, - points[i + 1].X, points[i + 1].Y, - points[i + 2].X, points[i + 2].Y); - - if (!isFrame) - renderer->Fill(); - - renderer->DrawPath(c_nStroke); - renderer->EndCommand(c_nPathType); - renderer->PathCommandEnd(); - - delete[] points; -} - -void DrawArc(NSGraphics::IGraphicsRenderer* renderer, FILE* file, PICTrectangle arc, size_t penWidth, size_t penHeight) -{ - short start_angle = ReadShortValue(file); - short angle = ReadShortValue(file); - if (feof(file) || (penWidth == 0 && penHeight == 0)) - return; - - if (angle < 0) - { - start_angle = start_angle + angle; - angle = -angle; - } - - double ang1 = agg::deg2rad(start_angle); - double ang2 = agg::deg2rad(angle); - - renderer->PathCommandStart(); - renderer->BeginCommand(c_nPathType); - Aggplus::CGraphicsPath path; - path.AddArc(arc.left, arc.top, arc.right - arc.left, arc.bottom - arc.top, ang1, ang2); - - size_t points_count = path.GetPointCount(); - - Aggplus::PointF* points = new Aggplus::PointF[points_count]; - path.GetPathPoints(points, points_count); - - renderer->PathCommandMoveTo(points[0].X, points[0].Y); - - for (size_t i = 1; i < points_count; i += 3) - renderer->PathCommandCurveTo(points[i].X, points[i].Y, - points[i + 1].X, points[i + 1].Y, - points[i + 2].X, points[i + 2].Y); - - renderer->DrawPath(c_nStroke); - renderer->EndCommand(c_nPathType); - renderer->PathCommandEnd(); - - delete[] points; -} - -void ReadAndDrawText(NSGraphics::IGraphicsRenderer* renderer, FILE* hFile, size_t penWidth, size_t penHeight, const std::wstring& fontName, short fontSize, const long& fontStyle, short x, short y) -{ - char text[256]; - char byte_len = ReadByte(hFile); - unsigned long len = static_cast(byte_len) & 0x000000ff; - len = Read(hFile, len, &text); - - if (penWidth == 0 && penHeight == 0) - return; - - while (len > 0 && static_cast(text[len - 1]) < 32) - len--; - text[len] = 0; - renderer->put_FontName(fontName); - renderer->put_FontSize(fontSize); - renderer->put_FontStyle(fontStyle); - - std::wstring ws_text(len, L'\0'); - std::mbstowcs(&ws_text[0], text, len); - - renderer->BeginCommand(c_nTextGraphicType); - renderer->CommandDrawText(ws_text, x, y, 0.0, 0.0); - renderer->EndCommand(c_nTextGraphicType); -} - -bool DecodePICT(FILE* hFile, ImagePICT* image) -{ - if (hFile == nullptr) - return 0; - - PICTPixmap pixmap; - pixmap.bits_per_pixel=0; - pixmap.component_count=0; - - if (!DecodeHeader(hFile, image)) - return false; - - if (feof(hFile) != 0) - return false; - - long long flags = 0; - image->m_ndepth = 8; - image->resolutionX = 72.0; - image->resolutionY = 72.0; - - if (!AquirePixelsMemory(image)) - return false; - - NSGraphics::IGraphicsRenderer* renderer = NSGraphics::Create(); - NSFonts::IFontManager* fmp = NSFonts::NSFontManager::Create(); - renderer->SetFontManager(fmp); - - bool is_pix_data = false; - BYTE* data = new BYTE[4 * image->m_nWidth * image->m_nHeight]; - - CBgraFrame frame; - frame.put_Data(data); - frame.put_Width(image->m_nWidth); - frame.put_Height(image->m_nHeight); - frame.put_Stride(4 * image->m_nWidth); - - renderer->CreateFromBgraFrame(&frame); - renderer->SetSwapRGB(false); - renderer->put_Width(image->m_nWidth); - renderer->put_Height(image->m_nHeight); - renderer->put_PenColor(0x000000); - - short pen_width = 0; - short pen_height = 0; - - Point pen_point; - Point text_point; - std::wstring font_name; - short font_size = 0; - long font_style = 0; - - PICTrectangle last_rect; - PICTrectangle last_round_rect; - PICTrectangle last_oval; - PICTrectangle last_arc; - Polygon last_polygon; - - for (int code = 0; feof(hFile) == 0; ) - { - if ((image->m_pctVersion == 1) || ((ftell(hFile) % 2) != 0)) - code = ReadByte(hFile); - if (image->m_pctVersion == 2) - code = ReadSignedShortValue(hFile); - code &= 0xffff; - if (code < 0) - break; - if (code == 0) - continue; - if (code <= 0xa1) - { - switch(code) - { - case 0x01: - { - size_t length = (size_t) ReadShortValue(hFile); - if (length > GetSize(hFile)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - - if (length != 0x000a) - { - for (size_t i = 0; i < length - 2; i++) - if (ReadByte(hFile) == EOF) - break; - break; - } - - PICTrectangle frame; - if (ReadRectangle(hFile, &frame) == 0) - return false; - if (((frame.left & 0x8000) != 0) || ((frame.top & 0x8000) != 0)) - break; - image->m_nHeight = (size_t) (frame.bottom - frame.top); - image->m_nWidth = (size_t) (frame.right - frame.left); - - if (!AquirePixelsMemory(image)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - break; - } - case 0x11: - { - fseek(hFile, 1, SEEK_CUR); - break; - } - case 0x03: - case 0x05: - case 0x08: - case 0x15: - case 0x16: - case 0xa0: - { - fseek(hFile, 2, SEEK_CUR); - break; - } - case 0x1d: - case 0x1f: - { - fseek(hFile, 3, SEEK_CUR); - break; - } - case 0x06: - case 0x0b: - case 0x0c: - case 0x0f: - case 0x6d: - case 0x6e: - case 0x6f: - { - fseek(hFile, 4, SEEK_CUR); - break; - } - case 0x02: - case 0x09: - case 0x0a: - case 0x10: - case 0x35: - case 0x36: - case 0x37: - case 0x45: - case 0x46: - case 0x47: - case 0x55: - case 0x56: - case 0x57: - { - fseek(hFile, 8, SEEK_CUR); - break; - } - case 0x2d: - { - fseek(hFile, 10, SEEK_CUR); - break; - } - case 0x65: - case 0x66: - case 0x67: - { - fseek(hFile, 12, SEEK_CUR); - break; - } - case 0xa1: - { - fseek(hFile, 2, SEEK_CUR); - short length = ReadShortValue(hFile); - if (length > GetSize(hFile)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - fseek(hFile, length, SEEK_CUR); - break; - } - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x2e: - case 0x2f: - case 0x75: - case 0x76: - case 0x77: - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - case 0x9c: - case 0x9d: - case 0x9e: - case 0x9f: - { - short length = ReadShortValue(hFile); - if (length > GetSize(hFile)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - fseek(hFile, length - 2, SEEK_CUR); - break; - } - case 0x85: - case 0x86: - case 0x87: - { - short length = ReadShortValue(hFile); - if (length > GetSize(hFile)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - fseek(hFile, length - 4, SEEK_CUR); - break; - } - case 0x04: - { - char c = ReadByte(hFile); - if ((c & 0x01) != 0) - font_style |= 0x01; - if ((c & 0x02) != 0) - font_style |= 0x02; - if ((c & 0x04) != 0) - font_style |= 0x7c >> 2; - if ((c & 0x08) != 0) - font_style |= 0x0180 >> 7; - break; - } - case 0x07: - { - pen_height = ReadShortValue(hFile); - pen_width = ReadShortValue(hFile); - break; - } - case 0x0d: - { - font_size = ReadShortValue(hFile); - break; - } - case 0x0e: - { - long color = ReadLongValue(hFile); - - switch(color) - { - case 33: renderer->put_BrushColor1(0x000000); break; - case 30: renderer->put_BrushColor1(0xFFFFFF); break; - case 205: renderer->put_BrushColor1(0xFF8080); break; //lightred - case 341: renderer->put_BrushColor1(0x90EE90); break; //lightgreen - case 409: renderer->put_BrushColor1(0xADD8E6); break; //lightblue - case 273: renderer->put_BrushColor1(0xE0FFFF); break; //lightcyan - case 137: renderer->put_BrushColor1(0xFF80FF); break; //lightmagenta - case 69: renderer->put_BrushColor1(0xFFFF00); break; //yellow - default: renderer->put_BrushColor1(0xD3D3D3); break; //lightgray - } - break; - } - case 0x12: - case 0x13: - case 0x14: - { - int pattern; - size_t height, width; - pattern = (int) ReadShortValue(hFile); - for (size_t i = 0; i < 8; i++) - if (ReadByte(hFile) == EOF) - break; - if (pattern == 2) - { - for (size_t i = 0; i < 5; i++) - if (ReadByte(hFile) == EOF) - break; - break; - } - if (pattern != 1) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - - size_t length = (size_t) ReadShortValue(hFile); - if (length > GetSize(hFile)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - - PICTrectangle frame; - if (ReadRectangle(hFile, &frame) == 0) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - - if (ReadPixmap(hFile, &pixmap) == 0) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - - image->m_ndepth = (size_t) pixmap.component_size; - image->resolutionX = 1.0 * pixmap.horizontal_resolution; - image->resolutionY = 1.0 * pixmap.vertical_resolution; - - ReadLongValue(hFile); - flags = (long long) ReadShortValue(hFile); - length=ReadShortValue(hFile); - - if (length > GetSize(hFile)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - - for (size_t i = 0; i < length; i++) - ReadLongValue(hFile); - width=(size_t) (frame.bottom-frame.top); - height=(size_t) (frame.right-frame.left); - - if (pixmap.bits_per_pixel <= 8) - length &= 0x7fff; - if (pixmap.bits_per_pixel == 16) - width <<= 1; - if (length == 0) - length = width; - if (length < 8) - { - for (size_t i = 0; i < (length*height); i++) - if (ReadByte(hFile) == EOF) - break; - } - else - for (size_t i = 0; i < height; i++) - { - size_t scanline_length; - - if (feof(hFile) != 0) - break; - if (length > 200) - scanline_length=ReadShortValue(hFile); - else - scanline_length = (size_t) ReadByte(hFile); - if (scanline_length > GetSize(hFile)) - { - DeletePixelsMemory(image); - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - return false; - } - for (size_t j = 0; j < scanline_length; j++) - if (ReadByte(hFile) == EOF) - break; - } - break; - } - case 0x1a: - { - BYTE r = ReadShortValue(hFile) >> 8; - BYTE g = ReadShortValue(hFile) >> 8; - BYTE b = ReadShortValue(hFile) >> 8; - long c = r << 16 | g << 8 | b; - renderer->put_BrushColor1(c); - break; - } - case 0x1b: - { - image->background_color.red = 257.0 * ReadShortValue(hFile); - image->background_color.green = 257.0 * ReadShortValue(hFile); - image->background_color.blue = 257.0 * ReadShortValue(hFile); - break; - } - case 0x20: - { - short y1 = ReadShortValue(hFile); - short x1 = ReadShortValue(hFile); - short y2 = ReadShortValue(hFile); - short x2 = ReadShortValue(hFile); - - pen_point = Point(x2, y2); - - if (pen_height == 0 && pen_width == 0) - break; - - DrawLine(renderer, Point(x1, y1), Point(x2, y2), pen_width, pen_height); - break; - } - case 0x21: - { - short y1 = ReadShortValue(hFile); - short x1 = ReadShortValue(hFile); - - if (feof(hFile)) - break; - - if (pen_height == 0 && pen_width == 0) - break; - - DrawLine(renderer, Point(x1, y1), pen_point, pen_width, pen_height); - break; - } - case 0x22: - { - short y1 = ReadShortValue(hFile); - short x1 = ReadShortValue(hFile); - short y2 = static_cast(y1 + ReadByte(hFile)); - short x2 = static_cast(x1 + ReadByte(hFile)); - - if (pen_height == 0 && pen_width == 0) - break; - - DrawLine(renderer, Point(x1, y1), Point(x2, y2), pen_width, pen_height); - break; - } - case 0x23: - { - short y2 = static_cast(pen_point.Y + ReadByte(hFile)); - short x2 = static_cast(pen_point.X + ReadByte(hFile)); - - if (pen_height == 0 && pen_width == 0) - break; - - DrawLine(renderer, pen_point, Point(x2, y2), pen_width, pen_height); - break; - } - case 0x28: - { - short y = ReadShortValue(hFile); - short x = ReadShortValue(hFile); - - text_point = Point(x, y); - ReadAndDrawText(renderer, hFile, pen_width, pen_height, font_name, font_size, font_style, x, y); - break; - } - case 0x29: - { - unsigned char h = static_cast(ReadByte(hFile)); - ReadAndDrawText(renderer, hFile, pen_width, pen_height, font_name, font_size, font_style, text_point.X + h, text_point.Y); - break; - } - case 0x2a: - { - unsigned char v = static_cast(ReadByte(hFile)); - ReadAndDrawText(renderer, hFile, pen_width, pen_height, font_name, font_size, font_style, text_point.X, text_point.Y + v); - break; - } - case 0x2b: - { - unsigned char h = static_cast(ReadByte(hFile)); - unsigned char v = static_cast(ReadByte(hFile)); - ReadAndDrawText(renderer, hFile, pen_width, pen_height, font_name, font_size, font_style, text_point.X + h, text_point.Y + v); - break; - } - case 0x2c: - { - fseek(hFile, 4, SEEK_CUR); - char byte_len = ReadByte(hFile); - unsigned short len = static_cast(byte_len) & 0x00ff; - char f_name[256]; - Read(hFile, len, f_name); - f_name[len] = 0; - font_name = std::wstring(len, L'\0'); - std::mbstowcs(&font_name[0], f_name, len); - break; - } - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - { - PICTrectangle rect; - if (!ReadRectangle(hFile, &rect)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - last_rect = rect; - DrawRect(renderer, rect, pen_width, pen_height, code == 0x30); - break; - } - case 0x38: - case 0x39: - case 0x3a: - case 0x3b: - case 0x3c: - { - DrawRect(renderer, last_rect, pen_width, pen_height, code == 0x38); - break; - } - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - { - PICTrectangle round_rect; - if (!ReadRectangle(hFile, &round_rect)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - last_round_rect = round_rect; - DrawRoundRect(renderer, round_rect, pen_width, pen_height, code == 0x40); - break; - } - case 0x48: - case 0x49: - case 0x4a: - case 0x4b: - case 0x4c: - { - DrawRoundRect(renderer, last_round_rect, pen_width, pen_height, code == 0x48); - break; - } - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - { - PICTrectangle oval; - if (!ReadRectangle(hFile, &oval)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - last_oval = oval; - DrawOval(renderer, oval, pen_width, pen_height, code == 0x50); - break; - } - case 0x58: - case 0x59: - case 0x5a: - case 0x5b: - case 0x5c: - { - DrawOval(renderer, last_oval, pen_width, pen_height, code == 0x58); - break; - } - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - { - PICTrectangle arc; - if (!ReadRectangle(hFile, &arc)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - last_arc = arc; - DrawArc(renderer, hFile, arc, pen_width, pen_height); - break; - } - case 0x68: - case 0x69: - case 0x6a: - case 0x6b: - case 0x6c: - { - DrawArc(renderer, hFile, last_arc, pen_width, pen_height); - break; - } - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - { - Polygon poly; - ReadPolygon(hFile, poly); - last_polygon.Size = poly.Size; - last_polygon.Points = (Point*) malloc(poly.Size * sizeof(Point)); - memcpy(last_polygon.Points, poly.Points, poly.Size); - DrawPolygon(renderer, poly, pen_width, pen_height, code == 0x70); - break; - } - case 0x78: - case 0x79: - case 0x7a: - case 0x7b: - case 0x7c: - { - DrawPolygon(renderer, last_polygon, pen_width, pen_height, code == 0x78); - break; - } - case 0x90: - case 0x91: - case 0x98: - case 0x99: - case 0x9a: - case 0x9b: - { - is_pix_data = true; - PICTrectangle source, destination; - - unsigned char *p; - - size_t k; - - long long bytes_per_line; - - unsigned char *pixels; - - bytes_per_line = 0; - if ((code != 0x9a) && (code != 0x9b)) - bytes_per_line= (long long) ReadShortValue(hFile); - else - { - ReadShortValue(hFile); - ReadShortValue(hFile); - ReadShortValue(hFile); - } - - PICTrectangle frame; - if (ReadRectangle(hFile, &frame) == 0) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - - ImagePICT* tile_image = CloneImage(image, (size_t) (frame.right-frame.left), (size_t) (frame.bottom-frame.top)); - if (tile_image == nullptr) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - - if (!AquirePixelsMemory(tile_image)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - DestroyImage(tile_image); - return false; - } - - if ((code == 0x9a) || (code == 0x9b) || ((bytes_per_line & 0x8000) != 0)) - { - if (ReadPixmap(hFile, &pixmap) == 0) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - DestroyImage(tile_image); - return false; - } - tile_image->m_ndepth=(size_t) pixmap.component_size; - tile_image->alpha_trait=pixmap.component_count == 4 ? BlendPixelTrait : UndefinedPixelTrait; - tile_image->resolutionX=(double) pixmap.horizontal_resolution; - tile_image->resolutionY=(double) pixmap.vertical_resolution; - if (tile_image->alpha_trait != UndefinedPixelTrait) - SetImageAlpha(tile_image, 255); - } - if ((code != 0x9a) && (code != 0x9b)) - { - tile_image->colors = 2; - if ((bytes_per_line & 0x8000) != 0) - { - ReadLongValue(hFile); - flags = (long long) ReadShortValue(hFile); - tile_image->colors = 1UL * ReadShortValue(hFile) + 1; - } - if (!AquireImageColormap(tile_image, tile_image->colors)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - DestroyImage(tile_image); - return false; - } - - if ((bytes_per_line & 0x8000) != 0) - { - for (size_t i = 0; i < tile_image->colors; i++) - { - k = ReadShortValue(hFile) % tile_image->colors; - if ((flags & 0x8000) != 0) - k = (size_t) i; - tile_image->colormap[k].red = (unsigned char) ReadShortValue(hFile)/* + 128U / 257U*/; - tile_image->colormap[k].green = (unsigned char) ReadShortValue(hFile)/* + 128U / 257U*/; - tile_image->colormap[k].blue = (unsigned char) ReadShortValue(hFile)/* + 128U / 257U*/; - } - } - else - { - for (size_t i = 0; i < tile_image->colors; i++) - { - tile_image->colormap[i].red=((double) 255 - tile_image->colormap[i].blue); - tile_image->colormap[i].green=((double) 255 - tile_image->colormap[i].green); - tile_image->colormap[i].blue=((double) 255 - tile_image->colormap[i].red); - } - } - } - if (feof(hFile) != 0) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - DestroyImage(tile_image); - return false; - } - - if (ReadRectangle(hFile, &source) == 0) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - DestroyImage(tile_image); - return false; - } - - if (ReadRectangle(hFile, &destination) == 0) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - DestroyImage(tile_image); - return false; - } - - ReadShortValue(hFile); - - if ((code == 0x91) || (code == 0x99) || (code == 0x9b)) - { - size_t length = (size_t) ReadShortValue(hFile); - if ((size_t) length > GetSize(hFile)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - DestroyImage(tile_image); - return false; - } - - for (size_t i = 0; i < length - 2; i++) - if (ReadByte(hFile) == EOF) - break; - } - - size_t extent; - if ((code != 0x9a) && (code != 0x9b) && (bytes_per_line & 0x8000) == 0) - pixels = DecodeImage(hFile, tile_image, (size_t) bytes_per_line, 1, &extent); - else - pixels = DecodeImage(hFile, tile_image, (size_t) bytes_per_line, (unsigned int) pixmap.bits_per_pixel, &extent); - - if (pixels == (unsigned char*) nullptr) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - DestroyImage(tile_image); - return false; - } - - p = pixels; - for (size_t y=0; y < (long long) tile_image->m_nHeight; y++) - { - if (p > (pixels+extent+image->m_nWidth)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - free(pixels); - DeletePixelsMemory(image); - DeletePixelsMemory(tile_image); - DestroyImage(tile_image); - return 0; - } - unsigned char* q = tile_image->ppixels + tile_image->number_channels * (y * tile_image->m_nWidth); - if (q == (unsigned char *) nullptr) - break; - for (size_t x=0; x < tile_image->m_nWidth; x++) - { - if (tile_image->storage_class == PseudoClass) - { - unsigned char index; - if (((long long) *p < 0) || ((long long) *p >= (long long) tile_image->colors)) - index = 0; - else - index = *p; - SetPixelIndex(tile_image,index,q); - SetPixelRed(tile_image, tile_image->colormap[(long long) index].red,q); - SetPixelGreen(tile_image, tile_image->colormap[(long long) index].green,q); - SetPixelBlue(tile_image, tile_image->colormap[(long long) index].blue,q); - } - else - { - if (pixmap.bits_per_pixel == 16) - { - size_t i = (size_t) (*p++); - k=(size_t) (*p); - SetPixelRed(tile_image,(unsigned char) ((i & 0x7c) << 1),q); - SetPixelGreen(tile_image,(unsigned char) ((size_t) ((i & 0x03) << 6) |((k & 0xe0) >> 2)),q); - SetPixelBlue(tile_image,(unsigned char) ((k & 0x1f) << 3),q); - } - else if (tile_image->alpha_trait == UndefinedPixelTrait) - { - if (p > (pixels+extent+2*image->m_nWidth)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - free(pixels); - DeletePixelsMemory(image); - DestroyImage(tile_image); - return false; - } - SetPixelRed(tile_image,*p,q); - SetPixelGreen(tile_image,*(p+tile_image->m_nWidth),q); - SetPixelBlue(tile_image,*(p+2*tile_image->m_nWidth),q); - } - else - { - if (p > (pixels+extent+3*image->m_nWidth)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - free(pixels); - DeletePixelsMemory(image); - DestroyImage(tile_image); - return false; - } - SetPixelAlpha(tile_image,*p,q); - SetPixelRed(tile_image,*(p+1*tile_image->m_nWidth),q); - SetPixelGreen(tile_image,*(p+2*tile_image->m_nWidth),q); - SetPixelBlue(tile_image,*(p+3*tile_image->m_nWidth),q); - } - } - p++; - q+=tile_image->number_channels; - } - if ((tile_image->storage_class == DirectClass) && (pixmap.bits_per_pixel != 16)) - { - p+=(pixmap.component_count-1)*(long long) tile_image->m_nWidth; - if (p < pixels) - break; - } - } - - if (tile_image->storage_class == PseudoClass) - SetImageAlpha(tile_image, 255); - else if (pixmap.bits_per_pixel == 16) - SetImageAlpha(tile_image, 255); - else if (tile_image->alpha_trait == UndefinedPixelTrait) - SetImageAlpha(tile_image, 255); - - free(pixels); - if (feof(hFile) == 0) - if ((code == 0x9a) || (code == 0x9b) || ((bytes_per_line & 0x8000) != 0)) - CompositeImage(image,tile_image,1,(long long) destination.left,(long long)destination.top); - DestroyImage(tile_image); - break; - } - default: - break; - } - } - if (code == 0xc00) - { - for (size_t i = 0; i < 24; i++) - if (ReadByte(hFile) == EOF) - break; - continue; - } - if (((code >= 0xb0) && (code <= 0xcf)) || ((code >= 0x8000) && (code <= 0x80ff))) - continue; - if ((code == 0xff) || (code == 0xffff)) - continue; - if (((code >= 0xd0) && (code <= 0xfe)) || ((code >= 0x8100) && (code <= 0xffff))) - { - size_t length = (size_t) ReadShortValue(hFile); - if (length > GetSize(hFile)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - for (size_t i = 0; i < length; i++) - if (ReadByte(hFile) == EOF) - break; - continue; - } - if ((code >= 0x100) && (code <= 0x7fff)) - { - size_t length = (size_t) ((code >> 7) & 0xff); - if (length > GetSize(hFile)) - { - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - DeletePixelsMemory(image); - return false; - } - for (size_t i = 0; i ppixels, data, 4 * image->m_nWidth * image->m_nHeight * sizeof(unsigned char)); - - - RELEASEINTERFACE(fmp); - RELEASEINTERFACE(renderer); - - return true; -} diff --git a/DesktopEditor/raster/PICT/pic.h b/DesktopEditor/raster/PICT/pic.h deleted file mode 100644 index 5f1ba717f5..0000000000 --- a/DesktopEditor/raster/PICT/pic.h +++ /dev/null @@ -1,414 +0,0 @@ -/* - * (c) Copyright Ascensio System SIA 2010-2023 - * - * This program is a free software product. You can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License (AGPL) - * version 3 as published by the Free Software Foundation. In accordance with - * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect - * that Ascensio System SIA expressly excludes the warranty of non-infringement - * of any third-party rights. - * - * This program is distributed WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For - * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html - * - * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish - * street, Riga, Latvia, EU, LV-1050. - * - * The interactive user interfaces in modified source and object code versions - * of the Program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU AGPL version 3. - * - * Pursuant to Section 7(b) of the License you must retain the original Product - * logo when distributing the program. Pursuant to Section 7(e) we decline to - * grant you any rights under trademark law for use of our trademarks. - * - * All the Product's GUI elements, including illustrations and icon sets, as - * well as technical writing content are licensed under the terms of the - * Creative Commons Attribution-ShareAlike 4.0 International. See the License - * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode - * - */ - -#ifndef PIC_H -#define PIC_H - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -typedef enum -{ - UndefinedType, - BilevelType, - GrayscaleType, - GrayscaleAlphaType, - PaletteType, - PaletteAlphaType, - TrueColorType, - TrueColorAlphaType, - ColorSeparationType, - ColorSeparationAlphaType, - OptimizeType, - PaletteBilevelAlphaType -} ImageType; - -typedef struct -{ - char* path; - unsigned char* datum; - - size_t length; - size_t signature; - - char* name; -} StringInfo; - -typedef struct _NodeInfo -{ - void* key; - void* value; - - struct _NodeInfo* left; - struct _NodeInfo* right; -} NodeInfo; - -typedef struct -{ - NodeInfo* root; - - int (*compare)(const void*, const void*); - - int balance; - - void* key; - void* next; - - size_t nodes; - - size_t signature; -} SplayTreeInfo; - -typedef struct _PrimaryInfo -{ - double x; - double y; - double z; -} PrimaryInfo; - -typedef struct _ChromaticityInfo -{ - PrimaryInfo red_primary; - PrimaryInfo green_primary; - PrimaryInfo blue_primary; - PrimaryInfo white_point; -} ChromaticityInfo; - -typedef struct _PICTCode -{ - const char* name; - long long length; - - const char* description; -} PICTCode; - -typedef struct _PICTrectangle -{ - short top{0}; - short left{0}; - short bottom{0}; - short right{0}; - _PICTrectangle() {} - _PICTrectangle(short _top, short _left, short _bottom, short _right) : - top(_top), left(_left), bottom(_bottom), right(_right) {} -} PICTrectangle; - -typedef struct -{ - short version; - short pack_type; - - size_t pack_size; - size_t horizontal_resolution; - size_t vertical_resolution; - - short pixel_type; - short bits_per_pixel; - short component_count; - short component_size; - - size_t plane_bytes; - size_t table; - size_t reserved; -} PICTPixmap; - -typedef struct -{ - size_t width; - size_t height; - - long long x; - long long y; -} RectangleInfo; - -typedef struct _NexusInfo -{ - RectangleInfo region; - size_t length; - unsigned char* pixels; - int authentic_pixel_cache; - size_t signature; - struct _NexusInfo* virtual_nexus; -} NexusInfo; - - -typedef struct _GeometryInfo -{ - double rho; - double sigma; - double xi; - double psi; - double chi; -} GeometryInfo; - -typedef enum -{ - UndefinedChannel = 0x0000, - RedChannel = 0x0001, - GrayChannel = 0x0001, - CyanChannel = 0x0001, - LChannel = 0x0001, - GreenChannel = 0x0002, - MagentaChannel = 0x0002, - aChannel = 0x0002, - BlueChannel = 0x0004, - bChannel = 0x0002, - YellowChannel = 0x0004, - BlackChannel = 0x0008, - AlphaChannel = 0x0010, - OpacityChannel = 0x0010, - IndexChannel = 0x0020, /* Color Index Table? */ - ReadMaskChannel = 0x0040, /* Pixel is Not Readable? */ - WriteMaskChannel = 0x0080, /* Pixel is Write Protected? */ - MetaChannel = 0x0100, /* not used */ - CompositeMaskChannel = 0x0200, /* SVG mask */ - CompositeChannels = 0x001F, - AllChannels = 0X7FFFFFF, - /* - Special purpose channel types. - FUTURE: are these needed any more - they are more like hacks - SyncChannels for example is NOT a real channel but a 'flag' - It really says -- "User has not defined channels" - Though it does have extra meaning in the "-auto-level" operator - */ - TrueAlphaChannel = 0x0100, /* extract actual alpha channel from opacity */ - RGBChannels = 0x0200, /* set alpha from grayscale mask in RGB */ - GrayChannels = 0x0400, - SyncChannels = 0x20000, /* channels modified as a single unit */ - DefaultChannels = AllChannels -} ChannelType; - -typedef enum -{ - ReadMode, - WriteMode, - IOMode, - PersistMode -} MapMode; - -typedef enum -{ - UndefinedClass, - DirectClass, - PseudoClass -} ClassType; - -typedef enum -{ - UndefinedColorspace, - CMYColorspace, /* negated linear RGB colorspace */ - CMYKColorspace, /* CMY with Black separation */ - GRAYColorspace, /* Single Channel greyscale (non-linear) image */ - HCLColorspace, - HCLpColorspace, - HSBColorspace, - HSIColorspace, - HSLColorspace, - HSVColorspace, /* alias for HSB */ - HWBColorspace, - LabColorspace, - LCHColorspace, /* alias for LCHuv */ - LCHabColorspace, /* Cylindrical (Polar) Lab */ - LCHuvColorspace, /* Cylindrical (Polar) Luv */ - LogColorspace, - LMSColorspace, - LuvColorspace, - OHTAColorspace, - Rec601YCbCrColorspace, - Rec709YCbCrColorspace, - RGBColorspace, /* Linear RGB colorspace */ - scRGBColorspace, /* ??? */ - sRGBColorspace, /* Default: non-linear sRGB colorspace */ - TransparentColorspace, - xyYColorspace, - XYZColorspace, /* IEEE Color Reference colorspace */ - YCbCrColorspace, - YCCColorspace, - YDbDrColorspace, - YIQColorspace, - YPbPrColorspace, - YUVColorspace, - LinearGRAYColorspace, /* Single Channel greyscale (linear) image */ - JzazbzColorspace, - DisplayP3Colorspace, - Adobe98Colorspace, - ProPhotoColorspace, - OklabColorspace, - OklchColorspace -} ColorspaceType; - -typedef enum -{ - UndefinedPixelTrait = 0x000000, - CopyPixelTrait = 0x000001, - UpdatePixelTrait = 0x000002, - BlendPixelTrait = 0x000004 -} PixelTrait; - -typedef enum -{ - UndefinedPixelChannel = 0, - RedPixelChannel = 0, - CyanPixelChannel = 0, - GrayPixelChannel = 0, - LPixelChannel = 0, - LabelPixelChannel = 0, - YPixelChannel = 0, - aPixelChannel = 1, - GreenPixelChannel = 1, - MagentaPixelChannel = 1, - CbPixelChannel = 1, - bPixelChannel = 2, - BluePixelChannel = 2, - YellowPixelChannel = 2, - CrPixelChannel = 2, - BlackPixelChannel = 3, - AlphaPixelChannel = 4, - IndexPixelChannel = 5, - ReadMaskPixelChannel = 6, - WriteMaskPixelChannel = 7, - MetaPixelChannel = 8, /* deprecated */ - CompositeMaskPixelChannel = 9, - MetaPixelChannels = 10, - IntensityPixelChannel = 64, /* ???? */ - CompositePixelChannel = 64, /* ???? */ - SyncPixelChannel = 65 /* not a real channel */ -} PixelChannel; - -typedef struct -{ - PixelChannel channel; - PixelTrait traits; - long long offset; -} PixelChannelMap; - -typedef struct -{ - ClassType storage_class; - - ColorspaceType colorspace; - - PixelTrait alpha_trait; - - double fuzz; - - size_t depth; - size_t count; - - double red; - double green; - double blue; - double black; - double alpha; - double index; -} PixelInfo; - -template -struct Point { - T X{0}; - T Y{0}; - Point() {} - Point(T x, T y) : X(x), Y(y) {} -}; - -template -struct Polygon -{ - size_t Size; - Point* Points; - Polygon() {} - ~Polygon() - { - if (Points) - free(Points); - } -}; - -typedef struct -{ - ClassType storage_class; - ColorspaceType colorspace; - ChromaticityInfo chromaticity; - int m_pctVersion; - - size_t m_nHeight; - size_t m_nWidth; - size_t m_ndepth; - size_t m_nPixelsSize; - size_t colors; - - SplayTreeInfo* artifacts; - - double fuzz; - - unsigned char* ppixels; - - double resolutionX; - double resolutionY; - double gamma; - - ImageType type; - - PixelInfo background_color; - PixelInfo* colormap; - - PixelTrait alpha_trait; - - PixelChannelMap* channel_map; - - PixelTrait mask_trait; - - int taint; - - void* cache; - - size_t number_channels; - - char error[256]; -}ImagePICT; - -bool DecodePICT(FILE* hFile, ImagePICT* image); -void AquireImage(ImagePICT* image); -void DestroyImage(ImagePICT* image); - -#endif // PIC_H