📄 ps_util.c
字号:
/* * (c) Copyright 2001 Uwe Steinmann. * All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* $Id: ps_util.c,v 1.44 2007/07/11 16:03:57 steinm Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include "ps_intern.h"#include "ps_memory.h"#include "ps_fontenc.h"#include "ps_inputenc.h"#include "ps_error.h"/* ps_write() {{{ * Output data using the current writeprocedure */voidps_write(PSDoc *p, const void *data, size_t size) { (void) p->writeproc(p, (void *) data, size);}/* }}} *//* ps_putc() {{{ * Output char */voidps_putc(PSDoc *p, char c){ ps_write(p, (void *) &c, (size_t) 1);}/* }}} *//* ps_puts() {{{ * Output string */voidps_puts(PSDoc *p, const char *s){ ps_write(p, (void *) s, strlen(s));}/* }}} *//* ps_printf() {{{ * Output formated string */voidps_printf(PSDoc *p, const char *fmt, ...){ char buf[LINEBUFLEN]; /* formatting buffer */ va_list ap; va_start(ap, fmt); setlocale(LC_NUMERIC, "C"); (void) vsnprintf(buf, LINEBUFLEN, fmt, ap); setlocale(LC_NUMERIC, ""); ps_puts(p, buf); va_end(ap);}/* }}} *//* ps_ght_malloc() {{{ * * malloc routine which is passed to the hash table functions. */void* ps_ght_malloc(size_t size, void *data) { PSDoc *psdoc = data; return(psdoc->malloc(psdoc, size, _("Allocate memory for hash table of char metrics")));}/* }}} *//* ps_ght_free() {{{ * * free routine which is passed to the hash table functions. */void ps_ght_free(void *ptr, void *data) { PSDoc *psdoc = data; psdoc->free(psdoc, ptr);}/* }}} *//* ps_enter_scope() {{{ */void ps_enter_scope(PSDoc *psdoc, int scope) { if(psdoc->scopecount == (MAX_SCOPES-1)) { ps_error(psdoc, PS_RuntimeError, _("Maximum number of scopes reached.")); } else { psdoc->scopecount++; psdoc->scopes[psdoc->scopecount] = scope; }}/* }}} *//* ps_leave_scope() {{{ */void ps_leave_scope(PSDoc *psdoc, int scope) { if(scope != psdoc->scopes[psdoc->scopecount]) ps_error(psdoc, PS_RuntimeError, _("Trying to leave scope %d but you are in %d."), scope, psdoc->scopes[psdoc->scopecount]); else psdoc->scopecount--;}/* }}} *//* ps_current_scope() {{{ */int ps_current_scope(PSDoc *psdoc) { return(psdoc->scopes[psdoc->scopecount]);}/* }}} *//* ps_check_scope() {{{ */ps_bool ps_check_scope(PSDoc *psdoc, int scope) { return(scope & psdoc->scopes[psdoc->scopecount]);}/* }}} *//* ps_get_resources() {{{ * Returns an array of pointers to all resources of a category. */PS_RESOURCE **ps_get_resources(PSDoc *psdoc, const char *category, int *count) { PS_CATEGORY *cat; PS_RESOURCE *res; PS_RESOURCE **ress = NULL; int i; *count = 0; for(cat = dlst_first(psdoc->categories); cat != NULL; cat = dlst_next(cat)) { if (!strcmp(cat->name, category)) { ress = psdoc->malloc(psdoc, cat->resources->count * sizeof(PS_RESOURCE *), _("Allocate Memory for list of resources.")); *count = cat->resources->count; for(i=0, res = dlst_first(cat->resources); res != NULL; res = dlst_next(res), i++) { ress[i] = res; } } } return(ress);}/* }}} *//* ps_find_resource() {{{ */char *ps_find_resource(PSDoc *psdoc, const char *category, const char *resource) { PS_CATEGORY *cat; PS_RESOURCE *res; for(cat = dlst_first(psdoc->categories); cat != NULL; cat = dlst_next(cat)) { if (!strcmp(cat->name, category)) { for(res = dlst_first(cat->resources); res != NULL; res = dlst_next(res)) { if (!strcmp(res->name, resource)) return(res->value); } } } return(NULL);}/* }}} *//* ps_add_resource() {{{ */PS_RESOURCE * ps_add_resource(PSDoc *psdoc, const char *category, const char *resource, const char *filename, const char *prefix) { PS_CATEGORY *cat; PS_RESOURCE *res; /* Right and LeftMarginKerning are set in PS_set_paramter. They manipulate * the ADOBEINFO struct of the affected char directly. */ if (strcmp("SearchPath", category) && strcmp("FontAFM", category) && strcmp("FontEncoding", category) && strcmp("FontProtusion", category) && strcmp("FontOutline", category)) { return(NULL); } /* Search for the category */ for(cat = dlst_first(psdoc->categories); cat != NULL; cat = dlst_next(cat)) { if(!strcmp(cat->name, category)) break; } /* Create a new category if it does not exist */ if(cat == NULL) { if(NULL == (cat = (PS_CATEGORY *) dlst_newnode(psdoc->categories, sizeof(PS_CATEGORY)))) { return(NULL); } cat->name = ps_strdup(psdoc, category); cat->resources = dlst_init(psdoc->malloc, psdoc->realloc, psdoc->free); dlst_insertafter(psdoc->categories, cat, PS_DLST_HEAD(psdoc->categories)); } /* Check if resource already available */ if(resource) { for(res = dlst_first(cat->resources); res != NULL; res = dlst_next(res)) { if(!strcmp(res->name, resource)) break; } } else { res = NULL; } if(res) { psdoc->free(psdoc, res->name); res->name = ps_strdup(psdoc, resource); psdoc->free(psdoc, res->value); res->value = ps_strdup(psdoc, filename); } else { if(NULL == (res = (PS_RESOURCE *) dlst_newnode(cat->resources, sizeof(PS_RESOURCE)))) { return(NULL); } if(resource) res->name = ps_strdup(psdoc, resource); else res->name = NULL; res->value = ps_strdup(psdoc, filename); dlst_insertafter(cat->resources, res, PS_DLST_HEAD(cat->resources)); } return(res);}/* }}} *//* ps_del_resources() {{{ */void ps_del_resources(PSDoc *psdoc) { PS_CATEGORY *cat, *nextcat; PS_RESOURCE *res, *nextres; if(NULL == psdoc->categories) return; cat = dlst_first(psdoc->categories); while(cat != NULL) { nextcat = dlst_next(cat); psdoc->free(psdoc, cat->name); res = dlst_first(cat->resources); while(res != NULL) { nextres = dlst_next(res); if(res->name) psdoc->free(psdoc, res->name); if(res->value) psdoc->free(psdoc, res->value); res = nextres; } dlst_kill(cat->resources, dlst_freenode); cat = nextcat; } dlst_kill(psdoc->categories, dlst_freenode); psdoc->categories = NULL;}/* }}} *//* ps_del_parameters() {{{ */void ps_del_parameters(PSDoc *psdoc) { PS_PARAMETER *param, *nextparam; if(NULL == psdoc->parameters) return; param = dlst_first(psdoc->parameters); while(param != NULL) { nextparam = dlst_next(param); psdoc->free(psdoc, param->name); psdoc->free(psdoc, param->value); param = nextparam; } dlst_kill(psdoc->parameters, dlst_freenode); psdoc->parameters = NULL;}/* }}} *//* ps_del_values() {{{ */void ps_del_values(PSDoc *psdoc) { PS_VALUE *param, *nextparam; if(NULL == psdoc->values) return; param = dlst_first(psdoc->values); while(param != NULL) { nextparam = dlst_next(param); psdoc->free(psdoc, param->name); param = nextparam; } dlst_kill(psdoc->values, dlst_freenode); psdoc->values = NULL;}/* }}} *//* ps_del_bookmarks() {{{ */void ps_del_bookmarks(PSDoc *psdoc, DLIST *bookmarks) { PS_BOOKMARK *bm, *nextbm; if(NULL == bookmarks) return; bm = dlst_first(bookmarks); while(bm != NULL) { nextbm = dlst_next(bm); psdoc->free(psdoc, bm->text); ps_del_bookmarks(psdoc, bm->children); bm = nextbm; } dlst_kill(bookmarks, dlst_freenode);}/* }}} *//* ps_add_word_spacing() {{{ */void ps_add_word_spacing(PSDoc *psdoc, PSFont *psfont, float value) { psfont->wordspace += value * 1000.0 / psfont->size;}/* }}} *//* ps_set_word_spacing() {{{ */void ps_set_word_spacing(PSDoc *psdoc, PSFont *psfont, float value) { ADOBEINFO *ai; if(value != 0.0) { psfont->wordspace = value * 1000.0 / psfont->size; } else { ai = gfindadobe(psfont->metrics->gadobechars, "space"); if(ai) psfont->wordspace = ai->width; else psfont->wordspace = 500.0; }}/* }}} *//* ps_get_word_spacing() {{{ */float ps_get_word_spacing(PSDoc *psdoc, PSFont *psfont) { float ws; ws = ((float) psfont->wordspace) * psfont->size / 1000.0; return(ws);}/* }}} *//* ps_check_for_lig() {{{ * Checks if the characters in text form a ligature with the character * in ai. If that is the case the number of characters consumed in text * will be returned in offset and the name of the ligature will be returned * in newadobename. * Ligatures can be broken off by a ligdischar. In such a case 1 will be * returned * and offset is set to 1 in order to skip the ligdischar. newadobename is set * to the name of the passed character. */int ps_check_for_lig(PSDoc *psdoc, ADOBEFONTMETRIC *metrics, ADOBEINFO *ai, const char *text, char ligdischar, char **newadobename, int *offset) { ADOBEINFO *nextai; LIG *ligs; if((NULL == ai) || (NULL == ai->ligs)) return 0; if(NULL == text || text[0] == '\0') return 0; ligs = ai->ligs; /* ligdischar breaks ligatures. The idea is, that every char followed * by a ligdischar * forms a ligature which is the char itself. Setting offset to * 1 will skip the ligdischar */ if(ligs && text[0] == ligdischar) { *offset += 1; *newadobename = ai->adobename; return 1; } if(ligs) { int _offset = 0; char *nextadobename; nextai = gfindadobe(metrics->gadobechars, psdoc->inputenc->vec[(unsigned char) (text[0])]); if(NULL == nextai) return 0; /* check if nextai and the following char form a ligature * If that is the case then there is a change that we have a 3 char * ligature. First check if current char and ligature of 2nd and 3th * char for a ligature. */ if(ps_check_for_lig(psdoc, metrics, nextai, &text[1], ligdischar, &nextadobename, &_offset)) { while(ligs) { if(0 == strcmp(ligs->succ, nextadobename)) { *offset += 1+_offset; *newadobename = ligs->sub; return 1; } ligs = ligs->next; } } /* If we haven't found a three char ligature at this point then check * for a 2 char ligatur. */ ligs = ai->ligs; while(ligs) { // printf("Ligature for %s is %s\n", ai->adobename, ligs->succ); if(!strcmp(ligs->succ, nextai->adobename)) { ADOBEINFO *ligai; *offset += 1; /* check if the ligature made of the first two chars form a ligature * which the third char */ ligai = gfindadobe(metrics->gadobechars, ligs->sub); if(ligai) { if(ps_check_for_lig(psdoc, metrics, ligai, &text[1], ligdischar, &nextadobename, offset)) { *newadobename = nextadobename; return 1; } } *newadobename = ligs->sub; // printf("Found %s followed by %s replaced with %s\n", ai->adobename, nextai->adobename, ligs->sub); return 1; } ligs = ligs->next; } } return 0;}/* }}} *//* ps_build_enc_hash() {{{ * Builds the hash table of an encoding vector. * The glyhname is the the key, the position in the vector is the data. * The position of the glyph in the vector starts at 1 because 0 is reserved * by the hash table to indicate the end of the list. * If a glyphname exists more than once, only the first one will be * stored in the hash table. This would be the case for "" as glyphname, * but empty strings are not stored at all. */ght_hash_table_t *ps_build_enc_hash(PSDoc *psdoc, ENCODING *enc) { int i; ght_hash_table_t *hashvec; hashvec = ght_create(512); if(hashvec) { ght_set_alloc(hashvec, ps_ght_malloc, ps_ght_free, psdoc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -