All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
implied.
This software is distributed under license and may not be copied,
modified or distributed except as expressly authorized under the terms
of the license contained in the file LICENSE in this distribution.
Refer to licensing information at http://www.artifex.com or contact
Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
CA 94129, USA, for further information.
*/
* the 'gs_font' structure is not reference counted. The PostScript interpreter relies upon
* the garbage collector to clean these up, but since we aren't using a garbage collector
* we have to manage the lifetime of these ourselves.
*
* The complication is that the gs_font pointer is stored in the graphics state and there
* is no simple mechanism to know when a font in a graphics state is no longer being used
* (in the absence of a garbage collector). So what we do is use the 'client_data' member
* of the gs_font structure to point to our font object, a pdf_font *, which itself
* contains a pointer to the gs_font structure.
*
* On each pdfi_gsave() we look at the gs_font in the current graphics state (if any) and
* use the client_data to find the corresponding pdf_font, we then cout that object up. On
* each pdfi_grestore we again use the client_data to find our pdf_font object, and count
* it down. The Tf operator replaces the gs_font in the current graphics state, and we count
* the current one down, and the new one up, before replacing it.
*
* When the pdf_font object's reference count reaches 0 we can safely free the associated
* gs_font structure. Note that the cache may still contain a reference to the pdf_font
* object, so it may not be freed immediately it is no longer in use. This helps us avoid
* too much redefinition of fonts.
*
* When we create a pdf_font object, we replace the cached object, which is a dictionary,
* with the pdf_font object. So when we call pdfi_dereference() if we get back a pdf_font
* object we know that this is an existing font (keyed by object number) and don't need to
* rebuild it. If we get a pdf_dict object then we do need to build the graphics library
* font.
*
* This still does leave the (admittedly remote) possibility of using a font in one graphics
* state, gsave'ing, setting a new font, and then dereferencing enough objects to force the
* original font out of the cache, then using that same font again. While there is no
* obvious problem with that, it is inefficient. I think we can evade the problem by using
* the next and prev pointers in the gs_fotn structure. If we keep the linked list correct
* when creating and freeing fonts, we can walk the list of 'active' fonts, following
* the clien_data pointer to get the pdf_font object, and checking its object number against
* the one we are looking for. We only need to do this if the result of pdfi_derference()
* Is a pdf_dict object. Obviously if we don't find an active font then we need to go
* through the effort of creating one.
*
* FIXME - none of the above is yet implemented!
*/
#ifndef PDF_FONT_DATA
#define PDF_FONT_DATA
#include "pdf_types.h"
#include "pdf_cmap.h"
#include "gxfont.h"
#include "gsfont.h"
typedef enum pdf_font_type_e {
e_pdf_font_type0,
e_pdf_font_type1,
e_pdf_font_cff,
e_pdf_font_type3,
e_pdf_cidfont_type0 = 9,
e_pdf_cidfont_type1,
e_pdf_cidfont_type2,
e_pdf_cidfont_type4 = 32,
e_pdf_font_truetype = 42,
} pdf_font_type;
#define pdf_font_base \
pdf_obj_common;\
gs_font_base *pfont; \
pdf_font_type pdfi_font_type; \
pdf_dict *PDF_font; \
pdf_obj *BaseFont; \
pdf_dict *FontDescriptor; \
int64_t descflags; \
pdf_obj *ToUnicode; \
bool substitute; \
pdf_string *filename; \
font_proc_font_info((*default_font_info)); \
font_type orig_FontType; \
pdf_string *copyright; \
pdf_string *notice; \
pdf_string *fullname; \
pdf_string *familyname
#define pdf_font_common \
pdf_font_base;\
pdf_obj *Name; \
unsigned int FirstChar; \
unsigned int LastChar; \
double MissingWidth; \
double *Widths; \
pdf_array *Encoding
strings assumed to be managed be managed by the interpreter - so we have to stash
them in the pdfi font, too.
*/
#define pdf_cid_font_common \
pdf_font_base;\
pdf_dict *CIDSystemInfo; \
double DW; \
pdf_array *W; \
pdf_array *DW2; \
pdf_array *W2; \
pdf_string *registry; \
pdf_string *ordering; \
int supplement; \
pdf_buffer *cidtogidmap; \
pdfi_cid_decoding_t *decoding; \
pdfi_cid_subst_nwp_table_t *substnwp; \
font_proc_glyph_info((*orig_glyph_info))
typedef struct pdf_font_s {
pdf_font_common;
}pdf_font;
typedef struct pdfi_cid_decoding_s {
const char *s_order;
const char *d_order;
const int nranges;
const int val_sizes;
const int ranges[114][256][4];
} pdfi_cid_decoding_t;
struct pdfi_cid_subst_nwp_rec_s {
const char s_type;
const unsigned int s_scid;
const unsigned int e_scid;
const unsigned int s_dcid;
const char d_type;
};
typedef struct pdfi_cid_subst_nwp_table_s {
const char *ordering;
struct pdfi_cid_subst_nwp_rec_s subst[32];
} pdfi_cid_subst_nwp_table_t;
typedef struct pdf_font_type0_s {
pdf_font_base;
pdf_obj *Encoding;
pdf_array *DescendantFonts;
pdfi_cid_decoding_t *decoding;
pdfi_cid_subst_nwp_table_t *substnwp;
} pdf_font_type0;
typedef struct pdf_font_type1_s {
pdf_font_common;
pdf_array *Subrs;
pdf_dict *CharStrings;
pdf_array *blenddesignpositions;
pdf_array *blenddesignmap;
pdf_array *blendfontbbox;
pdf_array *blendaxistypes;
} pdf_font_type1;
typedef struct pdf_font_cff_s {
pdf_font_common;
pdf_array *Subrs;
int NumSubrs;
pdf_array *GlobalSubrs;
int NumGlobalSubrs;
pdf_dict *CharStrings;
int ncharstrings;
} pdf_font_cff;
typedef struct pdf_font_type3_s {
pdf_font_common;
pdf_array *FontBBox;
pdf_array *FontMatrix;
pdf_dict *CharProcs;
} pdf_font_type3;
typedef enum {
pdfi_truetype_cmap_none,
pdfi_truetype_cmap_10,
pdfi_truetype_cmap_30,
pdfi_truetype_cmap_31,
pdfi_truetype_cmap_310
} pdfi_truetype_cmap;
typedef struct pdf_font_truetype_s {
pdf_font_common;
pdf_buffer *sfnt;
pdfi_truetype_cmap cmap;
pdf_dict *post;
} pdf_font_truetype;
typedef struct pdf_cidfont_s {
pdf_cid_font_common;
} pdf_cidfont_t;
typedef struct pdf_cidfont_type0_s {
pdf_cid_font_common;
pdf_array *Subrs;
int NumSubrs;
pdf_array *GlobalSubrs;
int NumGlobalSubrs;
pdf_dict *CharStrings;
int ncharstrings;
pdf_array *FDArray;
int cidcount;
int uidbase;
} pdf_cidfont_type0;
typedef struct pdf_cidfont_type2_s {
pdf_cid_font_common;
pdf_buffer *sfnt;
} pdf_cidfont_type2;
#endif