aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/matplotlib/py3/extern/ttconv
diff options
context:
space:
mode:
authorshumkovnd <shumkovnd@yandex-team.com>2023-11-10 14:39:34 +0300
committershumkovnd <shumkovnd@yandex-team.com>2023-11-10 16:42:24 +0300
commit77eb2d3fdcec5c978c64e025ced2764c57c00285 (patch)
treec51edb0748ca8d4a08d7c7323312c27ba1a8b79a /contrib/python/matplotlib/py3/extern/ttconv
parentdd6d20cadb65582270ac23f4b3b14ae189704b9d (diff)
downloadydb-77eb2d3fdcec5c978c64e025ced2764c57c00285.tar.gz
KIKIMR-19287: add task_stats_drawing script
Diffstat (limited to 'contrib/python/matplotlib/py3/extern/ttconv')
-rw-r--r--contrib/python/matplotlib/py3/extern/ttconv/pprdrv.h102
-rw-r--r--contrib/python/matplotlib/py3/extern/ttconv/pprdrv_tt.cpp1401
-rw-r--r--contrib/python/matplotlib/py3/extern/ttconv/pprdrv_tt2.cpp693
-rw-r--r--contrib/python/matplotlib/py3/extern/ttconv/truetype.h129
-rw-r--r--contrib/python/matplotlib/py3/extern/ttconv/ttutil.cpp71
-rw-r--r--contrib/python/matplotlib/py3/extern/ttconv/ya.make13
6 files changed, 2409 insertions, 0 deletions
diff --git a/contrib/python/matplotlib/py3/extern/ttconv/pprdrv.h b/contrib/python/matplotlib/py3/extern/ttconv/pprdrv.h
new file mode 100644
index 0000000000..8c0b6c1955
--- /dev/null
+++ b/contrib/python/matplotlib/py3/extern/ttconv/pprdrv.h
@@ -0,0 +1,102 @@
+/* -*- mode: c++; c-basic-offset: 4 -*- */
+
+/*
+ * Modified for use within matplotlib
+ * 5 July 2007
+ * Michael Droettboom
+ */
+
+/*
+** ~ppr/src/include/pprdrv.h
+** Copyright 1995, Trinity College Computing Center.
+** Written by David Chappell.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+**
+** This file last revised 5 December 1995.
+*/
+
+#include <vector>
+#include <cassert>
+
+/*
+ * Encapsulates all of the output to write to an arbitrary output
+ * function. This both removes the hardcoding of output to go to stdout
+ * and makes output thread-safe. Michael Droettboom [06-07-07]
+ */
+class TTStreamWriter
+{
+ private:
+ // Private copy and assignment
+ TTStreamWriter& operator=(const TTStreamWriter& other);
+ TTStreamWriter(const TTStreamWriter& other);
+
+ public:
+ TTStreamWriter() { }
+ virtual ~TTStreamWriter() { }
+
+ virtual void write(const char*) = 0;
+
+ virtual void printf(const char* format, ...);
+ virtual void put_char(int val);
+ virtual void puts(const char* a);
+ virtual void putline(const char* a);
+};
+
+void replace_newlines_with_spaces(char* a);
+
+/*
+ * A simple class for all ttconv exceptions.
+ */
+class TTException
+{
+ const char* message;
+ TTException& operator=(const TTStreamWriter& other);
+ TTException(const TTStreamWriter& other);
+
+public:
+ TTException(const char* message_) : message(message_) { }
+ const char* getMessage()
+ {
+ return message;
+ }
+};
+
+/*
+** No debug code will be included if this
+** is not defined:
+*/
+/* #define DEBUG 1 */
+
+/*
+** Uncomment the defines for the debugging
+** code you want to have included.
+*/
+#ifdef DEBUG
+#define DEBUG_TRUETYPE /* truetype fonts, conversion to Postscript */
+#endif
+
+#if DEBUG_TRUETYPE
+#define debug(...) printf(__VA_ARGS__)
+#else
+#define debug(...)
+#endif
+
+/* Do not change anything below this line. */
+
+enum font_type_enum
+{
+ PS_TYPE_3 = 3,
+ PS_TYPE_42 = 42,
+ PS_TYPE_42_3_HYBRID = 43,
+};
+
+/* routines in pprdrv_tt.c */
+void insert_ttfont(const char *filename, TTStreamWriter& stream, font_type_enum target_type, std::vector<int>& glyph_ids);
+
+/* end of file */
diff --git a/contrib/python/matplotlib/py3/extern/ttconv/pprdrv_tt.cpp b/contrib/python/matplotlib/py3/extern/ttconv/pprdrv_tt.cpp
new file mode 100644
index 0000000000..a0c724c8aa
--- /dev/null
+++ b/contrib/python/matplotlib/py3/extern/ttconv/pprdrv_tt.cpp
@@ -0,0 +1,1401 @@
+/* -*- mode: c++; c-basic-offset: 4 -*- */
+
+/*
+ * Modified for use within matplotlib
+ * 5 July 2007
+ * Michael Droettboom
+ */
+
+/*
+** ~ppr/src/pprdrv/pprdrv_tt.c
+** Copyright 1995, Trinity College Computing Center.
+** Written by David Chappell.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+**
+** TrueType font support. These functions allow PPR to generate
+** PostScript fonts from Microsoft compatible TrueType font files.
+**
+** Last revised 19 December 1995.
+*/
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include "pprdrv.h"
+#include "truetype.h"
+#include <sstream>
+#ifdef _POSIX_C_SOURCE
+# undef _POSIX_C_SOURCE
+#endif
+#ifndef _AIX
+#ifdef _XOPEN_SOURCE
+# undef _XOPEN_SOURCE
+#endif
+#endif
+#include <Python.h>
+
+/*==========================================================================
+** Convert the indicated Truetype font file to a type 42 or type 3
+** PostScript font and insert it in the output stream.
+**
+** All the routines from here to the end of file file are involved
+** in this process.
+==========================================================================*/
+
+/*---------------------------------------
+** Endian conversion routines.
+** These routines take a BYTE pointer
+** and return a value formed by reading
+** bytes starting at that point.
+**
+** These routines read the big-endian
+** values which are used in TrueType
+** font files.
+---------------------------------------*/
+
+/*
+** Get an Unsigned 32 bit number.
+*/
+ULONG getULONG(BYTE *p)
+{
+ int x;
+ ULONG val=0;
+
+ for (x=0; x<4; x++)
+ {
+ val *= 0x100;
+ val += p[x];
+ }
+
+ return val;
+} /* end of ftohULONG() */
+
+/*
+** Get an unsigned 16 bit number.
+*/
+USHORT getUSHORT(BYTE *p)
+{
+ int x;
+ USHORT val=0;
+
+ for (x=0; x<2; x++)
+ {
+ val *= 0x100;
+ val += p[x];
+ }
+
+ return val;
+} /* end of getUSHORT() */
+
+/*
+** Get a 32 bit fixed point (16.16) number.
+** A special structure is used to return the value.
+*/
+Fixed getFixed(BYTE *s)
+{
+ Fixed val={0,0};
+
+ val.whole = ((s[0] * 256) + s[1]);
+ val.fraction = ((s[2] * 256) + s[3]);
+
+ return val;
+} /* end of getFixed() */
+
+/*-----------------------------------------------------------------------
+** Load a TrueType font table into memory and return a pointer to it.
+** The font's "file" and "offset_table" fields must be set before this
+** routine is called.
+**
+** This first argument is a TrueType font structure, the second
+** argument is the name of the table to retrieve. A table name
+** is always 4 characters, though the last characters may be
+** padding spaces.
+-----------------------------------------------------------------------*/
+BYTE *GetTable(struct TTFONT *font, const char *name)
+{
+ BYTE *ptr;
+ ULONG x;
+ debug("GetTable(file,font,\"%s\")",name);
+
+ /* We must search the table directory. */
+ ptr = font->offset_table + 12;
+ x=0;
+ while (true)
+ {
+ if ( strncmp((const char*)ptr,name,4) == 0 )
+ {
+ ULONG offset,length;
+ BYTE *table;
+
+ offset = getULONG( ptr + 8 );
+ length = getULONG( ptr + 12 );
+ table = (BYTE*)calloc( sizeof(BYTE), length + 2 );
+
+ try
+ {
+ debug("Loading table \"%s\" from offset %d, %d bytes",name,offset,length);
+
+ if ( fseek( font->file, (long)offset, SEEK_SET ) )
+ {
+ throw TTException("TrueType font may be corrupt (reason 3)");
+ }
+
+ if ( fread(table,sizeof(BYTE),length,font->file) != (sizeof(BYTE) * length))
+ {
+ throw TTException("TrueType font may be corrupt (reason 4)");
+ }
+ }
+ catch (TTException& )
+ {
+ free(table);
+ throw;
+ }
+ /* Always NUL-terminate; add two in case of UTF16 strings. */
+ table[length] = '\0';
+ table[length + 1] = '\0';
+ return table;
+ }
+
+ x++;
+ ptr += 16;
+ if (x == font->numTables)
+ {
+ throw TTException("TrueType font is missing table");
+ }
+ }
+
+} /* end of GetTable() */
+
+static void utf16be_to_ascii(char *dst, char *src, size_t length) {
+ ++src;
+ for (; *src != 0 && length; dst++, src += 2, --length) {
+ *dst = *src;
+ }
+}
+
+/*--------------------------------------------------------------------
+** Load the 'name' table, get information from it,
+** and store that information in the font structure.
+**
+** The 'name' table contains information such as the name of
+** the font, and it's PostScript name.
+--------------------------------------------------------------------*/
+void Read_name(struct TTFONT *font)
+{
+ BYTE *table_ptr,*ptr2;
+ int numrecords; /* Number of strings in this table */
+ BYTE *strings; /* pointer to start of string storage */
+ int x;
+ int platform; /* Current platform id */
+ int nameid; /* name id, */
+ int offset,length; /* offset and length of string. */
+ debug("Read_name()");
+
+ table_ptr = NULL;
+
+ /* Set default values to avoid future references to undefined
+ * pointers. Allocate each of PostName, FullName, FamilyName,
+ * Version, and Style separately so they can be freed safely. */
+ for (char **ptr = &(font->PostName); ptr != NULL; )
+ {
+ *ptr = (char*) calloc(sizeof(char), strlen("unknown")+1);
+ strcpy(*ptr, "unknown");
+ if (ptr == &(font->PostName)) ptr = &(font->FullName);
+ else if (ptr == &(font->FullName)) ptr = &(font->FamilyName);
+ else if (ptr == &(font->FamilyName)) ptr = &(font->Version);
+ else if (ptr == &(font->Version)) ptr = &(font->Style);
+ else ptr = NULL;
+ }
+ font->Copyright = font->Trademark = (char*)NULL;
+
+ table_ptr = GetTable(font, "name"); /* pointer to table */
+ try
+ {
+ numrecords = getUSHORT( table_ptr + 2 ); /* number of names */
+ strings = table_ptr + getUSHORT( table_ptr + 4 ); /* start of string storage */
+
+ ptr2 = table_ptr + 6;
+ for (x=0; x < numrecords; x++,ptr2+=12)
+ {
+ platform = getUSHORT(ptr2);
+ nameid = getUSHORT(ptr2+6);
+ length = getUSHORT(ptr2+8);
+ offset = getUSHORT(ptr2+10);
+ debug("platform %d, encoding %d, language 0x%x, name %d, offset %d, length %d",
+ platform,encoding,language,nameid,offset,length);
+
+ /* Copyright notice */
+ if ( platform == 1 && nameid == 0 )
+ {
+ font->Copyright = (char*)calloc(sizeof(char),length+1);
+ strncpy(font->Copyright,(const char*)strings+offset,length);
+ font->Copyright[length]='\0';
+ replace_newlines_with_spaces(font->Copyright);
+ debug("font->Copyright=\"%s\"",font->Copyright);
+ continue;
+ }
+
+
+ /* Font Family name */
+ if ( platform == 1 && nameid == 1 )
+ {
+ free(font->FamilyName);
+ font->FamilyName = (char*)calloc(sizeof(char),length+1);
+ strncpy(font->FamilyName,(const char*)strings+offset,length);
+ font->FamilyName[length]='\0';
+ replace_newlines_with_spaces(font->FamilyName);
+ debug("font->FamilyName=\"%s\"",font->FamilyName);
+ continue;
+ }
+
+
+ /* Font Family name */
+ if ( platform == 1 && nameid == 2 )
+ {
+ free(font->Style);
+ font->Style = (char*)calloc(sizeof(char),length+1);
+ strncpy(font->Style,(const char*)strings+offset,length);
+ font->Style[length]='\0';
+ replace_newlines_with_spaces(font->Style);
+ debug("font->Style=\"%s\"",font->Style);
+ continue;
+ }
+
+
+ /* Full Font name */
+ if ( platform == 1 && nameid == 4 )
+ {
+ free(font->FullName);
+ font->FullName = (char*)calloc(sizeof(char),length+1);
+ strncpy(font->FullName,(const char*)strings+offset,length);
+ font->FullName[length]='\0';
+ replace_newlines_with_spaces(font->FullName);
+ debug("font->FullName=\"%s\"",font->FullName);
+ continue;
+ }
+
+
+ /* Version string */
+ if ( platform == 1 && nameid == 5 )
+ {
+ free(font->Version);
+ font->Version = (char*)calloc(sizeof(char),length+1);
+ strncpy(font->Version,(const char*)strings+offset,length);
+ font->Version[length]='\0';
+ replace_newlines_with_spaces(font->Version);
+ debug("font->Version=\"%s\"",font->Version);
+ continue;
+ }
+
+
+ /* PostScript name */
+ if ( platform == 1 && nameid == 6 )
+ {
+ free(font->PostName);
+ font->PostName = (char*)calloc(sizeof(char),length+1);
+ strncpy(font->PostName,(const char*)strings+offset,length);
+ font->PostName[length]='\0';
+ replace_newlines_with_spaces(font->PostName);
+ debug("font->PostName=\"%s\"",font->PostName);
+ continue;
+ }
+
+ /* Microsoft-format PostScript name */
+ if ( platform == 3 && nameid == 6 )
+ {
+ free(font->PostName);
+ font->PostName = (char*)calloc(sizeof(char),length+1);
+ utf16be_to_ascii(font->PostName, (char *)strings+offset, length);
+ font->PostName[length/2]='\0';
+ replace_newlines_with_spaces(font->PostName);
+ debug("font->PostName=\"%s\"",font->PostName);
+ continue;
+ }
+
+
+ /* Trademark string */
+ if ( platform == 1 && nameid == 7 )
+ {
+ font->Trademark = (char*)calloc(sizeof(char),length+1);
+ strncpy(font->Trademark,(const char*)strings+offset,length);
+ font->Trademark[length]='\0';
+ replace_newlines_with_spaces(font->Trademark);
+ debug("font->Trademark=\"%s\"",font->Trademark);
+ continue;
+ }
+ }
+ }
+ catch (TTException& )
+ {
+ free(table_ptr);
+ throw;
+ }
+
+ free(table_ptr);
+} /* end of Read_name() */
+
+/*---------------------------------------------------------------------
+** Write the header for a PostScript font.
+---------------------------------------------------------------------*/
+void ttfont_header(TTStreamWriter& stream, struct TTFONT *font)
+{
+ int VMMin;
+ int VMMax;
+
+ /*
+ ** To show that it is a TrueType font in PostScript format,
+ ** we will begin the file with a specific string.
+ ** This string also indicates the version of the TrueType
+ ** specification on which the font is based and the
+ ** font manufacturer's revision number for the font.
+ */
+ if ( font->target_type == PS_TYPE_42 ||
+ font->target_type == PS_TYPE_42_3_HYBRID)
+ {
+ stream.printf("%%!PS-TrueTypeFont-%d.%d-%d.%d\n",
+ font->TTVersion.whole, font->TTVersion.fraction,
+ font->MfrRevision.whole, font->MfrRevision.fraction);
+ }
+
+ /* If it is not a Type 42 font, we will use a different format. */
+ else
+ {
+ stream.putline("%!PS-Adobe-3.0 Resource-Font");
+ } /* See RBIIp 641 */
+
+ /* We will make the title the name of the font. */
+ stream.printf("%%%%Title: %s\n",font->FullName);
+
+ /* If there is a Copyright notice, put it here too. */
+ if ( font->Copyright != (char*)NULL )
+ {
+ stream.printf("%%%%Copyright: %s\n",font->Copyright);
+ }
+
+ /* We created this file. */
+ if ( font->target_type == PS_TYPE_42 )
+ {
+ stream.putline("%%Creator: Converted from TrueType to type 42 by PPR");
+ }
+ else if (font->target_type == PS_TYPE_42_3_HYBRID)
+ {
+ stream.putline("%%Creator: Converted from TypeType to type 42/type 3 hybrid by PPR");
+ }
+ else
+ {
+ stream.putline("%%Creator: Converted from TrueType to type 3 by PPR");
+ }
+
+ /* If VM usage information is available, print it. */
+ if ( font->target_type == PS_TYPE_42 || font->target_type == PS_TYPE_42_3_HYBRID)
+ {
+ VMMin = (int)getULONG( font->post_table + 16 );
+ VMMax = (int)getULONG( font->post_table + 20 );
+ if ( VMMin > 0 && VMMax > 0 )
+ stream.printf("%%%%VMUsage: %d %d\n",VMMin,VMMax);
+ }
+
+ /* Start the dictionary which will eventually */
+ /* become the font. */
+ if (font->target_type == PS_TYPE_42)
+ {
+ stream.putline("15 dict begin");
+ }
+ else
+ {
+ stream.putline("25 dict begin");
+
+ /* Type 3 fonts will need some subroutines here. */
+ stream.putline("/_d{bind def}bind def");
+ stream.putline("/_m{moveto}_d");
+ stream.putline("/_l{lineto}_d");
+ stream.putline("/_cl{closepath eofill}_d");
+ stream.putline("/_c{curveto}_d");
+ stream.putline("/_sc{7 -1 roll{setcachedevice}{pop pop pop pop pop pop}ifelse}_d");
+ stream.putline("/_e{exec}_d");
+ }
+
+ stream.printf("/FontName /%s def\n",font->PostName);
+ stream.putline("/PaintType 0 def");
+
+ if (font->target_type == PS_TYPE_42 || font->target_type == PS_TYPE_42_3_HYBRID)
+ {
+ stream.putline("/FontMatrix[1 0 0 1 0 0]def");
+ }
+ else
+ {
+ stream.putline("/FontMatrix[.001 0 0 .001 0 0]def");
+ }
+
+ stream.printf("/FontBBox[%d %d %d %d]def\n",font->llx-1,font->lly-1,font->urx,font->ury);
+ if (font->target_type == PS_TYPE_42 || font->target_type == PS_TYPE_42_3_HYBRID)
+ {
+ stream.printf("/FontType 42 def\n", font->target_type );
+ }
+ else
+ {
+ stream.printf("/FontType 3 def\n", font->target_type );
+ }
+} /* end of ttfont_header() */
+
+/*-------------------------------------------------------------
+** Define the encoding array for this font.
+** Since we don't really want to deal with converting all of
+** the possible font encodings in the wild to a standard PS
+** one, we just explicitly create one for each font.
+-------------------------------------------------------------*/
+void ttfont_encoding(TTStreamWriter& stream, struct TTFONT *font, std::vector<int>& glyph_ids, font_type_enum target_type)
+{
+ if (target_type == PS_TYPE_3 || target_type == PS_TYPE_42_3_HYBRID)
+ {
+ stream.printf("/Encoding [ ");
+
+ for (std::vector<int>::const_iterator i = glyph_ids.begin();
+ i != glyph_ids.end(); ++i)
+ {
+ const char* name = ttfont_CharStrings_getname(font, *i);
+ stream.printf("/%s ", name);
+ }
+
+ stream.printf("] def\n");
+ }
+ else
+ {
+ stream.putline("/Encoding StandardEncoding def");
+ }
+} /* end of ttfont_encoding() */
+
+/*-----------------------------------------------------------
+** Create the optional "FontInfo" sub-dictionary.
+-----------------------------------------------------------*/
+void ttfont_FontInfo(TTStreamWriter& stream, struct TTFONT *font)
+{
+ Fixed ItalicAngle;
+
+ /* We create a sub dictionary named "FontInfo" where we */
+ /* store information which though it is not used by the */
+ /* interpreter, is useful to some programs which will */
+ /* be printing with the font. */
+ stream.putline("/FontInfo 10 dict dup begin");
+
+ /* These names come from the TrueType font's "name" table. */
+ stream.printf("/FamilyName (%s) def\n",font->FamilyName);
+ stream.printf("/FullName (%s) def\n",font->FullName);
+
+ if ( font->Copyright != (char*)NULL || font->Trademark != (char*)NULL )
+ {
+ stream.printf("/Notice (%s",
+ font->Copyright != (char*)NULL ? font->Copyright : "");
+ stream.printf("%s%s) def\n",
+ font->Trademark != (char*)NULL ? " " : "",
+ font->Trademark != (char*)NULL ? font->Trademark : "");
+ }
+
+ /* This information is not quite correct. */
+ stream.printf("/Weight (%s) def\n",font->Style);
+
+ /* Some fonts have this as "version". */
+ stream.printf("/Version (%s) def\n",font->Version);
+
+ /* Some information from the "post" table. */
+ ItalicAngle = getFixed( font->post_table + 4 );
+ stream.printf("/ItalicAngle %d.%d def\n",ItalicAngle.whole,ItalicAngle.fraction);
+ stream.printf("/isFixedPitch %s def\n", getULONG( font->post_table + 12 ) ? "true" : "false" );
+ stream.printf("/UnderlinePosition %d def\n", (int)getFWord( font->post_table + 8 ) );
+ stream.printf("/UnderlineThickness %d def\n", (int)getFWord( font->post_table + 10 ) );
+ stream.putline("end readonly def");
+} /* end of ttfont_FontInfo() */
+
+/*-------------------------------------------------------------------
+** sfnts routines
+** These routines generate the PostScript "sfnts" array which
+** contains one or more strings which contain a reduced version
+** of the TrueType font.
+**
+** A number of functions are required to accomplish this rather
+** complicated task.
+-------------------------------------------------------------------*/
+int string_len;
+int line_len;
+bool in_string;
+
+/*
+** This is called once at the start.
+*/
+void sfnts_start(TTStreamWriter& stream)
+{
+ stream.puts("/sfnts[<");
+ in_string=true;
+ string_len=0;
+ line_len=8;
+} /* end of sfnts_start() */
+
+/*
+** Write a BYTE as a hexadecimal value as part of the sfnts array.
+*/
+void sfnts_pputBYTE(TTStreamWriter& stream, BYTE n)
+{
+ static const char hexdigits[]="0123456789ABCDEF";
+
+ if (!in_string)
+ {
+ stream.put_char('<');
+ string_len=0;
+ line_len++;
+ in_string=true;
+ }
+
+ stream.put_char( hexdigits[ n / 16 ] );
+ stream.put_char( hexdigits[ n % 16 ] );
+ string_len++;
+ line_len+=2;
+
+ if (line_len > 70)
+ {
+ stream.put_char('\n');
+ line_len=0;
+ }
+
+} /* end of sfnts_pputBYTE() */
+
+/*
+** Write a USHORT as a hexadecimal value as part of the sfnts array.
+*/
+void sfnts_pputUSHORT(TTStreamWriter& stream, USHORT n)
+{
+ sfnts_pputBYTE(stream, n / 256);
+ sfnts_pputBYTE(stream, n % 256);
+} /* end of sfnts_pputUSHORT() */
+
+/*
+** Write a ULONG as part of the sfnts array.
+*/
+void sfnts_pputULONG(TTStreamWriter& stream, ULONG n)
+{
+ int x1,x2,x3;
+
+ x1 = n % 256;
+ n /= 256;
+ x2 = n % 256;
+ n /= 256;
+ x3 = n % 256;
+ n /= 256;
+
+ sfnts_pputBYTE(stream, n);
+ sfnts_pputBYTE(stream, x3);
+ sfnts_pputBYTE(stream, x2);
+ sfnts_pputBYTE(stream, x1);
+} /* end of sfnts_pputULONG() */
+
+/*
+** This is called whenever it is
+** necessary to end a string in the sfnts array.
+**
+** (The array must be broken into strings which are
+** no longer than 64K characters.)
+*/
+void sfnts_end_string(TTStreamWriter& stream)
+{
+ if (in_string)
+ {
+ string_len=0; /* fool sfnts_pputBYTE() */
+
+#ifdef DEBUG_TRUETYPE_INLINE
+ puts("\n% dummy byte:\n");
+#endif
+
+ sfnts_pputBYTE(stream, 0); /* extra byte for pre-2013 compatibility */
+ stream.put_char('>');
+ line_len++;
+ }
+ in_string=false;
+} /* end of sfnts_end_string() */
+
+/*
+** This is called at the start of each new table.
+** The argement is the length in bytes of the table
+** which will follow. If the new table will not fit
+** in the current string, a new one is started.
+*/
+void sfnts_new_table(TTStreamWriter& stream, ULONG length)
+{
+ if ( (string_len + length) > 65528 )
+ sfnts_end_string(stream);
+} /* end of sfnts_new_table() */
+
+/*
+** We may have to break up the 'glyf' table. That is the reason
+** why we provide this special routine to copy it into the sfnts
+** array.
+*/
+void sfnts_glyf_table(TTStreamWriter& stream, struct TTFONT *font, ULONG oldoffset, ULONG correct_total_length)
+{
+ ULONG off;
+ ULONG length;
+ int c;
+ ULONG total=0; /* running total of bytes written to table */
+ int x;
+ bool loca_is_local=false;
+ debug("sfnts_glyf_table(font,%d)", (int)correct_total_length);
+
+ if (font->loca_table == NULL)
+ {
+ font->loca_table = GetTable(font,"loca");
+ loca_is_local = true;
+ }
+
+ /* Seek to proper position in the file. */
+ fseek( font->file, oldoffset, SEEK_SET );
+
+ /* Copy the glyphs one by one */
+ for (x=0; x < font->numGlyphs; x++)
+ {
+ /* Read the glyph offset from the index-to-location table. */
+ if (font->indexToLocFormat == 0)
+ {
+ off = getUSHORT( font->loca_table + (x * 2) );
+ off *= 2;
+ length = getUSHORT( font->loca_table + ((x+1) * 2) );
+ length *= 2;
+ length -= off;
+ }
+ else
+ {
+ off = getULONG( font->loca_table + (x * 4) );
+ length = getULONG( font->loca_table + ((x+1) * 4) );
+ length -= off;
+ }
+ debug("glyph length=%d",(int)length);
+
+ /* Start new string if necessary. */
+ sfnts_new_table( stream, (int)length );
+
+ /*
+ ** Make sure the glyph is padded out to a
+ ** two byte boundary.
+ */
+ if ( length % 2 ) {
+ throw TTException("TrueType font contains a 'glyf' table without 2 byte padding");
+ }
+
+ /* Copy the bytes of the glyph. */
+ while ( length-- )
+ {
+ if ( (c = fgetc(font->file)) == EOF ) {
+ throw TTException("TrueType font may be corrupt (reason 6)");
+ }
+
+ sfnts_pputBYTE(stream, c);
+ total++; /* add to running total */
+ }
+
+ }
+
+ if (loca_is_local)
+ {
+ free(font->loca_table);
+ font->loca_table = NULL;
+ }
+
+ /* Pad out to full length from table directory */
+ while ( total < correct_total_length )
+ {
+ sfnts_pputBYTE(stream, 0);
+ total++;
+ }
+
+} /* end of sfnts_glyf_table() */
+
+/*
+** Here is the routine which ties it all together.
+**
+** Create the array called "sfnts" which
+** holds the actual TrueType data.
+*/
+void ttfont_sfnts(TTStreamWriter& stream, struct TTFONT *font)
+{
+ static const char *table_names[] = /* The names of all tables */
+ {
+ /* which it is worth while */
+ "cvt ", /* to include in a Type 42 */
+ "fpgm", /* PostScript font. */
+ "glyf",
+ "head",
+ "hhea",
+ "hmtx",
+ "loca",
+ "maxp",
+ "prep"
+ } ;
+
+ struct /* The location of each of */
+ {
+ ULONG oldoffset; /* the above tables. */
+ ULONG newoffset;
+ ULONG length;
+ ULONG checksum;
+ } tables[9];
+
+ BYTE *ptr; /* A pointer into the origional table directory. */
+ ULONG x,y; /* General use loop countes. */
+ int c; /* Input character. */
+ int diff;
+ ULONG nextoffset;
+ int count; /* How many `important' tables did we find? */
+
+ ptr = font->offset_table + 12;
+ nextoffset=0;
+ count=0;
+
+ /*
+ ** Find the tables we want and store there vital
+ ** statistics in tables[].
+ */
+ ULONG num_tables_read = 0; /* Number of tables read from the directory */
+ for (x = 0; x < 9; x++) {
+ do {
+ if (num_tables_read < font->numTables) {
+ /* There are still tables to read from ptr */
+ diff = strncmp((char*)ptr, table_names[x], 4);
+
+ if (diff > 0) { /* If we are past it. */
+ tables[x].length = 0;
+ diff = 0;
+ } else if (diff < 0) { /* If we haven't hit it yet. */
+ ptr += 16;
+ num_tables_read++;
+ } else if (diff == 0) { /* Here it is! */
+ tables[x].newoffset = nextoffset;
+ tables[x].checksum = getULONG( ptr + 4 );
+ tables[x].oldoffset = getULONG( ptr + 8 );
+ tables[x].length = getULONG( ptr + 12 );
+ nextoffset += ( ((tables[x].length + 3) / 4) * 4 );
+ count++;
+ ptr += 16;
+ num_tables_read++;
+ }
+ } else {
+ /* We've read the whole table directory already */
+ /* Some tables couldn't be found */
+ tables[x].length = 0;
+ break; /* Proceed to next tables[x] */
+ }
+ } while (diff != 0);
+
+ } /* end of for loop which passes over the table directory */
+
+ /* Begin the sfnts array. */
+ sfnts_start(stream);
+
+ /* Generate the offset table header */
+ /* Start by copying the TrueType version number. */
+ ptr = font->offset_table;
+ for (x=0; x < 4; x++)
+ {
+ sfnts_pputBYTE( stream, *(ptr++) );
+ }
+
+ /* Now, generate those silly numTables numbers. */
+ sfnts_pputUSHORT(stream, count); /* number of tables */
+
+ int search_range = 1;
+ int entry_sel = 0;
+
+ while (search_range <= count) {
+ search_range <<= 1;
+ entry_sel++;
+ }
+ entry_sel = entry_sel > 0 ? entry_sel - 1 : 0;
+ search_range = (search_range >> 1) * 16;
+ int range_shift = count * 16 - search_range;
+
+ sfnts_pputUSHORT(stream, search_range); /* searchRange */
+ sfnts_pputUSHORT(stream, entry_sel); /* entrySelector */
+ sfnts_pputUSHORT(stream, range_shift); /* rangeShift */
+
+ debug("only %d tables selected",count);
+
+ /* Now, emmit the table directory. */
+ for (x=0; x < 9; x++)
+ {
+ if ( tables[x].length == 0 ) /* Skip missing tables */
+ {
+ continue;
+ }
+
+ /* Name */
+ sfnts_pputBYTE( stream, table_names[x][0] );
+ sfnts_pputBYTE( stream, table_names[x][1] );
+ sfnts_pputBYTE( stream, table_names[x][2] );
+ sfnts_pputBYTE( stream, table_names[x][3] );
+
+ /* Checksum */
+ sfnts_pputULONG( stream, tables[x].checksum );
+
+ /* Offset */
+ sfnts_pputULONG( stream, tables[x].newoffset + 12 + (count * 16) );
+
+ /* Length */
+ sfnts_pputULONG( stream, tables[x].length );
+ }
+
+ /* Now, send the tables */
+ for (x=0; x < 9; x++)
+ {
+ if ( tables[x].length == 0 ) /* skip tables that aren't there */
+ {
+ continue;
+ }
+ debug("emmiting table '%s'",table_names[x]);
+
+ /* 'glyf' table gets special treatment */
+ if ( strcmp(table_names[x],"glyf")==0 )
+ {
+ sfnts_glyf_table(stream,font,tables[x].oldoffset,tables[x].length);
+ }
+ else /* Other tables may not exceed */
+ {
+ /* 65535 bytes in length. */
+ if ( tables[x].length > 65535 )
+ {
+ throw TTException("TrueType font has a table which is too long");
+ }
+
+ /* Start new string if necessary. */
+ sfnts_new_table(stream, tables[x].length);
+
+ /* Seek to proper position in the file. */
+ fseek( font->file, tables[x].oldoffset, SEEK_SET );
+
+ /* Copy the bytes of the table. */
+ for ( y=0; y < tables[x].length; y++ )
+ {
+ if ( (c = fgetc(font->file)) == EOF )
+ {
+ throw TTException("TrueType font may be corrupt (reason 7)");
+ }
+
+ sfnts_pputBYTE(stream, c);
+ }
+ }
+
+ /* Padd it out to a four byte boundary. */
+ y=tables[x].length;
+ while ( (y % 4) != 0 )
+ {
+ sfnts_pputBYTE(stream, 0);
+ y++;
+#ifdef DEBUG_TRUETYPE_INLINE
+ puts("\n% pad byte:\n");
+#endif
+ }
+
+ } /* End of loop for all tables */
+
+ /* Close the array. */
+ sfnts_end_string(stream);
+ stream.putline("]def");
+} /* end of ttfont_sfnts() */
+
+/*--------------------------------------------------------------
+** Create the CharStrings dictionary which will translate
+** PostScript character names to TrueType font character
+** indexes.
+**
+** If we are creating a type 3 instead of a type 42 font,
+** this array will instead convert PostScript character names
+** to executable proceedures.
+--------------------------------------------------------------*/
+const char *Apple_CharStrings[]=
+{
+ ".notdef",".null","nonmarkingreturn","space","exclam","quotedbl","numbersign",
+ "dollar","percent","ampersand","quotesingle","parenleft","parenright",
+ "asterisk","plus", "comma","hyphen","period","slash","zero","one","two",
+ "three","four","five","six","seven","eight","nine","colon","semicolon",
+ "less","equal","greater","question","at","A","B","C","D","E","F","G","H","I",
+ "J","K", "L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
+ "bracketleft","backslash","bracketright","asciicircum","underscore","grave",
+ "a","b","c","d","e","f","g","h","i","j","k", "l","m","n","o","p","q","r","s",
+ "t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde",
+ "Adieresis","Aring","Ccedilla","Eacute","Ntilde","Odieresis","Udieresis",
+ "aacute","agrave","acircumflex","adieresis","atilde","aring","ccedilla",
+ "eacute","egrave","ecircumflex","edieresis","iacute","igrave","icircumflex",
+ "idieresis","ntilde","oacute","ograve","ocircumflex","odieresis","otilde",
+ "uacute","ugrave","ucircumflex","udieresis","dagger","degree","cent",
+ "sterling","section","bullet","paragraph","germandbls","registered",
+ "copyright","trademark","acute","dieresis","notequal","AE","Oslash",
+ "infinity","plusminus","lessequal","greaterequal","yen","mu","partialdiff",
+ "summation","product","pi","integral","ordfeminine","ordmasculine","Omega",
+ "ae","oslash","questiondown","exclamdown","logicalnot","radical","florin",
+ "approxequal","Delta","guillemotleft","guillemotright","ellipsis",
+ "nobreakspace","Agrave","Atilde","Otilde","OE","oe","endash","emdash",
+ "quotedblleft","quotedblright","quoteleft","quoteright","divide","lozenge",
+ "ydieresis","Ydieresis","fraction","currency","guilsinglleft","guilsinglright",
+ "fi","fl","daggerdbl","periodcentered","quotesinglbase","quotedblbase",
+ "perthousand","Acircumflex","Ecircumflex","Aacute","Edieresis","Egrave",
+ "Iacute","Icircumflex","Idieresis","Igrave","Oacute","Ocircumflex","apple",
+ "Ograve","Uacute","Ucircumflex","Ugrave","dotlessi","circumflex","tilde",
+ "macron","breve","dotaccent","ring","cedilla","hungarumlaut","ogonek","caron",
+ "Lslash","lslash","Scaron","scaron","Zcaron","zcaron","brokenbar","Eth","eth",
+ "Yacute","yacute","Thorn","thorn","minus","multiply","onesuperior",
+ "twosuperior","threesuperior","onehalf","onequarter","threequarters","franc",
+ "Gbreve","gbreve","Idot","Scedilla","scedilla","Cacute","cacute","Ccaron",
+ "ccaron","dmacron","markingspace","capslock","shift","propeller","enter",
+ "markingtabrtol","markingtabltor","control","markingdeleteltor",
+ "markingdeletertol","option","escape","parbreakltor","parbreakrtol",
+ "newpage","checkmark","linebreakltor","linebreakrtol","markingnobreakspace",
+ "diamond","appleoutline"
+};
+
+/*
+** This routine is called by the one below.
+** It is also called from pprdrv_tt2.c
+*/
+const char *ttfont_CharStrings_getname(struct TTFONT *font, int charindex)
+{
+ int GlyphIndex;
+ static char temp[80];
+ char *ptr;
+ ULONG len;
+
+ Fixed post_format;
+
+ /* The 'post' table format number. */
+ post_format = getFixed( font->post_table );
+
+ if ( post_format.whole != 2 || post_format.fraction != 0 )
+ {
+ /* We don't have a glyph name table, so generate a name.
+ This generated name must match exactly the name that is
+ generated by FT2Font in get_glyph_name */
+ PyOS_snprintf(temp, 80, "uni%08x", charindex);
+ return temp;
+ }
+
+ GlyphIndex = (int)getUSHORT( font->post_table + 34 + (charindex * 2) );
+
+ if ( GlyphIndex <= 257 ) /* If a standard Apple name, */
+ {
+ return Apple_CharStrings[GlyphIndex];
+ }
+ else /* Otherwise, use one */
+ {
+ /* of the pascal strings. */
+ GlyphIndex -= 258;
+
+ /* Set pointer to start of Pascal strings. */
+ ptr = (char*)(font->post_table + 34 + (font->numGlyphs * 2));
+
+ len = (ULONG)*(ptr++); /* Step thru the strings */
+ while (GlyphIndex--) /* until we get to the one */
+ {
+ /* that we want. */
+ ptr += len;
+ len = (ULONG)*(ptr++);
+ }
+
+ if ( len >= sizeof(temp) )
+ {
+ throw TTException("TrueType font file contains a very long PostScript name");
+ }
+
+ strncpy(temp,ptr,len); /* Copy the pascal string into */
+ temp[len]='\0'; /* a buffer and make it ASCIIz. */
+
+ return temp;
+ }
+} /* end of ttfont_CharStrings_getname() */
+
+/*
+** This is the central routine of this section.
+*/
+void ttfont_CharStrings(TTStreamWriter& stream, struct TTFONT *font, std::vector<int>& glyph_ids)
+{
+ Fixed post_format;
+
+ /* The 'post' table format number. */
+ post_format = getFixed( font->post_table );
+
+ /* Emmit the start of the PostScript code to define the dictionary. */
+ stream.printf("/CharStrings %d dict dup begin\n", glyph_ids.size()+1);
+ /* Section 5.8.2 table 5.7 of the PS Language Ref says a CharStrings dictionary must contain an entry for .notdef */
+ stream.printf("/.notdef 0 def\n");
+
+ /* Emmit one key-value pair for each glyph. */
+ for (std::vector<int>::const_iterator i = glyph_ids.begin();
+ i != glyph_ids.end(); ++i)
+ {
+ if ((font->target_type == PS_TYPE_42 ||
+ font->target_type == PS_TYPE_42_3_HYBRID)
+ && *i < 256) /* type 42 */
+ {
+ stream.printf("/%s %d def\n",ttfont_CharStrings_getname(font, *i), *i);
+ }
+ else /* type 3 */
+ {
+ stream.printf("/%s{",ttfont_CharStrings_getname(font, *i));
+
+ tt_type3_charproc(stream, font, *i);
+
+ stream.putline("}_d"); /* "} bind def" */
+ }
+ }
+
+ stream.putline("end readonly def");
+} /* end of ttfont_CharStrings() */
+
+/*----------------------------------------------------------------
+** Emmit the code to finish up the dictionary and turn
+** it into a font.
+----------------------------------------------------------------*/
+void ttfont_trailer(TTStreamWriter& stream, struct TTFONT *font)
+{
+ /* If we are generating a type 3 font, we need to provide */
+ /* a BuildGlyph and BuildChar proceedures. */
+ if (font->target_type == PS_TYPE_3 ||
+ font->target_type == PS_TYPE_42_3_HYBRID)
+ {
+ stream.put_char('\n');
+
+ stream.putline("/BuildGlyph");
+ stream.putline(" {exch begin"); /* start font dictionary */
+ stream.putline(" CharStrings exch");
+ stream.putline(" 2 copy known not{pop /.notdef}if");
+ stream.putline(" true 3 1 roll get exec");
+ stream.putline(" end}_d");
+
+ stream.put_char('\n');
+
+ /* This proceedure is for compatibility with */
+ /* level 1 interpreters. */
+ stream.putline("/BuildChar {");
+ stream.putline(" 1 index /Encoding get exch get");
+ stream.putline(" 1 index /BuildGlyph get exec");
+ stream.putline("}_d");
+
+ stream.put_char('\n');
+ }
+
+ /* If we are generating a type 42 font, we need to check to see */
+ /* if this PostScript interpreter understands type 42 fonts. If */
+ /* it doesn't, we will hope that the Apple TrueType rasterizer */
+ /* has been loaded and we will adjust the font accordingly. */
+ /* I found out how to do this by examining a TrueType font */
+ /* generated by a Macintosh. That is where the TrueType interpreter */
+ /* setup instructions and part of BuildGlyph came from. */
+ if (font->target_type == PS_TYPE_42 ||
+ font->target_type == PS_TYPE_42_3_HYBRID)
+ {
+ stream.put_char('\n');
+
+ /* If we have no "resourcestatus" command, or FontType 42 */
+ /* is unknown, leave "true" on the stack. */
+ stream.putline("systemdict/resourcestatus known");
+ stream.putline(" {42 /FontType resourcestatus");
+ stream.putline(" {pop pop false}{true}ifelse}");
+ stream.putline(" {true}ifelse");
+
+ /* If true, execute code to produce an error message if */
+ /* we can't find Apple's TrueDict in VM. */
+ stream.putline("{/TrueDict where{pop}{(%%[ Error: no TrueType rasterizer ]%%)= flush}ifelse");
+
+ /* Since we are expected to use Apple's TrueDict TrueType */
+ /* reasterizer, change the font type to 3. */
+ stream.putline("/FontType 3 def");
+
+ /* Define a string to hold the state of the Apple */
+ /* TrueType interpreter. */
+ stream.putline(" /TrueState 271 string def");
+
+ /* It looks like we get information about the resolution */
+ /* of the printer and store it in the TrueState string. */
+ stream.putline(" TrueDict begin sfnts save");
+ stream.putline(" 72 0 matrix defaultmatrix dtransform dup");
+ stream.putline(" mul exch dup mul add sqrt cvi 0 72 matrix");
+ stream.putline(" defaultmatrix dtransform dup mul exch dup");
+ stream.putline(" mul add sqrt cvi 3 -1 roll restore");
+ stream.putline(" TrueState initer end");
+
+ /* This BuildGlyph procedure will look the name up in the */
+ /* CharStrings array, and then check to see if what it gets */
+ /* is a procedure. If it is, it executes it, otherwise, it */
+ /* lets the TrueType rasterizer loose on it. */
+
+ /* When this proceedure is executed the stack contains */
+ /* the font dictionary and the character name. We */
+ /* exchange arguments and move the dictionary to the */
+ /* dictionary stack. */
+ stream.putline(" /BuildGlyph{exch begin");
+ /* stack: charname */
+
+ /* Put two copies of CharStrings on the stack and consume */
+ /* one testing to see if the charname is defined in it, */
+ /* leave the answer on the stack. */
+ stream.putline(" CharStrings dup 2 index known");
+ /* stack: charname CharStrings bool */
+
+ /* Exchange the CharStrings dictionary and the charname, */
+ /* but if the answer was false, replace the character name */
+ /* with ".notdef". */
+ stream.putline(" {exch}{exch pop /.notdef}ifelse");
+ /* stack: CharStrings charname */
+
+ /* Get the value from the CharStrings dictionary and see */
+ /* if it is executable. */
+ stream.putline(" get dup xcheck");
+ /* stack: CharStrings_entry */
+
+ /* If is a proceedure. Execute according to RBIIp 277-278. */
+ stream.putline(" {currentdict systemdict begin begin exec end end}");
+
+ /* Is a TrueType character index, let the rasterizer at it. */
+ stream.putline(" {TrueDict begin /bander load cvlit exch TrueState render end}");
+
+ stream.putline(" ifelse");
+
+ /* Pop the font's dictionary off the stack. */
+ stream.putline(" end}bind def");
+
+ /* This is the level 1 compatibility BuildChar procedure. */
+ /* See RBIIp 281. */
+ stream.putline(" /BuildChar{");
+ stream.putline(" 1 index /Encoding get exch get");
+ stream.putline(" 1 index /BuildGlyph get exec");
+ stream.putline(" }bind def");
+
+ /* Here we close the condition which is true */
+ /* if the printer has no built-in TrueType */
+ /* rasterizer. */
+ stream.putline("}if");
+ stream.put_char('\n');
+ } /* end of if Type 42 not understood. */
+
+ stream.putline("FontName currentdict end definefont pop");
+ /* stream.putline("%%EOF"); */
+} /* end of ttfont_trailer() */
+
+/*------------------------------------------------------------------
+** This is the externally callable routine which inserts the font.
+------------------------------------------------------------------*/
+
+void read_font(const char *filename, font_type_enum target_type, std::vector<int>& glyph_ids, TTFONT& font)
+{
+ BYTE *ptr;
+
+ /* Decide what type of PostScript font we will be generating. */
+ font.target_type = target_type;
+
+ if (font.target_type == PS_TYPE_42)
+ {
+ bool has_low = false;
+ bool has_high = false;
+
+ for (std::vector<int>::const_iterator i = glyph_ids.begin();
+ i != glyph_ids.end(); ++i)
+ {
+ if (*i > 255)
+ {
+ has_high = true;
+ if (has_low) break;
+ }
+ else
+ {
+ has_low = true;
+ if (has_high) break;
+ }
+ }
+
+ if (has_high && has_low)
+ {
+ font.target_type = PS_TYPE_42_3_HYBRID;
+ }
+ else if (has_high && !has_low)
+ {
+ font.target_type = PS_TYPE_3;
+ }
+ }
+
+ /* Save the file name for error messages. */
+ font.filename=filename;
+
+ /* Open the font file */
+ if ( (font.file = fopen(filename,"rb")) == (FILE*)NULL )
+ {
+ throw TTException("Failed to open TrueType font");
+ }
+
+ /* Allocate space for the unvarying part of the offset table. */
+ assert(font.offset_table == NULL);
+ font.offset_table = (BYTE*)calloc( 12, sizeof(BYTE) );
+
+ /* Read the first part of the offset table. */
+ if ( fread( font.offset_table, sizeof(BYTE), 12, font.file ) != 12 )
+ {
+ throw TTException("TrueType font may be corrupt (reason 1)");
+ }
+
+ /* Determine how many directory entries there are. */
+ font.numTables = getUSHORT( font.offset_table + 4 );
+ debug("numTables=%d",(int)font.numTables);
+
+ /* Expand the memory block to hold the whole thing. */
+ font.offset_table = (BYTE*)realloc( font.offset_table, sizeof(BYTE) * (12 + font.numTables * 16) );
+
+ /* Read the rest of the table directory. */
+ if ( fread( font.offset_table + 12, sizeof(BYTE), (font.numTables*16), font.file ) != (font.numTables*16) )
+ {
+ throw TTException("TrueType font may be corrupt (reason 2)");
+ }
+
+ /* Extract information from the "Offset" table. */
+ font.TTVersion = getFixed( font.offset_table );
+
+ /* Load the "head" table and extract information from it. */
+ ptr = GetTable(&font, "head");
+ try
+ {
+ font.MfrRevision = getFixed( ptr + 4 ); /* font revision number */
+ font.unitsPerEm = getUSHORT( ptr + 18 );
+ font.HUPM = font.unitsPerEm / 2;
+ debug("unitsPerEm=%d",(int)font.unitsPerEm);
+ font.llx = topost2( getFWord( ptr + 36 ) ); /* bounding box info */
+ font.lly = topost2( getFWord( ptr + 38 ) );
+ font.urx = topost2( getFWord( ptr + 40 ) );
+ font.ury = topost2( getFWord( ptr + 42 ) );
+ font.indexToLocFormat = getSHORT( ptr + 50 ); /* size of 'loca' data */
+ if (font.indexToLocFormat != 0 && font.indexToLocFormat != 1)
+ {
+ throw TTException("TrueType font is unusable because indexToLocFormat != 0");
+ }
+ if ( getSHORT(ptr+52) != 0 )
+ {
+ throw TTException("TrueType font is unusable because glyphDataFormat != 0");
+ }
+ }
+ catch (TTException& )
+ {
+ free(ptr);
+ throw;
+ }
+ free(ptr);
+
+ /* Load information from the "name" table. */
+ Read_name(&font);
+
+ /* We need to have the PostScript table around. */
+ assert(font.post_table == NULL);
+ font.post_table = GetTable(&font, "post");
+ font.numGlyphs = getUSHORT( font.post_table + 32 );
+
+ /* If we are generating a Type 3 font, we will need to */
+ /* have the 'loca' and 'glyf' tables arround while */
+ /* we are generating the CharStrings. */
+ if (font.target_type == PS_TYPE_3 || font.target_type == PS_TYPE_42_3_HYBRID)
+ {
+ BYTE *ptr; /* We need only one value */
+ ptr = GetTable(&font, "hhea");
+ font.numberOfHMetrics = getUSHORT(ptr + 34);
+ free(ptr);
+
+ assert(font.loca_table == NULL);
+ font.loca_table = GetTable(&font,"loca");
+ assert(font.glyf_table == NULL);
+ font.glyf_table = GetTable(&font,"glyf");
+ assert(font.hmtx_table == NULL);
+ font.hmtx_table = GetTable(&font,"hmtx");
+ }
+
+ if (glyph_ids.size() == 0)
+ {
+ glyph_ids.clear();
+ glyph_ids.reserve(font.numGlyphs);
+ for (int x = 0; x < font.numGlyphs; ++x)
+ {
+ glyph_ids.push_back(x);
+ }
+ }
+ else if (font.target_type == PS_TYPE_3 ||
+ font.target_type == PS_TYPE_42_3_HYBRID)
+ {
+ ttfont_add_glyph_dependencies(&font, glyph_ids);
+ }
+
+} /* end of insert_ttfont() */
+
+void insert_ttfont(const char *filename, TTStreamWriter& stream,
+ font_type_enum target_type, std::vector<int>& glyph_ids)
+{
+ struct TTFONT font;
+
+ read_font(filename, target_type, glyph_ids, font);
+
+ /* Write the header for the PostScript font. */
+ ttfont_header(stream, &font);
+
+ /* Define the encoding. */
+ ttfont_encoding(stream, &font, glyph_ids, target_type);
+
+ /* Insert FontInfo dictionary. */
+ ttfont_FontInfo(stream, &font);
+
+ /* If we are generating a type 42 font, */
+ /* emmit the sfnts array. */
+ if (font.target_type == PS_TYPE_42 ||
+ font.target_type == PS_TYPE_42_3_HYBRID)
+ {
+ ttfont_sfnts(stream, &font);
+ }
+
+ /* Emmit the CharStrings array. */
+ ttfont_CharStrings(stream, &font, glyph_ids);
+
+ /* Send the font trailer. */
+ ttfont_trailer(stream, &font);
+
+} /* end of insert_ttfont() */
+
+TTFONT::TTFONT() :
+ file(NULL),
+ PostName(NULL),
+ FullName(NULL),
+ FamilyName(NULL),
+ Style(NULL),
+ Copyright(NULL),
+ Version(NULL),
+ Trademark(NULL),
+ offset_table(NULL),
+ post_table(NULL),
+ loca_table(NULL),
+ glyf_table(NULL),
+ hmtx_table(NULL)
+{
+
+}
+
+TTFONT::~TTFONT()
+{
+ if (file)
+ {
+ fclose(file);
+ }
+ free(PostName);
+ free(FullName);
+ free(FamilyName);
+ free(Style);
+ free(Copyright);
+ free(Version);
+ free(Trademark);
+ free(offset_table);
+ free(post_table);
+ free(loca_table);
+ free(glyf_table);
+ free(hmtx_table);
+}
+
+/* end of file */
diff --git a/contrib/python/matplotlib/py3/extern/ttconv/pprdrv_tt2.cpp b/contrib/python/matplotlib/py3/extern/ttconv/pprdrv_tt2.cpp
new file mode 100644
index 0000000000..ec2298c8c4
--- /dev/null
+++ b/contrib/python/matplotlib/py3/extern/ttconv/pprdrv_tt2.cpp
@@ -0,0 +1,693 @@
+/* -*- mode: c++; c-basic-offset: 4 -*- */
+
+/*
+ * Modified for use within matplotlib
+ * 5 July 2007
+ * Michael Droettboom
+ */
+
+/*
+** ~ppr/src/pprdrv/pprdrv_tt2.c
+** Copyright 1995, Trinity College Computing Center.
+** Written by David Chappell.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+**
+** TrueType font support. These functions allow PPR to generate
+** PostScript fonts from Microsoft compatible TrueType font files.
+**
+** The functions in this file do most of the work to convert a
+** TrueType font to a type 3 PostScript font.
+**
+** Most of the material in this file is derived from a program called
+** "ttf2ps" which L. S. Ng posted to the usenet news group
+** "comp.sources.postscript". The author did not provide a copyright
+** notice or indicate any restrictions on use.
+**
+** Last revised 11 July 1995.
+*/
+
+#include <cstdlib>
+#include <cmath>
+#include <cstring>
+#include <memory>
+#include "pprdrv.h"
+#include "truetype.h"
+#include <algorithm>
+#include <stack>
+#include <list>
+
+class GlyphToType3
+{
+private:
+ GlyphToType3& operator=(const GlyphToType3& other);
+ GlyphToType3(const GlyphToType3& other);
+
+ /* The PostScript bounding box. */
+ int llx,lly,urx,ury;
+ int advance_width;
+
+ /* Variables to hold the character data. */
+ int *epts_ctr; /* array of contour endpoints */
+ int num_pts, num_ctr; /* number of points, number of coutours */
+ FWord *xcoor, *ycoor; /* arrays of x and y coordinates */
+ BYTE *tt_flags; /* array of TrueType flags */
+
+ int stack_depth; /* A book-keeping variable for keeping track of the depth of the PS stack */
+
+ void load_char(TTFONT* font, BYTE *glyph);
+ void stack(TTStreamWriter& stream, int new_elem);
+ void stack_end(TTStreamWriter& stream);
+ void PSConvert(TTStreamWriter& stream);
+ void PSCurveto(TTStreamWriter& stream,
+ FWord x0, FWord y0,
+ FWord x1, FWord y1,
+ FWord x2, FWord y2);
+ void PSMoveto(TTStreamWriter& stream, int x, int y);
+ void PSLineto(TTStreamWriter& stream, int x, int y);
+ void do_composite(TTStreamWriter& stream, struct TTFONT *font, BYTE *glyph);
+
+public:
+ GlyphToType3(TTStreamWriter& stream, struct TTFONT *font, int charindex, bool embedded = false);
+ ~GlyphToType3();
+};
+
+// Each point on a TrueType contour is either on the path or off it (a
+// control point); here's a simple representation for building such
+// contours. Added by Jouni Seppänen 2012-05-27.
+enum Flag { ON_PATH, OFF_PATH };
+struct FlaggedPoint
+{
+ enum Flag flag;
+ FWord x;
+ FWord y;
+ FlaggedPoint(Flag flag_, FWord x_, FWord y_): flag(flag_), x(x_), y(y_) {};
+};
+
+/*
+** This routine is used to break the character
+** procedure up into a number of smaller
+** procedures. This is necessary so as not to
+** overflow the stack on certain level 1 interpreters.
+**
+** Prepare to push another item onto the stack,
+** starting a new proceedure if necessary.
+**
+** Not all the stack depth calculations in this routine
+** are perfectly accurate, but they do the job.
+*/
+void GlyphToType3::stack(TTStreamWriter& stream, int new_elem)
+{
+ if ( num_pts > 25 ) /* Only do something of we will have a log of points. */
+ {
+ if (stack_depth == 0)
+ {
+ stream.put_char('{');
+ stack_depth=1;
+ }
+
+ stack_depth += new_elem; /* Account for what we propose to add */
+
+ if (stack_depth > 100)
+ {
+ stream.puts("}_e{");
+ stack_depth = 3 + new_elem; /* A rough estimate */
+ }
+ }
+} /* end of stack() */
+
+void GlyphToType3::stack_end(TTStreamWriter& stream) /* called at end */
+{
+ if ( stack_depth )
+ {
+ stream.puts("}_e");
+ stack_depth=0;
+ }
+} /* end of stack_end() */
+
+/*
+** We call this routine to emmit the PostScript code
+** for the character we have loaded with load_char().
+*/
+void GlyphToType3::PSConvert(TTStreamWriter& stream)
+{
+ int j, k;
+
+ /* Step thru the contours.
+ * j = index to xcoor, ycoor, tt_flags (point data)
+ * k = index to epts_ctr (which points belong to the same contour) */
+ for(j = k = 0; k < num_ctr; k++)
+ {
+ // A TrueType contour consists of on-path and off-path points.
+ // Two consecutive on-path points are to be joined with a
+ // line; off-path points between on-path points indicate a
+ // quadratic spline, where the off-path point is the control
+ // point. Two consecutive off-path points have an implicit
+ // on-path point midway between them.
+ std::list<FlaggedPoint> points;
+
+ // Represent flags and x/y coordinates as a C++ list
+ for (; j <= epts_ctr[k]; j++)
+ {
+ if (!(tt_flags[j] & 1)) {
+ points.push_back(FlaggedPoint(OFF_PATH, xcoor[j], ycoor[j]));
+ } else {
+ points.push_back(FlaggedPoint(ON_PATH, xcoor[j], ycoor[j]));
+ }
+ }
+
+ if (points.size() == 0) {
+ // Don't try to access the last element of an empty list
+ continue;
+ }
+
+ // For any two consecutive off-path points, insert the implied
+ // on-path point.
+ FlaggedPoint prev = points.back();
+ for (std::list<FlaggedPoint>::iterator it = points.begin();
+ it != points.end();
+ it++)
+ {
+ if (prev.flag == OFF_PATH && it->flag == OFF_PATH)
+ {
+ points.insert(it,
+ FlaggedPoint(ON_PATH,
+ (prev.x + it->x) / 2,
+ (prev.y + it->y) / 2));
+ }
+ prev = *it;
+ }
+ // Handle the wrap-around: insert a point either at the beginning
+ // or at the end that has the same coordinates as the opposite point.
+ // This also ensures that the initial point is ON_PATH.
+ if (points.front().flag == OFF_PATH)
+ {
+ assert(points.back().flag == ON_PATH);
+ points.insert(points.begin(), points.back());
+ }
+ else
+ {
+ assert(points.front().flag == ON_PATH);
+ points.push_back(points.front());
+ }
+
+ // The first point
+ stack(stream, 3);
+ PSMoveto(stream, points.front().x, points.front().y);
+
+ // Step through the remaining points
+ std::list<FlaggedPoint>::const_iterator it = points.begin();
+ for (it++; it != points.end(); /* incremented inside */)
+ {
+ const FlaggedPoint& point = *it;
+ if (point.flag == ON_PATH)
+ {
+ stack(stream, 3);
+ PSLineto(stream, point.x, point.y);
+ it++;
+ } else {
+ std::list<FlaggedPoint>::const_iterator prev = it, next = it;
+ prev--;
+ next++;
+ assert(prev->flag == ON_PATH);
+ assert(next->flag == ON_PATH);
+ stack(stream, 7);
+ PSCurveto(stream,
+ prev->x, prev->y,
+ point.x, point.y,
+ next->x, next->y);
+ it++;
+ it++;
+ }
+ }
+ }
+
+ /* Now, we can fill the whole thing. */
+ stack(stream, 1);
+ stream.puts("_cl");
+} /* end of PSConvert() */
+
+void GlyphToType3::PSMoveto(TTStreamWriter& stream, int x, int y)
+{
+ stream.printf("%d %d _m\n", x, y);
+}
+
+void GlyphToType3::PSLineto(TTStreamWriter& stream, int x, int y)
+{
+ stream.printf("%d %d _l\n", x, y);
+}
+
+/*
+** Emit a PostScript "curveto" command, assuming the current point
+** is (x0, y0), the control point of a quadratic spline is (x1, y1),
+** and the endpoint is (x2, y2). Note that this requires a conversion,
+** since PostScript splines are cubic.
+*/
+void GlyphToType3::PSCurveto(TTStreamWriter& stream,
+ FWord x0, FWord y0,
+ FWord x1, FWord y1,
+ FWord x2, FWord y2)
+{
+ double sx[3], sy[3], cx[3], cy[3];
+
+ sx[0] = x0;
+ sy[0] = y0;
+ sx[1] = x1;
+ sy[1] = y1;
+ sx[2] = x2;
+ sy[2] = y2;
+ cx[0] = (2*sx[1]+sx[0])/3;
+ cy[0] = (2*sy[1]+sy[0])/3;
+ cx[1] = (sx[2]+2*sx[1])/3;
+ cy[1] = (sy[2]+2*sy[1])/3;
+ cx[2] = sx[2];
+ cy[2] = sy[2];
+ stream.printf("%d %d %d %d %d %d _c\n",
+ (int)cx[0], (int)cy[0], (int)cx[1], (int)cy[1],
+ (int)cx[2], (int)cy[2]);
+}
+
+/*
+** Deallocate the structures which stored
+** the data for the last simple glyph.
+*/
+GlyphToType3::~GlyphToType3()
+{
+ free(tt_flags); /* The flags array */
+ free(xcoor); /* The X coordinates */
+ free(ycoor); /* The Y coordinates */
+ free(epts_ctr); /* The array of contour endpoints */
+}
+
+/*
+** Load the simple glyph data pointed to by glyph.
+** The pointer "glyph" should point 10 bytes into
+** the glyph data.
+*/
+void GlyphToType3::load_char(TTFONT* font, BYTE *glyph)
+{
+ int x;
+ BYTE c, ct;
+
+ /* Read the contour endpoints list. */
+ epts_ctr = (int *)calloc(num_ctr,sizeof(int));
+ for (x = 0; x < num_ctr; x++)
+ {
+ epts_ctr[x] = getUSHORT(glyph);
+ glyph += 2;
+ }
+
+ /* From the endpoint of the last contour, we can */
+ /* determine the number of points. */
+ num_pts = epts_ctr[num_ctr-1]+1;
+#ifdef DEBUG_TRUETYPE
+ debug("num_pts=%d",num_pts);
+ stream.printf("%% num_pts=%d\n",num_pts);
+#endif
+
+ /* Skip the instructions. */
+ x = getUSHORT(glyph);
+ glyph += 2;
+ glyph += x;
+
+ /* Allocate space to hold the data. */
+ tt_flags = (BYTE *)calloc(num_pts,sizeof(BYTE));
+ xcoor = (FWord *)calloc(num_pts,sizeof(FWord));
+ ycoor = (FWord *)calloc(num_pts,sizeof(FWord));
+
+ /* Read the flags array, uncompressing it as we go. */
+ /* There is danger of overflow here. */
+ for (x = 0; x < num_pts; )
+ {
+ tt_flags[x++] = c = *(glyph++);
+
+ if (c&8) /* If next byte is repeat count, */
+ {
+ ct = *(glyph++);
+
+ if ( (x + ct) > num_pts )
+ {
+ throw TTException("Error in TT flags");
+ }
+
+ while (ct--)
+ {
+ tt_flags[x++] = c;
+ }
+ }
+ }
+
+ /* Read the x coordinates */
+ for (x = 0; x < num_pts; x++)
+ {
+ if (tt_flags[x] & 2) /* one byte value with */
+ {
+ /* external sign */
+ c = *(glyph++);
+ xcoor[x] = (tt_flags[x] & 0x10) ? c : (-1 * (int)c);
+ }
+ else if (tt_flags[x] & 0x10) /* repeat last */
+ {
+ xcoor[x] = 0;
+ }
+ else /* two byte signed value */
+ {
+ xcoor[x] = getFWord(glyph);
+ glyph+=2;
+ }
+ }
+
+ /* Read the y coordinates */
+ for (x = 0; x < num_pts; x++)
+ {
+ if (tt_flags[x] & 4) /* one byte value with */
+ {
+ /* external sign */
+ c = *(glyph++);
+ ycoor[x] = (tt_flags[x] & 0x20) ? c : (-1 * (int)c);
+ }
+ else if (tt_flags[x] & 0x20) /* repeat last value */
+ {
+ ycoor[x] = 0;
+ }
+ else /* two byte signed value */
+ {
+ ycoor[x] = getUSHORT(glyph);
+ glyph+=2;
+ }
+ }
+
+ /* Convert delta values to absolute values. */
+ for (x = 1; x < num_pts; x++)
+ {
+ xcoor[x] += xcoor[x-1];
+ ycoor[x] += ycoor[x-1];
+ }
+
+ for (x=0; x < num_pts; x++)
+ {
+ xcoor[x] = topost(xcoor[x]);
+ ycoor[x] = topost(ycoor[x]);
+ }
+
+} /* end of load_char() */
+
+/*
+** Emmit PostScript code for a composite character.
+*/
+void GlyphToType3::do_composite(TTStreamWriter& stream, struct TTFONT *font, BYTE *glyph)
+{
+ USHORT flags;
+ USHORT glyphIndex;
+ int arg1;
+ int arg2;
+
+ /* Once around this loop for each component. */
+ do
+ {
+ flags = getUSHORT(glyph); /* read the flags word */
+ glyph += 2;
+
+ glyphIndex = getUSHORT(glyph); /* read the glyphindex word */
+ glyph += 2;
+
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ {
+ /* The tt spec. seems to say these are signed. */
+ arg1 = getSHORT(glyph);
+ glyph += 2;
+ arg2 = getSHORT(glyph);
+ glyph += 2;
+ }
+ else /* The tt spec. does not clearly indicate */
+ {
+ /* whether these values are signed or not. */
+ arg1 = *(signed char *)(glyph++);
+ arg2 = *(signed char *)(glyph++);
+ }
+
+ if (flags & WE_HAVE_A_SCALE)
+ {
+ glyph += 2;
+ }
+ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
+ {
+ glyph += 4;
+ }
+ else if (flags & WE_HAVE_A_TWO_BY_TWO)
+ {
+ glyph += 8;
+ }
+ else
+ {
+ }
+
+ /* Debugging */
+#ifdef DEBUG_TRUETYPE
+ stream.printf("%% flags=%d, arg1=%d, arg2=%d\n",
+ (int)flags,arg1,arg2);
+#endif
+
+ /* If we have an (X,Y) shift and it is non-zero, */
+ /* translate the coordinate system. */
+ if ( flags & ARGS_ARE_XY_VALUES )
+ {
+ if ( arg1 != 0 || arg2 != 0 )
+ stream.printf("gsave %d %d translate\n", topost(arg1), topost(arg2) );
+ }
+ else
+ {
+ stream.printf("%% unimplemented shift, arg1=%d, arg2=%d\n",arg1,arg2);
+ }
+
+ /* Invoke the CharStrings procedure to print the component. */
+ stream.printf("false CharStrings /%s get exec\n",
+ ttfont_CharStrings_getname(font, glyphIndex));
+
+ /* If we translated the coordinate system, */
+ /* put it back the way it was. */
+ if ( flags & ARGS_ARE_XY_VALUES && (arg1 != 0 || arg2 != 0) )
+ {
+ stream.puts("grestore ");
+ }
+
+ }
+ while (flags & MORE_COMPONENTS);
+
+} /* end of do_composite() */
+
+/*
+** Return a pointer to a specific glyph's data.
+*/
+BYTE *find_glyph_data(struct TTFONT *font, int charindex)
+{
+ ULONG off;
+ ULONG length;
+
+ /* Read the glyph offset from the index to location table. */
+ if (font->indexToLocFormat == 0)
+ {
+ off = getUSHORT( font->loca_table + (charindex * 2) );
+ off *= 2;
+ length = getUSHORT( font->loca_table + ((charindex+1) * 2) );
+ length *= 2;
+ length -= off;
+ }
+ else
+ {
+ off = getULONG( font->loca_table + (charindex * 4) );
+ length = getULONG( font->loca_table + ((charindex+1) * 4) );
+ length -= off;
+ }
+
+ if (length > 0)
+ {
+ return font->glyf_table + off;
+ }
+ else
+ {
+ return (BYTE*)NULL;
+ }
+
+} /* end of find_glyph_data() */
+
+GlyphToType3::GlyphToType3(TTStreamWriter& stream, struct TTFONT *font, int charindex, bool embedded /* = false */)
+{
+ BYTE *glyph;
+
+ tt_flags = NULL;
+ xcoor = NULL;
+ ycoor = NULL;
+ epts_ctr = NULL;
+ stack_depth = 0;
+
+ /* Get a pointer to the data. */
+ glyph = find_glyph_data( font, charindex );
+
+ /* If the character is blank, it has no bounding box, */
+ /* otherwise read the bounding box. */
+ if ( glyph == (BYTE*)NULL )
+ {
+ llx=lly=urx=ury=0; /* A blank char has an all zero BoundingBox */
+ num_ctr=0; /* Set this for later if()s */
+ }
+ else
+ {
+ /* Read the number of contours. */
+ num_ctr = getSHORT(glyph);
+
+ /* Read PostScript bounding box. */
+ llx = getFWord(glyph + 2);
+ lly = getFWord(glyph + 4);
+ urx = getFWord(glyph + 6);
+ ury = getFWord(glyph + 8);
+
+ /* Advance the pointer. */
+ glyph += 10;
+ }
+
+ /* If it is a simple character, load its data. */
+ if (num_ctr > 0)
+ {
+ load_char(font, glyph);
+ }
+ else
+ {
+ num_pts=0;
+ }
+
+ /* Consult the horizontal metrics table to determine */
+ /* the character width. */
+ if ( charindex < font->numberOfHMetrics )
+ {
+ advance_width = getuFWord( font->hmtx_table + (charindex * 4) );
+ }
+ else
+ {
+ advance_width = getuFWord( font->hmtx_table + ((font->numberOfHMetrics-1) * 4) );
+ }
+
+ /* Execute setcachedevice in order to inform the font machinery */
+ /* of the character bounding box and advance width. */
+ stack(stream, 7);
+ if (font->target_type == PS_TYPE_42_3_HYBRID)
+ {
+ stream.printf("pop gsave .001 .001 scale %d 0 %d %d %d %d setcachedevice\n",
+ topost(advance_width),
+ topost(llx), topost(lly), topost(urx), topost(ury) );
+ }
+ else
+ {
+ stream.printf("%d 0 %d %d %d %d _sc\n",
+ topost(advance_width),
+ topost(llx), topost(lly), topost(urx), topost(ury) );
+ }
+
+ /* If it is a simple glyph, convert it, */
+ /* otherwise, close the stack business. */
+ if ( num_ctr > 0 ) /* simple */
+ {
+ PSConvert(stream);
+ }
+ else if ( num_ctr < 0 ) /* composite */
+ {
+ do_composite(stream, font, glyph);
+ }
+
+ if (font->target_type == PS_TYPE_42_3_HYBRID)
+ {
+ stream.printf("\ngrestore\n");
+ }
+
+ stack_end(stream);
+}
+
+/*
+** This is the routine which is called from pprdrv_tt.c.
+*/
+void tt_type3_charproc(TTStreamWriter& stream, struct TTFONT *font, int charindex)
+{
+ GlyphToType3 glyph(stream, font, charindex);
+} /* end of tt_type3_charproc() */
+
+/*
+** Some of the given glyph ids may refer to composite glyphs.
+** This function adds all of the dependencies of those composite
+** glyphs to the glyph id vector. Michael Droettboom [06-07-07]
+*/
+void ttfont_add_glyph_dependencies(struct TTFONT *font, std::vector<int>& glyph_ids)
+{
+ std::sort(glyph_ids.begin(), glyph_ids.end());
+
+ std::stack<int> glyph_stack;
+ for (std::vector<int>::iterator i = glyph_ids.begin();
+ i != glyph_ids.end(); ++i)
+ {
+ glyph_stack.push(*i);
+ }
+
+ while (glyph_stack.size())
+ {
+ int gind = glyph_stack.top();
+ glyph_stack.pop();
+
+ BYTE* glyph = find_glyph_data( font, gind );
+ if (glyph != (BYTE*)NULL)
+ {
+
+ int num_ctr = getSHORT(glyph);
+ if (num_ctr <= 0) // This is a composite glyph
+ {
+
+ glyph += 10;
+ USHORT flags = 0;
+
+ do
+ {
+ flags = getUSHORT(glyph);
+ glyph += 2;
+ gind = (int)getUSHORT(glyph);
+ glyph += 2;
+
+ std::vector<int>::iterator insertion =
+ std::lower_bound(glyph_ids.begin(), glyph_ids.end(), gind);
+ if (insertion == glyph_ids.end() || *insertion != gind)
+ {
+ glyph_ids.insert(insertion, gind);
+ glyph_stack.push(gind);
+ }
+
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ {
+ glyph += 4;
+ }
+ else
+ {
+ glyph += 2;
+ }
+
+ if (flags & WE_HAVE_A_SCALE)
+ {
+ glyph += 2;
+ }
+ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
+ {
+ glyph += 4;
+ }
+ else if (flags & WE_HAVE_A_TWO_BY_TWO)
+ {
+ glyph += 8;
+ }
+ }
+ while (flags & MORE_COMPONENTS);
+ }
+ }
+ }
+}
+
+/* end of file */
diff --git a/contrib/python/matplotlib/py3/extern/ttconv/truetype.h b/contrib/python/matplotlib/py3/extern/ttconv/truetype.h
new file mode 100644
index 0000000000..86be14fe37
--- /dev/null
+++ b/contrib/python/matplotlib/py3/extern/ttconv/truetype.h
@@ -0,0 +1,129 @@
+/* -*- mode: c; c-basic-offset: 4 -*- */
+
+/*
+ * Modified for use within matplotlib
+ * 5 July 2007
+ * Michael Droettboom
+ */
+
+#include <stdio.h>
+
+/*
+** ~ppr/src/include/typetype.h
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+**
+** This include file is shared by the source files
+** "pprdrv/pprdrv_tt.c" and "pprdrv/pprdrv_tt2.c".
+**
+** Last modified 19 April 1995.
+*/
+
+/* Types used in TrueType font files. */
+#define BYTE unsigned char
+#define USHORT unsigned short int
+#define SHORT short signed int
+#define ULONG unsigned int
+#define FIXED long signed int
+#define FWord short signed int
+#define uFWord short unsigned int
+
+/* This structure stores a 16.16 bit fixed */
+/* point number. */
+typedef struct
+ {
+ short int whole;
+ unsigned short int fraction;
+ } Fixed;
+
+/* This structure tells what we have found out about */
+/* the current font. */
+struct TTFONT
+ {
+ // A quick-and-dirty way to create a minimum level of exception safety
+ // Added by Michael Droettboom
+ TTFONT();
+ ~TTFONT();
+
+ const char *filename; /* Name of TT file */
+ FILE *file; /* the open TT file */
+ font_type_enum target_type; /* 42 or 3 for PS, or -3 for PDF */
+
+ ULONG numTables; /* number of tables present */
+ char *PostName; /* Font's PostScript name */
+ char *FullName; /* Font's full name */
+ char *FamilyName; /* Font's family name */
+ char *Style; /* Font's style string */
+ char *Copyright; /* Font's copyright string */
+ char *Version; /* Font's version string */
+ char *Trademark; /* Font's trademark string */
+ int llx,lly,urx,ury; /* bounding box */
+
+ Fixed TTVersion; /* Truetype version number from offset table */
+ Fixed MfrRevision; /* Revision number of this font */
+
+ BYTE *offset_table; /* Offset table in memory */
+ BYTE *post_table; /* 'post' table in memory */
+
+ BYTE *loca_table; /* 'loca' table in memory */
+ BYTE *glyf_table; /* 'glyf' table in memory */
+ BYTE *hmtx_table; /* 'hmtx' table in memory */
+
+ USHORT numberOfHMetrics;
+ int unitsPerEm; /* unitsPerEm converted to int */
+ int HUPM; /* half of above */
+
+ int numGlyphs; /* from 'post' table */
+
+ int indexToLocFormat; /* short or long offsets */
+};
+
+ULONG getULONG(BYTE *p);
+USHORT getUSHORT(BYTE *p);
+Fixed getFixed(BYTE *p);
+
+/*
+** Get an funits word.
+** since it is 16 bits long, we can
+** use getUSHORT() to do the real work.
+*/
+#define getFWord(x) (FWord)getUSHORT(x)
+#define getuFWord(x) (uFWord)getUSHORT(x)
+
+/*
+** We can get a SHORT by making USHORT signed.
+*/
+#define getSHORT(x) (SHORT)getUSHORT(x)
+
+/* This is the one routine in pprdrv_tt.c that is */
+/* called from pprdrv_tt.c. */
+const char *ttfont_CharStrings_getname(struct TTFONT *font, int charindex);
+
+void tt_type3_charproc(TTStreamWriter& stream, struct TTFONT *font, int charindex);
+
+/* Added 06-07-07 Michael Droettboom */
+void ttfont_add_glyph_dependencies(struct TTFONT *font, std::vector<int>& glypy_ids);
+
+/* This routine converts a number in the font's character coordinate */
+/* system to a number in a 1000 unit character system. */
+#define topost(x) (int)( ((int)(x) * 1000 + font->HUPM) / font->unitsPerEm )
+#define topost2(x) (int)( ((int)(x) * 1000 + font.HUPM) / font.unitsPerEm )
+
+/* Composite glyph values. */
+#define ARG_1_AND_2_ARE_WORDS 1
+#define ARGS_ARE_XY_VALUES 2
+#define ROUND_XY_TO_GRID 4
+#define WE_HAVE_A_SCALE 8
+/* RESERVED 16 */
+#define MORE_COMPONENTS 32
+#define WE_HAVE_AN_X_AND_Y_SCALE 64
+#define WE_HAVE_A_TWO_BY_TWO 128
+#define WE_HAVE_INSTRUCTIONS 256
+#define USE_MY_METRICS 512
+
+/* end of file */
diff --git a/contrib/python/matplotlib/py3/extern/ttconv/ttutil.cpp b/contrib/python/matplotlib/py3/extern/ttconv/ttutil.cpp
new file mode 100644
index 0000000000..6028e1d45d
--- /dev/null
+++ b/contrib/python/matplotlib/py3/extern/ttconv/ttutil.cpp
@@ -0,0 +1,71 @@
+/* -*- mode: c++; c-basic-offset: 4 -*- */
+
+/*
+ * Modified for use within matplotlib
+ * 5 July 2007
+ * Michael Droettboom
+ */
+
+/* Very simple interface to the ppr TT routines */
+/* (c) Frank Siegert 1996 */
+
+#include <cstdio>
+#include <cstdarg>
+#include <cstdlib>
+#include "pprdrv.h"
+
+#define PRINTF_BUFFER_SIZE 512
+void TTStreamWriter::printf(const char* format, ...)
+{
+ va_list arg_list;
+ va_start(arg_list, format);
+ char buffer[PRINTF_BUFFER_SIZE];
+
+#if defined(WIN32) || defined(_MSC_VER)
+ int size = _vsnprintf(buffer, PRINTF_BUFFER_SIZE, format, arg_list);
+#else
+ int size = vsnprintf(buffer, PRINTF_BUFFER_SIZE, format, arg_list);
+#endif
+ if (size >= PRINTF_BUFFER_SIZE) {
+ char* buffer2 = (char*)malloc(size);
+#if defined(WIN32) || defined(_MSC_VER)
+ _vsnprintf(buffer2, size, format, arg_list);
+#else
+ vsnprintf(buffer2, size, format, arg_list);
+#endif
+ this->write(buffer2);
+ free(buffer2);
+ } else {
+ this->write(buffer);
+ }
+
+ va_end(arg_list);
+}
+
+void TTStreamWriter::put_char(int val)
+{
+ char c[2];
+ c[0] = (char)val;
+ c[1] = 0;
+ this->write(c);
+}
+
+void TTStreamWriter::puts(const char *a)
+{
+ this->write(a);
+}
+
+void TTStreamWriter::putline(const char *a)
+{
+ this->write(a);
+ this->write("\n");
+}
+
+void replace_newlines_with_spaces(char *a) {
+ char* i = a;
+ while (*i != 0) {
+ if (*i == '\r' || *i == '\n')
+ *i = ' ';
+ i++;
+ }
+}
diff --git a/contrib/python/matplotlib/py3/extern/ttconv/ya.make b/contrib/python/matplotlib/py3/extern/ttconv/ya.make
new file mode 100644
index 0000000000..bd5fca39b2
--- /dev/null
+++ b/contrib/python/matplotlib/py3/extern/ttconv/ya.make
@@ -0,0 +1,13 @@
+PY23_LIBRARY()
+
+LICENSE(PSF-2.0)
+
+NO_COMPILER_WARNINGS()
+
+SRCS(
+ pprdrv_tt.cpp
+ pprdrv_tt2.cpp
+ ttutil.cpp
+)
+
+END()