1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
/* Copyright (C) 2001-2023 Artifex Software, Inc.
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.
*/
/* pxffont.c */
/* PCL XL font-finding procedures */
#include "string_.h"
#include "gx.h"
#include "gschar.h"
#include "gsmatrix.h" /* for gsfont.h */
#include "gxfont.h"
#include "gxfont42.h"
#include "pxoper.h"
#include "pxstate.h"
#include "pxfont.h"
#include "pjtop.h"
/* ---------------- Operator utilities ---------------- */
#if ARCH_IS_BIG_ENDIAN
# define pxd_native_byte_order pxd_big_endian
#else
# define pxd_native_byte_order 0
#endif
/* Widen and/or byte-swap a font name to Unicode if needed. */
/* The argument is a ubyte or uint16 array; the result is a uint16 array */
/* with the elements in native byte order. */
/* We don't deal with mappings: we just widen 8-bit to 16-bit characters */
/* and hope for the best.... */
static int
px_widen_font_name(px_value_t * pfnv, px_state_t * pxs)
{
uint type = pfnv->type;
if ((type & (pxd_uint16 | pxd_big_endian)) ==
(pxd_uint16 | pxd_native_byte_order)
)
return 0; /* already in correct format */
{
byte *old_data = (byte *) pfnv->value.array.data; /* break const */
uint size = pfnv->value.array.size;
char16 *new_data;
uint i;
if (type & pxd_on_heap)
old_data = (byte *)
(new_data =
(char16 *) gs_resize_object(pxs->memory, old_data,
size * 2, "px_widen_font_name"));
else
new_data =
(char16 *) gs_alloc_byte_array(pxs->memory, size,
sizeof(char16),
"px_widen_font_name");
if (new_data == 0)
return_error(errorInsufficientMemory);
for (i = size; i;) {
--i;
new_data[i] =
(type & pxd_ubyte ? old_data[i] :
uint16at(old_data + i * 2, type & pxd_big_endian));
}
pfnv->value.array.data = (byte *) new_data;
}
pfnv->type = (type & ~(pxd_ubyte | pxd_big_endian)) |
(pxd_uint16 | pxd_native_byte_order | pxd_on_heap);
return 0;
}
/* ---------------- Operator implementations ---------------- */
/* Look up a font name and return an existing font. */
/* This procedure may widen and/or byte-swap the font name. */
/* If this font is supposed to be built in but no .TTF file is available, */
/* or if loading the font fails, return >= 0 and store 0 in *ppxfont. */
int
px_find_existing_font(px_value_t * pfnv, px_font_t ** ppxfont,
px_state_t * pxs)
{
int code;
void *pxfont;
*ppxfont = NULL;
/* Normalize the font name to Unicode. */
code = px_widen_font_name(pfnv, pxs);
if (code < 0)
return code;
if (px_dict_find(&pxs->font_dict, pfnv, &pxfont)) {
/* Make sure this isn't a partially defined font */
if (((px_font_t *) pxfont)->pfont)
*ppxfont = pxfont;
else {
/* in the process of being downloaded. */
dmprintf(pxs->memory, "font is being downloaded???\n");
return -1;
}
} else if (px_dict_find(&pxs->builtin_font_dict, pfnv, &pxfont))
if (((px_font_t *) pxfont)->pfont)
*ppxfont = pxfont;
else {
dmprintf(pxs->memory, "corrupt pxl builtin font\n");
return -1;
} else
return -1; /* font not found or corrupt builtin font */
return 0;
}
/* Look up a font name and return a font, possibly with substitution. */
/* This procedure implements most of the SetFont operator. */
/* This procedure may widen and/or byte-swap the font name. */
int
px_find_font(px_value_t * pfnv, uint symbol_set, px_font_t ** ppxfont,
px_state_t * pxs)
{
int code;
/* Check if we know the font already. */
/* Note that px_find_existing_font normalizes the font name. */
code = px_find_existing_font(pfnv, ppxfont, pxs);
/* substitute for missing builtin font */
if (code < 0) {
px_value_t default_font_value;
/* the documentation states the default font chosen here
is device dependent */
const char *default_font = "Courier ";
char message[px_max_error_line + 1];
default_font_value.type = pxd_ubyte | pxd_array;
default_font_value.value.array.data = (const byte *)default_font;
default_font_value.value.array.size = strlen(default_font);
code = px_find_existing_font(&default_font_value, ppxfont, pxs);
/* shouldn't fail */
if (code < 0)
return code;
message[0] = (char)0;
px_concat_font_name(message, px_max_error_line, &default_font_value);
strcat(message, "substituted for ");
px_concat_font_name(message, px_max_error_line, pfnv);
code = px_record_warning(message, false, pxs);
}
if (code >= 0)
return pl_load_resident_font_data_from_file(pxs->memory, *ppxfont);
else
return code;
}
|