add apis for font format conversion and merging
Change-Id: Ica67fba1ea32a0d98326e6c2979556bee1759a3b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191211 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com> (cherry picked from commit fe9e639b38e6b6a07e0a37e215d1fc75e62e537b) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192333 Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com> Tested-by: Jenkins
This commit is contained in:
@@ -109,6 +109,19 @@ public:
|
||||
|
||||
EmbeddedFontsManager(const css::uno::Reference<css::frame::XModel>& xModel);
|
||||
~EmbeddedFontsManager();
|
||||
|
||||
// write text dump
|
||||
static bool tx_dump(const OUString& srcFontUrl, const OUString& destFileUrl);
|
||||
// write Type 1 font
|
||||
static bool tx_t1(const OUString& srcFontUrl, const OUString& destFontUrl);
|
||||
// merge fonts together (can also be used to convert a name keyed font to a cid keyed font)
|
||||
// each font in fonts is glyphaliasfile, mergefontfile
|
||||
static bool mergefonts(const OUString& cidFontInfoUrl, const OUString& destFileUrl,
|
||||
const std::vector<std::pair<OUString, OUString>>& fonts);
|
||||
// write OTF font, features is optional
|
||||
static bool makeotf(const OUString& srcFontUrl, const OUString& destFileUrl,
|
||||
const OUString& fontMenuNameDBUrl, const OUString& charMapUrl,
|
||||
const OUString& featuresUrl);
|
||||
};
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <svdpdf.hxx>
|
||||
|
||||
#include <tools/UnitConversion.hxx>
|
||||
#include <vcl/embeddedfontsmanager.hxx>
|
||||
#include <vcl/graph.hxx>
|
||||
#include <vcl/vectorgraphicdata.hxx>
|
||||
|
||||
|
||||
@@ -323,6 +323,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
|
||||
vcl/source/gdi/formpdfexport \
|
||||
vcl/source/gdi/cvtgrf \
|
||||
vcl/source/gdi/embeddedfontsmanager \
|
||||
vcl/source/gdi/embeddedfontsafdko \
|
||||
vcl/source/gdi/FileDefinitionWidgetDraw \
|
||||
vcl/source/gdi/WidgetDefinitionReader \
|
||||
vcl/source/gdi/WidgetDefinition \
|
||||
@@ -722,6 +723,7 @@ $(eval $(call gb_Library_use_externals,vcl,\
|
||||
freetype \
|
||||
) \
|
||||
$(if $(filter PDFIUM,$(BUILD_TYPE)),pdfium) \
|
||||
$(if $(filter AFDKO,$(BUILD_TYPE)),afdko libxml2) \
|
||||
))
|
||||
|
||||
$(eval $(call gb_Library_add_libs,vcl,\
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Copyright 2014-2018 Adobe Systems Incorporated (http://www.adobe.com/). All Rights Reserved.
|
||||
* This software is licensed as OpenSource, under the Apache License, Version 2.0.
|
||||
* This license is available at: http://opensource.org/licenses/Apache-2.0.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
extern "C" {
|
||||
#include <tx_shared.h>
|
||||
#include <hotconv.h>
|
||||
#include <cb.h>
|
||||
extern txCtx txNew(char* progname);
|
||||
extern void txFree(txCtx h);
|
||||
extern void cfrReadFont(txCtx h, long origin, int ttcIndex);
|
||||
|
||||
extern txCtx mergeFontsNew(char* progname);
|
||||
extern void mergeFontsFree(txCtx h);
|
||||
extern void readCIDFontInfo(txCtx h, char* filePath);
|
||||
extern int doMergeFileSet(txCtx h, int argc, char* args[], int i);
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
||||
@@ -0,0 +1,240 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Copyright 2014-2018 Adobe Systems Incorporated (http://www.adobe.com/). All Rights Reserved.
|
||||
* This software is licensed as OpenSource, under the Apache License, Version 2.0.
|
||||
* This license is available at: http://opensource.org/licenses/Apache-2.0.
|
||||
*/
|
||||
|
||||
#include <vcl/embeddedfontsmanager.hxx>
|
||||
#include <osl/file.hxx>
|
||||
#include "afdko.hxx"
|
||||
|
||||
static bool convertTx(txCtx h)
|
||||
{
|
||||
h->src.stm.fp = fopen(h->src.stm.filename, "rb");
|
||||
if (!h->src.stm.fp)
|
||||
return false;
|
||||
|
||||
h->src.stm.flags = STM_DONT_CLOSE;
|
||||
|
||||
buildFontList(h);
|
||||
|
||||
for (long i = 0; i < h->fonts.cnt; ++i)
|
||||
{
|
||||
const FontRec& rec = h->fonts.array[i];
|
||||
|
||||
h->src.type = rec.type;
|
||||
|
||||
switch (h->src.type)
|
||||
{
|
||||
case src_Type1:
|
||||
t1rReadFont(h, rec.offset);
|
||||
break;
|
||||
case src_OTF:
|
||||
h->cfr.flags |= CFR_NO_ENCODING;
|
||||
[[fallthrough]];
|
||||
case src_CFF:
|
||||
cfrReadFont(h, rec.offset, rec.iTTC);
|
||||
break;
|
||||
default:
|
||||
SAL_WARN("vcl.fonts", "unhandled font type: " << h->src.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// System afdko could be used by calling: tx -dump src dest here
|
||||
bool EmbeddedFontsManager::tx_dump(const OUString& srcFontUrl, const OUString& destFileUrl)
|
||||
{
|
||||
OUString srcFontPath, destFilePath;
|
||||
if (osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL(srcFontUrl, srcFontPath)
|
||||
|| osl::FileBase::E_None
|
||||
!= osl::FileBase::getSystemPathFromFileURL(destFileUrl, destFilePath))
|
||||
{
|
||||
SAL_WARN("vcl.fonts", "path failure");
|
||||
return false;
|
||||
}
|
||||
|
||||
txCtx h = txNew(nullptr);
|
||||
if (!h)
|
||||
return false;
|
||||
|
||||
OString srcFontPathA(srcFontPath.toUtf8());
|
||||
h->src.stm.filename = const_cast<char*>(srcFontPathA.getStr());
|
||||
OString destFilePathA(destFilePath.toUtf8());
|
||||
h->dst.stm.filename = const_cast<char*>(destFilePathA.getStr());
|
||||
bool result = convertTx(h);
|
||||
txFree(h);
|
||||
return result;
|
||||
}
|
||||
|
||||
// System afdko could be used by calling: tx -t1 src dest here
|
||||
bool EmbeddedFontsManager::tx_t1(const OUString& srcFontUrl, const OUString& destFileUrl)
|
||||
{
|
||||
OUString srcFontPath, destFilePath;
|
||||
if (osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL(srcFontUrl, srcFontPath)
|
||||
|| osl::FileBase::E_None
|
||||
!= osl::FileBase::getSystemPathFromFileURL(destFileUrl, destFilePath))
|
||||
{
|
||||
SAL_WARN("vcl.fonts", "path failure");
|
||||
return false;
|
||||
}
|
||||
|
||||
txCtx h = txNew(nullptr);
|
||||
if (!h)
|
||||
return false;
|
||||
|
||||
setMode(h, mode_t1);
|
||||
|
||||
OString srcFontPathA(srcFontPath.toUtf8());
|
||||
h->src.stm.filename = const_cast<char*>(srcFontPathA.getStr());
|
||||
OString destFilePathA(destFilePath.toUtf8());
|
||||
h->dst.stm.filename = const_cast<char*>(destFilePathA.getStr());
|
||||
bool result = convertTx(h);
|
||||
txFree(h);
|
||||
return result;
|
||||
}
|
||||
|
||||
// System afdko could be used by calling: mergefonts -cid cidfontinfo destfile [glyphaliasfile mergefontfile]+ here
|
||||
bool EmbeddedFontsManager::mergefonts(const OUString& cidFontInfoUrl, const OUString& destFileUrl,
|
||||
const std::vector<std::pair<OUString, OUString>>& fonts)
|
||||
{
|
||||
OUString cidFontInfoPath, destFilePath;
|
||||
if (osl::FileBase::E_None
|
||||
!= osl::FileBase::getSystemPathFromFileURL(cidFontInfoUrl, cidFontInfoPath)
|
||||
|| osl::FileBase::E_None
|
||||
!= osl::FileBase::getSystemPathFromFileURL(destFileUrl, destFilePath))
|
||||
{
|
||||
SAL_WARN("vcl.fonts", "path failure");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<OString> paths;
|
||||
for (const auto& font : fonts)
|
||||
{
|
||||
OUString glyphAliasPath;
|
||||
OUString mergeFontFilePath;
|
||||
if (osl::FileBase::E_None
|
||||
!= osl::FileBase::getSystemPathFromFileURL(font.first, glyphAliasPath)
|
||||
|| osl::FileBase::E_None
|
||||
!= osl::FileBase::getSystemPathFromFileURL(font.second, mergeFontFilePath))
|
||||
{
|
||||
SAL_WARN("vcl.fonts", "path failure");
|
||||
return false;
|
||||
}
|
||||
paths.push_back(glyphAliasPath.toUtf8());
|
||||
paths.push_back(mergeFontFilePath.toUtf8());
|
||||
}
|
||||
|
||||
txCtx h = mergeFontsNew(nullptr);
|
||||
if (!h)
|
||||
return false;
|
||||
|
||||
OString cidFontInfoPathA(cidFontInfoPath.toUtf8());
|
||||
readCIDFontInfo(h, const_cast<char*>(cidFontInfoPathA.getStr()));
|
||||
|
||||
setMode(h, mode_cff);
|
||||
|
||||
OString destFilePathA(destFilePath.toUtf8());
|
||||
dstFileSetName(h, const_cast<char*>(destFilePathA.getStr()));
|
||||
h->cfw.flags |= CFW_CHECK_IF_GLYPHS_DIFFER;
|
||||
h->cfw.flags |= CFW_PRESERVE_GLYPH_ORDER;
|
||||
|
||||
std::vector<char*> args;
|
||||
for (const auto& path : paths)
|
||||
{
|
||||
args.push_back(const_cast<char*>(path.getStr()));
|
||||
}
|
||||
// merge the input fonts into destfile
|
||||
size_t resultarg = doMergeFileSet(h, args.size(), args.data(), 0);
|
||||
SAL_WARN_IF(resultarg != args.size() - 1, "vcl.fonts",
|
||||
"suspicious doMergeFileSet result of: " << resultarg);
|
||||
|
||||
// convert that merged cid result to Type 1
|
||||
h->src.stm.filename = const_cast<char*>(destFilePathA.getStr());
|
||||
OString tmpdestfile = destFilePathA + ".temp";
|
||||
h->dst.stm.filename = const_cast<char*>(tmpdestfile.getStr());
|
||||
setMode(h, mode_t1);
|
||||
bool result = convertTx(h);
|
||||
|
||||
remove(destFilePathA.getStr());
|
||||
rename(h->dst.stm.filename, destFilePathA.getStr());
|
||||
|
||||
mergeFontsFree(h);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void* cb_memory(ctlMemoryCallbacks* /*cb*/, void* old, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
free(old);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (old != nullptr)
|
||||
return realloc(old, size);
|
||||
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
// System afdko could be used by calling: makeotf[exe] -mf fontMenuNameDB -f srcFont -o destFile -ch charMap [-ff features]
|
||||
bool EmbeddedFontsManager::makeotf(const OUString& srcFontUrl, const OUString& destFileUrl,
|
||||
const OUString& fontMenuNameDBUrl, const OUString& charMapUrl,
|
||||
const OUString& featuresUrl)
|
||||
{
|
||||
OUString srcFontPath, destFilePath, charMapPath, fontMenuNameDBPath, featuresPath;
|
||||
if (osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL(srcFontUrl, srcFontPath)
|
||||
|| osl::FileBase::E_None
|
||||
!= osl::FileBase::getSystemPathFromFileURL(destFileUrl, destFilePath)
|
||||
|| osl::FileBase::E_None
|
||||
!= osl::FileBase::getSystemPathFromFileURL(fontMenuNameDBUrl, fontMenuNameDBPath)
|
||||
|| osl::FileBase::E_None
|
||||
!= osl::FileBase::getSystemPathFromFileURL(charMapUrl, charMapPath))
|
||||
{
|
||||
SAL_WARN("vcl.fonts", "path failure");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!featuresUrl.isEmpty()
|
||||
&& osl::FileBase::E_None
|
||||
!= osl::FileBase::getSystemPathFromFileURL(featuresUrl, featuresPath))
|
||||
{
|
||||
SAL_WARN("vcl.fonts", "path failure");
|
||||
return false;
|
||||
}
|
||||
|
||||
ctlMemoryCallbacks cb_dna_memcb{ nullptr, cb_memory };
|
||||
dnaCtx mainDnaCtx = dnaNew(&cb_dna_memcb, DNA_CHECK_ARGS);
|
||||
|
||||
cbCtx cbctx = cbNew(nullptr, const_cast<char*>(""), const_cast<char*>(""),
|
||||
const_cast<char*>(""), const_cast<char*>(""), mainDnaCtx);
|
||||
|
||||
OString fontMenuNameDBPathA(fontMenuNameDBPath.toUtf8());
|
||||
cbFCDBRead(cbctx, const_cast<char*>(fontMenuNameDBPathA.getStr()));
|
||||
|
||||
OString srcFontPathA(srcFontPath.toUtf8());
|
||||
OString destFilePathA(destFilePath.toUtf8());
|
||||
OString charMapPathA(charMapPath.toUtf8());
|
||||
OString featuresPathA(featuresPath.toUtf8());
|
||||
cbConvert(cbctx, HOT_NO_OLD_OPS, nullptr, const_cast<char*>(srcFontPathA.getStr()),
|
||||
const_cast<char*>(destFilePathA.getStr()),
|
||||
!featuresPathA.isEmpty() ? const_cast<char*>(featuresPathA.getStr()) : nullptr,
|
||||
const_cast<char*>(charMapPathA.getStr()), nullptr, nullptr, nullptr, 0, 0, 0, 0, 0,
|
||||
-1, -1, 0, nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
||||
Reference in New Issue
Block a user