Drop freshly unused font subsetting code
These output font formats were for PostScript that is now gone. Change-Id: Ib29f921fe25432aaa558ba842ee77fe1e8023d47 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155069 Reviewed-by: خالد حسني <khaled@libreoffice.org> Tested-by: خالد حسني <khaled@libreoffice.org>
This commit is contained in:
@@ -38,8 +38,6 @@ enum class FontType {
|
||||
TYPE1_PFA = 1<<3, ///< PSType1 Postscript Font Ascii
|
||||
TYPE1_PFB = 1<<4, ///< PSType1 Postscript Font Binary
|
||||
CFF_FONT = 1<<5, ///< CFF-container with PSType2 glyphs
|
||||
TYPE3_FONT = 1<<6, ///< PSType3 Postscript font
|
||||
TYPE42_FONT = 1<<7, ///< PSType42 wrapper for an SFNT_TTF
|
||||
ANY_SFNT = SFNT_TTF | SFNT_CFF,
|
||||
ANY_TYPE1 = TYPE1_PFA | TYPE1_PFB
|
||||
};
|
||||
@@ -55,7 +53,6 @@ public:
|
||||
|
||||
void LoadFont( FontType eInFontType,
|
||||
const unsigned char* pFontBytes, int nByteLength );
|
||||
void LoadFont( vcl::TrueTypeFont* pSftTrueTypeFont );
|
||||
|
||||
bool CreateFontSubset( FontType nOutFontTypeMask,
|
||||
SvStream* pOutFile, const char* pOutFontName,
|
||||
@@ -77,7 +74,6 @@ private:
|
||||
unsigned const char* mpInFontBytes;
|
||||
int mnInByteLength;
|
||||
FontType meInFontType; ///< allowed mask of input font-types
|
||||
vcl::TrueTypeFont* mpSftTTFont;
|
||||
|
||||
// subset-request details
|
||||
FontType mnReqFontTypeMask; ///< allowed subset-target font types
|
||||
@@ -88,7 +84,6 @@ private:
|
||||
int mnReqGlyphCount;
|
||||
|
||||
bool CreateFontSubsetFromCff();
|
||||
bool CreateFontSubsetFromSfnt();
|
||||
};
|
||||
|
||||
int VCL_DLLPUBLIC TestFontSubset(const void* data, sal_uInt32 size);
|
||||
|
||||
+1
-46
@@ -61,7 +61,7 @@ namespace vcl
|
||||
typedef sal_Int32 F16Dot16; /**< fixed: 16.16 */
|
||||
/*@}*/
|
||||
|
||||
/** Return value of OpenTTFont() and CreateT3FromTTGlyphs() */
|
||||
/** Return value of OpenTTFont() */
|
||||
enum class SFErrCodes {
|
||||
Ok, /**< no error */
|
||||
BadFile, /**< file not found */
|
||||
@@ -565,25 +565,6 @@ class TrueTypeFont;
|
||||
|
||||
void GetTTNameRecords(AbstractTrueTypeFont const *ttf, std::vector<NameRecord>& nr);
|
||||
|
||||
/**
|
||||
* Generates a new PostScript Type 3 font and dumps it to <b>outf</b> file.
|
||||
* This function substitutes glyph 0 for all glyphIDs that are not found in the font.
|
||||
* @param ttf pointer to the TrueTypeFont structure
|
||||
* @param outf the resulting font is written to this stream
|
||||
* @param fname font name for the new font. If it is NULL the PostScript name of the
|
||||
* original font will be used
|
||||
* @param glyphArray pointer to an array of glyphs that are to be extracted from ttf
|
||||
* @param encoding array of encoding values. encoding[i] specifies the position of the glyph
|
||||
* glyphArray[i] in the encoding vector of the resulting Type3 font
|
||||
* @param nGlyphs number of glyph IDs in glyphArray and encoding values in encoding
|
||||
* @param wmode writing mode for the output file: 0 - horizontal, 1 - vertical
|
||||
* @return return the value of SFErrCodes enum
|
||||
* @see SFErrCodes
|
||||
* @ingroup sft
|
||||
*
|
||||
*/
|
||||
SFErrCodes CreateT3FromTTGlyphs(TrueTypeFont *ttf, SvStream *outf, const char *fname, sal_uInt16 const *glyphArray, sal_uInt8 *encoding, int nGlyphs, int wmode);
|
||||
|
||||
/**
|
||||
* Generates a new TrueType font and dumps it to <b>outf</b> file.
|
||||
* This function substitutes glyph 0 for all glyphIDs that are not found in the font.
|
||||
@@ -612,32 +593,6 @@ class TrueTypeFont;
|
||||
const sal_GlyphId* pGlyphIds,
|
||||
const sal_uInt8* pEncoding,
|
||||
int nGlyphCount, FontSubsetInfo& rInfo);
|
||||
/**
|
||||
* Generates a new PostScript Type42 font and dumps it to <b>outf</b> file.
|
||||
* This function substitutes glyph 0 for all glyphIDs that are not found in the font.
|
||||
* @param ttf pointer to the TrueTypeFont structure
|
||||
* @param outf output stream for a resulting font
|
||||
* @param psname PostScript name of the resulting font
|
||||
* @param glyphArray pointer to an array of glyphs that are to be extracted from ttf. The first
|
||||
* element of this array has to be glyph 0 (default glyph)
|
||||
* @param encoding array of encoding values. encoding[i] specifies character code for
|
||||
* the glyphID glyphArray[i]. Character code 0 usually points to a default
|
||||
* glyph (glyphID 0)
|
||||
* @param nGlyphs number of glyph IDs in glyphArray and encoding values in encoding
|
||||
* @return SFErrCodes::Ok - no errors
|
||||
* SFErrCodes::GlyphNum - too many glyphs (> 255)
|
||||
* SFErrCodes::TtFormat - corrupted TrueType fonts
|
||||
*
|
||||
* @see SFErrCodes
|
||||
* @ingroup sft
|
||||
*
|
||||
*/
|
||||
SFErrCodes CreateT42FromTTGlyphs(TrueTypeFont *ttf,
|
||||
SvStream *outf,
|
||||
const char *psname,
|
||||
sal_uInt16 const *glyphArray,
|
||||
sal_uInt8 *encoding,
|
||||
int nGlyphs);
|
||||
|
||||
/**
|
||||
* Returns global font information about the TrueType font.
|
||||
|
||||
@@ -33,7 +33,6 @@ FontSubsetInfo::FontSubsetInfo()
|
||||
, mpInFontBytes( nullptr)
|
||||
, mnInByteLength( 0)
|
||||
, meInFontType( FontType::NO_FONT)
|
||||
, mpSftTTFont( nullptr)
|
||||
, mnReqFontTypeMask( FontType::NO_FONT )
|
||||
, mpOutFile(nullptr)
|
||||
, mpReqFontName(nullptr)
|
||||
@@ -52,20 +51,11 @@ void FontSubsetInfo::LoadFont(
|
||||
FontType eInFontType,
|
||||
const unsigned char* pInFontBytes, int nInByteLength)
|
||||
{
|
||||
SAL_WARN_IF( (mpSftTTFont != nullptr), "vcl", "Subset from SFT and from mapped font-file requested");
|
||||
meInFontType = eInFontType;
|
||||
mpInFontBytes = pInFontBytes;
|
||||
mnInByteLength = nInByteLength;
|
||||
}
|
||||
|
||||
// prepare subsetting for fonts that are known to the SFT-parser
|
||||
void FontSubsetInfo::LoadFont( vcl::TrueTypeFont* pSftTTFont )
|
||||
{
|
||||
SAL_WARN_IF( (mpInFontBytes != nullptr), "vcl", "Subset from SFT and from mapped font-file requested");
|
||||
mpSftTTFont = pSftTTFont;
|
||||
meInFontType = FontType::ANY_SFNT;
|
||||
}
|
||||
|
||||
bool FontSubsetInfo::CreateFontSubset(
|
||||
FontType nReqFontTypeMask,
|
||||
SvStream* pOutFile, const char* pReqFontName,
|
||||
@@ -90,18 +80,9 @@ bool FontSubsetInfo::CreateFontSubset(
|
||||
|
||||
// TODO: better match available input-type to possible subset-types
|
||||
switch( meInFontType) {
|
||||
case FontType::SFNT_TTF:
|
||||
case FontType::SFNT_CFF:
|
||||
case FontType::ANY_SFNT:
|
||||
bOK = CreateFontSubsetFromSfnt();
|
||||
break;
|
||||
case FontType::CFF_FONT:
|
||||
bOK = CreateFontSubsetFromCff();
|
||||
break;
|
||||
case FontType::TYPE1_PFA:
|
||||
case FontType::TYPE1_PFB:
|
||||
case FontType::ANY_TYPE1:
|
||||
case FontType::NO_FONT:
|
||||
default:
|
||||
OSL_FAIL( "unhandled type in CreateFontSubset()");
|
||||
break;
|
||||
@@ -110,48 +91,4 @@ bool FontSubsetInfo::CreateFontSubset(
|
||||
return bOK;
|
||||
}
|
||||
|
||||
// TODO: move function to sft.cxx to replace dummy implementation
|
||||
bool FontSubsetInfo::CreateFontSubsetFromSfnt()
|
||||
{
|
||||
// handle SFNT_CFF fonts
|
||||
sal_uInt32 nCffLength = 0;
|
||||
const sal_uInt8* pCffBytes = mpSftTTFont->table(vcl::O_CFF, nCffLength);
|
||||
if (pCffBytes)
|
||||
{
|
||||
LoadFont( FontType::CFF_FONT, pCffBytes, nCffLength);
|
||||
const bool bOK = CreateFontSubsetFromCff();
|
||||
return bOK;
|
||||
}
|
||||
|
||||
// handle SFNT_TTF fonts
|
||||
// by forwarding the subset request to AG's sft subsetter
|
||||
#if 1 // TODO: remove conversion tp 16bit glyphids when sft-subsetter has been updated
|
||||
std::vector<sal_uInt16> aShortGlyphIds;
|
||||
aShortGlyphIds.reserve(mnReqGlyphCount);
|
||||
for (int i = 0; i < mnReqGlyphCount; ++i)
|
||||
aShortGlyphIds.push_back(static_cast<sal_uInt16>(mpReqGlyphIds[i]));
|
||||
// remove const_cast when sft-subsetter is const-correct
|
||||
sal_uInt8* pEncArray = const_cast<sal_uInt8*>( mpReqEncodedIds );
|
||||
#endif
|
||||
vcl::SFErrCodes nSFTErr = vcl::SFErrCodes::BadArg;
|
||||
if( mnReqFontTypeMask & FontType::TYPE42_FONT )
|
||||
{
|
||||
nSFTErr = CreateT42FromTTGlyphs( mpSftTTFont, mpOutFile, mpReqFontName,
|
||||
aShortGlyphIds.data(), pEncArray, mnReqGlyphCount );
|
||||
}
|
||||
else if( mnReqFontTypeMask & FontType::TYPE3_FONT )
|
||||
{
|
||||
nSFTErr = CreateT3FromTTGlyphs( mpSftTTFont, mpOutFile, mpReqFontName,
|
||||
aShortGlyphIds.data(), pEncArray, mnReqGlyphCount,
|
||||
0 /* 0 = horizontal, 1 = vertical */ );
|
||||
}
|
||||
else if( mnReqFontTypeMask & FontType::SFNT_TTF )
|
||||
{
|
||||
// TODO: use CreateTTFromTTGlyphs()
|
||||
// TODO: move functionality from callers here
|
||||
}
|
||||
|
||||
return (nSFTErr != vcl::SFErrCodes::Ok);
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -58,46 +58,8 @@
|
||||
namespace vcl
|
||||
{
|
||||
|
||||
/*- module identification */
|
||||
|
||||
const char * const modname = "SunTypeTools-TT";
|
||||
const char * const modver = "1.0";
|
||||
const char * const modextra = "gelf";
|
||||
|
||||
/*- private functions, constants and data types */
|
||||
|
||||
namespace {
|
||||
|
||||
enum PathSegmentType {
|
||||
PS_NOOP = 0,
|
||||
PS_MOVETO = 1,
|
||||
PS_LINETO = 2,
|
||||
PS_CURVETO = 3,
|
||||
PS_CLOSEPATH = 4
|
||||
};
|
||||
|
||||
struct PSPathElement
|
||||
{
|
||||
PathSegmentType type;
|
||||
int x1, y1;
|
||||
int x2, y2;
|
||||
int x3, y3;
|
||||
|
||||
explicit PSPathElement( PathSegmentType i_eType ) : type( i_eType ),
|
||||
x1( 0 ), y1( 0 ),
|
||||
x2( 0 ), y2( 0 ),
|
||||
x3( 0 ), y3( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
PSPathElement() : type( PS_NOOP ),
|
||||
x1( 0 ), y1( 0 ),
|
||||
x2( 0 ), y2( 0 ),
|
||||
x3( 0 ), y3( 0 )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/*- In horizontal writing mode right sidebearing is calculated using this formula
|
||||
*- rsb = aw - (lsb + xMax - xMin) -*/
|
||||
struct TTGlyphMetrics {
|
||||
@@ -110,34 +72,6 @@ struct TTGlyphMetrics {
|
||||
sal_uInt16 ah; /*- advance height (vertical writing mode) */
|
||||
};
|
||||
|
||||
constexpr int HFORMAT_LINELEN = 64;
|
||||
|
||||
class HexFmt {
|
||||
public:
|
||||
HexFmt(SvStream *outf) : o(outf) {}
|
||||
~HexFmt()
|
||||
{
|
||||
Flush();
|
||||
}
|
||||
bool Flush();
|
||||
void OpenString();
|
||||
void CloseString();
|
||||
void BlockWrite(const void *ptr, sal_uInt32 size);
|
||||
|
||||
private:
|
||||
SvStream *o;
|
||||
char buffer[HFORMAT_LINELEN];
|
||||
size_t bufpos = 0;
|
||||
int total = 0;
|
||||
};
|
||||
|
||||
class GlyphOffsets {
|
||||
public:
|
||||
GlyphOffsets(sal_uInt8 *sfntP, sal_uInt32 sfntLen);
|
||||
sal_uInt32 nGlyphs; /* number of glyphs in the font + 1 */
|
||||
std::unique_ptr<sal_uInt32[]> offs; /* array of nGlyphs offsets */
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/*- Data access methods for data stored in big-endian format */
|
||||
@@ -207,58 +141,6 @@ static int XUnits(int unitsPerEm, int n)
|
||||
return (n * 1000) / unitsPerEm;
|
||||
}
|
||||
|
||||
static char toHex(sal_uInt8 nIndex)
|
||||
{
|
||||
/* Hex Formatter functions */
|
||||
static const char HexChars[] = "0123456789ABCDEF";
|
||||
assert(nIndex < SAL_N_ELEMENTS(HexChars));
|
||||
return HexChars[nIndex];
|
||||
}
|
||||
|
||||
bool HexFmt::Flush()
|
||||
{
|
||||
bool bRet = true;
|
||||
if (bufpos) {
|
||||
size_t nWritten = o->WriteBytes(buffer, bufpos);
|
||||
bRet = nWritten == bufpos;
|
||||
bufpos = 0;
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
|
||||
void HexFmt::OpenString()
|
||||
{
|
||||
o->WriteOString("<\n");
|
||||
}
|
||||
|
||||
void HexFmt::CloseString()
|
||||
{
|
||||
Flush();
|
||||
o->WriteOString("00\n>\n");
|
||||
}
|
||||
|
||||
void HexFmt::BlockWrite(const void *ptr, sal_uInt32 size)
|
||||
{
|
||||
if (total + size > 65534) {
|
||||
Flush();
|
||||
CloseString();
|
||||
total = 0;
|
||||
OpenString();
|
||||
}
|
||||
|
||||
for (sal_uInt32 i = 0; i < size; ++i) {
|
||||
sal_uInt8 Ch = static_cast<sal_uInt8 const *>(ptr)[i];
|
||||
buffer[bufpos++] = toHex(Ch >> 4);
|
||||
buffer[bufpos++] = toHex(Ch & 0xF);
|
||||
if (bufpos == HFORMAT_LINELEN) {
|
||||
Flush();
|
||||
o->WriteOString("\n");
|
||||
}
|
||||
|
||||
}
|
||||
total += size;
|
||||
}
|
||||
|
||||
/* Outline Extraction functions */
|
||||
|
||||
/* fills the aw and lsb entries of the TTGlyphMetrics structure from hmtx table -*/
|
||||
@@ -742,133 +624,6 @@ static int GetTTGlyphOutline(AbstractTrueTypeFont *ttf, sal_uInt32 glyphID, std:
|
||||
return res;
|
||||
}
|
||||
|
||||
/*- returns the number of items in the path -*/
|
||||
|
||||
static int BSplineToPSPath(ControlPoint const *srcA, int srcCount, std::unique_ptr<PSPathElement[]>& path)
|
||||
{
|
||||
std::vector< PSPathElement > aPathList;
|
||||
int nPathCount = 0;
|
||||
PSPathElement p( PS_NOOP );
|
||||
|
||||
int x0 = 0, y0 = 0, x1 = 0, y1 = 0, x2, y2, curx, cury;
|
||||
bool lastOff = false; /*- last point was off-contour */
|
||||
int scflag = 1; /*- start contour flag */
|
||||
bool ecflag = false; /*- end contour flag */
|
||||
int cp = 0; /*- current point */
|
||||
int StartContour = 0, EndContour = 1;
|
||||
|
||||
path.reset();
|
||||
|
||||
/* if (srcCount > 0) for(;;) */
|
||||
while (srcCount > 0) { /*- srcCount does not get changed inside the loop. */
|
||||
if (scflag) {
|
||||
int l = cp;
|
||||
StartContour = cp;
|
||||
while (!(srcA[l].flags & 0x8000)) l++;
|
||||
EndContour = l;
|
||||
if (StartContour == EndContour) {
|
||||
if (cp + 1 < srcCount) {
|
||||
cp++;
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
p = PSPathElement(PS_MOVETO);
|
||||
if (!(srcA[cp].flags & 1)) {
|
||||
if (!(srcA[EndContour].flags & 1)) {
|
||||
p.x1 = x0 = (srcA[cp].x + srcA[EndContour].x + 1) / 2;
|
||||
p.y1 = y0 = (srcA[cp].y + srcA[EndContour].y + 1) / 2;
|
||||
} else {
|
||||
p.x1 = x0 = srcA[EndContour].x;
|
||||
p.y1 = y0 = srcA[EndContour].y;
|
||||
}
|
||||
} else {
|
||||
p.x1 = x0 = srcA[cp].x;
|
||||
p.y1 = y0 = srcA[cp].y;
|
||||
cp++;
|
||||
}
|
||||
aPathList.push_back( p );
|
||||
lastOff = false;
|
||||
scflag = 0;
|
||||
}
|
||||
|
||||
curx = srcA[cp].x;
|
||||
cury = srcA[cp].y;
|
||||
|
||||
if (srcA[cp].flags & 1)
|
||||
{
|
||||
if (lastOff)
|
||||
{
|
||||
p = PSPathElement(PS_CURVETO);
|
||||
p.x1 = x0 + (2 * (x1 - x0) + 1) / 3;
|
||||
p.y1 = y0 + (2 * (y1 - y0) + 1) / 3;
|
||||
p.x2 = x1 + (curx - x1 + 1) / 3;
|
||||
p.y2 = y1 + (cury - y1 + 1) / 3;
|
||||
p.x3 = curx;
|
||||
p.y3 = cury;
|
||||
aPathList.push_back( p );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x0 != curx || y0 != cury)
|
||||
{ /* eliminate empty lines */
|
||||
p = PSPathElement(PS_LINETO);
|
||||
p.x1 = curx;
|
||||
p.y1 = cury;
|
||||
aPathList.push_back( p );
|
||||
}
|
||||
}
|
||||
x0 = curx; y0 = cury; lastOff = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lastOff)
|
||||
{
|
||||
x2 = (x1 + curx + 1) / 2;
|
||||
y2 = (y1 + cury + 1) / 2;
|
||||
p = PSPathElement(PS_CURVETO);
|
||||
p.x1 = x0 + (2 * (x1 - x0) + 1) / 3;
|
||||
p.y1 = y0 + (2 * (y1 - y0) + 1) / 3;
|
||||
p.x2 = x1 + (x2 - x1 + 1) / 3;
|
||||
p.y2 = y1 + (y2 - y1 + 1) / 3;
|
||||
p.x3 = x2;
|
||||
p.y3 = y2;
|
||||
aPathList.push_back( p );
|
||||
x0 = x2; y0 = y2;
|
||||
x1 = curx; y1 = cury;
|
||||
} else {
|
||||
x1 = curx; y1 = cury;
|
||||
}
|
||||
lastOff = true;
|
||||
}
|
||||
|
||||
if (ecflag) {
|
||||
aPathList.emplace_back(PS_CLOSEPATH );
|
||||
scflag = 1;
|
||||
ecflag = false;
|
||||
cp = EndContour + 1;
|
||||
if (cp >= srcCount) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cp == EndContour) {
|
||||
cp = StartContour;
|
||||
ecflag = true;
|
||||
} else {
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
|
||||
if( (nPathCount = static_cast<int>(aPathList.size())) > 0)
|
||||
{
|
||||
path.reset(new PSPathElement[nPathCount]);
|
||||
memcpy( path.get(), aPathList.data(), nPathCount * sizeof(PSPathElement) );
|
||||
}
|
||||
|
||||
return nPathCount;
|
||||
}
|
||||
|
||||
/*- Extracts a string from the name table and allocates memory for it -*/
|
||||
|
||||
static OString nameExtract( const sal_uInt8* name, int nTableSize, int n, int dbFlag, OUString* ucs2result )
|
||||
@@ -1561,188 +1316,6 @@ int GetTTGlyphComponents(AbstractTrueTypeFont *ttf, sal_uInt32 glyphID, std::vec
|
||||
return n;
|
||||
}
|
||||
|
||||
SFErrCodes CreateT3FromTTGlyphs(TrueTypeFont *ttf, SvStream *outf, const char *fname,
|
||||
sal_uInt16 const *glyphArray, sal_uInt8 *encoding, int nGlyphs,
|
||||
int wmode)
|
||||
{
|
||||
std::vector<ControlPoint> pa;
|
||||
std::unique_ptr<PSPathElement[]> path;
|
||||
int i, j, n;
|
||||
sal_uInt32 nSize;
|
||||
const sal_uInt8* table = ttf->table(O_head, nSize);
|
||||
TTGlyphMetrics metrics;
|
||||
int UPEm = ttf->unitsPerEm();
|
||||
|
||||
const char * const h01 = "%%!PS-AdobeFont-%d.%d-%d.%d\n";
|
||||
const char * const h02 = "%% Creator: %s %s %s\n";
|
||||
const char * const h09 = "%% Original font name: %s\n";
|
||||
|
||||
const char * const h10 =
|
||||
"30 dict begin\n"
|
||||
"/PaintType 0 def\n"
|
||||
"/FontType 3 def\n"
|
||||
"/StrokeWidth 0 def\n";
|
||||
|
||||
const char * const h11 = "/FontName (%s) cvn def\n";
|
||||
|
||||
/*
|
||||
const char *h12 = "%/UniqueID %d def\n";
|
||||
*/
|
||||
const char * const h13 = "/FontMatrix [.001 0 0 .001 0 0] def\n";
|
||||
const char * const h14 = "/FontBBox [%d %d %d %d] def\n";
|
||||
|
||||
const char * const h15=
|
||||
"/Encoding 256 array def\n"
|
||||
" 0 1 255 {Encoding exch /.notdef put} for\n";
|
||||
|
||||
const char * const h16 = " Encoding %d /glyph%d put\n";
|
||||
const char * const h17 = "/XUID [103 0 0 16#%08" SAL_PRIXUINT32 " %d 16#%08" SAL_PRIXUINT32 " 16#%08" SAL_PRIXUINT32 "] def\n";
|
||||
|
||||
const char * const h30 = "/CharProcs %d dict def\n";
|
||||
const char * const h31 = " CharProcs begin\n";
|
||||
const char * const h32 = " /.notdef {} def\n";
|
||||
const char * const h33 = " /glyph%d {\n";
|
||||
const char * const h34 = " } bind def\n";
|
||||
const char * const h35 = " end\n";
|
||||
|
||||
const char * const h40 =
|
||||
"/BuildGlyph {\n"
|
||||
" exch /CharProcs get exch\n"
|
||||
" 2 copy known not\n"
|
||||
" {pop /.notdef} if\n"
|
||||
" get exec\n"
|
||||
"} bind def\n"
|
||||
"/BuildChar {\n"
|
||||
" 1 index /Encoding get exch get\n"
|
||||
" 1 index /BuildGlyph get exec\n"
|
||||
"} bind def\n"
|
||||
"currentdict end\n";
|
||||
|
||||
const char * const h41 = "(%s) cvn exch definefont pop\n";
|
||||
|
||||
if ((nGlyphs <= 0) || (nGlyphs > 256)) return SFErrCodes::GlyphNum;
|
||||
if (!glyphArray) return SFErrCodes::BadArg;
|
||||
if (!fname) fname = ttf->psname.getStr();
|
||||
|
||||
constexpr int bufmax = 256;
|
||||
char buf[bufmax];
|
||||
|
||||
snprintf(buf, bufmax, h01, GetInt16(table, 0), GetUInt16(table, 2), GetInt16(table, 4), GetUInt16(table, 6));
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, h02, modname, modver, modextra);
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, h09, ttf->psname.getStr());
|
||||
outf->WriteOString(buf);
|
||||
|
||||
snprintf(buf, bufmax, "%s", h10);
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, h11, fname);
|
||||
outf->WriteOString(buf);
|
||||
/* snprintf(buf, bufmax, h12, 4000000); */
|
||||
|
||||
/* XUID generation:
|
||||
* 103 0 0 C1 C2 C3 C4
|
||||
* C1 - CRC-32 of the entire source TrueType font
|
||||
* C2 - number of glyphs in the subset
|
||||
* C3 - CRC-32 of the glyph array
|
||||
* C4 - CRC-32 of the encoding array
|
||||
*
|
||||
* All CRC-32 numbers are presented as hexadecimal numbers
|
||||
*/
|
||||
|
||||
snprintf(buf, bufmax, h17, rtl_crc32(0, ttf->ptr, ttf->fsize), nGlyphs, rtl_crc32(0, glyphArray, nGlyphs * 2), rtl_crc32(0, encoding, nGlyphs));
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "%s", h13);
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, h14, XUnits(UPEm, GetInt16(table, 36)), XUnits(UPEm, GetInt16(table, 38)), XUnits(UPEm, GetInt16(table, 40)), XUnits(UPEm, GetInt16(table, 42)));
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "%s", h15);
|
||||
outf->WriteOString(buf);
|
||||
|
||||
for (i = 0; i < nGlyphs; i++) {
|
||||
snprintf(buf, bufmax, h16, encoding[i], i);
|
||||
outf->WriteOString(buf);
|
||||
}
|
||||
|
||||
snprintf(buf, bufmax, h30, nGlyphs+1);
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "%s", h31);
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "%s", h32);
|
||||
outf->WriteOString(buf);
|
||||
|
||||
for (i = 0; i < nGlyphs; i++) {
|
||||
snprintf(buf, bufmax, h33, i);
|
||||
outf->WriteOString(buf);
|
||||
int r = GetTTGlyphOutline(ttf, glyphArray[i] < ttf->glyphCount() ? glyphArray[i] : 0, pa, &metrics, nullptr);
|
||||
|
||||
if (r > 0) {
|
||||
n = BSplineToPSPath(pa.data(), r, path);
|
||||
} else {
|
||||
n = 0; /* glyph might have zero contours but valid metrics ??? */
|
||||
path = nullptr;
|
||||
if (r < 0) { /* glyph is not present in the font - pa array was not allocated, so no need to free it */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
snprintf(buf, bufmax, "\t%d %d %d %d %d %d setcachedevice\n",
|
||||
wmode == 0 ? XUnits(UPEm, metrics.aw) : 0,
|
||||
wmode == 0 ? 0 : -XUnits(UPEm, metrics.ah),
|
||||
XUnits(UPEm, metrics.xMin),
|
||||
XUnits(UPEm, metrics.yMin),
|
||||
XUnits(UPEm, metrics.xMax),
|
||||
XUnits(UPEm, metrics.yMax));
|
||||
outf->WriteOString(buf);
|
||||
|
||||
for (j = 0; j < n; j++)
|
||||
{
|
||||
switch (path[j].type)
|
||||
{
|
||||
case PS_MOVETO:
|
||||
snprintf(buf, bufmax, "\t%d %d moveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1));
|
||||
outf->WriteOString(buf);
|
||||
break;
|
||||
|
||||
case PS_LINETO:
|
||||
snprintf(buf, bufmax, "\t%d %d lineto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1));
|
||||
outf->WriteOString(buf);
|
||||
break;
|
||||
|
||||
case PS_CURVETO:
|
||||
snprintf(buf, bufmax, "\t%d %d %d %d %d %d curveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1), XUnits(UPEm, path[j].x2), XUnits(UPEm, path[j].y2), XUnits(UPEm, path[j].x3), XUnits(UPEm, path[j].y3));
|
||||
outf->WriteOString(buf);
|
||||
break;
|
||||
|
||||
case PS_CLOSEPATH:
|
||||
snprintf(buf, bufmax, "\tclosepath\n");
|
||||
outf->WriteOString(buf);
|
||||
break;
|
||||
case PS_NOOP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n > 0)
|
||||
{
|
||||
snprintf(buf, bufmax, "\tfill\n"); /* if glyph is not a whitespace character */
|
||||
outf->WriteOString(buf);
|
||||
}
|
||||
|
||||
snprintf(buf, bufmax, "%s", h34);
|
||||
outf->WriteOString(buf);
|
||||
|
||||
path.reset();
|
||||
}
|
||||
snprintf(buf, bufmax, "%s", h35);
|
||||
outf->WriteOString(buf);
|
||||
|
||||
snprintf(buf, bufmax, "%s", h40);
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, h41, fname);
|
||||
outf->WriteOString(buf);
|
||||
|
||||
return SFErrCodes::Ok;
|
||||
}
|
||||
|
||||
SFErrCodes CreateTTFromTTGlyphs(AbstractTrueTypeFont *ttf,
|
||||
std::vector<sal_uInt8>& rOutBuffer,
|
||||
sal_uInt16 const *glyphArray,
|
||||
@@ -1977,289 +1550,6 @@ bool CreateTTFfontSubset(vcl::AbstractTrueTypeFont& rTTF, std::vector<sal_uInt8>
|
||||
== vcl::SFErrCodes::Ok);
|
||||
}
|
||||
|
||||
GlyphOffsets::GlyphOffsets(sal_uInt8 *sfntP, sal_uInt32 sfntLen)
|
||||
{
|
||||
sal_uInt8 *loca = nullptr;
|
||||
sal_uInt16 numTables = GetUInt16(sfntP, 4);
|
||||
sal_uInt32 locaLen = 0;
|
||||
sal_Int16 indexToLocFormat = 0;
|
||||
|
||||
sal_uInt32 nMaxPossibleTables = sfntLen / (3*sizeof(sal_uInt32)); /*the three GetUInt32 calls*/
|
||||
if (numTables > nMaxPossibleTables)
|
||||
{
|
||||
SAL_WARN( "vcl.fonts", "GlyphOffsetsNew claimed to have "
|
||||
<< numTables << " tables, but that's impossibly large");
|
||||
numTables = nMaxPossibleTables;
|
||||
}
|
||||
|
||||
for (sal_uInt16 i = 0; i < numTables; i++) {
|
||||
sal_uInt32 nLargestFixedOffsetPos = 12 + 16 * i + 12;
|
||||
sal_uInt32 nMinSize = nLargestFixedOffsetPos + sizeof(sal_uInt32);
|
||||
if (nMinSize > sfntLen)
|
||||
{
|
||||
SAL_WARN( "vcl.fonts", "GlyphOffsetsNew claimed to have "
|
||||
<< numTables << " tables, but only space for " << i);
|
||||
break;
|
||||
}
|
||||
|
||||
sal_uInt32 tag = GetUInt32(sfntP, 12 + 16 * i);
|
||||
sal_uInt32 off = GetUInt32(sfntP, 12 + 16 * i + 8);
|
||||
sal_uInt32 len = GetUInt32(sfntP, nLargestFixedOffsetPos);
|
||||
|
||||
if (tag == T_loca) {
|
||||
loca = sfntP + off;
|
||||
locaLen = len;
|
||||
} else if (tag == T_head) {
|
||||
indexToLocFormat = GetInt16(sfntP + off, 50);
|
||||
}
|
||||
}
|
||||
|
||||
this->nGlyphs = locaLen / ((indexToLocFormat == 1) ? 4 : 2);
|
||||
assert(this->nGlyphs != 0);
|
||||
this->offs = std::make_unique<sal_uInt32[]>(this->nGlyphs);
|
||||
|
||||
for (sal_uInt32 i = 0; i < this->nGlyphs; i++) {
|
||||
if (indexToLocFormat == 1) {
|
||||
this->offs[i] = GetUInt32(loca, i * 4);
|
||||
} else {
|
||||
this->offs[i] = GetUInt16(loca, i * 2) << 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpSfnts(SvStream *outf, sal_uInt8 *sfntP, sal_uInt32 sfntLen)
|
||||
{
|
||||
if (sfntLen < 12)
|
||||
{
|
||||
SAL_WARN( "vcl.fonts", "DumpSfnts sfntLen is too short: "
|
||||
<< sfntLen << " legal min is: " << 12);
|
||||
return;
|
||||
}
|
||||
|
||||
const sal_uInt32 nSpaceForTables = sfntLen - 12;
|
||||
const sal_uInt32 nTableSize = 16;
|
||||
const sal_uInt32 nMaxPossibleTables = nSpaceForTables/nTableSize;
|
||||
|
||||
HexFmt h(outf);
|
||||
sal_uInt16 i, numTables = GetUInt16(sfntP, 4);
|
||||
GlyphOffsets go(sfntP, sfntLen);
|
||||
sal_uInt8 const pad[] = {0,0,0,0}; /* zeroes */
|
||||
|
||||
if (numTables > nMaxPossibleTables)
|
||||
{
|
||||
SAL_WARN( "vcl.fonts", "DumpSfnts claimed to have "
|
||||
<< numTables << " tables, but only space for " << nMaxPossibleTables);
|
||||
numTables = nMaxPossibleTables;
|
||||
}
|
||||
|
||||
assert(numTables <= 9); /* Type42 has 9 required tables */
|
||||
|
||||
std::unique_ptr<sal_uInt32[]> offs(new sal_uInt32[numTables]);
|
||||
|
||||
outf->WriteOString("/sfnts [");
|
||||
h.OpenString();
|
||||
h.BlockWrite(sfntP, 12); /* stream out the Offset Table */
|
||||
h.BlockWrite(sfntP+12, 16 * numTables); /* stream out the Table Directory */
|
||||
|
||||
for (i=0; i<numTables; i++)
|
||||
{
|
||||
sal_uInt32 nLargestFixedOffsetPos = 12 + 16 * i + 12;
|
||||
sal_uInt32 nMinSize = nLargestFixedOffsetPos + sizeof(sal_uInt32);
|
||||
if (nMinSize > sfntLen)
|
||||
{
|
||||
SAL_WARN( "vcl.fonts", "DumpSfnts claimed to have "
|
||||
<< numTables << " tables, but only space for " << i);
|
||||
break;
|
||||
}
|
||||
|
||||
sal_uInt32 tag = GetUInt32(sfntP, 12 + 16 * i);
|
||||
sal_uInt32 off = GetUInt32(sfntP, 12 + 16 * i + 8);
|
||||
if (off > sfntLen)
|
||||
{
|
||||
SAL_WARN( "vcl.fonts", "DumpSfnts claims offset of "
|
||||
<< off << " but max possible is " << sfntLen);
|
||||
break;
|
||||
}
|
||||
sal_uInt8 *pRecordStart = sfntP + off;
|
||||
sal_uInt32 len = GetUInt32(sfntP, nLargestFixedOffsetPos);
|
||||
sal_uInt32 nMaxLenPossible = sfntLen - off;
|
||||
if (len > nMaxLenPossible)
|
||||
{
|
||||
SAL_WARN( "vcl.fonts", "DumpSfnts claims len of "
|
||||
<< len << " but only space for " << nMaxLenPossible);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tag != T_glyf)
|
||||
{
|
||||
h.BlockWrite(pRecordStart, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
sal_uInt8 *glyf = pRecordStart;
|
||||
sal_uInt8 *eof = pRecordStart + nMaxLenPossible;
|
||||
for (sal_uInt32 j = 0; j < go.nGlyphs - 1; j++)
|
||||
{
|
||||
sal_uInt32 nStartOffset = go.offs[j];
|
||||
sal_uInt8 *pSubRecordStart = glyf + nStartOffset;
|
||||
if (pSubRecordStart > eof)
|
||||
{
|
||||
SAL_WARN( "vcl.fonts", "DumpSfnts start glyf claims offset of "
|
||||
<< pSubRecordStart - sfntP << " but max possible is " << eof - sfntP);
|
||||
break;
|
||||
}
|
||||
|
||||
sal_uInt32 nEndOffset = go.offs[j + 1];
|
||||
sal_uInt8 *pSubRecordEnd = glyf + nEndOffset;
|
||||
if (pSubRecordEnd > eof)
|
||||
{
|
||||
SAL_WARN( "vcl.fonts", "DumpSfnts end glyf offset of "
|
||||
<< pSubRecordEnd - sfntP << " but max possible is " << eof - sfntP);
|
||||
break;
|
||||
}
|
||||
|
||||
sal_uInt32 l = pSubRecordEnd - pSubRecordStart;
|
||||
h.BlockWrite(pSubRecordStart, l);
|
||||
}
|
||||
}
|
||||
h.BlockWrite(pad, (4 - (len & 3)) & 3);
|
||||
}
|
||||
h.CloseString();
|
||||
outf->WriteOString("] def\n");
|
||||
}
|
||||
|
||||
SFErrCodes CreateT42FromTTGlyphs(TrueTypeFont *ttf,
|
||||
SvStream *outf,
|
||||
const char *psname,
|
||||
sal_uInt16 const *glyphArray,
|
||||
sal_uInt8 *encoding,
|
||||
int nGlyphs)
|
||||
{
|
||||
std::unique_ptr<TrueTypeTable> head, hhea, maxp, cvt, prep, fpgm;
|
||||
std::unique_ptr<TrueTypeTableGlyf> glyf;
|
||||
int i;
|
||||
SFErrCodes res;
|
||||
|
||||
sal_uInt16 ver;
|
||||
sal_Int32 rev;
|
||||
|
||||
int UPEm = ttf->unitsPerEm();
|
||||
|
||||
if (nGlyphs >= 256) return SFErrCodes::GlyphNum;
|
||||
|
||||
assert(psname != nullptr);
|
||||
|
||||
TrueTypeCreator ttcr(T_true);
|
||||
|
||||
/* head */
|
||||
sal_uInt32 nTableSize;
|
||||
const sal_uInt8* p = ttf->table(O_head, nTableSize);
|
||||
const sal_uInt8* headP = p;
|
||||
assert(p != nullptr);
|
||||
head.reset(new TrueTypeTableHead(GetInt32(p, HEAD_fontRevision_offset), GetUInt16(p, HEAD_flags_offset), GetUInt16(p, HEAD_unitsPerEm_offset), p+HEAD_created_offset, GetUInt16(p, HEAD_macStyle_offset), GetUInt16(p, HEAD_lowestRecPPEM_offset), GetInt16(p, HEAD_fontDirectionHint_offset)));
|
||||
ver = GetUInt16(p, HEAD_majorVersion_offset);
|
||||
rev = GetInt32(p, HEAD_fontRevision_offset);
|
||||
|
||||
/** hhea **/
|
||||
p = ttf->table(O_hhea, nTableSize);
|
||||
if (p)
|
||||
hhea.reset(new TrueTypeTableHhea(GetInt16(p, HHEA_ascender_offset), GetInt16(p, HHEA_descender_offset), GetInt16(p, HHEA_lineGap_offset), GetInt16(p, HHEA_caretSlopeRise_offset), GetInt16(p, HHEA_caretSlopeRun_offset)));
|
||||
else
|
||||
hhea.reset(new TrueTypeTableHhea(0, 0, 0, 0, 0));
|
||||
|
||||
/** maxp **/
|
||||
p = ttf->table(O_maxp, nTableSize);
|
||||
maxp.reset(new TrueTypeTableMaxp(p, nTableSize));
|
||||
|
||||
/** cvt **/
|
||||
if ((p = ttf->table(O_cvt, nTableSize)) != nullptr)
|
||||
cvt.reset(new TrueTypeTableGeneric(T_cvt, nTableSize, p));
|
||||
|
||||
/** prep **/
|
||||
if ((p = ttf->table(O_prep, nTableSize)) != nullptr)
|
||||
prep.reset(new TrueTypeTableGeneric(T_prep, nTableSize, p));
|
||||
|
||||
/** fpgm **/
|
||||
if ((p = ttf->table(O_fpgm, nTableSize)) != nullptr)
|
||||
fpgm.reset(new TrueTypeTableGeneric(T_fpgm, nTableSize, p));
|
||||
|
||||
/** glyf **/
|
||||
glyf.reset(new TrueTypeTableGlyf());
|
||||
std::unique_ptr<sal_uInt16[]> gID(new sal_uInt16[nGlyphs]);
|
||||
|
||||
for (i = 0; i < nGlyphs; i++) {
|
||||
gID[i] = static_cast<sal_uInt16>(glyf->glyfAdd(GetTTRawGlyphData(ttf, glyphArray[i]), ttf));
|
||||
}
|
||||
|
||||
const int nGlyfCount = static_cast<int>(glyf->glyfCount());
|
||||
|
||||
ttcr.AddTable(std::move(head)); ttcr.AddTable(std::move(hhea)); ttcr.AddTable(std::move(maxp)); ttcr.AddTable(std::move(cvt));
|
||||
ttcr.AddTable(std::move(prep)); ttcr.AddTable(std::move(glyf)); ttcr.AddTable(std::move(fpgm));
|
||||
|
||||
std::vector<sal_uInt8> aOutBuffer;
|
||||
if ((res = ttcr.StreamToMemory(aOutBuffer)) != SFErrCodes::Ok) {
|
||||
return res;
|
||||
}
|
||||
|
||||
constexpr int bufmax = 256;
|
||||
char buf[bufmax];
|
||||
|
||||
snprintf(buf, bufmax, "%%!PS-TrueTypeFont-%d.%d-%d.%d\n", static_cast<int>(ver), static_cast<int>(ver & 0xFF), static_cast<int>(rev>>16), static_cast<int>(rev & 0xFFFF));
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "%%%%Creator: %s %s %s\n", modname, modver, modextra);
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "%%- Font subset generated from a source font file: '%s'\n", ttf->fileName().data());
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "%%- Original font name: %s\n", ttf->psname.getStr());
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "%%- Original font family: %s\n", ttf->family.getStr());
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "%%- Original font sub-family: %s\n", ttf->subfamily.getStr());
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "11 dict begin\n");
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "/FontName (%s) cvn def\n", psname);
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "/PaintType 0 def\n");
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "/FontMatrix [1 0 0 1 0 0] def\n");
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "/FontBBox [%d %d %d %d] def\n", XUnits(UPEm, GetInt16(headP, HEAD_xMin_offset)), XUnits(UPEm, GetInt16(headP, HEAD_yMin_offset)), XUnits(UPEm, GetInt16(headP, HEAD_xMax_offset)), XUnits(UPEm, GetInt16(headP, HEAD_yMax_offset)));
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "/FontType 42 def\n");
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "/Encoding 256 array def\n");
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, " 0 1 255 {Encoding exch /.notdef put} for\n");
|
||||
outf->WriteOString(buf);
|
||||
|
||||
for (i = 1; i<nGlyphs; i++) {
|
||||
snprintf(buf, bufmax, "Encoding %d /glyph%u put\n", encoding[i], gID[i]);
|
||||
outf->WriteOString(buf);
|
||||
}
|
||||
snprintf(buf, bufmax, "/XUID [103 0 1 16#%08X %u 16#%08X 16#%08X] def\n", static_cast<unsigned int>(rtl_crc32(0, ttf->ptr, ttf->fsize)), static_cast<unsigned int>(nGlyphs), static_cast<unsigned int>(rtl_crc32(0, glyphArray, nGlyphs * 2)), static_cast<unsigned int>(rtl_crc32(0, encoding, nGlyphs)));
|
||||
outf->WriteOString(buf);
|
||||
|
||||
DumpSfnts(outf, aOutBuffer.data(), aOutBuffer.size());
|
||||
|
||||
/* dump charstrings */
|
||||
snprintf(buf, bufmax, "/CharStrings %d dict dup begin\n", nGlyphs);
|
||||
outf->WriteOString(buf);
|
||||
snprintf(buf, bufmax, "/.notdef 0 def\n");
|
||||
outf->WriteOString(buf);
|
||||
for (i = 1; i < nGlyfCount; i++) {
|
||||
snprintf(buf, bufmax, "/glyph%d %d def\n", i, i);
|
||||
outf->WriteOString(buf);
|
||||
}
|
||||
snprintf(buf, bufmax, "end readonly def\n");
|
||||
outf->WriteOString(buf);
|
||||
|
||||
snprintf(buf, bufmax, "FontName currentdict end definefont pop\n");
|
||||
outf->WriteOString(buf);
|
||||
|
||||
return SFErrCodes::Ok;
|
||||
}
|
||||
|
||||
bool GetTTGlobalFontHeadInfo(const AbstractTrueTypeFont *ttf, int& xMin, int& yMin, int& xMax, int& yMax, sal_uInt16& macStyle)
|
||||
{
|
||||
sal_uInt32 table_size;
|
||||
|
||||
Reference in New Issue
Block a user