Files
core/PdfFile/SrcWriter/FontTT.cpp
2026-04-02 08:10:57 +03:00

212 lines
6.8 KiB
C++

/*
* (c) Copyright Ascensio System SIA 2010-2023
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include "FontTT.h"
#include "FontCidTT.h"
#include "Document.h"
#include "Streams.h"
#include "Utils.h"
#include "FontTTWriter.h"
#include "Encodings.h"
#include "../../DesktopEditor/graphics/pro/Fonts.h"
#include "../../DesktopEditor/common/File.h"
#include <string>
#include FT_TRUETYPE_TABLES_H
namespace PdfWriter
{
//----------------------------------------------------------------------------------------
// CFontTrueType
//----------------------------------------------------------------------------------------
CFontTrueType::CFontTrueType(CXref* pXref, CDocument* pDocument, const std::wstring& wsFontPath, unsigned int unIndex) : CFontDict(pXref, pDocument), m_bCanEmbed(false)
{
CFontFileTrueType* pFontTT = CFontFileTrueType::LoadFromFile(wsFontPath, unIndex);
m_pFontFile = pFontTT;
m_wsFontPath = wsFontPath;
m_unFontIndex = unIndex;
Add("Type", "Font");
Add("Subtype", "TrueType");
Add("Encoding", "WinAnsiEncoding");
Add("FirstChar", 0);
Add("LastChar", 255);
CDictObject* pFontDescriptor = new CDictObject();
// FontDescriptor must be a reference
m_pXref->Add(pFontDescriptor);
pFontDescriptor->Add("Type", "FontDescriptor");
m_pFontDescriptor = pFontDescriptor;
Add("FontDescriptor", pFontDescriptor);
ReadName();
if (m_bCanEmbed)
{
// Set Symbolic bit and clear NonSymbolic bit
unsigned int nFlags = 0;
if (!(nFlags & 4))
UIntChangeBit(nFlags, 2);
if (nFlags & 32)
UIntChangeBit(nFlags, 5);
pFontDescriptor->Add("Flags", nFlags);
m_pFontFileDict = new CDictObject(m_pXref);
pFontDescriptor->Add("FontFile2", m_pFontFileDict);
}
else
{
// Set NonSymbolic flag, because Adobe poorly selects fonts with Symbolic flag
// TODO: Should add check whether to set Symbolic flag
unsigned int nFlags = 0;
UIntChangeBit(nFlags, 5);
pFontDescriptor->Add("Flags", nFlags);
m_pFontFileDict = NULL;
}
}
CFontTrueType::~CFontTrueType()
{
if (m_pFontFile)
delete m_pFontFile;
}
void CFontTrueType::BeforeWrite()
{
if (m_pFontFile && m_pFontFileDict)
{
CStream* pStream = m_pFontFileDict->GetStream();
if (m_pFontFile->GetOpenTypeCFF())
m_pFontFile->WriteOTF(pStream);
else
m_pFontFile->WriteTTF(pStream);
m_pFontFileDict->Add("Length1", pStream->Size());
m_pFontFileDict->SetFilter(STREAM_FILTER_FLATE_DECODE);
}
}
void CFontTrueType::ReadName()
{
FT_Library pLibrary = m_pDocument->GetFreeTypeLibrary();
if (!pLibrary)
return;
DWORD dwFileSize;
FT_Byte* pFaceMemory = NULL;
NSFile::CFileBinary::ReadAllBytes(m_wsFontPath, &pFaceMemory, dwFileSize);
if (!pFaceMemory)
return;
FT_Face pFace = NULL;
FT_New_Memory_Face(pLibrary, pFaceMemory, dwFileSize, m_unFontIndex, &pFace);
if (!pFace)
{
RELEASEARRAYOBJECTS(pFaceMemory);
return;
}
// Write font name to all required dictionaries and fill descriptor
std::string sFontName = pFace->family_name ? std::string(pFace->family_name) : std::string();
if (pFace->style_flags & FT_STYLE_FLAG_ITALIC)
sFontName += "-Italic";
if (pFace->style_flags & FT_STYLE_FLAG_BOLD)
sFontName += "-Bold";
const char* sName = sFontName.c_str();
Add("BaseFont", sName);
Add("Name", sName);
m_pFontDescriptor->Add("FontName", sName);
CArrayObject* pWidths = new CArrayObject();
Add("Widths", pWidths);
unsigned int unUnitsPerEm = pFace->units_per_EM;
double dKoef = 1000.0 / unUnitsPerEm;
for (unsigned int unIndex = 0; unIndex < 255; ++unIndex)
{
unsigned int unGID = GetGID(pFace, c_arrWinAnsiEncoding[unIndex]);
if (0 == FT_Load_Glyph(pFace, unGID, FT_LOAD_NO_SCALE | FT_LOAD_NO_RECURSE))
{
unsigned int unWidth = 0;
if (unUnitsPerEm)
unWidth = ((unsigned int)pFace->glyph->metrics.horiAdvance * 1000 / unUnitsPerEm);
else
unWidth = ((unsigned int)pFace->glyph->metrics.horiAdvance);
pWidths->Add(unWidth);
}
}
int xMin = (int)(unUnitsPerEm ? pFace->bbox.xMin * dKoef : pFace->bbox.xMin);
int yMin = (int)(unUnitsPerEm ? pFace->bbox.yMin * dKoef : pFace->bbox.yMin);
int xMax = (int)(unUnitsPerEm ? pFace->bbox.xMax * dKoef : pFace->bbox.xMax);
int yMax = (int)(unUnitsPerEm ? pFace->bbox.yMax * dKoef : pFace->bbox.yMax);
m_nLineHeight = yMax - yMin;
m_nAscent = yMax;
m_dHeight = pFace->height;
m_dDescent = pFace->descender;
m_dAscent = pFace->ascender;
m_dUnitsPerEm = pFace->units_per_EM;
m_dMaxY = pFace->bbox.yMax;
m_dMinY = pFace->bbox.yMin;
CArrayObject* pBBox = new CArrayObject();
pBBox->Add(xMin);
pBBox->Add(yMin);
pBBox->Add(xMax);
pBBox->Add(yMax);
m_pFontDescriptor->Add("FontBBox", pBBox);
m_pFontDescriptor->Add("Ascent", yMax);
m_pFontDescriptor->Add("Descent", yMin);
m_pFontDescriptor->Add("CapHeight", m_pFontFile ? (int)(unUnitsPerEm ? m_pFontFile->GetCapHeight() * dKoef : m_pFontFile->GetCapHeight()) : 800);
m_pFontDescriptor->Add("ItalicAngle", 0);
m_pFontDescriptor->Add("StemV", 80);
m_pFontDescriptor->Add("FontWeight", m_pFontFile ? m_pFontFile->GetWeight() : 400);
// Currently this class is used for embedding fonts that will be used for filling
// within forms. If the class is used for something else, embedding restrictions need to be set
FT_UShort fsType = FT_Get_FSType_Flags(pFace);
m_bCanEmbed = NSFonts::CFontInfo::CanEmbedForEdit(fsType);
FT_Done_Face(pFace);
RELEASEARRAYOBJECTS(pFaceMemory);
}
}