⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ps_util.c

📁 PSlib是一个用来生成PostScript文件的类库。提供了一个生成PostScript文件的简单方法。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *    (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 + -