mirror of
https://github.com/michaelrsweet/pdfio.git
synced 2024-12-26 05:18:21 +01:00
Save work on Unicode font support - still something isn't quite right.
This commit is contained in:
parent
a2da67c415
commit
e9d5e082af
520
pdfio-content.c
520
pdfio-content.c
@ -51,6 +51,42 @@ const double pdfioSRGBWhitePoint[3] = { 0.9505, 1.0, 1.0890 };
|
||||
#define _PDFIO_PNG_TYPE_GRAYA 4 // Grayscale + alpha
|
||||
#define _PDFIO_PNG_TYPE_RGBA 6 // RGB + alpha
|
||||
|
||||
static int _pdfio_cp1252[] = // CP1252-specific character mapping
|
||||
{
|
||||
0x20AC,
|
||||
0x0000,
|
||||
0x201A,
|
||||
0x0192,
|
||||
0x201E,
|
||||
0x2026,
|
||||
0x2020,
|
||||
0x2021,
|
||||
0x02C6,
|
||||
0x2030,
|
||||
0x0160,
|
||||
0x2039,
|
||||
0x0152,
|
||||
0x0000,
|
||||
0x017D,
|
||||
0x0000,
|
||||
0x0000,
|
||||
0x2018,
|
||||
0x2019,
|
||||
0x201C,
|
||||
0x201D,
|
||||
0x2022,
|
||||
0x2013,
|
||||
0x2014,
|
||||
0x02DC,
|
||||
0x2122,
|
||||
0x0161,
|
||||
0x203A,
|
||||
0x0153,
|
||||
0x0000,
|
||||
0x017E,
|
||||
0x0178
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Local types...
|
||||
@ -67,7 +103,7 @@ static pdfio_obj_t *copy_jpeg(pdfio_dict_t *dict, int fd);
|
||||
static pdfio_obj_t *copy_png(pdfio_dict_t *dict, int fd);
|
||||
static void ttf_error_cb(pdfio_file_t *pdf, const char *message);
|
||||
static unsigned update_png_crc(unsigned crc, const unsigned char *buffer, size_t length);
|
||||
static bool write_string(pdfio_stream_t *st, const char *s, bool *newline);
|
||||
static bool write_string(pdfio_stream_t *st, bool unicode, const char *s, bool *newline);
|
||||
|
||||
|
||||
//
|
||||
@ -1015,17 +1051,22 @@ pdfioContentTextNextLine(
|
||||
//
|
||||
// 'pdfioContentTextShow()' - Show text.
|
||||
//
|
||||
// This function shows some text in a PDF content stream. The "unicode" argument
|
||||
// specifies that the current font maps to full Unicode. The "s" argument
|
||||
// specifies a UTF-8 encoded string.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
pdfioContentTextShow(
|
||||
pdfio_stream_t *st, // I - Stream
|
||||
bool unicode, // I - Unicode text?
|
||||
const char *s) // I - String to show
|
||||
{
|
||||
bool newline = false; // New line?
|
||||
|
||||
|
||||
// Write the string...
|
||||
if (!write_string(st, s, &newline))
|
||||
if (!write_string(st, unicode, s, &newline))
|
||||
return (false);
|
||||
|
||||
// Draw it...
|
||||
@ -1039,10 +1080,15 @@ pdfioContentTextShow(
|
||||
//
|
||||
// 'pdfioContentTextShowf()' - Show formatted text.
|
||||
//
|
||||
// This function shows some text in a PDF content stream. The "unicode" argument
|
||||
// specifies that the current font maps to full Unicode. The "format" argument
|
||||
// specifies a UTF-8 encoded `printf`-style format string.
|
||||
//
|
||||
|
||||
bool
|
||||
pdfioContentTextShowf(
|
||||
pdfio_stream_t *st, // I - Stream
|
||||
bool unicode, // I - Unicode text?
|
||||
const char *format, // I - `printf`-style format string
|
||||
...) // I - Additional arguments as needed
|
||||
{
|
||||
@ -1057,7 +1103,7 @@ pdfioContentTextShowf(
|
||||
va_end(ap);
|
||||
|
||||
// Write the string...
|
||||
if (!write_string(st, buffer, &newline))
|
||||
if (!write_string(st, unicode, buffer, &newline))
|
||||
return (false);
|
||||
|
||||
// Draw it...
|
||||
@ -1071,10 +1117,15 @@ pdfioContentTextShowf(
|
||||
//
|
||||
// 'pdfioContentTextShowJustified()' - Show justified text.
|
||||
//
|
||||
// This function shows some text in a PDF content stream. The "unicode" argument
|
||||
// specifies that the current font maps to full Unicode. The "fragments"
|
||||
// argument specifies an array of UTF-8 encoded strings.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
pdfioContentTextShowJustified(
|
||||
pdfio_stream_t *st, // I - Stream
|
||||
bool unicode, // I - Unicode text?
|
||||
size_t num_fragments, // I - Number of text fragments
|
||||
const double *offsets, // I - Text offsets before fragments
|
||||
const char * const *fragments) // I - Text fragments
|
||||
@ -1096,7 +1147,7 @@ pdfioContentTextShowJustified(
|
||||
|
||||
if (fragments[i])
|
||||
{
|
||||
if (!write_string(st, fragments[i], NULL))
|
||||
if (!write_string(st, unicode, fragments[i], NULL))
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
@ -1126,6 +1177,9 @@ pdfioContentTextShowJustified(
|
||||
// - `Times-Roman`
|
||||
// - `ZapfDingbats`
|
||||
//
|
||||
// Base fonts always use the Windows CP1252 (ISO-8859-1 with additional
|
||||
// characters such as the Euro symbol) subset of Unicode.
|
||||
//
|
||||
|
||||
pdfio_obj_t * // O - Font object
|
||||
pdfioFileCreateFontObjFromBase(
|
||||
@ -1154,12 +1208,18 @@ pdfioFileCreateFontObjFromBase(
|
||||
//
|
||||
// 'pdfioFileCreateFontObjFromFile()' - Add a font object to a PDF file.
|
||||
//
|
||||
// This function embeds a TrueType/OpenType font into a PDF file. The
|
||||
// "unicode" parameter controls whether the font is encoded for two-byte
|
||||
// characters (potentially full Unicode, but more typically a subset)
|
||||
// or to only support the Windows CP1252 (ISO-8859-1 with additional
|
||||
// characters such as the Euro symbol) subset of Unicode.
|
||||
//
|
||||
|
||||
pdfio_obj_t * // O - Font object
|
||||
pdfioFileCreateFontObjFromFile(
|
||||
pdfio_file_t *pdf, // I - PDF file
|
||||
const char *filename, // I - Filename
|
||||
bool unicode) // I - Unicode font?
|
||||
bool unicode) // I - Force Unicode
|
||||
{
|
||||
ttf_t *font; // TrueType font
|
||||
int ch, // Current character
|
||||
@ -1167,12 +1227,13 @@ pdfioFileCreateFontObjFromFile(
|
||||
lastch; // Last character
|
||||
ttf_rect_t bounds; // Font bounds
|
||||
pdfio_dict_t *dict, // Font dictionary
|
||||
*desc; // Font descriptor
|
||||
*desc, // Font descriptor
|
||||
*file; // Font file dictionary
|
||||
pdfio_obj_t *obj, // Font object
|
||||
*desc_obj, // Font descriptor object
|
||||
*widths_obj; // Font widths object
|
||||
*file_obj; // Font file object
|
||||
const char *basefont; // Base font name
|
||||
pdfio_array_t *bbox; // Font bounding box array
|
||||
pdfio_array_t *widths; // Font widths array
|
||||
pdfio_stream_t *st; // Font stream
|
||||
int fd; // File
|
||||
unsigned char buffer[16384]; // Read buffer
|
||||
@ -1201,102 +1262,23 @@ pdfioFileCreateFontObjFromFile(
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
// Create the font descriptor dictionary and object...
|
||||
if ((bbox = pdfioArrayCreate(pdf)) == NULL)
|
||||
// Create the font file dictionary and object...
|
||||
if ((file = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ttfGetBounds(font, &bounds);
|
||||
pdfioDictSetName(file, "Filter", "FlateDecode");
|
||||
|
||||
pdfioArrayAppendNumber(bbox, bounds.left);
|
||||
pdfioArrayAppendNumber(bbox, bounds.bottom);
|
||||
pdfioArrayAppendNumber(bbox, bounds.right);
|
||||
pdfioArrayAppendNumber(bbox, bounds.top);
|
||||
|
||||
if ((desc = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pdfioDictSetName(desc, "Type", "FontDescriptor");
|
||||
pdfioDictSetName(desc, "FontName", pdfioStringCreate(pdf, ttfGetPostScriptName(font)));
|
||||
pdfioDictSetName(desc, "FontFamily", pdfioStringCreate(pdf, ttfGetFamily(font)));
|
||||
pdfioDictSetNumber(desc, "Flags", ttfIsFixedPitch(font) ? 0x21 : 0x20);
|
||||
pdfioDictSetArray(desc, "FontBBox", bbox);
|
||||
pdfioDictSetNumber(desc, "ItalicAngle", ttfGetItalicAngle(font));
|
||||
pdfioDictSetNumber(desc, "Ascent", ttfGetAscent(font));
|
||||
pdfioDictSetNumber(desc, "Descent", ttfGetDescent(font));
|
||||
pdfioDictSetNumber(desc, "CapHeight", ttfGetCapHeight(font));
|
||||
pdfioDictSetNumber(desc, "XHeight", ttfGetXHeight(font));
|
||||
// Note: No TrueType value exists for this but PDF requires it, so we
|
||||
// calculate a value from 50 to 250...
|
||||
pdfioDictSetNumber(desc, "StemV", ttfGetWeight(font) / 4 + 25);
|
||||
|
||||
if ((desc_obj = pdfioFileCreateObj(pdf, desc)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pdfioObjClose(desc_obj);
|
||||
|
||||
// Create the widths array and object...
|
||||
if ((widths = pdfioArrayCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
firstch = 32;
|
||||
lastch = unicode ? 65535 : 255;
|
||||
|
||||
for (ch = firstch; ch <= lastch; ch ++)
|
||||
pdfioArrayAppendNumber(widths, ttfGetWidth(font, ch));
|
||||
|
||||
if ((widths_obj = pdfioFileCreateArrayObj(pdf, widths)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pdfioObjClose(widths_obj);
|
||||
|
||||
// Create the font object...
|
||||
if ((dict = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pdfioDictSetName(dict, "Type", "Font");
|
||||
pdfioDictSetName(dict, "Subtype", "TrueType");
|
||||
pdfioDictSetName(dict, "BaseFont", pdfioStringCreate(pdf, ttfGetPostScriptName(font)));
|
||||
pdfioDictSetName(dict, "Encoding", "WinAnsiEncoding"); // TODO: Fix encoding for unicode
|
||||
pdfioDictSetName(dict, "Filter", "FlateDecode");
|
||||
|
||||
pdfioDictSetObj(dict, "FontDescriptor", desc_obj);
|
||||
pdfioDictSetNumber(dict, "FirstChar", firstch);
|
||||
pdfioDictSetNumber(dict, "LastChar", lastch);
|
||||
pdfioDictSetObj(dict, "Widths", widths_obj);
|
||||
|
||||
ttfDelete(font);
|
||||
|
||||
if ((obj = pdfioFileCreateObj(pdf, dict)) == NULL)
|
||||
if ((file_obj = pdfioFileCreateObj(pdf, file)) == NULL)
|
||||
{
|
||||
close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((st = pdfioObjCreateStream(obj, PDFIO_FILTER_FLATE)) == NULL)
|
||||
if ((st = pdfioObjCreateStream(file_obj, PDFIO_FILTER_FLATE)) == NULL)
|
||||
{
|
||||
close(fd);
|
||||
return (NULL);
|
||||
@ -1315,6 +1297,189 @@ pdfioFileCreateFontObjFromFile(
|
||||
close(fd);
|
||||
pdfioStreamClose(st);
|
||||
|
||||
// Create the font descriptor dictionary and object...
|
||||
if ((bbox = pdfioArrayCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ttfGetBounds(font, &bounds);
|
||||
|
||||
pdfioArrayAppendNumber(bbox, bounds.left);
|
||||
pdfioArrayAppendNumber(bbox, bounds.bottom);
|
||||
pdfioArrayAppendNumber(bbox, bounds.right);
|
||||
pdfioArrayAppendNumber(bbox, bounds.top);
|
||||
|
||||
if ((desc = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
basefont = pdfioStringCreate(pdf, ttfGetPostScriptName(font));
|
||||
|
||||
pdfioDictSetName(desc, "Type", "FontDescriptor");
|
||||
pdfioDictSetName(desc, "FontName", basefont);
|
||||
pdfioDictSetObj(desc, "FontFile2", file_obj);
|
||||
pdfioDictSetNumber(desc, "Flags", ttfIsFixedPitch(font) ? 0x21 : 0x20);
|
||||
pdfioDictSetArray(desc, "FontBBox", bbox);
|
||||
pdfioDictSetNumber(desc, "ItalicAngle", ttfGetItalicAngle(font));
|
||||
pdfioDictSetNumber(desc, "Ascent", ttfGetAscent(font));
|
||||
pdfioDictSetNumber(desc, "Descent", ttfGetDescent(font));
|
||||
pdfioDictSetNumber(desc, "CapHeight", ttfGetCapHeight(font));
|
||||
pdfioDictSetNumber(desc, "XHeight", ttfGetXHeight(font));
|
||||
// Note: No TrueType value exists for this but PDF requires it, so we
|
||||
// calculate a value from 50 to 250...
|
||||
pdfioDictSetNumber(desc, "StemV", ttfGetWeight(font) / 4 + 25);
|
||||
|
||||
if ((desc_obj = pdfioFileCreateObj(pdf, desc)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pdfioObjClose(desc_obj);
|
||||
|
||||
if (unicode)
|
||||
{
|
||||
// Unicode (CID) font...
|
||||
pdfio_dict_t *type2; // CIDFontType2 font dictionary
|
||||
pdfio_obj_t *type2_obj; // CIDFontType2 font object
|
||||
pdfio_array_t *descendants; // Decendant font list
|
||||
pdfio_dict_t *sidict; // CIDSystemInfo dictionary
|
||||
|
||||
// Create a CIDFontType2 dictionary for the Unicode font...
|
||||
if ((type2 = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((sidict = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
// CIDSystemInfo mapping to Adobe Identity (Unicode)
|
||||
pdfioDictSetString(sidict, "Registry", "Adobe");
|
||||
pdfioDictSetString(sidict, "Ordering", "Identity");
|
||||
pdfioDictSetNumber(sidict, "Supplement", 0);
|
||||
|
||||
// Then the dictionary for the CID base font...
|
||||
pdfioDictSetName(type2, "Type", "Font");
|
||||
pdfioDictSetName(type2, "Subtype", "CIDFontType2");
|
||||
pdfioDictSetName(type2, "BaseFont", basefont);
|
||||
pdfioDictSetDict(type2, "CIDSystemInfo", sidict);
|
||||
pdfioDictSetName(type2, "CIDToGIDMap", "Identity");
|
||||
pdfioDictSetObj(type2, "FontDescriptor", desc_obj);
|
||||
|
||||
if ((type2_obj = pdfioFileCreateObj(pdf, type2)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pdfioObjClose(type2_obj);
|
||||
|
||||
// Create a Type 0 font object...
|
||||
if ((descendants = pdfioArrayCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pdfioArrayAppendObj(descendants, type2_obj);
|
||||
|
||||
if ((dict = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pdfioDictSetName(dict, "Type", "Font");
|
||||
pdfioDictSetName(dict, "Subtype", "Type0");
|
||||
pdfioDictSetName(dict, "BaseFont", basefont);
|
||||
pdfioDictSetArray(dict, "DescendantFonts", descendants);
|
||||
pdfioDictSetName(dict, "Encoding", "Identity-H");
|
||||
|
||||
if ((obj = pdfioFileCreateObj(pdf, dict)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
pdfioObjClose(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simple (CP1282 or custom encoding) 8-bit font...
|
||||
pdfio_array_t *widths; // Font widths array
|
||||
pdfio_obj_t *widths_obj; // Font widths object
|
||||
|
||||
// Create the widths array and object...
|
||||
if ((widths = pdfioArrayCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
firstch = ttfGetMinChar(font);
|
||||
lastch = ttfGetMaxChar(font);
|
||||
|
||||
if (lastch < 255)
|
||||
{
|
||||
// Provide widths for all characters...
|
||||
for (ch = firstch; ch <= lastch; ch ++)
|
||||
pdfioArrayAppendNumber(widths, ttfGetWidth(font, ch));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Provide widths only for CP1252 characters...
|
||||
lastch = 255;
|
||||
|
||||
for (ch = firstch; ch < 128; ch ++)
|
||||
pdfioArrayAppendNumber(widths, ttfGetWidth(font, ch));
|
||||
for (; ch < 160; ch ++)
|
||||
pdfioArrayAppendNumber(widths, ttfGetWidth(font, _pdfio_cp1252[ch - 128]));
|
||||
for (; ch <= lastch && ch < 128; ch ++)
|
||||
pdfioArrayAppendNumber(widths, ttfGetWidth(font, ch));
|
||||
}
|
||||
|
||||
if ((widths_obj = pdfioFileCreateArrayObj(pdf, widths)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pdfioObjClose(widths_obj);
|
||||
|
||||
// Create a TrueType font object...
|
||||
if ((dict = pdfioDictCreate(pdf)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pdfioDictSetName(dict, "Type", "Font");
|
||||
pdfioDictSetName(dict, "Subtype", "TrueType");
|
||||
pdfioDictSetName(dict, "BaseFont", basefont);
|
||||
pdfioDictSetName(dict, "Encoding", "WinAnsi");
|
||||
|
||||
pdfioDictSetObj(dict, "FontDescriptor", desc_obj);
|
||||
pdfioDictSetNumber(dict, "FirstChar", firstch);
|
||||
pdfioDictSetNumber(dict, "LastChar", lastch);
|
||||
pdfioDictSetObj(dict, "Widths", widths_obj);
|
||||
|
||||
if ((obj = pdfioFileCreateObj(pdf, dict)) == NULL)
|
||||
{
|
||||
ttfDelete(font);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
pdfioObjClose(obj);
|
||||
}
|
||||
|
||||
ttfDelete(font);
|
||||
|
||||
return (obj);
|
||||
}
|
||||
|
||||
@ -2229,140 +2394,93 @@ update_png_crc(
|
||||
|
||||
static bool // O - `true` on success, `false` otherwise
|
||||
write_string(pdfio_stream_t *st, // I - Stream
|
||||
bool unicode, // I - Unicode text?
|
||||
const char *s, // I - String
|
||||
bool *newline) // O - Ends with a newline?
|
||||
{
|
||||
int ch; // Unicode character
|
||||
const char *ptr; // Pointer into string
|
||||
|
||||
|
||||
// Determine whether this is Unicode or just ASCII...
|
||||
// Start the string...
|
||||
if (!pdfioStreamPuts(st, unicode ? "<" : "("))
|
||||
return (false);
|
||||
|
||||
// Loop through the string, handling UTF-8 as needed...
|
||||
for (ptr = s; *ptr; ptr ++)
|
||||
{
|
||||
if (*ptr & 0x80)
|
||||
if ((*ptr & 0xe0) == 0xc0)
|
||||
{
|
||||
// UTF-8, allow Unicode up to 255...
|
||||
if ((*ptr & 0xe0) == 0xc0 && (*ptr & 0x3f) <= 3 && (ptr[1] & 0xc0) == 0x80)
|
||||
{
|
||||
ptr ++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Two-byte UTF-8
|
||||
ch = ((ptr[0] & 0x1f) << 6) | (ptr[1] & 0x3f);
|
||||
ptr ++;
|
||||
}
|
||||
else if ((*ptr & 0xf0) == 0xe0)
|
||||
{
|
||||
// Three-byte UTF-8
|
||||
ch = ((ptr[0] & 0x0f) << 12) | ((ptr[1] & 0x3f) << 6) | (ptr[2] & 0x3f);
|
||||
ptr += 2;
|
||||
}
|
||||
else if ((*ptr & 0xf8) == 0xf0)
|
||||
{
|
||||
// Four-byte UTF-8
|
||||
ch = ((ptr[0] & 0x07) << 18) | ((ptr[1] & 0x3f) << 12) | ((ptr[2] & 0x3f) << 6) | (ptr[3] & 0x3f);
|
||||
ptr += 3;
|
||||
}
|
||||
else if (*ptr == '\n' && newline)
|
||||
{
|
||||
*newline = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
ch = *ptr & 255;
|
||||
|
||||
if (*ptr)
|
||||
{
|
||||
// Unicode string...
|
||||
int ch; // Unicode character
|
||||
|
||||
if (!pdfioStreamPuts(st, "<"))
|
||||
return (false);
|
||||
|
||||
for (ptr = s; *ptr; ptr ++)
|
||||
if (unicode)
|
||||
{
|
||||
if ((*ptr & 0xe0) == 0xc0)
|
||||
{
|
||||
// Two-byte UTF-8
|
||||
ch = ((ptr[0] & 0x1f) << 6) | (ptr[1] & 0x3f);
|
||||
ptr ++;
|
||||
}
|
||||
else if ((*ptr & 0xf0) == 0xe0)
|
||||
{
|
||||
// Three-byte UTF-8
|
||||
ch = ((ptr[0] & 0x0f) << 12) | ((ptr[1] & 0x3f) << 6) | (ptr[2] & 0x3f);
|
||||
ptr += 2;
|
||||
}
|
||||
else if ((*ptr & 0xf8) == 0xf0)
|
||||
{
|
||||
// Four-byte UTF-8
|
||||
ch = ((ptr[0] & 0x07) << 18) | ((ptr[1] & 0x3f) << 12) | ((ptr[2] & 0x3f) << 6) | (ptr[3] & 0x3f);
|
||||
ptr += 3;
|
||||
}
|
||||
else if (*ptr == '\n' && newline)
|
||||
{
|
||||
*newline = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
ch = *ptr & 255;
|
||||
|
||||
// Write a two-byte character...
|
||||
if (!pdfioStreamPrintf(st, "%04X", ch))
|
||||
return (false);
|
||||
return (false);
|
||||
}
|
||||
if (!pdfioStreamPuts(st, ">"))
|
||||
return (false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ASCII string...
|
||||
const char *start = s; // Start of fragment
|
||||
|
||||
if (!pdfioStreamPuts(st, "("))
|
||||
return (false);
|
||||
|
||||
for (ptr = start; *ptr; ptr ++)
|
||||
else
|
||||
{
|
||||
if (*ptr == '\n' && newline)
|
||||
// Write a one-byte character...
|
||||
if (ch == '\\' || ch == '(' || ch == ')' || ch < ' ')
|
||||
{
|
||||
if (ptr > start)
|
||||
// Escaped character...
|
||||
if (ch < ' ')
|
||||
{
|
||||
if (!pdfioStreamWrite(st, start, (size_t)(ptr - start)))
|
||||
return (false);
|
||||
|
||||
start = ptr + 1;
|
||||
}
|
||||
|
||||
*newline = true;
|
||||
break;
|
||||
}
|
||||
else if ((*ptr & 0xe0) == 0xc0)
|
||||
{
|
||||
// Two-byte UTF-8
|
||||
unsigned char ch = (unsigned char)(((ptr[0] & 0x1f) << 6) | (ptr[1] & 0x3f));
|
||||
// Unicode character
|
||||
|
||||
if (ptr > start)
|
||||
{
|
||||
if (!pdfioStreamWrite(st, start, (size_t)(ptr - start)))
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (!pdfioStreamWrite(st, &ch, 1))
|
||||
return (false);
|
||||
|
||||
ptr ++;
|
||||
start = ptr + 1;
|
||||
}
|
||||
else if (*ptr == '\\' || *ptr == '(' || *ptr == ')' || *ptr < ' ')
|
||||
{
|
||||
if (ptr > start)
|
||||
{
|
||||
if (!pdfioStreamWrite(st, start, (size_t)(ptr - start)))
|
||||
return (false);
|
||||
}
|
||||
|
||||
start = ptr + 1;
|
||||
|
||||
if (*ptr < ' ')
|
||||
{
|
||||
if (!pdfioStreamPrintf(st, "\\%03o", *ptr))
|
||||
if (!pdfioStreamPrintf(st, "\\%03o", ch))
|
||||
return (false);
|
||||
}
|
||||
else if (!pdfioStreamPrintf(st, "\\%c", *ptr))
|
||||
else if (!pdfioStreamPrintf(st, "\\%c", ch))
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Non-escaped character...
|
||||
if (ch > 255)
|
||||
{
|
||||
// Try mapping from Unicode to CP1252...
|
||||
int i; // Looping var
|
||||
|
||||
if (ptr > start)
|
||||
{
|
||||
if (!pdfioStreamPrintf(st, "%s)", start))
|
||||
return (false);
|
||||
for (i = 0; i < (int)(sizeof(_pdfio_cp1252) / sizeof(_pdfio_cp1252[0])); i ++)
|
||||
{
|
||||
if (ch == _pdfio_cp1252[i])
|
||||
{
|
||||
ch = i + 128;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ch > 255)
|
||||
ch = '?'; // Unsupported chars map to ?
|
||||
}
|
||||
|
||||
// Write the character...
|
||||
pdfioStreamPutChar(st, ch);
|
||||
}
|
||||
}
|
||||
else if (!pdfioStreamPuts(st, ")"))
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (true);
|
||||
return (pdfioStreamPuts(st, unicode ? ">" : ")"));
|
||||
}
|
||||
|
@ -139,9 +139,9 @@ extern bool pdfioContentTextEnd(pdfio_stream_t *st) PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextMoveLine(pdfio_stream_t *st, double tx, double ty) PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextMoveTo(pdfio_stream_t *st, double tx, double ty) PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextNextLine(pdfio_stream_t *st) PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextShow(pdfio_stream_t *st, const char *s) PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextShowf(pdfio_stream_t *st, const char *format, ...) PDFIO_PUBLIC PDFIO_FORMAT(2,3);
|
||||
extern bool pdfioContentTextShowJustified(pdfio_stream_t *st, size_t num_fragments, const double *offsets, const char * const *fragments) PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextShow(pdfio_stream_t *st, bool unicode, const char *s) PDFIO_PUBLIC;
|
||||
extern bool pdfioContentTextShowf(pdfio_stream_t *st, bool unicode, const char *format, ...) PDFIO_PUBLIC PDFIO_FORMAT(3,4);
|
||||
extern bool pdfioContentTextShowJustified(pdfio_stream_t *st, bool unicode, size_t num_fragments, const double *offsets, const char * const *fragments) PDFIO_PUBLIC;
|
||||
|
||||
// Resource helpers...
|
||||
extern pdfio_obj_t *pdfioFileCreateFontObjFromBase(pdfio_file_t *pdf, const char *name) PDFIO_PUBLIC;
|
||||
|
@ -556,6 +556,26 @@ pdfioStreamPrintf(
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// '()' - Write a single character to a stream.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
pdfioStreamPutChar(pdfio_stream_t *st, // I - Stream
|
||||
int ch) // I - Character
|
||||
{
|
||||
char buffer[1]; // Write buffer
|
||||
|
||||
|
||||
if (!st || st->pdf->mode != _PDFIO_MODE_WRITE)
|
||||
return (false);
|
||||
|
||||
buffer[0] = (char)ch;
|
||||
|
||||
return (pdfioStreamWrite(st, buffer, 1));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'pdfioStreamPuts()' - Write a literal string to a stream.
|
||||
//
|
||||
|
1
pdfio.h
1
pdfio.h
@ -181,6 +181,7 @@ extern bool pdfioStreamConsume(pdfio_stream_t *st, size_t bytes) PDFIO_PUBLIC;
|
||||
extern bool pdfioStreamGetToken(pdfio_stream_t *st, char *buffer, size_t bufsize) PDFIO_PUBLIC;
|
||||
extern ssize_t pdfioStreamPeek(pdfio_stream_t *st, void *buffer, size_t bytes) PDFIO_PUBLIC;
|
||||
extern bool pdfioStreamPrintf(pdfio_stream_t *st, const char *format, ...) PDFIO_PUBLIC PDFIO_FORMAT(2,3);
|
||||
extern bool pdfioStreamPutChar(pdfio_stream_t *st, int ch) PDFIO_PUBLIC;
|
||||
extern bool pdfioStreamPuts(pdfio_stream_t *st, const char *s) PDFIO_PUBLIC;
|
||||
extern ssize_t pdfioStreamRead(pdfio_stream_t *st, void *buffer, size_t bytes) PDFIO_PUBLIC;
|
||||
extern bool pdfioStreamWrite(pdfio_stream_t *st, const void *buffer, size_t bytes) PDFIO_PUBLIC;
|
||||
|
80
testpdfio.c
80
testpdfio.c
@ -388,7 +388,7 @@ draw_image(pdfio_stream_t *st,
|
||||
return (1);
|
||||
|
||||
printf("pdfioContentTextShow(\"%s\"): ", label);
|
||||
if (pdfioContentTextShow(st, label))
|
||||
if (pdfioContentTextShow(st, false, label))
|
||||
puts("PASS");
|
||||
else
|
||||
return (1);
|
||||
@ -829,7 +829,7 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file
|
||||
goto error;
|
||||
|
||||
fputs("pdfioContentTextShow(\"AdobeRGB\"): ", stdout);
|
||||
if (pdfioContentTextShow(st, "AdobeRGB"))
|
||||
if (pdfioContentTextShow(st, false, "AdobeRGB"))
|
||||
puts("PASS");
|
||||
else
|
||||
goto error;
|
||||
@ -841,7 +841,7 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file
|
||||
goto error;
|
||||
|
||||
fputs("pdfioContentTextShow(\"DisplayP3\"): ", stdout);
|
||||
if (pdfioContentTextShow(st, "DisplayP3"))
|
||||
if (pdfioContentTextShow(st, false, "DisplayP3"))
|
||||
puts("PASS");
|
||||
else
|
||||
goto error;
|
||||
@ -853,7 +853,7 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file
|
||||
goto error;
|
||||
|
||||
fputs("pdfioContentTextShow(\"sRGB\"): ", stdout);
|
||||
if (pdfioContentTextShow(st, "sRGB"))
|
||||
if (pdfioContentTextShow(st, false, "sRGB"))
|
||||
puts("PASS");
|
||||
else
|
||||
goto error;
|
||||
@ -865,7 +865,7 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file
|
||||
goto error;
|
||||
|
||||
fputs("pdfioContentTextShow(\"ProPhotoRGB\"): ", stdout);
|
||||
if (pdfioContentTextShow(st, "ProPhotoRGB"))
|
||||
if (pdfioContentTextShow(st, false, "ProPhotoRGB"))
|
||||
puts("PASS");
|
||||
else
|
||||
goto error;
|
||||
@ -877,7 +877,7 @@ write_color_test(pdfio_file_t *pdf, // I - PDF file
|
||||
goto error;
|
||||
|
||||
fputs("pdfioContentTextShow(\"DeviceCMYK\"): ", stdout);
|
||||
if (pdfioContentTextShow(st, "DeviceCMYK"))
|
||||
if (pdfioContentTextShow(st, false, "DeviceCMYK"))
|
||||
puts("PASS");
|
||||
else
|
||||
goto error;
|
||||
@ -1049,7 +1049,7 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
{
|
||||
"Welcome\n",
|
||||
"Welkom\n",
|
||||
// "ḫaṣānu\n",
|
||||
"ḫaṣānu\n",
|
||||
"Mayad-ayad nga pad-abot\n",
|
||||
"Mir se vjên\n",
|
||||
"Mirë se vjen\n",
|
||||
@ -1058,15 +1058,15 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
"Ghini vinit!\n",
|
||||
"Bienveníu\n",
|
||||
"Miro peicak\n",
|
||||
// "Xoş gəlmişsiniz!\n",
|
||||
"Xoş gəlmişsiniz!\n",
|
||||
"Salamat datang\n",
|
||||
// "Сәләм бирем!\n",
|
||||
"Сәләм бирем!\n",
|
||||
"Menjuah-juah!\n",
|
||||
// "Še das d' kemma bisd\n",
|
||||
"Še das d' kemma bisd\n",
|
||||
"Mwaiseni\n",
|
||||
"Maogmáng Pag-abót\n",
|
||||
"Welkam\n",
|
||||
// "Dobrodošli\n",
|
||||
"Dobrodošli\n",
|
||||
"Degemer mat\n",
|
||||
"Benvingut\n",
|
||||
"Maayong pag-abot\n",
|
||||
@ -1074,7 +1074,7 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
"Bienvenida\n",
|
||||
"Bien binidu\n",
|
||||
"Bienbenidu\n",
|
||||
// "Hóʔą\n",
|
||||
"Hóʔą\n",
|
||||
"Boolkhent!\n",
|
||||
"Kopivosian do kinoikatan\n",
|
||||
"Malipayeng Pag-abot!\n",
|
||||
@ -1085,7 +1085,7 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
"Emedi\n",
|
||||
"Welkumin\n",
|
||||
"Tere tulemast\n",
|
||||
// "Woé zɔ\n",
|
||||
"Woé zɔ\n",
|
||||
"Bienveníu\n",
|
||||
"Vælkomin\n",
|
||||
"Bula\n",
|
||||
@ -1098,8 +1098,8 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
"Benvignût\n",
|
||||
"Benvido\n",
|
||||
"Willkommen\n",
|
||||
// "Ἀσπάζομαι!\n",
|
||||
// "Καλώς Ήρθες\n",
|
||||
"Ἀσπάζομαι!\n",
|
||||
"Καλώς Ήρθες\n",
|
||||
"Tikilluarit\n",
|
||||
"Byen venu\n",
|
||||
"Sannu da zuwa\n",
|
||||
@ -1110,7 +1110,7 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
"Üdvözlet\n",
|
||||
"Selamat datai\n",
|
||||
"Velkomin\n",
|
||||
// "Nnọọ\n",
|
||||
"Nnọọ\n",
|
||||
"Selamat datang\n",
|
||||
"Qaimarutin\n",
|
||||
"Fáilte\n",
|
||||
@ -1119,11 +1119,11 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
"Murakaza neza\n",
|
||||
"Mauri\n",
|
||||
"Tu be xér hatî ye!\n",
|
||||
// "Taŋyáŋ yahí\n",
|
||||
"Taŋyáŋ yahí\n",
|
||||
"Salve\n",
|
||||
// "Laipni lūdzam\n",
|
||||
"Laipni lūdzam\n",
|
||||
"Wilkóm\n",
|
||||
// "Sveiki atvykę\n",
|
||||
"Sveiki atvykę\n",
|
||||
"Willkamen\n",
|
||||
"Mu amuhezwi\n",
|
||||
"Tukusanyukidde\n",
|
||||
@ -1131,15 +1131,15 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
"Swagatam\n",
|
||||
"Tonga soa\n",
|
||||
"Selamat datang\n",
|
||||
// "Merħba\n",
|
||||
// "B’a’ntulena\n",
|
||||
"Merħba\n",
|
||||
"B’a’ntulena\n",
|
||||
"Failt ort\n",
|
||||
"Haere mai\n",
|
||||
"mai\n",
|
||||
// "Pjila’si\n",
|
||||
"Pjila’si\n",
|
||||
"Benvegnüu\n",
|
||||
"Ne y kena\n",
|
||||
// "Ximopanōltih\n",
|
||||
"Ximopanōltih\n",
|
||||
"Yá'át'ééh\n",
|
||||
"Siyalemukela\n",
|
||||
"Siyalemukela\n",
|
||||
@ -1148,7 +1148,7 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
"Velkommen\n",
|
||||
"Benvengut!\n",
|
||||
"Bon bini\n",
|
||||
// "Witam Cię\n",
|
||||
"Witam Cię\n",
|
||||
"Bem-vindo\n",
|
||||
"Haykuykuy!\n",
|
||||
"T'aves baxtalo\n",
|
||||
@ -1160,7 +1160,7 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
"Mauya\n",
|
||||
"Bon vinutu\n",
|
||||
"Vitaj\n",
|
||||
// "Dobrodošli\n",
|
||||
"Dobrodošli\n",
|
||||
"Soo dhowow\n",
|
||||
"Witaj\n",
|
||||
"Bienvenido\n",
|
||||
@ -1179,8 +1179,8 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
"Lek oy li la tale\n",
|
||||
"amogetswe\n",
|
||||
"Tempokani\n",
|
||||
// "Hoş geldin\n",
|
||||
// "Koş geldiniz\n",
|
||||
"Hoş geldin\n",
|
||||
"Koş geldiniz\n",
|
||||
"Ulufale mai!\n",
|
||||
"Xush kelibsiz\n",
|
||||
"Benvignùo\n",
|
||||
@ -1191,14 +1191,14 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
"Croeso\n",
|
||||
"Merhbe\n",
|
||||
"Wamkelekile\n",
|
||||
// "Märr-ŋamathirri\n",
|
||||
// "Ẹ ku abọ\n",
|
||||
"Märr-ŋamathirri\n",
|
||||
"Ẹ ku abọ\n",
|
||||
"Kíimak 'oolal\n",
|
||||
"Ngiyakwemukela\n"
|
||||
};
|
||||
|
||||
fputs("pdfioFileCreateFontObjFromFile(OpenSans-Regular.ttf): ", stdout);
|
||||
if ((opensans = pdfioFileCreateFontObjFromFile(pdf, "testfiles/OpenSans-Regular.ttf", false)) != NULL)
|
||||
if ((opensans = pdfioFileCreateFontObjFromFile(pdf, "testfiles/OpenSans-Regular.ttf", true)) != NULL)
|
||||
puts("PASS");
|
||||
else
|
||||
return (1);
|
||||
@ -1267,7 +1267,7 @@ write_font_test(pdfio_file_t *pdf, // I - PDF file
|
||||
}
|
||||
|
||||
printf("pdfioContentTextShow(\"%s\"): ", welcomes[i]);
|
||||
if (pdfioContentTextShow(st, welcomes[i]))
|
||||
if (pdfioContentTextShow(st, true, welcomes[i]))
|
||||
puts("PASS");
|
||||
else
|
||||
return (1);
|
||||
@ -1329,7 +1329,7 @@ write_header_footer(
|
||||
return (1);
|
||||
|
||||
printf("pdfioContentTextShow(\"%s\"): ", title);
|
||||
if (pdfioContentTextShow(st, title))
|
||||
if (pdfioContentTextShow(st, false, title))
|
||||
puts("PASS");
|
||||
else
|
||||
return (1);
|
||||
@ -1347,7 +1347,7 @@ write_header_footer(
|
||||
return (1);
|
||||
|
||||
printf("pdfioContentTextShowf(\"%d\"): ", number);
|
||||
if (pdfioContentTextShowf(st, "%d", number))
|
||||
if (pdfioContentTextShowf(st, false, "%d", number))
|
||||
puts("PASS");
|
||||
else
|
||||
return (1);
|
||||
@ -1740,7 +1740,7 @@ write_png_test(pdfio_file_t *pdf, // I - PDF file
|
||||
goto error;
|
||||
|
||||
fputs("pdfioContentTextShow(\"PNG RGB Color\"): ", stdout);
|
||||
if (pdfioContentTextShow(st, "PNG RGB Color"))
|
||||
if (pdfioContentTextShow(st, false, "PNG RGB Color"))
|
||||
puts("PASS");
|
||||
else
|
||||
goto error;
|
||||
@ -1752,7 +1752,7 @@ write_png_test(pdfio_file_t *pdf, // I - PDF file
|
||||
goto error;
|
||||
|
||||
fputs("pdfioContentTextShow(\"PNG Gray\"): ", stdout);
|
||||
if (pdfioContentTextShow(st, "PNG Gray"))
|
||||
if (pdfioContentTextShow(st, false, "PNG Gray"))
|
||||
puts("PASS");
|
||||
else
|
||||
goto error;
|
||||
@ -1764,7 +1764,7 @@ write_png_test(pdfio_file_t *pdf, // I - PDF file
|
||||
goto error;
|
||||
|
||||
fputs("pdfioContentTextShow(\"PNG Indexed\"): ", stdout);
|
||||
if (pdfioContentTextShow(st, "PNG Indexed"))
|
||||
if (pdfioContentTextShow(st, false, "PNG Indexed"))
|
||||
puts("PASS");
|
||||
else
|
||||
goto error;
|
||||
@ -1936,7 +1936,7 @@ write_text_test(pdfio_file_t *pdf, // I - PDF file
|
||||
|
||||
if (!pdfioContentSetFillColorDeviceGray(st, 0.75))
|
||||
goto error;
|
||||
if (!pdfioContentTextShowf(st, "%3d ", flinenum))
|
||||
if (!pdfioContentTextShowf(st, false, "%3d ", flinenum))
|
||||
goto error;
|
||||
if (!pdfioContentSetFillColorDeviceGray(st, 0.0))
|
||||
goto error;
|
||||
@ -1948,15 +1948,15 @@ write_text_test(pdfio_file_t *pdf, // I - PDF file
|
||||
temp[80] = '\n';
|
||||
temp[81] = '\0';
|
||||
|
||||
if (!pdfioContentTextShow(st, temp))
|
||||
if (!pdfioContentTextShow(st, false, temp))
|
||||
goto error;
|
||||
|
||||
if (!pdfioContentTextShowf(st, " %s", line + 80))
|
||||
if (!pdfioContentTextShowf(st, false, " %s", line + 80))
|
||||
goto error;
|
||||
|
||||
plinenum ++;
|
||||
}
|
||||
else if (!pdfioContentTextShow(st, line))
|
||||
else if (!pdfioContentTextShow(st, false, line))
|
||||
goto error;
|
||||
|
||||
plinenum ++;
|
||||
|
32
ttf.c
32
ttf.c
@ -187,6 +187,8 @@ struct _ttf_s
|
||||
char *postscript_name; // PostScript name string
|
||||
char *version; // Font version string
|
||||
bool is_fixed; // Is this a fixed-width font?
|
||||
int max_char, // Last character in font
|
||||
min_char; // First character in font
|
||||
_ttf_metric_t *widths[TTF_FONT_MAX_CHAR / 256];
|
||||
// Character metrics (sparse array)
|
||||
float units; // Width units
|
||||
@ -447,6 +449,8 @@ ttfCreate(const char *filename, // I - Filename
|
||||
font->x_height = 3 * font->ascent / 5;
|
||||
|
||||
// Build a sparse glyph widths table...
|
||||
font->min_char = -1;
|
||||
|
||||
for (i = 0; i < num_cmap; i ++)
|
||||
{
|
||||
if (cmap[i] >= 0)
|
||||
@ -454,6 +458,12 @@ ttfCreate(const char *filename, // I - Filename
|
||||
int bin = i / 256, // Sub-array bin
|
||||
glyph = cmap[i]; // Glyph index
|
||||
|
||||
// Update min/max...
|
||||
if (font->min_char < 0)
|
||||
font->min_char = i;
|
||||
|
||||
font->max_char = i;
|
||||
|
||||
// Allocate a sub-array as needed...
|
||||
if (!font->widths[bin])
|
||||
font->widths[bin] = (_ttf_metric_t *)calloc(256, sizeof(_ttf_metric_t));
|
||||
@ -720,6 +730,28 @@ ttfGetItalicAngle(ttf_t *font) // I - Font
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'ttfGetMaxChar()' - Get the last character in the font.
|
||||
//
|
||||
|
||||
int // O - Last character in font
|
||||
ttfGetMaxChar(ttf_t *font) // I - Font
|
||||
{
|
||||
return (font ? font->max_char : 0);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'ttfGetMinChar()' - Get the first character in the font.
|
||||
//
|
||||
|
||||
int // O - First character in font
|
||||
ttfGetMinChar(ttf_t *font) // I - Font
|
||||
{
|
||||
return (font ? font->min_char : 0);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'ttfGetNumFonts()' - Get the number of fonts in this collection.
|
||||
//
|
||||
|
2
ttf.h
2
ttf.h
@ -95,6 +95,8 @@ extern int ttfGetDescent(ttf_t *font);
|
||||
extern ttf_rect_t *ttfGetExtents(ttf_t *font, float size, const char *s, ttf_rect_t *extents);
|
||||
extern const char *ttfGetFamily(ttf_t *font);
|
||||
extern float ttfGetItalicAngle(ttf_t *font);
|
||||
extern int ttfGetMaxChar(ttf_t *font);
|
||||
extern int ttfGetMinChar(ttf_t *font);
|
||||
extern size_t ttfGetNumFonts(ttf_t *font);
|
||||
extern const char *ttfGetPostScriptName(ttf_t *font);
|
||||
extern ttf_stretch_t ttfGetStretch(ttf_t *font);
|
||||
|
Loading…
Reference in New Issue
Block a user