Commit 8a7c8660 authored by Ilya.Kirillov's avatar Ilya.Kirillov Committed by Alexander Trofimov

Добавлена новая кроссплатформенная библиотека для записи Pdf файлов.

git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@63069 954022d7-b5bf-4e40-9824-e11837661b57
parent 03bcfc8e
......@@ -7338,6 +7338,9 @@ PdfReader/Resources/Fonts/n022024l.pfm svn_mime_002dtype=application%2Foctet-str
PdfReader/Resources/Fonts/s050000l.pfb svn_mime_002dtype=application%2Foctet-stream
PdfReader/Resources/Fonts/s050000l.pfm svn_mime_002dtype=application%2Foctet-stream
PdfReader/Src svnc_tsvn_003alogminsize=5
/PdfWriter svnc_tsvn_003alogminsize=5
PdfWriter/PdfWriterTest svnc_tsvn_003alogminsize=5
PdfWriter/Src svnc_tsvn_003alogminsize=5
Redist/ASCEBOOKWriter.dll svn_mime_002dtype=application%2Foctet-stream
Redist/ASCFontConverter.dll svn_mime_002dtype=application%2Foctet-stream
Redist/ASCGraphics.dll svn_mime_002dtype=application%2Foctet-stream

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30723.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PdfWriter", "PdfWriter.vcxproj", "{D4A77282-62EC-465D-ACB4-9CEE6BC704E5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PdfWriterTest", "PdfWriterTest\PdfWriterTest.vcxproj", "{B819B482-8822-4809-B633-09F8946D761E}"
ProjectSection(ProjectDependencies) = postProject
{D4A77282-62EC-465D-ACB4-9CEE6BC704E5} = {D4A77282-62EC-465D-ACB4-9CEE6BC704E5}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Mixed Platforms = Release|Mixed Platforms
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D4A77282-62EC-465D-ACB4-9CEE6BC704E5}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{D4A77282-62EC-465D-ACB4-9CEE6BC704E5}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{D4A77282-62EC-465D-ACB4-9CEE6BC704E5}.Debug|Win32.ActiveCfg = Debug|x64
{D4A77282-62EC-465D-ACB4-9CEE6BC704E5}.Debug|Win32.Build.0 = Debug|x64
{D4A77282-62EC-465D-ACB4-9CEE6BC704E5}.Debug|x64.ActiveCfg = Debug|x64
{D4A77282-62EC-465D-ACB4-9CEE6BC704E5}.Debug|x64.Build.0 = Debug|x64
{D4A77282-62EC-465D-ACB4-9CEE6BC704E5}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{D4A77282-62EC-465D-ACB4-9CEE6BC704E5}.Release|Mixed Platforms.Build.0 = Release|Win32
{D4A77282-62EC-465D-ACB4-9CEE6BC704E5}.Release|Win32.ActiveCfg = Release|Win32
{D4A77282-62EC-465D-ACB4-9CEE6BC704E5}.Release|Win32.Build.0 = Release|Win32
{D4A77282-62EC-465D-ACB4-9CEE6BC704E5}.Release|x64.ActiveCfg = Release|x64
{D4A77282-62EC-465D-ACB4-9CEE6BC704E5}.Release|x64.Build.0 = Release|x64
{B819B482-8822-4809-B633-09F8946D761E}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{B819B482-8822-4809-B633-09F8946D761E}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{B819B482-8822-4809-B633-09F8946D761E}.Debug|Win32.ActiveCfg = Debug|Win32
{B819B482-8822-4809-B633-09F8946D761E}.Debug|Win32.Build.0 = Debug|Win32
{B819B482-8822-4809-B633-09F8946D761E}.Debug|x64.ActiveCfg = Debug|x64
{B819B482-8822-4809-B633-09F8946D761E}.Debug|x64.Build.0 = Debug|x64
{B819B482-8822-4809-B633-09F8946D761E}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{B819B482-8822-4809-B633-09F8946D761E}.Release|Mixed Platforms.Build.0 = Release|Win32
{B819B482-8822-4809-B633-09F8946D761E}.Release|Win32.ActiveCfg = Release|Win32
{B819B482-8822-4809-B633-09F8946D761E}.Release|Win32.Build.0 = Release|Win32
{B819B482-8822-4809-B633-09F8946D761E}.Release|x64.ActiveCfg = Release|x64
{B819B482-8822-4809-B633-09F8946D761E}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{D4A77282-62EC-465D-ACB4-9CEE6BC704E5}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>PdfWriter</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DisableSpecificWarnings>4018;4005;4267</DisableSpecificWarnings>
<AdditionalIncludeDirectories>..\DesktopEditor\freetype-2.5.2\include;..\DesktopEditor\agg-2.4\include;..\DesktopEditor\cximage\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Src\Annotation.cpp" />
<ClCompile Include="Src\Catalog.cpp" />
<ClCompile Include="Src\Destination.cpp" />
<ClCompile Include="Src\Document.cpp" />
<ClCompile Include="Src\Encrypt.cpp" />
<ClCompile Include="Src\EncryptDictionary.cpp" />
<ClCompile Include="Src\Font.cpp" />
<ClCompile Include="Src\Font14.cpp" />
<ClCompile Include="Src\FontCidTT.cpp" />
<ClCompile Include="Src\FontTTWriter.cpp" />
<ClCompile Include="Src\GState.cpp" />
<ClCompile Include="Src\Image.cpp" />
<ClCompile Include="Src\Info.cpp" />
<ClCompile Include="Src\Objects.cpp" />
<ClCompile Include="Src\Outline.cpp" />
<ClCompile Include="Src\Pages.cpp" />
<ClCompile Include="Src\Pattern.cpp" />
<ClCompile Include="Src\Shading.cpp" />
<ClCompile Include="Src\Streams.cpp" />
<ClCompile Include="Src\Utils.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Src\Annotation.h" />
<ClInclude Include="Src\Catalog.h" />
<ClInclude Include="Src\Consts.h" />
<ClInclude Include="Src\Destination.h" />
<ClInclude Include="Src\Document.h" />
<ClInclude Include="Src\Encrypt.h" />
<ClInclude Include="Src\EncryptDictionary.h" />
<ClInclude Include="Src\Font.h" />
<ClInclude Include="Src\Font14.h" />
<ClInclude Include="Src\FontCidTT.h" />
<ClInclude Include="Src\FontTTWriter.h" />
<ClInclude Include="Src\GState.h" />
<ClInclude Include="Src\Image.h" />
<ClInclude Include="Src\Info.h" />
<ClInclude Include="Src\Objects.h" />
<ClInclude Include="Src\Outline.h" />
<ClInclude Include="Src\Pages.h" />
<ClInclude Include="Src\Pattern.h" />
<ClInclude Include="Src\Shading.h" />
<ClInclude Include="Src\Streams.h" />
<ClInclude Include="Src\Types.h" />
<ClInclude Include="Src\Utils.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Src">
<UniqueIdentifier>{1fccc0b6-4331-4120-a261-6d13ed199aab}</UniqueIdentifier>
</Filter>
<Filter Include="Src\Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Src\Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Src\Font">
<UniqueIdentifier>{207e9ca3-771d-48cd-b185-e8557f5a59c9}</UniqueIdentifier>
</Filter>
<Filter Include="Src\Encrypt">
<UniqueIdentifier>{e955fc8f-90e5-44a8-89b6-4f281e87c89a}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Src\Annotation.cpp">
<Filter>Src\Source Files</Filter>
</ClCompile>
<ClCompile Include="Src\Catalog.cpp">
<Filter>Src\Source Files</Filter>
</ClCompile>
<ClCompile Include="Src\Destination.cpp">
<Filter>Src\Source Files</Filter>
</ClCompile>
<ClCompile Include="Src\Document.cpp">
<Filter>Src\Source Files</Filter>
</ClCompile>
<ClCompile Include="Src\GState.cpp">
<Filter>Src\Source Files</Filter>
</ClCompile>
<ClCompile Include="Src\Image.cpp">
<Filter>Src\Source Files</Filter>
</ClCompile>
<ClCompile Include="Src\Info.cpp">
<Filter>Src\Source Files</Filter>
</ClCompile>
<ClCompile Include="Src\Objects.cpp">
<Filter>Src\Source Files</Filter>
</ClCompile>
<ClCompile Include="Src\Outline.cpp">
<Filter>Src\Source Files</Filter>
</ClCompile>
<ClCompile Include="Src\Pages.cpp">
<Filter>Src\Source Files</Filter>
</ClCompile>
<ClCompile Include="Src\Streams.cpp">
<Filter>Src\Source Files</Filter>
</ClCompile>
<ClCompile Include="Src\Utils.cpp">
<Filter>Src\Source Files</Filter>
</ClCompile>
<ClCompile Include="Src\Font.cpp">
<Filter>Src\Font</Filter>
</ClCompile>
<ClCompile Include="Src\Encrypt.cpp">
<Filter>Src\Encrypt</Filter>
</ClCompile>
<ClCompile Include="Src\EncryptDictionary.cpp">
<Filter>Src\Encrypt</Filter>
</ClCompile>
<ClCompile Include="Src\Font14.cpp">
<Filter>Src\Font</Filter>
</ClCompile>
<ClCompile Include="Src\FontCidTT.cpp">
<Filter>Src\Font</Filter>
</ClCompile>
<ClCompile Include="Src\FontTTWriter.cpp">
<Filter>Src\Font</Filter>
</ClCompile>
<ClCompile Include="Src\Shading.cpp">
<Filter>Src\Source Files</Filter>
</ClCompile>
<ClCompile Include="Src\Pattern.cpp">
<Filter>Src\Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Src\Annotation.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\Catalog.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\Consts.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\Destination.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\Document.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\GState.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\Image.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\Info.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\Objects.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\Outline.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\Pages.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\Streams.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\Types.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\Utils.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\Font.h">
<Filter>Src\Font</Filter>
</ClInclude>
<ClInclude Include="Src\Encrypt.h">
<Filter>Src\Encrypt</Filter>
</ClInclude>
<ClInclude Include="Src\EncryptDictionary.h">
<Filter>Src\Encrypt</Filter>
</ClInclude>
<ClInclude Include="Src\Font14.h">
<Filter>Src\Font</Filter>
</ClInclude>
<ClInclude Include="Src\FontCidTT.h">
<Filter>Src\Font</Filter>
</ClInclude>
<ClInclude Include="Src\FontTTWriter.h">
<Filter>Src\Font</Filter>
</ClInclude>
<ClInclude Include="Src\Shading.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
<ClInclude Include="Src\Pattern.h">
<Filter>Src\Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file
// PdfWriterTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "../Src/Streams.h"
#include "../Src/Utils.h"
#include "../Src/Objects.h"
#include "../Src/Encrypt.h"
#include "../Src/Info.h"
#include "../Src/Document.h"
#include "../Src/Outline.h"
#include "../Src/Destination.h"
#include "../Src/Pages.h"
#include "../Src/Annotation.h"
#include "../Src/Image.h"
#include "../Src/Font.h"
#include "../Src/Font14.h"
#include "../Src/FontCidTT.h"
#include "../Src/Pattern.h"
#include <iostream>
#include "../../DesktopEditor/raster/BgraFrame.h"
#include "../../DesktopEditor/common/File.h"
#include "../../DesktopEditor/cximage/CxImage/ximage.h"
#include "../../DesktopEditor/cximage/CxImage/ximatif.h"
#include "../../DesktopEditor/raster/BgraFrame.h"
#include "../../DesktopEditor/cximage/tiff/tiffio.h"
#ifdef DrawText
#undef DrawText
#endif
using namespace PdfWriter;
void TestStreams()
{
CFileStream oFS;
oFS.OpenFile(L"D:/Test Files/1.txt", false);
while (!oFS.IsEof())
{
char nChar = oFS.ReadChar();
std::cout << nChar;
}
CMemoryStream oMS;
oMS.WriteStream(&oFS, 0, NULL);
CFileStream oTS;
oTS.OpenFile(L"D:/Test Files/TestStreams.tmp", true);
oTS.WriteStream(&oMS, 0, NULL);
oTS.WriteChar(' ');
oTS.WriteChar('c');
oTS.WriteChar(' ');
oTS.WriteBinary((const BYTE*)"123", 3, NULL);
oTS.WriteChar(' ');
oTS.WriteEscapeName((const char*)"EscapeName");
oTS.WriteChar(' ');
oTS.WriteEscapeText((const BYTE*)"EscapeTest", StrLen("EscapeTest", 12));
oTS.WriteChar(' ');
oTS.WriteHex(251, 2);
oTS.WriteChar(' ');
oTS.WriteHex(251, 4);
oTS.WriteChar(' ');
oTS.WriteInt(63);
oTS.WriteChar(' ');
oTS.WriteReal(0.12);
oTS.WriteChar(' ');
oTS.WriteStr("String");
oTS.WriteChar(' ');
oTS.Close();
CFileStream oTS2;
oTS2.OpenFile(L"D:/Test Files/TestStreamsFilter.tmp", true);
oTS2.WriteStream(&oMS, STREAM_FILTER_FLATE_DECODE, NULL);
oTS2.Close();
}
void TestObjects()
{
CStream* pStream = new CFileStream();
((CFileStream*)pStream)->OpenFile(L"D:/Test Files/TestObjects.tmp", true);
CNullObject oNull;
pStream->Write(&oNull);
pStream->WriteChar('\n');
CBoolObject oBool = true;
pStream->Write(&oBool);
pStream->WriteChar('\n');
CNumberObject oNumber = 75;
pStream->Write(&oNumber);
pStream->WriteChar('\n');
CRealObject oReal = 13.756;
pStream->Write(&oReal);
pStream->WriteChar('\n');
CNameObject oName = "Name";
pStream->Write(&oName);
pStream->WriteChar('\n');
CStringObject oString("String");
pStream->Write(&oString, NULL);
pStream->WriteChar('\n');
CBinaryObject oBinary((BYTE*)"123", 3);
pStream->Write(&oBinary, NULL);
pStream->WriteChar('\n');
CArrayObject* pArray = new CArrayObject();
pArray->Add(12);
pArray->Add(0.13);
pArray->Add(13.1);
pStream->Write(pArray, NULL);
pStream->WriteChar('\n');
CProxyObject oProxy(pArray);
oProxy.SetRef(123, 0);
pStream->Write(&oProxy, NULL);
pStream->WriteChar('\n');
CDictObject oDict;
oDict.Add("Bool", true);
oDict.Add("Real", 0.12);
oDict.Add("Number", 12);
oDict.Add("Name", "SomeName");
oDict.Add("Array", pArray);
pStream->Write(&oDict, NULL);
pStream->WriteChar('\n');
delete pStream;
}
void TestEncrypt()
{
CEncrypt oEncrypt;
oEncrypt.Init();
oEncrypt.InitKey(1231, 0);
CFileStream oFS;
oFS.OpenFile(L"D:/Test Files/TestStreams.tmp", false);
CFileStream oTS;
oTS.OpenFile(L"D:/Test Files/TestEncrypt.tmp", true);
oTS.WriteStream(&oFS, 0, &oEncrypt);
oTS.Close();
oFS.Close();
}
void TestDict()
{
CStream* pStream = new CFileStream();
((CFileStream*)pStream)->OpenFile(L"D:/Test Files/TestDict.tmp", true);
CXref oXref(0);
CDictObject* pDict = new CDictObject(&oXref);
pDict->Add("Bool", true);
pDict->Add("Real", 0.12);
pDict->Add("Number", 12);
pDict->Add("Name", "SomeName");
pDict->Add("Array", new CArrayObject());
CStream* pDictStream = pDict->GetStream();
pDictStream->WriteEscapeText((BYTE*)"TestTest", 8);
pDictStream->WriteBinary((BYTE*)"TestTest", 8, NULL);
CDictObject* pDict2 = new CDictObject(&oXref);
pDict2->Add("Bool", true);
pDict2->Add("Real", 0.12);
pDict2->Add("Number", 12);
pDict2->Add("Name", "SomeName");
pDict2->Add("Array", new CArrayObject());
pDict2->SetFilter(STREAM_FILTER_FLATE_DECODE);
CStream* pDictStream2 = pDict2->GetStream();
pDictStream2->WriteEscapeText((BYTE*)"TestTest", 8);
pDictStream2->WriteBinary((BYTE*)"TestTest", 8, NULL);
TDate oDate;
MemSet(&oDate, 0, sizeof(oDate));
oDate.nDay = 18;
oDate.nMonth = 10;
oDate.nYear = 1986;
oDate.nHour = 12;
oDate.nMinutes = 0;
oDate.nSeconds = 0;
oDate.nInd = '-';
CInfoDict* pInfo = new CInfoDict(&oXref);
pInfo->SetInfo(EInfoType::InfoCreator, "Ilya");
pInfo->SetInfo(EInfoType::InfoCreationDate, oDate);
oXref.WriteToStream(pStream, NULL);
delete pStream;
}
void TestDocument1()
{
// PageLabels and Encryption
CDocument oPdf;
oPdf.CreateNew();
oPdf.AddPage();
oPdf.AddPageLabel(pagenumstyle_Decimal, 1, "Dec-");
oPdf.AddPage();
oPdf.AddPage();
oPdf.AddPageLabel(2, pagenumstyle_UpperRoman, 21, "UppRom-");
oPdf.SetPassword("123", "qwe");
oPdf.SetPermission(ENABLE_READ);
oPdf.SetEncryptionMode(encryptmode_R3);
oPdf.SaveToFile(L"D:/Test Files/Test1.pdf");
oPdf.Close();
}
void TestDocument2()
{
// Outline
CDocument oPdf;
oPdf.CreateNew();
oPdf.AddPage();
oPdf.AddPage();
oPdf.AddPage();
oPdf.AddPage();
COutline* pOutline1 = oPdf.CreateOutline(NULL, "Test1");
COutline* pOutline11 = oPdf.CreateOutline(pOutline1, "Test1.1");
COutline* pOutline111 = oPdf.CreateOutline(pOutline11, "Test1.1.1");
COutline* pOutline12 = oPdf.CreateOutline(pOutline1, "Test1.2");
COutline* pOutline2 = oPdf.CreateOutline(NULL, "Test2");
COutline* pOutline21 = oPdf.CreateOutline(pOutline2, "Test21");
COutline* pOutline22 = oPdf.CreateOutline(pOutline2, "Test22");
COutline* pOutline23 = oPdf.CreateOutline(pOutline2, "Test23");
COutline* pOutline221 = oPdf.CreateOutline(pOutline22, "Test223");
CDestination* pDest = oPdf.CreateDestination(2);
pDest->SetXYZ(0, 792, 0);
pOutline21->SetDestination(pDest);
pDest = oPdf.CreateDestination(3);
pDest->SetFit();
pOutline11->SetDestination(pDest);
oPdf.SaveToFile(L"D:/Test Files/Test2.pdf");
oPdf.Close();
}
void TestDocument3()
{
CDocument oPdf;
oPdf.CreateNew();
CPage* pPage;
pPage = oPdf.AddPage();
pPage->SetHeight(100);
pPage->SetWidth(100);
pPage->MoveTo(10, 10);
pPage->LineTo(20, 20);
pPage->CurveTo(70, 30, 30, 20, 50, 50);
pPage->ClosePath();
pPage->Fill();
pPage = oPdf.AddPage();
pPage->SetHeight(400);
pPage->SetWidth(600);
pPage->Ellipse(200, 200, 50, 100);
pPage->Fill();
pPage->GrSave();
double dAngle = 30 * 3.141592f / 180;
pPage->Concat(cos(dAngle), -sin(dAngle), sin(dAngle), cos(dAngle), -50, 50);
pPage->MoveTo(400, 200);
pPage->EllipseArcTo(400, 200, 50, 100, 0, 145);
pPage->Stroke();
pPage->GrRestore();
double pPattern[] ={ 1, 5, 5, 2 };
pPage->SetDash((const double*)pPattern, 4, 5);
pPage->MoveTo(10, 10);
pPage->LineTo(20, 20);
pPage->CurveTo(70, 30, 30, 20, 50, 50);
pPage->ClosePath();
pPage->Stroke();
pPage = oPdf.AddPage();
pPage->SetHeight(600);
pPage->SetWidth(400);
pPage->MoveTo(10, 10);
pPage->LineTo(350, 10);
pPage->LineTo(350, 350);
pPage->LineTo(10, 350);
pPage->ClosePath();
pPage->Stroke();
pPage->SetLineWidth(4);
pPage->GrSave();
pPage->SetLineCap(linecap_Butt);
pPage->MoveTo(20, 20);
pPage->LineTo(330, 20);
pPage->Stroke();
pPage->SetLineCap(linecap_Round);
pPage->MoveTo(20, 40);
pPage->LineTo(330, 40);
pPage->Stroke();
pPage->SetLineCap(linecap_ProjectingSquare);
pPage->MoveTo(20, 60);
pPage->LineTo(330, 60);
pPage->Stroke();
pPage->GrRestore();
pPage->GrSave();
double pPattern1[] ={ 1, 5, 5, 2 };
pPage->SetDash((const double*)pPattern1, 4, 0);
pPage->MoveTo(20, 80);
pPage->LineTo(330, 80);
pPage->Stroke();
double pPattern2[] ={ 1, 5, 5, 2 };
pPage->SetDash((const double*)pPattern2, 4, 5);
pPage->MoveTo(20, 100);
pPage->LineTo(330, 100);
pPage->Stroke();
pPage->GrRestore();
pPage->GrSave();
pPage->SetStrokeColor(255, 0, 0);
pPage->SetLineJoin(linejoin_Bevel);
pPage->MoveTo(20, 120);
pPage->LineTo(100, 120);
pPage->LineTo(100, 180);
pPage->Stroke();
pPage->SetStrokeColor(0, 255, 0);
pPage->SetLineJoin(linejoin_Miter);
pPage->SetMiterLimit(30);
pPage->MoveTo(120, 120);
pPage->LineTo(210, 120);
pPage->LineTo(210, 180);
pPage->Stroke();
pPage->SetStrokeColor(0, 0, 255);
pPage->SetLineJoin(linejoin_Round);
pPage->MoveTo(220, 120);
pPage->LineTo(330, 120);
pPage->LineTo(330, 180);
pPage->Stroke();
pPage->GrRestore();
pPage->GrSave();
pPage->SetFillColor(120, 15, 15);
pPage->MoveTo(30, 210);
pPage->LineTo(140, 210);
pPage->LineTo(140, 240);
pPage->LineTo(30, 240);
pPage->ClosePath();
pPage->MoveTo(20, 200);
pPage->LineTo(150, 200);
pPage->LineTo(150, 250);
pPage->LineTo(20, 250);
pPage->ClosePath();
pPage->EoFillStroke();
pPage->SetExtGrState(oPdf.GetExtGState(0.8, 0.8));
pPage->SetFillColor(15, 15, 120);
pPage->MoveTo(230, 210);
pPage->LineTo(320, 210);
pPage->LineTo(320, 240);
pPage->LineTo(230, 240);
pPage->ClosePath();
pPage->MoveTo(220, 200);
pPage->LineTo(330, 200);
pPage->LineTo(330, 250);
pPage->LineTo(220, 250);
pPage->ClosePath();
pPage->FillStroke();
pPage->GrRestore();
pPage->MoveTo(230, 310);
pPage->LineTo(320, 310);
pPage->LineTo(280, 340);
pPage->ClosePath();
pPage->Clip();
pPage->EndPath();
pPage->SetExtGrState(oPdf.GetExtGState(0.5, 0.5));
pPage->MoveTo(230, 310);
pPage->LineTo(320, 310);
pPage->LineTo(320, 340);
pPage->LineTo(230, 340);
pPage->ClosePath();
pPage->MoveTo(220, 300);
pPage->LineTo(330, 300);
pPage->LineTo(330, 350);
pPage->LineTo(220, 350);
pPage->ClosePath();
pPage->FillStroke();
oPdf.SaveToFile(L"D:/Test Files/Test3.pdf");
oPdf.Close();
}
void TestDocument4()
{
CDocument oPdf;
oPdf.CreateNew();
CPage* pPage = oPdf.AddPage();
pPage->SetHeight(600);
pPage->SetWidth(600);
pPage = oPdf.AddPage();
pPage->SetHeight(600);
pPage->SetWidth(600);
CDestination* pDest = oPdf.CreateDestination(1);
pDest->SetXYZ(0, 792, 0);
CAnnotation* pAnnot = oPdf.CreateLinkAnnot(0, TRect(0, 100, 100, 0), pDest);
pAnnot = oPdf.CreateUriLinkAnnot(0, TRect(0, 200, 100, 100), "www.rbc.ru");
oPdf.SaveToFile(L"D:/Test Files/Test4.pdf");
oPdf.Close();
}
void TestDocument5()
{
CDocument oPdf;
oPdf.CreateNew();
CPage* pPage = oPdf.AddPage();
pPage->SetHeight(600);
pPage->SetWidth(600);
//CBgraFrame oFrame;
//oFrame.OpenFile(L"D:/Test Files/Test.jb2");
//TIFF* pTiff = TIFFOpenW(L"D:/Test Files/Test.tiff", "w+");
//TIFFSetField(pTiff, TIFFTAG_IMAGEWIDTH, 800);
//TIFFSetField(pTiff, TIFFTAG_IMAGELENGTH, 1000);
//TIFFSetField(pTiff, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
//TIFFSetField(pTiff, TIFFTAG_XRESOLUTION, 200.0);
//TIFFSetField(pTiff, TIFFTAG_YRESOLUTION, 200.0);
//TIFFSetField(pTiff, TIFFTAG_COMPRESSION, COMPRESSION_CCITT_T6);
//for (int nY = 0; nY < 1000; ++nY)
//{
// BYTE pBuffer[800];
// for (int nX = 0; nX < 100; ++nX)
// {
// pBuffer[nX] = (nX > nY ? 0 : 255);
// }
// TIFFWriteScanline(pTiff, pBuffer, nY);
//}
//TIFFClose(pTiff);
//CImageDict* pImage = oPdf.CreateImage();
//pImage->LoadCCITT4(L"D:/Test Files/Test.tiff", 800, 1000);
//pPage->DrawImage(pImage, 100, 100, 200, 200);
BYTE* pBuffer = new BYTE[100 * 800];
for (int nY = 0; nY < 800; ++nY)
{
for (int nX = 0; nX < 100; ++nX)
{
pBuffer[nX + nY * 100] = rand() % 255;// (nX * 8 > nY ? 0 : 255);
}
}
CImageDict* pImage = oPdf.CreateImage();
pImage->LoadBW(pBuffer, 800, 800, 100);
delete pBuffer;
pPage->DrawImage(pImage, 100, 100, 200, 200);
pBuffer = new BYTE[100 * 800];
for (int nY = 0; nY < 800; ++nY)
{
for (int nX = 0; nX < 100; ++nX)
{
pBuffer[nX + nY * 100] = rand() % 255;// (nX * 8 > nY ? 0 : 255);
}
}
pImage = oPdf.CreateImage();
pImage->LoadBW(pBuffer, 800, 800, 100);
delete pBuffer;
pPage->DrawImage(pImage, 300, 300, 200, 200);
//CxImage oImage;
//oImage.Load(L"D:/Test Files/Test.jb2");
//CImageDict* pJb2Image = oPdf.CreateImage();
//pJb2Image->LoadJb2(L"D:/Test Files/Test.jb2", 1728, 2376);
//pPage->DrawImage(pJb2Image, 100, 100, 200, 200);
//CImageDict* pJpegImage = oPdf.CreateImage();
//pJpegImage->LoadJpeg(L"D:/Test Files/Test.jpg", 670, 473);
//pPage->DrawImage(pJpegImage, 100, 100, 200, 200);
//BYTE* pAlpha = new BYTE[4 * 400 * 300];
//for (int nY = 0; nY < 300; nY++)
//{
// for (int nX = 0; nX < 400; nX++)
// {
// int nIndex = 4 * (nY * 400 + nX);
// if (nY > 300 / 2)
// {
// pAlpha[nIndex + 0] = 255;
// pAlpha[nIndex + 1] = 0;
// pAlpha[nIndex + 2] = 0;
// pAlpha[nIndex + 3] = 255;
// }
// else
// {
// pAlpha[nIndex + 0] = 0;
// pAlpha[nIndex + 1] = 0;
// pAlpha[nIndex + 2] = 255;
// pAlpha[nIndex + 3] = 128;
// }
// }
//}
//CImageDict* pJpxImage = oPdf.CreateImage();
//pJpxImage->LoadJpx(L"D:/Test Files/Test.jp2", 400, 300);
//pJpxImage->LoadSMask(pAlpha, 400, 300);
//pPage->DrawImage(pJpxImage, 300, 100, 200, 200);
//delete[] pAlpha;
////CImageDict* pJb2Image = oPdf.CreateImage();
////pJb2Image->LoadJb2(L"D:/Test Files/Test.jbig2", 400, 300);
////pPage->DrawImage(pJb2Image, 300, 300, 200, 200);
//CImageDict* pRawImage = oPdf.CreateImage();
//BYTE* pBgra = new BYTE[4 * 100 * 100];
//for (int nY = 0; nY < 100; nY++)
//{
// for (int nX = 0; nX < 100; nX++)
// {
// int nIndex = 4 * (nY * 100 + nX);
// if (nX > nY)
// {
// pBgra[nIndex + 0] = 255;
// pBgra[nIndex + 1] = 0;
// pBgra[nIndex + 2] = 0;
// pBgra[nIndex + 3] = 255;
// }
// else
// {
// pBgra[nIndex + 0] = 0;
// pBgra[nIndex + 1] = 0;
// pBgra[nIndex + 2] = 255;
// pBgra[nIndex + 3] = 20;
// }
// }
//}
//pRawImage->LoadRaw(pBgra, 100, 100);
//pRawImage->LoadSMask(pBgra, 100, 100);
//pPage->DrawImage(pRawImage, 300, 300, 200, 200);
//delete[] pBgra;
oPdf.SaveToFile(L"D:/Test Files/Test5.pdf");
oPdf.Close();
}
void TestDocument6()
{
CDocument oPdf;
oPdf.CreateNew();
CPage* pPage = oPdf.AddPage();
pPage->SetHeight(600);
pPage->SetWidth(600);
CFontDict* pFont = oPdf.CreateFont14(standard14fonts_CourierOblique);
pPage->BeginText();
pPage->SetFontAndSize(pFont, 15);
pPage->DrawText(10, 100, (const BYTE*)"Ilya", 4);
pPage->SetFontAndSize(pFont, 30);
pPage->DrawText(100, 100, (const BYTE*)"Ilya", 4);
pPage->SetCharSpace(6);
pPage->DrawText(100, 200, (const BYTE*)"Ilya", 4);
pPage->SetCharSpace(0);
pPage->SetHorizontalScalling(200.0);
pPage->DrawText(100, 300, (const BYTE*)"Ilya", 4);
pPage->SetHorizontalScalling(100.0);
double dAngle = 30 * 3.141592f / 180;
pPage->SetTextMatrix(cos(dAngle), -sin(dAngle), sin(dAngle), cos(dAngle), 0, 0);
pPage->DrawText(100, 400, (const BYTE*)"Ilya", 4);
pPage->SetTextMatrix(1, 0, 0, 1, 0, 0);
pPage->DrawText(100, 500, (const BYTE*)"Ilya", 4);
pPage->EndText();
pFont = oPdf.CreateFont14(standard14fonts_TimesBold);
pPage->BeginText();
pPage->SetFontAndSize(pFont, 30);
pPage->SetTextRenderingMode(textrenderingmode_Fill);
pPage->DrawText(300, 100, (const BYTE*)"Ilya", 4);
pPage->SetTextRenderingMode(textrenderingmode_Stroke);
pPage->DrawText(300, 200, (const BYTE*)"Ilya", 4);
pPage->SetCharSpace(0);
pPage->SetFillColor(255, 0, 0);
pPage->SetStrokeColor(0, 0, 255);
pPage->SetTextRenderingMode(textrenderingmode_FillThenStroke);
pPage->DrawText(300, 300, (const BYTE*)"Ilya", 4);
pPage->SetHorizontalScalling(100.0);
pPage->SetTextRenderingMode(textrenderingmode_Invisible);
pPage->DrawText(300, 400, (const BYTE*)"Ilya", 4);
pPage->SetTextRenderingMode(textrenderingmode_StrokeClipping);
pPage->DrawText(300, 500, (const BYTE*)"Ilya", 4);
pPage->EndText();
pPage->MoveTo(300, 505);
pPage->LineTo(400, 505);
pPage->LineTo(400, 515);
pPage->LineTo(300, 515);
pPage->ClosePath();
pPage->Fill();
oPdf.SaveToFile(L"D:/Test Files/Test6.pdf");
oPdf.Close();
}
void TestDocument7()
{
struct TRange
{
unsigned int rangeStart;
unsigned int rangeEnd;
};
int nRangesCount = 10;
const TRange arrRanges[] =
{
{ 0x1D400, 0x1D4FF },
{ 0x1D500, 0x1D5FF },
{ 0x1D600, 0x1D6FF },
{ 0x1D700, 0x1D7FF },
{ 0x10000, 0x1007F },
{ 0x10380, 0x1039F },
{ 0x0020, 0x007F },
{ 0x0400, 0x04FF },
{ 0x3040, 0x309F },
{ 0x30A0, 0x30FF }
};
CDocument oPdf;
oPdf.CreateNew();
CPage* pPage = oPdf.AddPage();
pPage->SetHeight(600);
pPage->SetWidth(1000);
//CFontCidTrueType* pFont = oPdf.CreateTrueTypeFont(L"D:/Test Files/Test.ttf", 0);
CFontCidTrueType* pFont = oPdf.CreateTrueTypeFont(L"D:/Test Files/cambria.ttc", 1);
pPage->BeginText();
int nX = 10;
int nY = 590;
for (int nRangeIndex = 0; nRangeIndex < nRangesCount; nRangeIndex++)
{
unsigned int rangeStart = arrRanges[nRangeIndex].rangeStart;
unsigned int rangeEnd = arrRanges[nRangeIndex].rangeEnd;
unsigned int rangeLen = rangeEnd - rangeStart + 1;
unsigned int* pRange = new unsigned int[rangeLen];
for (unsigned int unIndex = rangeStart; unIndex <= rangeEnd; unIndex++)
{
pRange[unIndex - rangeStart] = unIndex;
}
pPage->SetFontAndSize(pFont, 10);
unsigned char* pString = pFont->EncodeString(pRange, rangeLen);
pPage->DrawText(nX, nY, (const BYTE*)pString, rangeLen * 2);
delete[] pString;
delete[] pRange;
nY -= 10;
}
pPage->EndText();
oPdf.SaveToFile(L"D:/Test Files/Test7.pdf");
oPdf.Close();
}
void TestDocument8()
{
CDocument oPdf;
oPdf.CreateNew();
CPage* pPage;
pPage = oPdf.AddPage();
pPage->SetHeight(600);
pPage->SetWidth(600);
pPage->GrSave();
pPage->Ellipse(200, 200, 50, 100);
pPage->Clip();
pPage->EndPath();
int nCount = 2;
unsigned char pColors[] =
{
255, 0, 0,
0, 0, 255
};
double pPoints[] ={0, 1};
CShading* pShading = oPdf.CreateAxialShading(200, 150, 200, 250, pColors, pPoints, 2);
pPage->DrawShading(pShading);
pPage->GrRestore();
pPage->GrSave();
pPage->Ellipse(400, 200, 50, 100);
pPage->Clip();
pPage->EndPath();
int nCount2 = 4;
unsigned char pColors2[] =
{
255, 0, 0,
0, 255, 0,
255, 255, 255,
0, 0, 255
};
double pPoints2[] ={ 0, 0.3, 0.7, 1 };
CShading* pShading2 = oPdf.CreateAxialShading(400, 150, 400, 250, pColors2, pPoints2, nCount2);
pPage->DrawShading(pShading2);
pPage->GrRestore();
pPage->GrSave();
pPage->Ellipse(200, 400, 100, 100);
pPage->Clip();
pPage->EndPath();
int nCount3 = 3;
unsigned char pColors3[] =
{
255, 0, 0,
255, 255, 0,
0, 0, 255
};
double pPoints3[] ={ 0, 0.5, 1 };
CShading* pShading3 = oPdf.CreateRaidalShading(200, 375, 20, 200, 425, 100, pColors3, pPoints3, nCount3);
pPage->DrawShading(pShading3);
pPage->GrRestore();
oPdf.SaveToFile(L"D:/Test Files/Test8.pdf");
oPdf.Close();
}
void TestDocument9()
{
CDocument oPdf;
oPdf.CreateNew();
CPage* pPage;
pPage = oPdf.AddPage();
pPage->SetHeight(600);
pPage->SetWidth(600);
CImageDict* pJpegImage = oPdf.CreateImage();
pJpegImage->LoadJpeg(L"D:/Test Files/Test.jpg", 600, 400);
CImageTilePattern* pPattern = oPdf.CreateImageTilePattern(70, 70, pJpegImage, imagetilepatterntype_InverseX);
pPage->GrSave();
pPage->SetPatternColorSpace(pPattern);
pPage->Ellipse(300, 300, 200, 150);
pPage->Clip();
pPage->Fill();
pPage->GrRestore();
oPdf.SaveToFile(L"D:/Test Files/Test9.pdf");
oPdf.Close();
}
void main()
{
TestStreams();
TestObjects();
TestEncrypt();
TestDict();
TestDocument1();
TestDocument2();
TestDocument3();
TestDocument4();
TestDocument5();
TestDocument6();
TestDocument7();
TestDocument8();
TestDocument9();
}
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B819B482-8822-4809-B633-09F8946D761E}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>PdfWriterTest</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\..\..\DesktopEditor\freetype-2.5.2\include;..\..\..\DesktopEditor\agg-2.4\include;..\..\..\DesktopEditor\cximage\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\..\..\DesktopEditor\freetype-2.5.2\include;..\..\..\DesktopEditor\agg-2.4\include;..\..\..\DesktopEditor\cximage\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4018;4005;4267</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="PdfWriterTest.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PdfWriterTest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
========================================================================
CONSOLE APPLICATION : PdfWriterTest Project Overview
========================================================================
AppWizard has created this PdfWriterTest application for you.
This file contains a summary of what you will find in each of the files that
make up your PdfWriterTest application.
PdfWriterTest.vcxproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.
PdfWriterTest.vcxproj.filters
This is the filters file for VC++ projects generated using an Application Wizard.
It contains information about the association between the files in your project
and the filters. This association is used in the IDE to show grouping of files with
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
"Source Files" filter).
PdfWriterTest.cpp
This is the main application source file.
/////////////////////////////////////////////////////////////////////////////
Other standard files:
StdAfx.h, StdAfx.cpp
These files are used to build a precompiled header (PCH) file
named PdfWriterTest.pch and a precompiled types file named StdAfx.obj.
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" comments to indicate parts of the source code you
should add to or customize.
/////////////////////////////////////////////////////////////////////////////
// stdafx.cpp : source file that includes just the standard includes
// PdfWriterTest.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#ifdef _DEBUG
#pragma comment(lib, "../x64/Debug/PdfWriter.lib")
#pragma comment(lib, "../../DesktopEditor/Qt_build/graphics/project/debug/graphics.lib")
#pragma comment(lib, "../../ASCOfficeUtils/ASCOfficeUtilsLib/Win/x64/Debug/ASCOfficeUtilsLib.lib")
#pragma comment(lib, "Ws2_32.lib")
#else
#pragma comment(lib, "../x64/Release/PdfWriter.lib")
#pragma comment(lib, "../../../DesktopEditor/Qt_build/graphics/project/release/graphics.lib")
#endif
// TODO: reference additional headers your program requires here
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>
========================================================================
STATIC LIBRARY : PdfWriter Project Overview
========================================================================
AppWizard has created this PdfWriter library project for you.
No source files were created as part of your project.
PdfWriter.vcxproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.
PdfWriter.vcxproj.filters
This is the filters file for VC++ projects generated using an Application Wizard.
It contains information about the association between the files in your project
and the filters. This association is used in the IDE to show grouping of files with
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
"Source Files" filter).
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" comments to indicate parts of the source code you
should add to or customize.
/////////////////////////////////////////////////////////////////////////////
#include "Annotation.h"
#include "Pages.h"
#define BS_DEF_WIDTH 1
namespace PdfWriter
{
const static char* c_sAnnotTypeNames[] =
{
"Text",
"Link",
"Sound",
"FreeText",
"Stamp",
"Square",
"Circle",
"StrikeOut",
"Highlight",
"Underline",
"Ink",
"FileAttachment",
"Popup"
};
const static char* c_sAnnotIconNames[] =
{
"Comment",
"Key",
"Note",
"Help",
"NewParagraph",
"Paragraph",
"Insert"
};
//----------------------------------------------------------------------------------------
// CAnnotation
//----------------------------------------------------------------------------------------
CAnnotation::CAnnotation(CXref* pXref, EAnnotType eType, const TRect& oRect)
{
pXref->Add(this);
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("Rect", pArray);
if (oRect.fTop < oRect.fBottom)
{
pArray->Add(oRect.fLeft);
pArray->Add(oRect.fTop);
pArray->Add(oRect.fRight);
pArray->Add(oRect.fBottom);
}
else
{
pArray->Add(oRect.fLeft);
pArray->Add(oRect.fBottom);
pArray->Add(oRect.fRight);
pArray->Add(oRect.fTop);
}
Add("Type", "Annot");
Add("Subtype", c_sAnnotTypeNames[(int)eType]);
}
void CAnnotation::SetBorderStyle(EBorderSubtype eSubtype, float fWidth, unsigned short nDashOn, unsigned short nDashOff, unsigned short nDashPhase)
{
CDictObject* pBorderStyleDict = new CDictObject();
if (!pBorderStyleDict)
return;
Add("BS", pBorderStyleDict);
if (border_subtype_Dashed == eSubtype)
{
CArrayObject* pDash = new CArrayObject();
if (!pDash)
return;
pBorderStyleDict->Add("D", pDash);
pBorderStyleDict->Add("Type", "Border");
pDash->Add(nDashOn);
pDash->Add(nDashOff);
if (0 != nDashPhase)
pDash->Add(nDashOff);
}
switch (eSubtype)
{
case border_subtype_Solid: pBorderStyleDict->Add("S", "S"); break;
case border_subtype_Dashed: pBorderStyleDict->Add("S", "D"); break;
case border_subtype_Beveled: pBorderStyleDict->Add("S", "B"); break;
case border_subtype_Inset: pBorderStyleDict->Add("S", "I"); break;
case border_subtype_Underlined: pBorderStyleDict->Add("S", "U"); break;
}
if (BS_DEF_WIDTH != fWidth)
pBorderStyleDict->Add("W", fWidth);
}
//----------------------------------------------------------------------------------------
// CLinkAnnotation
//----------------------------------------------------------------------------------------
CLinkAnnotation::CLinkAnnotation(CXref* pXref, const TRect& oRect, CDestination* pDestination) : CAnnotation(pXref, AnnotLink, oRect)
{
Add("Dest", (CObjectBase*)pDestination);
}
void CLinkAnnotation::SetBorderStyle(float fWidth, unsigned short nDashOn, unsigned short nDashOff)
{
fWidth = max(fWidth, 0);
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("Border", pArray);
pArray->Add(0);
pArray->Add(0);
pArray->Add(fWidth);
if (nDashOn && nDashOff)
{
CArrayObject* pDash = new CArrayObject();
if (!pDash)
return;
pArray->Add(pDash);
pDash->Add(nDashOn);
pDash->Add(nDashOff);
}
}
void CLinkAnnotation::SetHighlightMode(EAnnotHighlightMode eMode)
{
switch (eMode)
{
case AnnotNoHighlight: Add("H", "N"); break;
case AnnotInvertBorder: Add("H", "O"); break;
case AnnotDownAppearance: Add("H", "P"); break;
default: Remove("H"); break;
}
}
//----------------------------------------------------------------------------------------
// CTextAnnotation
//----------------------------------------------------------------------------------------
CTextAnnotation::CTextAnnotation(CXref* pXref, const TRect& oRect, const char* sText) : CAnnotation(pXref, AnnotTextNotes, oRect)
{
Add("Contents", new CStringObject(sText));
}
void SetIcon(EAnnotIcon eIcon);
void SetOpened(bool bOpened);
void CTextAnnotation::SetIcon(EAnnotIcon eIcon)
{
eIcon = (EAnnotIcon)min(max(AnnotIconMin, eIcon), AnnotIconMax);
Add("Name", c_sAnnotIconNames[(int)eIcon]);
}
void CTextAnnotation::SetOpened(bool bOpened)
{
Add("Open", new CBoolObject(bOpened));
}
//----------------------------------------------------------------------------------------
// CUriLinkAnnotation
//----------------------------------------------------------------------------------------
CUriLinkAnnotation::CUriLinkAnnotation(CXref* pXref, const TRect& oRect, const char* sUri) : CAnnotation(pXref, AnnotLink, oRect)
{
CDictObject* pAction = new CDictObject();
if (!pAction)
return;
Add("A", pAction);
pAction->Add("Type", "Action");
pAction->Add("S", "URI");
pAction->Add("URI", new CStringObject(sUri));
}
}
\ No newline at end of file
#ifndef _PDF_WRITER_SRC_ANNOTATION_H
#define _PDF_WRITER_SRC_ANNOTATION_H
#include "Objects.h"
#include "Types.h"
namespace PdfWriter
{
class CDestination;
enum EBorderSubtype
{
border_subtype_Solid,
border_subtype_Dashed,
border_subtype_Beveled,
border_subtype_Inset,
border_subtype_Underlined
};
enum EAnnotType
{
AnnotUnknown = -1,
AnnotTextNotes = 0,
AnnotLink = 1,
AnnotSound = 2,
AnnotFreeText = 3,
AnnotStamp = 4,
AnnotSquare = 5,
AnnotCircle = 6,
AnnotStrikeOut = 7,
AnnotHighLight = 8,
AnnotUnderline = 9,
AnnotInk = 10,
AnnotFileAttachment = 11,
AnnotPopup = 12
};
enum EAnnotHighlightMode
{
AnnotNoHighlight = 0,
AnnotInvertBox,
AnnotInvertBorder,
AnnotDownAppearance,
AnnotHighlightModeEOF
};
enum EAnnotIcon
{
AnnotIconComment = 0,
AnnotIconKey = 1,
AnnotIconNote = 2,
AnnotIconHelp = 3,
AnnotIconNewParagraph = 4,
AnnotIconParagraph = 5,
AnnotIconInsert = 6,
AnnotIconMin = 0,
AnnotIconMax = 6
};
class CAnnotation : public CDictObject
{
public:
CAnnotation(CXref* pXref, EAnnotType eType, const TRect& oRect);
void SetBorderStyle(EBorderSubtype eSubtype, float fWidth, unsigned short nDashOn, unsigned short nDashOff, unsigned short nDashPhase);
EDictType GetDictType() const
{
return dict_type_ANNOTATION;
}
virtual EAnnotType GetAnnotationType() const
{
return AnnotUnknown;
}
};
class CLinkAnnotation : public CAnnotation
{
public:
CLinkAnnotation(CXref* pXref, const TRect& oRect, CDestination* pDestination);
EAnnotType GetAnnotationType() const
{
return AnnotLink;
}
void SetBorderStyle (float fWidth, unsigned short nDashOn, unsigned short nDashOff);
void SetHighlightMode(EAnnotHighlightMode eMode);
};
class CTextAnnotation : public CAnnotation
{
public:
CTextAnnotation(CXref* pXref, const TRect& oRect, const char* sText);
EAnnotType GetAnnotationType() const
{
return AnnotTextNotes;
}
void SetIcon(EAnnotIcon eIcon);
void SetOpened(bool bOpened);
};
class CUriLinkAnnotation : public CAnnotation
{
public:
CUriLinkAnnotation(CXref* pXref, const TRect& oRect, const char* sUri);
EAnnotType GetAnnotationType() const
{
return AnnotLink;
}
};
}
#endif // _PDF_WRITER_SRC_ANNOTATION_H
#include "Catalog.h"
#include "Destination.h"
#include "Pages.h"
#include "Utils.h"
namespace PdfWriter
{
static const char* c_sPageLayoutNames[] =
{
"SinglePage",
"OneColumn",
"TwoColumnLeft",
"TwoColumnRight",
NULL
};
static const char* c_sPageModeNames[] =
{
"UseNone",
"UseOutlines",
"UseThumbs",
"FullScreen",
"UseOC",
"UseAttachments",
NULL
};
//----------------------------------------------------------------------------------------
// CCatalog
//----------------------------------------------------------------------------------------
CCatalog::CCatalog(CXref* pXref)
{
pXref->Add(this);
Add("Type", "Catalog");
Add("Pages", new CPageTree(pXref));
}
CPageTree* CCatalog::GetRoot() const
{
return (CPageTree*)Get("Pages");
}
EPageLayout CCatalog::GetPageLayout() const
{
CNameObject* pLayout = (CNameObject*)Get("PageLayout");
if (!pLayout)
return pagelayout_Single;
unsigned int unIndex = 0;
while (c_sPageLayoutNames[unIndex])
{
if (0 == StrCmp(pLayout->Get(), c_sPageLayoutNames[unIndex]))
return (EPageLayout)unIndex;
unIndex++;
}
return pagelayout_Single;
}
void CCatalog::SetPageLayout(EPageLayout eLayout)
{
return Add("PageLayout", c_sPageLayoutNames[(int)eLayout]);
}
EPageMode CCatalog::GetPageMode() const
{
CNameObject* pMode = (CNameObject*)Get("PageMode");
if (!pMode)
return pagemode_UseNone;
unsigned int unIndex = 0;
while (c_sPageModeNames[unIndex])
{
if (0 == StrCmp(pMode->Get(), c_sPageModeNames[unIndex]))
return (EPageMode)unIndex;
unIndex++;
}
return pagemode_UseNone;
}
void CCatalog::SetPageMode(EPageMode eMode)
{
Add("PageMode", c_sPageModeNames[(int)eMode]);
}
void CCatalog::SetOpenAction(CDestination* pOpenAction)
{
if (!pOpenAction)
Remove("OpenAction");
else
Add("OpenAction", pOpenAction);
}
void CCatalog::AddPageLabel(unsigned int unPageNum, CDictObject* pPageLabel)
{
CDictObject* pLabels = (CDictObject*)Get("PageLabels");
if (!pLabels)
{
pLabels = new CDictObject();
if (!pLabels)
return;
Add("PageLabels", pLabels);
}
CArrayObject* pNums = (CArrayObject*)pLabels->Get("Nums");
if (!pNums)
{
pNums = new CArrayObject();
if (!pNums)
return;
pLabels->Add("Nums", pNums);
}
pNums->Add(unPageNum);
pNums->Add(pPageLabel);
}
}
\ No newline at end of file
#ifndef _PDF_WRITER_SRC_CATALOG_H
#define _PDF_WRITER_SRC_CATALOG_H
#include "Objects.h"
namespace PdfWriter
{
class CPageTree;
class CDestination;
class CCatalog : public CDictObject
{
public:
CCatalog(CXref* pXref);
CPageTree* GetRoot() const;
EPageLayout GetPageLayout() const;
void SetPageLayout(EPageLayout eLayout);
EPageMode GetPageMode() const;
void SetPageMode(EPageMode eMode);
void SetOpenAction(CDestination* pOpenAction);
void AddPageLabel(unsigned int unIndex, CDictObject* pPageLabel);
EDictType GetDictType() const
{
return dict_type_CATALOG;
}
};
}
#endif // _PDF_WRITER_SRC_CATALOG_H
#ifndef _PDF_WRITER_SRC_CONSTS_H
#define _PDF_WRITER_SRC_CONSTS_H
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#define OK 0
#define NOERROR 0
// Стандартный размер буфера в memory-stream-object
#define STREAM_BUF_SIZ 4096
// стандартный размер массива list-object
#define DEF_ITEMS_PER_BLOCK 20
// стандартный размер массива cross-reference-table
#define DEFALUT_XREF_ENTRY_NUM 1024
// стандартный размер таблицы ширин (widths-table) в cid-fontdef
#define DEF_CHAR_WIDTHS_NUM 128
// стандартный рамер массива page-list-tablef
#define DEF_PAGE_LIST_NUM 256
// стандартный размер таблицы range-table в cid-fontdef
#define DEF_RANGE_TBL_NUM 128
// Необходимый размер буффера для конвертирования с символьную строку.
#define TEMP_BUFFER_SIZE 512
#define SHORT_BUFFER_SIZE 32
#define REAL_LEN 31//11
#define INT_LEN 11
#define TEXT_DEFAULT_LEN 256
#define UNICODE_HEADER_LEN 2
#define DATE_TIME_STR_LEN 23
// Соответсвующие длины в таблицу cross-reference-table
#define BYTE_OFFSET_LEN 10
#define OBJ_ID_LEN 7
#define GEN_NO_LEN 5
// Стандартный размер страницы (А4)
#define DEF_PAGE_WIDTH 595.276
#define DEF_PAGE_HEIGHT 841.89
// Типы компрессии
#define COMP_NONE 0x00
#define COMP_TEXT 0x01
#define COMP_IMAGE 0x02
#define COMP_METADATA 0x04
#define COMP_ALL 0x0F
// #define COMP_BEST_COMPRESS 0x10
// #define COMP_BEST_SPEED 0x20
#define COMP_MASK 0xFF
// Permission flags (only Revision 2 is supported)
#define ENABLE_READ 0
#define ENABLE_PRINT 4
#define ENABLE_EDIT_ALL 8
#define ENABLE_COPY 16
#define ENABLE_EDIT 32
// Варианты просмотра документа
#define HIDE_TOOLBAR 1
#define HIDE_MENUBAR 2
#define HIDE_WINDOW_UI 4
#define FIT_WINDOW 8
#define CENTER_WINDOW 16
// Ограничения, в соответствии со спецификацией (PDF1.4)
#define LIMIT_MAX_INT 2147483647
#define LIMIT_MIN_INT -2147483647
#define LIMIT_MAX_REAL 3.402823466e+38F
#define LIMIT_MIN_REAL -3.402823466e+38F
#define LIMIT_MAX_STRING_LEN 65535
#define LIMIT_MAX_NAME_LEN 127
#define LIMIT_MAX_ARRAY 8191
#define LIMIT_MAX_DICT_ELEMENT 4095
#define LIMIT_MAX_XREF_ELEMENT 8388607
#define LIMIT_MAX_GSTATE 28
#define LIMIT_MAX_DEVICE_N 8
#define LIMIT_MAX_DEVICE_N_V15 32
#define LIMIT_MAX_CID 65535
#define MAX_GENERATION_NUM 65535
#define MIN_PAGE_HEIGHT 3
#define MIN_PAGE_WIDTH 3
#define MAX_PAGE_HEIGHT 14400
#define MAX_PAGE_WIDTH 14400
#define MIN_MAGNIFICATION_FACTOR 8
#define MAX_MAGNIFICATION_FACTOR 3200
// Коды стран
#define COUNTRY_AF "AF" /* AFGHANISTAN */
#define COUNTRY_AL "AL" /* ALBANIA */
#define COUNTRY_DZ "DZ" /* ALGERIA */
#define COUNTRY_AS "AS" /* AMERICAN SAMOA */
#define COUNTRY_AD "AD" /* ANDORRA */
#define COUNTRY_AO "AO" /* ANGOLA */
#define COUNTRY_AI "AI" /* ANGUILLA */
#define COUNTRY_AQ "AQ" /* ANTARCTICA */
#define COUNTRY_AG "AG" /* ANTIGUA AND BARBUDA */
#define COUNTRY_AR "AR" /* ARGENTINA */
#define COUNTRY_AM "AM" /* ARMENIA */
#define COUNTRY_AW "AW" /* ARUBA */
#define COUNTRY_AU "AU" /* AUSTRALIA */
#define COUNTRY_AT "AT" /* AUSTRIA */
#define COUNTRY_AZ "AZ" /* AZERBAIJAN */
#define COUNTRY_BS "BS" /* BAHAMAS */
#define COUNTRY_BH "BH" /* BAHRAIN */
#define COUNTRY_BD "BD" /* BANGLADESH */
#define COUNTRY_BB "BB" /* BARBADOS */
#define COUNTRY_BY "BY" /* BELARUS */
#define COUNTRY_BE "BE" /* BELGIUM */
#define COUNTRY_BZ "BZ" /* BELIZE */
#define COUNTRY_BJ "BJ" /* BENIN */
#define COUNTRY_BM "BM" /* BERMUDA */
#define COUNTRY_BT "BT" /* BHUTAN */
#define COUNTRY_BO "BO" /* BOLIVIA */
#define COUNTRY_BA "BA" /* BOSNIA AND HERZEGOWINA */
#define COUNTRY_BW "BW" /* BOTSWANA */
#define COUNTRY_BV "BV" /* BOUVET ISLAND */
#define COUNTRY_BR "BR" /* BRAZIL */
#define COUNTRY_IO "IO" /* BRITISH INDIAN OCEAN TERRITORY */
#define COUNTRY_BN "BN" /* BRUNEI DARUSSALAM */
#define COUNTRY_BG "BG" /* BULGARIA */
#define COUNTRY_BF "BF" /* BURKINA FASO */
#define COUNTRY_BI "BI" /* BURUNDI */
#define COUNTRY_KH "KH" /* CAMBODIA */
#define COUNTRY_CM "CM" /* CAMEROON */
#define COUNTRY_CA "CA" /* CANADA */
#define COUNTRY_CV "CV" /* CAPE VERDE */
#define COUNTRY_KY "KY" /* CAYMAN ISLANDS */
#define COUNTRY_CF "CF" /* CENTRAL AFRICAN REPUBLIC */
#define COUNTRY_TD "TD" /* CHAD */
#define COUNTRY_CL "CL" /* CHILE */
#define COUNTRY_CN "CN" /* CHINA */
#define COUNTRY_CX "CX" /* CHRISTMAS ISLAND */
#define COUNTRY_CC "CC" /* COCOS (KEELING) ISLANDS */
#define COUNTRY_CO "CO" /* COLOMBIA */
#define COUNTRY_KM "KM" /* COMOROS */
#define COUNTRY_CG "CG" /* CONGO */
#define COUNTRY_CK "CK" /* COOK ISLANDS */
#define COUNTRY_CR "CR" /* COSTA RICA */
#define COUNTRY_CI "CI" /* COTE D'IVOIRE */
#define COUNTRY_HR "HR" /* CROATIA (local name: Hrvatska) */
#define COUNTRY_CU "CU" /* CUBA */
#define COUNTRY_CY "CY" /* CYPRUS */
#define COUNTRY_CZ "CZ" /* CZECH REPUBLIC */
#define COUNTRY_DK "DK" /* DENMARK */
#define COUNTRY_DJ "DJ" /* DJIBOUTI */
#define COUNTRY_DM "DM" /* DOMINICA */
#define COUNTRY_DO "DO" /* DOMINICAN REPUBLIC */
#define COUNTRY_TP "TP" /* EAST TIMOR */
#define COUNTRY_EC "EC" /* ECUADOR */
#define COUNTRY_EG "EG" /* EGYPT */
#define COUNTRY_SV "SV" /* EL SALVADOR */
#define COUNTRY_GQ "GQ" /* EQUATORIAL GUINEA */
#define COUNTRY_ER "ER" /* ERITREA */
#define COUNTRY_EE "EE" /* ESTONIA */
#define COUNTRY_ET "ET" /* ETHIOPIA */
#define COUNTRY_FK "FK" /* FALKLAND ISLANDS (MALVINAS) */
#define COUNTRY_FO "FO" /* FAROE ISLANDS */
#define COUNTRY_FJ "FJ" /* FIJI */
#define COUNTRY_FI "FI" /* FINLAND */
#define COUNTRY_FR "FR" /* FRANCE */
#define COUNTRY_FX "FX" /* FRANCE, METROPOLITAN */
#define COUNTRY_GF "GF" /* FRENCH GUIANA */
#define COUNTRY_PF "PF" /* FRENCH POLYNESIA */
#define COUNTRY_TF "TF" /* FRENCH SOUTHERN TERRITORIES */
#define COUNTRY_GA "GA" /* GABON */
#define COUNTRY_GM "GM" /* GAMBIA */
#define COUNTRY_GE "GE" /* GEORGIA */
#define COUNTRY_DE "DE" /* GERMANY */
#define COUNTRY_GH "GH" /* GHANA */
#define COUNTRY_GI "GI" /* GIBRALTAR */
#define COUNTRY_GR "GR" /* GREECE */
#define COUNTRY_GL "GL" /* GREENLAND */
#define COUNTRY_GD "GD" /* GRENADA */
#define COUNTRY_GP "GP" /* GUADELOUPE */
#define COUNTRY_GU "GU" /* GUAM */
#define COUNTRY_GT "GT" /* GUATEMALA */
#define COUNTRY_GN "GN" /* GUINEA */
#define COUNTRY_GW "GW" /* GUINEA-BISSAU */
#define COUNTRY_GY "GY" /* GUYANA */
#define COUNTRY_HT "HT" /* HAITI */
#define COUNTRY_HM "HM" /* HEARD AND MC DONALD ISLANDS */
#define COUNTRY_HN "HN" /* HONDURAS */
#define COUNTRY_HK "HK" /* HONG KONG */
#define COUNTRY_HU "HU" /* HUNGARY */
#define COUNTRY_IS "IS" /* ICELAND */
#define COUNTRY_IN "IN" /* INDIA */
#define COUNTRY_ID "ID" /* INDONESIA */
#define COUNTRY_IR "IR" /* IRAN (ISLAMIC REPUBLIC OF) */
#define COUNTRY_IQ "IQ" /* IRAQ */
#define COUNTRY_IE "IE" /* IRELAND */
#define COUNTRY_IL "IL" /* ISRAEL */
#define COUNTRY_IT "IT" /* ITALY */
#define COUNTRY_JM "JM" /* JAMAICA */
#define COUNTRY_JP "JP" /* JAPAN */
#define COUNTRY_JO "JO" /* JORDAN */
#define COUNTRY_KZ "KZ" /* KAZAKHSTAN */
#define COUNTRY_KE "KE" /* KENYA */
#define COUNTRY_KI "KI" /* KIRIBATI */
#define COUNTRY_KP "KP" /* KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF */
#define COUNTRY_KR "KR" /* KOREA, REPUBLIC OF */
#define COUNTRY_KW "KW" /* KUWAIT */
#define COUNTRY_KG "KG" /* KYRGYZSTAN */
#define COUNTRY_LA "LA" /* LAO PEOPLE'S DEMOCRATIC REPUBLIC */
#define COUNTRY_LV "LV" /* LATVIA */
#define COUNTRY_LB "LB" /* LEBANON */
#define COUNTRY_LS "LS" /* LESOTHO */
#define COUNTRY_LR "LR" /* LIBERIA */
#define COUNTRY_LY "LY" /* LIBYAN ARAB JAMAHIRIYA */
#define COUNTRY_LI "LI" /* LIECHTENSTEIN */
#define COUNTRY_LT "LT" /* LITHUANIA */
#define COUNTRY_LU "LU" /* LUXEMBOURG */
#define COUNTRY_MO "MO" /* MACAU */
#define COUNTRY_MK "MK" /* MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF */
#define COUNTRY_MG "MG" /* MADAGASCAR */
#define COUNTRY_MW "MW" /* MALAWI */
#define COUNTRY_MY "MY" /* MALAYSIA */
#define COUNTRY_MV "MV" /* MALDIVES */
#define COUNTRY_ML "ML" /* MALI */
#define COUNTRY_MT "MT" /* MALTA */
#define COUNTRY_MH "MH" /* MARSHALL ISLANDS */
#define COUNTRY_MQ "MQ" /* MARTINIQUE */
#define COUNTRY_MR "MR" /* MAURITANIA */
#define COUNTRY_MU "MU" /* MAURITIUS */
#define COUNTRY_YT "YT" /* MAYOTTE */
#define COUNTRY_MX "MX" /* MEXICO */
#define COUNTRY_FM "FM" /* MICRONESIA, FEDERATED STATES OF */
#define COUNTRY_MD "MD" /* MOLDOVA, REPUBLIC OF */
#define COUNTRY_MC "MC" /* MONACO */
#define COUNTRY_MN "MN" /* MONGOLIA */
#define COUNTRY_MS "MS" /* MONTSERRAT */
#define COUNTRY_MA "MA" /* MOROCCO */
#define COUNTRY_MZ "MZ" /* MOZAMBIQUE */
#define COUNTRY_MM "MM" /* MYANMAR */
#define COUNTRY_NA "NA" /* NAMIBIA */
#define COUNTRY_NR "NR" /* NAURU */
#define COUNTRY_NP "NP" /* NEPAL */
#define COUNTRY_NL "NL" /* NETHERLANDS */
#define COUNTRY_AN "AN" /* NETHERLANDS ANTILLES */
#define COUNTRY_NC "NC" /* NEW CALEDONIA */
#define COUNTRY_NZ "NZ" /* NEW ZEALAND */
#define COUNTRY_NI "NI" /* NICARAGUA */
#define COUNTRY_NE "NE" /* NIGER */
#define COUNTRY_NG "NG" /* NIGERIA */
#define COUNTRY_NU "NU" /* NIUE */
#define COUNTRY_NF "NF" /* NORFOLK ISLAND */
#define COUNTRY_MP "MP" /* NORTHERN MARIANA ISLANDS */
#define COUNTRY_NO "NO" /* NORWAY */
#define COUNTRY_OM "OM" /* OMAN */
#define COUNTRY_PK "PK" /* PAKISTAN */
#define COUNTRY_PW "PW" /* PALAU */
#define COUNTRY_PA "PA" /* PANAMA */
#define COUNTRY_PG "PG" /* PAPUA NEW GUINEA */
#define COUNTRY_PY "PY" /* PARAGUAY */
#define COUNTRY_PE "PE" /* PERU */
#define COUNTRY_PH "PH" /* PHILIPPINES */
#define COUNTRY_PN "PN" /* PITCAIRN */
#define COUNTRY_PL "PL" /* POLAND */
#define COUNTRY_PT "PT" /* PORTUGAL */
#define COUNTRY_PR "PR" /* PUERTO RICO */
#define COUNTRY_QA "QA" /* QATAR */
#define COUNTRY_RE "RE" /* REUNION */
#define COUNTRY_RO "RO" /* ROMANIA */
#define COUNTRY_RU "RU" /* RUSSIAN FEDERATION */
#define COUNTRY_RW "RW" /* RWANDA */
#define COUNTRY_KN "KN" /* SAINT KITTS AND NEVIS */
#define COUNTRY_LC "LC" /* SAINT LUCIA */
#define COUNTRY_VC "VC" /* SAINT VINCENT AND THE GRENADINES */
#define COUNTRY_WS "WS" /* SAMOA */
#define COUNTRY_SM "SM" /* SAN MARINO */
#define COUNTRY_ST "ST" /* SAO TOME AND PRINCIPE */
#define COUNTRY_SA "SA" /* SAUDI ARABIA */
#define COUNTRY_SN "SN" /* SENEGAL */
#define COUNTRY_SC "SC" /* SEYCHELLES */
#define COUNTRY_SL "SL" /* SIERRA LEONE */
#define COUNTRY_SG "SG" /* SINGAPORE */
#define COUNTRY_SK "SK" /* SLOVAKIA (Slovak Republic) */
#define COUNTRY_SI "SI" /* SLOVENIA */
#define COUNTRY_SB "SB" /* SOLOMON ISLANDS */
#define COUNTRY_SO "SO" /* SOMALIA */
#define COUNTRY_ZA "ZA" /* SOUTH AFRICA */
#define COUNTRY_ES "ES" /* SPAIN */
#define COUNTRY_LK "LK" /* SRI LANKA */
#define COUNTRY_SH "SH" /* ST. HELENA */
#define COUNTRY_PM "PM" /* ST. PIERRE AND MIQUELON */
#define COUNTRY_SD "SD" /* SUDAN */
#define COUNTRY_SR "SR" /* SURINAME */
#define COUNTRY_SJ "SJ" /* SVALBARD AND JAN MAYEN ISLANDS */
#define COUNTRY_SZ "SZ" /* SWAZILAND */
#define COUNTRY_SE "SE" /* SWEDEN */
#define COUNTRY_CH "CH" /* SWITZERLAND */
#define COUNTRY_SY "SY" /* SYRIAN ARAB REPUBLIC */
#define COUNTRY_TW "TW" /* TAIWAN, PROVINCE OF CHINA */
#define COUNTRY_TJ "TJ" /* TAJIKISTAN */
#define COUNTRY_TZ "TZ" /* TANZANIA, UNITED REPUBLIC OF */
#define COUNTRY_TH "TH" /* THAILAND */
#define COUNTRY_TG "TG" /* TOGO */
#define COUNTRY_TK "TK" /* TOKELAU */
#define COUNTRY_TO "TO" /* TONGA */
#define COUNTRY_TT "TT" /* TRINIDAD AND TOBAGO */
#define COUNTRY_TN "TN" /* TUNISIA */
#define COUNTRY_TR "TR" /* TURKEY */
#define COUNTRY_TM "TM" /* TURKMENISTAN */
#define COUNTRY_TC "TC" /* TURKS AND CAICOS ISLANDS */
#define COUNTRY_TV "TV" /* TUVALU */
#define COUNTRY_UG "UG" /* UGANDA */
#define COUNTRY_UA "UA" /* UKRAINE */
#define COUNTRY_AE "AE" /* UNITED ARAB EMIRATES */
#define COUNTRY_GB "GB" /* UNITED KINGDOM */
#define COUNTRY_US "US" /* UNITED STATES */
#define COUNTRY_UM "UM" /* UNITED STATES MINOR OUTLYING ISLANDS */
#define COUNTRY_UY "UY" /* URUGUAY */
#define COUNTRY_UZ "UZ" /* UZBEKISTAN */
#define COUNTRY_VU "VU" /* VANUATU */
#define COUNTRY_VA "VA" /* VATICAN CITY STATE (HOLY SEE) */
#define COUNTRY_VE "VE" /* VENEZUELA */
#define COUNTRY_VN "VN" /* VIET NAM */
#define COUNTRY_VG "VG" /* VIRGIN ISLANDS (BRITISH) */
#define COUNTRY_VI "VI" /* VIRGIN ISLANDS (U.S.) */
#define COUNTRY_WF "WF" /* WALLIS AND FUTUNA ISLANDS */
#define COUNTRY_EH "EH" /* WESTERN SAHARA */
#define COUNTRY_YE "YE" /* YEMEN */
#define COUNTRY_YU "YU" /* YUGOSLAVIA */
#define COUNTRY_ZR "ZR" /* ZAIRE */
#define COUNTRY_ZM "ZM" /* ZAMBIA */
#define COUNTRY_ZW "ZW" /* ZIMBABWE */
// Коды языков
#define LANG_AA "aa" /* Afar */
#define LANG_AB "ab" /* Abkhazian */
#define LANG_AF "af" /* Afrikaans */
#define LANG_AM "am" /* Amharic */
#define LANG_AR "ar" /* Arabic */
#define LANG_AS "as" /* Assamese */
#define LANG_AY "ay" /* Aymara */
#define LANG_AZ "az" /* Azerbaijani */
#define LANG_BA "ba" /* Bashkir */
#define LANG_BE "be" /* Byelorussian */
#define LANG_BG "bg" /* Bulgarian */
#define LANG_BH "bh" /* Bihari */
#define LANG_BI "bi" /* Bislama */
#define LANG_BN "bn" /* Bengali Bangla */
#define LANG_BO "bo" /* Tibetan */
#define LANG_BR "br" /* Breton */
#define LANG_CA "ca" /* Catalan */
#define LANG_CO "co" /* Corsican */
#define LANG_CS "cs" /* Czech */
#define LANG_CY "cy" /* Welsh */
#define LANG_DA "da" /* Danish */
#define LANG_DE "de" /* German */
#define LANG_DZ "dz" /* Bhutani */
#define LANG_EL "el" /* Greek */
#define LANG_EN "en" /* English */
#define LANG_EO "eo" /* Esperanto */
#define LANG_ES "es" /* Spanish */
#define LANG_ET "et" /* Estonian */
#define LANG_EU "eu" /* Basque */
#define LANG_FA "fa" /* Persian */
#define LANG_FI "fi" /* Finnish */
#define LANG_FJ "fj" /* Fiji */
#define LANG_FO "fo" /* Faeroese */
#define LANG_FR "fr" /* French */
#define LANG_FY "fy" /* Frisian */
#define LANG_GA "ga" /* Irish */
#define LANG_GD "gd" /* Scots Gaelic */
#define LANG_GL "gl" /* Galician */
#define LANG_GN "gn" /* Guarani */
#define LANG_GU "gu" /* Gujarati */
#define LANG_HA "ha" /* Hausa */
#define LANG_HI "hi" /* Hindi */
#define LANG_HR "hr" /* Croatian */
#define LANG_HU "hu" /* Hungarian */
#define LANG_HY "hy" /* Armenian */
#define LANG_IA "ia" /* Interlingua */
#define LANG_IE "ie" /* Interlingue */
#define LANG_IK "ik" /* Inupiak */
#define LANG_IN "in" /* Indonesian */
#define LANG_IS "is" /* Icelandic */
#define LANG_IT "it" /* Italian */
#define LANG_IW "iw" /* Hebrew */
#define LANG_JA "ja" /* Japanese */
#define LANG_JI "ji" /* Yiddish */
#define LANG_JW "jw" /* Javanese */
#define LANG_KA "ka" /* Georgian */
#define LANG_KK "kk" /* Kazakh */
#define LANG_KL "kl" /* Greenlandic */
#define LANG_KM "km" /* Cambodian */
#define LANG_KN "kn" /* Kannada */
#define LANG_KO "ko" /* Korean */
#define LANG_KS "ks" /* Kashmiri */
#define LANG_KU "ku" /* Kurdish */
#define LANG_KY "ky" /* Kirghiz */
#define LANG_LA "la" /* Latin */
#define LANG_LN "ln" /* Lingala */
#define LANG_LO "lo" /* Laothian */
#define LANG_LT "lt" /* Lithuanian */
#define LANG_LV "lv" /* Latvian,Lettish */
#define LANG_MG "mg" /* Malagasy */
#define LANG_MI "mi" /* Maori */
#define LANG_MK "mk" /* Macedonian */
#define LANG_ML "ml" /* Malayalam */
#define LANG_MN "mn" /* Mongolian */
#define LANG_MO "mo" /* Moldavian */
#define LANG_MR "mr" /* Marathi */
#define LANG_MS "ms" /* Malay */
#define LANG_MT "mt" /* Maltese */
#define LANG_MY "my" /* Burmese */
#define LANG_NA "na" /* Nauru */
#define LANG_NE "ne" /* Nepali */
#define LANG_NL "nl" /* Dutch */
#define LANG_NO "no" /* Norwegian */
#define LANG_OC "oc" /* Occitan */
#define LANG_OM "om" /* (Afan)Oromo */
#define LANG_OR "or" /* Oriya */
#define LANG_PA "pa" /* Punjabi */
#define LANG_PL "pl" /* Polish */
#define LANG_PS "ps" /* Pashto,Pushto */
#define LANG_PT "pt" /* Portuguese */
#define LANG_QU "qu" /* Quechua */
#define LANG_RM "rm" /* Rhaeto-Romance */
#define LANG_RN "rn" /* Kirundi */
#define LANG_RO "ro" /* Romanian */
#define LANG_RU "ru" /* Russian */
#define LANG_RW "rw" /* Kinyarwanda */
#define LANG_SA "sa" /* Sanskrit */
#define LANG_SD "sd" /* Sindhi */
#define LANG_SG "sg" /* Sangro */
#define LANG_SH "sh" /* Serbo-Croatian */
#define LANG_SI "si" /* Singhalese */
#define LANG_SK "sk" /* Slovak */
#define LANG_SL "sl" /* Slovenian */
#define LANG_SM "sm" /* Samoan */
#define LANG_SN "sn" /* Shona */
#define LANG_SO "so" /* Somali */
#define LANG_SQ "sq" /* Albanian */
#define LANG_SR "sr" /* Serbian */
#define LANG_SS "ss" /* Siswati */
#define LANG_ST "st" /* Sesotho */
#define LANG_SU "su" /* Sundanese */
#define LANG_SV "sv" /* Swedish */
#define LANG_SW "sw" /* Swahili */
#define LANG_TA "ta" /* Tamil */
#define LANG_TE "te" /* Tegulu */
#define LANG_TG "tg" /* Tajik */
#define LANG_TH "th" /* Thai */
#define LANG_TI "ti" /* Tigrinya */
#define LANG_TK "tk" /* Turkmen */
#define LANG_TL "tl" /* Tagalog */
#define LANG_TN "tn" /* Setswanato Tonga */
#define LANG_TR "tr" /* Turkish */
#define LANG_TS "ts" /* Tsonga */
#define LANG_TT "tt" /* Tatar */
#define LANG_TW "tw" /* Twi */
#define LANG_UK "uk" /* Ukrainian */
#define LANG_UR "ur" /* Urdu */
#define LANG_UZ "uz" /* Uzbek */
#define LANG_VI "vi" /* Vietnamese */
#define LANG_VO "vo" /* Volapuk */
#define LANG_WO "wo" /* Wolof */
#define LANG_XH "xh" /* Xhosa */
#define LANG_YO "yo" /* Yoruba */
#define LANG_ZH "zh" /* Chinese */
#define LANG_ZU "zu" /* Zulu */
//-----------------------------------------------------------------------------
#endif // _PDF_WRITER_SRC_CONSTS_H
#include "Destination.h"
#include "Pages.h"
namespace PdfWriter
{
//----------------------------------------------------------------------------------------
// CDestination
//----------------------------------------------------------------------------------------
CDestination::CDestination(CPage* pPage, CXref* pXref)
{
pXref->Add(this);
// Первый элемент массива должен быть страницей, которой принадлежит объект
Add((CObjectBase*)pPage);
Add("Fit"); // Значение по умолчанию Fit
}
bool CDestination::IsValid() const
{
if (m_arrList.size() < 2)
return false;
CObjectBase* pObject = Get(0, false);
if (object_type_DICT != pObject->GetType() || dict_type_PAGE != ((CDictObject*)pObject)->GetDictType())
return false;
return true;
}
void CDestination::PrepareArray()
{
CPage* pPage = (CPage*)Get(0);
if (m_arrList.size() > 1)
{
Clear();
Add((CObjectBase*)pPage);
}
}
void CDestination::SetXYZ(float fLeft, float fTop, float fZoom)
{
if (!IsValid())
return;
// Если параметр приближения задан некорректно, тогда оставляем его нетронутым(что соответствует значению 0)
if (fZoom < 0.08 || fZoom > 32)
fZoom = 0;
fLeft = max(fLeft, 0);
fTop = max(fTop, 0);
PrepareArray();
Add("XYZ");
Add(fLeft);
Add(fTop);
Add(fZoom);
}
void CDestination::SetFit()
{
if (!IsValid())
return;
PrepareArray();
Add("Fit");
}
void CDestination::SetFitH(float fTop)
{
if (!IsValid())
return;
PrepareArray();
Add("FitH");
Add(fTop);
}
void CDestination::SetFitV(float fLeft)
{
if (!IsValid())
return;
PrepareArray();
Add("FitV");
Add(fLeft);
}
void CDestination::SetFitR(float fLeft, float fBottom, float fRight, float fTop)
{
if (!IsValid())
return;
PrepareArray();
Add("FitR");
Add(fLeft);
Add(fBottom);
Add(fRight);
Add(fTop);
}
void CDestination::SetFitB()
{
if (!IsValid())
return;
PrepareArray();
Add("FitB");
}
void CDestination::SetFitBH(float fTop)
{
if (!IsValid())
return;
PrepareArray();
Add("FitBH");
Add(fTop);
}
void CDestination::SetFitBV(float fLeft)
{
if (!IsValid())
return;
PrepareArray();
Add("FitBV");
Add(fLeft);
}
}
#ifndef _PDF_WRITER_SRC_ANNOTATION_DESTINATION_H
#define _PDF_WRITER_SRC_ANNOTATION_DESTINATION_H
#include "Objects.h"
namespace PdfWriter
{
class CPage;
class CDestination : public CArrayObject
{
public:
CDestination(CPage* pPage, CXref* pXref);
bool IsValid() const;
void SetXYZ (float fLeft, float fTop, float fZoom);
void SetFit ();
void SetFitH (float fTop);
void SetFitV (float fLeft);
void SetFitR (float fLeft, float fBottom, float fRight, float fTop);
void SetFitB ();
void SetFitBH(float fTop);
void SetFitBV(float fLeft);
private:
void PrepareArray();
};
}
#endif // _PDF_WRITER_SRC_ANNOTATION_DESTINATION_H
#include "Document.h"
#include "Info.h"
#include "Catalog.h"
#include "Streams.h"
#include "EncryptDictionary.h"
#include "Encrypt.h"
#include "Pages.h"
#include "Outline.h"
#include "Destination.h"
#include "GState.h"
#include "Annotation.h"
#include "Image.h"
#include "Font14.h"
#include "FontCidTT.h"
#include "Shading.h"
#include "Pattern.h"
#ifdef CreateFont
#undef CreateFont
#endif
namespace PdfWriter
{
const char* c_sPdfHeader = "%PDF-1.7\012%ASC\012";
//----------------------------------------------------------------------------------------
// CDocument
//----------------------------------------------------------------------------------------
CDocument::CDocument()
{
m_pCatalog = NULL;
m_pOutlines = NULL;
m_pXref = NULL;
m_pPageTree = NULL;
m_pCurPage = NULL;
m_nCurPageNum = -1;
m_pInfo = NULL;
m_pTrailer = NULL;
m_pResources = NULL;
m_bEncrypt = false;
m_pEncryptDict = NULL;
m_unCompressMode = COMP_NONE;
m_pJbig2 = NULL;
memset((void*)m_sTTFontTag, 0x00, 8);
}
CDocument::~CDocument()
{
Close();
}
bool CDocument::CreateNew()
{
Close();
m_pXref = new CXref(0);
if (!m_pXref)
return false;
m_pTrailer = m_pXref->GetTrailer();
if (!m_pTrailer)
return false;
m_pCatalog = new CCatalog(m_pXref);
if (!m_pCatalog)
return false;
m_pCatalog->SetPageMode(pagemode_UseNone);
m_pCatalog->SetPageLayout(pagelayout_Single);
m_pPageTree = m_pCatalog->GetRoot();
if (!m_pPageTree)
return false;
m_pInfo = new CInfoDict(m_pXref);
if (!m_pInfo)
return false;
m_pInfo->SetCreationTime();
m_pInfo->SetInfo(InfoProducer, "Ascensio System SIA Copyright (c) 2015");
m_nCurPageNum = -1;
m_vPages.clear();
return true;
}
void CDocument::Close()
{
// Все объекты удаляются внутри CXref
if (m_pXref)
{
delete m_pXref;
m_pXref = NULL;
}
m_pTrailer = NULL;
m_pCatalog = NULL;
m_pOutlines = NULL;
m_pPageTree = NULL;
m_pCurPage = NULL;
m_bEncrypt = false;
m_pEncryptDict = NULL;
m_pInfo = NULL;
m_unCompressMode = COMP_NONE;
memset((void*)m_sTTFontTag, 0x00, 8);
m_vExtGrStates.clear();
m_vPages.clear();
m_vShadings.clear();
}
bool CDocument::SaveToFile(const std::wstring& wsPath)
{
CFileStream* pStream = new CFileStream();
if (!pStream || !pStream->OpenFile(wsPath, true))
return false;
if (m_pJbig2)
m_pJbig2->FlushStreams();
SaveToStream((CStream*)pStream);
delete pStream;
return true;
}
void CDocument::SaveToStream(CStream* pStream)
{
unsigned long nRet = OK;
// Пишем заголовок
pStream->WriteStr(c_sPdfHeader);
// Добавляем в Trailer необходимые элементы
m_pTrailer->Add("Root", m_pCatalog);
m_pTrailer->Add("Info", m_pInfo);
// Шифруем документ, если это необходимо
CEncrypt* pEncrypt = NULL;
if (m_bEncrypt)
{
pEncrypt = m_pEncryptDict->GetEncrypt();
PrepareEncryption();
}
m_pXref->WriteToStream(pStream, pEncrypt);
}
void CDocument::PrepareEncryption()
{
CEncrypt* pEncrypt = m_pEncryptDict->GetEncrypt();
if (!pEncrypt)
return;
m_pEncryptDict->Prepare(m_pInfo, m_pXref);
CArrayObject* pID = (CArrayObject*)m_pTrailer->Get("ID");
if (!pID)
{
pID = new CArrayObject();
m_pTrailer->Add("ID", pID);
}
else
pID->Clear();
pID->Add(new CBinaryObject(pEncrypt->m_anEncryptID, ID_LEN));
pID->Add(new CBinaryObject(pEncrypt->m_anEncryptID, ID_LEN));
}
void CDocument::SetEncryptionMode(EEncryptMode eMode, unsigned int unKeyLen)
{
if (!m_bEncrypt)
return;
CEncrypt* pEncrypt = m_pEncryptDict->GetEncrypt();
pEncrypt->SetMode(eMode, unKeyLen);
}
void CDocument::SetPassword(const char* sOwnerPassword, const char* sUserPassword)
{
if (!m_pEncryptDict)
m_pEncryptDict = new CEncryptDict(m_pXref);
if (!m_pEncryptDict)
return;
m_pEncryptDict->SetPassword(sOwnerPassword, sUserPassword);
m_pTrailer->Add("Encrypt", m_pEncryptDict);
m_bEncrypt = true;
}
CPage* CDocument::AddPage()
{
CPage* pPage = new CPage(m_pXref, m_pPageTree);
m_pPageTree->AddPage(pPage);
m_pCurPage = pPage;
m_vPages.push_back(pPage);
#ifndef FILTER_FLATE_DECODE_DISABLED
if (m_unCompressMode & COMP_TEXT)
pPage->SetFilter(STREAM_FILTER_FLATE_DECODE);
#endif
m_nCurPageNum++;
return pPage;
}
void CDocument::SetPermission(unsigned int unPermission)
{
if (!m_bEncrypt)
return;
CEncrypt* pEncrypt = m_pEncryptDict->GetEncrypt();
pEncrypt->SetPermission(unPermission);
}
void CDocument::SetCompressionMode(unsigned int unMode)
{
m_unCompressMode = unMode;
}
void CDocument::AddPageLabel(EPageNumStyle eStyle, unsigned int unFirstPage, const char* sPrefix)
{
CDictObject* pPageLabel = CreatePageLabel(eStyle, unFirstPage, sPrefix);
if (!pPageLabel)
return;
m_pCatalog->AddPageLabel(m_nCurPageNum, pPageLabel);
}
void CDocument::AddPageLabel(unsigned int unPageNum, EPageNumStyle eStyle, unsigned int unFirstPage, const char* sPrefix)
{
CDictObject* pPageLabel = CreatePageLabel(eStyle, unFirstPage, sPrefix);
if (!pPageLabel)
return;
m_pCatalog->AddPageLabel(unPageNum, pPageLabel);
}
CDictObject* CDocument::CreatePageLabel(EPageNumStyle eStyle, unsigned int unFirstPage, const char* sPrefix)
{
CDictObject* pLabel = new CDictObject();
if (!pLabel)
return NULL;
eStyle = min(max(eStyle, pagenumstyle_Min), pagenumstyle_Max);
switch (eStyle)
{
case pagenumstyle_UpperRoman: pLabel->Add("S", "R"); break;
case pagenumstyle_LowerRoman: pLabel->Add("S", "r"); break;
case pagenumstyle_UpperLetters: pLabel->Add("S", "A"); break;
case pagenumstyle_LowerLetters: pLabel->Add("S", "a"); break;
case pagenumstyle_Decimal: pLabel->Add("S", "D"); break;
}
if (sPrefix && 0 != sPrefix[0])
pLabel->Add("P", new CStringObject(sPrefix));
if (0 != unFirstPage)
pLabel->Add("St", unFirstPage);
return pLabel;
}
COutline* CDocument::CreateOutline(COutline* pParent, const char* sTitle)
{
if (!pParent)
{
if (!m_pOutlines)
{
m_pOutlines = new COutline(m_pXref);
if (m_pOutlines)
m_pCatalog->Add("Outlines", m_pOutlines);
else
return NULL;
}
pParent = m_pOutlines;
}
return new COutline(pParent, sTitle, m_pXref);
}
CDestination* CDocument::CreateDestination(unsigned int unPageIndex)
{
if (unPageIndex >= m_vPages.size())
return NULL;
CPage* pPage = m_vPages.at(unPageIndex);
return new CDestination(pPage, m_pXref);
}
CExtGrState* CDocument::FindExtGrState(double dAlphaStroke, double dAlphaFill, EBlendMode eMode, int nStrokeAdjustment)
{
CExtGrState* pExtGrState = NULL;
for (unsigned int unIndex = 0, unCount = m_vExtGrStates.size(); unIndex < unCount; unIndex++)
{
pExtGrState = m_vExtGrStates.at(unIndex);
if (dAlphaStroke != pExtGrState->GetAlphaStroke())
continue;
if (dAlphaFill != pExtGrState->GetAlphaFill())
continue;
if (eMode != pExtGrState->GetBlendMode())
continue;
if ((0 == nStrokeAdjustment ? false : true) != pExtGrState->GetStrokeAdjustment())
continue;
return pExtGrState;
}
return NULL;
}
CExtGrState* CDocument::GetExtGState(double dAlphaStroke, double dAlphaFill, EBlendMode eMode, int nStrokeAdjustment)
{
CExtGrState* pExtGrState = FindExtGrState(dAlphaStroke, dAlphaFill, eMode, nStrokeAdjustment);
if (!pExtGrState)
{
pExtGrState = new CExtGrState(m_pXref);
if (!pExtGrState)
return NULL;
if (-1 != dAlphaStroke)
pExtGrState->SetAlphaStroke(dAlphaStroke);
if (-1 != dAlphaFill)
pExtGrState->SetAlphaFill(dAlphaFill);
if (blendmode_Unknown != eMode)
pExtGrState->SetBlendMode(eMode);
if (-1 != nStrokeAdjustment)
pExtGrState->SetStrokeAdjustment(0 == nStrokeAdjustment ? false : true);
m_vExtGrStates.push_back(pExtGrState);
}
return pExtGrState;
}
CAnnotation* CDocument::CreateTextAnnot(unsigned int unPageNum, TRect oRect, const char* sText)
{
CAnnotation* pAnnot = new CTextAnnotation(m_pXref, oRect, sText);
if (pAnnot)
{
CPage* pPage = m_vPages.at(unPageNum);
pPage->AddAnnotation(pAnnot);
}
return pAnnot;
}
CAnnotation* CDocument::CreateLinkAnnot(unsigned int unPageNum, TRect oRect, CDestination* pDest)
{
CAnnotation* pAnnot = new CLinkAnnotation(m_pXref, oRect, pDest);
if (pAnnot)
{
CPage* pPage = m_vPages.at(unPageNum);
pPage->AddAnnotation(pAnnot);
}
return pAnnot;
}
CAnnotation* CDocument::CreateUriLinkAnnot(unsigned int unPageNum, TRect oRect, const char* sUri)
{
CAnnotation* pAnnot = new CUriLinkAnnotation(m_pXref, oRect, sUri);
if (pAnnot)
{
CPage* pPage = m_vPages.at(unPageNum);
pPage->AddAnnotation(pAnnot);
}
return pAnnot;
}
CImageDict* CDocument::CreateImage()
{
return new CImageDict(m_pXref, this);
}
CFont14* CDocument::CreateFont14(EStandard14Fonts eType)
{
return new CFont14(m_pXref, this, eType);
}
CFontCidTrueType* CDocument::CreateTrueTypeFont(const std::wstring& wsFontPath, unsigned int unIndex)
{
return new CFontCidTrueType(m_pXref, this, wsFontPath, unIndex);
}
char* CDocument::GetTTFontTag()
{
if (0 == m_sTTFontTag[0])
{
MemCpy((BYTE*)m_sTTFontTag, (BYTE*)"BAAAAA+", 7);
}
else
{
for (unsigned int nIndex = 0; nIndex <= 5; nIndex++)
{
m_sTTFontTag[nIndex] += 1;
if (m_sTTFontTag[nIndex] > 'Z')
m_sTTFontTag[nIndex] = 'A';
else
break;
}
}
return m_sTTFontTag;
}
CJbig2Global* CDocument::GetJbig2Global()
{
if (m_pJbig2 && m_pJbig2->GetImagesCount() > 4)
{
// Удалять не надо, т.к. объект удалится в CXref
m_pJbig2->FlushStreams();
m_pJbig2 = NULL;
}
if (!m_pJbig2)
m_pJbig2 = new CJbig2Global(m_pXref);
return m_pJbig2;
}
CShading* CDocument::CreateAxialShading(double dX0, double dY0, double dX1, double dY1, unsigned char* pColors, double* pPoints, int nCount)
{
for (int nIndex = 0, nShadingsCount = m_vShadings.size(); nIndex < nShadingsCount; nIndex++)
{
CShading* pShading = m_vShadings.at(nIndex);
if (shadingtype_Axial == pShading->GetShadingType()
&& ((CAxialShading*)pShading)->Compare(dX0, dY0, dX1, dY1)
&& pShading->CompareColors(pColors, pPoints, nCount)
&& pShading->CompareExtend(true, true))
return pShading;
}
CAxialShading* pShading = new CAxialShading(m_pXref, dX0, dY0, dX1, dY1);
if (!pShading)
return NULL;
pShading->SetColors(pColors, pPoints, nCount);
pShading->SetExtend(true, true);
m_vShadings.push_back(pShading);
return pShading;
}
CShading* CDocument::CreateRaidalShading(double dX0, double dY0, double dR0, double dX1, double dY1, double dR1, unsigned char* pColors, double* pPoints, int nCount)
{
for (int nIndex = 0, nShadingsCount = m_vShadings.size(); nIndex < nShadingsCount; nIndex++)
{
CShading* pShading = m_vShadings.at(nIndex);
if (shadingtype_Radial == pShading->GetShadingType()
&& ((CRadialShading*)pShading)->Compare(dX0, dY0, dR0, dX1, dY1, dR1)
&& pShading->CompareColors(pColors, pPoints, nCount)
&& pShading->CompareExtend(true, true))
return pShading;
}
CRadialShading* pShading = new CRadialShading(m_pXref, dX0, dY0, dR0, dX1, dY1, dR1);
if (!pShading)
return NULL;
pShading->SetColors(pColors, pPoints, nCount);
pShading->SetExtend(true, true);
m_vShadings.push_back(pShading);
return pShading;
}
CImageTilePattern*CDocument::CreateImageTilePattern(double dW, double dH, CImageDict* pImageDict, EImageTilePatternType eType)
{
return new CImageTilePattern(m_pXref, dW, dH, pImageDict, eType);
}
}
#ifndef _PDF_WRITER_SRC_DOCUMENT_H
#define _PDF_WRITER_SRC_DOCUMENT_H
#include <vector>
#include <string>
#include "Types.h"
#ifdef CreateFont
#undef CreateFont
#endif
class CFontManager;
namespace PdfWriter
{
class CCatalog;
class COutline;
class CXref;
class CPageTree;
class CPage;
class CInfoDict;
class CDictObject;
class CEncryptDict;
class CStream;
class CDestination;
class CExtGrState;
class CAnnotation;
class CImageDict;
class CFontDict;
class CFont14;
class CFontCidTrueType;
class CJbig2Global;
class CShading;
class CImageTilePattern;
//----------------------------------------------------------------------------------------
// CDocument
//----------------------------------------------------------------------------------------
class CDocument
{
public:
CDocument();
~CDocument();
bool CreateNew();
void Close();
bool SaveToFile(const std::wstring& wsPath);
void SetEncryptionMode(EEncryptMode eMode, unsigned int unKeyLen = 0);
void SetPassword(const char* sOwnerPassword, const char* sUserPassword);
void SetPermission(unsigned int unPermission);
void SetCompressionMode(unsigned int unMode);
CPage* AddPage();
void AddPageLabel(EPageNumStyle eStyle, unsigned int unFirstPage, const char* sPrefix);
void AddPageLabel(unsigned int unPageIndex, EPageNumStyle eStyle, unsigned int unFirstPage, const char* sPrefix);
COutline* CreateOutline(COutline* pParent, const char* sTitle);
CDestination* CreateDestination(unsigned int unPageIndex);
CExtGrState* GetExtGState(double dAlphaStroke = -1, double dAlphaFill = -1, EBlendMode eMode = blendmode_Unknown, int nStrokeAdjustment = -1);
CJbig2Global* GetJbig2Global();
CAnnotation* CreateTextAnnot(unsigned int unPageNum, TRect oRect, const char* sText);
CAnnotation* CreateLinkAnnot(unsigned int unPageNum, TRect oRect, CDestination* pDest);
CAnnotation* CreateUriLinkAnnot(unsigned int unPageNum, TRect oRect, const char* sUri);
CImageDict* CreateImage();
CFont14* CreateFont14(EStandard14Fonts eType);
CFontCidTrueType* CreateTrueTypeFont(const std::wstring& wsFontPath, unsigned int unIndex);
CShading* CreateAxialShading(double dX0, double dY0, double dX1, double dY1, unsigned char* pColors, double* pPoints, int nCount);
CShading* CreateRaidalShading(double dX0, double dY0, double dR0, double dX1, double dY1, double dR1, unsigned char* pColors, double* pPoints, int nCount);
CImageTilePattern*CreateImageTilePattern(double dW, double dH, CImageDict* pImageDict, EImageTilePatternType eType = imagetilepatterntype_Default);
private:
char* GetTTFontTag();
CExtGrState* FindExtGrState(double dAlphaStroke = -1, double dAlphaFill = -1, EBlendMode eMode = blendmode_Unknown, int nStrokeAdjustment = -1);
void SaveToStream(CStream* pStream);
void PrepareEncryption();
CDictObject* CreatePageLabel(EPageNumStyle eStyle, unsigned int unFirstPage, const char* sPrefix);
private:
CCatalog* m_pCatalog;
COutline* m_pOutlines;
CXref* m_pXref;
CPageTree* m_pPageTree;
CPage* m_pCurPage;
int m_nCurPageNum;
CInfoDict* m_pInfo;
CDictObject* m_pTrailer;
CDictObject* m_pResources;
bool m_bEncrypt;
CEncryptDict* m_pEncryptDict;
unsigned int m_unCompressMode;
std::vector<CPage*> m_vPages;
std::vector<CExtGrState*> m_vExtGrStates;
char m_sTTFontTag[8]; // 6 символов + '+' + 0x00 ("BAAAAA+/0")
CJbig2Global* m_pJbig2;
std::vector<CShading*> m_vShadings;
friend class CFontCidTrueType;
};
}
#endif // _PDF_WRITER_SRC_DOCUMENT_H
#include "Encrypt.h"
#include "Objects.h"
// Оптимизационные функции.
#define OptFunc1(x, y, z) (z ^ (x & (y ^ z)))
#define OptFunc2(x, y, z) OptFunc1(z, x, y)
#define OptFunc3(x, y, z) (x ^ y ^ z)
#define OptFunc4(x, y, z) (y ^ (x | ~z))
// Основной шаг в алгоритме MD5.
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
namespace PdfWriter
{
static const BYTE c_sPaddingString[] =
{
0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41,
0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80,
0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A
};
void PadOrTrancatePassword(const char* sPassword, BYTE* pNewPassword)
{
unsigned int unLen = StrLen(sPassword, PASSWD_LEN + 1);
MemSet(pNewPassword, 0x00, PASSWD_LEN);
if (unLen >= PASSWD_LEN)
MemCpy(pNewPassword, (BYTE*)sPassword, PASSWD_LEN);
else
{
if (unLen > 0)
MemCpy(pNewPassword, (BYTE*)sPassword, unLen);
MemCpy(pNewPassword + unLen, c_sPaddingString, PASSWD_LEN - unLen);
}
}
// The core of the MD5 algorithm, this alters an existing MD5 hash to
// reflect the addition of 16 longwords of new data. MD5Update blocks
// the data and converts bytes into longwords for this routine.
static void MD5ByteReverse(BYTE *pBuf, unsigned int nLongs)
{
unsigned int nTemp = 0;
do
{
nTemp = (unsigned int)((unsigned int)pBuf[3] << 8 | pBuf[2]) << 16 | ((unsigned int)pBuf[1] << 8 | pBuf[0]);
*(unsigned int *)pBuf = nTemp;
pBuf += 4;
} while (--nLongs);
}
static void MD5Transform(unsigned int anBuf[4], const unsigned int anIn[16])
{
register unsigned int a, b, c, d;
a = anBuf[0];
b = anBuf[1];
c = anBuf[2];
d = anBuf[3];
MD5STEP(OptFunc1, a, b, c, d, anIn[0] + 0xd76aa478, 7);
MD5STEP(OptFunc1, d, a, b, c, anIn[1] + 0xe8c7b756, 12);
MD5STEP(OptFunc1, c, d, a, b, anIn[2] + 0x242070db, 17);
MD5STEP(OptFunc1, b, c, d, a, anIn[3] + 0xc1bdceee, 22);
MD5STEP(OptFunc1, a, b, c, d, anIn[4] + 0xf57c0faf, 7);
MD5STEP(OptFunc1, d, a, b, c, anIn[5] + 0x4787c62a, 12);
MD5STEP(OptFunc1, c, d, a, b, anIn[6] + 0xa8304613, 17);
MD5STEP(OptFunc1, b, c, d, a, anIn[7] + 0xfd469501, 22);
MD5STEP(OptFunc1, a, b, c, d, anIn[8] + 0x698098d8, 7);
MD5STEP(OptFunc1, d, a, b, c, anIn[9] + 0x8b44f7af, 12);
MD5STEP(OptFunc1, c, d, a, b, anIn[10] + 0xffff5bb1, 17);
MD5STEP(OptFunc1, b, c, d, a, anIn[11] + 0x895cd7be, 22);
MD5STEP(OptFunc1, a, b, c, d, anIn[12] + 0x6b901122, 7);
MD5STEP(OptFunc1, d, a, b, c, anIn[13] + 0xfd987193, 12);
MD5STEP(OptFunc1, c, d, a, b, anIn[14] + 0xa679438e, 17);
MD5STEP(OptFunc1, b, c, d, a, anIn[15] + 0x49b40821, 22);
MD5STEP(OptFunc2, a, b, c, d, anIn[1] + 0xf61e2562, 5);
MD5STEP(OptFunc2, d, a, b, c, anIn[6] + 0xc040b340, 9);
MD5STEP(OptFunc2, c, d, a, b, anIn[11] + 0x265e5a51, 14);
MD5STEP(OptFunc2, b, c, d, a, anIn[0] + 0xe9b6c7aa, 20);
MD5STEP(OptFunc2, a, b, c, d, anIn[5] + 0xd62f105d, 5);
MD5STEP(OptFunc2, d, a, b, c, anIn[10] + 0x02441453, 9);
MD5STEP(OptFunc2, c, d, a, b, anIn[15] + 0xd8a1e681, 14);
MD5STEP(OptFunc2, b, c, d, a, anIn[4] + 0xe7d3fbc8, 20);
MD5STEP(OptFunc2, a, b, c, d, anIn[9] + 0x21e1cde6, 5);
MD5STEP(OptFunc2, d, a, b, c, anIn[14] + 0xc33707d6, 9);
MD5STEP(OptFunc2, c, d, a, b, anIn[3] + 0xf4d50d87, 14);
MD5STEP(OptFunc2, b, c, d, a, anIn[8] + 0x455a14ed, 20);
MD5STEP(OptFunc2, a, b, c, d, anIn[13] + 0xa9e3e905, 5);
MD5STEP(OptFunc2, d, a, b, c, anIn[2] + 0xfcefa3f8, 9);
MD5STEP(OptFunc2, c, d, a, b, anIn[7] + 0x676f02d9, 14);
MD5STEP(OptFunc2, b, c, d, a, anIn[12] + 0x8d2a4c8a, 20);
MD5STEP(OptFunc3, a, b, c, d, anIn[5] + 0xfffa3942, 4);
MD5STEP(OptFunc3, d, a, b, c, anIn[8] + 0x8771f681, 11);
MD5STEP(OptFunc3, c, d, a, b, anIn[11] + 0x6d9d6122, 16);
MD5STEP(OptFunc3, b, c, d, a, anIn[14] + 0xfde5380c, 23);
MD5STEP(OptFunc3, a, b, c, d, anIn[1] + 0xa4beea44, 4);
MD5STEP(OptFunc3, d, a, b, c, anIn[4] + 0x4bdecfa9, 11);
MD5STEP(OptFunc3, c, d, a, b, anIn[7] + 0xf6bb4b60, 16);
MD5STEP(OptFunc3, b, c, d, a, anIn[10] + 0xbebfbc70, 23);
MD5STEP(OptFunc3, a, b, c, d, anIn[13] + 0x289b7ec6, 4);
MD5STEP(OptFunc3, d, a, b, c, anIn[0] + 0xeaa127fa, 11);
MD5STEP(OptFunc3, c, d, a, b, anIn[3] + 0xd4ef3085, 16);
MD5STEP(OptFunc3, b, c, d, a, anIn[6] + 0x04881d05, 23);
MD5STEP(OptFunc3, a, b, c, d, anIn[9] + 0xd9d4d039, 4);
MD5STEP(OptFunc3, d, a, b, c, anIn[12] + 0xe6db99e5, 11);
MD5STEP(OptFunc3, c, d, a, b, anIn[15] + 0x1fa27cf8, 16);
MD5STEP(OptFunc3, b, c, d, a, anIn[2] + 0xc4ac5665, 23);
MD5STEP(OptFunc4, a, b, c, d, anIn[0] + 0xf4292244, 6);
MD5STEP(OptFunc4, d, a, b, c, anIn[7] + 0x432aff97, 10);
MD5STEP(OptFunc4, c, d, a, b, anIn[14] + 0xab9423a7, 15);
MD5STEP(OptFunc4, b, c, d, a, anIn[5] + 0xfc93a039, 21);
MD5STEP(OptFunc4, a, b, c, d, anIn[12] + 0x655b59c3, 6);
MD5STEP(OptFunc4, d, a, b, c, anIn[3] + 0x8f0ccc92, 10);
MD5STEP(OptFunc4, c, d, a, b, anIn[10] + 0xffeff47d, 15);
MD5STEP(OptFunc4, b, c, d, a, anIn[1] + 0x85845dd1, 21);
MD5STEP(OptFunc4, a, b, c, d, anIn[8] + 0x6fa87e4f, 6);
MD5STEP(OptFunc4, d, a, b, c, anIn[15] + 0xfe2ce6e0, 10);
MD5STEP(OptFunc4, c, d, a, b, anIn[6] + 0xa3014314, 15);
MD5STEP(OptFunc4, b, c, d, a, anIn[13] + 0x4e0811a1, 21);
MD5STEP(OptFunc4, a, b, c, d, anIn[4] + 0xf7537e82, 6);
MD5STEP(OptFunc4, d, a, b, c, anIn[11] + 0xbd3af235, 10);
MD5STEP(OptFunc4, c, d, a, b, anIn[2] + 0x2ad7d2bb, 15);
MD5STEP(OptFunc4, b, c, d, a, anIn[9] + 0xeb86d391, 21);
anBuf[0] += a;
anBuf[1] += b;
anBuf[2] += c;
anBuf[3] += d;
}
//----------------------------------------------------------------------------------------
// CMd5
//----------------------------------------------------------------------------------------
CMd5::CMd5()
{
Init();
};
void CMd5::Init()
{
m_anBuf[0] = 0x67452301;
m_anBuf[1] = 0xefcdab89;
m_anBuf[2] = 0x98badcfe;
m_anBuf[3] = 0x10325476;
m_anBits[0] = 0;
m_anBits[1] = 0;
MemSet(m_anIn, 0x00, 64 * sizeof(BYTE));
}
void CMd5::Update(const BYTE* pBuffer, unsigned int unLen)
{
// Update bitcount
unsigned int nTempBit = m_anBits[0];
if ((m_anBits[0] = nTempBit + (unLen << 3)) < nTempBit)
m_anBits[1]++; // Carry from low to high
m_anBits[1] += unLen >> 29;
nTempBit = (nTempBit >> 3) & 0x3f; // Bytes already in shsInfo->data
// Handle any leading odd-sized chunks
if (nTempBit)
{
BYTE *pTemp = (BYTE *)m_anIn + nTempBit;
nTempBit = 64 - nTempBit;
if (unLen < nTempBit && pBuffer)
{
MemCpy(pTemp, pBuffer, unLen);
return;
}
if (pBuffer)
MemCpy(pTemp, pBuffer, nTempBit);
MD5ByteReverse(m_anIn, 16);
MD5Transform(m_anBuf, (unsigned int *)m_anIn);
pBuffer += nTempBit;
unLen -= nTempBit;
}
// Process data in 64-byte chunks
while (unLen >= 64)
{
MemCpy(m_anIn, pBuffer, 64);
MD5ByteReverse(m_anIn, 16);
MD5Transform(m_anBuf, (unsigned int *)m_anIn);
pBuffer += 64;
unLen -= 64;
}
// Handle any remaining bytes of data.
MemCpy(m_anIn, pBuffer, unLen);
}
// Final wrapup - pad to 64-byte boundary with the bit pattern
// 1 0* (64-bit count of bits processed, MSB-first)
void CMd5::Final(BYTE anDigest[16])
{
// Вычисляем количество байтов по модулю 64
unsigned int nCount = (m_anBits[0] >> 3) & 0x3F;
// Устанавливаем первый символ в дополнительной строке(padding) значением 0x80.
// Это безопасно, поскольку всегда как минимум один байт свободен.
BYTE *pTemp = m_anIn + nCount;
*pTemp++ = 0x80;
// Bytes of padding needed to make 64 bytes
nCount = 64 - 1 - nCount;
// Pad out to 56 mod 64
if (nCount < 8)
{
// Two lots of padding: Pad the first block to 64 bytes
MemSet(pTemp, 0, nCount);
MD5ByteReverse(m_anIn, 16);
MD5Transform(m_anBuf, (unsigned int *)m_anIn);
// Now fill the next block with 56 bytes
MemSet(m_anIn, 0, 56);
}
else
{
// Pad block to 56 bytes
MemSet(pTemp, 0, nCount - 8);
}
MD5ByteReverse(m_anIn, 14);
// Append length in bits and transform
((unsigned int *)m_anIn)[14] = m_anBits[0];
((unsigned int *)m_anIn)[15] = m_anBits[1];
MD5Transform(m_anBuf, (unsigned int *)m_anIn);
MD5ByteReverse((BYTE *)m_anBuf, 4);
MemCpy((BYTE *)anDigest, (BYTE *)m_anBuf, 16);
Clear(); // In case it's sensitive
}
void CMd5::Clear()
{
MemSet(m_anBits, 0, 2 * sizeof(unsigned int));
MemSet(m_anBuf, 0, 4 * sizeof(unsigned int));
MemSet(m_anIn, 0x00, 64 * sizeof(BYTE));
}
//----------------------------------------------------------------------------------------
// CArc4
//----------------------------------------------------------------------------------------
void CArc4::Init(const BYTE* pKey, unsigned int unKeyLen)
{
BYTE pTempArray[ARC4_BUF_SIZE];
unsigned int nJ = 0;
for (unsigned int nIndex = 0; nIndex < ARC4_BUF_SIZE; nIndex++)
m_anState[nIndex] = nIndex;
for (unsigned int nIndex = 0; nIndex < ARC4_BUF_SIZE; nIndex++)
pTempArray[nIndex] = pKey[nIndex % unKeyLen];
for (unsigned int nIndex = 0; nIndex < ARC4_BUF_SIZE; nIndex++)
{
nJ = (nJ + m_anState[nIndex] + pTempArray[nIndex]) % ARC4_BUF_SIZE;
BYTE nTemp = m_anState[nIndex];
m_anState[nIndex] = m_anState[nJ];
m_anState[nJ] = nTemp;
}
m_nIndex1 = 0;
m_nIndex2 = 0;
}
void CArc4::CryptBuf(const BYTE* pIn, BYTE* pOut, unsigned int unLen)
{
for (unsigned int nIndex = 0; nIndex < unLen; nIndex++)
{
m_nIndex1 = (m_nIndex1 + 1) % 256;
m_nIndex2 = (m_nIndex2 + m_anState[m_nIndex1]) % 256;
BYTE nTemp = m_anState[m_nIndex1];
m_anState[m_nIndex1] = m_anState[m_nIndex2];
m_anState[m_nIndex2] = nTemp;
unsigned int nTempIndex = (m_anState[m_nIndex1] + m_anState[m_nIndex2]) % 256;
BYTE nKoef = m_anState[nTempIndex];
pOut[nIndex] = pIn[nIndex] ^ nKoef;
}
}
//----------------------------------------------------------------------------------------
// CEncrypt
//----------------------------------------------------------------------------------------
CEncrypt::CEncrypt()
{
Init();
}
void CEncrypt::Init()
{
m_eMode = encryptmode_R2;
m_unKeyLen = 5;
MemCpy(m_anOwnerPassword, c_sPaddingString, PASSWD_LEN);
MemCpy(m_anUserPassword, c_sPaddingString, PASSWD_LEN);
m_unPermission = ENABLE_PRINT | ENABLE_EDIT_ALL | ENABLE_COPY | ENABLE_EDIT | PERMISSION_PAD;
MemSet(m_anOwnerKey, 0, PASSWD_LEN);
MemSet(m_anUserKey, 0, PASSWD_LEN);
MemSet(m_anEncryptID, 0, ID_LEN);
MemSet(m_anEncryptionKey, 0, MD5_KEY_LEN + 5);
MemSet(m_anMD5EncryptionKey, 0, MD5_KEY_LEN);
}
void CEncrypt::CreateUserKey()
{
CArc4 oContext;
// Algorithm 3.4/5 step1
// Algorithm 3.4 step2
oContext.Init(m_anEncryptionKey, m_unKeyLen);
oContext.CryptBuf(c_sPaddingString, m_anUserKey, PASSWD_LEN);
if (encryptmode_R3 == m_eMode)
{
CMd5 oMmd5;
BYTE anDigest[MD5_KEY_LEN];
BYTE anDigest2[MD5_KEY_LEN];
// Algorithm 3.5 step2 (same as Algorithm3.2 step2)
oMmd5.Init();
oMmd5.Update(c_sPaddingString, PASSWD_LEN);
// Algorithm 3.5 step3
oMmd5.Update(m_anEncryptID, ID_LEN);
oMmd5.Final(anDigest);
// Algorithm 3.5 step4
oContext.Init(m_anEncryptionKey, m_unKeyLen);
oContext.CryptBuf(anDigest, anDigest2, MD5_KEY_LEN);
// Algorithm 3.5 step5
for (unsigned int nI = 1; nI <= 19; nI++)
{
BYTE pNewKey[MD5_KEY_LEN];
for (unsigned int nJ = 0; nJ < m_unKeyLen; nJ++)
pNewKey[nJ] = m_anEncryptionKey[nJ] ^ nI;
MemCpy(anDigest, anDigest2, MD5_KEY_LEN);
oContext.Init(pNewKey, m_unKeyLen);
oContext.CryptBuf(anDigest, anDigest2, MD5_KEY_LEN);
}
// use the result of Algorithm 3.4 as 'arbitrary padding'
MemSet(m_anUserKey, 0, PASSWD_LEN);
MemCpy(m_anUserKey, anDigest2, MD5_KEY_LEN);
}
}
void CEncrypt::CreateOwnerKey()
{
CArc4 oArc4;
CMd5 oMd5;
BYTE anDigest[MD5_KEY_LEN];
BYTE anTempPassword[PASSWD_LEN];
// create md5-digest using the value of anOwnerPassword
// Algorithm 3.3 step 2
oMd5.Init();
oMd5.Update(m_anOwnerPassword, PASSWD_LEN);
oMd5.Final(anDigest);
// Algorithm 3.3 step 3 (Revision 3 only)
if (encryptmode_R3 == m_eMode)
{
for (unsigned int nIndex = 0; nIndex < 50; nIndex++)
{
oMd5.Init();
oMd5.Update(anDigest, m_unKeyLen);
oMd5.Final(anDigest);
}
}
// Algorithm 3.3 step 4
oArc4.Init(anDigest, m_unKeyLen);
// Algorithm 3.3 step 6
oArc4.CryptBuf(m_anUserPassword, anTempPassword, PASSWD_LEN);
// Algorithm 3.3 step 7
if (encryptmode_R3 == m_eMode)
{
BYTE anTempPassword2[PASSWD_LEN];
for (unsigned int i = 1; i <= 19; i++)
{
BYTE anNewKey[MD5_KEY_LEN];
for (unsigned int j = 0; j < m_unKeyLen; j++)
anNewKey[j] = anDigest[j] ^ i;
MemCpy(anTempPassword2, anTempPassword, PASSWD_LEN);
oArc4.Init(anNewKey, m_unKeyLen);
oArc4.CryptBuf(anTempPassword2, anTempPassword, PASSWD_LEN);
}
}
// Algorithm 3.3 step 8
MemCpy(m_anOwnerKey, anTempPassword, PASSWD_LEN);
}
void CEncrypt::CreateEncryptionKey()
{
CMd5 oMd5;
BYTE anTempFlag[4];
// Algorithm3.2 step2
oMd5.Init();
oMd5.Update(m_anUserPassword, PASSWD_LEN);
// Algorithm3.2 step3
oMd5.Update(m_anOwnerKey, PASSWD_LEN);
// Algorithm3.2 step4
anTempFlag[0] = m_unPermission;
anTempFlag[1] = (m_unPermission >> 8);
anTempFlag[2] = (m_unPermission >> 16);
anTempFlag[3] = (m_unPermission >> 24);
oMd5.Update(anTempFlag, 4);
// Algorithm3.2 step5
oMd5.Update(m_anEncryptID, ID_LEN);
oMd5.Final(m_anEncryptionKey);
// Algorithm 3.2 step6 (Revision 3 only)
if (encryptmode_R3 == m_eMode)
{
for (unsigned int nIndex = 0; nIndex < 50; nIndex++)
{
oMd5.Init();
oMd5.Update(m_anEncryptionKey, m_unKeyLen);
oMd5.Final(m_anEncryptionKey);
}
}
}
void CEncrypt::InitKey(unsigned int unObjectId, unsigned short unGenNo)
{
m_anEncryptionKey[m_unKeyLen + 0] = (BYTE) unObjectId;
m_anEncryptionKey[m_unKeyLen + 1] = (BYTE)(unObjectId >> 8);
m_anEncryptionKey[m_unKeyLen + 2] = (BYTE)(unObjectId >> 16);
m_anEncryptionKey[m_unKeyLen + 3] = (BYTE) unGenNo;
m_anEncryptionKey[m_unKeyLen + 4] = (BYTE)(unGenNo >> 8);
CMd5 oMd5;
oMd5.Init();
oMd5.Update(m_anEncryptionKey, m_unKeyLen + 5);
oMd5.Final(m_anMD5EncryptionKey);
unsigned int unKeyLen = (m_unKeyLen + 5 > ENCRYPT_KEY_MAX) ? ENCRYPT_KEY_MAX : m_unKeyLen + 5;
m_oArc4Context.Init(m_anMD5EncryptionKey, unKeyLen);
}
void CEncrypt::Reset()
{
unsigned int unKeyLen = (m_unKeyLen + 5 > ENCRYPT_KEY_MAX) ? ENCRYPT_KEY_MAX : m_unKeyLen + 5;
m_oArc4Context.Init(m_anMD5EncryptionKey, unKeyLen);
}
void CEncrypt::CryptBuf(const BYTE* pSrc, BYTE* pDst, unsigned int unLen)
{
m_oArc4Context.CryptBuf(pSrc, pDst, unLen);
}
void CEncrypt::SetPermission(unsigned int unPermission)
{
m_unPermission = unPermission;
}
void CEncrypt::SetMode(EEncryptMode eMode, unsigned int unKeyLen)
{
if (encryptmode_R2 == eMode)
m_unKeyLen = 5;
else
{
if (unKeyLen >= 5 && unKeyLen <= 16)
m_unKeyLen = unKeyLen;
else
m_unKeyLen = 16;
}
m_eMode = eMode;
}
}
\ No newline at end of file
#ifndef _PDF_WRITER_SRC_ENCRYPT_H
#define _PDF_WRITER_SRC_ENCRYPT_H
#include "Utils.h"
#define ID_LEN 16
#define PASSWD_LEN 32
#define ENCRYPT_KEY_MAX 16
#define MD5_KEY_LEN 16
#define PERMISSION_PAD 0xFFFFFFC0
#define ARC4_BUF_SIZE 256
namespace PdfWriter
{
void PadOrTrancatePassword(const char *sPassword, BYTE *pNewPassword);
//----------------------------------------------------------------------------------------
//
// The code implements MD5 message-digest algorithm.
// To compute the message digest of a chunk of bytes, declare an
// MD5Context structure, pass it to MD5Init, call MD5Update as
// needed on buffers full of bytes, and then call MD5Final, which
// will fill a supplied 16-byte array with the digest.
//
//----------------------------------------------------------------------------------------
class CMd5
{
public:
CMd5();
void Init();
void Update(const BYTE* pBuffer, unsigned int unLen);
void Final(BYTE anDigest[16]);
private:
void Clear();
private:
unsigned int m_anBuf[4];
unsigned int m_anBits[2];
BYTE m_anIn[64];
};
class CArc4
{
public:
void Init(const BYTE* pKey, unsigned int unKeyLen);
void CryptBuf(const BYTE* pIn, BYTE* pOut, unsigned int unLen);
private:
BYTE m_nIndex1;
BYTE m_nIndex2;
BYTE m_anState[ARC4_BUF_SIZE];
};
class CEncrypt
{
public:
CEncrypt();
void Init();
void CreateUserKey();
void CreateOwnerKey();
void CreateEncryptionKey();
void InitKey(unsigned int unObjectId, unsigned short unGenNo);
void Reset();
void CryptBuf(const BYTE* pSrc, BYTE* pDst, unsigned int unLen);
void SetPermission(unsigned int unPermission);
void SetMode(EEncryptMode eMode, unsigned int unKeyLen);
private:
EEncryptMode m_eMode;
unsigned int m_unKeyLen; // unKeyLen должно быть кратно 8, и лежать в отрезке от 40 и до 128
BYTE m_anOwnerPassword[PASSWD_LEN]; // Owner-Password (не шифрованный)
BYTE m_anUserPassword[PASSWD_LEN]; // User-Password (не шифрованный)
BYTE m_anOwnerKey[PASSWD_LEN]; // Owner-Password (шифрованный)
BYTE m_anUserKey[PASSWD_LEN]; // User-Password (шифрованный)
unsigned int m_unPermission;
BYTE m_anEncryptID[ID_LEN];
BYTE m_anEncryptionKey[MD5_KEY_LEN + 5];
BYTE m_anMD5EncryptionKey[MD5_KEY_LEN];
CArc4 m_oArc4Context;
friend class CEncryptDict;
friend class CDocument;
};
}
#endif // _PDF_WRITER_SRC_ENCRYPT_H
#include "EncryptDictionary.h"
#include "Encrypt.h"
#include "Info.h"
#include <ctime>
namespace PdfWriter
{
//----------------------------------------------------------------------------------------
// CEncryptDict
//----------------------------------------------------------------------------------------
CEncryptDict::CEncryptDict(CXref* pXref)
{
m_pEncrypt = new CEncrypt();
if (m_pEncrypt)
m_pEncrypt->Init();
pXref->Add(this);
}
CEncryptDict::~CEncryptDict()
{
if (m_pEncrypt)
delete m_pEncrypt;
}
void CEncryptDict::CreateId(CInfoDict* pInfo, CXref* pXref)
{
CMd5 oMd5;
oMd5.Init();
std::time_t oTime = time(0);
oMd5.Update((BYTE*)&oTime, sizeof(oTime));
// Создаем идентификатор файла по элементам библиотеки Info.
if (pInfo)
{
const char *sTemp = NULL;
unsigned int nLen = 0;
// Author
sTemp = pInfo->GetInfo(InfoAuthor);
if ((nLen = StrLen(sTemp, -1)) > 0)
oMd5.Update((const BYTE *)sTemp, nLen);
// Creator
sTemp = pInfo->GetInfo(InfoCreator);
if ((nLen = StrLen(sTemp, -1)) > 0)
oMd5.Update((const BYTE *)sTemp, nLen);
// Producer
sTemp = pInfo->GetInfo(InfoProducer);
if ((nLen = StrLen(sTemp, -1)) > 0)
oMd5.Update((const BYTE *)sTemp, nLen);
// Title
sTemp = pInfo->GetInfo(InfoTitle);
if ((nLen = StrLen(sTemp, -1)) > 0)
oMd5.Update((const BYTE *)sTemp, nLen);
// Subject
sTemp = pInfo->GetInfo(InfoSubject);
if ((nLen = StrLen(sTemp, -1)) > 0)
oMd5.Update((const BYTE *)sTemp, nLen);
// Keywords
sTemp = pInfo->GetInfo(InfoKeyWords);
if ((nLen = StrLen(sTemp, -1)) > 0)
oMd5.Update((const BYTE *)sTemp, nLen);
int nXrefEntriesCount = pXref->GetCount();
oMd5.Update((const BYTE *)&nXrefEntriesCount, sizeof(unsigned int));
}
oMd5.Final(m_pEncrypt->m_anEncryptID);
}
void CEncryptDict::SetPassword(const char* sOwnerPassword, const char* sUserPassword)
{
if (0 == StrLen(sOwnerPassword, 2))
return;
if (sOwnerPassword && sUserPassword && 0 == StrCmp(sOwnerPassword, sUserPassword))
return;
PadOrTrancatePassword(sOwnerPassword, m_pEncrypt->m_anOwnerPassword);
PadOrTrancatePassword(sUserPassword, m_pEncrypt->m_anUserPassword);
}
void CEncryptDict::Prepare(CInfoDict* pInfo, CXref* pXref)
{
CreateId(pInfo, pXref);
m_pEncrypt->CreateOwnerKey();
m_pEncrypt->CreateEncryptionKey();
m_pEncrypt->CreateUserKey();
CBinaryObject* pOwnerKey = new CBinaryObject(m_pEncrypt->m_anOwnerKey, PASSWD_LEN);
if (!pOwnerKey)
return;
Add("O", pOwnerKey);
CBinaryObject* pUserKey = new CBinaryObject(m_pEncrypt->m_anUserKey, PASSWD_LEN);
if (!pUserKey)
return;
Add("U", pUserKey);
Add("Filter", "Standard");
if (encryptmode_R2 == m_pEncrypt->m_eMode)
{
Add("V", 1);
Add("R", 2);
}
else if (encryptmode_R3 == m_pEncrypt->m_eMode)
{
Add("V", 2);
Add("R", 3);
Add("Length", m_pEncrypt->m_unKeyLen * 8);
}
Add("P", m_pEncrypt->m_unPermission);
}
}
\ No newline at end of file
#ifndef _PDF_WRITER_SRC_ENCRYPT_DICTIONARY_H
#define _PDF_WRITER_SRC_ENCRYPT_DICTIONARY_H
#include "Objects.h"
namespace PdfWriter
{
class CEncrypt;
class CInfoDict;
class CEncryptDict : public CDictObject
{
public:
CEncryptDict(CXref* pXref);
~CEncryptDict();
EDictType GetDictType() const
{
return dict_type_ENCRYPT;
}
void CreateId(CInfoDict* pInfo, CXref* pXref);
void SetPassword(const char* sOwnerPassword, const char* sUserPassword);
void Prepare(CInfoDict* pInfo, CXref* pXref);
CEncrypt* GetEncrypt() const
{
return m_pEncrypt;
}
private:
CEncrypt* m_pEncrypt;
};
}
#endif // _PDF_WRITER_SRC_ENCRYPT_DICTIONARY_H
#include "Font.h"
namespace PdfWriter
{
CFontDict::CFontDict(CXref* pXref, CDocument* pDocument)
{
m_pXref = pXref;
pXref->Add(this);
m_pDocument = pDocument;
}
CFontDict::~CFontDict()
{
}
}
#ifndef _PDF_WRITER_SRC_FONT_H
#define _PDF_WRITER_SRC_FONT_H
#include "Objects.h"
namespace PdfWriter
{
class CDocument;
class CFontDict : public CDictObject
{
public:
CFontDict(CXref* pXref, CDocument* pDocument);
virtual ~CFontDict();
EDictType GetDictType() const
{
return dict_type_FONT;
}
virtual EFontType GetFontType()
{
return fontUnknownType;
}
protected:
CXref* m_pXref;
CDocument* m_pDocument;
};
}
#endif // _PDF_WRITER_SRC_FONT_H
#include "Font14.h"
namespace PdfWriter
{
static const char* c_sStandardFontNames[] =
{
"Helvetica",
"Helvetica-Bold",
"Helvetica-Oblique",
"Helvetice-BoldOblique",
"Courier",
"Courier-Bold",
"Courier-Oblique",
"Courier-BoldOblique",
"Times",
"Times-Bold",
"Times-Oblique",
"Times-BoldOblique",
"Symbol",
"ZapfDingbats",
NULL
};
CFont14::CFont14(CXref* pXref, CDocument* pDocument, EStandard14Fonts eType) : CFontDict(pXref, pDocument)
{
Add("Type", "Font");
Add("Subtype", "Type1");
Add("BaseFont", c_sStandardFontNames[(int)eType]);
}
}
\ No newline at end of file
#ifndef _PDF_WRITER_SRC_FONT14_H
#define _PDF_WRITER_SRC_FONT14_H
#include "Font.h"
namespace PdfWriter
{
class CXref;
class CDocument;
class CFont14 : public CFontDict
{
public:
CFont14(CXref* pXref, CDocument* pDocument, EStandard14Fonts eType);
EFontType GetFontType()
{
return fontType1;
}
};
}
#endif // _PDF_WRITER_SRC_FONT14_H
\ No newline at end of file
#include "FontCidTT.h"
#include "Document.h"
#include "Streams.h"
#include "Utils.h"
#include "FontTTWriter.h"
#include "../../DesktopEditor/fontengine/FontManager.h"
#include "../../DesktopEditor/common/File.h"
#include <string>
#include FT_TRUETYPE_TABLES_H
namespace PdfWriter
{
static const char* c_sToUnicodeHeader = "/CIDInit /ProcSet findresource begin\n12 dict begin\nbegincmap\n";
static const char* c_sToUnicodeInfo = "/CIDSystemInfo\n<< /Registry (Adobe)\n /Ordering (UCS)\n /Supplement 0\n >> def\n/CMapName /Adobe-Identity-UCS def\n/CMapType 2 def\n1 begincodespacerange\n<0000> <FFFF>\nendcodespacerange\n";
static const char* c_sToUnicodeFooter = "endcmap\nCMapName currentdict /CMap defineresource pop\nend\nend\n";
static unsigned short GetGID(FT_Face pFace, unsigned int unUnicode)
{
int nCharIndex = 0;
if (!pFace)
return nCharIndex;
for (int nIndex = 0; nIndex < pFace->num_charmaps; nIndex++)
{
FT_CharMap pCharMap = pFace->charmaps[nIndex];
if (FT_Set_Charmap(pFace, pCharMap))
continue;
FT_Encoding pEncoding = pCharMap->encoding;
if (FT_ENCODING_UNICODE == pEncoding)
{
if (nCharIndex = FT_Get_Char_Index(pFace, unUnicode))
return nCharIndex;
}
if (FT_ENCODING_NONE == pEncoding || FT_ENCODING_MS_SYMBOL == pEncoding || FT_ENCODING_APPLE_ROMAN == pEncoding)
{
nCharIndex = FT_Get_Char_Index(pFace, unUnicode);
}
/*else if ( FT_ENCODING_ADOBE_STANDARD == pEncoding )
{
nCharIndex = FT_Get_Char_Index( pFace, unUnicode );
}
else if ( FT_ENCODING_ADOBE_CUSTOM == pEncoding )
{
nCharIndex = FT_Get_Char_Index( pFace, unUnicode );
}
else if ( FT_ENCODING_ADOBE_EXPERT == pEncoding )
{
nCharIndex = FT_Get_Char_Index( pFace, unUnicode );
}*/
}
return nCharIndex;
}
static int GetSymbolicCmapIndex(FT_Face pFace)
{
TT_OS2 *pOs2 = (TT_OS2 *)FT_Get_Sfnt_Table(pFace, ft_sfnt_os2);
if (NULL == pOs2 || 0xFFFF == pOs2->version)
return -1;
// 31
if (!(pOs2->ulCodePageRange1 & 0x80000000) && !(pOs2->ulCodePageRange1 == 0 && pOs2->ulCodePageRange2 == 0))
return -1;
for (int nIndex = 0; nIndex < pFace->num_charmaps; nIndex++)
{
// Symbol
if (0 == pFace->charmaps[nIndex]->encoding_id && 3 == pFace->charmaps[nIndex]->platform_id)
return nIndex;
}
return -1;
}
//----------------------------------------------------------------------------------------
// CFontFileBase
//----------------------------------------------------------------------------------------
CFontCidTrueType::CFontCidTrueType(CXref* pXref, CDocument* pDocument, const std::wstring& wsFontPath, unsigned int unIndex) : CFontDict(pXref, pDocument)
{
CFontFileTrueType* pFontTT = CFontFileTrueType::LoadFromFile(wsFontPath, unIndex);
m_pFontFile = pFontTT;
m_wsFontPath = wsFontPath;
m_unFontIndex = unIndex;
Add("Type", "Font");
Add("Subtype", "Type0");
Add("Encoding", "Identity-H");
CDictObject* pFont = new CDictObject();
m_pXref->Add(pFont);
CArrayObject* pDescendantFonts = new CArrayObject();
pDescendantFonts->Add(pFont);
Add("DescendantFonts", pDescendantFonts);
CDictObject* pToUnicodeDict = new CDictObject(m_pXref, true);
Add("ToUnicode", pToUnicodeDict);
pToUnicodeDict->SetFilter(STREAM_FILTER_FLATE_DECODE);
m_pToUnicodeStream = pToUnicodeDict->GetStream();
CreateCIDFont2(pFont);
}
CFontCidTrueType::~CFontCidTrueType()
{
if (m_pFontFile)
delete m_pFontFile;
}
void CFontCidTrueType::CreateCIDFont2(CDictObject* pFont)
{
m_pFont = pFont;
pFont->Add("Subtype", "CIDFontType2");
CDictObject* pSystemInfo = new CDictObject();
pSystemInfo->Add("Registry", new CStringObject("Adobe"));
pSystemInfo->Add("Ordering", new CStringObject("Identity"));
pSystemInfo->Add("Supplement", 0);
pFont->Add("CIDSystemInfo", pSystemInfo);
CDictObject* pFontDescriptor = new CDictObject();
// FontDescriptor
m_pXref->Add(pFontDescriptor);
pFontDescriptor->Add("Type", "FontDescriptor");
m_pFontDescriptor = pFontDescriptor;
// Symbolic, NonSymbolic
unsigned int nFlags = 0;
if (!(nFlags & 4))
UIntChangeBit(nFlags, 2);
if (nFlags & 32)
UIntChangeBit(nFlags, 5);
pFontDescriptor->Add("Flags", nFlags);
CArrayObject* pBBox = new CArrayObject();
int* pFontBBox = m_pFontFile->GetBBox();
pBBox->Add(pFontBBox[0]);
pBBox->Add(pFontBBox[1]);
pBBox->Add(pFontBBox[2]);
pBBox->Add(pFontBBox[3]);
pFontDescriptor->Add("FontBBox", pBBox);
pFontDescriptor->Add("ItalicAngle", 0);
pFontDescriptor->Add("Ascent", m_pFontFile->GetAscent());
pFontDescriptor->Add("Descent", m_pFontFile->GetDescent());
pFontDescriptor->Add("CapHeight", m_pFontFile->GetCapHeight());
pFontDescriptor->Add("StemV", 0);
pFontDescriptor->Add("FontWeight", m_pFontFile->GetWeight());
m_pFontFileDict = new CDictObject(m_pXref, true);
pFontDescriptor->Add("FontFile2", m_pFontFileDict);
pFont->Add("FontDescriptor", pFontDescriptor);
CDictObject* pCIDToGIDMapDict = new CDictObject(m_pXref, true);
pFont->Add("CIDToGIDMap", pCIDToGIDMapDict);
pCIDToGIDMapDict->SetFilter(STREAM_FILTER_FLATE_DECODE);
m_pCidToGidMapStream = pCIDToGIDMapDict->GetStream();
}
unsigned char* CFontCidTrueType::EncodeString(unsigned int* pUnicodes, unsigned int unLen)
{
unsigned char* pEncodedString = new unsigned char[unLen * 2];
// 0x0000..0xFFFF
// Gid .
// .
for (unsigned int unIndex = 0; unIndex < unLen; unIndex++)
{
std::map<unsigned int, unsigned short>::const_iterator oIter = m_mUnicodeToCode.find(pUnicodes[unIndex]);
unsigned short ushCode;
if (oIter != m_mUnicodeToCode.end())
{
ushCode = oIter->second;
}
else
{
m_mUnicodeToCode.insert(std::pair<unsigned int, unsigned short>(pUnicodes[unIndex], m_ushCodesCount));
ushCode = m_ushCodesCount;
m_vUnicodes.push_back(pUnicodes[unIndex]);
m_ushCodesCount++;
}
pEncodedString[2 * unIndex + 0] = (ushCode >> 8) & 0xFF;
pEncodedString[2 * unIndex + 1] = ushCode & 0xFF;
}
return pEncodedString;
}
void CFontCidTrueType::BeforeWrite()
{
if (m_pFontFile)
{
unsigned short* pCodeToGid;
unsigned int* pWidths;
unsigned char* pGlyphs;
unsigned int unGlyphsCount;
GetWidthsAndGids(&pCodeToGid, &pWidths, &pGlyphs, unGlyphsCount);
CStream* pStream = m_pFontFileDict->GetStream();
m_pFontFile->WriteTTF(pStream, NULL, pCodeToGid, m_ushCodesCount, pGlyphs, unGlyphsCount);
m_pFontFileDict->Add("Length1", pStream->Size());
m_pFontFileDict->SetFilter(STREAM_FILTER_FLATE_DECODE);
CArrayObject* pWArray = new CArrayObject();
m_pFont->Add("W", pWArray);
pWArray->Add(0);
CArrayObject* pWidthsArray = new CArrayObject();
pWArray->Add(pWidthsArray);
for (unsigned short ushIndex = 0; ushIndex < m_ushCodesCount; ushIndex++)
{
pWidthsArray->Add(pWidths[ushIndex]);
}
pStream = m_pCidToGidMapStream;
for (unsigned short ushCode = 0; ushCode < m_ushCodesCount; ushCode++)
{
unsigned short ushGid = pCodeToGid[ushCode];
pStream->WriteChar(((ushGid >> 8) & 0xFF));
pStream->WriteChar((ushGid & 0xFF));
}
WriteToUnicode();
}
}
void CFontCidTrueType::GetWidthsAndGids(unsigned short** ppCodeToGid, unsigned int** ppWidths, unsigned char** ppGlyphs, unsigned int& unGlyphsCount)
{
FT_Library pLibrary = NULL;
FT_Init_FreeType(&pLibrary);
FT_Face pFace = NULL;
NSFile::CFileBinary oFile;
oFile.OpenFile(m_wsFontPath, false);
DWORD lFileSize = oFile.SizeFile();
FT_Byte* pMemory = new FT_Byte[lFileSize];
if (!pMemory)
{
FT_Done_FreeType(pLibrary);
return;
}
NSFile::CFileBinary::ReadAllBytes(m_wsFontPath, &pMemory, lFileSize);
FT_New_Memory_Face(pLibrary, pMemory, lFileSize, m_unFontIndex, &pFace);
if (!pFace)
{
FT_Done_FreeType(pLibrary);
return;
}
int nSymbolic = GetSymbolicCmapIndex(pFace);
unsigned short* pCodeToGID = new unsigned short[m_ushCodesCount];
for (unsigned short ushCode = 0; ushCode < m_ushCodesCount; ushCode++)
{
unsigned int unUnicode = m_vUnicodes[ushCode];
pCodeToGID[ushCode] = GetGID(pFace, unUnicode);
if (0 == pCodeToGID[ushCode] && -1 != nSymbolic)
pCodeToGID[ushCode] = GetGID(pFace, unUnicode + 0xF000);
}
// ,
long lGlyfsCount = pFace->num_glyphs;
unsigned char *pUseGlyf = new unsigned char[lGlyfsCount];
memset((void *)pUseGlyf, 0x00, pFace->num_glyphs * sizeof(unsigned char));
//
unsigned int* pWidths = new unsigned int[m_ushCodesCount];
memset((void*)pWidths, 0x00, m_ushCodesCount * sizeof(unsigned int));
for (unsigned short ushCode = 0; ushCode < m_ushCodesCount; ushCode++)
{
unsigned short ushGID = pCodeToGID[ushCode];
if ((long)ushGID >= lGlyfsCount)
continue;
//
pUseGlyf[ushGID] = 1;
// (CompositeGlyf), (subglyfs)
if (0 == FT_Load_Glyph(pFace, ushGID, FT_LOAD_NO_SCALE | FT_LOAD_NO_RECURSE))
{
for (int nSubIndex = 0; nSubIndex < pFace->glyph->num_subglyphs; nSubIndex++)
{
FT_Int nSubGID;
FT_UInt unFlags;
FT_Int nArg1;
FT_Int nArg2;
FT_Matrix oMatrix;
FT_Get_SubGlyph_Info(pFace->glyph, nSubIndex, &nSubGID, &unFlags, &nArg1, &nArg2, &oMatrix);
pUseGlyf[nSubGID] = 1;
}
if (0 != pFace->units_per_EM)
pWidths[ushCode] = (unsigned int)pFace->glyph->metrics.horiAdvance * 1000 / pFace->units_per_EM;
else
pWidths[ushCode] = (unsigned int)pFace->glyph->metrics.horiAdvance;
}
}
// ,
std::string sFontName = m_pDocument->GetTTFontTag() + std::string(pFace->family_name);
const char* sName = sFontName.c_str();
Add("BaseFont", sName);
m_pFont->Add("BaseFont", sName);
m_pFontDescriptor->Add("FontName", sName);
FT_Done_Face(pFace);
FT_Done_FreeType(pLibrary);
*ppCodeToGid = pCodeToGID;
*ppWidths = pWidths;
*ppGlyphs = pUseGlyf;
unGlyphsCount = lGlyfsCount;
}
void CFontCidTrueType::WriteToUnicode()
{
CStream* pS = m_pToUnicodeStream;
pS->WriteStr(c_sToUnicodeHeader);
pS->WriteStr(c_sToUnicodeInfo);
pS->WriteInt(m_ushCodesCount);
pS->WriteStr(" beginbfchar\n");
for (unsigned short ushCode = 0; ushCode < m_ushCodesCount; ushCode++)
{
unsigned int unUnicode = m_vUnicodes[ushCode];
pS->WriteChar('<');
pS->WriteHex(ushCode, 4);
pS->WriteStr("> <");
if (unUnicode < 0x10000)
{
pS->WriteHex(unUnicode, 4);
}
else
{
unUnicode = unUnicode - 0x10000;
unsigned short ushLo = 0xDC00 | (unUnicode & 0x3FF);
unsigned short ushHi = 0xD800 | (unUnicode >> 10);
pS->WriteHex(ushHi, 4);
pS->WriteHex(ushLo, 4);
}
pS->WriteStr(">\n");
}
pS->WriteStr("endbfchar\n");
m_pToUnicodeStream->WriteStr(c_sToUnicodeFooter);
}
}
#ifndef _PDF_WRITER_SRC_FONTCIDTT_H
#define _PDF_WRITER_SRC_FONTCIDTT_H
#include "Font.h"
#include "Objects.h"
#include <string>
#include <map>
#include <vector>
namespace PdfWriter
{
class CXref;
class CStream;
class CFontFileTrueType;
class CDocument;
//----------------------------------------------------------------------------------------
// CFontFileBase
//----------------------------------------------------------------------------------------
class CFontCidTrueType : public CFontDict
{
public:
CFontCidTrueType(CXref* pXref, CDocument* pDocument, const std::wstring& wsFontPath, unsigned int unIndex);
~CFontCidTrueType();
unsigned char* EncodeString(unsigned int* pUnicodes, unsigned int unLen);
EFontType GetFontType()
{
return fontCIDType2;
}
private:
void BeforeWrite();
void GetWidthsAndGids(unsigned short** ppCodeToGid, unsigned int** pWidths, unsigned char** ppGlyphs, unsigned int& unGlyphsCount);
void CreateCIDFont2(CDictObject* pFont);
void WriteToUnicode();
private:
std::wstring m_wsFontPath;
unsigned int m_unFontIndex;
CFontFileTrueType* m_pFontFile;
CDictObject* m_pFontFileDict;
CStream* m_pCidToGidMapStream;
CStream* m_pToUnicodeStream;
CDictObject* m_pFont;
CDictObject* m_pFontDescriptor;
unsigned short m_ushCodesCount; //
std::map<unsigned int, unsigned short> m_mUnicodeToCode; // ->
std::vector<unsigned int> m_vUnicodes; // ->
};
}
#endif // _PDF_WRITER_SRC_FONTCIDTT_H
\ No newline at end of file
#include "FontTTWriter.h"
#include "../../DesktopEditor/common/File.h"
#define ttcfTag 0x74746366
#define cmapTag 0x636d6170
#define glyfTag 0x676c7966
#define headTag 0x68656164
#define hheaTag 0x68686561
#define hmtxTag 0x686d7478
#define locaTag 0x6c6f6361
#define nameTag 0x6e616d65
#define os2Tag 0x4f532f32
#define postTag 0x706f7374
#define cvtTag 0x63767420
#define fpgmTag 0x6670676d
#define maxpTag 0x6d617870
#define prepTag 0x70726570
namespace PdfWriter
{
struct TrueTypeTable
{
unsigned int unTag;
unsigned int unChecksum;
int nOffset;
int nOrigOffset;
int nLen;
};
struct TrueTypeCmap
{
int nPlatform;
int nEncoding;
int nOffset;
int nLen;
int nFormat;
};
struct TrueTypeLoca
{
int nIndex;
int nOrigOffset;
int nNewOffset;
int nLen;
};
static int CompareTrueTypeLocaOffset(const void *pL1, const void *pL2)
{
TrueTypeLoca *pLoca1 = (TrueTypeLoca *)pL1;
TrueTypeLoca *pLoca2 = (TrueTypeLoca *)pL2;
if (pLoca1->nOrigOffset == pLoca2->nOrigOffset)
return pLoca1->nIndex - pLoca2->nIndex;
return pLoca1->nOrigOffset - pLoca2->nOrigOffset;
}
static int CompareTrueTypeLocaIndex(const void *pL1, const void *pL2)
{
TrueTypeLoca *pLoca1 = (TrueTypeLoca *)pL1;
TrueTypeLoca *pLoca2 = (TrueTypeLoca *)pL2;
return pLoca1->nIndex - pLoca2->nIndex;
}
static int CompareTrueTypeTableTag(const void *pTab1, const void *pTab2)
{
TrueTypeTable *pTable1 = (TrueTypeTable *)pTab1;
TrueTypeTable *pTable2 = (TrueTypeTable *)pTab2;
return (int)pTable1->unTag - (int)pTable2->unTag;
}
//----------------------------------------------------------------------------------------
// CFontFileBase
//----------------------------------------------------------------------------------------
CFontFileBase::CFontFileBase(char *sFile, int nLen, bool bFreeFileData)
{
m_sFileData = m_sFile = (unsigned char *)sFile;
m_nLen = nLen;
m_bFreeFileData = bFreeFileData;
}
CFontFileBase::~CFontFileBase()
{
if (m_bFreeFileData)
free(m_sFileData);
}
char* CFontFileBase::ReadFile(const std::wstring & wsFileName, int *pnFileLen)
{
NSFile::CFileBinary oFile;
if (oFile.OpenFile(wsFileName) == false)
return NULL;
int nLen = oFile.GetFileSize();
DWORD nLenRead = 0;
char *sBuffer = (char *)malloc(nLen);
if (NULL != sBuffer)
{
if ((int)oFile.ReadFile((BYTE*)sBuffer, nLen, nLenRead) == false)
{
if (sBuffer)
free(sBuffer);
oFile.CloseFile();
return NULL;
}
oFile.CloseFile();
*pnFileLen = nLen;
}
else
{
oFile.CloseFile();
}
return sBuffer;
}
int CFontFileBase::GetS8(int nPos, bool *pbSuccess)
{
*pbSuccess = true;
if (nPos < 0 || nPos >= m_nLen)
{
*pbSuccess = false;
return 0;
}
int nRes = m_sFile[nPos];
if (nRes & 0x80)
nRes |= ~0xff;
return nRes;
}
int CFontFileBase::GetU8(int nPos, bool *pbSuccess)
{
*pbSuccess = true;
if (nPos < 0 || nPos >= m_nLen)
{
*pbSuccess = false;
return 0;
}
return m_sFile[nPos];
}
int CFontFileBase::GetS16BE(int nPos, bool *pbSuccess)
{
*pbSuccess = true;
if (nPos < 0 || nPos + 1 >= m_nLen)
{
*pbSuccess = false;
return 0;
}
int nRes = m_sFile[nPos];
nRes = (nRes << 8) + m_sFile[nPos + 1];
if (nRes & 0x8000)
nRes |= ~0xffff;
return nRes;
}
int CFontFileBase::GetU16BE(int nPos, bool *pbSuccess)
{
*pbSuccess = true;
if (nPos < 0 || nPos + 1 >= m_nLen)
{
*pbSuccess = false;
return 0;
}
int nRes = m_sFile[nPos];
nRes = (nRes << 8) + m_sFile[nPos + 1];
return nRes;
}
int CFontFileBase::GetS32BE(int nPos, bool *pbSuccess)
{
*pbSuccess = true;
if (nPos < 0 || nPos + 3 >= m_nLen)
{
*pbSuccess = false;
return 0;
}
int nRes = m_sFile[nPos];
nRes = (nRes << 8) + m_sFile[nPos + 1];
nRes = (nRes << 8) + m_sFile[nPos + 2];
nRes = (nRes << 8) + m_sFile[nPos + 3];
if (nRes & 0x80000000)
nRes |= ~0xffffffff;
return nRes;
}
unsigned int CFontFileBase::GetU32BE(int nPos, bool *pbSuccess)
{
*pbSuccess = true;
if (nPos < 0 || nPos + 3 >= m_nLen)
{
*pbSuccess = false;
return 0;
}
unsigned int nRes = m_sFile[nPos];
nRes = (nRes << 8) + m_sFile[nPos + 1];
nRes = (nRes << 8) + m_sFile[nPos + 2];
nRes = (nRes << 8) + m_sFile[nPos + 3];
return nRes;
}
unsigned int CFontFileBase::GetUVarBE(int nPos, int nSize, bool *pbSuccess)
{
*pbSuccess = true;
if (nPos < 0 || nPos + nSize > m_nLen)
{
*pbSuccess = false;
return 0;
}
unsigned int nRes = 0;
for (int nIndex = 0; nIndex < nSize; ++nIndex)
nRes = (nRes << 8) + m_sFile[nPos + nIndex];
return nRes;
}
bool CFontFileBase::CheckRegion(int nPos, int nSize)
{
return (nPos >= 0 && nPos + nSize >= nPos && nPos + nSize <= m_nLen);
}
//----------------------------------------------------------------------------------------
// CFontFileTrueType
//----------------------------------------------------------------------------------------
CFontFileTrueType::CFontFileTrueType(char *sBuffer, int nLen, bool bFreeFileData, unsigned int unFontIndex) :CFontFileBase(sBuffer, nLen, bFreeFileData)
{
m_pTables = NULL;
m_nTablesCount = 0;
m_pCMaps = NULL;
m_nCMapsCount = 0;
m_bSuccess = false;
m_unFontIndex = unFontIndex;
m_nAscent = 1000;
m_nDescent = -500;
m_nCapHeight = 800;
Parse();
}
CFontFileTrueType* CFontFileTrueType::LoadFromBuffer(char *sBuffer, int nLen, unsigned int unIndex)
{
CFontFileTrueType *pTTF = new CFontFileTrueType(sBuffer, nLen, false, unIndex);
if (!pTTF->m_bSuccess)
{
delete pTTF;
return NULL;
}
return pTTF;
}
CFontFileTrueType* CFontFileTrueType::LoadFromFile(const std::wstring& wsFileName, unsigned int unIndex)
{
char *sBuffer;
int nLen = 0;
if (!(sBuffer = CFontFileBase::ReadFile(wsFileName, &nLen)))
return NULL;
CFontFileTrueType *pTTF = new CFontFileTrueType(sBuffer, nLen, true, unIndex);
if (!pTTF->m_bSuccess)
{
delete pTTF;
return NULL;
}
return pTTF;
}
CFontFileTrueType::~CFontFileTrueType()
{
if (m_pTables)
free(m_pTables);
if (m_pCMaps)
free(m_pCMaps);
}
void CFontFileTrueType::WriteTTF(CStream* pOutputStream, char* sName, unsigned short* pCodeToGID, unsigned int unCodesCount, unsigned char* pUseGlyfs, long lGlyfsCount)
{
static char arrCMapTab[36] =
{
0, 0, // table version number
0, 1, // number of encoding tables
0, 1, // platform ID
0, 0, // encoding ID
0, 0, 0, 12, // offset of subtable
0, 4, // subtable format
0, 24, // subtable length
0, 0, // subtable version
0, 2, // segment count * 2
0, 2, // 2 * 2 ^ floor(log2(segCount))
0, 0, // floor(log2(segCount))
0, 0, // 2*segCount - 2*2^floor(log2(segCount))
(char)0xff, (char)0xff, // endCount[0]
0, 0, // reserved
0, 0, // startCount[0]
0, 0, // idDelta[0]
0, 0 // pad to a mulitple of four bytes
};
static char arrNameTab[8] =
{
0, 0, // format
0, 0, // number of name records
0, 6, // offset to start of string storage
0, 0 // pad to multiple of four bytes
};
static char arrPostTab[32] =
{
0, 1, 0, 0, // format
0, 0, 0, 0, // italic angle
0, 0, // underline position
0, 0, // underline thickness
0, 0, 0, 0, // fixed pitch
0, 0, 0, 0, // min Type 42 memory
0, 0, 0, 0, // max Type 42 memory
0, 0, 0, 0, // min Type 1 memory
0, 0, 0, 0 // max Type 1 memory
};
static char arrOS2Tab[86] =
{
0, 1, // version
0, 1, // xAvgCharWidth
0, 0, // usWeightClass
0, 0, // usWidthClass
0, 0, // fsType
0, 0, // ySubscriptXSize
0, 0, // ySubscriptYSize
0, 0, // ySubscriptXOffset
0, 0, // ySubscriptYOffset
0, 0, // ySuperscriptXSize
0, 0, // ySuperscriptYSize
0, 0, // ySuperscriptXOffset
0, 0, // ySuperscriptYOffset
0, 0, // yStrikeoutSize
0, 0, // yStrikeoutPosition
0, 0, // sFamilyClass
0, 0, 0, 0, 0, // panose
0, 0, 0, 0, 0,
0, 0, 0, 0, // ulUnicodeRange1
0, 0, 0, 0, // ulUnicodeRange2
0, 0, 0, 0, // ulUnicodeRange3
0, 0, 0, 0, // ulUnicodeRange4
0, 0, 0, 0, // achVendID
0, 0, // fsSelection
0, 0, // usFirstCharIndex
0, 0, // usLastCharIndex
0, 0, // sTypoAscender
0, 0, // sTypoDescender
0, 0, // sTypoLineGap
0, 0, // usWinAscent
0, 0, // usWinDescent
0, 0, 0, 0, // ulCodePageRange1
0, 0, 0, 0 // ulCodePageRange2
};
bool badCmapLen, abbrevHMTX;
int nZeroLengthTables;
int nHMetrics, nAdvWidth, nLeftSideBearing;
TrueTypeTable *pNewTables;
char *arrNewNameTable, *arrNewCmapTable, *arrNewHHEATable, *arrNewHMTXTable;
int nNewTables, nCmapIndex, nCmapLen, nGlyphLen, nNewNameLen, nNewCmapLen, nNext;
int nNewHHEALen, nNewHMTXLen;
unsigned int nLocaChecksum, nGlyphChecksum, nFileChecksum;
char *arrTableDir;
char arrLocaBuf[4], arrChecksumBuf[4];
unsigned int t;
int nPos = 0, i, j, k, n;
// OpenType
if (m_bOpenTypeCFF)
{
WriteOTF(pOutputStream, sName, pCodeToGID);
return;
}
//
bool bMissingCmap = (nCmapIndex = SeekTable("cmap")) < 0;
bool bMissingName = SeekTable("name") < 0;
bool bMissingPost = SeekTable("post") < 0;
bool bMissingOS2 = SeekTable("OS/2") < 0;
TrueTypeLoca *pLocaTable = (TrueTypeLoca *)malloc((m_nGlyphs + 1) * sizeof(TrueTypeLoca));
bool bUnsortedLoca = false;
i = SeekTable("loca");
nPos = m_pTables[i].nOffset;
bool bSuccess = true;
for (i = 0; i <= m_nGlyphs; ++i)
{
if (m_nLocaFormat)
{
pLocaTable[i].nOrigOffset = (int)GetU32BE(nPos + i * 4, &bSuccess);
}
else
{
pLocaTable[i].nOrigOffset = 2 * GetU16BE(nPos + i * 2, &bSuccess);
}
if (i > 0 && pLocaTable[i].nOrigOffset < pLocaTable[i - 1].nOrigOffset)
{
bUnsortedLoca = true;
}
// 12 (nContours,
// xMin, yMin, xMax, yMax, instructionLength - 2 );
if (i > 0 && pLocaTable[i].nOrigOffset - pLocaTable[i - 1].nOrigOffset > 0 && pLocaTable[i].nOrigOffset - pLocaTable[i - 1].nOrigOffset < 12)
{
pLocaTable[i - 1].nOrigOffset = pLocaTable[i].nOrigOffset;
bUnsortedLoca = true;
}
pLocaTable[i].nIndex = i;
}
//
nZeroLengthTables = 0;
for (i = 0; i < m_nTablesCount; ++i)
{
if (m_pTables[i].nLen == 0)
++nZeroLengthTables;
}
// Cmap
badCmapLen = false;
nCmapLen = 0;
if (!bMissingCmap)
{
nCmapLen = m_pCMaps[0].nOffset + m_pCMaps[0].nLen;
for (i = 1; i < m_nCMapsCount; ++i)
{
if (m_pCMaps[i].nOffset + m_pCMaps[i].nLen > nCmapLen)
{
nCmapLen = m_pCMaps[i].nOffset + m_pCMaps[i].nLen;
}
}
nCmapLen -= m_pTables[nCmapIndex].nOffset;
if (nCmapLen > m_pTables[nCmapIndex].nLen)
{
badCmapLen = true;
}
}
// , 'hmtx' .
i = SeekTable("hhea");
nHMetrics = GetU16BE(m_pTables[i].nOffset + 34, &bSuccess);
abbrevHMTX = nHMetrics < m_nGlyphs;
// , 'cmap' 'name', TTF
if (!bMissingCmap && !bMissingName && !bMissingPost && !bMissingOS2 && !bUnsortedLoca && !badCmapLen && !abbrevHMTX && nZeroLengthTables == 0 && !sName && !pCodeToGID)
{
pOutputStream->Write((BYTE *)m_sFile, m_nLen);
free(pLocaTable);
return;
}
// 'loca':
// 'loca'; 'loca'
// , cmpTrueTypeLocaOffset
// ,
// ( ,
// , )
nGlyphLen = 0;
if (bUnsortedLoca || pUseGlyfs)
{
qsort(pLocaTable, m_nGlyphs + 1, sizeof(TrueTypeLoca), &CompareTrueTypeLocaOffset);
for (i = 0; i < m_nGlyphs; ++i)
{
pLocaTable[i].nLen = pLocaTable[i + 1].nOrigOffset - pLocaTable[i].nOrigOffset;
}
pLocaTable[m_nGlyphs].nLen = 0;
qsort(pLocaTable, m_nGlyphs + 1, sizeof(TrueTypeLoca), &CompareTrueTypeLocaIndex);
nPos = 0;
for (i = 0; i <= m_nGlyphs; ++i)
{
// TO DO: ,
if (pUseGlyfs && lGlyfsCount == m_nGlyphs)
{
pLocaTable[i].nNewOffset = nPos;
int nCurGlyfLen = pLocaTable[i].nLen;
pLocaTable[i].nLen = 0;
if (1 == pUseGlyfs[i])
{
pLocaTable[i].nLen = nCurGlyfLen;
nPos += pLocaTable[i].nLen;
if (nPos & 3)
{
nPos += 4 - (nPos & 3);
}
}
}
else
{
pLocaTable[i].nNewOffset = nPos;
nPos += pLocaTable[i].nLen;
if (nPos & 3)
{
nPos += 4 - (nPos & 3);
}
}
}
nGlyphLen = nPos;
}
// 'loca' 'glyf'
nLocaChecksum = nGlyphChecksum = 0;
if (bUnsortedLoca || pUseGlyfs)
{
if (m_nLocaFormat)
{
for (j = 0; j <= m_nGlyphs; ++j)
{
nLocaChecksum += pLocaTable[j].nNewOffset;
}
}
else
{
for (j = 0; j <= m_nGlyphs; j += 2)
{
nLocaChecksum += pLocaTable[j].nNewOffset << 16;
if (j + 1 <= m_nGlyphs)
{
nLocaChecksum += pLocaTable[j + 1].nNewOffset;
}
}
}
nPos = m_pTables[SeekTable("glyf")].nOffset;
for (j = 0; j < m_nGlyphs; ++j)
{
n = pLocaTable[j].nLen;
if (n > 0)
{
k = pLocaTable[j].nOrigOffset;
if (CheckRegion(nPos + k, n))
{
nGlyphChecksum += ComputeTableChecksum(m_sFile + nPos + k, n);
}
}
}
}
// 'name'
if (sName)
{
n = strlen(sName);
nNewNameLen = (6 + 4 * 12 + 2 * (3 * n + 7) + 3) & ~3;
arrNewNameTable = (char *)malloc(nNewNameLen);
memset(arrNewNameTable, 0, nNewNameLen);
arrNewNameTable[0] = 0; // format selector
arrNewNameTable[1] = 0;
arrNewNameTable[2] = 0; // number of name records
arrNewNameTable[3] = 4;
arrNewNameTable[4] = 0; // offset to start of string storage
arrNewNameTable[5] = 6 + 4 * 12;
nNext = 0;
for (i = 0; i < 4; ++i)
{
arrNewNameTable[6 + i * 12 + 0] = 0; // platform ID = Microsoft
arrNewNameTable[6 + i * 12 + 1] = 3;
arrNewNameTable[6 + i * 12 + 2] = 0; // encoding ID = Unicode
arrNewNameTable[6 + i * 12 + 3] = 1;
arrNewNameTable[6 + i * 12 + 4] = 0x04; // language ID = American English
arrNewNameTable[6 + i * 12 + 5] = 0x09;
arrNewNameTable[6 + i * 12 + 6] = 0; // name ID
arrNewNameTable[6 + i * 12 + 7] = i + 1;
arrNewNameTable[6 + i * 12 + 8] = i + 1 == 2 ? 0 : ((2 * n) >> 8); // string length
arrNewNameTable[6 + i * 12 + 9] = i + 1 == 2 ? 14 : ((2 * n) & 0xff);
arrNewNameTable[6 + i * 12 + 10] = nNext >> 8; // string offset
arrNewNameTable[6 + i * 12 + 11] = nNext & 0xff;
if (i + 1 == 2)
{
memcpy(arrNewNameTable + 6 + 4 * 12 + nNext, "\0R\0e\0g\0u\0l\0a\0r", 14);
nNext += 14;
}
else
{
for (j = 0; j < n; ++j)
{
arrNewNameTable[6 + 4 * 12 + nNext + 2 * j] = 0;
arrNewNameTable[6 + 4 * 12 + nNext + 2 * j + 1] = sName[j];
}
nNext += 2 * n;
}
}
}
else
{
nNewNameLen = 0;
arrNewNameTable = NULL;
}
// 'cmap'
if (pCodeToGID)
{
unsigned short ushSubTableLen = 10 + unCodesCount * 2;
nNewCmapLen = 12 + ushSubTableLen;
arrNewCmapTable = (char *)malloc(nNewCmapLen);
arrNewCmapTable[0] = 0; // table version number = 0
arrNewCmapTable[1] = 0; //
arrNewCmapTable[2] = 0; // number of encoding tables = 1
arrNewCmapTable[3] = 1; //
arrNewCmapTable[4] = 0; // platform ID = 1 (MacOS) //
arrNewCmapTable[5] = 1; // // , , Adobe
arrNewCmapTable[6] = 0; // encoding ID = 0 // Acrobat .
arrNewCmapTable[7] = 0; // //
arrNewCmapTable[8] = 0; // offset of subtable
arrNewCmapTable[9] = 0; //
arrNewCmapTable[10] = 0; //
arrNewCmapTable[11] = 12; //
arrNewCmapTable[12] = 0; // subtable format = 6
arrNewCmapTable[13] = 6; //
arrNewCmapTable[14] = (ushSubTableLen >> 8) & 0xFF; // subtable length
arrNewCmapTable[15] = ushSubTableLen & 0xFF; //
arrNewCmapTable[16] = 0; // subtable version = 0
arrNewCmapTable[17] = 0; //
arrNewCmapTable[18] = 0; // firstCode
arrNewCmapTable[19] = 0; //
arrNewCmapTable[20] = 0x01; // entryCount
arrNewCmapTable[21] = 0x00; //
for (i = 0; i < unCodesCount; ++i)
{
arrNewCmapTable[22 + 2 * i] = pCodeToGID[i] >> 8;
arrNewCmapTable[22 + 2 * i + 1] = pCodeToGID[i] & 0xff;
}
}
else
{
nNewCmapLen = 0;
arrNewCmapTable = NULL;
}
// 'hmtx' 'hhea'
if (abbrevHMTX)
{
i = SeekTable("hhea");
nPos = m_pTables[i].nOffset;
nNewHHEALen = 36;
arrNewHHEATable = (char *)malloc(nNewHHEALen);
for (i = 0; i < nNewHHEALen; ++i)
{
arrNewHHEATable[i] = GetU8(nPos++, &bSuccess);
}
arrNewHHEATable[34] = m_nGlyphs >> 8;
arrNewHHEATable[35] = m_nGlyphs & 0xff;
i = SeekTable("hmtx");
nPos = m_pTables[i].nOffset;
nNewHMTXLen = 4 * m_nGlyphs;
arrNewHMTXTable = (char *)malloc(nNewHMTXLen);
nAdvWidth = 0;
for (i = 0; i < nHMetrics; ++i)
{
nAdvWidth = GetU16BE(nPos, &bSuccess);
nLeftSideBearing = GetU16BE(nPos + 2, &bSuccess);
nPos += 4;
arrNewHMTXTable[4 * i] = nAdvWidth >> 8;
arrNewHMTXTable[4 * i + 1] = nAdvWidth & 0xff;
arrNewHMTXTable[4 * i + 2] = nLeftSideBearing >> 8;
arrNewHMTXTable[4 * i + 3] = nLeftSideBearing & 0xff;
}
for (; i < m_nGlyphs; ++i)
{
nLeftSideBearing = GetU16BE(nPos, &bSuccess);
nPos += 2;
arrNewHMTXTable[4 * i] = nAdvWidth >> 8;
arrNewHMTXTable[4 * i + 1] = nAdvWidth & 0xff;
arrNewHMTXTable[4 * i + 2] = nLeftSideBearing >> 8;
arrNewHMTXTable[4 * i + 3] = nLeftSideBearing & 0xff;
}
}
else
{
arrNewHHEATable = arrNewHMTXTable = NULL;
nNewHHEALen = nNewHMTXLen = 0;
}
// :
// -
// - 'cmap',
// -
// -
// - , 4-
// -
nNewTables = m_nTablesCount - nZeroLengthTables + (bMissingCmap ? 1 : 0) + (bMissingName ? 1 : 0) + (bMissingPost ? 1 : 0) + (bMissingOS2 ? 1 : 0);
pNewTables = (TrueTypeTable *)malloc(nNewTables * sizeof(TrueTypeTable));
j = 0;
for (i = 0; i < m_nTablesCount; ++i)
{
if (m_pTables[i].nLen > 0)
{
pNewTables[j] = m_pTables[i];
pNewTables[j].nOrigOffset = m_pTables[i].nOffset;
if (CheckRegion(m_pTables[i].nOffset, pNewTables[i].nLen))
{
pNewTables[j].unChecksum = ComputeTableChecksum(m_sFile + m_pTables[i].nOffset, m_pTables[i].nLen);
if (m_pTables[i].unTag == headTag)
{
// don't include the file checksum
pNewTables[j].unChecksum -= GetU32BE(m_pTables[i].nOffset + 8, &bSuccess);
}
}
if (pNewTables[j].unTag == cmapTag && pCodeToGID)
{
pNewTables[j].nLen = nNewCmapLen;
pNewTables[j].unChecksum = ComputeTableChecksum((unsigned char *)arrNewCmapTable, nNewCmapLen);
}
else if (pNewTables[j].unTag == cmapTag && badCmapLen)
{
pNewTables[j].nLen = nCmapLen;
}
else if (pNewTables[j].unTag == locaTag && (bUnsortedLoca || pCodeToGID))
{
pNewTables[j].nLen = (m_nGlyphs + 1) * (m_nLocaFormat ? 4 : 2);
pNewTables[j].unChecksum = nLocaChecksum;
}
else if (pNewTables[j].unTag == glyfTag && (bUnsortedLoca || pCodeToGID))
{
pNewTables[j].nLen = nGlyphLen;
pNewTables[j].unChecksum = nGlyphChecksum;
}
else if (pNewTables[j].unTag == nameTag && sName)
{
pNewTables[j].nLen = nNewNameLen;
pNewTables[j].unChecksum = ComputeTableChecksum((unsigned char *)arrNewNameTable, nNewNameLen);
}
else if (pNewTables[j].unTag == hheaTag && abbrevHMTX)
{
pNewTables[j].nLen = nNewHHEALen;
pNewTables[j].unChecksum = ComputeTableChecksum((unsigned char *)arrNewHHEATable, nNewHHEALen);
}
else if (pNewTables[j].unTag == hmtxTag && abbrevHMTX)
{
pNewTables[j].nLen = nNewHMTXLen;
pNewTables[j].unChecksum = ComputeTableChecksum((unsigned char *)arrNewHMTXTable, nNewHMTXLen);
}
++j;
}
}
if (bMissingCmap)
{
pNewTables[j].unTag = cmapTag;
if (pCodeToGID)
{
pNewTables[j].unChecksum = ComputeTableChecksum((unsigned char *)arrNewCmapTable, nNewCmapLen);
pNewTables[j].nLen = nNewCmapLen;
}
else
{
pNewTables[j].unChecksum = ComputeTableChecksum((unsigned char *)arrCMapTab, sizeof(arrCMapTab));
pNewTables[j].nLen = sizeof(arrCMapTab);
}
++j;
}
if (bMissingName)
{
pNewTables[j].unTag = nameTag;
if (sName)
{
pNewTables[j].unChecksum = ComputeTableChecksum((unsigned char *)arrNewNameTable, nNewNameLen);
pNewTables[j].nLen = nNewNameLen;
}
else
{
pNewTables[j].unChecksum = ComputeTableChecksum((unsigned char *)arrNameTab, sizeof(arrNameTab));
pNewTables[j].nLen = sizeof(arrNameTab);
}
++j;
}
if (bMissingPost)
{
pNewTables[j].unTag = postTag;
pNewTables[j].unChecksum = ComputeTableChecksum((unsigned char *)arrPostTab, sizeof(arrPostTab));
pNewTables[j].nLen = sizeof(arrPostTab);
++j;
}
if (bMissingOS2)
{
pNewTables[j].unTag = os2Tag;
pNewTables[j].unChecksum = ComputeTableChecksum((unsigned char *)arrOS2Tab, sizeof(arrOS2Tab));
pNewTables[j].nLen = sizeof(arrOS2Tab);
++j;
}
qsort(pNewTables, nNewTables, sizeof(TrueTypeTable), CompareTrueTypeTableTag);
unsigned char *pUseTable = new unsigned char[nNewTables];
if (!pUseTable)
{
free(arrNewHMTXTable);
free(arrNewHHEATable);
free(arrNewCmapTable);
free(arrNewNameTable);
free(pNewTables);
free(pLocaTable);
return;
}
::memset(pUseTable, 0, nNewTables * sizeof(unsigned char));
int nNewReqTables = 0;
for (int nIndex = 0; nIndex < nNewTables; nIndex++)
{
if (pNewTables[nIndex].unTag == cmapTag || pNewTables[nIndex].unTag == glyfTag ||
pNewTables[nIndex].unTag == headTag || pNewTables[nIndex].unTag == hheaTag ||
pNewTables[nIndex].unTag == hmtxTag || pNewTables[nIndex].unTag == locaTag ||
pNewTables[nIndex].unTag == nameTag || pNewTables[nIndex].unTag == os2Tag ||
pNewTables[nIndex].unTag == postTag || pNewTables[nIndex].unTag == cvtTag ||
pNewTables[nIndex].unTag == fpgmTag || pNewTables[nIndex].unTag == maxpTag ||
pNewTables[nIndex].unTag == prepTag)
{
pUseTable[nIndex] = 1;
nNewReqTables++;
}
}
nPos = 12 + nNewReqTables * 16;
for (i = 0; i < nNewTables; ++i)
{
if (1 == pUseTable[i])
{
pNewTables[i].nOffset = nPos;
nPos += pNewTables[i].nLen;
if (nPos & 3)
{
nPos += 4 - (nPos & 3);
}
}
}
//
arrTableDir = (char *)malloc(12 + nNewReqTables * 16);
arrTableDir[0] = 0x00; // sfnt version
arrTableDir[1] = 0x01; //
arrTableDir[2] = 0x00; //
arrTableDir[3] = 0x00; //
arrTableDir[4] = (char)((nNewReqTables >> 8) & 0xff); // numTables
arrTableDir[5] = (char)(nNewReqTables & 0xff);
for (i = -1, t = (unsigned int)nNewReqTables; t; ++i, t >>= 1);
t = 1 << (4 + i);
arrTableDir[6] = (char)((t >> 8) & 0xff); // searchRange
arrTableDir[7] = (char)(t & 0xff);
arrTableDir[8] = (char)((i >> 8) & 0xff); // entrySelector
arrTableDir[9] = (char)(i & 0xff);
t = nNewReqTables * 16 - t;
arrTableDir[10] = (char)((t >> 8) & 0xff); // rangeShift
arrTableDir[11] = (char)(t & 0xff);
nPos = 12;
for (i = 0; i < nNewTables; ++i)
{
if (1 == pUseTable[i])
{
arrTableDir[nPos] = (char)(pNewTables[i].unTag >> 24);
arrTableDir[nPos + 1] = (char)(pNewTables[i].unTag >> 16);
arrTableDir[nPos + 2] = (char)(pNewTables[i].unTag >> 8);
arrTableDir[nPos + 3] = (char)pNewTables[i].unTag;
arrTableDir[nPos + 4] = (char)(pNewTables[i].unChecksum >> 24);
arrTableDir[nPos + 5] = (char)(pNewTables[i].unChecksum >> 16);
arrTableDir[nPos + 6] = (char)(pNewTables[i].unChecksum >> 8);
arrTableDir[nPos + 7] = (char)pNewTables[i].unChecksum;
arrTableDir[nPos + 8] = (char)(pNewTables[i].nOffset >> 24);
arrTableDir[nPos + 9] = (char)(pNewTables[i].nOffset >> 16);
arrTableDir[nPos + 10] = (char)(pNewTables[i].nOffset >> 8);
arrTableDir[nPos + 11] = (char)pNewTables[i].nOffset;
arrTableDir[nPos + 12] = (char)(pNewTables[i].nLen >> 24);
arrTableDir[nPos + 13] = (char)(pNewTables[i].nLen >> 16);
arrTableDir[nPos + 14] = (char)(pNewTables[i].nLen >> 8);
arrTableDir[nPos + 15] = (char)pNewTables[i].nLen;
nPos += 16;
}
}
pOutputStream->Write((BYTE*)arrTableDir, 12 + nNewReqTables * 16);
//
nFileChecksum = ComputeTableChecksum((unsigned char *)arrTableDir, 12 + nNewReqTables * 16);
for (i = 0; i < nNewTables; ++i)
{
if (1 == pUseTable[i])
{
nFileChecksum += pNewTables[i].unChecksum;
}
}
nFileChecksum = 0xb1b0afba - nFileChecksum;
//
for (i = 0; i < nNewTables; ++i)
{
if (1 == pUseTable[i])
{
if (pNewTables[i].unTag == headTag)
{
if (CheckRegion(pNewTables[i].nOrigOffset, pNewTables[i].nLen))
{
pOutputStream->Write((BYTE*)m_sFile + pNewTables[i].nOrigOffset, 8);
arrChecksumBuf[0] = nFileChecksum >> 24;
arrChecksumBuf[1] = nFileChecksum >> 16;
arrChecksumBuf[2] = nFileChecksum >> 8;
arrChecksumBuf[3] = nFileChecksum;
pOutputStream->Write((BYTE*)arrChecksumBuf, 4);
pOutputStream->Write((BYTE*)((char *)m_sFile + pNewTables[i].nOrigOffset + 12), pNewTables[i].nLen - 12);
}
else
{
for (j = 0; j < pNewTables[i].nLen; ++j)
{
pOutputStream->Write((BYTE*)"\0", 1);
}
}
}
else if (pNewTables[i].unTag == cmapTag && pCodeToGID)
pOutputStream->Write((BYTE*)arrNewCmapTable, pNewTables[i].nLen);
else if (pNewTables[i].unTag == cmapTag && bMissingCmap)
pOutputStream->Write((BYTE*)arrCMapTab, pNewTables[i].nLen);
else if (pNewTables[i].unTag == nameTag && sName)
pOutputStream->Write((BYTE*)arrNewNameTable, pNewTables[i].nLen);
else if (pNewTables[i].unTag == nameTag && bMissingName)
pOutputStream->Write((BYTE*)arrNameTab, pNewTables[i].nLen);
else if (pNewTables[i].unTag == postTag && bMissingPost)
pOutputStream->Write((BYTE*)arrPostTab, pNewTables[i].nLen);
else if (pNewTables[i].unTag == os2Tag && bMissingOS2)
pOutputStream->Write((BYTE*)arrOS2Tab, pNewTables[i].nLen);
else if (pNewTables[i].unTag == hheaTag && abbrevHMTX)
pOutputStream->Write((BYTE*)arrNewHHEATable, pNewTables[i].nLen);
else if (pNewTables[i].unTag == hmtxTag && abbrevHMTX)
pOutputStream->Write((BYTE*)arrNewHMTXTable, pNewTables[i].nLen);
else if (pNewTables[i].unTag == locaTag && (bUnsortedLoca || pCodeToGID))
{
for (j = 0; j <= m_nGlyphs; ++j)
{
if (m_nLocaFormat)
{
arrLocaBuf[0] = (char)(pLocaTable[j].nNewOffset >> 24);
arrLocaBuf[1] = (char)(pLocaTable[j].nNewOffset >> 16);
arrLocaBuf[2] = (char)(pLocaTable[j].nNewOffset >> 8);
arrLocaBuf[3] = (char)pLocaTable[j].nNewOffset;
pOutputStream->Write((BYTE*)arrLocaBuf, 4);
}
else
{
arrLocaBuf[0] = (char)(pLocaTable[j].nNewOffset >> 9);
arrLocaBuf[1] = (char)(pLocaTable[j].nNewOffset >> 1);
pOutputStream->Write((BYTE*)arrLocaBuf, 2);
}
}
}
else if (pNewTables[i].unTag == glyfTag && (bUnsortedLoca || pCodeToGID))
{
nPos = m_pTables[SeekTable("glyf")].nOffset;
for (j = 0; j < m_nGlyphs; ++j)
{
n = pLocaTable[j].nLen;
if (n > 0)
{
k = pLocaTable[j].nOrigOffset;
if (CheckRegion(nPos + k, n))
{
pOutputStream->Write((BYTE*)((char *)m_sFile + nPos + k), n);
}
else
{
for (k = 0; k < n; ++k)
{
pOutputStream->Write((BYTE*)"\0", 1);
}
}
if ((k = pLocaTable[j].nLen & 3))
{
pOutputStream->Write((BYTE*)"\0\0\0\0", 4 - k);
}
}
}
}
else
{
if (CheckRegion(pNewTables[i].nOrigOffset, pNewTables[i].nLen))
{
pOutputStream->Write((BYTE*)((char *)m_sFile + pNewTables[i].nOrigOffset), pNewTables[i].nLen);
}
else
{
for (j = 0; j < pNewTables[i].nLen; ++j)
{
pOutputStream->Write((BYTE*)"\0", 1);
}
}
}
if (pNewTables[i].nLen & 3)
{
pOutputStream->Write((BYTE*)"\0\0\0", 4 - (pNewTables[i].nLen & 3));
}
}
}
delete[]pUseTable;
free(arrNewHMTXTable);
free(arrNewHHEATable);
free(arrNewCmapTable);
free(arrNewNameTable);
free(arrTableDir);
free(pNewTables);
free(pLocaTable);
}
void CFontFileTrueType::WriteOTF(CStream* pOutputStream, char* sName, unsigned short* pCodeToGID)
{
if (!m_bOpenTypeCFF || SeekTable("CFF ") < 0)
return;
// Open Type Font ,
pOutputStream->Write((BYTE*)m_sFile, m_nLen);
return;
}
int CFontFileTrueType::GetAscent()
{
return m_nAscent;
}
int CFontFileTrueType::GetDescent()
{
return m_nDescent;
}
int CFontFileTrueType::GetCapHeight()
{
return m_nCapHeight;
}
int* CFontFileTrueType::GetBBox()
{
return m_arrBBox;
}
int CFontFileTrueType::GetWeight()
{
return m_nWeight;
}
unsigned int CFontFileTrueType::ComputeTableChecksum(unsigned char *sData, int nLength)
{
unsigned int nWord = 0;
unsigned int nChecksum = 0;
for (int nIndex = 0; nIndex + 3 < nLength; nIndex += 4)
{
nWord = ((sData[nIndex] & 0xff) << 24) + ((sData[nIndex + 1] & 0xff) << 16) + ((sData[nIndex + 2] & 0xff) << 8) + (sData[nIndex + 3] & 0xff);
nChecksum += nWord;
}
if (nLength & 3)
{
nWord = 0;
int nTemp = nLength & ~3;
switch (nLength & 3)
{
case 3:
nWord |= (sData[nTemp + 2] & 0xff) << 8;
case 2:
nWord |= (sData[nTemp + 1] & 0xff) << 16;
case 1:
nWord |= (sData[nTemp] & 0xff) << 24;
break;
}
nChecksum += nWord;
}
return nChecksum;
}
void CFontFileTrueType::Parse()
{
int nPos = 0, nIndex = 0, nJ;
m_bSuccess = true;
// (TTC)
unsigned int unTopTag = GetU32BE(0, &m_bSuccess);
if (!m_bSuccess)
return;
if (unTopTag == ttcfTag)
{
unsigned int unVersion = GetU32BE(4, &m_bSuccess);
unsigned int unNumFonts = GetU32BE(8, &m_bSuccess);
unsigned int unFontIndex = m_unFontIndex >= unNumFonts ? 0 : m_unFontIndex;
nPos = GetU32BE(12 + 4 * unFontIndex, &m_bSuccess);
if (!m_bSuccess)
return;
}
else
nPos = 0;
// sfnt
int nSfntVersion = GetU32BE(nPos, &m_bSuccess);
if (!m_bSuccess)
return;
// . CCF ?
m_bOpenTypeCFF = (nSfntVersion == 0x4f54544f); // 'OTTO'
m_nTablesCount = GetU16BE(nPos + 4, &m_bSuccess);
if (!m_bSuccess)
return;
m_pTables = (TrueTypeTable *)malloc(m_nTablesCount * sizeof(TrueTypeTable));
nPos += 12;
for (nIndex = 0; nIndex < m_nTablesCount; ++nIndex)
{
m_pTables[nIndex].unTag = GetU32BE(nPos, &m_bSuccess);
m_pTables[nIndex].unChecksum = GetU32BE(nPos + 4, &m_bSuccess);
m_pTables[nIndex].nOffset = (int)GetU32BE(nPos + 8, &m_bSuccess);
m_pTables[nIndex].nLen = (int)GetU32BE(nPos + 12, &m_bSuccess);
if (m_pTables[nIndex].nOffset + m_pTables[nIndex].nLen < m_pTables[nIndex].nOffset || m_pTables[nIndex].nOffset + m_pTables[nIndex].nLen > m_nLen)
{
m_bSuccess = false;
}
nPos += 16;
}
if (!m_bSuccess)
return;
// TrueType Type 42
if (SeekTable("head") < 0 || SeekTable("hhea") < 0 || SeekTable("maxp") < 0 || SeekTable("hmtx") < 0 || (!m_bOpenTypeCFF && SeekTable("loca") < 0) || (!m_bOpenTypeCFF && SeekTable("glyf") < 0) || (m_bOpenTypeCFF && SeekTable("CFF ") < 0))
{
m_bSuccess = false;
return;
}
// CMaps
if ((nIndex = SeekTable("cmap")) >= 0)
{
nPos = m_pTables[nIndex].nOffset + 2;
m_nCMapsCount = GetU16BE(nPos, &m_bSuccess);
nPos += 2;
if (!m_bSuccess)
return;
m_pCMaps = (TrueTypeCmap *)malloc(m_nCMapsCount * sizeof(TrueTypeCmap));
for (nJ = 0; nJ < m_nCMapsCount; ++nJ)
{
m_pCMaps[nJ].nPlatform = GetU16BE(nPos, &m_bSuccess);
m_pCMaps[nJ].nEncoding = GetU16BE(nPos + 2, &m_bSuccess);
unsigned int nTemp = GetU32BE(nPos + 4, &m_bSuccess);
m_pCMaps[nJ].nOffset = m_pTables[nIndex].nOffset + GetU32BE(nPos + 4, &m_bSuccess);
nPos += 8;
m_pCMaps[nJ].nFormat = GetU16BE(m_pCMaps[nJ].nOffset, &m_bSuccess);
m_pCMaps[nJ].nLen = GetU16BE(m_pCMaps[nJ].nOffset + 2, &m_bSuccess);
}
if (!m_bSuccess)
return;
}
else
m_nCMapsCount = 0;
nIndex = SeekTable("maxp");
m_nGlyphs = GetU16BE(m_pTables[nIndex].nOffset + 4, &m_bSuccess);
if (!m_bSuccess)
return;
nIndex = SeekTable("head");
m_arrBBox[0] = GetS16BE(m_pTables[nIndex].nOffset + 36, &m_bSuccess);
m_arrBBox[1] = GetS16BE(m_pTables[nIndex].nOffset + 38, &m_bSuccess);
m_arrBBox[2] = GetS16BE(m_pTables[nIndex].nOffset + 40, &m_bSuccess);
m_arrBBox[3] = GetS16BE(m_pTables[nIndex].nOffset + 42, &m_bSuccess);
m_nLocaFormat = GetS16BE(m_pTables[nIndex].nOffset + 50, &m_bSuccess);
if (!m_bSuccess)
return;
// loca
if (!m_bOpenTypeCFF)
{
nIndex = SeekTable("loca");
if (m_pTables[nIndex].nLen < 0)
{
m_bSuccess = false;
return;
}
if (m_pTables[nIndex].nLen < (m_nGlyphs + 1) * (m_nLocaFormat ? 4 : 2))
{
m_nGlyphs = m_pTables[nIndex].nLen / (m_nLocaFormat ? 4 : 2) - 1;
}
for (nJ = 0; nJ <= m_nGlyphs; ++nJ)
{
if (m_nLocaFormat)
nPos = (int)GetU32BE(m_pTables[nIndex].nOffset + nJ * 4, &m_bSuccess);
else
nPos = GetU16BE(m_pTables[nIndex].nOffset + nJ * 2, &m_bSuccess);
if (nPos < 0 || nPos > m_nLen)
m_bSuccess = false;
}
if (!m_bSuccess)
return;
}
ReadOS2();
}
int CFontFileTrueType::SeekTable(char *sTag)
{
unsigned int nTagIndex = ((sTag[0] & 0xff) << 24) | ((sTag[1] & 0xff) << 16) | ((sTag[2] & 0xff) << 8) | (sTag[3] & 0xff);
for (int nIndex = 0; nIndex < m_nTablesCount; ++nIndex)
{
if (m_pTables[nIndex].unTag == nTagIndex)
{
return nIndex;
}
}
return -1;
}
void CFontFileTrueType::ReadOS2()
{
int nIndex = SeekTable("OS/2");
if (-1 != nIndex && m_pTables[nIndex].nLen > 0)
{
unsigned int unOffset = m_pTables[nIndex].nOffset;
m_nWeight = GetS16BE(unOffset + 4, &m_bSuccess);
m_nAscent = GetS16BE(unOffset + 68, &m_bSuccess);
m_nDescent = GetS16BE(unOffset + 70, &m_bSuccess);
m_nCapHeight = GetS16BE(unOffset + 88, &m_bSuccess);
}
}
}
\ No newline at end of file
#ifndef _PDF_WRITER_SRC_TTWRITER_H
#define _PDF_WRITER_SRC_TTWRITER_H
#include "Streams.h"
namespace PdfWriter
{
struct TrueTypeTable;
struct TrueTypeCmap;
//----------------------------------------------------------------------------------------
// CFontFileBase
//----------------------------------------------------------------------------------------
class CFontFileBase
{
public:
virtual ~CFontFileBase();
protected:
CFontFileBase(char *sFile, int nLen, bool bFreeFileData);
static char *ReadFile(const std::wstring & wsFileName, int *pnFileLen);
int GetS8(int nPos, bool *pbSuccess);
int GetU8(int nPos, bool *pbSuccess);
int GetS16BE(int nPos, bool *pbSuccess);
int GetU16BE(int nPos, bool *pbSuccess);
int GetS32BE(int nPos, bool *pbSuccess);
unsigned int GetU32BE(int nPos, bool *pbSuccess);
unsigned int GetUVarBE(int nPos, int nSize, bool *pbSuccess);
bool CheckRegion(int nPos, int nSize);
protected:
unsigned char *m_sFileData;
unsigned char *m_sFile;
int m_nLen;
bool m_bFreeFileData;
};
//----------------------------------------------------------------------------------------
// CFontFileTrueType
//----------------------------------------------------------------------------------------
class CFontFileTrueType : public CFontFileBase
{
public:
static CFontFileTrueType *LoadFromBuffer(char* sBuffer, int nLen, unsigned int unIndex);
static CFontFileTrueType *LoadFromFile(const std::wstring& wsFileName, unsigned int unIndex);
~CFontFileTrueType();
// Записываем TrueTypeFont File, заполняя недостающие таблицы и корректируя
// различные ошибки. Если задан парметр <sName>, в шрифте переписываем таблицу
// 'name'. Если задан парамтре <pCodeToGID>, тогда в шрифте переписываем
// таблицу 'cmap'.
void WriteTTF(CStream* pOutputStream, char *sName = NULL, unsigned short *pCodeToGID = NULL, unsigned int unCodesCount = 0, unsigned char *pUseGlyfs = NULL, long lGlyfsCount = 0);
void WriteOTF(CStream* pOutputStream, char *sName = NULL, unsigned short *pCodeToGID = NULL);
int GetAscent();
int GetDescent();
int GetCapHeight();
int* GetBBox();
int GetWeight();
private:
CFontFileTrueType(char *sBuffer, int nLen, bool bFreeFileData, unsigned int unFontIndex);
unsigned int ComputeTableChecksum(unsigned char *sData, int nLength);
void Parse();
int SeekTable(char *sTag);
void ReadOS2();
private:
unsigned int m_unFontIndex;
TrueTypeTable* m_pTables;
int m_nTablesCount;
TrueTypeCmap* m_pCMaps;
int m_nCMapsCount;
int m_nGlyphs;
int m_nLocaFormat;
int m_arrBBox[4];
bool m_bOpenTypeCFF;
int m_nAscent;
int m_nDescent;
int m_nCapHeight;
int m_nWeight;
bool m_bSuccess;
};
}
#endif // _PDF_WRITER_SRC_TTWRITER_H
#include "GState.h"
namespace PdfWriter
{
const static char* c_sBlendModeNames[] =
{
"Normal",
"Multiply",
"Screen",
"Overlay",
"Darken",
"Lighten",
"ColorDodge",
"ColorBurn",
"HardLight",
"SoftLight",
"Difference",
"Exclusion"
};
//----------------------------------------------------------------------------------------
// CGrState
//----------------------------------------------------------------------------------------
CGrState::CGrState(CGrState* pCurrent)
{
if (pCurrent)
{
m_oMatrix = pCurrent->m_oMatrix;
m_dLineWidth = pCurrent->m_dLineWidth;
m_eLineCap = pCurrent->m_eLineCap;
m_eLineJoin = pCurrent->m_eLineJoin;
m_dMiterLimit = pCurrent->m_dMiterLimit;
m_oDashMode = pCurrent->m_oDashMode;
m_dFlatness = pCurrent->m_dFlatness;
m_dCharSpace = pCurrent->m_dCharSpace;
m_dWordSpace = pCurrent->m_dWordSpace;
m_dHScalling = pCurrent->m_dHScalling;
m_dTextLeading = pCurrent->m_dTextLeading;
m_eRenderingMode = pCurrent->m_eRenderingMode;
m_dTextRise = pCurrent->m_dTextRise;
m_oFillColor = pCurrent->m_oFillColor;
m_oStrokeColor = pCurrent->m_oStrokeColor;
m_pFont = pCurrent->m_pFont;
m_dFontSize = pCurrent->m_dFontSize;
m_pPrev = pCurrent;
m_unDepth = pCurrent->m_unDepth + 1;
}
else
{
m_dLineWidth = DEF_LINEWIDTH;
m_eLineCap = DEF_LINECAP;
m_eLineJoin = DEF_LINEJOIN;
m_dMiterLimit = DEF_MITERLIMIT;
m_dFlatness = DEF_FLATNESS;
m_dCharSpace = DEF_CHARSPACE;
m_dWordSpace = DEF_WORDSPACE;
m_dHScalling = DEF_HSCALING;
m_dTextLeading = DEF_LEADING;
m_eRenderingMode = DEF_RENDERING_MODE;
m_dTextRise = DEF_RISE;
m_pFont = NULL;
m_dFontSize = 0;
m_pPrev = NULL;
m_unDepth = 1;
}
}
CGrState::~CGrState()
{
}
//----------------------------------------------------------------------------------------
// CExtGrState
//----------------------------------------------------------------------------------------
CExtGrState::CExtGrState(CXref* pXref)
{
pXref->Add(this);
Add("Type", "ExtGState");
m_eBlendMode = blendmode_Unknown;
m_dAlphaFill = 1;
m_dAlphaStroke = 1;
m_bStrokeAdj = true;
}
void CExtGrState::SetAlphaStroke (double dValue)
{
dValue = min(1, max(0, dValue));
Add("CA", dValue);
}
void CExtGrState::SetAlphaFill (double dValue)
{
dValue = min(1, max(0, dValue));
Add("ca", dValue);
}
void CExtGrState::SetBlendMode (EBlendMode eBlendMode)
{
eBlendMode = min(blendmode_Max, max(blendmode_Min, eBlendMode));
Add("BM", c_sBlendModeNames[(int)eBlendMode]);
}
void CExtGrState::SetStrokeAdjustment(bool bValue)
{
Add("SA", bValue);
}
double CExtGrState::GetAlphaStroke()
{
return m_dAlphaStroke;
}
double CExtGrState::GetAlphaFill()
{
return m_dAlphaFill;
}
EBlendMode CExtGrState::GetBlendMode()
{
return m_eBlendMode;
}
bool CExtGrState::GetStrokeAdjustment()
{
return m_bStrokeAdj;
}
}
#ifndef _PDF_WRITER_SRC_GSTATE_H
#define _PDF_WRITER_SRC_GSTATE_H
#include "Types.h"
#include "Objects.h"
// Стандартные значения для Graphic State
#define DEF_FONT "Helvetica"
#define DEF_WORDSPACE 0
#define DEF_CHARSPACE 0
#define DEF_FONTSIZE 10
#define DEF_HSCALING 100
#define DEF_LEADING 0
#define DEF_RENDERING_MODE PdfWriter::textrenderingmode_Fill
#define DEF_RISE 0
#define DEF_LINEWIDTH 1
#define DEF_LINECAP PdfWriter::linecap_Butt
#define DEF_LINEJOIN PdfWriter::linejoin_Miter
#define DEF_MITERLIMIT 10
#define DEF_FLATNESS 1
#define DEF_PAGE_NUM 1
namespace PdfWriter
{
class CFontDict;
class CDictObject;
//----------------------------------------------------------------------------------------
// CGrState
//----------------------------------------------------------------------------------------
class CGrState
{
public:
CGrState(CGrState* pCurrent);
~CGrState();
CGrState* GetPrev()
{
return m_pPrev;
}
unsigned int GetDepth()
{
return m_unDepth;
}
private:
CMatrix m_oMatrix;
double m_dLineWidth;
ELineCapStyle m_eLineCap;
ELineJoinStyle m_eLineJoin;
double m_dMiterLimit;
CDashMode m_oDashMode;
double m_dFlatness;
double m_dCharSpace;
double m_dWordSpace;
double m_dHScalling;
double m_dTextLeading;
ETextRenderingMode m_eRenderingMode;
double m_dTextRise;
TRgb m_oFillColor;
TRgb m_oStrokeColor;
CFontDict* m_pFont;
double m_dFontSize;
CGrState* m_pPrev;
unsigned int m_unDepth;
friend class CPage;
};
//----------------------------------------------------------------------------------------
// CExtGrState
//----------------------------------------------------------------------------------------
class CExtGrState : public CDictObject
{
public:
CExtGrState(CXref* pXref);
void SetAlphaStroke (double dValue);
void SetAlphaFill (double dValue);
void SetBlendMode (EBlendMode eBlendMode);
void SetStrokeAdjustment(bool bValue);
double GetAlphaStroke();
double GetAlphaFill();
EBlendMode GetBlendMode();
bool GetStrokeAdjustment();
EDictType GetDictType() const
{
return dict_type_EXT_GSTATE;
}
private:
double m_dAlphaStroke;
double m_dAlphaFill;
EBlendMode m_eBlendMode;
bool m_bStrokeAdj;
};
}
#endif // _PDF_WRITER_SRC_GSTATE_H
#include "Image.h"
#include "Streams.h"
#include "Document.h"
#include "../../DesktopEditor/raster/JBig2/source/Encoder/jbig2enc.h"
#include "../../DesktopEditor/raster/JBig2/source/LeptonLib/allheaders.h"
namespace PdfWriter
{
//----------------------------------------------------------------------------------------
// CImageDict
//----------------------------------------------------------------------------------------
CImageDict::CImageDict(CXref* pXref, CDocument* pDocument)
{
m_pXref = pXref;
m_pDocument = pDocument;
}
void CImageDict::LoadJpeg(const wchar_t* wsFilePath, unsigned int unWidth, unsigned int unHeight)
{
CFileStream* pStream = new CFileStream();
if (!pStream)
return;
pStream->OpenFile(wsFilePath);
SetStream(m_pXref, pStream);
Add("Type", "XObject");
Add("Subtype", "Image");
Add("Height", unHeight);
Add("Width", unWidth);
Add("ColorSpace", "DeviceRGB");
Add("BitsPerComponent", 8);
SetFilter(STREAM_FILTER_DCT_DECODE);
}
void CImageDict::LoadJpx(const wchar_t* wsFilePath, unsigned int unWidth, unsigned int unHeight)
{
CFileStream* pStream = new CFileStream();
if (!pStream)
return;
pStream->OpenFile(wsFilePath);
SetStream(m_pXref, pStream);
Add("Type", "XObject");
Add("Subtype", "Image");
Add("Height", unHeight);
Add("Width", unWidth);
Add("ColorSpace", "DeviceRGB");
Add("BitsPerComponent", 8);
SetFilter(STREAM_FILTER_JPX_DECODE);
}
void CImageDict::LoadJb2(const wchar_t* wsFilePath, unsigned int unWidth, unsigned int unHeight)
{
CFileStream* pStream = new CFileStream();
if (!pStream)
return;
pStream->OpenFile(wsFilePath);
SetStream(m_pXref, pStream);
Add("Type", "XObject");
Add("Subtype", "Image");
Add("Height", unHeight);
Add("Width", unWidth);
Add("ColorSpace", "DeviceGray");
Add("BitsPerComponent", 1);
SetFilter(STREAM_FILTER_JBIG2_DECODE);
}
void CImageDict::LoadCCITT4(const wchar_t* wsTempFile, unsigned int unWidth, unsigned int unHeight)
{
CFileStream* pStream = new CFileStream();
if (!pStream)
return;
pStream->OpenFile(wsTempFile);
SetStream(m_pXref, pStream);
Add("Type", "XObject");
Add("Subtype", "Image");
Add("Height", unHeight);
Add("Width", unWidth);
Add("ColorSpace", "DeviceGray");
Add("BitsPerComponent", 1);
CArrayObject* pDecodeParams = new CArrayObject();
CDictObject* pParams = new CDictObject();
pDecodeParams->Add(pParams);
pParams->Add("K", 0);
pParams->Add("Columns", unWidth);
pParams->Add("EncodedByteAlign", true);
Add("DecodeParams", pDecodeParams);
SetFilter(STREAM_FILTER_CCITT_DECODE);
}
void CImageDict::LoadRaw(const BYTE* pBgra, unsigned int unWidth, unsigned int unHeight)
{
CMemoryStream* pStream = new CMemoryStream();
if (!pStream)
return;
for (unsigned int unIndex = 0, unSize = 4 * unWidth * unHeight; unIndex < unSize; unIndex += 4)
{
pStream->Write(pBgra + unIndex, 3);
}
SetStream(m_pXref, pStream);
Add("Type", "XObject");
Add("Subtype", "Image");
Add("ColorSpace", "DeviceRGB");
Add("Width", unWidth);
Add("Height", unHeight);
Add("BitsPerComponent", 8);
}
void CImageDict::LoadSMask(const BYTE* pBgra, unsigned int unWidth, unsigned int unHeight)
{
CMemoryStream* pStream = new CMemoryStream();
if (!pStream)
return;
for (unsigned int unIndex = 0, unSize = 4 * unWidth * unHeight; unIndex < unSize; unIndex += 4)
{
pStream->Write(pBgra + unIndex + 3, 1);
}
CImageDict* pImageSMask = new CImageDict(m_pXref, m_pDocument);
if (!pImageSMask)
return;
pImageSMask->SetStream(m_pXref, pStream);
pImageSMask->Add("Type", "XObject");
pImageSMask->Add("Subtype", "Image");
pImageSMask->Add("ColorSpace", "DeviceGray");
pImageSMask->Add("Width", unWidth);
pImageSMask->Add("Height", unHeight);
pImageSMask->Add("BitsPerComponent", 8);
//#ifndef FILTER_FLATE_DECODE_DISABLED
// pImageSMask->SetFilter(STREAM_FILTER_LZW_DECODE | STREAM_FILTER_FLATE_DECODE);
//#else
pImageSMask->SetFilter(STREAM_FILTER_FLATE_DECODE);
//#endif
Add("SMask", pImageSMask);
}
void CImageDict::LoadBW(const BYTE* pImage, unsigned int unWidth, unsigned int unHeight, unsigned int unStride)
{
SetStream(m_pXref, new CMemoryStream());
CJbig2Global* pJbig2Global = m_pDocument->GetJbig2Global();
pJbig2Global->AddImage(pImage, unWidth, unHeight, unStride, GetStream());
Add("Type", "XObject");
Add("Subtype", "Image");
Add("Height", unHeight);
Add("Width", unWidth);
Add("ColorSpace", "DeviceGray");
Add("BitsPerComponent", 1);
SetFilter(STREAM_FILTER_JBIG2_DECODE);
CArrayObject* pDecodeParams = new CArrayObject();
CDictObject* pParams = new CDictObject();
pDecodeParams->Add(pParams);
pParams->Add("JBIG2Globals", pJbig2Global);
Add("DecodeParms", pDecodeParams);
}
void CImageDict::LoadBW(Pix* pPix, unsigned int unWidth, unsigned int unHeight)
{
SetStream(m_pXref, new CMemoryStream());
CJbig2Global* pJbig2Global = m_pDocument->GetJbig2Global();
pJbig2Global->AddImage(pPix, GetStream());
Add("Type", "XObject");
Add("Subtype", "Image");
Add("Height", unHeight);
Add("Width", unWidth);
Add("ColorSpace", "DeviceGray");
Add("BitsPerComponent", 1);
SetFilter(STREAM_FILTER_JBIG2_DECODE);
CArrayObject* pDecodeParams = new CArrayObject();
CDictObject* pParams = new CDictObject();
pDecodeParams->Add(pParams);
pParams->Add("JBIG2Globals", pJbig2Global);
Add("DecodeParms", pDecodeParams);
}
//----------------------------------------------------------------------------------------
// CJbig2Global
//----------------------------------------------------------------------------------------
CJbig2Global::CJbig2Global(CXref* pXref) : CDictObject(pXref, true)
{
m_pXref = pXref;
m_pContext = jbig2_init(0.85, 0.5, -1, -1, false, -1);
}
CJbig2Global::~CJbig2Global()
{
if (m_pContext)
jbig2_destroy(m_pContext);
}
void CJbig2Global::FlushStreams()
{
CStream* pStream = GetStream();
int nLen = 0;
BYTE* pBuffer = jbig2_pages_complete(m_pContext, &nLen);
if (pBuffer)
{
pStream->Write(pBuffer, nLen);
free(pBuffer);
}
for (int nIndex = 0, nCount = m_vImages.size(); nIndex < nCount; nIndex++)
{
pBuffer = jbig2_produce_page(m_pContext, nIndex, -1, -1, &nLen);
if (pBuffer)
{
pStream = m_vImages.at(nIndex);
if (pStream)
{
pStream->Write(pBuffer, nLen);
}
free(pBuffer);
}
}
jbig2_destroy(m_pContext);
m_pContext = NULL;
}
void CJbig2Global::AddImage(const BYTE* pImage, unsigned int unWidth, unsigned int unHeight, unsigned int unStride, CStream* pImageStream)
{
if (!m_pContext)
return;
Pix* pPix = pixCreate(unWidth, unHeight, 1);
if (!pPix)
return;
BYTE* pLine = (BYTE*)pImage;
for (unsigned int unY = 0; unY < unHeight; unY++, pLine += unStride)
{
char nBit = 0;
BYTE* pCur = pLine;
for (unsigned int unX = 0; unX < unWidth; unX++)
{
pixSetPixel(pPix, unX, unY, pCur[0] & (1 << nBit));
nBit++;
if (8 == nBit)
{
nBit = 0;
pCur++;
}
}
}
jbig2_add_page(m_pContext, pPix);
pixDestroy(&pPix);
m_vImages.push_back(pImageStream);
}
void CJbig2Global::AddImage(Pix* pPix, CStream* pImageStream)
{
if (!m_pContext)
return;
jbig2_add_page(m_pContext, pPix);
m_vImages.push_back(pImageStream);
}
int CJbig2Global::GetImagesCount()
{
return m_vImages.size();
}
}
\ No newline at end of file
#ifndef _PDF_WRITER_SRC_IMAGE_H
#define _PDF_WRITER_SRC_IMAGE_H
#include "Objects.h"
struct jbig2ctx;
struct Pix;
namespace PdfWriter
{
class CDocument;
class CXObject : public CDictObject
{
public:
EDictType GetDictType() const
{
return dict_type_XOBJECT;
}
};
//----------------------------------------------------------------------------------------
// CImageDict
//----------------------------------------------------------------------------------------
class CImageDict : public CXObject
{
public:
CImageDict(CXref* pXref, CDocument* pDocument);
void LoadJpeg(const wchar_t* wsTempFile, unsigned int unWidth, unsigned int unHeight);
void LoadJpx(const wchar_t* wsTempFile, unsigned int unWidth, unsigned int unHeight);
void LoadJb2(const wchar_t* wsTempFile, unsigned int unWidth, unsigned int unHeight);
void LoadCCITT4(const wchar_t* wsTempFile, unsigned int unWidth, unsigned int unHeight);
void LoadRaw(const BYTE* pBgra, unsigned int unWidth, unsigned int unHeight);
void LoadSMask(const BYTE* pBgra, unsigned int unWidth, unsigned int unHeight);
void LoadBW(const BYTE* pImage, unsigned int unWidth, unsigned int unHeight, unsigned int unStride);
void LoadBW(Pix* pPix, unsigned int unWidth, unsigned int unHeight);
private:
CDocument* m_pDocument;
CXref* m_pXref;
};
//----------------------------------------------------------------------------------------
// CJbig2Global
//----------------------------------------------------------------------------------------
class CJbig2Global : public CDictObject
{
public:
CJbig2Global(CXref* pXref);
~CJbig2Global();
void AddImage(const BYTE* pImage, unsigned int unWidth, unsigned int unHeight, unsigned int unStride, CStream* pImageStream);
void AddImage(Pix* pPix, CStream* pImageStream);
void FlushStreams();
int GetImagesCount();
private:
CXref* m_pXref;
jbig2ctx* m_pContext;
std::vector<CStream*> m_vImages;
};
}
#endif // _PDF_WRITER_SRC_IMAGE_H
\ No newline at end of file
#include "Info.h"
#include "Utils.h"
#include "Objects.h"
#include <ctime>
static const char *c_asInfoItemNames[] =
{
"CreationDate",
"ModDate",
"Author",
"Creator",
"Producer",
"Title",
"Subject",
"Keywords",
NULL
};
namespace PdfWriter
{
static const char* InfoTypeToName(EInfoType eType)
{
unsigned int nIndex = (unsigned int)eType;
return c_asInfoItemNames[nIndex];
}
//----------------------------------------------------------------------------------------
// CInfoDict
//----------------------------------------------------------------------------------------
CInfoDict::CInfoDict(CXref* pXref)
{
pXref->Add(this);
}
void CInfoDict::SetInfo(EInfoType eType, const char* sValue)
{
const char* sName = InfoTypeToName(eType);
if (eType <= InfoModaDate)
return;
Add(sName, new CStringObject(sValue));
}
const char* CInfoDict::GetInfo(EInfoType eType)
{
const char* sName = InfoTypeToName(eType);
CStringObject* pString = (CStringObject*)Get(std::string(sName));
if (!pString || object_type_STRING != pString->GetType())
return NULL;
return (const char*)pString->GetString();
}
void CInfoDict::SetInfo(EInfoType eType, const TDate& oDate)
{
char sTemp[DATE_TIME_STR_LEN + 1];
char* pTemp = NULL;
const char* sName = InfoTypeToName(eType);
if (eType > InfoModaDate)
return;
MemSet(sTemp, 0, DATE_TIME_STR_LEN + 1);
if (oDate.nMonth < 1 || 12 < oDate.nMonth ||
oDate.nDay < 1 ||
23 < oDate.nHour || 59 < oDate.nMinutes || 59 < oDate.nSeconds ||
(oDate.nInd != '+' && oDate.nInd != '-' && oDate.nInd != 'Z' && oDate.nInd != ' ') ||
23 < oDate.nOffHour || 59 < oDate.nOffMinutes)
{
return;
}
switch (oDate.nMonth)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if (oDate.nDay > 31)
return;
break;
case 4:
case 6:
case 9:
case 11:
if (oDate.nDay > 30)
return;
break;
case 2:
if (oDate.nDay > 29 || (oDate.nDay == 29 && (oDate.nYear % 4 != 0 || (oDate.nYear % 100 == 0 && oDate.nYear % 400 != 0))))
return;
break;
default:
return;
}
pTemp = (char*)MemCpy((BYTE*)sTemp, (BYTE*)"D:", 2);
pTemp = ItoA2(pTemp, oDate.nYear, 5);
pTemp = ItoA2(pTemp, oDate.nMonth, 3);
pTemp = ItoA2(pTemp, oDate.nDay, 3);
pTemp = ItoA2(pTemp, oDate.nHour, 3);
pTemp = ItoA2(pTemp, oDate.nMinutes, 3);
pTemp = ItoA2(pTemp, oDate.nSeconds, 3);
if (' ' != oDate.nInd)
{
*pTemp++ = oDate.nInd;
pTemp = ItoA2(pTemp, oDate.nOffHour, 3);
*pTemp++ = '\'';
pTemp = ItoA2(pTemp, oDate.nOffMinutes, 3);
*pTemp++ = '\'';
}
*pTemp = 0;
Add(sName, new CStringObject(sTemp));
}
void CInfoDict::SetCreationTime()
{
time_t oTime = time(0);
struct tm* oNow = localtime(&oTime);
TDate oDate;
oDate.nYear = oNow->tm_year + 1900;
oDate.nMonth = oNow->tm_mon + 1;
oDate.nDay = oNow->tm_mday;
oDate.nHour = oNow->tm_hour;
oDate.nMinutes = oNow->tm_min;
oDate.nSeconds = oNow->tm_sec;
oDate.nInd = ' ';
SetInfo(InfoCreationDate, oDate);
}
}
\ No newline at end of file
#ifndef _PDF_WRITER_SRC_INFO_H
#define _PDF_WRITER_SRC_INFO_H
#include "Objects.h"
namespace PdfWriter
{
enum EInfoType
{
// Данные относительно даты создания и изменения.
InfoCreationDate = 0,
InfoModaDate = 1,
// Текстовые данные
InfoAuthor = 2,
InfoCreator = 3,
InfoProducer = 4,
InfoTitle = 5,
InfoSubject = 6,
InfoKeyWords = 7,
InfoMin = 0,
InfoMax = 0
};
struct TDate
{
int nYear;
int nMonth;
int nDay;
int nHour;
int nMinutes;
int nSeconds;
char nInd;
int nOffHour;
int nOffMinutes;
};
class CXref;
class CInfoDict : public CDictObject
{
public:
CInfoDict(CXref* pXref);
void SetInfo(EInfoType eType, const char* sValue);
const char* GetInfo(EInfoType eType);
void SetInfo(EInfoType eType, const TDate& oDate);
void SetCreationTime();
};
}
#endif // _PDF_WRITER_SRC_INFO_H
#include "Objects.h"
#include "Utils.h"
#include "Types.h"
#include "Encrypt.h"
#include "Streams.h"
// Если установлен бит OTYPE_DIRECT, значит данный объект принадлежит другому
// объекту. Если установлен бит OTYPE_INDIRECT, значит объект управляется таблицей xref.
#define FLAG_NONE 0x0
#define FLAG_HIDDEN 0x1
#define FLAG_INDIRECT 0x4
#define FLAG_DIRECT 0x8
//------ Значения относящиеся к объекту xref ------------------------------------
#define FREE_ENTRY 'f'
#define IN_USE_ENTRY 'n'
#define RELEASE_OBJECT(pObject) \
if (pObject && !pObject->IsIndirect())\
delete pObject;\
static const BYTE UNICODE_HEADER[] ={ 0xFE, 0xFF };
namespace PdfWriter
{
//----------------------------------------------------------------------------------------
// CObjectBase
//----------------------------------------------------------------------------------------
bool CObjectBase::IsHidden() const
{
return (m_unFlags & FLAG_HIDDEN ? true : false);
}
bool CObjectBase::IsDirect() const
{
return (m_unFlags & FLAG_DIRECT ? true : false);
}
bool CObjectBase::IsIndirect() const
{
return (m_unFlags & FLAG_INDIRECT ? true : false);
}
void CObjectBase::SetDirect()
{
m_unFlags |= FLAG_DIRECT;
}
void CObjectBase::SetIndirect()
{
m_unFlags |= FLAG_INDIRECT;
}
void CObjectBase::SetHidden()
{
m_unFlags |= FLAG_HIDDEN;
}
void CObjectBase::WriteValue(CStream* pStream, CEncrypt* pEncrypt)
{
switch (GetType())
{
case object_type_NAME: pStream->Write((CNameObject*)this); break;
case object_type_NUMBER: pStream->Write((CNumberObject*)this); break;
case object_type_REAL: pStream->Write((CRealObject*)this); break;
case object_type_STRING: pStream->Write((CStringObject*)this, pEncrypt); break;
case object_type_BINARY: pStream->Write((CBinaryObject*)this, pEncrypt); break;
case object_type_ARRAY: pStream->Write((CArrayObject*)this, pEncrypt); break;
case object_type_DICT: pStream->Write((CDictObject*)this, pEncrypt); break;
case object_type_BOOLEAN:pStream->Write((CBoolObject*)this); break;
case object_type_NULL: pStream->WriteStr("null"); break;
}
}
void CObjectBase::Write (CStream* pStream, CEncrypt* pEncrypt)
{
if (IsHidden())
return;
if (object_type_PROXY == GetType())
{
char sBuf[SHORT_BUFFER_SIZE];
char *pBuf = sBuf;
char *pEndPtr = sBuf + SHORT_BUFFER_SIZE - 1;
CObjectBase* pObject = ((CProxyObject*)this)->Get();
pBuf = ItoA(pBuf, pObject->m_unObjId & 0x00FFFFFF, pEndPtr);
*pBuf++ = ' ';
pBuf = ItoA(pBuf, pObject->m_unGenNo, pEndPtr);
StrCpy(pBuf, " R", pEndPtr);
pStream->WriteStr(sBuf);
}
else
{
WriteValue(pStream, pEncrypt);
}
}
//----------------------------------------------------------------------------------------
// CNameObject
//----------------------------------------------------------------------------------------
void CNameObject::Set(const char* sValue)
{
if (!sValue || 0 == sValue[0])
m_sValue[0] = 0;
else
{
StrCpy(m_sValue, sValue, m_sValue + LIMIT_MAX_NAME_LEN);
}
}
//----------------------------------------------------------------------------------------
// CStringObject
//----------------------------------------------------------------------------------------
CStringObject::CStringObject(const char* sValue)
{
m_pValue = NULL;
m_unLen = 0;
Set(sValue);
}
CStringObject::~CStringObject()
{
if (m_pValue)
delete[] m_pValue;
}
void CStringObject::Set(const char* sValue)
{
if (m_pValue)
{
delete[] m_pValue;
m_unLen = 0;
}
unsigned int unLen = StrLen(sValue, LIMIT_MAX_STRING_LEN);
m_pValue = new BYTE[unLen + 1];
StrCpy((char*)m_pValue, (char*)sValue, (char*)(m_pValue + unLen));
m_unLen = unLen;
}
//----------------------------------------------------------------------------------------
// CBinaryObject
//----------------------------------------------------------------------------------------
CBinaryObject::CBinaryObject(const BYTE* pValue, unsigned int unLen)
{
m_pValue = NULL;
m_unLen = 0;
Set(pValue, unLen);
}
CBinaryObject::~CBinaryObject()
{
if (m_pValue)
delete[] m_pValue;
}
void CBinaryObject::Set(const BYTE* pValue, unsigned int unLen)
{
unLen = min(LIMIT_MAX_STRING_LEN, unLen);
if (m_pValue)
{
delete[] m_pValue;
m_pValue = NULL;
m_unLen = 0;
}
if (!pValue || !unLen)
return;
m_unLen = unLen;
m_pValue = new BYTE[unLen];
MemCpy(m_pValue, pValue, unLen);
}
//----------------------------------------------------------------------------------------
// CArrayObject
//----------------------------------------------------------------------------------------
void CArrayObject::Add(CObjectBase* pObject)
{
if (!pObject)
return;
// Не даем писать сложные объекты в массив не по ссылке
if (pObject->IsDirect())
return;
if (GetCount() >= LIMIT_MAX_ARRAY)
{
RELEASE_OBJECT(pObject);
return;
}
if (pObject->IsIndirect())
{
CObjectBase* pProxy = new CProxyObject(pObject);
if (!pProxy)
{
RELEASE_OBJECT(pObject);
return;
}
pObject = pProxy;
}
pObject->SetDirect();
m_arrList.push_back(pObject);
}
void CArrayObject::Add(bool bValue)
{
CObjectBase* pBool = new CBoolObject(bValue);
if (pBool)
Add(pBool);
}
void CArrayObject::Add(int nValue)
{
CObjectBase* pNumber = new CNumberObject(nValue);
if (pNumber)
Add(pNumber);
}
void CArrayObject::Add(unsigned int unValue)
{
CObjectBase* pNumber = new CNumberObject((int)unValue);
if (pNumber)
Add(pNumber);
}
void CArrayObject::Add(float fValue)
{
CObjectBase* pReal = new CRealObject(fValue);
if (pReal)
Add(pReal);
}
void CArrayObject::Add(const char* sName)
{
CObjectBase* pName = new CNameObject(sName);
if (pName)
Add(pName);
}
void CArrayObject::Add(double dValue)
{
CObjectBase* pReal = new CRealObject(dValue);
if (pReal)
Add(pReal);
}
void CArrayObject::Insert(CObjectBase *pTarget, CObjectBase* pObject)
{
if (!pObject)
return;
if (pObject->IsDirect())
return;
if (GetCount() >= LIMIT_MAX_ARRAY)
{
RELEASE_OBJECT(pObject);
return;
}
if (pObject->IsIndirect())
{
CObjectBase* pProxy = new CProxyObject(pObject);
if (!pProxy)
{
RELEASE_OBJECT(pObject);
return;
}
pObject = pProxy;
}
pObject->SetDirect();
//получаем target-object из списка
//рассмотреть случай, когда указатель на содержимое списка
//может быть proxy-object.
for (int nIndex = 0, nCount = m_arrList.size(); nIndex < nCount; nIndex++)
{
CObjectBase* pObjectItem = m_arrList.at(nIndex);
if (object_type_PROXY == pObjectItem->GetType())
pObjectItem = ((CProxyObject*)pObjectItem)->Get();
if (pObjectItem == pTarget)
{
m_arrList.insert(m_arrList.begin() + nIndex, pObject);
return;
}
}
// Дошли до сюда, значит не вставили данный объект, поэтому удаляем его
RELEASE_OBJECT(pObject);
}
CObjectBase* CArrayObject::Get(unsigned int unIndex, bool bCheckProxy) const
{
if (unIndex >= m_arrList.size())
return NULL;
CObjectBase* pObject = m_arrList.at(unIndex);
if (bCheckProxy && object_type_PROXY == pObject->GetType())
pObject = ((CProxyObject*)pObject)->Get();
return pObject;
}
void CArrayObject::Clear()
{
for (int nIndex = 0, nCount = m_arrList.size(); nIndex < nCount; nIndex++)
{
CObjectBase* pObject = m_arrList.at(nIndex);
RELEASE_OBJECT(pObject);
}
m_arrList.clear();
}
CArrayObject* CArrayObject::CreateBox(const TBox& oBox)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return NULL;
pArray->Add(oBox.fLeft);
pArray->Add(oBox.fBottom);
pArray->Add(oBox.fRight);
pArray->Add(oBox.fTop);
return pArray;
}
CArrayObject* CArrayObject::CreateBox(double dL, double dB, double dR, double dT)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return NULL;
pArray->Add(dL);
pArray->Add(dB);
pArray->Add(dR);
pArray->Add(dT);
return pArray;
}
//----------------------------------------------------------------------------------------
// CDictObject
//----------------------------------------------------------------------------------------
CDictObject::CDictObject()
{
m_unFilter = STREAM_FILTER_NONE;
m_unPredictor = STREAM_PREDICTOR_NONE;
m_pStream = NULL;
}
CDictObject::CDictObject(CXref* pXref, bool bMemoryStream, const wchar_t* wsTempFile, unsigned int unCheckSum)
{
m_unFilter = STREAM_FILTER_NONE;
m_unPredictor = STREAM_PREDICTOR_NONE;
m_pStream = NULL;
CNumberObject* pLength = new CNumberObject(0);
// Только stream object добавляются в таблицу xref автоматически
pXref->Add((CObjectBase*)this);
pXref->Add((CObjectBase*)pLength);
Add("Length", (CObjectBase*)pLength);
if (bMemoryStream)
m_pStream = new CMemoryStream(STREAM_BUF_SIZ);
else
{
m_pStream = new CFileStream();
((CFileStream*)m_pStream)->OpenTempFile(wsTempFile, unCheckSum);
}
}
CDictObject::~CDictObject()
{
for (auto const &oIter : m_mList)
{
CObjectBase* pObject = oIter.second;
RELEASE_OBJECT(pObject);
}
if (m_pStream)
delete m_pStream;
}
CObjectBase* CDictObject::Get(const std::string& sKey) const
{
std::map<std::string, CObjectBase*>::const_iterator oIter = m_mList.find(sKey);
if (m_mList.end() != oIter)
{
CObjectBase* pObject = oIter->second;
if (pObject && object_type_PROXY == pObject->GetType())
pObject = ((CProxyObject*)pObject)->Get();
return pObject;
}
return NULL;
}
void CDictObject::Add(const std::string& sKey, CObjectBase* pObject)
{
if (!pObject)
return;
if (pObject->IsDirect())
return;
if (m_mList.size() >= LIMIT_MAX_DICT_ELEMENT)
{
RELEASE_OBJECT(pObject);
return;
}
// Удаляем старую запись, если она была
Remove(sKey);
if (pObject->IsIndirect())
{
CObjectBase* pProxy = new CProxyObject(pObject);
pObject = pProxy;
}
pObject->SetDirect();
m_mList.insert(std::pair<std::string, CObjectBase*>(sKey, pObject));
}
void CDictObject::Remove(const std::string& sKey)
{
std::map<std::string, CObjectBase*>::const_iterator pIter = m_mList.find(sKey);
if (m_mList.end() != pIter)
{
CObjectBase* pObject = pIter->second;
RELEASE_OBJECT(pObject);
m_mList.erase(sKey);
}
}
void CDictObject::Add(const std::string& sKey, const char* sName)
{
Add(sKey, new CNameObject(sName));
}
void CDictObject::Add(const std::string& sKey, int nNumber)
{
Add(sKey, new CNumberObject(nNumber));
}
void CDictObject::Add(const std::string& sKey, unsigned int unNumber)
{
Add(sKey, (int)unNumber);
}
void CDictObject::Add(const std::string& sKey, float fReal)
{
Add(sKey, new CRealObject(fReal));
}
void CDictObject::Add(const std::string& sKey, double dReal)
{
Add(sKey, new CRealObject(dReal));
}
void CDictObject::Add(const std::string& sKey, bool bBool)
{
Add(sKey, new CBoolObject(bBool));
}
const char* CDictObject::GetKey(CObjectBase* pObject)
{
for (auto const &oIter : m_mList)
{
CObjectBase* pListObject = oIter.second;
if (pListObject && object_type_PROXY == pListObject->GetType())
pListObject = ((CProxyObject*)pListObject)->Get();
if (pListObject == pObject)
return oIter.first.c_str();
}
return NULL;
}
void CDictObject::WriteToStream(CStream* pStream, CEncrypt* pEncrypt)
{
for (auto const &oIter : m_mList)
{
CObjectBase* pObject = oIter.second;
if (!pObject)
continue;
if (pObject->IsHidden())
{
// ничего не делаем
}
else
{
pStream->WriteEscapeName(oIter.first.c_str());
pStream->WriteChar(' ');
pStream->Write(pObject, pEncrypt);
pStream->WriteStr("\012");
}
}
}
void CDictObject::SetStream(CXref* pXref, CStream* pStream)
{
if (m_pStream)
delete m_pStream;
if (!Get("Length"))
{
CNumberObject* pLength = new CNumberObject(0);
// Только stream object добавляются в таблицу xref автоматически
pXref->Add((CObjectBase*)this);
pXref->Add((CObjectBase*)pLength);
Add("Length", (CObjectBase*)pLength);
}
m_pStream = pStream;
}
//----------------------------------------------------------------------------------------
// CXref
//----------------------------------------------------------------------------------------
CXref::CXref(unsigned int unOffset)
{
m_unStartOffset = unOffset;
m_unAddr = 0;
m_pPrev = NULL;
m_pTrailer = NULL;
if (0 == m_unStartOffset)
{
// Добавляем первый элемент в таблицу xref
// он должен иметь вид 0000000000 65535 f
TXrefEntry* pEntry = new TXrefEntry;
pEntry->nEntryType = FREE_ENTRY;
pEntry->unByteOffset = 0;
pEntry->unGenNo = MAX_GENERATION_NUM;
pEntry->pObject = NULL;
m_arrEntries.push_back(pEntry);
}
m_pTrailer = new CDictObject();
}
CXref::~CXref()
{
for (int nIndex = 0, nCount = m_arrEntries.size(); nIndex < nCount; nIndex++)
{
TXrefEntry* pEntry = m_arrEntries.at(nIndex);
if (pEntry)
{
CObjectBase* pObject = pEntry->pObject;
if (pObject)
delete pObject;
}
delete pEntry;
}
if (m_pTrailer)
delete m_pTrailer;
if (m_pPrev)
delete m_pPrev;
}
TXrefEntry* CXref::GetEntry(unsigned int unIndex) const
{
return m_arrEntries.at(unIndex);
}
TXrefEntry* CXref::GetEntryByObjectId(unsigned int nObjectId) const
{
const CXref* pXref = this;
while (pXref)
{
if (pXref->m_arrEntries.size() + pXref->m_unStartOffset > nObjectId)
return NULL;
if (pXref->m_unStartOffset < nObjectId)
{
for (unsigned int unIndex = 0, nCount = pXref->m_arrEntries.size(); unIndex < nCount; unIndex++)
{
if (pXref->m_unStartOffset + unIndex == nObjectId)
{
return pXref->GetEntry(unIndex);
}
}
}
pXref = (const CXref*)pXref->m_pPrev;
}
return NULL;
}
void CXref::Add(CObjectBase* pObject)
{
if (!pObject)
return;
if (pObject->IsDirect() || pObject->IsIndirect())
return;
if (m_arrEntries.size() >= LIMIT_MAX_XREF_ELEMENT)
{
RELEASE_OBJECT(pObject);
return;
}
// В случае ошибки r объектe нужно применить dispose
TXrefEntry* pEntry = new TXrefEntry;
if (NULL == pEntry)
{
RELEASE_OBJECT(pObject);
return;
}
m_arrEntries.push_back(pEntry);
pEntry->nEntryType = IN_USE_ENTRY;
pEntry->unByteOffset = 0;
pEntry->unGenNo = 0;
pEntry->pObject = pObject;
pObject->SetRef(m_unStartOffset + m_arrEntries.size() - 1, pEntry->unGenNo);
pObject->SetIndirect();
}
void CXref::WriteTrailer(CStream* pStream)
{
unsigned int unMaxObjId = m_arrEntries.size() + m_unStartOffset;
m_pTrailer->Add("Size", unMaxObjId);
if (m_pPrev)
m_pTrailer->Add("Prev", m_pPrev->m_unAddr);
pStream->WriteStr("trailer\012");
pStream->Write(m_pTrailer, NULL);
pStream->WriteStr("\012startxref\012");
pStream->WriteUInt(m_unAddr);
pStream->WriteStr("\012%%EOF\012");
}
void CXref::WriteToStream(CStream* pStream, CEncrypt* pEncrypt)
{
std::string sBuffer;
char sBuf[SHORT_BUFFER_SIZE];
char* pBuf;
char* pEndPtr = sBuf + SHORT_BUFFER_SIZE - 1;
CXref* pXref = this;
while (pXref)
{
unsigned int unStartIndex = (0 == pXref->m_unStartOffset ? 1 : 0);
for (unsigned int unIndex = unStartIndex, unCount = pXref->m_arrEntries.size(); unIndex < unCount; unIndex++)
{
TXrefEntry* pEntry = pXref->m_arrEntries.at(unIndex);
unsigned int unObjId = pXref->m_unStartOffset + unIndex;
unsigned int unGenNo = pEntry->unGenNo;
pEntry->unByteOffset = pStream->Tell();
if (pEncrypt)
pEncrypt->InitKey(unObjId, unGenNo);
pBuf = sBuf;
pBuf = ItoA(pBuf, unObjId, pEndPtr);
*pBuf++ = ' ';
pBuf = ItoA(pBuf, unGenNo, pEndPtr);
StrCpy(pBuf, " obj\012", pEndPtr);
pStream->WriteStr(sBuf);
pEntry->pObject->WriteValue(pStream, pEncrypt);
pStream->WriteStr("\012endobj\012");
}
pXref = pXref->m_pPrev;
}
// Записываем cross-reference table
pXref = this;
while (pXref)
{
pXref->m_unAddr = pStream->Tell();
pBuf = sBuf;
pBuf = (char*)StrCpy(pBuf, "xref\012", pEndPtr);
pBuf = ItoA(pBuf, pXref->m_unStartOffset, pEndPtr);
*pBuf++ = ' ';
pBuf = ItoA(pBuf, pXref->m_arrEntries.size(), pEndPtr);
StrCpy(pBuf, "\012", pEndPtr);
pStream->WriteStr(sBuffer.c_str());
for (unsigned int unIndex = 0, unCount = pXref->m_arrEntries.size(); unIndex < unCount; unIndex++)
{
TXrefEntry* pEntry = pXref->GetEntry(unIndex);
sBuffer =
pBuf = sBuf;
pBuf = ItoA2(pBuf, pEntry->unByteOffset, BYTE_OFFSET_LEN + 1);
*pBuf++ = ' ';
pBuf = ItoA2(pBuf, pEntry->unGenNo, GEN_NO_LEN + 1);
*pBuf++ = ' ';
*pBuf++ = pEntry->nEntryType;
StrCpy(pBuf, "\015\012", pEndPtr);
pStream->WriteStr(sBuf);
}
pXref = pXref->m_pPrev;
}
// Записываем Trailer
WriteTrailer(pStream);
}
}
#ifndef _PDF_WRITER_SRC_OBJECTS_H
#define _PDF_WRITER_SRC_OBJECTS_H
#include <string>
#include <map>
#include <vector>
#include "Types.h"
namespace PdfWriter
{
class CXref;
class CStream;
class CEncrypt;
typedef enum
{
object_type_UNKNOWN = 0x01,
object_type_NULL = 0x02,
object_type_BOOLEAN = 0x03,
object_type_NUMBER = 0x04,
object_type_REAL = 0x05,
object_type_NAME = 0x06,
object_type_STRING = 0x07,
object_type_BINARY = 0x08,
object_type_ARRAY = 0x10,
object_type_DICT = 0x11,
object_type_PROXY = 0x12,
object_type_PATTERN_REF = 0xFA,
object_type_FUNC_REF = 0xF2,
object_type_MASK_FORM = 0xF3,
object_type_MASK_REF = 0xF4,
object_type_XFORM = 0xF5
} EObjectType;
typedef enum
{
dict_type_UNKNOWN = 0x00,
dict_type_FONT = 0x01,
dict_type_CATALOG = 0x02,
dict_type_PAGES = 0x03,
dict_type_PAGE = 0x04,
dict_type_XOBJECT = 0x05,
dict_type_OUTLINE = 0x06,
dict_type_DESTINATION = 0x07,
dict_type_ANNOTATION = 0x08,
dict_type_ENCRYPT = 0x09,
dict_type_EXT_GSTATE = 0x0A,
dict_type_EXT_GSTATE_R = 0x0B /* read only object */
} EDictType;
class CObjectBase
{
public:
CObjectBase()
{
m_unFlags = 0;
m_unGenNo = 0;
m_unObjId = 0;
}
virtual ~CObjectBase()
{}
virtual EObjectType GetType() const
{
return object_type_UNKNOWN;
}
bool IsHidden() const;
bool IsDirect() const;
bool IsIndirect() const;
void SetDirect();
void SetIndirect();
void SetHidden();
void SetRef(unsigned int unObjId, unsigned int unGenNo)
{
m_unObjId = unObjId;
m_unGenNo = unGenNo;
}
void WriteValue(CStream* pStream, CEncrypt* pEncrypt);
void Write (CStream* pStream, CEncrypt* pEncrypt);
private:
unsigned int m_unFlags;
unsigned int m_unObjId;
unsigned int m_unGenNo;
};
class CNullObject : public CObjectBase
{
public:
EObjectType GetType() const
{
return object_type_NULL;
}
};
class CBoolObject : public CObjectBase
{
public:
CBoolObject(const bool& bValue)
{
m_bValue = bValue;
}
EObjectType GetType() const
{
return object_type_BOOLEAN;
}
bool Get() const
{
return m_bValue;
}
private:
bool m_bValue;
};
class CNumberObject : public CObjectBase
{
public:
CNumberObject()
{
m_nValue = 0;
}
CNumberObject(const int& nValue)
{
m_nValue = nValue;
}
EObjectType GetType() const
{
return object_type_NUMBER;
}
void Set(const int& nValue)
{
m_nValue = nValue;
}
int Get() const
{
return m_nValue;
}
void operator++(int)
{
m_nValue++;
}
private:
int m_nValue;
};
class CRealObject : public CObjectBase
{
public:
CRealObject(float fValue)
{
Set(fValue);
}
CRealObject(double dValue)
{
Set((float)dValue);
}
EObjectType GetType() const
{
return object_type_REAL;
}
void Set(float fValue)
{
m_fValue = min(max(fValue, LIMIT_MIN_REAL), LIMIT_MAX_REAL);
}
void Set(double dValue)
{
m_fValue = (float)min(max(dValue, LIMIT_MIN_REAL), LIMIT_MAX_REAL);
}
float Get() const
{
return m_fValue;
}
private:
float m_fValue;
};
class CNameObject : public CObjectBase
{
public:
CNameObject(const char* sValue)
{
Set(sValue);
}
void Set(const char* sValue);
const char* Get() const
{
return m_sValue;
}
EObjectType GetType() const
{
return object_type_NAME;
}
private:
char m_sValue[LIMIT_MAX_NAME_LEN + 1];
};
class CStringObject : public CObjectBase
{
public:
CStringObject(const char* sValue);
virtual ~CStringObject();
void Set(const char* sValue);
const BYTE* GetString() const
{
return (const BYTE*)m_pValue;
}
unsigned int GetLength() const
{
return m_unLen;
}
EObjectType GetType() const
{
return object_type_STRING;
}
private:
BYTE* m_pValue;
unsigned int m_unLen;
};
class CBinaryObject : public CObjectBase
{
public:
CBinaryObject(const BYTE* pValue, unsigned int unLen);
~CBinaryObject();
void Set(const BYTE* pValue, unsigned int unLen);
BYTE* GetValue() const
{
return m_pValue;
}
unsigned int GetLength() const
{
return m_unLen;
}
EObjectType GetType() const
{
return object_type_BINARY;
}
private:
BYTE* m_pValue;
unsigned int m_unLen;
};
class CProxyObject : public CObjectBase
{
public:
CProxyObject(CObjectBase* pObject)
{
m_pObject = pObject;
}
CObjectBase* Get() const
{
return m_pObject;
}
EObjectType GetType() const
{
return object_type_PROXY;
}
private:
CObjectBase* m_pObject;
};
class CArrayObject : public CObjectBase
{
public:
CArrayObject()
{
}
virtual ~CArrayObject()
{
Clear();
}
int GetCount() const
{
return m_arrList.size();
}
void Add(CObjectBase* pObject);
void Add(bool bValue);
void Add(int nValue);
void Add(unsigned int unValue);
void Add(float fValue);
void Add(const char* sValue);
void Add(double dValue);
void Insert(CObjectBase* pTarget, CObjectBase* pObject);
CObjectBase* Get(unsigned int unIndex, bool bCheckProxy = true) const;
void Clear();
EObjectType GetType() const
{
return object_type_ARRAY;
}
static CArrayObject* CreateBox(const TBox& oBox);
static CArrayObject* CreateBox(double dL, double dB, double dR, double dT);
protected:
std::vector<CObjectBase*> m_arrList;
};
class CDictObject : public CObjectBase
{
public:
CDictObject();
CDictObject(CXref* pXref, bool bMemoryStream = true, const wchar_t* wsTempFile = NULL, unsigned int unCheckSum = 0);
virtual ~CDictObject();
virtual EObjectType GetType() const
{
return object_type_DICT;
}
CObjectBase* Get(const std::string& sKey) const;
void Add(const std::string& sKey, CObjectBase* pObject);
void Remove(const std::string& sKey);
void Add(const std::string& sKey, const char* sName);
void Add(const std::string& sKey, int nNumber);
void Add(const std::string& sKey, unsigned int unNumber);
void Add(const std::string& sKey, float fReal);
void Add(const std::string& sKey, double dReal);
void Add(const std::string& sKey, bool bBool);
const char* GetKey(CObjectBase* pObject);
CStream* GetStream() const
{
return m_pStream;
}
unsigned int GetFilter() const
{
return m_unFilter;
}
unsigned int GetPredictor() const
{
return m_unPredictor;
}
void SetFilter(unsigned int unFiler)
{
m_unFilter = unFiler;
}
void SetStream(CXref* pXref, CStream* pStream);
virtual void BeforeWrite(){}
virtual void Write(CStream* pStream){}
virtual void AfterWrite(){}
virtual EDictType GetDictType() const
{
return dict_type_UNKNOWN;
}
void WriteToStream(CStream* pStream, CEncrypt* pEncrypt);
private:
std::map<std::string, CObjectBase*> m_mList;
unsigned int m_unFilter;
unsigned int m_unPredictor;
CStream* m_pStream;
};
struct TXrefEntry
{
char nEntryType;
unsigned int unByteOffset;
unsigned int unGenNo;
CObjectBase* pObject;
};
class CXref
{
public:
CXref(unsigned int unOffset);
~CXref();
TXrefEntry* GetEntry(unsigned int unIndex) const;
TXrefEntry* GetEntryByObjectId(unsigned int unObjectId) const;
void Add(CObjectBase* pObject);
void WriteToStream(CStream* pStream, CEncrypt* pEncrypt);
int GetCount() const
{
return m_arrEntries.size();
}
CDictObject*GetTrailer() const
{
return m_pTrailer;
}
private:
void WriteTrailer(CStream* pStream);
private:
std::vector<TXrefEntry*> m_arrEntries;
unsigned int m_unStartOffset;
unsigned int m_unAddr;
CXref* m_pPrev;
CDictObject* m_pTrailer;
};
}
#endif // _PDF_WRITER_SRC_OBJECTS_H
#include "Outline.h"
#include "Destination.h"
#define OUTLINE_CLOSED 0
#define OUTLINE_OPENED 1
namespace PdfWriter
{
COutline::COutline(CXref* pXref)
{
pXref->Add(this);
CNumberObject* pOpenFlag = new CNumberObject(OUTLINE_OPENED);
if (!pOpenFlag)
return;
pOpenFlag->SetHidden();
Add("_OPENED", pOpenFlag);
Add("Type", "Outline");
}
COutline::COutline(COutline* pParent, const char* sTitle, CXref* pXref)
{
if (!pParent || !pXref)
return;
pXref->Add(this);
CStringObject* pString = new CStringObject(sTitle);
if (!pString)
return;
Add("Title", pString);
CNumberObject* pOpenFlag = new CNumberObject(OUTLINE_OPENED);
if (!pOpenFlag)
return;
pOpenFlag->SetHidden();
Add("_OPENED", pOpenFlag);
Add("Type", "Outline");
pParent->AddChild(this);
}
void COutline::BeforeWrite()
{
CNumberObject* pNumber = (CNumberObject*)Get("Count");
unsigned int unCount = CountChild();
if (0 == unCount && pNumber)
return Remove("Count");
if (!GetOpened())
unCount *= -1;
if (pNumber)
pNumber->Set(unCount);
else if (unCount)
Add("Count", unCount);
}
void COutline::AddChild(COutline* pItem)
{
COutline* pFirst = (COutline*)Get("First");
COutline* pLast = (COutline*)Get("Last");
if (!pFirst)
Add("First", pItem);
if (pLast)
{
pLast->Add("Next", pItem);
pItem->Add("Prev", pLast);
}
Add("Last", pItem);
pItem->Add("Parent", this);
}
unsigned int COutline::CountChild()
{
COutline* pOutline = GetFirst();
unsigned int unCount = 0;
while (pOutline)
{
unCount++;
if (pOutline->GetOpened())
unCount += pOutline->CountChild();
pOutline = pOutline->GetNext();
}
return unCount;
}
COutline* COutline::GetFirst()
{
return (COutline*)Get("First");
}
COutline* COutline::GetLast ()
{
return (COutline*)Get("Last");
}
COutline* COutline::GetPrev ()
{
return (COutline*)Get("Prev");
}
COutline* COutline::GetNext ()
{
return (COutline*)Get("Next");
}
COutline* COutline::GetParent()
{
return (COutline*)Get("Parent");
}
bool COutline::GetOpened()
{
CNumberObject* pNumber = (CNumberObject*)Get("_OPENED");
if (!pNumber)
return false;
return (pNumber->Get() == OUTLINE_OPENED ? true : false);
}
void COutline::SetDestination(CDestination* pDestination)
{
if (NULL == pDestination)
Remove("Dest");
else
Add("Dest", pDestination);
}
void COutline::SetOpened(bool bOpened)
{
CNumberObject* pNumber = (CNumberObject*)Get("_OPENED");
if (!pNumber)
{
pNumber = new CNumberObject(bOpened ? OUTLINE_OPENED : OUTLINE_CLOSED);
if (pNumber)
Add("_OPENED", pNumber);
}
else
pNumber->Set(bOpened ? OUTLINE_OPENED : OUTLINE_CLOSED);
}
}
\ No newline at end of file
#ifndef _PDF_WRITER_SRC_OUTLINE_H
#define _PDF_WRITER_SRC_OUTLINE_H
#include "Objects.h"
namespace PdfWriter
{
class CDestination;
class COutline : public CDictObject
{
public:
COutline(CXref* pXref);
COutline(COutline* pParent, const char* sTitle, CXref* pXref);
void SetDestination(CDestination* pDestination);
void SetOpened(bool bOpened);
void BeforeWrite();
EDictType GetDictType() const
{
return dict_type_OUTLINE;
}
COutline* GetFirst();
COutline* GetLast();
COutline* GetPrev();
COutline* GetNext();
COutline* GetParent();
bool GetOpened();
private:
void AddChild(COutline* pItem);
unsigned int CountChild();
};
}
#endif // _PDF_WRITER_SRC_OUTLINE_H
#include "Objects.h"
#include "Pages.h"
#include "Utils.h"
#include "GState.h"
#include "Streams.h"
#include "Annotation.h"
#include "Font.h"
#include "Image.h"
#include "Shading.h"
#include "Pattern.h"
#ifdef DrawText
#undef DrawText
#endif
#define MIN_HORIZONTALSCALING 0.01
#define MAX_HORIZONTALSCALING 1000
#define MIN_CHARSPACE -30
#define MAX_CHARSPACE 300
#define MAX_FONTSIZE 1000
namespace PdfWriter
{
static const double c_dKappa = 0.552;
static void QuarterEllipseA(CStream* pStream, double dX, double dY, double dXRad, double dYRad)
{
pStream->WriteReal(dX - dXRad);
pStream->WriteChar(' ');
pStream->WriteReal(dY + dYRad * c_dKappa);
pStream->WriteChar(' ');
pStream->WriteReal(dX - dXRad * c_dKappa);
pStream->WriteChar(' ');
pStream->WriteReal(dY + dYRad);
pStream->WriteChar(' ');
pStream->WriteReal(dX);
pStream->WriteChar(' ');
pStream->WriteReal(dY + dYRad);
pStream->WriteStr(" c\012");
}
static void QuarterEllipseB(CStream* pStream, double dX, double dY, double dXRad, double dYRad)
{
pStream->WriteReal(dX + dXRad * c_dKappa);
pStream->WriteChar(' ');
pStream->WriteReal(dY + dYRad);
pStream->WriteChar(' ');
pStream->WriteReal(dX + dXRad);
pStream->WriteChar(' ');
pStream->WriteReal(dY + dYRad * c_dKappa);
pStream->WriteChar(' ');
pStream->WriteReal(dX + dXRad);
pStream->WriteChar(' ');
pStream->WriteReal(dY);
pStream->WriteStr(" c\012");
}
static void QuarterEllipseC(CStream* pStream, double dX, double dY, double dXRad, double dYRad)
{
pStream->WriteReal(dX + dXRad);
pStream->WriteChar(' ');
pStream->WriteReal(dY - dYRad * c_dKappa);
pStream->WriteChar(' ');
pStream->WriteReal(dX + dXRad * c_dKappa);
pStream->WriteChar(' ');
pStream->WriteReal(dY - dYRad);
pStream->WriteChar(' ');
pStream->WriteReal(dX);
pStream->WriteChar(' ');
pStream->WriteReal(dY - dYRad);
pStream->WriteStr(" c\012");
}
static void QuarterEllipseD(CStream* pStream, double dX, double dY, double dXRad, double dYRad)
{
pStream->WriteReal(dX - dXRad * c_dKappa);
pStream->WriteChar(' ');
pStream->WriteReal(dY - dYRad);
pStream->WriteChar(' ');
pStream->WriteReal(dX - dXRad);
pStream->WriteChar(' ');
pStream->WriteReal(dY - dYRad * c_dKappa);
pStream->WriteChar(' ');
pStream->WriteReal(dX - dXRad);
pStream->WriteChar(' ');
pStream->WriteReal(dY);
pStream->WriteStr(" c\012");
}
static double AngToEllPrm(double dAngle, double dXRad, double dYRad)
{
// Функция для перевода реального угла в параметрическое задание эллписа
// т.е. x= a cos(t) y = b sin(t) - параметрическое задание эллписа.
// x = r cos(p), y = r sin(p) => t = atan2( sin(p) / b, cos(p) / a );
return atan2(sin(dAngle) / dYRad, cos(dAngle) / dXRad);
}
static void WriteEllipseArc(CStream* pStream, double dX, double dY, double dXRad, double dYRad, double dAngle1, double dAngle2, double& dXCur, double& dYCur, bool bClockDirection = false)
{
// Рассчитаем начальную, конечную и контрольные точки
double dX1 = 0.0, dX2 = 0.0, dY1 = 0.0, dY2 = 0.0;
double dCX1 = 0.0, dCX2 = 0.0, dCY1 = 0.0, dCY2 = 0.0;
double dAlpha = sin(dAngle2 - dAngle1) * (sqrt(4.0 + 3.0 * tan((dAngle2 - dAngle1) / 2.0) * tan((dAngle2 - dAngle1) / 2.0)) - 1.0) / 3.0;
dX1 = dX + dXRad * cos(dAngle1);
dY1 = dY + dYRad * sin(dAngle1);
dX2 = dX + dXRad * cos(dAngle2);
dY2 = dY + dYRad * sin(dAngle2);
dCX1 = dX1 - dAlpha * dXRad * sin(dAngle1);
dCY1 = dY1 + dAlpha * dYRad * cos(dAngle1);
dCX2 = dX2 + dAlpha * dXRad * sin(dAngle2);
dCY2 = dY2 - dAlpha * dYRad * cos(dAngle2);
if ( !bClockDirection )
{
pStream->WriteReal(dCX1);
pStream->WriteChar(' ');
pStream->WriteReal(dCY1);
pStream->WriteChar(' ');
pStream->WriteReal(dCX2);
pStream->WriteChar(' ');
pStream->WriteReal(dCY2);
pStream->WriteChar(' ');
pStream->WriteReal(dX2);
pStream->WriteChar(' ');
pStream->WriteReal(dY2);
dXCur = dX2;
dYCur = dY2;
}
else
{
pStream->WriteReal(dCX2);
pStream->WriteChar(' ');
pStream->WriteReal(dCY2);
pStream->WriteChar(' ');
pStream->WriteReal(dCX1);
pStream->WriteChar(' ');
pStream->WriteReal(dCY1);
pStream->WriteChar(' ');
pStream->WriteReal(dX1);
pStream->WriteChar(' ');
pStream->WriteReal(dY1);
dXCur = dX1;
dYCur = dY1;
}
pStream->WriteStr(" c\012");
}
//----------------------------------------------------------------------------------------
// CPageTree
//----------------------------------------------------------------------------------------
CPageTree::CPageTree(CXref* pXref)
{
pXref->Add(this);
m_pPages = new CArrayObject();
m_pCount = new CNumberObject(0);
Add("Type", "Pages");
Add("Kids", m_pPages);
Add("Count", m_pCount);
}
void CPageTree::AddPage(CDictObject* pPage)
{
m_pPages->Add(pPage);
(*m_pCount)++;
}
//----------------------------------------------------------------------------------------
// CPage
//----------------------------------------------------------------------------------------
CPage::CPage(CXref* pXref, CPageTree* pParent)
{
pXref->Add(this);
m_pXref = pXref;
m_pContents = new CDictObject(pXref);
m_pStream = m_pContents->GetStream();
m_eGrMode = grmode_PAGE;
m_pGrState = new CGrState(NULL);
m_pExtGStates = NULL;
m_unExtGStatesCount = 0;
m_pFonts = NULL;
m_pFont = NULL;
m_unFontsCount = 0;
m_pXObjects = NULL;
m_unXObjectsCount = 0;
m_pShadings = NULL;
m_unShadingsCount = 0;
m_pPatterns = NULL;
m_unPatternsCount = 0;
Add("Type", "Page");
Add("Parent", pParent);
Add("MediaBox", CArrayObject::CreateBox(0, 0, DEF_PAGE_WIDTH, DEF_PAGE_HEIGHT));
Add("Contents", m_pContents);
AddResource();
}
CPage::~CPage()
{
CGrState* pGrState = m_pGrState, *pPrev = NULL;
while (pGrState)
{
pPrev = m_pGrState->GetPrev();
delete pGrState;
pGrState = pPrev;
}
}
void CPage::SetWidth(double dValue)
{
dValue = min(max(dValue, 1), 14400);
SetMediaBoxValue(2, dValue);
}
double CPage::GetWidth()
{
return GetMediaBox().fRight;
}
void CPage::SetHeight(double dValue)
{
dValue = min(max(dValue, 1), 14400);
SetMediaBoxValue(3, dValue);
}
double CPage::GetHeight()
{
return GetMediaBox().fTop;
}
TBox CPage::GetMediaBox()
{
TBox oMediaBox ={ 0, 0, 0, 0 };
CArrayObject* pArray = GetMediaBoxItem();
if (pArray)
{
CRealObject* pReal;
pReal = (CRealObject*)pArray->Get(0);
if (pReal)
oMediaBox.fLeft = pReal->Get();
pReal = (CRealObject*)pArray->Get(1);
if (pReal)
oMediaBox.fBottom = pReal->Get();
pReal = (CRealObject*)pArray->Get(2);
if (pReal)
oMediaBox.fRight = pReal->Get();
pReal = (CRealObject*)pArray->Get(3);
if (pReal)
oMediaBox.fTop = pReal->Get();
}
return oMediaBox;
}
void CPage::SetMediaBoxValue(unsigned int unIndex, double dValue)
{
CArrayObject* pArray = GetMediaBoxItem();
if (!pArray)
return;
CRealObject* pReal = (CRealObject*)pArray->Get(unIndex);
if (!pReal)
return;
pReal->Set(dValue);
}
CArrayObject* CPage::GetMediaBoxItem()
{
return (CArrayObject*)Get("MediaBox");
}
CDictObject* CPage::GetResourcesItem()
{
CObjectBase* pObject = Get("Resources");
// Если объект Resources нулевой, тогда ищем Resources у родительского объекта рекурсивно
if (!pObject)
{
CPageTree* pPageTree = (CPageTree*)Get("Parent");
while (pPageTree)
{
pObject = Get("Resources");
if (pObject)
break;
pPageTree = (CPageTree*)pPageTree->Get("Parent");
}
}
return (CDictObject*)pObject;
}
CObjectBase* CPage::GetCropBoxItem()
{
return Get("CropBox");
}
CObjectBase* CPage::GetRotateItem()
{
return Get("Rotate");
}
void CPage::AddResource()
{
CDictObject* pResource = new CDictObject();
if (!pResource)
return;
// Не смотря на то, что ProcSet - устаревший объект, добавляем
// его для совместимости
Add("Resources", pResource);
CArrayObject* pProcset = new CArrayObject();
if (!pProcset)
return;
pResource->Add("ProcSet", pProcset);
pProcset->Add(new CNameObject("PDF"));
pProcset->Add(new CNameObject("Text"));
pProcset->Add(new CNameObject("ImageB"));
pProcset->Add(new CNameObject("ImageC"));
pProcset->Add(new CNameObject("ImageI"));
}
void CPage::BeforeWrite()
{
if (grmode_PATH == m_eGrMode)
EndPath();
if (grmode_TEXT == m_eGrMode)
EndText();
while (m_pGrState->GetPrev())
{
GrRestore();
}
}
void CPage::SetGrMode(EGrMode eMode)
{
m_eGrMode = eMode;
// TODO: Сделать проверку плохих ситуаций
}
void CPage::CheckGrMode(EGrMode eMode)
{
// TODO: Сделать проверку плохих ситуаций
}
void CPage::MoveTo (double dX, double dY)
{
// Operator : m
// Description: Начинаем новый subpath, передвигая текущий указатель в точку (x, y)(она же стартовая).
SetGrMode(grmode_PATH);
m_pStream->WriteReal(dX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dY);
m_pStream->WriteStr(" m\012");
m_oCurPos.Set(dX, dY);
m_oStartPos = m_oCurPos;
}
void CPage::LineTo (double dX, double dY)
{
// Operator : l
// Description: Добавляем линию от текущей точки до точки (x, y). Текущую точку выставляем (х, у).
CheckGrMode(grmode_PATH);
m_pStream->WriteReal(dX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dY);
m_pStream->WriteStr(" l\012");
m_oCurPos.Set(dX, dY);
}
void CPage::CurveTo(double dX1, double dY1, double dX2, double dY2, double dX3, double dY3)
{
// Operator : c
// Description: Добавляем кривую Безье(кубическую). Начинается кривая в текущей позиции, заканчивается
// в точке (x3, y3). (x1, y1) и (x2, y2) - контрольные точки. Текущую точку устанавливаем
// в (х3, у3).
CheckGrMode(grmode_PATH);
m_pStream->WriteReal(dX1);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dY1);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dX2);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dY2);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dX3);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dY3);
m_pStream->WriteStr(" c\012");
m_oCurPos.Set(dX3, dY3);
}
void CPage::Ellipse(double dX, double dY, double dXRay, double dYRay)
{
SetGrMode(grmode_PATH);
m_pStream->WriteReal(dX - dXRay);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dY);
m_pStream->WriteStr(" m\012");
QuarterEllipseA(m_pStream, dX, dY, dXRay, dYRay);
QuarterEllipseB(m_pStream, dX, dY, dXRay, dYRay);
QuarterEllipseC(m_pStream, dX, dY, dXRay, dYRay);
QuarterEllipseD(m_pStream, dX, dY, dXRay, dYRay);
m_oCurPos.Set(dX - dXRay, dY);
m_oStartPos = m_oCurPos;
}
void CPage::EllipseArc(double dX, double dY, double dXRad, double dYRad, double _dAngle1, double _dAngle2, bool bClockDirection)
{
CheckGrMode(grmode_PATH);
// переведем углы в радианы
double dAngle1 = _dAngle1 * 3.141592f / 180;
double dAngle2 = _dAngle2 * 3.141592f / 180;
// Выясним в каких четвертях находятся начальная и конечная точки
int nFirstPointQuard = int(_dAngle1) / 90 + 1;
int nSecondPointQuard = int(_dAngle2) / 90 + 1;
nSecondPointQuard = min(4, max(1, nSecondPointQuard));
nFirstPointQuard = min(4, max(1, nFirstPointQuard));
// Проведем линию в начальную точку дуги
double dStartX = 0.0, dStartY = 0.0, dEndX = 0.0, dEndY = 0.0;
dStartX = dX + dXRad * cos(AngToEllPrm(dAngle1, dXRad, dYRad));
dStartY = dY + dYRad * sin(AngToEllPrm(dAngle1, dXRad, dYRad));
m_pStream->WriteReal(dStartX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dStartY);
m_pStream->WriteStr(" l\012");
// Дальше рисуем по четверям
double dCurX = dStartX, dCurY = dStartY;
double dStartAngle = dAngle1;
double dEndAngle = 0;
if ( !bClockDirection )
{
for (unsigned int nIndex = nFirstPointQuard; nIndex <= nSecondPointQuard; nIndex++)
{
if (nIndex == nSecondPointQuard)
dEndAngle = dAngle2;
else
dEndAngle = (90 * (nIndex)) * 3.141592f / 180;
if (!(nIndex == nFirstPointQuard))
dStartAngle = (90 * (nIndex - 1)) * 3.141592f / 180;
WriteEllipseArc(m_pStream, dX, dY, dXRad, dYRad, AngToEllPrm(dStartAngle, dXRad, dYRad), AngToEllPrm(dEndAngle, dXRad, dYRad), dEndX, dEndY, false);
}
}
else
{
for( unsigned int nIndex = nFirstPointQuard; nIndex >= nSecondPointQuard; nIndex-- )
{
if ( nIndex == nFirstPointQuard )
dStartAngle = dAngle1;
else
dStartAngle = (90 * (nIndex ) ) * 3.141592f / 180;
if ( !( nIndex == nSecondPointQuard ) )
dEndAngle = (90 * (nIndex - 1 ) ) * 3.141592f / 180;
else
dEndAngle = dAngle2;
WriteEllipseArc(m_pStream, dX, dY, dXRad, dYRad, AngToEllPrm(dStartAngle, dXRad, dYRad), AngToEllPrm(dEndAngle, dXRad, dYRad), dEndX, dEndY, false);
}
}
m_oCurPos.Set(dEndX, dEndY);
m_oStartPos = m_oCurPos;
}
void CPage::EllipseArcTo(double dX, double dY, double dXRad, double dYRad, double _dAngle1, double _dAngle2, bool bClockDirection)
{
// Проверяем эллипс на невырожденность
if (dXRad < 0.001 || dYRad < 0.001)
{
double dAngle1 = _dAngle1 * 3.141592f / 180;
double dAngle2 = _dAngle2 * 3.141592f / 180;
if (dXRad < 0.001 && dYRad < 0.001)
LineTo(dX, dY);
else if (dXRad < 0.001)
{
LineTo(dX, dY + sin(dAngle1) * dYRad);
LineTo(dX, dY + sin(dAngle2) * dYRad);
}
else // if (dYRad < 0.001)
{
LineTo(dX + cos(dAngle1) * dXRad, dY);
LineTo(dX + cos(dAngle2) * dXRad, dY);
}
return;
}
while (_dAngle1 < 0)
_dAngle1 += 360;
while (_dAngle1 > 360)
_dAngle1 -= 360;
while (_dAngle2 < 0)
_dAngle2 += 360;
while (_dAngle2 >= 360)
_dAngle2 -= 360;
if (!bClockDirection)
{
if (_dAngle1 <= _dAngle2)
EllipseArc(dX, dY, dXRad, dYRad, _dAngle1, _dAngle2, false);
else
{
EllipseArc(dX, dY, dXRad, dYRad, _dAngle1, 360, false);
EllipseArc(dX, dY, dXRad, dYRad, 0, _dAngle2, false);
}
}
else
{
if (_dAngle1 >= _dAngle2)
EllipseArc(dX, dY, dXRad, dYRad, _dAngle1, _dAngle2, true);
else
{
EllipseArc(dX, dY, dXRad, dYRad, _dAngle1, 0, true);
EllipseArc(dX, dY, dXRad, dYRad, 360, _dAngle2, true);
}
}
}
void CPage::ClosePath()
{
// Operator : h
// Description: Закрываем subpath, соединяя текущую точку с начальной прямой линией. Если subpath
// уже закрыт, тогда ничего не делаем
CheckGrMode(grmode_PATH);
m_pStream->WriteStr("h\012");
m_oCurPos = m_oStartPos;
}
void CPage::Stroke()
{
// Operator : S
// Description: Обводим path.
SetGrMode(grmode_PAGE);
m_pStream->WriteStr("S\012");
m_oCurPos.Reset();
}
void CPage::Fill()
{
// Operator : f
// Description: Заливка path по правилу Nonzero Winding Number Rule(см. спецификацию PDF Part1: PDF 1.7
// стр. 136, закладка 8.5.3.3.2).
SetGrMode(grmode_PAGE);
m_pStream->WriteStr("f\012");
m_oCurPos.Reset();
}
void CPage::EoFill()
{
// Operator : f*
// Description: Заливка path по правилу Even-Odd Rule(см. спецификацию PDF Part1: PDF 1.7 стр. 137,
// закладка 8.5.3.3.3).
SetGrMode(grmode_PAGE);
m_pStream->WriteStr("f*\012");
m_oCurPos.Reset();
}
void CPage::FillStroke()
{
// Operator : B
// Description: Заливка и обоводка path, используя правило для заливки Nonzero Winding Number Rule(см.
// спецификацию PDF Part1: PDF 1.7 стр. 136, закладка 8.5.3.3.2). Этот оператор должен
// привести к тому же самому результату как строительство двух идентичных объектов path,
// применяя к первому оператор f и ко второму - S.
SetGrMode(grmode_PAGE);
m_pStream->WriteStr("B\012");
m_oCurPos.Reset();
}
void CPage::EoFillStroke()
{
// Operator : B*
// Description: Заливка и обоводка path, используя правило для заливки Even-Odd Rule(см.
// спецификацию PDF Part1: PDF 1.7 стр. 137, закладка 8.5.3.3.3). Этот оператор должен
// привести к тому же самому результату как строительство двух идентичных объектов path,
// применяя к первому оператор f* и ко второму - S.
SetGrMode(grmode_PAGE);
m_pStream->WriteStr("B*\012");
m_oCurPos.Reset();
}
void CPage::EndPath()
{
// Operator : n
// Description: Закрываем path, не заливая и не обводя его. Этот оператор используется прежде всего для
// изменения текущего path.
SetGrMode(grmode_PAGE);
m_pStream->WriteStr("n\012");
m_oCurPos.Reset();
}
void CPage::SetLineWidth(double dLineWidth)
{
// Operator : w
// Descriprion: устанавливаем толщину линии
dLineWidth = max(dLineWidth, 0);
m_pStream->WriteReal(dLineWidth);
m_pStream->WriteStr(" w\012");
m_pGrState->m_dLineWidth = dLineWidth;
}
void CPage::SetLineCap(ELineCapStyle eLineCap)
{
// Operator : J
// Descriprion: устанавливаем вид окончания линии (LineCapStyle)
eLineCap = max(linecap_Min, min(linecap_Max, eLineCap));
m_pStream->WriteInt((unsigned int)eLineCap);
m_pStream->WriteStr(" J\012");
m_pGrState->m_eLineCap = eLineCap;
}
void CPage::SetLineJoin(ELineJoinStyle eLineJoin)
{
// Operator : j
// Descriprion: устанавливаем вид соединения линий (LineJoinStyle)
eLineJoin = max(linejoin_Min, min(linejoin_Max, eLineJoin));
m_pStream->WriteInt((unsigned int)eLineJoin);
m_pStream->WriteStr(" j\012");
m_pGrState->m_eLineJoin = eLineJoin;
}
void CPage::SetMiterLimit(double dMiterLimit)
{
// Operator : M
// Descriprion: устанавливаем MiterLimit - константа, относящаяся к виду соединения линий
dMiterLimit = max(1, dMiterLimit);
m_pStream->WriteReal(dMiterLimit);
m_pStream->WriteStr(" M\012");
m_pGrState->m_dMiterLimit = dMiterLimit;
}
void CPage::SetDash(const double* pPattern, unsigned int unCount, double dPhase)
{
// Operator : d
// Descriprion: устанавливаем вид линий (DashMode)
if (0 == unCount || !pPattern)
return;
bool bFalseDash = true;
for (unsigned int unIndex = 0; unIndex < unCount; unIndex++)
{
if (0 != pPattern[unIndex])
{
bFalseDash = false;
break;
}
}
if (bFalseDash)
return;
m_pStream->WriteChar('[');
for (unsigned int unIndex = 0; unIndex < unCount; unIndex++)
{
m_pStream->WriteReal(pPattern[unIndex]);
m_pStream->WriteChar(' ');
}
m_pStream->WriteStr("] ");
m_pStream->WriteReal(dPhase);
m_pStream->WriteStr(" d\012");
m_pGrState->m_oDashMode.Set(pPattern, unCount, dPhase);
}
void CPage::SetFlat(double dFlatness)
{
// Operator : i
// Descriprion: устанавливаем порог ошибки линии (Flatness tolerance)
dFlatness = min(100, max(0, dFlatness));
m_pStream->WriteReal(dFlatness);
m_pStream->WriteStr(" i\012");
m_pGrState->m_dFlatness = dFlatness;
}
void CPage::GrSave()
{
// Operator : q
// Description: сохраняем текущий GState в графическом стеке
CheckGrMode(grmode_PAGE);
CGrState* pState = new CGrState(m_pGrState);
if (!pState)
return;
m_pStream->WriteStr("q\012");
m_pGrState = pState;
}
void CPage::GrRestore()
{
// Operator : Q
// Description: Восстанавливаем GState, удаляя самый последний GState, и делаем данный GState текущим
CheckGrMode(grmode_PAGE);
if (!m_pGrState->m_pPrev)
return;
CGrState* pPrev = m_pGrState->m_pPrev;
delete m_pGrState;
m_pGrState = pPrev;
m_pStream->WriteStr("Q\012");
}
void CPage::SetStrokeColor(unsigned char unR, unsigned char unG, unsigned char unB)
{
// Operator : RG
// Description: Устанавливаем цветовое пространтсво для обводки в DeviceRGB и устанавливаем цвет для
// операций связанных с обведением фигур.
double dR = unR / 255.0;
double dG = unG / 255.0;
double dB = unB / 255.0;
m_pStream->WriteReal(dR);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dG);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dB);
m_pStream->WriteStr(" RG\012");
m_pGrState->m_oStrokeColor.r = dR;
m_pGrState->m_oStrokeColor.g = dG;
m_pGrState->m_oStrokeColor.b = dB;
}
void CPage::SetFillColor(unsigned char unR, unsigned char unG, unsigned char unB)
{
// Operator : rg
// Description: Устанавливаем цветовое пространтсво для заливки в DeviceRGB и устанавливаем цвет для
// операций связанных с заливкой фигур.
double dR = unR / 255.0;
double dG = unG / 255.0;
double dB = unB / 255.0;
m_pStream->WriteReal(dR);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dG);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dB);
m_pStream->WriteStr(" rg\012");
m_pGrState->m_oFillColor.r = dR;
m_pGrState->m_oFillColor.g = dG;
m_pGrState->m_oFillColor.b = dB;
}
void CPage::Concat(double dM11, double dM12, double dM21, double dM22, double dX, double dY)
{
// Operator : cm
// Description: меняем матрицу преобразований (CTM - Current Transformation Matrix)
m_pStream->WriteReal(dM11);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dM12);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dM21);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dM22);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dY);
m_pStream->WriteStr(" cm\012");
CMatrix oCTM = m_pGrState->m_oMatrix;
// перемножаем матрицы oCTM(новая)= oCTM(преобразования(которая параметрами задана)) x oCTM(старая)
m_pGrState->m_oMatrix.m11 = oCTM.m11 * dM11 + oCTM.m12 * dM21;
m_pGrState->m_oMatrix.m12 = oCTM.m11 * dM12 + oCTM.m12 * dM22;
m_pGrState->m_oMatrix.m21 = oCTM.m21 * dM11 + oCTM.m22 * dM21;
m_pGrState->m_oMatrix.m22 = oCTM.m21 * dM12 + oCTM.m22 * dM22;
m_pGrState->m_oMatrix.x = oCTM.x + dX * oCTM.m11 + dY * oCTM.m21;
m_pGrState->m_oMatrix.y = oCTM.y + dX * oCTM.m12 + dY * oCTM.m22;
}
void CPage::Clip()
{
// Operator : W
// Description: Изменяем текущий clipping path, пересакая его с текущим path, ипользуя правило Nonzero
// Winding Number Rule, для определения какие регионы лежат внутри clipping path.
SetGrMode(grmode_CLIP);
m_pStream->WriteStr("W\012");
}
void CPage::Eoclip()
{
// Operator : W*
// Description: Изменяем текущий clipping path, пересакая его с текущим path, ипользуя правило Even-Odd
// Rule, для определения какие регионы лежат внутри clipping path.
SetGrMode(grmode_CLIP);
m_pStream->WriteStr("W*\012");
}
void CPage::SetExtGrState(CExtGrState* pState)
{
// Operator : gs
// Description: устанавливаем сразу все настройки данного графического состояния(ExtGState)
const char* sGsName = GetExtGrStateName(pState);
if (!sGsName)
return;
m_pStream->WriteEscapeName(sGsName);
m_pStream->WriteStr(" gs\012");
}
const char* CPage::GetExtGrStateName(CExtGrState* pState)
{
const char *sKey;
if (!m_pExtGStates)
{
CDictObject* pResources = (CDictObject*)GetResourcesItem();
if (!pResources)
return NULL;
m_pExtGStates = new CDictObject();
if (!m_pExtGStates)
return NULL;
pResources->Add("ExtGState", m_pExtGStates);
}
sKey = m_pExtGStates->GetKey(pState);
if (!sKey)
{
// Если ExtGState не зарегистрирован в Resource, регистрируем.
char sExtGrStateName[LIMIT_MAX_NAME_LEN + 1];
char *pPointer;
char *pEndPointer = sExtGrStateName + LIMIT_MAX_NAME_LEN;
pPointer = (char*)StrCpy(sExtGrStateName, "E", pEndPointer);
ItoA(pPointer, m_unCompressionMode + 1, pEndPointer);
m_unCompressionMode++;
m_pExtGStates->Add(sExtGrStateName, pState);
sKey = m_pExtGStates->GetKey(pState);
}
return sKey;
}
void CPage::AddAnnotation(CAnnotation* pAnnot)
{
CArrayObject* pArray = (CArrayObject*)Get("Annots");
if (!pArray)
{
pArray = new CArrayObject();
if (!pArray)
return;
Add("Annots", pArray);
}
return pArray->Add(pAnnot);
}
void CPage::BeginText()
{
// Operator : BT
// Description: Начало текста
SetGrMode(grmode_TEXT);
m_pStream->WriteStr("BT\012");
m_oTextPos.Reset();
m_oTextMatrix.Reset();
}
void CPage::EndText()
{
// Operator : ET
// Description: Окончание текста
CheckGrMode(grmode_TEXT);
m_pStream->WriteStr("ET\012");
SetGrMode(grmode_PAGE);
}
void CPage::MoveTextPos(double dX, double dY)
{
// Operator : Td
// Description: Переходим к началу следующей линии, сдвигаясь от начала текущей на ( fX, fY ).
CheckGrMode(grmode_TEXT);
m_pStream->WriteReal(dX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dY);
m_pStream->WriteStr(" Td\012");
m_oTextMatrix.x += dX * m_oTextMatrix.m11 + dY * m_oTextMatrix.m21;
m_oTextMatrix.y += dX * m_oTextMatrix.m12 + dY * m_oTextMatrix.m22;
m_oTextPos.Set(m_oTextMatrix.x, m_oTextMatrix.y);
}
void CPage::ShowText(const BYTE* sText, unsigned int unLen)
{
// Operator : Tj
// Description: Показать текстовую строку.
CheckGrMode(grmode_TEXT);
WriteText(sText, unLen);
m_pStream->WriteStr(" Tj\012");
}
void CPage::WriteText(const BYTE* sText, unsigned int unLen)
{
EFontType eType = m_pFont->GetFontType();
if (fontCIDType0 == eType || fontCIDType0C == eType || fontCIDType0COT == eType || fontCIDType2 == eType || fontCIDType2OT == eType)
{
m_pStream->WriteChar('<');
m_pStream->WriteBinary(sText, unLen, NULL);
m_pStream->WriteChar('>');
}
else
{
m_pStream->WriteEscapeText(sText, unLen);
}
}
void CPage::DrawText(double dXpos, double dYpos, const BYTE* sText, unsigned int unLen)
{
CheckGrMode(grmode_TEXT);
double dX = 0.0;
double dY = 0.0;
if (0 == m_oTextMatrix.m11)
{
dY = (dXpos - m_oTextMatrix.x) / m_oTextMatrix.m21;
dX = (dYpos - m_oTextMatrix.y - (dXpos - m_oTextMatrix.x) * m_oTextMatrix.m22 / m_oTextMatrix.m21) / m_oTextMatrix.m12;
}
else
{
dY = (dYpos - m_oTextMatrix.y - (dXpos - m_oTextMatrix.x) * m_oTextMatrix.m12 / m_oTextMatrix.m11) / (m_oTextMatrix.m22 - m_oTextMatrix.m21 * m_oTextMatrix.m12 / m_oTextMatrix.m11);
dX = (dXpos - m_oTextMatrix.x - dY * m_oTextMatrix.m21) / m_oTextMatrix.m11;
}
MoveTextPos(dX, dY);
ShowText(sText, unLen);
}
void CPage::SetCharSpace(double dValue)
{
// Operator : Tc
// Description: Устанавливаем расстояние между буквами
CheckGrMode(grmode_TEXT);
dValue = min(MAX_CHARSPACE, max(MIN_CHARSPACE, dValue));
m_pStream->WriteReal(dValue);
m_pStream->WriteStr(" Tc\012");
}
void CPage::SetHorizontalScalling(double dValue)
{
// Operator : Tz
// Description: Устанавливаем горизонтальное растяжение/сжатие
CheckGrMode(grmode_TEXT);
dValue = min(MAX_HORIZONTALSCALING, max(MIN_HORIZONTALSCALING, dValue));
m_pStream->WriteReal(dValue);
m_pStream->WriteStr(" Tz\012");
}
void CPage::SetFontAndSize(CFontDict* pFont, double dSize)
{
// Operator : Tf
// Description: Устанавливаем фонт и размер фонта
dSize = min(MAX_FONTSIZE, max(0, dSize));
const char* sFontName = GetLocalFontName(pFont);
if (!sFontName)
return;
m_pStream->WriteEscapeName(sFontName);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dSize);
m_pStream->WriteStr(" Tf\012");
m_pFont = pFont;
}
const char* CPage::GetLocalFontName(CFontDict* pFont)
{
if (!m_pFonts)
{
CDictObject* pResources = GetResourcesItem();
if (!pResources)
return NULL;
m_pFonts = new CDictObject();
if (!m_pFonts)
return NULL;
pResources->Add("Font", m_pFonts);
}
const char *sKey = m_pFonts->GetKey(pFont);
if (!sKey)
{
// если фонт не зарегистрирован в ресурсах, тогда регистрируем его
char sFontName[LIMIT_MAX_NAME_LEN + 1];
char *pPointer = NULL;
char *pEndPointer = sFontName + LIMIT_MAX_NAME_LEN;
pPointer = (char*)StrCpy(sFontName, "F", pEndPointer);
ItoA(pPointer, m_unFontsCount + 1, pEndPointer);
m_unFontsCount++;
m_pFonts->Add(sFontName, pFont);
sKey = m_pFonts->GetKey(pFont);
}
return sKey;
}
void CPage::SetTextRenderingMode(ETextRenderingMode eMode)
{
// Operator : Tr
// Description: Устанавливаем тип закрашивания символов (TextRenderingMode)
CheckGrMode(grmode_TEXT);
m_pStream->WriteInt((int)eMode);
m_pStream->WriteStr(" Tr\012");
}
void CPage::SetTextMatrix(double dM11, double dM12, double dM21, double dM22, double dX, double dY)
{
// Operator : Tm
// Description: Устанавливаем матрицу преобразования для текста.
CheckGrMode(grmode_TEXT);
m_pStream->WriteReal(dM11);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dM12);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dM21);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dM22);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dY);
m_pStream->WriteStr(" Tm\012");
m_oTextMatrix.m11 = dM11;
m_oTextMatrix.m12 = dM12;
m_oTextMatrix.m21 = dM21;
m_oTextMatrix.m22 = dM22;
m_oTextMatrix.x = dX;
m_oTextMatrix.y = dY;
m_oTextPos.Set(m_oTextMatrix.x, m_oTextMatrix.y);
}
void CPage::ExecuteXObject(CXObject* pXObject)
{
const char* sXObjectName = GetXObjectName(pXObject);
if (!sXObjectName)
return;
m_pStream->WriteEscapeName(sXObjectName);
m_pStream->WriteStr(" Do\012");
}
void CPage::DrawImage(CImageDict* pImage, double dX, double dY, double dWidth, double dHeight)
{
GrSave();
Concat(dWidth, 0, 0, dHeight, dX, dY);
ExecuteXObject(pImage);
GrRestore();
}
const char* CPage::GetXObjectName(CXObject* pObject)
{
if (!m_pXObjects)
{
CDictObject* pResources = GetResourcesItem();
if (!pResources)
return NULL;
m_pXObjects = new CDictObject();
if (!m_pXObjects)
return NULL;
pResources->Add("XObject", m_pXObjects);
}
const char* sKey = m_pXObjects->GetKey(pObject);
if (!sKey)
{
char sXObjName[LIMIT_MAX_NAME_LEN + 1];
char *pPointer;
char *pEndPointer = sXObjName + LIMIT_MAX_NAME_LEN;
pPointer = (char*)StrCpy(sXObjName, "X", pEndPointer);
ItoA(pPointer, m_unXObjectsCount + 1, pEndPointer);
m_unXObjectsCount++;
m_pXObjects->Add(sXObjName, pObject);
sKey = m_pXObjects->GetKey(pObject);
}
return sKey;
}
void CPage::DrawShading(CShading* pShading)
{
// Operator : sh
// Description: отрисовываем градиент
const char* sShadingName = GetLocalShadingName(pShading);
if (!sShadingName)
return;
m_pStream->WriteEscapeName(sShadingName);
m_pStream->WriteStr(" sh\012");
}
const char* CPage::GetLocalShadingName(CShading* pShading)
{
if (!m_pShadings)
{
CDictObject* pResources = GetResourcesItem();
if (!pResources)
return NULL;
m_pShadings = new CDictObject();
if (!m_pShadings)
return NULL;
pResources->Add("Shading", m_pShadings);
}
const char* sKey = m_pShadings->GetKey(pShading);
if (!sKey)
{
char sShadingName[LIMIT_MAX_NAME_LEN + 1];
char *pPointer;
char *pEndPointer = sShadingName + LIMIT_MAX_NAME_LEN;
pPointer = (char*)StrCpy(sShadingName, "S", pEndPointer);
ItoA(pPointer, m_unShadingsCount + 1, pEndPointer);
m_unShadingsCount++;
m_pShadings->Add(sShadingName, pShading);
sKey = m_pShadings->GetKey(pShading);
}
return sKey;
}
const char* CPage::GetLocalPatternName(CImageTilePattern* pPattern)
{
if (!m_pPatterns)
{
CDictObject* pResources = GetResourcesItem();
if (!pResources)
return NULL;
m_pPatterns = new CDictObject();
if (!m_pPatterns)
return NULL;
pResources->Add("Pattern", m_pPatterns);
}
const char* sKey = m_pPatterns->GetKey(pPattern);
if (!sKey)
{
char sPatternName[LIMIT_MAX_NAME_LEN + 1];
char *pPointer;
char *pEndPointer = sPatternName + LIMIT_MAX_NAME_LEN;
pPointer = (char*)StrCpy(sPatternName, "P", pEndPointer);
ItoA(pPointer, m_unPatternsCount + 1, pEndPointer);
m_unPatternsCount++;
m_pPatterns->Add(sPatternName, pPattern);
sKey = m_pPatterns->GetKey(pPattern);
}
return sKey;
}
void CPage::SetPatternColorSpace(CImageTilePattern* pPattern)
{
// Operator : csn
// Description: задаем паттерн для рисования
const char* sPatternName = GetLocalPatternName(pPattern);
if (!sPatternName)
return;
m_pStream->WriteStr("/Pattern cs\012");
m_pStream->WriteEscapeName(sPatternName);
m_pStream->WriteStr(" scn\012");
}
}
\ No newline at end of file
#ifndef _PDF_WRITER_SRC_PAGES_H
#define _PDF_WRITER_SRC_PAGES_H
#include "Objects.h"
#ifdef DrawText
#undef DrawText
#endif
namespace PdfWriter
{
class CXref;
class CGrState;
class CExtGrState;
class CAnnotation;
class CFontDict;
class CXObject;
class CImageDict;
class CShading;
class CImageTilePattern;
//----------------------------------------------------------------------------------------
// CPageTree
//----------------------------------------------------------------------------------------
class CPageTree : public CDictObject
{
public:
CPageTree(CXref* pXref);
void AddPage(CDictObject* pPage);
EDictType GetDictType() const
{
return dict_type_PAGES;
}
private:
CNumberObject* m_pCount;
CArrayObject* m_pPages;
};
//----------------------------------------------------------------------------------------
// CPage
//----------------------------------------------------------------------------------------
class CPage : public CDictObject
{
public:
CPage(CXref* pXref, CPageTree* pParent);
~CPage();
void SetHeight(double dHeight);
void SetWidth(double dWidth);
double GetWidth();
double GetHeight();
EDictType GetDictType() const
{
return dict_type_PAGE;
}
void BeforeWrite();
void MoveTo(double dX, double dY);
void LineTo(double dX, double dY);
void CurveTo(double dX1, double dY1, double dX2, double dY2, double dXe, double dYe);
void Ellipse(double dX, double dY, double dXRay, double dYRay);
void EllipseArcTo(double dX, double dY, double dXRad, double dYRad, double dAngle1, double dAngle2, bool bClockDirection = false);
void ClosePath();
void Stroke();
void Fill();
void EoFill();
void FillStroke();
void EoFillStroke();
void EndPath();
void Clip();
void Eoclip();
void SetLineWidth(double dLineWidth);
void SetLineCap(ELineCapStyle eLineCap);
void SetLineJoin(ELineJoinStyle eLineJoin);
void SetMiterLimit(double dMiterLimit);
void SetDash(const double* pPattern, unsigned int unCount, double dPhase);
void SetFlat(double dFlatness);
void GrSave();
void GrRestore();
void SetStrokeColor(unsigned char unR, unsigned char unG, unsigned char unB);
void SetFillColor(unsigned char unR, unsigned char unG, unsigned char unB);
void Concat(double dM11, double dM12, double dM21, double dM22, double dX, double dY);
void SetExtGrState(CExtGrState* pExtGrState);
void AddAnnotation(CAnnotation* pAnnot);
void DrawShading(CShading* pShading);
void BeginText();
void EndText();
void MoveTextPos(double dX, double dY);
void ShowText(const BYTE* sText, unsigned int unLen);
void DrawText(double dX, double dY, const BYTE* sText, unsigned int unLen);
void SetCharSpace(double dValue);
void SetHorizontalScalling(double dValue);
void SetFontAndSize(CFontDict* pFont, double dSize);
void SetTextRenderingMode(ETextRenderingMode eMode);
void SetTextMatrix(double dM11, double dM12, double dM21, double dM22, double dX, double dY);
void ExecuteXObject(CXObject* pXObject);
void DrawImage(CImageDict* pImage, double dX, double dY, double dWidth, double dHeight);
void SetPatternColorSpace(CImageTilePattern* pPattern);
private:
void EllipseArc(double dX, double dY, double dXRad, double dYRad, double dAngle1, double dAngle2, bool bClockDirection);
CArrayObject* GetMediaBoxItem();
CDictObject* GetResourcesItem();
CObjectBase* GetCropBoxItem();
CObjectBase* GetRotateItem();
TBox GetMediaBox();
void SetMediaBoxValue(unsigned int unIndex, double dValue);
void AddResource();
void SetGrMode(EGrMode eMode);
void CheckGrMode(EGrMode eMode);
void WriteText(const BYTE* sText, unsigned int unLen);
const char* GetExtGrStateName(CExtGrState* pState);
const char* GetLocalFontName(CFontDict* pFont);
const char* GetXObjectName(CXObject* pObject);
const char* GetLocalShadingName(CShading* pShading);
const char* GetLocalPatternName(CImageTilePattern* pPattern);
private:
CPageTree* m_pParent;
CXref* m_pXref;
CPoint m_oStartPos; // Позиция начала текущего пата
CPoint m_oCurPos; // Текущая позиция пата
CPoint m_oTextPos; // Текущая позиция текста
CMatrix m_oTextMatrix;
CDictObject* m_pContents;
CStream* m_pStream;
unsigned int m_unCompressionMode;
CDictObject* m_pExtGStates;
unsigned int m_unExtGStatesCount;
EGrMode m_eGrMode;
CGrState* m_pGrState;
CDictObject* m_pFonts;
unsigned int m_unFontsCount;
CFontDict* m_pFont; // Текущий шрифт
CDictObject* m_pXObjects;
unsigned int m_unXObjectsCount;
CDictObject* m_pShadings;
unsigned int m_unShadingsCount;
CDictObject* m_pPatterns;
unsigned int m_unPatternsCount;
};
}
#endif // _PDF_WRITER_SRC_PAGES_H
#include "Pattern.h"
#include "Image.h"
#include "Streams.h"
namespace PdfWriter
{
//----------------------------------------------------------------------------------------
// CImageTilePattern
//----------------------------------------------------------------------------------------
CImageTilePattern::CImageTilePattern(CXref* pXref, double dW, double dH, CImageDict* pImageDict, EImageTilePatternType eType) : CDictObject(pXref, true)
{
Add("Type", "Pattern");
Add("PatternType", 1);
Add("PaintType", 1); // Uncolored
Add("TilingType", 1); // No distortion
CDictObject* pResources = new CDictObject();
if (!pResources)
return;
Add("Resources", pResources);
CDictObject* pXObject = new CDictObject();
if (!pXObject)
return;
pResources->Add("XObject", pXObject);
pXObject->Add("X1", pImageDict);
CStream* pStream = GetStream();
if (!pStream)
return;
if (imagetilepatterntype_Default == eType)
{
Add("BBox", CArrayObject::CreateBox(0, 0, dW, dH));
Add("XStep", dW);
Add("YStep", dH);
pStream->WriteReal(dW);
pStream->WriteStr(" 0 0 ");
pStream->WriteReal(dH);
pStream->WriteStr(" 0 0 cm\12");
pStream->WriteStr("/X1 Do\12");
}
else if (imagetilepatterntype_InverseX == eType)
{
Add("BBox", CArrayObject::CreateBox(0, 0, 2 * dW, dH));
Add("XStep", 2 * dW);
Add("YStep", dH);
pStream->WriteStr("q\12");
pStream->WriteReal(dW);
pStream->WriteStr(" 0 0 ");
pStream->WriteReal(dH);
pStream->WriteStr(" 0 0 cm\12");
pStream->WriteStr("/X1 Do\12");
pStream->WriteStr("Q\12");
pStream->WriteReal(-dW);
pStream->WriteStr(" 0 0 ");
pStream->WriteReal(dH);
pStream->WriteStr(" ");
pStream->WriteReal(2 * dW);
pStream->WriteStr(" 0 cm\12");
pStream->WriteStr("/X1 Do\12");
}
else if (imagetilepatterntype_InverseY == eType)
{
Add("BBox", CArrayObject::CreateBox(0, 0, dW, 2 * dH));
Add("XStep", dW);
Add("YStep", 2 * dH);
pStream->WriteStr("q\12");
pStream->WriteReal(dW);
pStream->WriteStr(" 0 0 ");
pStream->WriteReal(dH);
pStream->WriteStr(" 0 0 cm\12");
pStream->WriteStr("/X1 Do\12");
pStream->WriteStr("Q\12");
pStream->WriteReal(dW);
pStream->WriteStr(" 0 0 ");
pStream->WriteReal(-dH);
pStream->WriteStr(" 0 ");
pStream->WriteReal(2 * dH);
pStream->WriteStr(" cm\12");
pStream->WriteStr("/X1 Do\12");
}
else if (imagetilepatterntype_InverseXY == eType)
{
Add("BBox", CArrayObject::CreateBox(0, 0, 2 * dW, 2 * dH));
Add("XStep", 2 * dW);
Add("YStep", 2 * dH);
pStream->WriteStr("q\12");
pStream->WriteReal(dW);
pStream->WriteStr(" 0 0 ");
pStream->WriteReal(dH);
pStream->WriteStr(" 0 0 cm\12");
pStream->WriteStr("/X1 Do\12");
pStream->WriteStr("Q\12");
pStream->WriteStr("q\12");
pStream->WriteReal(dW);
pStream->WriteStr(" 0 0 ");
pStream->WriteReal(-dH);
pStream->WriteStr(" 0 ");
pStream->WriteReal(2 * dH);
pStream->WriteStr(" cm\12");
pStream->WriteStr("/X1 Do\12");
pStream->WriteStr("Q\12");
pStream->WriteStr("q\12");
pStream->WriteReal(-dW);
pStream->WriteStr(" 0 0 ");
pStream->WriteReal(dH);
pStream->WriteStr(" ");
pStream->WriteReal(2 * dW);
pStream->WriteStr(" 0 cm\12");
pStream->WriteStr("/X1 Do\12");
pStream->WriteStr("Q\12");
pStream->WriteReal(-dW);
pStream->WriteStr(" 0 0 ");
pStream->WriteReal(-dH);
pStream->WriteStr(" ");
pStream->WriteReal(2 * dW);
pStream->WriteStr(" ");
pStream->WriteReal(2 * dH);
pStream->WriteStr(" cm\12");
pStream->WriteStr("/X1 Do\12");
}
}
}
\ No newline at end of file
#ifndef _PDF_WRITER_SRC_PATTERN_H
#define _PDF_WRITER_SRC_PATTERN_H
#include "Objects.h"
namespace PdfWriter
{
class CImageDict;
//----------------------------------------------------------------------------------------
// CImageTilePattern
//----------------------------------------------------------------------------------------
class CImageTilePattern : public CDictObject
{
public:
CImageTilePattern(CXref* pXref, double dW, double dH, CImageDict* pImageDict, EImageTilePatternType eType = imagetilepatterntype_Default);
};
}
#endif // _PDF_WRITER_SRC_PATTERN_H
\ No newline at end of file
#include "Shading.h"
namespace PdfWriter
{
//----------------------------------------------------------------------------------------
// CLinearFuntion
//----------------------------------------------------------------------------------------
class CLinearFuntion : public CDictObject
{
public:
CLinearFuntion(CXref* pXref, double* pC0Values, double* pC1Values, int nCount)
{
if (!nCount || !pC0Values || !pC1Values)
return;
pXref->Add(this);
Add("FunctionType", 2);
CArrayObject* pDomain = new CArrayObject();
if (!pDomain)
return;
pDomain->Add(0.0);
pDomain->Add(1.0);
Add("Domain", pDomain);
CArrayObject* pC0Array = new CArrayObject();
if (!pC0Array)
return;
Add("C0", pC0Array);
CArrayObject* pC1Array = new CArrayObject();
if (!pC1Array)
return;
Add("C1", pC1Array);
Add("N", 1);
for (int nIndex = 0; nIndex < nCount; nIndex++)
{
pC0Array->Add(pC0Values[nIndex]);
pC1Array->Add(pC1Values[nIndex]);
}
}
};
//----------------------------------------------------------------------------------------
// CLineSegmentFuntion
//----------------------------------------------------------------------------------------
class CLineSegmentFuntion : public CDictObject
{
public:
CLineSegmentFuntion(CXref* pXref, double** ppValues, double* pPoints, int nFunctionsCount, int nOutputDimension)
{
pXref->Add(this);
Add("FunctionType", 3);
CArrayObject* pDomain = new CArrayObject();
if (!pDomain)
return;
pDomain->Add(0.0);
pDomain->Add(1.0);
Add("Domain", pDomain);
CArrayObject* pFunctions = new CArrayObject();
if (!pFunctions)
return;
Add("Functions", pFunctions);
CArrayObject* pBounds = new CArrayObject();
if (!pBounds)
return;
Add("Bounds", pBounds);
CArrayObject* pEncode = new CArrayObject();
if (!pEncode)
return;
Add("Encode", pEncode);
for (int nFunctionIndex = 0; nFunctionIndex < nFunctionsCount; nFunctionIndex++)
{
CLinearFuntion* pFunc = new CLinearFuntion(pXref, ppValues[2 * nFunctionIndex], ppValues[2 * nFunctionIndex + 1], nOutputDimension);
pFunctions->Add(pFunc);
pEncode->Add(0.0);
pEncode->Add(1.0);
if (nFunctionIndex != nFunctionsCount - 1)
pBounds->Add(pPoints[nFunctionIndex]);
}
}
};
//----------------------------------------------------------------------------------------
// CShading
//----------------------------------------------------------------------------------------
CShading::CShading(CXref* pXref)
{
m_pXref = pXref;
pXref->Add(this);
m_pColors = NULL;
m_pColorsPoints = NULL;
m_nColorsCount = 0;
m_bBeginExtend = false;
m_bEndExtend = false;
}
CShading::~CShading()
{
if (m_pColors)
delete[] m_pColors;
if (m_pColorsPoints)
delete[] m_pColorsPoints;
}
void CShading::SetColors(unsigned char* pColors, double* pPoints, int nCount)
{
if (!pColors || !pPoints || nCount <= 1)
return;
m_pColors = new unsigned char[3 * nCount];
m_pColorsPoints = new double[nCount];
m_nColorsCount = nCount;
if (!m_pColors || !m_pColorsPoints)
return;
for (int nIndex = 0; nIndex < nCount; nIndex++)
{
m_pColors[3 * nIndex + 0] = pColors[3 * nIndex + 0];
m_pColors[3 * nIndex + 1] = pColors[3 * nIndex + 1];
m_pColors[3 * nIndex + 2] = pColors[3 * nIndex + 2];
m_pColorsPoints[nIndex] = pPoints[nIndex];
}
Add("ColorSpace", "DeviceRGB");
CArrayObject* pDomain = new CArrayObject();
if (!pDomain)
return;
pDomain->Add(0.0);
pDomain->Add(1.0);
Add("Domain", pDomain);
if (nCount <= 2)
{
double pC0Values[] ={
pColors[0] / 255.0,
pColors[1] / 255.0,
pColors[2] / 255.0
};
double pC1Values[] ={
pColors[3] / 255.0,
pColors[4] / 255.0,
pColors[5] / 255.0
};
CLinearFuntion* pFunction = new CLinearFuntion(m_pXref, pC0Values, pC1Values, 3);
Add("Function", pFunction);
}
else
{
double** ppValues = new double*[(nCount - 1) * 2];
for (int nIndex = 0; nIndex < nCount - 1; nIndex++)
{
ppValues[2 * nIndex + 0] = new double[3];
ppValues[2 * nIndex + 1] = new double[3];
ppValues[2 * nIndex + 0][0] = pColors[3 * nIndex + 0] / 255.0;
ppValues[2 * nIndex + 0][1] = pColors[3 * nIndex + 1] / 255.0;
ppValues[2 * nIndex + 0][2] = pColors[3 * nIndex + 2] / 255.0;
ppValues[2 * nIndex + 1][0] = pColors[3 * (nIndex + 1) + 0] / 255.0;
ppValues[2 * nIndex + 1][1] = pColors[3 * (nIndex + 1) + 1] / 255.0;
ppValues[2 * nIndex + 1][2] = pColors[3 * (nIndex + 1) + 2] / 255.0;
}
CLineSegmentFuntion* pFunction = new CLineSegmentFuntion(m_pXref, ppValues, pPoints + 1, nCount - 1, 3);
Add("Function", pFunction);
for (int nIndex = 0; nIndex < nCount - 1; nIndex++)
{
delete[] ppValues[2 * nIndex + 0];
delete[] ppValues[2 * nIndex + 1];
}
delete[] ppValues;
}
}
void CShading::SetExtend(bool bBegin, bool bEnd)
{
CArrayObject* pExtend = new CArrayObject();
if (!pExtend)
return;
pExtend->Add(bBegin);
pExtend->Add(bEnd);
Add("Extend", pExtend);
m_bBeginExtend = bBegin;
m_bEndExtend = bEnd;
}
bool CShading::CompareColors(unsigned char* pColors, double* pPoints, int nCount)
{
if (nCount != m_nColorsCount
|| (pColors && !m_pColors)
|| (pPoints && !m_pColorsPoints)
|| (!pColors && m_pColors)
|| (!pPoints && m_pColorsPoints))
return false;
for (int nIndex = 0; nIndex < nCount; nIndex++)
{
if (pColors[3 * nIndex + 0] != m_pColors[3 * nIndex + 0]
|| pColors[3 * nIndex + 1] != m_pColors[3 * nIndex + 1]
|| pColors[3 * nIndex + 2] != m_pColors[3 * nIndex + 2]
|| abs(pPoints[nIndex] - m_pColorsPoints[nIndex]) > 0.01)
return false;
}
return true;
}
bool CShading::CompareExtend(bool bBegin, bool bEnd)
{
if (bBegin != m_bBeginExtend || bEnd != m_bEndExtend)
return false;
return true;
}
//----------------------------------------------------------------------------------------
// CAxialShading
//----------------------------------------------------------------------------------------
CAxialShading::CAxialShading(CXref* pXref, double dX0, double dY0, double dX1, double dY1) : CShading(pXref)
{
Add("ShadingType", 2);
CArrayObject* pCoords = new CArrayObject();
if (!pCoords)
return;
pCoords->Add(dX0);
pCoords->Add(dY0);
pCoords->Add(dX1);
pCoords->Add(dY1);
Add("Coords", pCoords);
m_dX0 = dX0;
m_dY0 = dY0;
m_dX1 = dX1;
m_dY1 = dY1;
}
bool CAxialShading::Compare(double dX0, double dY0, double dX1, double dY1)
{
if (abs(dX0 - m_dX0) > 0.01
|| abs(dY0 - m_dY0) > 0.01
|| abs(dX1 - m_dX1) > 0.01
|| abs(dY1 - m_dY1) > 0.01)
return false;
return true;
}
//----------------------------------------------------------------------------------------
// CRadialShading
//----------------------------------------------------------------------------------------
CRadialShading::CRadialShading(CXref* pXref, double dX0, double dY0, double dR0, double dX1, double dY1, double dR1) : CShading(pXref)
{
Add("ShadingType", 3);
CArrayObject* pCoords = new CArrayObject();
if (!pCoords)
return;
pCoords->Add(dX0);
pCoords->Add(dY0);
pCoords->Add(dR0);
pCoords->Add(dX1);
pCoords->Add(dY1);
pCoords->Add(dR1);
Add("Coords", pCoords);
m_dX0 = dX0;
m_dY0 = dY0;
m_dR0 = dR0;
m_dX1 = dX1;
m_dY1 = dY1;
m_dR1 = dR1;
}
bool CRadialShading::Compare(double dX0, double dY0, double dR0, double dX1, double dY1, double dR1)
{
if (abs(dX0 - m_dX0) > 0.01
|| abs(dY0 - m_dY0) > 0.01
|| abs(dR0 - m_dR0) > 0.01
|| abs(dX1 - m_dX1) > 0.01
|| abs(dY1 - m_dY1) > 0.01
|| abs(dR1 - m_dR1) > 0.01)
return false;
return true;
}
}
\ No newline at end of file
#ifndef _PDF_WRITER_SRC_SHADING_H
#define _PDF_WRITER_SRC_STREAMS_H
#include "Objects.h"
namespace PdfWriter
{
enum EShadingType
{
shadingtype_Unknown = 0,
shadingtype_Axial = 2,
shadingtype_Radial = 3
};
//----------------------------------------------------------------------------------------
// CShading
//----------------------------------------------------------------------------------------
class CShading : public CDictObject
{
public:
CShading(CXref* pXref);
virtual ~CShading();
void SetColors(unsigned char* pColors, double* dPoints, int nCount);
void SetExtend(bool bBeing, bool bEnd);
bool CompareColors(unsigned char* pColors, double* pPoints, int nCount);
bool CompareExtend(bool bBeing, bool bEnd);
virtual EShadingType GetShadingType()
{
return shadingtype_Unknown;
}
protected:
CXref* m_pXref;
private:
unsigned char* m_pColors;
double* m_pColorsPoints;
int m_nColorsCount;
bool m_bBeginExtend;
bool m_bEndExtend;
};
//----------------------------------------------------------------------------------------
// CAxialShading
//----------------------------------------------------------------------------------------
class CAxialShading : public CShading
{
public:
CAxialShading(CXref* pXref, double dX0, double dY0, double dX1, double dY1);
bool Compare(double dX0, double dY0, double dX1, double dY1);
EShadingType GetShadingType()
{
return shadingtype_Axial;
}
private:
double m_dX0;
double m_dY0;
double m_dX1;
double m_dY1;
};
//----------------------------------------------------------------------------------------
// CRadialShading
//----------------------------------------------------------------------------------------
class CRadialShading : public CShading
{
public:
CRadialShading(CXref* pXref, double dX0, double dY0, double dR0, double dX1, double dY1, double dR1);
bool Compare(double dX0, double dY0, double dR0, double dX1, double dY1, double dR1);
EShadingType GetShadingType()
{
return shadingtype_Radial;
}
private:
double m_dX0;
double m_dY0;
double m_dR0;
double m_dX1;
double m_dY1;
double m_dR1;
};
}
#endif // _PDF_WRITER_SRC_STREAMS_H
\ No newline at end of file
#include "Streams.h"
#include "Utils.h"
#include "Encrypt.h"
#include "Objects.h"
#include <sstream>
#include "../../ASCOfficeUtils/ZLIB/zlib-1.2.3/zlib.h"
#define DEFLATE_BUF_SIZ ((int)(STREAM_BUF_SIZ * 1.1) + 13)
namespace PdfWriter
{
//----------------------------------------------------------------------------------------
// CStream
//----------------------------------------------------------------------------------------
bool CStream::CheckSize(unsigned int unSize)
{
if (Size() - Tell() >= unSize)
return true;
return false;
}
unsigned int CStream::ReadUInt()
{
if (!CheckSize(4))
return 0;
unsigned int unBytesRead = 1;
int nChar0, nChar1, nChar2, nChar3;
Read((BYTE*)&nChar0, &unBytesRead);
Read((BYTE*)&nChar1, &unBytesRead);
Read((BYTE*)&nChar2, &unBytesRead);
Read((BYTE*)&nChar3, &unBytesRead);
return (unsigned int)((nChar0 << 24) | (nChar1 << 16) | (nChar2 << 8) | nChar3);
}
unsigned char CStream::ReadUChar()
{
if (!CheckSize(1))
return 0;
int nChar;
unsigned int unBytesRead = 1;
Read((BYTE*)&nChar, &unBytesRead);
return nChar;
}
char CStream::ReadChar()
{
return (char)ReadUChar();
}
unsigned short CStream::ReadUShort()
{
if (!CheckSize(2))
return 0;
unsigned int unBytesRead = 1;
int nChar0, nChar1;
Read((BYTE*)&nChar0, &unBytesRead);
Read((BYTE*)&nChar1, &unBytesRead);
return (unsigned short)((nChar0 << 8) | nChar1);
}
void CStream::Write(const BYTE* pBuffer, unsigned int unSize, bool bCalcCheckSum)
{
Write(pBuffer, unSize);
if (bCalcCheckSum)
{
CRC32 oCRC;
oCRC.ProcessCRC((void*)pBuffer, unSize);
m_unCheckSum = oCRC.m_nCRC32;
}
}
void CStream::WriteChar(char nChar)
{
Write((BYTE*)&nChar, 1);
}
void CStream::WriteStr(const char* sString)
{
unsigned int nLen = StrLen(sString, -1);
Write((BYTE*)sString, nLen);
}
void CStream::WriteUChar(unsigned char unValue)
{
Write(&unValue, 1);
}
void CStream::WriteInt(int nValue)
{
std::string sString = std::to_string(nValue);
Write((BYTE*)sString.c_str(), sString.length());
}
void CStream::WriteUInt(unsigned int unValue)
{
WriteInt((int)unValue);
}
void CStream::WriteHex(int nValue, int nLen)
{
std::stringstream oStringStream;
oStringStream << std::hex << nValue;
std::string sString = oStringStream.str();
while (sString.length() < nLen)
{
sString = "0" + sString;
}
return WriteStr(sString.c_str());
}
void CStream::WriteReal(float fValue)
{
std::string sString = std::to_string(fValue);
return WriteStr(sString.c_str());
}
void CStream::WriteReal(double dValue)
{
std::string sString = std::to_string(dValue);
return WriteStr(sString.c_str());
}
void CStream::WriteEscapeName(const char* sValue)
{
char sTmpChar[LIMIT_MAX_NAME_LEN * 3 + 2];
const BYTE* pPos1;
char* pPos2;
pPos1 = (BYTE*)sValue;
pPos2 = sTmpChar;
*pPos2++ = '/';
int nLen = StrLen(sValue, LIMIT_MAX_NAME_LEN);
for (int nIndex = 0; nIndex < nLen; nIndex++)
{
BYTE nChar = *pPos1++;
if (NEEDS_ESCAPE(nChar))
{
*pPos2++ = '#';
*pPos2 = (char)(nChar >> 4);
if (*pPos2 <= 9)
*pPos2 += 0x30;
else
*pPos2 += 0x41 - 10;
pPos2++;
*pPos2 = (char)(nChar & 0x0f);
if (*pPos2 <= 9)
*pPos2 += 0x30;
else
*pPos2 += 0x41 - 10;
pPos2++;
}
else
*pPos2++ = nChar;
}
*pPos2 = 0;
Write((BYTE*)sTmpChar, StrLen(sTmpChar, -1));
}
void CStream::WriteEscapeText(const BYTE* sText, unsigned int unLen)
{
if (!unLen || !sText)
return;
char sBuf[TEXT_DEFAULT_LEN];
unsigned int nIndex = 0;
const BYTE* sTxt = sText;
unsigned long nRet = 0;
sBuf[nIndex++] = '(';
for (int nCounter = 0; nCounter < unLen; nCounter++)
{
BYTE nChar = (BYTE)*sTxt++;
if (NEEDS_ESCAPE(nChar))
{
sBuf[nIndex++] = '\\';
sBuf[nIndex] = nChar >> 6;
sBuf[nIndex] += 0x30;
nIndex++;
sBuf[nIndex] = (nChar & 0x38) >> 3;
sBuf[nIndex] += 0x30;
nIndex++;
sBuf[nIndex] = (nChar & 0x07);
sBuf[nIndex] += 0x30;
nIndex++;
}
else
sBuf[nIndex++] = nChar;
if (nIndex > TEXT_DEFAULT_LEN - 4)
{
Write((BYTE*)sBuf, nIndex);
nIndex = 0;
}
}
sBuf[nIndex++] = ')';
Write((BYTE*)sBuf, nIndex);
}
void CStream::WriteBinary(const BYTE* pData, unsigned int unLen, CEncrypt* pEncrypt)
{
char sBuf[TEXT_DEFAULT_LEN];
BYTE* pBuf = NULL;
bool bDelete = false;
unsigned int nIndex = 0;
const BYTE* pBuffer = NULL;
if (pEncrypt)
{
pBuf = new BYTE[unLen];
bDelete = true;
pEncrypt->CryptBuf(pData, pBuf, unLen);
pBuffer = pBuf;
}
else
{
pBuffer = pData;
}
for (int nCounter = 0; nCounter < unLen; nCounter++, pBuffer++)
{
char nChar = *pBuffer >> 4;
if (nChar <= 9)
nChar += 0x30;
else
nChar += 0x41 - 10;
sBuf[nIndex++] = nChar;
nChar = *pBuffer & 0x0f;
if (nChar <= 9)
nChar += 0x30;
else
nChar += 0x41 - 10;
sBuf[nIndex++] = nChar;
if (nIndex > TEXT_DEFAULT_LEN - 2)
{
Write((BYTE*)sBuf, nIndex);
nIndex = 0;
}
}
if (nIndex > 0)
{
Write((BYTE*)sBuf, nIndex);
}
if (bDelete)
delete[] pBuf;
}
void CStream::WriteStreamWithDeflate(CStream* pStream, CEncrypt* pEncrypt)
{
unsigned long nRet = OK;
z_stream pZStream;
Bytef inbuf[STREAM_BUF_SIZ];
Bytef otbuf[DEFLATE_BUF_SIZ];
BYTE ebuf[DEFLATE_BUF_SIZ];
// initialize input stream
pStream->Seek(0, SeekSet);
// initialize decompression stream.
MemSet(&pZStream, 0x00, sizeof(z_stream));
pZStream.next_out = otbuf;
pZStream.avail_out = DEFLATE_BUF_SIZ;
deflateInit_(&pZStream, Z_DEFAULT_COMPRESSION, ZLIB_VERSION, sizeof(z_stream));
pZStream.next_in = inbuf;
pZStream.avail_in = 0;
for (;;)
{
unsigned int unSize = STREAM_BUF_SIZ;
pStream->Read(inbuf, &unSize);
pZStream.next_in = inbuf;
pZStream.avail_in = unSize;
if (0 == unSize)
break;
while (pZStream.avail_in > 0)
{
deflate(&pZStream, Z_NO_FLUSH);
if (pZStream.avail_out == 0)
{
if (pEncrypt)
{
pEncrypt->CryptBuf(otbuf, ebuf, DEFLATE_BUF_SIZ);
Write(ebuf, DEFLATE_BUF_SIZ);
}
else
Write(otbuf, DEFLATE_BUF_SIZ);
pZStream.next_out = otbuf;
pZStream.avail_out = DEFLATE_BUF_SIZ;
}
}
}
bool bEnd = false;
for (;;)
{
nRet = deflate(&pZStream, Z_FINISH);
if (Z_OK != nRet && Z_STREAM_END != nRet)
{
deflateEnd(&pZStream);
return;
}
if (Z_STREAM_END == nRet)
bEnd = true;
if (pZStream.avail_out < DEFLATE_BUF_SIZ)
{
unsigned int osize = DEFLATE_BUF_SIZ - pZStream.avail_out;
if (pEncrypt)
{
pEncrypt->CryptBuf(otbuf, ebuf, osize);
Write(ebuf, osize);
}
else
Write(otbuf, osize);
pZStream.next_out = otbuf;
pZStream.avail_out = DEFLATE_BUF_SIZ;
}
if (bEnd)
break;
}
deflateEnd(&pZStream);
}
void CStream::WriteStream(CStream* pStream, unsigned int unFilter, CEncrypt *pEncrypt)
{
if (pStream->Size() <= 0)
return;
#ifndef FILTER_FLATE_DECODE_DISABLED
if (unFilter & STREAM_FILTER_FLATE_DECODE)
return WriteStreamWithDeflate(pStream, pEncrypt);
#endif
BYTE pBuf[STREAM_BUF_SIZ];
BYTE pEBuf[STREAM_BUF_SIZ];
pStream->Seek(0, SeekSet);
for (;;)
{
unsigned int unSize = STREAM_BUF_SIZ;
pStream->Read(pBuf, &unSize);
if (0 == unSize)
break;
if (pEncrypt)
{
pEncrypt->CryptBuf(pBuf, pEBuf, unSize);
Write(pEBuf, unSize);
}
else
{
Write(pBuf, unSize);
}
}
}
void CStream::Write(CNullObject* pNull)
{
}
void CStream::Write(CBoolObject* pBool)
{
if (pBool->Get())
WriteStr("true");
else
WriteStr("false");
}
void CStream::Write(CNumberObject* pNumber)
{
WriteInt(pNumber->Get());
}
void CStream::Write(CRealObject* pReal)
{
WriteReal(pReal->Get());
}
void CStream::Write(CNameObject* pName)
{
WriteEscapeName(pName->Get());
}
void CStream::Write(CStringObject* pString, CEncrypt* pEncrypt)
{
if (pEncrypt)
pEncrypt->Reset();
if (pEncrypt)
{
const BYTE* pBinary = pString->GetString();
WriteChar('<');
WriteBinary(pBinary, StrLen((const char*)pBinary, -1), pEncrypt);
WriteChar('>');
}
else
{
WriteEscapeText(pString->GetString(), pString->GetLength());
}
}
void CStream::Write(CBinaryObject* pBinary, CEncrypt* pEncrypt)
{
unsigned int unLen = pBinary->GetLength();
BYTE* pValue = pBinary->GetValue();
if (0 == unLen || !pValue)
return WriteStr("<>");
if (pEncrypt)
pEncrypt->Reset();
WriteChar('<');
WriteBinary(pValue, unLen, pEncrypt);
WriteChar('>');
}
void CStream::Write(CArrayObject* pArray, CEncrypt* pEncrypt)
{
WriteStr("[ ");
for (int nIndex = 0, nCount = pArray->GetCount(); nIndex < nCount; nIndex++)
{
CObjectBase* pObject = pArray->Get(nIndex, false);
Write(pObject, pEncrypt);
WriteChar(' ');
}
WriteChar(']');
}
void CStream::Write(CDictObject* pDict, CEncrypt* pEncrypt)
{
WriteStr("<<\012");
pDict->BeforeWrite();
// EncryptDict не надо шифровать
if (dict_type_ENCRYPT == pDict->GetDictType())
pEncrypt = NULL;
// Добавляем запись Filter
if (pDict->GetStream())
{
pDict->Remove("Filter");
unsigned int unFilter = pDict->GetFilter();
if (STREAM_FILTER_NONE != unFilter)
{
CArrayObject* pFilter = new CArrayObject();
pDict->Add("Filter", pFilter);
#ifndef FILTER_FLATE_DECODE_DISABLED
if (unFilter & STREAM_FILTER_FLATE_DECODE)
pFilter->Add("FlateDecode");
#endif
if (unFilter & STREAM_FILTER_DCT_DECODE)
pFilter->Add("DCTDecode");
if (unFilter & STREAM_FILTER_JPX_DECODE)
pFilter->Add("JPXDecode");
if (unFilter & STREAM_FILTER_JBIG2_DECODE)
pFilter->Add("JBIG2Decode");
if (unFilter & STREAM_FILTER_LZW_DECODE)
pFilter->Add("LZWDecode");
if (unFilter & STREAM_FILTER_CCITT_DECODE)
pFilter->Add("CCITTFaxDecode");
unsigned int unPredictor = pDict->GetPredictor();
//pDict->Remove("DecodeParams");
if (STREAM_PREDICTOR_NONE != unPredictor)
{
CArrayObject* pDecode = new CArrayObject();
pDict->Add("DecodeParams", pDecode);
#ifndef FILTER_FLATE_DECODE_DISABLED
if (unFilter & STREAM_FILTER_FLATE_DECODE)
{
//if ( STREAM_PREDICTOR_FLATE_TIFF == oDict->nPredictor )
pDecode->Add(new CNullObject());
}
#endif
if (unFilter & STREAM_FILTER_DCT_DECODE)
{
pDecode->Add(new CNullObject());
}
if (unFilter & STREAM_FILTER_JPX_DECODE)
{
pDecode->Add(new CNullObject());
}
if (unFilter & STREAM_FILTER_JBIG2_DECODE)
{
pDecode->Add(new CNullObject());
}
if (unFilter & STREAM_FILTER_LZW_DECODE)
{
pDecode->Add(new CNullObject());
}
}
}
}
pDict->WriteToStream(this, pEncrypt);
pDict->Write(this);
WriteStr(">>");
CStream* pStream = pDict->GetStream();
if (pStream)
{
CNumberObject* pLength = (CNumberObject*)pDict->Get("Length");
// "Length" должен управляться таблицей Xref (флаг Indirect)
if (pLength && object_type_NUMBER == pLength->GetType() && pLength->IsIndirect())
{
if (pEncrypt)
pEncrypt->Reset();
WriteStr("\012stream\015\012");
unsigned int unStartSize = Tell();
WriteStream(pStream, pDict->GetFilter(), pEncrypt);
pLength->Set(Tell() - unStartSize);
WriteStr("\012endstream");
}
}
pDict->AfterWrite();
}
void CStream::Write(CObjectBase* pObject, CEncrypt* pEncrypt)
{
if (pObject)
{
pObject->Write(this, pEncrypt);
}
}
//----------------------------------------------------------------------------------------
// CMemoryStream
//----------------------------------------------------------------------------------------
CMemoryStream::CMemoryStream()
{
m_unSize = 0;
m_nBufferSize = 0;
m_pBuffer = NULL;
m_pCur = NULL;
}
CMemoryStream::CMemoryStream(unsigned int unBufferSize)
{
m_unSize = 0;
m_nBufferSize = 0;
m_pBuffer = NULL;
m_pCur = NULL;
Shrink(unBufferSize);
}
CMemoryStream::~CMemoryStream()
{
Close();
}
bool CMemoryStream::IsEof()
{
int nRemainBytes = Size() - Tell();
if (nRemainBytes <= 0)
return true;
return false;
}
void CMemoryStream::Write(const BYTE* pBuffer, unsigned int unSize)
{
unsigned int unRemainBytes = m_nBufferSize - Tell();
if (unRemainBytes < unSize)
{
Shrink(unSize);
}
MemCpy(m_pCur, pBuffer, unSize);
m_pCur += unSize;
m_unSize = (unsigned int)max(m_unSize, m_pCur - m_pBuffer);
}
void CMemoryStream::Read(BYTE* pBuffer, unsigned int* punSize)
{
unsigned int unRemainBytes = m_unSize - Tell();
unsigned int unReadedBytes = (punSize ? min(*punSize, unRemainBytes) : unRemainBytes);
MemCpy(pBuffer, m_pCur, unReadedBytes);
m_pCur += unReadedBytes;
if (punSize)
*punSize = unReadedBytes;
}
void CMemoryStream::Seek(int nPos, EWhenceMode eMode)
{
switch (eMode)
{
case SeekCur: m_pCur += nPos; break;
case SeekEnd: m_pCur = m_pBuffer + m_unSize - nPos; break;
case SeekSet: m_pCur = m_pBuffer + nPos; break;
}
}
int CMemoryStream::Tell()
{
return (int)(m_pCur - m_pBuffer);
}
void CMemoryStream::Close()
{
if (m_pBuffer)
delete[] m_pBuffer;
m_nBufferSize = 0;
m_pBuffer = NULL;
m_pCur = NULL;
m_unSize = 0;
}
unsigned int CMemoryStream::Size()
{
return m_unSize;
}
void CMemoryStream::Shrink(unsigned int unSize)
{
if (m_pBuffer)
{
long lPos = Tell();
BYTE* pNewBuffer = new BYTE[m_nBufferSize + unSize];
MemCpy(pNewBuffer, m_pBuffer, m_unSize);
delete[] m_pBuffer;
m_pBuffer = pNewBuffer;
m_pCur = m_pBuffer + lPos;
m_nBufferSize = m_nBufferSize + unSize;
}
else
{
m_pBuffer = new BYTE[unSize];
m_pCur = m_pBuffer;
m_nBufferSize = unSize;
}
}
//----------------------------------------------------------------------------------------
// CFileStream
//----------------------------------------------------------------------------------------
CFileStream::CFileStream()
{
m_wsFilePath = L"";
m_bDelete = false;
}
CFileStream::~CFileStream()
{
Close();
}
bool CFileStream::IsEof()
{
if (m_oFile.TellFile() >= m_oFile.SizeFile())
return true;
return false;
}
void CFileStream::Write(const BYTE* pBuffer, unsigned int unSize)
{
m_oFile.WriteFile((BYTE*)pBuffer, unSize);
}
void CFileStream::Read(BYTE *pBuffer, unsigned int* punSize)
{
DWORD dwBytesToRead = *punSize;
DWORD dwSizeRead = 0;
m_oFile.ReadFile(pBuffer, dwBytesToRead, dwSizeRead);
*punSize = dwSizeRead;
}
void CFileStream::Seek(int nPos, EWhenceMode eMode)
{
switch (eMode)
{
case SeekCur: m_oFile.SeekFile(nPos, SEEK_CUR); break;
case SeekEnd: m_oFile.SeekFile(nPos, SEEK_END); break;
case SeekSet: m_oFile.SeekFile(nPos, SEEK_SET); break;
}
}
int CFileStream::Tell()
{
return m_oFile.TellFile();
}
void CFileStream::Close()
{
m_oFile.CloseFile();
//if (m_bDelete)
//{
// NSFile::CFileBinary::Remove(m_wsFilePath);
// m_bDelete = false;
// m_wsFilePath = L"";
//}
}
unsigned int CFileStream::Size()
{
return m_oFile.SizeFile();
}
bool CFileStream::OpenFile(const std::wstring& wsFilePath, bool bWrite)
{
Close();
m_wsFilePath = wsFilePath;
m_bDelete = false;
if (!bWrite)
{
if (!m_oFile.OpenFile(wsFilePath))
return false;
}
else
{
if (!m_oFile.CreateFile(wsFilePath))
return false;
}
return true;
}
bool CFileStream::OpenTempFile(const std::wstring& wsFilePath, unsigned int unCheckSum)
{
Close();
m_wsFilePath = wsFilePath;
if (L"" == m_wsFilePath)
{
m_wsFilePath = NSFile::CFileBinary::CreateTempFileWithUniqueName(NSFile::CFileBinary::GetTempPath(), L"Pdf");
}
if (!m_oFile.CreateFile(m_wsFilePath))
return false;
m_bDelete = true;
m_unCheckSum = unCheckSum;
return true;
}
}
\ No newline at end of file
#ifndef _PDF_WRITER_SRC_STREAMS_H
#define _PDF_WRITER_SRC_STREAMS_H
#include "Types.h"
#include "../../DesktopEditor/common/File.h"
#define STREAM_FILTER_NONE 0x0000
#define STREAM_FILTER_ASCIIHEX 0x0100
#define STREAM_FILTER_ASCII85 0x0200
#define STREAM_FILTER_FLATE_DECODE 0x0400
#define STREAM_FILTER_DCT_DECODE 0x0800
#define STREAM_FILTER_JPX_DECODE 0x1000
#define STREAM_FILTER_JBIG2_DECODE 0x2000
#define STREAM_FILTER_LZW_DECODE 0x4000
#define STREAM_FILTER_CCITT_DECODE 0x8000
#define STREAM_PREDICTOR_NONE 0x0000
#define STREAM_PREDICTOR_FLATE_TIFF 0x0001
namespace PdfWriter
{
typedef enum
{
SeekSet = 0,
SeekCur = 1,
SeekEnd = 2,
SeekWrite = 3
} EWhenceMode;
typedef enum
{
StreamUnknown = 0,
StreamCallBack = 1,
StreamFile = 2,
StreamMemory = 3,
StreamTempFile = 4
} EStreamType;
class CNullObject;
class CBoolObject;
class CNumberObject;
class CRealObject;
class CNameObject;
class CStringObject;
class CBinaryObject;
class CArrayObject;
class CDictObject;
class CObjectBase;
class CEncrypt;
class CStream
{
public:
CStream()
{
m_unCheckSum = 0;
}
virtual ~CStream()
{
}
virtual bool IsEof() = 0;
virtual void Write(const BYTE* pBuffer, unsigned int unSize) = 0;
virtual void Read(BYTE* pBuffer, unsigned int* punSize) = 0;
virtual void Seek(int nPos, EWhenceMode eMode) = 0;
virtual int Tell() = 0;
virtual void Close() = 0;
virtual unsigned int Size() = 0;
virtual EStreamType GetType()
{
return StreamUnknown;
}
unsigned int ReadUInt();
unsigned char ReadUChar();
char ReadChar();
unsigned short ReadUShort();
void Write(const BYTE* pBuffer, unsigned int unSize, bool bCalcCheckSum);
void WriteChar (char nChar);
void WriteStr (const char* sString);
void WriteUChar(unsigned char unChar);
void WriteInt (int nValue);
void WriteUInt (unsigned int nValue);
void WriteHex (int nValue, int nLen);
void WriteReal (float fValue);
void WriteReal (double dValue);
void WriteEscapeName(const char* sValue);
void WriteEscapeText(const BYTE* sText, unsigned int unLen);
void WriteBinary(const BYTE* pData, unsigned int unLen, CEncrypt* pEncrypt);
void WriteStream(CStream* pStream, unsigned int unFilter, CEncrypt* pEncrypt);
void Write(CNullObject* pNull);
void Write(CBoolObject* pBool);
void Write(CNumberObject* pNumber);
void Write(CRealObject* pReal);
void Write(CNameObject* pName);
void Write(CStringObject* pString, CEncrypt* pEncrypt);
void Write(CBinaryObject* pBinary, CEncrypt* pEncrypt);
void Write(CArrayObject* pBinary, CEncrypt* pEncrypt);
void Write(CDictObject* pDict, CEncrypt* pEncrypt);
void Write(CObjectBase* pObject, CEncrypt* pEncrypt);
private:
void WriteStreamWithDeflate(CStream* pStream, CEncrypt* pEncrypt);
bool CheckSize(unsigned int unSize);
protected:
unsigned int m_unCheckSum;
};
class CMemoryStream : public CStream
{
public:
CMemoryStream();
CMemoryStream(unsigned int unBufferSize);
~CMemoryStream();
bool IsEof();
void Write(const BYTE* pBuffer, unsigned int unSize);
void Read(BYTE* pBuffer, unsigned int* punSize);
void Seek(int nPos, EWhenceMode eMode);
int Tell();
void Close();
unsigned int Size();
EStreamType GetType()
{
return StreamMemory;
}
private:
void Shrink(unsigned int unSize);
private:
BYTE* m_pBuffer;
int m_nBufferSize;
BYTE* m_pCur;
unsigned int m_unSize;
};
class CFileStream : public CStream
{
public:
CFileStream();
~CFileStream();
bool IsEof();
void Write(const BYTE* pBuffer, unsigned int unSize);
void Read(BYTE* pBuffer, unsigned int* punSize);
void Seek(int nPos, EWhenceMode eMode);
int Tell();
void Close();
unsigned int Size();
EStreamType GetType()
{
return StreamFile;
}
bool OpenFile(const std::wstring& wsFilePath, bool bWrite = false);
bool OpenTempFile(const std::wstring& wsFilePath = L"", unsigned int unCheckSum = 0);
private:
NSFile::CFileBinary m_oFile;
std::wstring m_wsFilePath;
bool m_bDelete;
};
}
#endif // _PDF_WRITER_SRC_STREAMS_H
#ifndef _PDF_WRITER_SRC_TYPES_H
#define _PDF_WRITER_SRC_TYPES_H
#include "Consts.h"
#include "../../DesktopEditor/common/Types.h"
#include <string>
namespace PdfWriter
{
enum EEncryptMode
{
encryptmode_R2 = 2,
encryptmode_R3 = 3
};
struct TRect
{
TRect()
{
fLeft = 0.0;
fBottom = 0.0;
fRight = 0.0;
fTop = 0.0;
}
TRect(double dL, double dT, double dR, double dB)
{
fLeft = dL;
fBottom = dB;
fRight = dR;
fTop = dT;
}
double fLeft;
double fBottom;
double fRight;
double fTop;
};
typedef TRect TBox;
class CMatrix
{
public:
CMatrix()
{
m11 = 1;
m12 = 0;
m21 = 0;
m22 = 1;
x = 0;
y = 0;
}
void Reset()
{
m11 = 1;
m12 = 0;
m21 = 0;
m22 = 1;
x = 0;
y = 0;
}
public:
double m11;
double m12;
double m21;
double m22;
double x;
double y;
};
enum ELineCapStyle
{
linecap_Butt = 0,
linecap_Round = 1,
linecap_ProjectingSquare = 2,
linecap_Min = 0,
linecap_Max = 2
};
enum ELineJoinStyle
{
linejoin_Miter = 0,
linejoin_Round = 1,
linejoin_Bevel = 2,
linejoin_Min = 0,
linejoin_Max = 2
};
class CDashMode
{
public:
CDashMode()
{
m_pPattern = NULL;
m_unCount = 0;
m_dPhase = 0;
}
~CDashMode()
{
if (m_pPattern)
delete[] m_pPattern;
}
void Set(const double* pPattern, unsigned int unCount, double dPhase)
{
if (!pPattern || !unCount)
return;
if (m_pPattern)
delete[] m_pPattern;
m_pPattern = new double[unCount];
if (!m_pPattern)
return;
::memcpy((BYTE*)m_pPattern, (BYTE*)pPattern, unCount * sizeof(double));
m_unCount = unCount;
m_dPhase = dPhase;
}
private:
double* m_pPattern;
unsigned int m_unCount;
double m_dPhase;
};
enum ETextRenderingMode
{
textrenderingmode_Fill = 0,
textrenderingmode_Stroke = 1,
textrenderingmode_FillThenStroke = 2,
textrenderingmode_Invisible = 3,
textrenderingmode_FillClipping = 4,
textrenderingmode_StrokeClipping = 5,
textrenderingmode_FillStrokeClipping = 6,
textrenderingmode_Clipping = 7,
textrenderingmode_Min = 0,
textrenderingmode_Max = 7
};
enum EColorSpace
{
colotspace_DeviceGray = 0,
colotspace_DeviceRGB = 1,
colotspace_DeviceCMYK = 2,
colotspace_CalGray = 3,
colotspace_CalRGB = 4,
colotspace_LAB = 5,
colotspace_ICCBASED = 6,
colotspace_Separation = 7,
colotspace_DeviceN = 8,
colotspace_Indexed = 9,
colotspace_Pattern = 10,
colotspace_Min = 0,
colotspace_Max = 10
};
struct TRgb
{
double r;
double g;
double b;
public:
TRgb()
{
r = 0;
g = 0;
b = 0;
}
TRgb(const TRgb& oColor)
{
r = oColor.r;
g = oColor.g;
b = oColor.b;
}
bool operator ==(const TRgb& oColor)const
{
if (r == oColor.r && g == oColor.g && b == oColor.b)
return true;
return false;
}
};
enum EPageLayout
{
pagelayout_Single = 0,
pagelayout_OneColumn = 1,
pagelayout_TwoColumnLeft = 2,
pagelayout_TwoCoulmnRight = 3,
pagelayout_Min = 0,
pagelayout_Max = 3
};
enum EPageMode
{
pagemode_UseNone = 0,
pagemode_UseOutline = 1,
pagemode_UseThumbs = 2,
pagemode_FullScreen = 3,
pagemode_Min = 0,
pagemode_Max = 3
};
enum EPageNumStyle
{
pagenumstyle_Decimal = 0,
pagenumstyle_UpperRoman = 1,
pagenumstyle_LowerRoman = 2,
pagenumstyle_UpperLetters = 3,
pagenumstyle_LowerLetters = 4,
pagenumstyle_Min = 0,
pagenumstyle_Max = 4
};
class CPoint
{
public:
CPoint()
{
x = 0;
y = 0;
}
void Set(double dX, double dY)
{
x = dX;
y = dY;
}
void Reset()
{
x = 0;
y = 0;
}
CPoint& operator=(const CPoint& oPoint)
{
x = oPoint.x;
y = oPoint.y;
return *this;
}
public:
double x;
double y;
};
enum EGrMode
{
grmode_PAGE = 0x01,
grmode_PATH = 0x02,
grmode_TEXT = 0x03,
grmode_CLIP = 0x04,
grmode_SHADE = 0x05,
grmode_IMAGE = 0x06,
grmode_XOBJ = 0x08
};
enum EBlendMode
{
blendmode_Normal = 0,
blendmode_Multiply = 1,
blendmode_Screen = 2,
blendmode_Overlay = 3,
blendmode_Darken = 4,
blendmode_Lighten = 5,
blendmode_ColorDodge = 6,
blendmode_ColorBum = 7,
blendmode_HardLight = 8,
blendmode_SoftLight = 9,
blendmode_Difference = 10,
blendmode_Exclusion = 11,
blendmode_Min = 0,
blendmode_Max = 11,
blendmode_Unknown = 12
};
enum EStandard14Fonts
{
standard14fonts_Helvetica = 0,
standard14fonts_HelveticaBold = 1,
standard14fonts_HelveticaOblique = 2,
standard14fonts_HelveticeBoldOblique = 3,
standard14fonts_Courier = 4,
standard14fonts_CourierBold = 5,
standard14fonts_CourierOblique = 6,
standard14fonts_CourierBoldOblique = 7,
standard14fonts_Times = 8,
standard14fonts_TimesBold = 9,
standard14fonts_TimesOblique = 10,
standard14fonts_TimesBoldOblique = 11,
standard14fonts_Symbol = 12,
standard14fonts_ZapfDingbats = 13,
standard14fonts_Min = 0,
standard14fonts_Max = 13
};
enum EImageTilePatternType
{
imagetilepatterntype_Default = 0,
imagetilepatterntype_InverseX = 1,
imagetilepatterntype_InverseY = 2,
imagetilepatterntype_InverseXY = 3
};
enum EFontType
{
fontUnknownType,
//----- Gr8BitFont
fontType1,
fontType1C,
fontType1COT,
fontType3,
fontTrueType,
fontTrueTypeOT,
//----- GrCIDFont
fontCIDType0,
fontCIDType0C,
fontCIDType0COT,
fontCIDType2,
fontCIDType2OT
};
}
#endif // _PDF_WRITER_SRC_TYPES_H
\ No newline at end of file
#include "Utils.h"
#include <vector>
namespace PdfWriter
{
BYTE* MemCpy(BYTE* pDst, const BYTE *pSrc, unsigned int unLen)
{
if (unLen > 0)
memcpy(pDst, pSrc, unLen);
return pDst;
}
int StrLen(const char* sString, int nMaxLen)
{
int nLen = 0;
if (!sString)
return 0;
while (*sString != 0 && (nMaxLen < 0 || nLen < nMaxLen))
{
sString++;
nLen++;
}
return nLen;
}
BYTE* StrCpy(char* sDst, const char* sSrc, char* pEnd)
{
if (NULL != sSrc)
{
while (pEnd > sDst && *sSrc != 0)
*sDst++ = *sSrc++;
}
*sDst = 0;
return (BYTE*)sDst;
}
void MemSet(void *pBuf, BYTE nChar, unsigned int unLen)
{
memset(pBuf, nChar, unLen);
}
char* ItoA (char *str, int nVal, char *eptr)
{
char* sTemp;
char sBuf[INT_LEN + 1];
if (nVal < 0)
{
if (nVal < LIMIT_MIN_INT)
nVal = LIMIT_MIN_INT;
*str++ = '-';
nVal = -nVal;
}
else if (nVal > LIMIT_MAX_INT)
{
nVal = LIMIT_MAX_INT;
}
else if (nVal == 0)
{
*str++ = '0';
}
sTemp = sBuf + INT_LEN;
*sTemp-- = 0;
while (nVal > 0)
{
*sTemp = (char)(nVal % 10) + '0';
nVal /= 10;
sTemp--;
}
sTemp++;
while (str < eptr && *sTemp != 0)
*str++ = *sTemp++;
*str = 0;
return str;
}
char* ItoA2 (char *str, unsigned int nVal, unsigned int nLen)
{
char* sT;
char* sU;
if (nVal > LIMIT_MAX_INT)
nVal = LIMIT_MAX_INT;
sU = str + nLen - 1;
*sU = 0;
sT = sU - 1;
while (nVal > 0 && sT >= str)
{
*sT = (char)(nVal % 10) + '0';
nVal /= 10;
sT--;
}
while (str <= sT)
*sT-- = '0';
return str + nLen - 1;
}
int StrCmp(const char* s1, const char* s2)
{
if (!s1 || !s2)
{
if (!s1 && !s2)
return 0;
if (!s1 && s2)
return -1;
else
return 1;
}
while (*s1 == *s2)
{
s1++;
s2++;
if (*s1 == 0 || *s2 == 0)
break;
}
return (BYTE)*s1 - (BYTE)*s2;
}
char* FtoA (char* sDst, double dVal, char* pEnd)
{
int nNPartVal = 0;
int nFPartVal = 0;
char sBuf[REAL_LEN + 1];
char* sptr = sDst;
char* sTemp;
unsigned int nIndex = 0;
if (dVal > LIMIT_MAX_REAL)
dVal = LIMIT_MAX_REAL;
else if (dVal < LIMIT_MIN_REAL)
dVal = LIMIT_MIN_REAL;
sTemp = sBuf + REAL_LEN;
*sTemp-- = 0;
if (dVal < 0)
{
*sDst++ = '-';
dVal = -dVal;
}
// разделяем целую и дробную части
nNPartVal = (int)(dVal + 0.000005);
nFPartVal = (int)((float)(dVal - nNPartVal + 0.000005) * 100000);
// пишем дробную часть
for (nIndex = 0; nIndex < 5; nIndex++)
{
*sTemp = (char)(nFPartVal % 10) + '0';
nFPartVal /= 10;
sTemp--;
}
// пишем целую часть
*sTemp-- = '.';
*sTemp = '0';
if (nNPartVal == 0)
sTemp--;
while (nNPartVal > 0)
{
*sTemp = (char)(nNPartVal % 10) + '0';
nNPartVal /= 10;
sTemp--;
}
sTemp++;
while (sDst <= pEnd && *sTemp != 0)
*sDst++ = *sTemp++;
sDst--;
// TODO: при избавлении от нулей при сдвиге конец строки тоже нужно чистить
// пример число -00.90123 результат "-0.901234"
while (sDst > sptr)
{
if (*sDst == '0')
*sDst = 0;
else {
if (*sDst == '.')
*sDst = 0;
break;
}
sDst--;
}
return (*sDst == 0) ? sDst : ++sDst;
}
void UIntChangeBit(unsigned int& nValue, short nBit)
{
// работаем только с 4-байтовыми числами
if (nBit < 0 || nBit > 31)
return;
unsigned int unBitNum = 1 << nBit;
if (nValue & unBitNum)
nValue ^= unBitNum;
else
nValue |= unBitNum;
}
}
#ifndef _PDF_WRITER_SRC_UTILS_H
#define _PDF_WRITER_SRC_UTILS_H
#include "Types.h"
#define NEEDS_ESCAPE(c) (c < 0x21 || \
c > 0x7e || \
c == '\\' || \
c == '%' || \
c == '#' || \
c == '/' || \
c == '(' || \
c == ')' || \
c == '<' || \
c == '>' || \
c == '[' || \
c == ']' || \
c == '{' || \
c == '}' ) \
#define IS_WHITE_SPACE(c) (c == 0x00 || \
c == 0x09 || \
c == 0x0A || \
c == 0x0C || \
c == 0x0D || \
c == 0x20 ) \
//-----------------------------------------------------------------------------------------------------
// CRC 32
//-----------------------------------------------------------------------------------------------------
class CRC32
{
public:
CRC32()
{
const unsigned CRC_POLY = 0xEDB88320;
for ( unsigned int i = 0; i < 256; i++ )
{
unsigned int r, j;
for ( r = i, j = 8; j; j--)
r = r & 1? (r >> 1) ^ CRC_POLY: r >> 1;
m_pTable[i] = r;
}
m_nCRC32 = 0;
}
void Init(unsigned int nCRC = 0)
{
m_nCRC32 = nCRC;
}
void ProcessCRC(void* pData, int nLen)
{
const unsigned CRC_MASK = 0xD202EF8D;
register unsigned char *sData = reinterpret_cast<unsigned char*>(pData);
register unsigned int nCRC = m_nCRC32;
while ( nLen-- )
{
nCRC = m_pTable[static_cast<unsigned char>(nCRC) ^ *sData++] ^ nCRC >> 8;
nCRC ^= CRC_MASK;
}
m_nCRC32 = nCRC;
}
protected:
unsigned int m_pTable[256];
public:
unsigned int m_nCRC32;
};
namespace PdfWriter
{
BYTE* MemCpy(BYTE* pDst, const BYTE *pSrc, unsigned int unLen);
void MemSet(void* pBuf, BYTE nChar, unsigned int unLen);
BYTE* StrCpy(char* sDst, const char* sSrc, char* pEnd);
int StrLen(const char* sString, int nMaxLen);
char* ItoA (char* sDst, int nVal, char* pEnd);
char* ItoA2 (char* sDst, unsigned int unVal, unsigned int unLen);
int StrCmp(const char* s1, const char* s2);
char* FtoA (char* sDst, double dVal, char* pEnd);
void UIntChangeBit(unsigned int& nValue, short nBit);
void UIntChangeBit2(unsigned int& nValue, short nBit);
}
#endif // _PDF_WRITER_SRC_UTILS_H
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment