Based on patch from Stuart Parmenter. Now one can use
cairo_ft_font_face_create_for_pattern() to create cairo-ft font
faces using provided FT_Face but also requesting advanced
options like emboldening and hinting.
Rewrite the PDF operators show_glyphs() function to make it more
maintainable and better optimized.
The changes include:
- Use a separate function to output each text operator and update the
internal state.
- Store glyphs in a buffer until they can be written out as one
string. This reduces the complexity of the code for emitting glyph
strings and significantly optimizes the output size as glyphs from
multiple calls to show_glyphs() can be accumulated and written in one
string.
- The code now better handles rotated text. Previously, using rotated
text resulted in the text matrix emitted for every glyph. Now rotated
text can be emitted as strings in the some way as non rotated
text. This is particulary useful for printing in landscape mode where
all text on the page is rotated.
A text object is a series of text operations enclosed in a 'BT'/'ET'
pair.
After a call to _cairo_pdf_operators_show_glyphs() the closing 'ET'
will not be emitted. This allows subsequent calls to show_glyphs() to
emit text into the same text object. A call to any other operator or
_cairo_pdf_operators_flush() will close the text object.
The optimizations planned for pdf-operators will mean that it will no
longer emit complete operations on each call to
fill/stroke/show_glyphs. For example a call to _show_glyphs() may not
finish the text operation to allow a subsequent call to _show_glyphs()
to be merged into the same text object.
A flush function is required to force pdf_operators to complete the
current operation before the pdf surface can emit any pdf operators.
Some Type 1 fonts have some PostScript code at the start of the font
that checks if the font is already cached in the printer (based on the
font UniqueID key). This breaks our subsetted font as it is not the
same as the original font.
Checking for and removing a random blob of PostScript is difficult so
this patch takes the simpler approach of searching for the PS code
that checks if the UniqueID dictionary entry exists
ie
/UniqueID known
this code leaves the value "true" or "false" on the PS interpreter
stack depending on whether the "UniqueID" key exists.
Then the patch inserts the PS code " pop false " after the above code
to remove the old result and place "false" on the stack to make it
appear that UniqueID does not exist.
This approach should be able to handle any type of PostScript code
that attempts to do something with the UniqueID value in the font
dictionary.
This ensures that PS/PDF output is always the same for the same cairo
input. Previously the order of the embedded fonts depended on the hash
key of the fonts which depended on the memory location of fonts.
In the eexec encryption used in Type 1 fonts, the first four bytes of
ciphertext must not start with a white space character or contain an
ASCII Hex character. Some fonts do not comply with this
restriction. This may cause problems for some PDF consumers.
Fix this by overwriting the four random bytes at the start of the
decrypted cleartext with spaces. When re-encrypted the first four
bytes of ciphertext will always be 0xf0, 0x83, 0xef, 0x00 which
complies with the restrictions.
These are all perfectly correct code. Most are simply there because when
we support vertical text writing mode we need to update there, but that's
pretty trivial. No special markers needed.
/me is trying to make user-font clean of XXX and TODO marks
Someone reported on cairo list that on some system with gcc, he had the
compile-time assertion failing, meaning that the following struct:
typedef struct {
unsigned long index;
union {
struct {
double x;
double y;
} d;
struct {
int x;
int y;
} i;
} p;
} cairo_xlib_glyph_t;
had a different size from:
typedef struct {
unsigned long index;
double x;
double y;
} cairo_glyph_t;
That looks quite a weird thing for a compiler to do. Anyway, rewriting
our struct like this may help in those weird situations:
typedef union {
cairo_glyph_t d;
unsigned long index;
struct {
unsigned long index;
int x;
int y;
} i;
} cairo_xlib_glyph_t;
That's what we do now.