Files
core/DesktopEditor/raster/PICT/PICFile.h
Alexander Trofimov 76ee07f61c [copyright] Update copyright header
Co-authored-by: Alexander Trofimov <alexander.trofimov@onlyoffice.com>
Co-committed-by: Alexander Trofimov <alexander.trofimov@onlyoffice.com>
2026-05-14 08:23:56 +00:00

287 lines
7.1 KiB
C++

/*
* Copyright (C) Ascensio System SIA, 2009-2026
*
* 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, together with the
* additional terms provided in the LICENSE file.
*
* 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: https://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA by email at info@onlyoffice.com
* or by postal mail at 20A-6 Ernesta Birznieka-Upisha Street, Riga,
* LV-1050, Latvia, European Union.
*
* The interactive user interfaces in modified versions of the Program
* are required to display Appropriate Legal Notices in accordance with
* Section 5 of the GNU AGPL version 3.
*
* No trademark rights are granted under this License.
*
* All non-code elements of the Product, including illustrations,
* icon sets, and technical writing content, are licensed under the
* Creative Commons Attribution-ShareAlike 4.0 International License:
* https://creativecommons.org/licenses/by-sa/4.0/legalcode
*
* This license applies only to such non-code elements and does not
* modify or replace the licensing terms applicable to the Program's
* source code, which remains licensed under the GNU Affero General
* Public License v3.
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
#ifndef PICFILE_H
#define PICFILE_H
#include "../../graphics/pro/Graphics.h"
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)
free(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) * sizeof(PixelInfo));
}
memcpy(m_pChannelMap, other.m_pChannelMap, 65 * sizeof(PixelChannelMap));
return *this;
}
void Realloc(const size_t& w, const size_t& h, const bool& isCopy = true)
{
size_t oldSize = 4 * m_nWidth * m_nHeight;
size_t newSize = 4 * w * h;
m_nWidth = w;
m_nHeight = h;
if (0 == newSize)
{
if (m_pPixelData)
free(m_pPixelData);
m_pPixelData = nullptr;
return;
}
if (oldSize == newSize)
return;
BYTE* oldPixels = m_pPixelData;
if (oldSize > newSize || !m_pPixelData)
{
m_pPixelData = (BYTE*)malloc(newSize);
if (isCopy && oldPixels)
memcpy(m_pPixelData, oldPixels, newSize);
if (oldPixels)
free(oldPixels);
}
else
{
m_pPixelData = (BYTE*)realloc(oldPixels, newSize);
if (NULL == m_pPixelData)
{
m_pPixelData = (BYTE*)malloc(newSize);
if (isCopy && oldPixels)
memcpy(m_pPixelData, oldPixels, oldSize);
if (oldPixels)
free(oldPixels);
}
}
}
};
class CPictFile
{
public:
CPictFile();
~CPictFile();
bool Open(CBgraFrame* frame, const std::wstring& fileName, bool isRGB);
bool Open(CBgraFrame* frame, BYTE* buffer, const size_t& size, bool isRGB);
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);
BYTE* GetPixels(const Image& image, const long long& x, const long long& y, const size_t& width, const size_t& height) const;
void CompositeImage(const Image& composite,const long long& xOffset, const long long& yOffset);
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 InitializeFonts();
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{1};
size_t m_nPenWidth{1};
int m_nFontStyle{0};
int m_nFontSize{0};
std::wstring m_wsFontName{};
Aggplus::Point m_oPenPoint{0, 0};
Aggplus::Point m_oTextPoint{0, 0};
Aggplus::Rect m_oLastRect{};
Aggplus::Rect m_oLastRoundRect{};
Aggplus::Rect m_oLastOval{};
Aggplus::Rect m_oLastArc{};
std::vector<Aggplus::Point> m_arLastPolygon{};
NSGraphics::IGraphicsRenderer* m_pRenderer{nullptr};
NSFonts::IApplicationFonts* m_pAppFonts{nullptr};
NSFonts::IFontManager* m_pFontManager{nullptr};
};
#endif // PICFILE_H