summaryrefslogtreecommitdiff
path: root/pcl/pcsymbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'pcl/pcsymbol.c')
-rw-r--r--pcl/pcsymbol.c330
1 files changed, 330 insertions, 0 deletions
diff --git a/pcl/pcsymbol.c b/pcl/pcsymbol.c
new file mode 100644
index 000000000..67e437de3
--- /dev/null
+++ b/pcl/pcsymbol.c
@@ -0,0 +1,330 @@
+/* Portions Copyright (C) 2001 artofcode LLC.
+ Portions Copyright (C) 1996, 2001 Artifex Software Inc.
+ Portions Copyright (C) 1988, 2000 Aladdin Enterprises.
+ This software is based in part on the work of the Independent JPEG Group.
+ All Rights Reserved.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/ or
+ contact Artifex Software, Inc., 101 Lucas Valley Road #110,
+ San Rafael, CA 94903, (415)492-9861, for further information. */
+/*$Id$ */
+
+/* pcsymbol.c */
+/* PCL5 user-defined symbol set commands */
+#include "stdio_.h" /* std.h + NULL */
+#include "plvalue.h"
+#include "pcommand.h"
+#include "pcstate.h"
+#include "pcfont.h"
+#include "pcsymbol.h"
+
+
+static int /* ESC * c <id> R */
+pcl_symbol_set_id_code(pcl_args_t *pargs, pcl_state_t *pcs)
+{ uint id = uint_arg(pargs);
+ id_set_value(pcs->symbol_set_id, id);
+ return 0;
+}
+
+static int /* ESC ( f <count> W */
+pcl_define_symbol_set(pcl_args_t *pargs, pcl_state_t *pcs)
+{ uint count = uint_arg(pargs);
+ const pl_symbol_map_t *psm = (pl_symbol_map_t *)arg_data(pargs);
+ uint header_size;
+ uint first_code, last_code;
+ gs_memory_t *mem = pcs->memory;
+ pl_symbol_map_t *header;
+ pcl_symbol_set_t *symsetp;
+ pl_glyph_vocabulary_t gv;
+
+#define psm_header_size 18
+ if ( count < psm_header_size )
+ return e_Range;
+ header_size = pl_get_uint16(psm->header_size);
+ if ( header_size < psm_header_size ||
+ psm->id[0] != id_key(pcs->symbol_set_id)[0] ||
+ psm->id[1] != id_key(pcs->symbol_set_id)[1] ||
+ psm->type > 2
+ )
+ return e_Range;
+ switch ( psm->format )
+ {
+ case 1:
+ case 3:
+ break;
+ default:
+ return e_Range;
+ }
+ first_code = pl_get_uint16(psm->first_code);
+ last_code = pl_get_uint16(psm->last_code);
+ gv = (psm->character_requirements[7] & 07)==1? plgv_Unicode: plgv_MSL;
+ { int num_codes = last_code - first_code + 1;
+ int i;
+
+ if ( num_codes <= 0 || last_code > 255 || (count != psm_header_size + num_codes * 2) )
+ return e_Range;
+
+ header =
+ (pl_symbol_map_t *)gs_alloc_bytes(mem,
+ sizeof(pl_symbol_map_t),
+ "pcl_font_header(header)");
+ if ( header == 0 )
+ return_error(e_Memory);
+ memcpy((void *)header, (void *)psm, psm_header_size);
+ /* specify that we do not allow these sets to map to and fro
+ msl and unicode */
+ header->mapping_type = PLGV_NO_MAPPING;
+ /*
+ * Byte swap the codes now, so that we don't have to byte swap
+ * them every time we access them.
+ */
+ for ( i = num_codes; --i >= 0; )
+ header->codes[i] =
+ pl_get_uint16((byte *)psm + psm_header_size + i * 2);
+ }
+#undef psm_header_size
+
+ /* Symbol set may already exist; if so, we may be replacing one of
+ * its existing maps or adding one for a new glyph vocabulary. */
+ if ( pl_dict_find(&pcs->soft_symbol_sets, id_key(pcs->symbol_set_id),
+ 2, (void **)&symsetp) )
+ {
+ if ( symsetp->maps[gv] != NULL )
+ gs_free_object(mem, symsetp->maps[gv], "symset map");
+ }
+ else
+ { pl_glyph_vocabulary_t gx;
+ symsetp = (pcl_symbol_set_t *)gs_alloc_bytes(mem,
+ sizeof(pcl_symbol_set_t), "symset dict value");
+ if ( !symsetp )
+ return_error(e_Memory);
+ for ( gx = plgv_MSL; gx < plgv_next; gx++ )
+ symsetp->maps[gx] = NULL;
+ symsetp->storage = pcds_temporary;
+ pl_dict_put(&pcs->soft_symbol_sets, id_key(pcs->symbol_set_id),
+ 2, symsetp);
+ }
+ symsetp->maps[gv] = header;
+
+ return 0;
+}
+
+static int /* ESC * c <ssc_enum> S */
+pcl_symbol_set_control(pcl_args_t *pargs, pcl_state_t *pcs)
+{ gs_const_string key;
+ void *value;
+ pl_dict_enum_t denum;
+
+ switch ( int_arg(pargs) )
+ {
+ case 0:
+ { /* Delete all user-defined symbol sets. */
+ /* Note: When deleting symbol set(s), it is easier (safer?)
+ * to decache and reselect fonts unconditionally. (Consider,
+ * for example, deleting a downloaded overload of a built-in
+ * which might be the default ID.) */
+ pl_dict_release(&pcs->soft_symbol_sets);
+ pcl_decache_font(pcs, -1);
+ }
+ return 0;
+ case 1:
+ { /* Delete all temporary symbol sets. */
+ pl_dict_enum_stack_begin(&pcs->soft_symbol_sets, &denum, false);
+ while ( pl_dict_enum_next(&denum, &key, &value) )
+ if ( ((pcl_symbol_set_t *)value)->storage == pcds_temporary )
+ pl_dict_undef(&pcs->soft_symbol_sets, key.data, key.size);
+ pcl_decache_font(pcs, -1);
+ }
+ return 0;
+ case 2:
+ { /* Delete symbol set <symbol_set_id>. */
+ pl_dict_undef(&pcs->soft_symbol_sets,
+ id_key(pcs->symbol_set_id), 2);
+ pcl_decache_font(pcs, -1);
+ }
+ return 0;
+ case 4:
+ { /* Make <symbol_set_id> temporary. */
+ if ( pl_dict_find(&pcs->soft_symbol_sets,
+ id_key(pcs->symbol_set_id), 2, &value) )
+ ((pcl_symbol_set_t *)value)->storage = pcds_temporary;
+ }
+ return 0;
+ case 5:
+ { /* Make <symbol_set_id> permanent. */
+ if ( pl_dict_find(&pcs->soft_symbol_sets,
+ id_key(pcs->symbol_set_id), 2, &value) )
+ ((pcl_symbol_set_t *)value)->storage = pcds_permanent;
+ }
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static void /* free any symbol maps as well as dict value entry */
+pcsymbol_dict_value_free(gs_memory_t *mem, void *value, client_name_t cname)
+{ pcl_symbol_set_t *ssp = (pcl_symbol_set_t *)value;
+ pl_glyph_vocabulary_t gx;
+
+ if ( ssp->storage != pcds_internal )
+ {
+ for ( gx = plgv_MSL; gx < plgv_next; gx++ )
+ {
+ if ( ssp->maps[gx] != NULL )
+ gs_free_object(mem, (void*)ssp->maps[gx], cname);
+ }
+ }
+ gs_free_object(mem, value, cname);
+}
+
+static int
+pcl_load_built_in_symbol_sets(pcl_state_t *pcs)
+{
+ const pl_symbol_map_t **maplp;
+ pcl_symbol_set_t *symsetp;
+ pl_glyph_vocabulary_t gv;
+
+ for ( maplp = &pl_built_in_symbol_maps[0]; *maplp; maplp++ )
+ {
+ const pl_symbol_map_t *mapp = *maplp;
+ /* Create entry for symbol set if this is the first map for
+ * that set. */
+ if ( !pl_dict_find(&pcs->built_in_symbol_sets, mapp->id, 2,
+ (void **)&symsetp) )
+ { pl_glyph_vocabulary_t gx;
+ symsetp = (pcl_symbol_set_t *)gs_alloc_bytes(pcs->memory,
+ sizeof(pcl_symbol_set_t), "symset init dict value");
+ if ( !symsetp )
+ return_error(e_Memory);
+ for ( gx = plgv_MSL; gx < plgv_next; gx++ )
+ symsetp->maps[gx] = NULL;
+ symsetp->storage = pcds_internal;
+ }
+ gv = (mapp->character_requirements[7] & 07)==1?
+ plgv_Unicode: plgv_MSL;
+ pl_dict_put(&pcs->built_in_symbol_sets, mapp->id, 2, symsetp);
+ symsetp->maps[gv] = (pl_symbol_map_t *)mapp;
+ }
+ return 0;
+}
+
+bool
+pcl_check_symbol_support(const byte *symset_req, const byte *font_sup)
+{ int i;
+
+ /* if glyph vocabularies match, following will work on the
+ * last 3 bits of last byte. Note that the font-support bits
+ * are inverted (0 means available).
+ */
+ for ( i = 0; i < 7; i++ )
+ if ( symset_req[i] & font_sup[i] )
+ return false; /* something needed, not present */
+ /* check the last byte but not the glyph vocabularies. */
+ if ((symset_req[7] >> 3) & (font_sup[7] >> 3))
+ return false;
+
+ return true;
+}
+
+
+/* Find the symbol map for a particular symbol set and glyph vocabulary,
+ * if it exists.
+ * There are two dictionaries--one for soft (downloaded) symbol sets and
+ * one for built-ins. These are searched separately. The actual maps
+ * present for a symbol set may overlap between soft and built-in. */
+pl_symbol_map_t *
+pcl_find_symbol_map(const pcl_state_t *pcs, const byte *id,
+ pl_glyph_vocabulary_t gv)
+{
+ pcl_symbol_set_t *setp;
+
+ if ( pl_dict_find((pl_dict_t *)&pcs->soft_symbol_sets,
+ id, 2, (void **)&setp) &&
+ setp->maps[gv] != NULL )
+ return setp->maps[gv];
+ if ( pl_dict_find((pl_dict_t *)&pcs->built_in_symbol_sets,
+ id, 2, (void**)&setp) ) {
+ /* simple case we found a matching symbol set */
+ if ( setp->maps[gv] != NULL )
+ return setp->maps[gv];
+ /* we requested a unicode symbol set and found an msl
+ symbol set that can be mapped to unicode */
+ if ( (gv == plgv_Unicode) &&
+ (setp->maps[plgv_MSL]) &&
+ ((setp->maps[plgv_MSL])->mapping_type == PLGV_M2U_MAPPING) )
+ return setp->maps[plgv_MSL];
+ /* we requested an msl symbol set and found a unicode
+ symbol set that can be mapped to msl */
+ if ( (gv == plgv_MSL) &&
+ (setp->maps[plgv_Unicode]) &&
+ ((setp->maps[plgv_Unicode])->mapping_type == PLGV_U2M_MAPPING) )
+ return setp->maps[plgv_Unicode];
+ }
+ return NULL;
+}
+
+/* Initialization */
+static int
+pcsymbol_do_registration(
+ pcl_parser_state_t *pcl_parser_state,
+ gs_memory_t *mem
+)
+{ /* Register commands */
+ DEFINE_CLASS_COMMAND_ARGS('*', 'c', 'R', "Symbol Set ID Code",
+ pcl_symbol_set_id_code,
+ pca_neg_error|pca_big_error)
+ DEFINE_CLASS_COMMAND_ARGS('(', 'f', 'W', "Define Symbol Set",
+ pcl_define_symbol_set, pca_byte_data|pca_neg_error|pca_big_clamp)
+ DEFINE_CLASS_COMMAND_ARGS('*', 'c', 'S', "Symbol Set Control",
+ pcl_symbol_set_control,
+ pca_neg_ignore|pca_big_ignore)
+ return 0;
+}
+
+static void
+pcsymbol_do_reset(pcl_state_t *pcs, pcl_reset_type_t type)
+{
+ if ( type & (pcl_reset_initial | pcl_reset_printer | pcl_reset_overlay) ) {
+ id_set_value(pcs->symbol_set_id, 0);
+ if ( type & pcl_reset_initial ) {
+ /* Don't set a parent relationship from soft to built-in
+ * symbol sets. Although it is arguably useful, it's
+ * better to avoid it and keep anyone who's looking at the
+ * soft symbol sets from mucking up the permanent ones. */
+ pl_dict_init(&pcs->soft_symbol_sets, pcs->memory,
+ pcsymbol_dict_value_free);
+ pl_dict_init(&pcs->built_in_symbol_sets, pcs->memory,
+ pcsymbol_dict_value_free);
+ /* NB. Symbol sets are require for RTL/HPGL/2 mode for
+ * stickfonts but we shouldn't load all of them. */
+ if ( pcl_load_built_in_symbol_sets(pcs) < 0 )
+ dprintf("Internal error, no symbol sets found");
+ }
+ else if ( type & pcl_reset_printer ) {
+ pcl_args_t args;
+ arg_set_uint(&args, 1); /* delete temporary symbol sets */
+ pcl_symbol_set_control(&args, pcs);
+ }
+ }
+ if ( type & pcl_reset_permanent ) {
+ pl_dict_release(&pcs->soft_symbol_sets);
+ pl_dict_release(&pcs->built_in_symbol_sets);
+ }
+}
+
+static int
+pcsymbol_do_copy(pcl_state_t *psaved, const pcl_state_t *pcs,
+ pcl_copy_operation_t operation)
+{ if ( operation & pcl_copy_after )
+ { /* Don't restore the downloaded symbol set dictionary. */
+ psaved->built_in_symbol_sets = pcs->built_in_symbol_sets;
+ }
+ return 0;
+}
+
+const pcl_init_t pcsymbol_init = {
+ pcsymbol_do_registration, pcsymbol_do_reset, pcsymbol_do_copy
+};