/* * (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 * */ #pragma once #include "ReadStructures.h" #include "../../DocFile/MemoryStream.h" #include "../../../OfficeCryptReader/source/CryptTransform.h" namespace PPT { static ODRAW::CColor GetStandartPaletteColor(int index) { ODRAW::CColor color; static BYTE palette [56][3] = { { 0 , 0 , 0 }, { 255 , 255 , 255 }, { 255 , 0 , 0 }, { 0 , 255 , 0 }, { 0 , 0 , 255 }, { 255 , 255 , 0 }, { 255 , 0 , 255 }, { 0 , 255 , 255 }, { 128 , 0 , 0 }, { 0 , 128 , 0 }, { 0 , 0 , 128 }, { 128 , 128 , 0 }, { 128 , 0 , 128 }, { 0 , 128 , 128 }, { 192 , 192 , 192 }, { 128 , 128 , 128 }, { 153 , 153 , 255 }, { 153 , 51 , 102 }, { 255 , 255 , 204 }, { 204 , 255 , 255 }, { 102 , 0 , 102 }, { 255 , 128 , 128 }, { 0 , 102 , 204 }, { 204 , 204 , 255 }, { 0 , 0 , 128 }, { 255 , 0 , 255 }, { 255 , 255 , 0 }, { 0 , 255 , 255 }, { 128 , 0 , 128 }, { 128 , 0 , 0 }, { 0 , 128 , 128 }, { 0 , 0 , 255 }, { 0 , 204 , 255 }, { 204 , 255 , 255 }, { 204 , 255 , 204 }, { 255 , 255 , 153 }, { 153 , 204 , 255 }, { 255 , 153 , 204 }, { 204 , 153 , 255 }, { 255 , 204 , 153 }, { 51 , 102 , 255 }, { 51 , 204 , 204 }, { 153 , 204 , 0 }, { 255 , 204 , 0 }, { 255 , 153 , 0 }, { 255 , 102 , 0 }, { 102 , 102 , 153 }, { 150 , 150 , 150 }, { 0 , 51 , 102 }, { 51 , 153 , 102 }, { 0 , 51 , 0 }, { 51 , 51 , 0 }, { 153 , 51 , 0 }, { 153 , 51 , 102 }, { 51 , 51 , 153 } }; color.SetRGB(palette[index][0], palette[index][1], palette[index][2]); return color; } namespace NSStreamReader { void Read(POLE::Stream* pStream, PPT::CTextRuler& oRun) { double dScaleX = 625 * 2.54; //1/576 inch = 72/576 pt = 360000 *72 * 2.54 /(72*576) emu _UINT32 dwFlags = StreamUtils::ReadDWORD(pStream); BYTE flag1 = (BYTE)(dwFlags); BYTE flag2 = (BYTE)(dwFlags >> 8); BYTE flag3 = (BYTE)(dwFlags >> 16); BYTE flag4 = (BYTE)(dwFlags >> 24); bool bDefaultTabSize_ = (0x01 == (0x01 & flag1)); bool bCLevels_ = (0x02 == (0x02 & flag1)); bool bTabStops_ = (0x04 == (0x04 & flag1)); bool bLeftMargin1_ = (0x08 == (0x08 & flag1)); bool bLeftMargin2_ = (0x10 == (0x10 & flag1)); bool bLeftMargin3_ = (0x20 == (0x20 & flag1)); bool bLeftMargin4_ = (0x40 == (0x40 & flag1)); bool bLeftMargin5_ = (0x80 == (0x80 & flag1)); bool bIndent1_ = (0x01 == (0x01 & flag2)); bool bIndent2_ = (0x02 == (0x02 & flag2)); bool bIndent3_ = (0x04 == (0x04 & flag2)); bool bIndent4_ = (0x08 == (0x08 & flag2)); bool bIndent5_ = (0x10 == (0x10 & flag2)); if (bCLevels_) oRun.CLevels = StreamUtils::ReadSHORT(pStream); if (bDefaultTabSize_) oRun.DefaultTabSize = (long)(StreamUtils::ReadSHORT(pStream) * dScaleX); if (bTabStops_) { WORD tabStopsCount = StreamUtils::ReadWORD(pStream); oRun.tabsStops.clear(); for (WORD i = 0; i < tabStopsCount; ++i) { WORD tabPos = StreamUtils::ReadWORD(pStream); WORD tabType = StreamUtils::ReadWORD(pStream); if ((tabPos & 0xff00) == 0xff00) break; tabType = 0x0000; oRun.tabsStops.push_back(std::pair(tabPos * dScaleX, tabType)); } } if (bLeftMargin1_) oRun.LeftMargin1 = StreamUtils::ReadSHORT(pStream) * dScaleX; if (bIndent1_) oRun.Indent1 = StreamUtils::ReadSHORT(pStream) * dScaleX; if (bLeftMargin2_) oRun.LeftMargin2 = StreamUtils::ReadSHORT(pStream) * dScaleX; if (bIndent2_) oRun.Indent2 = StreamUtils::ReadSHORT(pStream) * dScaleX; if (bLeftMargin3_) oRun.LeftMargin3 = StreamUtils::ReadSHORT(pStream) * dScaleX; if (bIndent3_) oRun.Indent3 = StreamUtils::ReadSHORT(pStream) * dScaleX; if (bLeftMargin4_) oRun.LeftMargin4 = StreamUtils::ReadSHORT(pStream) * dScaleX; if (bIndent4_) oRun.Indent4 = StreamUtils::ReadSHORT(pStream) * dScaleX; if (bLeftMargin5_) oRun.LeftMargin5 = StreamUtils::ReadSHORT(pStream) * dScaleX; if (bIndent5_) oRun.Indent5 = StreamUtils::ReadSHORT(pStream) * dScaleX; } void Read(POLE::Stream* pStream, PPT::CTextSIRun& oRun, bool bIsIndentation) { if (bIsIndentation) { oRun.lCount = StreamUtils::ReadDWORD(pStream); } _UINT32 dwFlags = StreamUtils::ReadDWORD(pStream); BYTE flag1 = (BYTE)(dwFlags); BYTE flag2 = (BYTE)(dwFlags >> 8); oRun.bSpell = (0x01 == (0x01 & flag1)); oRun.bLang = (0x02 == (0x02 & flag1)); oRun.bAltLang = (0x04 == (0x04 & flag1)); // unused // unused oRun.bPp10ext = (0x20 == (0x20 & flag1)); oRun.bBidi = (0x40 == (0x40 & flag1)); // unused // reserved oRun.bSmartTag = (0x02 == (0x02 & flag2)); if (oRun.bSpell) { oRun.Spell = StreamUtils::ReadWORD(pStream); } if (oRun.bLang) { oRun.Lang = StreamUtils::ReadWORD(pStream); } if (oRun.bAltLang) { oRun.AltLang = StreamUtils::ReadWORD(pStream); } if (oRun.bBidi) { oRun.Bidi = StreamUtils::ReadWORD(pStream); } if (oRun.bPp10ext) { _UINT32 dwFlags = StreamUtils::ReadDWORD(pStream); BYTE flag1 = (BYTE)(dwFlags); BYTE flag2 = (BYTE)(dwFlags >> 8); BYTE flag3 = (BYTE)(dwFlags >> 16); BYTE flag4 = (BYTE)(dwFlags >> 24); oRun.pp10runid = (0x0F & flag1); oRun.bGramma = (0x80 == (0x80 & flag4)); } /*if (bSmartTag) { _UINT32 tabStopsCount = StreamUtils::ReadDWORD(pStream); arSmartTags.clear(); for (int i = 0; i < (int)tabStopsCount; ++i) { arSmartTags.Add(StreamUtils::ReadDWORD(pStream)); } }*/ } void Read(POLE::Stream *pStream, ODRAW::SPointAtom &oAtom) { oAtom.X = StreamUtils::ReadLONG(pStream); oAtom.Y = StreamUtils::ReadLONG(pStream); } void Read(POLE::Stream *pStream, ODRAW::SColorAtom &oAtom) { oAtom.R = StreamUtils::ReadBYTE(pStream); oAtom.G = StreamUtils::ReadBYTE(pStream); oAtom.B = StreamUtils::ReadBYTE(pStream); oAtom.Index = StreamUtils::ReadBYTE(pStream); oAtom.bPaletteIndex = oAtom.bPaletteRGB = oAtom.bSystemRGB = oAtom.bSysIndex = oAtom.bSchemeIndex = false; if (oAtom.Index != 0xFF) { oAtom.bPaletteRGB = (oAtom.Index == 0xFE); oAtom.bSchemeIndex = (oAtom.Index != 0xFE); } } } CTextPFRunRecord::CTextPFRunRecord() : m_oRun() { m_lLevel = -1; m_lCount = 0; } CTextPFRunRecord::CTextPFRunRecord(const CTextPFRunRecord &oSrc) { *this = oSrc; } CTextPFRunRecord &CTextPFRunRecord::operator=(const CTextPFRunRecord &oSrc) { m_oRun = oSrc.m_oRun; m_lLevel = oSrc.m_lLevel; m_lCount = oSrc.m_lCount; return *this; } void CTextPFRunRecord::LoadFromStream(POLE::Stream* pStream, bool bIsIndentation) { double dScaleX = 625 * 2.54; //1/576 inch = 72/576 pt = 360000 *72 * 2.54 /(72*576) emu if (bIsIndentation) { m_lCount = StreamUtils::ReadLONG(pStream); m_lLevel = (LONG)StreamUtils::ReadWORD(pStream); if (m_lLevel > 0x0004) m_lLevel = 0x0004; } _UINT32 dwFlags = StreamUtils::ReadDWORD(pStream); BYTE flag1 = (BYTE)(dwFlags); BYTE flag2 = (BYTE)(dwFlags >> 8); BYTE flag3 = (BYTE)(dwFlags >> 16); BYTE flag4 = (BYTE)(dwFlags >> 24); //флаги чтения bool hasBullet_ = (0x01 == (0x01 & flag1)); bool bulletHasFont_ = (0x02 == (0x02 & flag1)); bool bulletHasColor_ = (0x04 == (0x04 & flag1)); bool bulletHasSize_ = (0x08 == (0x08 & flag1)); bool bulletFontRef_ = (0x10 == (0x10 & flag1)); bool bulletColor_ = (0x20 == (0x20 & flag1)); bool bulletSize_ = (0x40 == (0x40 & flag1)); bool bulletChar_ = (0x80 == (0x80 & flag1)); bool leftMargin_ = (0x01 == (0x01 & flag2)); // reserved bool indent_ = (0x04 == (0x04 & flag2)); bool textAlignment_ = (0x08 == (0x08 & flag2)); bool lineSpacing_ = (0x10 == (0x10 & flag2)); bool spaceBefore_ = (0x20 == (0x20 & flag2)); bool spaceAfter_ = (0x40 == (0x40 & flag2)); bool defaultTabSize_ = (0x80 == (0x80 & flag2)); bool fontAlign_ = (0x01 == (0x01 & flag3)); bool charWrap_ = (0x02 == (0x02 & flag3)); bool wordWrap_ = (0x04 == (0x04 & flag3)); bool overflow_ = (0x08 == (0x08 & flag3)); bool tabStops_ = (0x10 == (0x10 & flag3)); bool textDirection_ = (0x20 == (0x20 & flag3)); //reserved bool bulletBlip_ = (0x80 == (0x80 & flag3)); bool bulletScheme_ = (0x01 == (0x01 & flag4)); bool bulletHasScheme_ = (0x02 == (0x02 & flag4)); WORD bulletFlag = 0; if (hasBullet_ || bulletHasFont_ || bulletHasColor_ || bulletHasSize_) { bulletFlag = StreamUtils::ReadWORD(pStream); if (bulletFlag & 0x0F) { m_oRun.hasBullet = (bool)(0x01 == (bulletFlag & 0x01)); } else m_oRun.hasBullet = false; } if (bulletChar_) { unsigned short utf16 = (unsigned short)StreamUtils::ReadWORD(pStream); if (utf16 > 0x0013) { if (sizeof(wchar_t) == 2) { m_oRun.bulletChar = utf16; } else { std::wstring utf32 = NSFile::CUtf8Converter::GetWStringFromUTF16(&utf16, 1); if (!utf32.empty()) m_oRun.bulletChar = utf32.c_str()[0]; } } } if (bulletFontRef_) { m_oRun.bulletFontRef = StreamUtils::ReadWORD(pStream); if (bulletFlag & 0x0F) { if (!(0x02 == (bulletFlag & 0x02))) m_oRun.bulletFontRef.reset(); } } if (bulletSize_) { m_oRun.bulletSize = StreamUtils::ReadWORD(pStream); if (bulletFlag & 0x0F) { if (!(0x08 == (bulletFlag & 0x08))) m_oRun.bulletSize.reset(); } } if (bulletColor_) { ODRAW::SColorAtom oColorAtom; NSStreamReader::Read(pStream, oColorAtom); ODRAW::CColor oColor; oColor.R = oColorAtom.R; oColor.G = oColorAtom.G; oColor.B = oColorAtom.B; oColor.A = 255; oColor.m_lSchemeIndex = -1; if (oColorAtom.bSchemeIndex) { oColor.m_lSchemeIndex = oColorAtom.Index; ODRAW::CorrectColorPPT(oColor.m_lSchemeIndex); } if (oColorAtom.bSchemeIndex || oColorAtom.bPaletteRGB) { m_oRun.bulletColor = oColor; if (bulletFlag & 0x0F) { if (!(0x04 == (bulletFlag & 0x04))) m_oRun.bulletColor.reset(); } } } if (textAlignment_) m_oRun.textAlignment = StreamUtils::ReadWORD(pStream); if (lineSpacing_) m_oRun.lineSpacing = -StreamUtils::ReadSHORT(pStream); if (spaceBefore_) m_oRun.spaceBefore = -StreamUtils::ReadSHORT(pStream); if (spaceAfter_) m_oRun.spaceAfter = -StreamUtils::ReadSHORT(pStream); if (leftMargin_) m_oRun.leftMargin = StreamUtils::ReadSHORT(pStream) * dScaleX; if (indent_) m_oRun.indent = StreamUtils::ReadSHORT(pStream) * dScaleX; if (defaultTabSize_) m_oRun.defaultTabSize = (_INT32)StreamUtils::ReadWORD(pStream) * dScaleX; if (tabStops_) { WORD tabStopsCount = StreamUtils::ReadWORD(pStream); m_oRun.tabStops.clear(); tabStopsCount = tabStopsCount & 0x000f; for (int i = 0; i < (int)tabStopsCount; ++i) { WORD tabPos = StreamUtils::ReadWORD(pStream); WORD tabType = StreamUtils::ReadWORD(pStream); if ((tabPos & 0xff00) == 0xff00) break; m_oRun.tabStops.push_back(std::pair(tabPos * dScaleX, tabType)); } //if (0 < m_oRun.tabStops.size()) // m_oRun.defaultTabSize = m_oRun.tabStops[0]; } if (fontAlign_) m_oRun.fontAlign = StreamUtils::ReadWORD(pStream); if (charWrap_ || wordWrap_ || overflow_) { m_oRun.wrapFlags = StreamUtils::ReadWORD(pStream); } if (textDirection_) m_oRun.textDirection = StreamUtils::ReadWORD(pStream); } CTextCFRunRecord::CTextCFRunRecord() : m_oRun() { m_lCount = 0; } CTextCFRunRecord::CTextCFRunRecord(const CTextCFRunRecord &oSrc) { *this = oSrc; } CTextCFRunRecord &CTextCFRunRecord::operator=(const CTextCFRunRecord &oSrc) { m_oRun = oSrc.m_oRun; m_lCount = oSrc.m_lCount; return *this; } void CTextCFRunRecord::LoadFromStream(POLE::Stream* pStream, bool bIsIndentation) { if (bIsIndentation) { m_lCount = StreamUtils::ReadLONG(pStream); } _UINT32 dwFlags = StreamUtils::ReadDWORD(pStream); BYTE flag1 = (BYTE)(dwFlags); BYTE flag2 = (BYTE)(dwFlags >> 8); BYTE flag3 = (BYTE)(dwFlags >> 16); BYTE flag4 = (BYTE)(dwFlags >> 24); bool hasBold = (0x01 == (0x01 & flag1)); bool hasItalic = (0x02 == (0x02 & flag1)); bool hasUnderline = (0x04 == (0x04 & flag1)); // unused bool hasShadow = (0x10 == (0x10 & flag1)); bool hasFehint = (0x20 == (0x20 & flag1)); // unused bool hasKimi = (0x80 == (0x80 & flag1)); // unused bool hasEmboss = (0x02 == (0x02 & flag2)); // unused BYTE hasStyle = ((0x3C & flag2) >> 2); // unused bool typeface_ = (0x01 == (0x01 & flag3)); bool size_ = (0x02 == (0x02 & flag3)); bool color_ = (0x04 == (0x04 & flag3)); bool BaseLineOffset_ = (0x08 == (0x08 & flag3)); bool EAFontRef_ = (0x20 == (0x20 & flag3)); bool AnsiFontRef_ = (0x40 == (0x40 & flag3)); bool SymbolFontRef_ = (0x80 == (0x80 & flag3)); bool hasNewEATypeface = (0x01 == (0x01 & flag4)); bool hasCsTypeface = (0x02 == (0x02 & flag4)); bool hasPp11ext = (0x04 == (0x04 & flag4)); bool bIsFontStylePresent = (hasBold || hasItalic || hasUnderline || hasShadow || hasFehint || hasKimi || hasEmboss || hasStyle != 0); if (bIsFontStylePresent) { WORD fontStyle = StreamUtils::ReadWORD(pStream); m_oRun.FontBold = 0x01 == (0x01 & fontStyle); m_oRun.FontItalic = 0x02 == (0x02 & fontStyle); m_oRun.FontUnderline = 0x04 == (0x04 & fontStyle); m_oRun.FontShadow = 0x10 == (0x10 & fontStyle); m_oRun.pp9rt = (0x3c00 & fontStyle) >> 10; } if (typeface_) m_oRun.fontRef = StreamUtils::ReadWORD(pStream); if (EAFontRef_) m_oRun.eaFontRef = StreamUtils::ReadWORD(pStream); if (AnsiFontRef_) m_oRun.ansiFontRef = StreamUtils::ReadWORD(pStream); if (SymbolFontRef_) m_oRun.symbolFontRef = StreamUtils::ReadWORD(pStream); if (size_) m_oRun.Size = StreamUtils::ReadWORD(pStream); if (color_) { ODRAW::SColorAtom oColorAtom; NSStreamReader::Read(pStream, oColorAtom); ODRAW::CColor oColor; oColor.R = oColorAtom.R; oColor.G = oColorAtom.G; oColor.B = oColorAtom.B; oColor.A = 255; oColor.m_lSchemeIndex = -1; if (oColorAtom.Index < 8 && oColorAtom.bSchemeIndex) { oColor.m_lSchemeIndex = oColorAtom.Index; ODRAW::CorrectColorPPT(oColor.m_lSchemeIndex); } if (oColorAtom.bSchemeIndex || oColorAtom.bPaletteRGB) { m_oRun.Color = oColor; } } if (BaseLineOffset_) m_oRun.BaseLineOffset = (double)StreamUtils::ReadSHORT(pStream); // или два последних наоборот???? } void ConvertPPTTextToEditorStructure(std::vector& oArrayPF, std::vector& oArrayCF, std::wstring& strText, PPT::CTextAttributesEx& oAttributes) { int nCountPFs = (int)oArrayPF.size(); int nCountCFs = (int)oArrayCF.size(); oAttributes.m_arParagraphs.clear(); oAttributes.m_originalText = strText; int nCurrentPF = 0; int nCurrentCF = 0; int nOffsetCF = 0; int nIndexLast = strText.length(); int nIndexText = 0; for (int nIndexPF = 0; nIndexPF < nCountPFs; ++nIndexPF) { CParagraph elm; oAttributes.m_arParagraphs.push_back(elm); PPT::CParagraph* pPar = &oAttributes.m_arParagraphs[nIndexPF]; pPar->m_lTextLevel = oArrayPF[nIndexPF].m_lLevel; pPar->m_oPFRun = oArrayPF[nIndexPF].m_oRun; pPar->m_lTextType = oAttributes.m_lTextType; pPar->m_lStyleThemeIndex = oAttributes.m_lStyleThemeIndex; int nCountInPF = oArrayPF[nIndexPF].m_lCount; while (true) { if (nCurrentCF >= nCountCFs) break; int nCountAdd = oArrayCF[nCurrentCF].m_lCount - nOffsetCF; int nCountAddTrue = nCountAdd; if (nIndexText + nCountAdd > nIndexLast) { nCountAddTrue = nIndexLast - nIndexText; if (nCountAddTrue < 0) nCountAddTrue = 0; } if (nCountAdd > nCountInPF) { nOffsetCF += nCountInPF; PPT::CSpan oSpan; oSpan.m_oRun = oArrayCF[nCurrentCF].m_oRun; nCountAddTrue = nCountInPF; if (nIndexText + nCountInPF > nIndexLast) { nCountAddTrue = nIndexLast - nIndexText; if (nCountAddTrue < 0) nCountAddTrue = 0; } if (nCountAddTrue > 0) { oSpan.m_strText = strText.substr(nIndexText, nCountAddTrue); pPar->m_arSpans.push_back(oSpan); } nIndexText += nCountInPF; break; } else if (nCountAdd == nCountInPF) { nOffsetCF = 0; PPT::CSpan oSpan; oSpan.m_oRun = oArrayCF[nCurrentCF].m_oRun; if (nCountAddTrue > 0) { oSpan.m_strText = strText.substr(nIndexText, nCountAddTrue); pPar->m_arSpans.push_back(oSpan); } nIndexText += nCountAdd; ++nCurrentCF; break; } else { nOffsetCF = 0; PPT::CSpan oSpan; oSpan.m_oRun = oArrayCF[nCurrentCF].m_oRun; if (nCountAddTrue > 0) { oSpan.m_strText = strText.substr(nIndexText, nCountAddTrue); pPar->m_arSpans.push_back(oSpan); } nIndexText += nCountAdd; nCountInPF -= nCountAdd; ++nCurrentCF; } } } } //------------------------------------------------------------------------------------ CMetaHeader::CMetaHeader() { } void CMetaHeader::FromStream(POLE::Stream* pStream, CRYPT::ECMADecryptor *pDecryptor) { BYTE pData[34]; pStream->read(pData, 34); if (pDecryptor) { pDecryptor->Decrypt((char*)pData, 34, 0); } MemoryStream memStream(pData, 34, false); cbSize = memStream.ReadUInt32(); rcBounds.left = memStream.ReadInt32(); rcBounds.top = memStream.ReadInt32(); rcBounds.right = memStream.ReadInt32(); rcBounds.bottom = memStream.ReadInt32(); ptSize.x = memStream.ReadInt32(); ptSize.y = memStream.ReadInt32(); cbSave = memStream.ReadUInt32(); compression = memStream.ReadByte(); filter = memStream.ReadByte(); } void CMetaHeader::ToEMFHeader(Gdiplus::ENHMETAHEADER3* pHeader) { if (NULL == pHeader) return; pHeader->iType = 0x00000001; pHeader->nSize = 88; pHeader->rclBounds.left = rcBounds.left; pHeader->rclBounds.top = rcBounds.top; pHeader->rclBounds.right = rcBounds.right; pHeader->rclBounds.bottom = rcBounds.bottom; // нужно перевести в мм pHeader->rclFrame.left = rcBounds.left; pHeader->rclFrame.top = rcBounds.top; pHeader->rclFrame.right = rcBounds.right; pHeader->rclFrame.bottom = rcBounds.bottom; pHeader->dSignature = 0x464D4520; pHeader->nVersion = 0x00010000; pHeader->nBytes = cbSize; pHeader->nRecords = 1; pHeader->nHandles = 0; pHeader->sReserved = 0; pHeader->nDescription = 0; pHeader->offDescription = 0; pHeader->nPalEntries = 0; pHeader->szlDevice.cx = 200; pHeader->szlDevice.cy = 200; // нужно перевести в мм pHeader->szlMillimeters.cx = 100; pHeader->szlMillimeters.cy = 100; } void CMetaHeader::ToWMFHeader(Gdiplus::WmfPlaceableFileHeader* pHeader) { if (NULL == pHeader) return; pHeader->Key = 0x9AC6CDD7; pHeader->Hmf = 0; pHeader->BoundingBox.Left = (short)rcBounds.left; pHeader->BoundingBox.Top = (short)rcBounds.top; pHeader->BoundingBox.Right = (short)rcBounds.right; pHeader->BoundingBox.Bottom = (short)rcBounds.bottom; pHeader->Inch = 1440; // 1:1 pHeader->Reserved = 0; pHeader->Checksum = 0; pHeader->Checksum ^= (pHeader->Key & 0x0000FFFFL); pHeader->Checksum ^= ((pHeader->Key & 0xFFFF0000L) >> 16); pHeader->Checksum ^= pHeader->Hmf; pHeader->Checksum ^= pHeader->BoundingBox.Left; pHeader->Checksum ^= pHeader->BoundingBox.Top; pHeader->Checksum ^= pHeader->BoundingBox.Right; pHeader->Checksum ^= pHeader->BoundingBox.Bottom; pHeader->Checksum ^= pHeader->Inch; pHeader->Checksum ^= (pHeader->Reserved & 0x0000FFFFL); pHeader->Checksum ^= ((pHeader->Reserved & 0xFFFF0000L) >> 16); } #define CLIPSIZE 12 #define PIXMAPRECSIZE 50 #define HEADERSIZE 40 #define MAXCOLORTABLESIZE 256*8+8 #define OPCODEMISCSIZE 2+8+8+2 /* opcode+srcRect+dstRect+mode */ #define ENDOFPICTSIZE 2 #define PICSIZE PIXMAPRECSIZE + HEADERSIZE + MAXCOLORTABLESIZE + ENDOFPICTSIZE + OPCODEMISCSIZE + CLIPSIZE void CMetaHeader::ToPICTHeader(BYTE *& pHeader, int & size) { short myRowBytes; short *picPtr; // short iii; // long handleSize; myRowBytes = cbSize & 0x3fff; //Skip picSize and put out picFrame (10 bytes). picPtr = (short *)pHeader; *picPtr++ = (short)myRowBytes; *picPtr++ = (short)rcBounds.top; *picPtr++ = (short)rcBounds.left; *picPtr++ = (short)rcBounds.bottom; *picPtr++ = (short)rcBounds.right; // Put out header (30 bytes). This could be done from a resource or taken from an existing picture. *picPtr++ = 0x11; /* Version opcode. */ *picPtr++ = 0x2ff; /* Version number. */ *picPtr++ = 0xC00; /* Header opcode. */ *picPtr++ = 0xFFFF; /* Put out PICT header version. */ *picPtr++ = 0xFFFF; //The rest of the header is ignored--0 it out. for (int iii = 10; iii > 0; iii--) *picPtr++ = 0; /* Write out 24 bytes of 0. */ /* Put out current port's clip region. */ *picPtr++ = 0x01; *picPtr++ = 0x0A; /* Clip region only has bounds rectangle. */ *picPtr++ = (short)rcBounds.top; *picPtr++ = (short)rcBounds.left; *picPtr++ = (short)rcBounds.bottom; *picPtr++ = (short)rcBounds.right; //filter ??? //if(srcBits->pixelType == RGBDirect) //{ /* Must be 32-bits/pixel */ ///* Put out opCode $9A, DirectBitsRect. */ *picPtr++ = 0x9A; // *picPtr++ = 0; /* BaseAddr for direct pixMaps is 0x000000FF. */ // *picPtr++ = 0xFF; // PutOutPixMapSrcRectDstRectAndMode(srcBits, &picPtr, srcRect, // dstRect, mode); // if(PutOutPackedDirectPixData(srcBits, &picPtr)) /* Nonzero // indicates an error. */ // goto errorExit; //} //else //{ /* Put out opCode $98, PackBitsRect. */ //*picPtr++ = 0x98; //PutOutPixMapSrcRectDstRectAndMode(srcBits, &picPtr, srcRect, dstRect, mode); //if(PutOutPackedIndexedPixData(srcBits, &picPtr)) //{ // /* Nonzero indicates an error. */ //} //} int sz = ((BYTE*)picPtr - pHeader); size = sz; } CMetaFileBuffer::CMetaFileBuffer() { m_bIsCompressed = false; m_bIsValid = false; m_pMetaHeader = NULL; m_pMetaFile = NULL; m_lMetaHeaderSize = 0; m_lMetaFileSize = 0; } CMetaFileBuffer::~CMetaFileBuffer() { RELEASEARRAYOBJECTS(m_pMetaHeader); RELEASEARRAYOBJECTS(m_pMetaFile); if (m_bIsCompressed) RELEASEARRAYOBJECTS(m_pMetaFile); m_bIsCompressed = false; } void CMetaFileBuffer::SetHeader(BYTE *pHeader, LONG lSize) { m_pMetaHeader = pHeader; m_lMetaHeaderSize = lSize; } void CMetaFileBuffer::SetData(BYTE *pCompress, LONG lCompressSize, LONG lUncompressSize, bool bIsCompressed) { m_bIsCompressed = bIsCompressed; if (!m_bIsCompressed) { m_pMetaFile = pCompress; m_lMetaFileSize = lUncompressSize; } else { ULONG lSize = lUncompressSize; m_pMetaFile = new BYTE[lUncompressSize]; bool bRes = NSZip::Decompress(pCompress, (ULONG)lCompressSize, m_pMetaFile, lSize); if (bRes) { m_lMetaFileSize = (LONG)lSize; m_bIsCompressed = true; } else { RELEASEARRAYOBJECTS(m_pMetaFile); m_pMetaFile = pCompress; m_lMetaFileSize = lUncompressSize; m_bIsCompressed = false; } } } int CMetaFileBuffer::ToBuffer(BYTE*& Data) { int sz = 0; if (NULL != m_pMetaHeader) sz += m_lMetaHeaderSize; if (NULL != m_pMetaFile) sz += m_lMetaFileSize; Data = new BYTE[sz]; int pos = 0; if (NULL != m_pMetaHeader) { memcpy(Data, (BYTE*)m_pMetaHeader, m_lMetaHeaderSize); pos += m_lMetaHeaderSize; } if (NULL != m_pMetaFile) { memcpy(Data + pos, (BYTE*)m_pMetaFile, m_lMetaFileSize); } return sz; } void CMetaFileBuffer::ToFile(NSFile::CFileBinary *pFile) { if (NULL != m_pMetaHeader) { pFile->WriteFile(m_pMetaHeader, m_lMetaHeaderSize); } if (NULL != m_pMetaFile) { pFile->WriteFile(m_pMetaFile, m_lMetaFileSize); } } void SScalingAtom::FromStream(POLE::Stream *pStream) { X.FromStream(pStream); Y.FromStream(pStream); } void SRatioAtom::FromStream(POLE::Stream *pStream) { Number = StreamUtils::ReadLONG(pStream); Denom = StreamUtils::ReadLONG(pStream); } void SFileIdCluster::ReadFromStream(POLE::Stream *pStream) { DrawingGroupID = (UINT)StreamUtils::ReadDWORD(pStream); CurrentShapeID = (UINT)StreamUtils::ReadDWORD(pStream); } }