~ubuntu-branches/ubuntu/karmic/grace/karmic

« back to all changes in this revision

Viewing changes to T1lib/type1/fontfcn.c

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2002-03-19 14:19:58 UTC
  • Revision ID: james.westby@ubuntu.com-20020319141958-5gxna6vo1ek3zjml
Tags: upstream-5.1.7
ImportĀ upstreamĀ versionĀ 5.1.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $XConsortium: fontfcn.c,v 1.8 92/03/27 18:15:45 eswu Exp $ */
 
2
/* Copyright International Business Machines,Corp. 1991
 
3
 * All Rights Reserved
 
4
 *
 
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.
 
13
 *
 
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
 
28
 * SOFTWARE.
 
29
 */
 
30
/* Author: Katherine A. Hitchcock    IBM Almaden Research Laboratory */
 
31
 
 
32
#include <stdio.h>
 
33
#include <string.h>
 
34
#include <stdlib.h>
 
35
 
 
36
#include "t1imager.h" 
 
37
#include "util.h"
 
38
#include "fontfcn.h"
 
39
#include "fontmisc.h"
 
40
#include "paths_rmz.h" 
 
41
 
 
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"
 
48
 
 
49
extern xobject Type1Char(psfont *env, struct XYspace *S,
 
50
                         psobj *charstrP, psobj *subrsP,
 
51
                         psobj *osubrsP,
 
52
                         struct blues_struct *bluesP,
 
53
                         int *modeP, char *name);
 
54
extern xobject Type1Line(psfont *env, struct XYspace *S,
 
55
                                 float line_position,
 
56
                                 float line_thickness,
 
57
                                 float line_length);
 
58
extern  boolean Init_BuiltInEncoding( void);
 
59
void objFormatName(psobj *objP, int length, char *valueP);
 
60
  
 
61
extern void T1io_reset( void);
 
62
 
 
63
#define BEZIERTYPE 0x10+0x02
 
64
#define LINETYPE   0x10+0x00
 
65
#define MOVETYPE   0x10+0x05
 
66
 
 
67
 
 
68
/***================================================================***/
 
69
/*   GLOBALS                                                          */
 
70
/***================================================================***/
 
71
static char CurCharName[257]="";
 
72
static char BaseCharName[257]="";
 
73
char CurFontName[120];
 
74
char *CurFontEnv;
 
75
char *vm_base = NULL;
 
76
 
 
77
static char notdef[]=".notdef";
 
78
 
 
79
 
 
80
/* the following is inserted by RMz for VM checking and reallocating: */
 
81
char *vm_used = NULL;
 
82
extern int vm_init_count;
 
83
extern int vm_init_amount;
 
84
 
 
85
static psfont *FontP = NULL;
 
86
psfont TheCurrentFont;
 
87
 
 
88
 
 
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)
 
96
 psdict *dictP;
 
97
 psobj  *keyP;
 
98
{
 
99
  int i,n;
 
100
 
 
101
 
 
102
  n =  dictP[0].key.len;
 
103
  for (i=1;i<=n;i++) {          /* scan the intire dictionary */
 
104
    if (
 
105
        (dictP[i].key.len  == keyP->len )
 
106
        &&
 
107
        (strncmp(dictP[i].key.data.valueP,
 
108
                 keyP->data.valueP,
 
109
                 keyP->len) == 0
 
110
        )
 
111
       ) return(i);
 
112
  }
 
113
  return(0);
 
114
}
 
115
/***================================================================***/
 
116
/* assignment of &TheCurrentFont removed by RMz:
 
117
 */
 
118
boolean initFont()
 
119
{
 
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;
 
127
  return(TRUE);
 
128
}
 
129
/***================================================================***/
 
130
int resetFont(env)
 
131
char *env;
 
132
{
 
133
 
 
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;
 
146
  T1io_reset();
 
147
 
 
148
  return(0);
 
149
  
 
150
}
 
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
 
157
   successfully. (ndw)
 
158
*/
 
159
int readFont(env)
 
160
char *env;
 
161
{
 
162
  int rcode;
 
163
  /* int memscale = 2; */ /* initially, try twice just like we used to ... */
 
164
 
 
165
  /* restore the virtual memory and eliminate old font */
 
166
  
 
167
  resetFont(env);
 
168
  /* This will load the font into the FontP */
 
169
 
 
170
  rcode = scan_font(FontP);
 
171
  return(rcode);
 
172
}
 
173
 
 
174
 
 
175
static int isCompositeChar( int FontID,
 
176
                            char *charname) 
 
177
{
 
178
  int i;
 
179
  FontInfo *pAFMData;
 
180
  
 
181
  if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
 
182
    /* No AFM data present */
 
183
    return( -1);
 
184
  }
 
185
 
 
186
  pAFMData=pFontBase->pFontArray[FontID].pAFMData;
 
187
  for ( i=0; i<pAFMData->numOfComps; i++) {
 
188
    if (strcmp( pAFMData->ccd[i].ccName, charname)==0)
 
189
      return( i);
 
190
  }
 
191
  
 
192
  return( -1);
 
193
  
 
194
}
 
195
 
 
196
 
 
197
 
 
198
/* dump a description of path elements to stdout */
 
199
static T1_PATHPOINT getDisplacement( struct segment *path)
 
200
{
 
201
 
 
202
  register struct segment *ipath;
 
203
  register struct beziersegment *ibpath;
 
204
  T1_PATHPOINT point={0,0};
 
205
  
 
206
  /* Step through the path list */
 
207
  ipath=(struct segment *)path;
 
208
  
 
209
  do {
 
210
    if (ipath->type==LINETYPE) {
 
211
      point.x+=ipath->dest.x;
 
212
      point.y+=ipath->dest.y;
 
213
    }
 
214
    else if (ipath->type==MOVETYPE) {
 
215
      point.x+=ipath->dest.x;
 
216
      point.y+=ipath->dest.y;
 
217
    }
 
218
    else if (ipath->type==BEZIERTYPE) {
 
219
      ibpath=(struct beziersegment *)ipath;
 
220
      point.x+=ibpath->dest.x;
 
221
      point.y+=ibpath->dest.y;
 
222
    }
 
223
    ipath=ipath->link;
 
224
  } while (ipath!=NULL);
 
225
  return( point);
 
226
  
 
227
}
 
228
 
 
229
 
 
230
 
 
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. 
 
238
        */
 
239
 
 
240
xobject fontfcnB(int FontID, int modflag,
 
241
                 struct XYspace *S, char **ev,
 
242
                 unsigned char index, int *mode,
 
243
                 psfont *Font_Ptr,
 
244
                 int do_raster)
 
245
{
 
246
 
 
247
  psobj *charnameP; /* points to psobj that is name of character*/
 
248
  FontInfo *pAFMData=NULL;
 
249
  int i=-1;
 
250
  int j=0;
 
251
  int numPieces=1;
 
252
  int N;
 
253
  T1_PATHPOINT currdisp;
 
254
  int basechar;
 
255
  
 
256
  psdict *CharStringsDictP; /* dictionary with char strings     */
 
257
  psobj   CodeName;   /* used to store the translation of the name*/
 
258
  psobj  *SubrsArrayP;
 
259
  psobj  *theStringP;
 
260
  int localmode=0;
 
261
  
 
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;
 
267
  
 
268
   
 
269
  /* set the global font pointer to the address of already allocated
 
270
     structure and setup pointers*/
 
271
  FontP=Font_Ptr;
 
272
  CharStringsDictP =  FontP->CharStringsP;
 
273
  SubrsArrayP = &(FontP->Subrs);
 
274
  charnameP = &CodeName;
 
275
 
 
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;
 
279
  }
 
280
  else{           /* some user-supplied encoding is to be used */
 
281
    charnameP->len = strlen(ev[index]);
 
282
    charnameP->data.stringP = (unsigned char *) ev[index];
 
283
  }
 
284
  strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
 
285
  CurCharName[charnameP->len]='\0';
 
286
  
 
287
 
 
288
  /* search the chars string for this charname as key */
 
289
  basechar = SearchDictName(CharStringsDictP,charnameP);
 
290
  if (basechar<=0) {
 
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;
 
300
      
 
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;
 
312
      }
 
313
    }
 
314
  }
 
315
  
 
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;
 
320
    charnameP->len = 7;
 
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 */
 
325
    if (basechar<=0) {
 
326
      *mode=FF_PARSE_ERROR;
 
327
      return(NULL);
 
328
    }
 
329
  } /* if (basechar<=0) */
 
330
  /* basechar is now the index of the base character in the CharStrings
 
331
     dictionary */
 
332
 
 
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)
 
343
    return(NULL);
 
344
  
 
345
  /* Defer rastering to later, we first have to handle the composite
 
346
     symbols */
 
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;
 
360
      charnameP->len = 7;
 
361
      charnameP->data.stringP = (unsigned char *) notdef;
 
362
      N = SearchDictName(CharStringsDictP,charnameP);
 
363
      localmode=FF_NOTDEF_SUBST;
 
364
      /* damaged Font */
 
365
      if (N<=0) {
 
366
        *mode=FF_PARSE_ERROR;
 
367
        if (charpath!=NULL) {
 
368
          KillPath( charpath);
 
369
        }
 
370
        return(NULL);
 
371
      }
 
372
    }
 
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);
 
377
    
 
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)
 
384
      return(NULL);
 
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);
 
401
    }
 
402
    else {
 
403
      charpath=(struct segment *)Join(charpath,tmppath3);
 
404
      tmppath4=(struct segment *)Join(tmppath4,charpath);
 
405
    }
 
406
  }
 
407
 
 
408
  /* concat composite symbols and base char */
 
409
  if (tmppath4==NULL) { /* no previous composite symbols */
 
410
    charpath=tmppath2; /* a simple char */
 
411
  }
 
412
  else { 
 
413
    charpath=(struct segment *)Join(tmppath4,tmppath2);
 
414
  }
 
415
  
 
416
  
 
417
  if (do_raster) { 
 
418
    /* fill with winding rule unless path was requested */
 
419
    if (*mode != FF_PATH) {
 
420
      charpath =  (struct segment *)Interior(charpath,WINDINGRULE+CONTINUITY);
 
421
    }
 
422
  }
 
423
 
 
424
  if (*mode==0)
 
425
    *mode=localmode;
 
426
  
 
427
  return((xobject) charpath);
 
428
}
 
429
 
 
430
 
 
431
 
 
432
 
 
433
/***================================================================***/
 
434
/*   fontfcnA(env, mode)                                              */
 
435
/*                                                                    */
 
436
/*          env is a pointer to a string that contains the fontname.  */
 
437
/*                                                                    */
 
438
/*     1) initialize the font     - global indicates it has been done */
 
439
/*     2) load the font                                               */
 
440
/*                                                                    */
 
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 */
 
445
 
 
446
#define MAXTRIAL              4
 
447
 
 
448
/***================================================================***/
 
449
Bool fontfcnA(env,mode,Font_Ptr)
 
450
char *env;
 
451
int  *mode;
 
452
psfont *Font_Ptr;
 
453
 
 
454
{
 
455
  int i, result;
 
456
  
 
457
  /* set the global font pointer to the address of already allocated
 
458
     structure */
 
459
  FontP=Font_Ptr;
 
460
 
 
461
  InitImager();
 
462
 
 
463
  /* Read the font program. */
 
464
  for (i=1; i<MAXTRIAL; i++){
 
465
    vm_init_count=0;
 
466
    /* We allocate larger chunks (4*65536 Bytes) in order to reduce load
 
467
       time for large fonts by initially requesting somewhat more
 
468
       memory. */
 
469
    vm_init_amount=MAX_STRING_LEN * 4 * i;
 
470
    if (!(initFont())) {
 
471
      /* we are really out of memory, not simulated! */
 
472
      *mode = SCAN_OUT_OF_MEMORY;
 
473
      return(FALSE);
 
474
    }
 
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();
 
479
      return(TRUE);
 
480
    }
 
481
    else{
 
482
      /* VM did not suffice, free it and try again with larger
 
483
         value: */
 
484
      free(vm_base);
 
485
    }
 
486
  }
 
487
  /* Font could not be loaded: */
 
488
  *mode = result;
 
489
  return(FALSE);
 
490
 
 
491
}
 
492
 
 
493
 
 
494
/***================================================================***/
 
495
/*   QueryFontLib(env, infoName,infoValue,rcodeP)                     */
 
496
/*                                                                    */
 
497
/*          env is a pointer to a string that contains the fontname.  */
 
498
/*                                                                    */
 
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
/***================================================================***/
 
503
 
 
504
void QueryFontLib(env,infoName,infoValue,rcodeP)
 
505
char *env;
 
506
char *infoName;
 
507
pointer infoValue;    /* parameter returned here    */
 
508
int  *rcodeP;
 
509
{
 
510
 
 
511
  int rc,N,i;
 
512
  psdict *dictP;
 
513
  psobj  nameObj;
 
514
  psobj  *valueP;
 
515
 
 
516
  /* Has the FontP initialized?  If not, then   */
 
517
  /* Initialize  */
 
518
  if (FontP == NULL) {
 
519
    InitImager();
 
520
    if (!(initFont())) {
 
521
      *rcodeP = 1;
 
522
      return;
 
523
    }
 
524
  }
 
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 */
 
529
    rc = readFont(env);
 
530
    if (rc != 0 ) {
 
531
      strcpy(CurFontName, "");    /* no font loaded */
 
532
      *rcodeP = 1;
 
533
      return;
 
534
    }
 
535
  }
 
536
  dictP = FontP->fontInfoP;
 
537
  objFormatName(&nameObj,strlen(infoName),infoName);
 
538
  N = SearchDictName(dictP,&nameObj);
 
539
  /* if found */
 
540
  if ( N > 0 ) {
 
541
    *rcodeP = 0;
 
542
    switch (dictP[N].value.type) {
 
543
       case OBJ_ARRAY:
 
544
         valueP = dictP[N].value.data.arrayP;
 
545
         if (strcmp(infoName,"FontMatrix") == 0) {
 
546
           /* 6 elments, return them as floats      */
 
547
           for (i=0;i<6;i++) {
 
548
             if (valueP->type == OBJ_INTEGER )
 
549
               ((float *)infoValue)[i] = valueP->data.integer;
 
550
             else
 
551
               ((float *)infoValue)[i] = valueP->data.real;
 
552
            valueP++;
 
553
           }
 
554
         }
 
555
         if (strcmp(infoName,"FontBBox") == 0) {
 
556
           /* 4 elments for Bounding Box.  all integers   */
 
557
           for (i=0;i<4;i++) {
 
558
             ((int *)infoValue)[i] = valueP->data.integer;
 
559
             valueP++;
 
560
           }
 
561
         break;
 
562
       case OBJ_INTEGER:
 
563
       case OBJ_BOOLEAN:
 
564
         *((int *)infoValue) = dictP[N].value.data.integer;
 
565
         break;
 
566
       case OBJ_REAL:
 
567
         *((float *)infoValue) = dictP[N].value.data.real;
 
568
         break;
 
569
       case OBJ_NAME:
 
570
       case OBJ_STRING:
 
571
         *((char **)infoValue) =  dictP[N].value.data.valueP;
 
572
         break;
 
573
       default:
 
574
         *rcodeP = 1;
 
575
         break;
 
576
     }
 
577
   }
 
578
  }
 
579
  else *rcodeP = 1;
 
580
}
 
581
 
 
582
 
 
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. 
 
590
        */
 
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,
 
596
                         int do_raster)
 
597
{
 
598
 
 
599
  psobj *charnameP; /* points to psobj that is name of character*/
 
600
  FontInfo *pAFMData=NULL;
 
601
  int i=-1;
 
602
  int j=0;
 
603
  int k=0;
 
604
  long acc_width=0;
 
605
  int numPieces=1;
 
606
  int N;
 
607
  T1_PATHPOINT currdisp;
 
608
  int basechar;
 
609
  
 
610
  psdict *CharStringsDictP; /* dictionary with char strings     */
 
611
  psobj   CodeName;   /* used to store the translation of the name*/
 
612
  psobj  *SubrsArrayP;
 
613
  psobj  *theStringP;
 
614
  int localmode=0;
 
615
  
 
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;
 
622
  
 
623
   
 
624
  /* set the global font pointer to the address of already allocated
 
625
     structure and setup pointers*/
 
626
  FontP=Font_Ptr;
 
627
  CharStringsDictP =  FontP->CharStringsP;
 
628
  SubrsArrayP = &(FontP->Subrs);
 
629
  charnameP = &CodeName;
 
630
 
 
631
  
 
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:
 
636
 
 
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
 
641
  */
 
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;
 
647
    }
 
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]];
 
652
    }
 
653
    
 
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;
 
659
    }
 
660
    else {
 
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';
 
664
      
 
665
      /* search the CharString for this charname as key */
 
666
      basechar = SearchDictName(CharStringsDictP,charnameP);
 
667
      if (basechar<=0) {
 
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;
 
677
          
 
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;
 
689
          }
 
690
        }
 
691
      }
 
692
      
 
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;
 
697
        charnameP->len = 7;
 
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 */
 
702
        if (basechar<=0) {
 
703
          *mode=FF_PARSE_ERROR;
 
704
          return(NULL);
 
705
        }
 
706
      } /* if (basechar<=0) */
 
707
      /* basechar is now the index of the base character in the CharStrings
 
708
         dictionary */
 
709
      
 
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) {
 
722
          KillPath( charpath);
 
723
        }
 
724
        if (tmppath1!=NULL) {
 
725
          KillPath( tmppath1);
 
726
        }
 
727
        if (tmppath2!=NULL) {
 
728
          KillPath( tmppath2);
 
729
        }
 
730
        if (tmppath3!=NULL) {
 
731
          KillPath( tmppath3);
 
732
        }
 
733
        if (tmppath4!=NULL) {
 
734
          KillPath( tmppath4);
 
735
        }
 
736
        if (tmppath5!=NULL) {
 
737
          KillPath( tmppath5);
 
738
        }
 
739
        return(NULL);
 
740
      }
 
741
        
 
742
      /* Defer rastering to later, we first have to handle the composite
 
743
         symbols */
 
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;
 
757
          charnameP->len = 7;
 
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 */
 
762
          if (N<=0) {
 
763
            *mode=FF_PARSE_ERROR;
 
764
            if (charpath!=NULL) {
 
765
              KillPath( charpath);
 
766
            }
 
767
            if (tmppath1!=NULL) {
 
768
              KillPath( tmppath1);
 
769
            }
 
770
            if (tmppath2!=NULL) {
 
771
              KillPath( tmppath2);
 
772
            }
 
773
            if (tmppath3!=NULL) {
 
774
              KillPath( tmppath3);
 
775
            }
 
776
            if (tmppath4!=NULL) {
 
777
              KillPath( tmppath4);
 
778
            }
 
779
            if (tmppath5!=NULL) {
 
780
              KillPath( tmppath5);
 
781
            }
 
782
            return(NULL);
 
783
          }
 
784
        }
 
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);
 
789
    
 
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)
 
796
          return(NULL);
 
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);
 
813
        }
 
814
        else {
 
815
          tmppath5=(struct segment *)Join(tmppath5,tmppath3);
 
816
          tmppath4=(struct segment *)Join(tmppath4,tmppath5);
 
817
        }
 
818
      }
 
819
      
 
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 */
 
824
      }
 
825
      else { 
 
826
        tmppath5=(struct segment *)Join(tmppath4,tmppath2);
 
827
      }
 
828
      
 
829
 
 
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.
 
834
      */
 
835
      if (numPieces>1) { /* composite character */
 
836
        acc_width +=pFontBase->pFontArray[FontID].pAFMData->ccd[-(pFontBase->pFontArray[FontID].pEncMap[string[k]]+1)].wx;
 
837
      }
 
838
      else { /* ordinary character */
 
839
        acc_width +=pFontBase->pFontArray[FontID].pAFMData->cmi[pFontBase->pFontArray[FontID].pEncMap[string[k]]-1].wx;
 
840
      }
 
841
      
 
842
    } /* else (if (char==space) */
 
843
 
 
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. */
 
846
    if (k<no_chars-1){
 
847
      tmppath2=(struct segment *)ILoc(S,kern_pairs[k],0); 
 
848
      tmppath5=(struct segment *)Join(tmppath5,tmppath2);
 
849
      acc_width += kern_pairs[k];
 
850
    }
 
851
    if (charpath!=NULL){
 
852
      charpath=(struct segment *)Join(charpath,tmppath5);
 
853
    }
 
854
    else{
 
855
      charpath=(struct segment *)tmppath5;
 
856
    }
 
857
    /* reset the temporary paths so that constructing composite
 
858
       characters wiil continue to work properly in the next interation. */
 
859
    tmppath1=NULL;
 
860
    tmppath2=NULL;
 
861
    tmppath3=NULL;
 
862
    tmppath4=NULL;
 
863
    tmppath5=NULL;
 
864
    /* reset composition parameters */
 
865
    i=-1;
 
866
    numPieces=1;
 
867
    
 
868
  } /* for (k<no_chars) */
 
869
  
 
870
  
 
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,
 
876
                                         (float) acc_width);
 
877
    charpath=(struct segment *)Join(charpath,tmppath2);
 
878
  }
 
879
  if (modflag & T1_OVERLINE){
 
880
    tmppath2=(struct segment *)Type1Line(FontP,S,
 
881
                                         pFontBase->pFontArray[FontID].OvrLnPos,
 
882
                                         pFontBase->pFontArray[FontID].OvrLnThick,
 
883
                                         (float) acc_width);
 
884
    charpath=(struct segment *)Join(charpath,tmppath2);
 
885
  }
 
886
  if (modflag & T1_OVERSTRIKE){
 
887
    tmppath2=(struct segment *)Type1Line(FontP,S,
 
888
                                         pFontBase->pFontArray[FontID].OvrStrkPos,
 
889
                                         pFontBase->pFontArray[FontID].OvrStrkThick,
 
890
                                         (float) acc_width);
 
891
    charpath=(struct segment *)Join(charpath,tmppath2);
 
892
  }
 
893
  
 
894
  /*
 
895
  printf("charpath->type: %x\n",charpath->type);
 
896
  printf("path1->type: %x\n",path1->type);
 
897
  printf("path2->type: %x\n",path2->type);
 
898
  */
 
899
 
 
900
  /* if Type1Char reported an error, then return */
 
901
 
 
902
  if ( *mode == FF_PARSE_ERROR)  return(NULL);
 
903
  if ( *mode == FF_PATH_ERROR)  return(NULL);
 
904
  if (do_raster) { 
 
905
    /* fill with winding rule unless path was requested */
 
906
    if (*mode != FF_PATH) {
 
907
      charpath = (struct segment *) Interior((path) charpath,WINDINGRULE+CONTINUITY);
 
908
    }
 
909
  }
 
910
  
 
911
  if (*mode==0)
 
912
    *mode=localmode;
 
913
 
 
914
  return((path)charpath);
 
915
}
 
916
 
 
917
 
 
918
/* This special variant is for generating character bitmaps from
 
919
   charactername */
 
920
xobject fontfcnB_ByName( int FontID, int modflag,
 
921
                         struct XYspace *S,
 
922
                         unsigned char *charname,
 
923
                         int *mode, psfont *Font_Ptr,
 
924
                         int do_raster)
 
925
{
 
926
 
 
927
  psobj *charnameP; /* points to psobj that is name of character*/
 
928
  FontInfo *pAFMData=NULL;
 
929
  int i=-1;
 
930
  int j=0;
 
931
  int numPieces=1;
 
932
  int N;
 
933
  T1_PATHPOINT currdisp;
 
934
  int basechar;
 
935
  
 
936
  psdict *CharStringsDictP; /* dictionary with char strings     */
 
937
  psobj   CodeName;   /* used to store the translation of the name*/
 
938
  psobj  *SubrsArrayP;
 
939
  psobj  *theStringP;
 
940
  int localmode=0;
 
941
  
 
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;
 
947
  
 
948
   
 
949
  /* set the global font pointer to the address of already allocated
 
950
     structure and setup pointers*/
 
951
  FontP=Font_Ptr;
 
952
  CharStringsDictP =  FontP->CharStringsP;
 
953
  SubrsArrayP = &(FontP->Subrs);
 
954
  charnameP = &CodeName;
 
955
 
 
956
  charnameP->len = strlen((char*)charname);
 
957
  charnameP->data.stringP = charname;
 
958
 
 
959
  strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
 
960
  CurCharName[charnameP->len]='\0';
 
961
  
 
962
 
 
963
  /* search the chars string for this charname as key */
 
964
  basechar = SearchDictName(CharStringsDictP,charnameP);
 
965
  if (basechar<=0) {
 
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;
 
975
      
 
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;
 
987
      }
 
988
    }
 
989
  }
 
990
  
 
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;
 
995
    charnameP->len = 7;
 
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 */
 
1000
    if (basechar<=0) {
 
1001
      *mode=FF_PARSE_ERROR;
 
1002
      return(NULL);
 
1003
    }
 
1004
  } /* if (basechar<=0) */
 
1005
  /* basechar is now the index of the base character in the CharStrings
 
1006
     dictionary */
 
1007
 
 
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)
 
1018
    return(NULL);
 
1019
  
 
1020
  /* Defer rastering to later, we first have to handle the composite
 
1021
     symbols */
 
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;
 
1035
      charnameP->len = 7;
 
1036
      charnameP->data.stringP = (unsigned char *) notdef;
 
1037
      N = SearchDictName(CharStringsDictP,charnameP);
 
1038
      localmode=FF_NOTDEF_SUBST;
 
1039
      /* damaged Font */
 
1040
      if (N<=0) {
 
1041
        *mode=FF_PARSE_ERROR;
 
1042
        if (charpath!=NULL) {
 
1043
          KillPath( charpath);
 
1044
        }
 
1045
        return(NULL);
 
1046
      }
 
1047
    }
 
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);
 
1052
    
 
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)
 
1059
      return(NULL);
 
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);
 
1076
    }
 
1077
    else {
 
1078
      charpath=(struct segment *)Join(charpath,tmppath3);
 
1079
      tmppath4=(struct segment *)Join(tmppath4,charpath);
 
1080
    }
 
1081
  }
 
1082
 
 
1083
  /* concat composite symbols and base char */
 
1084
  if (tmppath4==NULL) { /* no previous composite symbols */
 
1085
    charpath=tmppath2; /* a simple char */
 
1086
  }
 
1087
  else { 
 
1088
    charpath=(struct segment *)Join(tmppath4,tmppath2);
 
1089
  }
 
1090
  
 
1091
  
 
1092
  if (do_raster) { 
 
1093
    /* fill with winding rule unless path was requested */
 
1094
    if (*mode != FF_PATH) {
 
1095
      charpath =  (struct segment *)Interior(charpath,WINDINGRULE+CONTINUITY);
 
1096
    }
 
1097
  }
 
1098
 
 
1099
  if (*mode==0)
 
1100
    *mode=localmode;
 
1101
  
 
1102
  return((xobject) charpath);
 
1103
 
 
1104
}
 
1105