summaryrefslogtreecommitdiffstats
path: root/vcl/unx/generic/print/glyphset.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /vcl/unx/generic/print/glyphset.cxx
parentInitial commit. (diff)
downloadlibreoffice-upstream/4%7.4.7.tar.xz
libreoffice-upstream/4%7.4.7.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--vcl/unx/generic/print/glyphset.cxx301
1 files changed, 301 insertions, 0 deletions
diff --git a/vcl/unx/generic/print/glyphset.cxx b/vcl/unx/generic/print/glyphset.cxx
new file mode 100644
index 000000000..6b0475a62
--- /dev/null
+++ b/vcl/unx/generic/print/glyphset.cxx
@@ -0,0 +1,301 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "glyphset.hxx"
+
+#include <sft.hxx>
+
+#include <unx/printergfx.hxx>
+#include <fontsubset.hxx>
+#include <unx/fontmanager.hxx>
+
+#include <tools/gen.hxx>
+
+#include <osl/thread.h>
+
+#include <rtl/ustring.hxx>
+#include <rtl/strbuf.hxx>
+
+#include <unotools/tempfile.hxx>
+
+#include <algorithm>
+
+using namespace vcl;
+using namespace psp;
+
+GlyphSet::GlyphSet (sal_Int32 nFontID, bool bVertical)
+ : mnFontID (nFontID),
+ mbVertical (bVertical)
+{
+ PrintFontManager &rMgr = PrintFontManager::get();
+ maBaseName = OUStringToOString (rMgr.getPSName(mnFontID),
+ RTL_TEXTENCODING_ASCII_US);
+}
+
+void
+GlyphSet::GetGlyphID (
+ sal_GlyphId nGlyph,
+ unsigned char* nOutGlyphID,
+ sal_Int32* nOutGlyphSetID
+ )
+{
+ if (!LookupGlyphID(nGlyph, nOutGlyphID, nOutGlyphSetID))
+ AddGlyphID(nGlyph, nOutGlyphID, nOutGlyphSetID);
+}
+
+bool
+GlyphSet::LookupGlyphID (
+ sal_GlyphId nGlyph,
+ unsigned char* nOutGlyphID,
+ sal_Int32* nOutGlyphSetID
+ )
+{
+ sal_Int32 nGlyphSetID = 1;
+
+ // loop through all the font subsets
+ for (auto const& glyph : maGlyphList)
+ {
+ // check every subset if it contains the queried unicode char
+ glyph_map_t::const_iterator aGlyph = glyph.find (nGlyph);
+ if (aGlyph != glyph.end())
+ {
+ // success: found the glyph id, return the mapped glyphid and the glyphsetid
+ *nOutGlyphSetID = nGlyphSetID;
+ *nOutGlyphID = aGlyph->second;
+ return true;
+ }
+ ++nGlyphSetID;
+ }
+
+ *nOutGlyphSetID = -1;
+ *nOutGlyphID = 0;
+ return false;
+}
+
+void
+GlyphSet::AddNotdef (glyph_map_t &rGlyphMap)
+{
+ if (rGlyphMap.empty())
+ rGlyphMap[0] = 0;
+}
+
+void
+GlyphSet::AddGlyphID (
+ sal_GlyphId nGlyph,
+ unsigned char* nOutGlyphID,
+ sal_Int32* nOutGlyphSetID
+ )
+{
+ // create an empty glyphmap that is reserved for unencoded symbol glyphs,
+ // and a second map that takes any other
+ if (maGlyphList.empty())
+ {
+ glyph_map_t aMap, aMapp;
+
+ maGlyphList.push_back (aMap);
+ maGlyphList.push_back (aMapp);
+ }
+ // if the last map is full, create a new one
+ if (maGlyphList.back().size() == 255)
+ {
+ glyph_map_t aMap;
+ maGlyphList.push_back (aMap);
+ }
+
+ glyph_map_t& aGlyphSet = maGlyphList.back();
+ AddNotdef (aGlyphSet);
+
+ int nSize = aGlyphSet.size();
+
+ aGlyphSet [nGlyph] = nSize;
+ *nOutGlyphSetID = maGlyphList.size();
+ *nOutGlyphID = aGlyphSet [nGlyph];
+}
+
+OString
+GlyphSet::GetGlyphSetName (sal_Int32 nGlyphSetID)
+{
+ OStringBuffer aSetName( maBaseName.getLength() + 32 );
+ aSetName.append( maBaseName );
+ aSetName.append( "FID" );
+ aSetName.append( mnFontID );
+ aSetName.append( mbVertical ? "VGSet" : "HGSet" );
+ aSetName.append( nGlyphSetID );
+ return aSetName.makeStringAndClear();
+}
+
+OString
+GlyphSet::GetReencodedFontName (rtl_TextEncoding nEnc, std::string_view rFontName)
+{
+ if ( nEnc == RTL_TEXTENCODING_MS_1252
+ || nEnc == RTL_TEXTENCODING_ISO_8859_1)
+ {
+ return OString::Concat(rFontName) + "-iso1252";
+ }
+ else
+ if (nEnc >= RTL_TEXTENCODING_USER_START && nEnc <= RTL_TEXTENCODING_USER_END)
+ {
+ return OString::Concat(rFontName)
+ + "-enc"
+ + OString::number(nEnc - RTL_TEXTENCODING_USER_START);
+ }
+ else
+ {
+ return OString();
+ }
+}
+
+void GlyphSet::DrawGlyph(PrinterGfx& rGfx,
+ const Point& rPoint,
+ const sal_GlyphId nGlyphId)
+{
+ unsigned char nGlyphID;
+ sal_Int32 nGlyphSetID;
+
+ // convert to font glyph id and font subset
+ GetGlyphID (nGlyphId, &nGlyphID, &nGlyphSetID);
+
+ OString aGlyphSetName = GetGlyphSetName(nGlyphSetID);
+
+ rGfx.PSSetFont (aGlyphSetName, RTL_TEXTENCODING_DONTKNOW);
+ rGfx.PSMoveTo (rPoint);
+ rGfx.PSShowGlyph(nGlyphID);
+}
+
+namespace {
+
+struct EncEntry
+{
+ unsigned char aEnc;
+ tools::Long aGID;
+
+ EncEntry() : aEnc( 0 ), aGID( 0 ) {}
+
+ bool operator<( const EncEntry& rRight ) const
+ { return aEnc < rRight.aEnc; }
+};
+
+}
+
+static void CreatePSUploadableFont( TrueTypeFont* pSrcFont, FILE* pTmpFile,
+ const char* pGlyphSetName, int nGlyphCount,
+ /*const*/ const sal_uInt16* pRequestedGlyphs, /*const*/ const unsigned char* pEncoding,
+ bool bAllowType42 )
+{
+ // match the font-subset to the printer capabilities
+ // TODO: allow CFF for capable printers
+ FontType nTargetMask = FontType::TYPE1_PFA | FontType::TYPE3_FONT;
+ if( bAllowType42 )
+ nTargetMask |= FontType::TYPE42_FONT;
+
+ std::vector< EncEntry > aSorted( nGlyphCount, EncEntry() );
+ for( int i = 0; i < nGlyphCount; i++ )
+ {
+ aSorted[i].aEnc = pEncoding[i];
+ aSorted[i].aGID = pRequestedGlyphs[i];
+ }
+
+ std::stable_sort( aSorted.begin(), aSorted.end() );
+
+ std::vector< unsigned char > aEncoding( nGlyphCount );
+ std::vector< sal_GlyphId > aRequestedGlyphs( nGlyphCount );
+
+ for( int i = 0; i < nGlyphCount; i++ )
+ {
+ aEncoding[i] = aSorted[i].aEnc;
+ aRequestedGlyphs[i] = aSorted[i].aGID;
+ }
+
+ FontSubsetInfo aInfo;
+ aInfo.LoadFont( pSrcFont );
+
+ aInfo.CreateFontSubset( nTargetMask, pTmpFile, pGlyphSetName,
+ aRequestedGlyphs.data(), aEncoding.data(), nGlyphCount );
+}
+
+void
+GlyphSet::PSUploadFont (osl::File& rOutFile, PrinterGfx &rGfx, bool bAllowType42, std::vector< OString >& rSuppliedFonts )
+{
+ TrueTypeFont *pTTFont;
+ OString aTTFileName (rGfx.GetFontMgr().getFontFileSysPath(mnFontID));
+ int nFace = rGfx.GetFontMgr().getFontFaceNumber(mnFontID);
+ SFErrCodes nSuccess = OpenTTFontFile(aTTFileName.getStr(), nFace, &pTTFont);
+ if (nSuccess != SFErrCodes::Ok)
+ return;
+
+ utl::TempFile aTmpFile;
+ aTmpFile.EnableKillingFile();
+ FILE* pTmpFile = fopen(OUStringToOString(aTmpFile.GetFileName(), osl_getThreadTextEncoding()).getStr(), "w+b");
+ if (pTmpFile == nullptr)
+ return;
+
+ // encoding vector maps character encoding to the ordinal number
+ // of the glyph in the output file
+ unsigned char pEncoding[256];
+ sal_uInt16 pTTGlyphMapping[256];
+
+ // loop through all the font glyph subsets
+ sal_Int32 nGlyphSetID = 1;
+ for (auto const& glyph : maGlyphList)
+ {
+ if (glyph.empty())
+ {
+ ++nGlyphSetID;
+ continue;
+ }
+
+ // loop through all the glyphs in the subset
+ sal_Int32 n = 0;
+ for (auto const& elem : glyph)
+ {
+ pTTGlyphMapping [n] = elem.first;
+ pEncoding [n] = elem.second;
+ n++;
+ }
+
+ // create the current subset
+ OString aGlyphSetName = GetGlyphSetName(nGlyphSetID);
+ fprintf( pTmpFile, "%%%%BeginResource: font %s\n", aGlyphSetName.getStr() );
+ CreatePSUploadableFont( pTTFont, pTmpFile, aGlyphSetName.getStr(), glyph.size(),
+ pTTGlyphMapping, pEncoding, bAllowType42 );
+ fprintf( pTmpFile, "%%%%EndResource\n" );
+ rSuppliedFonts.push_back( aGlyphSetName );
+ ++nGlyphSetID;
+ }
+
+ // copy the file into the page header
+ rewind(pTmpFile);
+ fflush(pTmpFile);
+
+ unsigned char pBuffer[0x2000];
+ sal_uInt64 nIn;
+ sal_uInt64 nOut;
+ do
+ {
+ nIn = fread(pBuffer, 1, sizeof(pBuffer), pTmpFile);
+ rOutFile.write (pBuffer, nIn, nOut);
+ }
+ while ((nIn == nOut) && !feof(pTmpFile));
+
+ // cleanup
+ CloseTTFont (pTTFont);
+ fclose (pTmpFile);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */