1
/* $XConsortium: fontfcn.c,v 1.8 92/03/27 18:15:45 eswu Exp $ */
2
/* Copyright International Business Machines,Corp. 1991
5
* License to use, copy, modify, and distribute this software
6
* and its documentation for any purpose and without fee is
7
* hereby granted, provided that the above copyright notice
8
* appear in all copies and that both that copyright notice and
9
* this permission notice appear in supporting documentation,
10
* and that the name of IBM not be used in advertising or
11
* publicity pertaining to distribution of the software without
12
* specific, written prior permission.
14
* IBM PROVIDES THIS SOFTWARE "AS IS", WITHOUT ANY WARRANTIES
15
* OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT
16
* LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF
18
* THIRD PARTY RIGHTS. THE ENTIRE RISK AS TO THE QUALITY AND
19
* PERFORMANCE OF THE SOFTWARE, INCLUDING ANY DUTY TO SUPPORT
20
* OR MAINTAIN, BELONGS TO THE LICENSEE. SHOULD ANY PORTION OF
21
* THE SOFTWARE PROVE DEFECTIVE, THE LICENSEE (NOT IBM) ASSUMES
22
* THE ENTIRE COST OF ALL SERVICING, REPAIR AND CORRECTION. IN
23
* NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
25
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
26
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
27
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30
/* Author: Katherine A. Hitchcock IBM Almaden Research Laboratory */
40
#include "paths_rmz.h"
42
#include "../t1lib/parseAFM.h"
43
#include "../t1lib/t1types.h"
44
#include "../t1lib/t1extern.h"
45
#include "../t1lib/t1misc.h"
46
#include "../t1lib/t1base.h"
47
#include "../t1lib/t1finfo.h"
49
extern xobject Type1Char(psfont *env, struct XYspace *S,
50
psobj *charstrP, psobj *subrsP,
52
struct blues_struct *bluesP,
53
int *modeP, char *name);
54
extern xobject Type1Line(psfont *env, struct XYspace *S,
58
extern boolean Init_BuiltInEncoding( void);
59
void objFormatName(psobj *objP, int length, char *valueP);
61
extern void T1io_reset( void);
63
#define BEZIERTYPE 0x10+0x02
64
#define LINETYPE 0x10+0x00
65
#define MOVETYPE 0x10+0x05
68
/***================================================================***/
70
/***================================================================***/
71
static char CurCharName[257]="";
72
static char BaseCharName[257]="";
73
char CurFontName[120];
77
static char notdef[]=".notdef";
80
/* the following is inserted by RMz for VM checking and reallocating: */
82
extern int vm_init_count;
83
extern int vm_init_amount;
85
static psfont *FontP = NULL;
86
psfont TheCurrentFont;
89
/***================================================================***/
90
/* SearchDict - look for name */
91
/* - compare for match on len and string */
92
/* return 0 - not found. */
93
/* return n - nth element in dictionary. */
94
/***================================================================***/
95
int SearchDictName(dictP,keyP)
102
n = dictP[0].key.len;
103
for (i=1;i<=n;i++) { /* scan the intire dictionary */
105
(dictP[i].key.len == keyP->len )
107
(strncmp(dictP[i].key.data.valueP,
115
/***================================================================***/
116
/* assignment of &TheCurrentFont removed by RMz:
120
if (!(vm_init())) return(FALSE);
121
vm_base = vm_next_byte();
122
if (!(Init_BuiltInEncoding())) return(FALSE);
123
strcpy(CurFontName, ""); /* iniitialize to none */
124
FontP->vm_start = vm_next_byte();
125
FontP->FontFileName.len = 0;
126
FontP->FontFileName.data.valueP = CurFontName;
129
/***================================================================***/
134
vm_next = FontP->vm_start;
135
vm_free = vm_size - ( vm_next - vm_base);
136
FontP->Subrs.len = 0;
137
FontP->Subrs.data.stringP = NULL;
138
FontP->CharStringsP = NULL;
139
FontP->Private = NULL;
140
FontP->fontInfoP = NULL;
141
FontP->BluesP = NULL;
142
/* This will load the font into the FontP */
143
strcpy(CurFontName,env);
144
FontP->FontFileName.len = strlen(CurFontName);
145
FontP->FontFileName.data.nameP = CurFontName;
151
/***================================================================***/
152
/* Read font used to attempt to load the font and, upon failure,
153
try a second time with twice as much memory. Unfortunately, if
154
it's a really complex font, simply using 2*vm_size may be insufficient.
155
I've modified it so that the program will try progressively larger
156
amounts of memory until it really runs out or the font loads
163
/* int memscale = 2; */ /* initially, try twice just like we used to ... */
165
/* restore the virtual memory and eliminate old font */
168
/* This will load the font into the FontP */
170
rcode = scan_font(FontP);
175
static int isCompositeChar( int FontID,
181
if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
182
/* No AFM data present */
186
pAFMData=pFontBase->pFontArray[FontID].pAFMData;
187
for ( i=0; i<pAFMData->numOfComps; i++) {
188
if (strcmp( pAFMData->ccd[i].ccName, charname)==0)
198
/* dump a description of path elements to stdout */
199
static T1_PATHPOINT getDisplacement( struct segment *path)
202
register struct segment *ipath;
203
register struct beziersegment *ibpath;
204
T1_PATHPOINT point={0,0};
206
/* Step through the path list */
207
ipath=(struct segment *)path;
210
if (ipath->type==LINETYPE) {
211
point.x+=ipath->dest.x;
212
point.y+=ipath->dest.y;
214
else if (ipath->type==MOVETYPE) {
215
point.x+=ipath->dest.x;
216
point.y+=ipath->dest.y;
218
else if (ipath->type==BEZIERTYPE) {
219
ibpath=(struct beziersegment *)ipath;
220
point.x+=ibpath->dest.x;
221
point.y+=ibpath->dest.y;
224
} while (ipath!=NULL);
231
/***================================================================***/
232
/* RMz: instead of code, which is a character pointer to the name
233
of the character, we use "ev" which is a pointer to a desired
234
encoding vector (or NULL if font-internal encoding should be
235
used) and "index" as an index into the desired encoding vector!
236
The user thus has the opportunity of supplying whatever encoding
237
he wants. Font_Ptr is the pointer to the local psfont-structure.
240
xobject fontfcnB(int FontID, int modflag,
241
struct XYspace *S, char **ev,
242
unsigned char index, int *mode,
247
psobj *charnameP; /* points to psobj that is name of character*/
248
FontInfo *pAFMData=NULL;
253
T1_PATHPOINT currdisp;
256
psdict *CharStringsDictP; /* dictionary with char strings */
257
psobj CodeName; /* used to store the translation of the name*/
262
struct segment *charpath=NULL; /* the path for this character */
263
struct segment *tmppath1=NULL;
264
struct segment *tmppath2=NULL;
265
struct segment *tmppath3=NULL;
266
struct segment *tmppath4=NULL;
269
/* set the global font pointer to the address of already allocated
270
structure and setup pointers*/
272
CharStringsDictP = FontP->CharStringsP;
273
SubrsArrayP = &(FontP->Subrs);
274
charnameP = &CodeName;
276
if (ev==NULL){ /* font-internal encoding should be used */
277
charnameP->len = FontP->fontInfoP[ENCODING].value.data.arrayP[index].len;
278
charnameP->data.stringP = (unsigned char *) FontP->fontInfoP[ENCODING].value.data.arrayP[index].data.arrayP;
280
else{ /* some user-supplied encoding is to be used */
281
charnameP->len = strlen(ev[index]);
282
charnameP->data.stringP = (unsigned char *) ev[index];
284
strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
285
CurCharName[charnameP->len]='\0';
288
/* search the chars string for this charname as key */
289
basechar = SearchDictName(CharStringsDictP,charnameP);
291
/* Check first, whether a char in question is a composite char */
292
if ((i=isCompositeChar( FontID, CurCharName))>-1) {
293
/* i is now the index of the composite char definitions
294
(starting at 0). At this point it is clear that AFM-info
295
must be present -> fetch first component of composite char. */
296
pAFMData=pFontBase->pFontArray[FontID].pAFMData;
297
charnameP->len=strlen( pAFMData->ccd[i].pieces[0].pccName);
298
charnameP->data.stringP=(unsigned char*)pAFMData->ccd[i].pieces[0].pccName;
299
numPieces=pAFMData->ccd[i].numOfPieces;
301
if ((basechar=SearchDictName(CharStringsDictP,charnameP))<=0) {
302
/* this is bad, AFM-file and font file do not match. This
303
will most probably lead to errors or inconsistencies later.
304
However, we substitute .notdef and inform the user via
305
logfile and T1_errno. */
306
sprintf( err_warn_msg_buf,
307
"Charstring \"%s\" needed to construct composite char \"%s\" not defined (FontID=%d)",
308
pAFMData->ccd[i].pieces[0].pccName,
309
pAFMData->ccd[i].ccName, FontID);
310
T1_PrintLog( "fontfcnB():", err_warn_msg_buf, T1LOG_WARNING);
311
T1_errno=T1ERR_COMPOSITE_CHAR;
316
if (basechar<=0) { /* This means the requested char is unknown or the
317
base char of a composite is not found ->
318
we substitute .notdef */
319
charnameP = &CodeName;
321
charnameP->data.stringP = (unsigned char *) notdef;
322
basechar = SearchDictName(CharStringsDictP,charnameP);
323
localmode=FF_NOTDEF_SUBST;
324
/* Font must be completely damaged if it doesn't define a .notdef */
326
*mode=FF_PARSE_ERROR;
329
} /* if (basechar<=0) */
330
/* basechar is now the index of the base character in the CharStrings
333
/* we provide the Type1Char() procedure with the name of the character
334
to rasterize for debugging purposes */
335
strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
336
CurCharName[charnameP->len]='\0';
337
/* get CharString and character path */
338
theStringP = &(CharStringsDictP[basechar].value);
339
tmppath2 = (struct segment *) Type1Char(FontP,S,theStringP,SubrsArrayP,NULL,
340
FontP->BluesP,mode,CurCharName);
341
/* if Type1Char reported an error, then return */
342
if ( *mode == FF_PARSE_ERROR || *mode==FF_PATH_ERROR)
345
/* Defer rastering to later, we first have to handle the composite
347
for (j=1; j<numPieces; j++) {
348
/* get composite symbol name */
349
charnameP->len=strlen( pAFMData->ccd[i].pieces[j].pccName);
350
charnameP->data.stringP=(unsigned char*)pAFMData->ccd[i].pieces[j].pccName;
351
/* get CharString definition */
352
if ((N=SearchDictName(CharStringsDictP,charnameP))<=0) {
353
/* handling of errors, see comments above ... */
354
sprintf( err_warn_msg_buf,
355
"Charstring \"%s\" needed to construct composite char \"%s\" not defined (FontID=%d)",
356
pAFMData->ccd[i].pieces[j].pccName,
357
pAFMData->ccd[i].ccName, FontID);
358
T1_PrintLog( "fontfcnB():", err_warn_msg_buf, T1LOG_WARNING);
359
charnameP = &CodeName;
361
charnameP->data.stringP = (unsigned char *) notdef;
362
N = SearchDictName(CharStringsDictP,charnameP);
363
localmode=FF_NOTDEF_SUBST;
366
*mode=FF_PARSE_ERROR;
367
if (charpath!=NULL) {
373
theStringP = &(CharStringsDictP[N].value);
374
tmppath1=(struct segment *)ILoc(S,
375
pAFMData->ccd[i].pieces[j].deltax,
376
pAFMData->ccd[i].pieces[j].deltay);
378
strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
379
CurCharName[charnameP->len]='\0';
380
charpath=(struct segment *)Type1Char(FontP,S,theStringP,SubrsArrayP,NULL,
381
FontP->BluesP,mode,CurCharName);
382
/* return if Type1Char reports an error */
383
if ( *mode == FF_PARSE_ERROR || *mode==FF_PATH_ERROR)
385
/* get escapement of current symbol */
386
currdisp=getDisplacement( charpath);
387
/* concat displacement and symbol path */
388
charpath=(struct segment *)Join(tmppath1,charpath);
389
/* for composite symbols we have to step back the char escapement.
390
this is, in order to be able to use accents that cause a
391
non zero displacement of the current point! We further have to
392
step back the displacement from composite char data. */
393
tmppath1=(struct segment *)t1_PathSegment( MOVETYPE, -currdisp.x, -currdisp.y);
394
tmppath3=(struct segment *)ILoc(S,
395
-pAFMData->ccd[i].pieces[j].deltax,
396
-pAFMData->ccd[i].pieces[j].deltay);
397
tmppath3=(struct segment *)Join(tmppath1,tmppath3);
398
/* create path, or, respectively, append to existing path */
399
if (tmppath4==NULL) {
400
tmppath4=(struct segment *)Join(charpath,tmppath3);
403
charpath=(struct segment *)Join(charpath,tmppath3);
404
tmppath4=(struct segment *)Join(tmppath4,charpath);
408
/* concat composite symbols and base char */
409
if (tmppath4==NULL) { /* no previous composite symbols */
410
charpath=tmppath2; /* a simple char */
413
charpath=(struct segment *)Join(tmppath4,tmppath2);
418
/* fill with winding rule unless path was requested */
419
if (*mode != FF_PATH) {
420
charpath = (struct segment *)Interior(charpath,WINDINGRULE+CONTINUITY);
427
return((xobject) charpath);
433
/***================================================================***/
434
/* fontfcnA(env, mode) */
436
/* env is a pointer to a string that contains the fontname. */
438
/* 1) initialize the font - global indicates it has been done */
439
/* 2) load the font */
441
/* This function has been modified by RMz. It now takes a pointer which
442
already contains the address of a valid type1 font structure as the
443
third argument. The value of this pointer is first handed to FontP
444
so that most other routines may be used without changes */
448
/***================================================================***/
449
Bool fontfcnA(env,mode,Font_Ptr)
457
/* set the global font pointer to the address of already allocated
463
/* Read the font program. */
464
for (i=1; i<MAXTRIAL; i++){
466
/* We allocate larger chunks (4*65536 Bytes) in order to reduce load
467
time for large fonts by initially requesting somewhat more
469
vm_init_amount=MAX_STRING_LEN * 4 * i;
471
/* we are really out of memory, not simulated! */
472
*mode = SCAN_OUT_OF_MEMORY;
475
/* Try to read font into memory */
476
if ((result=readFont(env))==0){
477
/* In order to get the amount of memory that was really used */
478
vm_used=vm_next_byte();
482
/* VM did not suffice, free it and try again with larger
487
/* Font could not be loaded: */
494
/***================================================================***/
495
/* QueryFontLib(env, infoName,infoValue,rcodeP) */
497
/* env is a pointer to a string that contains the fontname. */
499
/* 1) initialize the font - global indicates it has been done */
500
/* 2) load the font */
501
/* 3) use the font to call getInfo for that value. */
502
/***================================================================***/
504
void QueryFontLib(env,infoName,infoValue,rcodeP)
507
pointer infoValue; /* parameter returned here */
516
/* Has the FontP initialized? If not, then */
525
/* if the env is null, then use font already loaded */
526
/* if the not same font name, reset and load next font */
527
if ( (env) && (strcmp(env,CurFontName) != 0 ) ) {
528
/* restore the virtual memory and eliminate old font */
531
strcpy(CurFontName, ""); /* no font loaded */
536
dictP = FontP->fontInfoP;
537
objFormatName(&nameObj,strlen(infoName),infoName);
538
N = SearchDictName(dictP,&nameObj);
542
switch (dictP[N].value.type) {
544
valueP = dictP[N].value.data.arrayP;
545
if (strcmp(infoName,"FontMatrix") == 0) {
546
/* 6 elments, return them as floats */
548
if (valueP->type == OBJ_INTEGER )
549
((float *)infoValue)[i] = valueP->data.integer;
551
((float *)infoValue)[i] = valueP->data.real;
555
if (strcmp(infoName,"FontBBox") == 0) {
556
/* 4 elments for Bounding Box. all integers */
558
((int *)infoValue)[i] = valueP->data.integer;
564
*((int *)infoValue) = dictP[N].value.data.integer;
567
*((float *)infoValue) = dictP[N].value.data.real;
571
*((char **)infoValue) = dictP[N].value.data.valueP;
583
/***================================================================***/
584
/* RMz: instead of code, which is a character pointer to the name
585
of the character, we use "ev" which is a pointer to a desired
586
encoding vector (or NULL if font-internal encoding should be
587
used) and "index" as an index into the desired encoding vector!
588
The user thus has the opportunity of supplying whatever encoding
589
he wants. Font_Ptr is the pointer to the local psfont-structure.
591
xobject fontfcnB_string( int FontID, int modflag,
592
struct XYspace *S, char **ev,
593
unsigned char *string, int no_chars,
594
int *mode, psfont *Font_Ptr,
595
int *kern_pairs, long spacewidth,
599
psobj *charnameP; /* points to psobj that is name of character*/
600
FontInfo *pAFMData=NULL;
607
T1_PATHPOINT currdisp;
610
psdict *CharStringsDictP; /* dictionary with char strings */
611
psobj CodeName; /* used to store the translation of the name*/
616
struct segment *charpath=NULL; /* the path for this character */
617
struct segment *tmppath1=NULL;
618
struct segment *tmppath2=NULL;
619
struct segment *tmppath3=NULL;
620
struct segment *tmppath4=NULL;
621
struct segment *tmppath5=NULL;
624
/* set the global font pointer to the address of already allocated
625
structure and setup pointers*/
627
CharStringsDictP = FontP->CharStringsP;
628
SubrsArrayP = &(FontP->Subrs);
629
charnameP = &CodeName;
632
/* In the following for-loop, all characters are processed, one after
633
the other. Between them, the amount of kerning is inserted.
634
The number of path variables used is somewhat numerous. We use the
635
follwing conventions:
637
charpath: the overall path of the string.
638
tmppath5: the overall path of one component (possibly a composite symbol)
639
tmppath2: the path of a simple char or base char of a composite
640
tmppath4: the path of all "accents" of a composite symbol
642
for (k=0; k<no_chars;k++) {
643
if (ev==NULL){ /* font-internal encoding should be used */
644
charnameP = &CodeName;
645
charnameP->len = FontP->fontInfoP[ENCODING].value.data.arrayP[string[k]].len;
646
charnameP->data.stringP = (unsigned char *) FontP->fontInfoP[ENCODING].value.data.arrayP[string[k]].data.arrayP;
648
else { /* some user-supplied encoding is to be used */
649
charnameP = &CodeName;
650
charnameP->len = strlen(ev[string[k]]);
651
charnameP->data.stringP = (unsigned char*) ev[string[k]];
654
/* Spacing is to be under users control: => if space is the charname, don't
655
raster it. Rather, generate a horizontal movement of spacewidth: */
656
if (strcmp((char *)charnameP->data.stringP, "space")==0){
657
tmppath5=(struct segment *)ILoc(S, spacewidth,0);
658
acc_width += spacewidth;
661
/* here a character or composite character is to be constructed */
662
strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
663
CurCharName[charnameP->len]='\0';
665
/* search the CharString for this charname as key */
666
basechar = SearchDictName(CharStringsDictP,charnameP);
668
/* Check first, whether a char in question is a composite char */
669
if ((i=isCompositeChar( FontID, CurCharName))>-1) {
670
/* i is now the index of the composite char definitions
671
(starting at 0). At this point it is clear that AFM-info
672
must be present -> fetch first component of composite char. */
673
pAFMData=pFontBase->pFontArray[FontID].pAFMData;
674
charnameP->len=strlen( pAFMData->ccd[i].pieces[0].pccName);
675
charnameP->data.stringP=(unsigned char*)pAFMData->ccd[i].pieces[0].pccName;
676
numPieces=pAFMData->ccd[i].numOfPieces;
678
if ((basechar=SearchDictName(CharStringsDictP,charnameP))<=0) {
679
/* this is bad, AFM-file and font file do not match. This
680
will most probably lead to errors or inconsistencies later.
681
However, we substitute .notdef and inform the user via
682
logfile and T1_errno. */
683
sprintf( err_warn_msg_buf,
684
"Charstring \"%s\" needed to construct composite char \"%s\" not defined (FontID=%d)",
685
pAFMData->ccd[i].pieces[0].pccName,
686
pAFMData->ccd[i].ccName, FontID);
687
T1_PrintLog( "fontfcnB():", err_warn_msg_buf, T1LOG_WARNING);
688
T1_errno=T1ERR_COMPOSITE_CHAR;
693
if (basechar<=0) { /* This means the requested char is unknown or the
694
base char of a composite is not found ->
695
we substitute .notdef */
696
charnameP = &CodeName;
698
charnameP->data.stringP = (unsigned char *) notdef;
699
basechar = SearchDictName(CharStringsDictP,charnameP);
700
localmode=FF_NOTDEF_SUBST;
701
/* Font must be completely damaged if it doesn't define a .notdef */
703
*mode=FF_PARSE_ERROR;
706
} /* if (basechar<=0) */
707
/* basechar is now the index of the base character in the CharStrings
710
/* we provide the Type1Char() procedure with the name of the character
711
to rasterize for debugging purposes */
712
strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
713
CurCharName[charnameP->len]='\0';
714
/* get CharString and character path */
715
theStringP = &(CharStringsDictP[basechar].value);
716
tmppath2 = (struct segment *) Type1Char(FontP,S,theStringP,SubrsArrayP,NULL,
717
FontP->BluesP,mode,CurCharName);
718
strcpy( BaseCharName, CurCharName);
719
/* if Type1Char reports an error, clean up and return */
720
if ( *mode == FF_PARSE_ERROR || *mode==FF_PATH_ERROR) {
721
if (charpath!=NULL) {
724
if (tmppath1!=NULL) {
727
if (tmppath2!=NULL) {
730
if (tmppath3!=NULL) {
733
if (tmppath4!=NULL) {
736
if (tmppath5!=NULL) {
742
/* Defer rastering to later, we first have to handle the composite
744
for (j=1; j<numPieces; j++) {
745
/* get composite symbol name */
746
charnameP->len=strlen( pAFMData->ccd[i].pieces[j].pccName);
747
charnameP->data.stringP=(unsigned char*)pAFMData->ccd[i].pieces[j].pccName;
748
/* get CharString definition */
749
if ((N=SearchDictName(CharStringsDictP,charnameP))<=0) {
750
/* handling of errors, see comments above ... */
751
sprintf( err_warn_msg_buf,
752
"Charstring \"%s\" needed to construct composite char \"%s\" not defined (FontID=%d)",
753
pAFMData->ccd[i].pieces[j].pccName,
754
pAFMData->ccd[i].ccName, FontID);
755
T1_PrintLog( "fontfcnB():", err_warn_msg_buf, T1LOG_WARNING);
756
charnameP = &CodeName;
758
charnameP->data.stringP = (unsigned char *) notdef;
759
N = SearchDictName(CharStringsDictP,charnameP);
760
localmode=FF_NOTDEF_SUBST;
761
/* an undefined .notdef is fatal -> clean up and return */
763
*mode=FF_PARSE_ERROR;
764
if (charpath!=NULL) {
767
if (tmppath1!=NULL) {
770
if (tmppath2!=NULL) {
773
if (tmppath3!=NULL) {
776
if (tmppath4!=NULL) {
779
if (tmppath5!=NULL) {
785
theStringP = &(CharStringsDictP[N].value);
786
tmppath1=(struct segment *)ILoc(S,
787
pAFMData->ccd[i].pieces[j].deltax,
788
pAFMData->ccd[i].pieces[j].deltay);
790
strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
791
CurCharName[charnameP->len]='\0';
792
tmppath5=(struct segment *)Type1Char(FontP,S,theStringP,SubrsArrayP,NULL,
793
FontP->BluesP,mode,CurCharName);
794
/* return if Type1Char reports an error */
795
if ( *mode == FF_PARSE_ERROR || *mode==FF_PATH_ERROR)
797
/* get escapement of current symbol */
798
currdisp=getDisplacement( tmppath5);
799
/* concat displacement and symbol path */
800
tmppath5=(struct segment *)Join(tmppath1,tmppath5);
801
/* for composite symbols we have to step back the char escapement.
802
this is, in order to be able to use accents that cause a
803
non zero displacement of the current point! We further have to
804
step back the displacement from composite char data. */
805
tmppath1=(struct segment *)t1_PathSegment( MOVETYPE, -currdisp.x, -currdisp.y);
806
tmppath3=(struct segment *)ILoc(S,
807
-pAFMData->ccd[i].pieces[j].deltax,
808
-pAFMData->ccd[i].pieces[j].deltay);
809
tmppath3=(struct segment *)Join(tmppath1,tmppath3);
810
/* create path, or, respectively, append to existing path */
811
if (tmppath4==NULL) {
812
tmppath4=(struct segment *)Join(tmppath5,tmppath3);
815
tmppath5=(struct segment *)Join(tmppath5,tmppath3);
816
tmppath4=(struct segment *)Join(tmppath4,tmppath5);
820
/* concat composite symbols and base char. We use tmppath5 to store
821
the path of the resulting (possibly composite) character. */
822
if (tmppath4==NULL) { /* no previous composite symbols */
823
tmppath5=tmppath2; /* a simple char */
826
tmppath5=(struct segment *)Join(tmppath4,tmppath2);
830
/* Accumulate displacement, but be careful: In case of composite
831
characters, we have to take the escapement of the base char only
832
into account, because accents do not cause spacing. The path is
833
constructed in a way that this automatically matches.
835
if (numPieces>1) { /* composite character */
836
acc_width +=pFontBase->pFontArray[FontID].pAFMData->ccd[-(pFontBase->pFontArray[FontID].pEncMap[string[k]]+1)].wx;
838
else { /* ordinary character */
839
acc_width +=pFontBase->pFontArray[FontID].pAFMData->cmi[pFontBase->pFontArray[FontID].pEncMap[string[k]]-1].wx;
842
} /* else (if (char==space) */
844
/* character path is now stored in tmppath5. It may be a composite character.
845
Insert kerning amount, if it is not the last character of the string. */
847
tmppath2=(struct segment *)ILoc(S,kern_pairs[k],0);
848
tmppath5=(struct segment *)Join(tmppath5,tmppath2);
849
acc_width += kern_pairs[k];
852
charpath=(struct segment *)Join(charpath,tmppath5);
855
charpath=(struct segment *)tmppath5;
857
/* reset the temporary paths so that constructing composite
858
characters wiil continue to work properly in the next interation. */
864
/* reset composition parameters */
868
} /* for (k<no_chars) */
871
/* Take care for underlining and such */
872
if (modflag & T1_UNDERLINE){
873
tmppath2=(struct segment *)Type1Line(FontP,S,
874
pFontBase->pFontArray[FontID].UndrLnPos,
875
pFontBase->pFontArray[FontID].UndrLnThick,
877
charpath=(struct segment *)Join(charpath,tmppath2);
879
if (modflag & T1_OVERLINE){
880
tmppath2=(struct segment *)Type1Line(FontP,S,
881
pFontBase->pFontArray[FontID].OvrLnPos,
882
pFontBase->pFontArray[FontID].OvrLnThick,
884
charpath=(struct segment *)Join(charpath,tmppath2);
886
if (modflag & T1_OVERSTRIKE){
887
tmppath2=(struct segment *)Type1Line(FontP,S,
888
pFontBase->pFontArray[FontID].OvrStrkPos,
889
pFontBase->pFontArray[FontID].OvrStrkThick,
891
charpath=(struct segment *)Join(charpath,tmppath2);
895
printf("charpath->type: %x\n",charpath->type);
896
printf("path1->type: %x\n",path1->type);
897
printf("path2->type: %x\n",path2->type);
900
/* if Type1Char reported an error, then return */
902
if ( *mode == FF_PARSE_ERROR) return(NULL);
903
if ( *mode == FF_PATH_ERROR) return(NULL);
905
/* fill with winding rule unless path was requested */
906
if (*mode != FF_PATH) {
907
charpath = (struct segment *) Interior((path) charpath,WINDINGRULE+CONTINUITY);
914
return((path)charpath);
918
/* This special variant is for generating character bitmaps from
920
xobject fontfcnB_ByName( int FontID, int modflag,
922
unsigned char *charname,
923
int *mode, psfont *Font_Ptr,
927
psobj *charnameP; /* points to psobj that is name of character*/
928
FontInfo *pAFMData=NULL;
933
T1_PATHPOINT currdisp;
936
psdict *CharStringsDictP; /* dictionary with char strings */
937
psobj CodeName; /* used to store the translation of the name*/
942
struct segment *charpath=NULL; /* the path for this character */
943
struct segment *tmppath1=NULL;
944
struct segment *tmppath2=NULL;
945
struct segment *tmppath3=NULL;
946
struct segment *tmppath4=NULL;
949
/* set the global font pointer to the address of already allocated
950
structure and setup pointers*/
952
CharStringsDictP = FontP->CharStringsP;
953
SubrsArrayP = &(FontP->Subrs);
954
charnameP = &CodeName;
956
charnameP->len = strlen((char*)charname);
957
charnameP->data.stringP = charname;
959
strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
960
CurCharName[charnameP->len]='\0';
963
/* search the chars string for this charname as key */
964
basechar = SearchDictName(CharStringsDictP,charnameP);
966
/* Check first, whether a char in question is a composite char */
967
if ((i=isCompositeChar( FontID, CurCharName))>-1) {
968
/* i is now the index of the composite char definitions
969
(starting at 0). At this point it is clear that AFM-info
970
must be present -> fetch first component of composite char. */
971
pAFMData=pFontBase->pFontArray[FontID].pAFMData;
972
charnameP->len=strlen( pAFMData->ccd[i].pieces[0].pccName);
973
charnameP->data.stringP=(unsigned char*)pAFMData->ccd[i].pieces[0].pccName;
974
numPieces=pAFMData->ccd[i].numOfPieces;
976
if ((basechar=SearchDictName(CharStringsDictP,charnameP))<=0) {
977
/* this is bad, AFM-file and font file do not match. This
978
will most probably lead to errors or inconsistencies later.
979
However, we substitute .notdef and inform the user via
980
logfile and T1_errno. */
981
sprintf( err_warn_msg_buf,
982
"Charstring \"%s\" needed to construct composite char \"%s\" not defined (FontID=%d)",
983
pAFMData->ccd[i].pieces[0].pccName,
984
pAFMData->ccd[i].ccName, FontID);
985
T1_PrintLog( "fontfcnB():", err_warn_msg_buf, T1LOG_WARNING);
986
T1_errno=T1ERR_COMPOSITE_CHAR;
991
if (basechar<=0) { /* This means the requested char is unknown or the
992
base char of a composite is not found ->
993
we substitute .notdef */
994
charnameP = &CodeName;
996
charnameP->data.stringP = (unsigned char *) notdef;
997
basechar = SearchDictName(CharStringsDictP,charnameP);
998
localmode=FF_NOTDEF_SUBST;
999
/* Font must be completely damaged if it doesn't define a .notdef */
1001
*mode=FF_PARSE_ERROR;
1004
} /* if (basechar<=0) */
1005
/* basechar is now the index of the base character in the CharStrings
1008
/* we provide the Type1Char() procedure with the name of the character
1009
to rasterize for debugging purposes */
1010
strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
1011
CurCharName[charnameP->len]='\0';
1012
/* get CharString and character path */
1013
theStringP = &(CharStringsDictP[basechar].value);
1014
tmppath2 = (struct segment *) Type1Char(FontP,S,theStringP,SubrsArrayP,NULL,
1015
FontP->BluesP,mode,CurCharName);
1016
/* if Type1Char reported an error, then return */
1017
if ( *mode == FF_PARSE_ERROR || *mode==FF_PATH_ERROR)
1020
/* Defer rastering to later, we first have to handle the composite
1022
for (j=1; j<numPieces; j++) {
1023
/* get composite symbol name */
1024
charnameP->len=strlen( pAFMData->ccd[i].pieces[j].pccName);
1025
charnameP->data.stringP=(unsigned char*)pAFMData->ccd[i].pieces[j].pccName;
1026
/* get CharString definition */
1027
if ((N=SearchDictName(CharStringsDictP,charnameP))<=0) {
1028
/* handling of errors, see comments above ... */
1029
sprintf( err_warn_msg_buf,
1030
"Charstring \"%s\" needed to construct composite char \"%s\" not defined (FontID=%d)",
1031
pAFMData->ccd[i].pieces[j].pccName,
1032
pAFMData->ccd[i].ccName, FontID);
1033
T1_PrintLog( "fontfcnB():", err_warn_msg_buf, T1LOG_WARNING);
1034
charnameP = &CodeName;
1036
charnameP->data.stringP = (unsigned char *) notdef;
1037
N = SearchDictName(CharStringsDictP,charnameP);
1038
localmode=FF_NOTDEF_SUBST;
1041
*mode=FF_PARSE_ERROR;
1042
if (charpath!=NULL) {
1043
KillPath( charpath);
1048
theStringP = &(CharStringsDictP[N].value);
1049
tmppath1=(struct segment *)ILoc(S,
1050
pAFMData->ccd[i].pieces[j].deltax,
1051
pAFMData->ccd[i].pieces[j].deltay);
1053
strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
1054
CurCharName[charnameP->len]='\0';
1055
charpath=(struct segment *)Type1Char(FontP,S,theStringP,SubrsArrayP,NULL,
1056
FontP->BluesP,mode,CurCharName);
1057
/* return if Type1Char reports an error */
1058
if ( *mode == FF_PARSE_ERROR || *mode==FF_PATH_ERROR)
1060
/* get escapement of current symbol */
1061
currdisp=getDisplacement( charpath);
1062
/* concat displacement and symbol path */
1063
charpath=(struct segment *)Join(tmppath1,charpath);
1064
/* for composite symbols we have to step back the char escapement.
1065
this is, in order to be able to use accents that cause a
1066
non zero displacement of the current point! We further have to
1067
step back the displacement from composite char data. */
1068
tmppath1=(struct segment *)t1_PathSegment( MOVETYPE, -currdisp.x, -currdisp.y);
1069
tmppath3=(struct segment *)ILoc(S,
1070
-pAFMData->ccd[i].pieces[j].deltax,
1071
-pAFMData->ccd[i].pieces[j].deltay);
1072
tmppath3=(struct segment *)Join(tmppath1,tmppath3);
1073
/* create path, or, respectively, append to existing path */
1074
if (tmppath4==NULL) {
1075
tmppath4=(struct segment *)Join(charpath,tmppath3);
1078
charpath=(struct segment *)Join(charpath,tmppath3);
1079
tmppath4=(struct segment *)Join(tmppath4,charpath);
1083
/* concat composite symbols and base char */
1084
if (tmppath4==NULL) { /* no previous composite symbols */
1085
charpath=tmppath2; /* a simple char */
1088
charpath=(struct segment *)Join(tmppath4,tmppath2);
1093
/* fill with winding rule unless path was requested */
1094
if (*mode != FF_PATH) {
1095
charpath = (struct segment *)Interior(charpath,WINDINGRULE+CONTINUITY);
1102
return((xobject) charpath);