1 /*--------------------------------------------------------------------------
2   ----- File:        t1set.c
3   ----- Author:      Rainer Menzner (Rainer.Menzner@web.de)
4   ----- Date:        2001-05-27
5   ----- Description: This file is part of the t1-library. It contains
6                      functions for setting characters and strings of
7 		     characters.
8   ----- Copyright:   t1lib is copyrighted (c) Rainer Menzner, 1996-2001.
9                      As of version 0.5, t1lib is distributed under the
10 		     GNU General Public Library Lincense. The
11 		     conditions can be found in the files LICENSE and
12 		     LGPL, which should reside in the toplevel
13 		     directory of the distribution.  Please note that
14 		     there are parts of t1lib that are subject to
15 		     other licenses:
16 		     The parseAFM-package is copyrighted by Adobe Systems
17 		     Inc.
18 		     The type1 rasterizer is copyrighted by IBM and the
19 		     X11-consortium.
20   ----- Warranties:  Of course, there's NO WARRANTY OF ANY KIND :-)
21   ----- Credits:     I want to thank IBM and the X11-consortium for making
22                      their rasterizer freely available.
23 		     Also thanks to Piet Tutelaers for his ps2pk, from
24 		     which I took the rasterizer sources in a format
25 		     independent from X11.
26                      Thanks to all people who make free software living!
27 --------------------------------------------------------------------------*/
28 
29 #define T1SET_C
30 
31 
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #if defined(_MSC_VER)
37 # include <io.h>
38 # include <sys/types.h>
39 # include <sys/stat.h>
40 #else
41 # include <unistd.h>
42 #endif
43 #include <stdlib.h>
44 #include <math.h>
45 #include <string.h>
46 #include <setjmp.h>
47 
48 #include "../type1/ffilest.h"
49 #include "../type1/types.h"
50 #include "parseAFM.h"
51 #include "../type1/objects.h"
52 #include "../type1/spaces.h"
53 #include "../type1/util.h"
54 #include "../type1/fontfcn.h"
55 #include "../type1/regions.h"
56 
57 
58 #include "t1types.h"
59 #include "t1extern.h"
60 #include "t1set.h"
61 #include "t1load.h"
62 #include "t1finfo.h"
63 #include "t1misc.h"
64 #include "t1base.h"
65 
66 
67 /* As a fall back */
68 #ifndef T1_AA_TYPE16
69 #define T1_AA_TYPE16    short
70 #endif
71 #ifndef T1_AA_TYPE32
72 #define T1_AA_TYPE32    int
73 #endif
74 
75 
76 extern char *t1_get_abort_message( int number);
77 extern struct region *Interior(struct segment *path, int fillrule);
78 extern unsigned T1_AA_TYPE32 T1aa_bg;          /* white value */
79 
80 
81 
82 static int T1_bit=T1GLYPH_BIT;
83 static int T1_byte;
84 static int T1_pad;
85 static int T1_wordsize;
86 
87 static int c_shift=8;
88 static int s_shift=16;
89 static int l_shift=32;
90 
91 
92 
93 /* T1_SetChar(...): Generate the bitmap for a character */
T1_SetChar(int FontID,char charcode,float size,T1_TMATRIX * transform)94 GLYPH *T1_SetChar( int FontID, char charcode, float size,
95 		   T1_TMATRIX *transform)
96 {
97   int i;
98   int mode;
99   struct region *area;
100   struct XYspace *Current_S;
101   int cache_flag=1;
102   int rot_flag=0;
103   unsigned char ucharcode;
104 
105 
106   FONTSIZEDEPS *font_ptr;
107   FONTPRIVATE  *fontarrayP;
108 
109   volatile int memsize=0;
110   LONG h,w;
111   LONG paddedW;
112 
113   /* We don't implement underlining for characters, but the rasterer
114      implements it. Thus, we use a modflag of constant 0 */
115   int modflag=0;
116 
117   static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1};
118 
119 
120   /* We return to this if something goes wrong deep in the rasterizer */
121   if ((i=setjmp( stck_state))!=0) {
122     T1_errno=T1ERR_TYPE1_ABORT;
123     sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
124 	     t1_get_abort_message( i));
125     T1_PrintLog( "T1_SetChar()", err_warn_msg_buf,
126 	       T1LOG_ERROR);
127     return( NULL);
128   }
129 
130   ucharcode=(unsigned char)charcode;
131 
132 
133   /* Reset character glyph, if necessary */
134   if (glyph.bits!=NULL){
135     free(glyph.bits);
136     glyph.bits=NULL;
137   }
138   glyph.metrics.leftSideBearing=0;
139   glyph.metrics.rightSideBearing=0;
140   glyph.metrics.advanceX=0;
141   glyph.metrics.advanceY=0;
142   glyph.metrics.ascent=0;
143   glyph.metrics.descent=0;
144   glyph.pFontCacheInfo=NULL;
145   glyph.bpp=1;
146 
147   /* First, check for a correct ID */
148   i=CheckForFontID(FontID);
149   if (i==-1){
150     T1_errno=T1ERR_INVALID_FONTID;
151     return(NULL);
152   }
153   /* if necessary load font into memory */
154   if (i==0)
155     if (T1_LoadFont(FontID))
156       return(NULL);
157 
158   /* Check for valid size */
159   if (size<=0.0){
160     T1_errno=T1ERR_INVALID_PARAMETER;
161     return(NULL);
162   }
163 
164   /* Assign padding value */
165   T1_pad=pFontBase->bitmap_pad;
166   if (pFontBase->endian)
167     T1_byte=1;
168   else
169     T1_byte=0;
170   T1_wordsize=T1_pad;
171 
172   fontarrayP=&(pFontBase->pFontArray[FontID]);
173 
174   /* Check if rotation is requested */
175   if (transform!=NULL){
176     /* there's rotation requested => do not cache the resulting bitmap */
177     rot_flag=1;
178     cache_flag=0;
179   }
180   else {
181     rot_flag=0;
182     cache_flag=1;
183   }
184   /* font is now loaded into memory =>
185      Check for size: */
186   if ((font_ptr=QueryFontSize( FontID, size, NO_ANTIALIAS))==NULL){
187     font_ptr=CreateNewFontSize( FontID, size, NO_ANTIALIAS);
188     if (font_ptr==NULL){
189       T1_errno=T1ERR_ALLOC_MEM;
190       return(NULL);
191     }
192   }
193   else {/* size is already existent in cache */
194     /* If no rotation, try to get character from cache */
195     if (rot_flag==0){
196       /* we don't use the .bits entry to check because in newer releases
197 	 also white glyphs (bits=NULL) are allowed. Rather, we check
198 	 whether bpp > 0! */
199       if (font_ptr->pFontCache[ucharcode].bpp > 0){
200 	/* Character is already in Chache -> create a copy of cache
201 	   and return a pointer to the result: */
202 	memcpy( &glyph, &(font_ptr->pFontCache[ucharcode]), sizeof(GLYPH));
203 	paddedW = PAD((glyph.metrics.rightSideBearing-glyph.metrics.leftSideBearing),
204 		      T1_pad);
205 	if (font_ptr->pFontCache[ucharcode].bits!=NULL) {
206 	  memsize = (glyph.metrics.ascent-glyph.metrics.descent)*paddedW / 8;
207 	  glyph.bits = (char *)malloc(memsize*sizeof( char));
208 	  if (glyph.bits == NULL){
209 	    T1_errno=T1ERR_ALLOC_MEM;
210 	    return(NULL);
211 	  }
212 	  memcpy( glyph.bits, font_ptr->pFontCache[ucharcode].bits, memsize);
213 	}
214 	return(&(glyph));
215       }
216     }
217   }
218   /* Setup an appropriate charspace matrix. Note that the rasterizer
219      assumes vertical values with inverted sign! Transformation should
220      create a copy of the local charspace matrix which then still has
221      to be made permanent. */
222   if (rot_flag){
223     Current_S=(struct XYspace *)
224       Permanent(Scale(Transform (font_ptr->pCharSpaceLocal,
225 				 transform->cxx, - transform->cxy,
226 				 transform->cyx, - transform->cyy),
227 		      DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
228   }
229   else{
230     Current_S=(struct XYspace *)
231       Permanent(Scale(Transform(font_ptr->pCharSpaceLocal,
232 				1.0, 0.0, 0.0, -1.0),
233 		      DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
234   }
235 
236   /* fnt_ptr now points to the correct FontSizeDeps-struct =>
237      lets now raster the character */
238   mode=0;
239   area=fontfcnB( FontID, modflag, Current_S,
240 		 fontarrayP->pFontEnc,
241 		 ucharcode, &mode,
242 		 fontarrayP->pType1Data,
243 		 DO_RASTER);
244   KillSpace (Current_S);
245 
246   /* fill the glyph-structure */
247   if (mode > 0) {
248     sprintf( err_warn_msg_buf, "fontfcnB() set mode=%d", mode);
249     T1_PrintLog( "T1_SetChar()", err_warn_msg_buf, T1LOG_WARNING);
250     T1_errno=mode;
251     return(NULL);
252   }
253   if (area == NULL){
254     T1_PrintLog( "T1_SetChar()", "area=NULL returned by fontfcnB()", T1LOG_WARNING);
255     T1_errno=mode;
256     return(NULL);
257   }
258   h = area->ymax - area->ymin;
259   w = area->xmax - area->xmin;
260 
261   if (mode == FF_NOTDEF_SUBST) {
262     sprintf( err_warn_msg_buf,
263 	     "\".notdef\" substituted for character %d from font %d",
264 	     ucharcode, FontID);
265     T1_PrintLog( "T1_SetChar()", err_warn_msg_buf, T1LOG_WARNING);
266     mode=0;
267   }
268 
269   paddedW = PAD(w, T1_pad);
270 
271   if (h > 0 && w > 0) {
272     memsize = h * paddedW / 8 + 1;
273     /* This is for the users copy of the character, for security-reasons
274        the original pointer to the cache area is not used. The entry glyph.bits
275        is free'ed every time this function is called: */
276     glyph.bits = (char *)malloc(memsize*sizeof( char));
277     if (glyph.bits == NULL){
278       T1_errno=T1ERR_ALLOC_MEM;
279       /* make sure to get rid of 'area' before leaving! */
280       KillRegion (area);
281       return(NULL);
282     }
283   }
284   else {
285     h = w = 0;
286     area->xmin = area->xmax = 0;
287     area->ymin = area->ymax = 0;
288   }
289 
290   /* Assign metrics */
291   glyph.metrics.leftSideBearing  = area->xmin;
292   glyph.metrics.advanceX   = NEARESTPEL(area->ending.x - area->origin.x);
293   glyph.metrics.advanceY   = - NEARESTPEL(area->ending.y - area->origin.y);
294   glyph.metrics.rightSideBearing = area->xmax;
295   glyph.metrics.descent          = - area->ymax;
296   glyph.metrics.ascent           = - area->ymin;
297 
298 
299   if (h > 0 && w > 0) {
300     (void) memset(glyph.bits, 0, memsize);
301     fill(glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize );
302   }
303 
304   /* make sure to get rid of 'area' before leaving! */
305   KillRegion (area);
306 
307   /* Cache glyph if requested, also if it contains only white space */
308   if (cache_flag){
309     /* Copy glyph to cache but be careful not to modify the pixmap
310        entry */
311     font_ptr->pFontCache[ucharcode].metrics.leftSideBearing=glyph.metrics.leftSideBearing;
312     font_ptr->pFontCache[ucharcode].metrics.rightSideBearing=glyph.metrics.rightSideBearing;
313     font_ptr->pFontCache[ucharcode].metrics.advanceX=glyph.metrics.advanceX;
314     font_ptr->pFontCache[ucharcode].metrics.advanceY=glyph.metrics.advanceY;
315     font_ptr->pFontCache[ucharcode].metrics.ascent=glyph.metrics.ascent;
316     font_ptr->pFontCache[ucharcode].metrics.descent=glyph.metrics.descent;
317     font_ptr->pFontCache[ucharcode].pFontCacheInfo=glyph.pFontCacheInfo;
318     font_ptr->pFontCache[ucharcode].bpp=glyph.bpp;
319     if (glyph.bits==NULL) {
320       font_ptr->pFontCache[ucharcode].bits=NULL;
321     }
322     else {
323       font_ptr->pFontCache[ucharcode].bits = (char *)malloc(memsize*sizeof( char));
324       if (font_ptr->pFontCache[ucharcode].bits == NULL){
325 	T1_errno=T1ERR_ALLOC_MEM;
326 	return(NULL);
327       }
328       /* ... and copy bitmap to cache area: */
329       memcpy( font_ptr->pFontCache[ucharcode].bits, glyph.bits, memsize);
330     }
331 
332   }
333 
334 
335   return(&glyph);
336 }
337 
338 
339 
340 /* T1_SetString(...): Generate the bitmap for a string of characters */
T1_SetString(int FontID,char * string,volatile int len,long spaceoff,int modflag,float size,T1_TMATRIX * transform)341 GLYPH *T1_SetString( int FontID, char *string, volatile int len,
342 		     long spaceoff, int modflag, float size,
343 		     T1_TMATRIX *transform)
344 {
345   volatile int i, j=0, k;
346   int mode;
347   /* initialize this to NULL just to be on the safe side */
348   struct region *area = NULL;
349   struct XYspace *Current_S, *S;
350   int cache_flag=1;
351   volatile int rot_flag=0;
352   int *kern_pairs;       /* use for accessing the kern pairs if kerning is
353 			    requested */
354   int no_chars=0;        /* The number of characters in the string */
355   static int lastno_chars=0;
356   float factor;
357   long spacewidth;       /* This is given to fontfcnb_string() */
358 
359 
360   FONTSIZEDEPS *font_ptr;
361   FONTPRIVATE  *fontarrayP;
362 
363 
364   volatile int memsize=0;
365 
366   long h,w;
367   long paddedW, char_paddedW;
368   int h_anchor, v_anchor;
369   static int *pixel_h_anchor_corr=NULL;
370   static int *flags=NULL;
371   int lsb_min, rsb_max;
372   long overallwidth=0;
373   long overallascent=0;
374   long overalldescent=0;
375 
376   int underline_startx, underline_starty, underline_endx, underline_endy;
377   int overline_startx, overline_starty, overline_endx, overline_endy;
378   int overstrike_startx, overstrike_starty, overstrike_endx, overstrike_endy;
379   int start, middle;
380   int afm_ind;
381 
382   char startmask, endmask;
383   static unsigned char *r2lstring;
384   static int r2l_len=0;
385 
386   static GLYPH string_glyph={NULL,{0,0,0,0,0,0},NULL,1};
387   GLYPH *currchar;
388 
389 
390 
391   /* The following are for bitmap blitting */
392   long BitShift;
393   long ByteOffset;
394   /* pad=8 */
395   unsigned T1_AA_TYPE16 BitBuf_c;
396   unsigned char *p_c;
397   unsigned char *Target_c;
398   /* pad=16 */
399   unsigned T1_AA_TYPE32 BitBuf_s;
400   unsigned T1_AA_TYPE16 *p_s;
401   unsigned T1_AA_TYPE16 *Target_s;
402 #ifdef T1_AA_TYPE64
403   /* pad=32 */
404   unsigned T1_AA_TYPE64 BitBuf_l;
405   unsigned T1_AA_TYPE32 *p_l;
406   unsigned T1_AA_TYPE32 *Target_l;
407 #endif
408   unsigned char *ustring;
409 
410 
411   /* We return to this if something goes wrong deep in the rasterizer */
412   if ((i=setjmp( stck_state))!=0) {
413     T1_errno=T1ERR_TYPE1_ABORT;
414     sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
415 	     t1_get_abort_message( i));
416     T1_PrintLog( "T1_SetString()", err_warn_msg_buf,
417 	       T1LOG_ERROR);
418     return( NULL);
419   }
420 
421   /* force string elements into unsigned */
422   ustring=(unsigned char*)string;
423 
424 
425   /* Check for valid string */
426   if (string==NULL){
427     T1_errno=T1ERR_INVALID_PARAMETER;
428     return(NULL);
429   }
430 
431   /* Reorganize if required */
432   if (modflag & T1_RIGHT_TO_LEFT){
433     if (len)
434       i=len;
435     else
436       i=j=strlen( string);
437     if (i+1>r2l_len){
438       if (r2lstring!=NULL)
439 	free( r2lstring);
440       r2lstring=(unsigned char *)malloc( (i+1)*sizeof(char));
441       r2l_len=i+1;
442     }
443     j--;
444     while ( i--) {
445       r2lstring[j-i]=ustring[i];
446     }
447     ustring=r2lstring;
448     len=j+1;
449   }
450 
451 
452   /* Reset string glyph, if necessary */
453   if (string_glyph.bits!=NULL){
454     free(string_glyph.bits);
455     string_glyph.bits=NULL;
456   }
457   string_glyph.metrics.leftSideBearing=0;
458   string_glyph.metrics.rightSideBearing=0;
459   string_glyph.metrics.advanceX=0;
460   string_glyph.metrics.advanceY=0;
461   string_glyph.metrics.ascent=0;
462   string_glyph.metrics.descent=0;
463   string_glyph.pFontCacheInfo=NULL;
464   string_glyph.bpp=1;
465 
466   /* We don't want to cache the resulting bitmap: */
467   cache_flag=0;
468 
469   /* First, check for a correct ID */
470   i=CheckForFontID(FontID);
471   if (i==-1){
472     T1_errno=T1ERR_INVALID_FONTID;
473     return(NULL);
474   }
475 
476   /* if necessary load font into memory */
477   if (i==0)
478     if (T1_LoadFont(FontID))
479       return(NULL);
480 
481   /* If no AFM info is present, we return an error */
482   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
483     T1_errno=T1ERR_NO_AFM_DATA;
484     return(NULL);
485   }
486 
487   /* Check for valid size */
488   if (size<=0.0){
489     T1_errno=T1ERR_INVALID_PARAMETER;
490     return(NULL);
491   }
492 
493   /* Assign padding value */
494   T1_pad=pFontBase->bitmap_pad;
495   if (pFontBase->endian)
496     T1_byte=1;
497   else
498     T1_byte=0;
499   T1_wordsize=T1_pad;
500 
501   fontarrayP=&(pFontBase->pFontArray[FontID]);
502 
503   /* Check if rotation is requested */
504   if (transform!=NULL){
505     /* there's rotation requested => do not cache the resulting bitmap */
506     rot_flag=1;
507     cache_flag=0;
508   }
509 
510   /* font is now loaded into memory =>
511      Check for size: */
512   if ((font_ptr=QueryFontSize( FontID, size, NO_ANTIALIAS))==NULL){
513     font_ptr=CreateNewFontSize( FontID, size, NO_ANTIALIAS);
514     if (font_ptr==NULL){
515       T1_errno=T1ERR_ALLOC_MEM;
516       return(NULL);
517     }
518   }
519 
520   /* Now comes string specific stuff: Get length of string and create an
521      array of integers where to store the bitmap positioning dimens: */
522   if (len<0){  /* invalid length */
523     T1_errno=T1ERR_INVALID_PARAMETER;
524     return(NULL);
525   }
526 
527   if (len==0) /* should be computed assuming "normal" 0-terminated string,
528 		 or R2L-part has already been computed! */
529     no_chars=strlen(string);
530   else        /* use value given on command line */
531     no_chars=len;
532 
533   /* If necessary, allocate memory */
534   if (no_chars>lastno_chars){
535     if (pixel_h_anchor_corr!=NULL){
536       free(pixel_h_anchor_corr);
537     }
538     if (flags!=NULL){
539       free(flags);
540     }
541     pixel_h_anchor_corr=(int *)calloc(no_chars, sizeof(int));
542     flags=(int *)calloc(no_chars, sizeof(int));
543     lastno_chars=no_chars;
544   }
545   else{
546     /* Reset flags  and position array */
547     for (i=0; i<no_chars; i++){
548       flags[i]=0;
549       pixel_h_anchor_corr[i]=0;
550     }
551   }
552 
553   /* Setup an appropriate charspace matrix. Note that the rasterizer
554      assumes vertical values with inverted sign! Transformation should
555      create a copy of the local charspace matrix which then still has
556      to be made permanent. */
557   if (rot_flag){
558     Current_S=(struct XYspace *)
559       Permanent(Scale(Transform (font_ptr->pCharSpaceLocal,
560 				 transform->cxx, - transform->cxy,
561 				 transform->cyx, - transform->cyy),
562 		      DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
563   }
564   else{
565     Current_S=(struct XYspace *)
566       Permanent(Scale(Transform(font_ptr->pCharSpaceLocal,
567 				1.0, 0.0, 0.0, -1.0),
568 		      DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
569   }
570 
571   /* Compute the correct spacewidth value (in charspace units). The
572      value supplied by the user is interpreted as an offset in
573      char space units:
574      */
575   spacewidth=T1_GetCharWidth(FontID,fontarrayP->space_position)+spaceoff;
576 
577 
578   /* The following if (rot_flag==0){ ... } contains the whole code
579      to execute when the string is oriented horizontal. Then, there's
580      the possibility of concatenating most probably existent bitmaps
581      from the Cache, which should be much faster than every time raster
582      all the characters.
583      */
584   /* First, ensure that all needed characters are in the Cache; if not,
585      generate them */
586   if ((rot_flag==0)){
587     overallwidth=0;
588     for (i=0; i<no_chars; i++) {
589       currchar= &(font_ptr->pFontCache[ustring[i]]);
590       if (currchar->bpp<1) {
591 	flags[i]=0;
592 	mode=0;
593 	/*  Don't try to generate space-character: */
594 	if (ustring[i]!=fontarrayP->space_position){
595 	  /* Note: Never underline etc. cached chars --> modflag=0 */
596 	  area=fontfcnB( FontID, 0, Current_S,
597 			 fontarrayP->pFontEnc,
598 			 ustring[i], &mode,
599 			 fontarrayP->pType1Data,
600 			 DO_RASTER);
601 
602 	  /* fill the glyph-structure */
603 	  if (mode > 0) {
604 	    sprintf( err_warn_msg_buf, "fontfcnB() set mode=%d", mode);
605 	    T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING);
606 	    T1_errno=mode;
607 	    /* Make sure to free the region if it's non-NULL */
608 	    if (area){
609 	      KillRegion (area);
610 	    }
611 	    return(NULL);
612 	  }
613 	  if (area == NULL){
614 	    T1_PrintLog( "T1_SetString()", "area=NULL returned by fontfcnB()", T1LOG_WARNING);
615 	    T1_errno=mode;
616 	    return(NULL);
617 	  }
618 
619 	  if (mode == FF_NOTDEF_SUBST) {
620 	    sprintf( err_warn_msg_buf,
621 		     "\".notdef\" substituted in string[%d] (=character %d) from font %d",
622 		     i, ustring[i], FontID);
623 	    T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING);
624 	    mode=0;
625 	    flags[i]=1; /* indicates that .notdef has been substituted */
626 	  }
627 
628 	  h = area->ymax - area->ymin;
629 	  w = area->xmax - area->xmin;
630 
631 	  if (h > 0 && w > 0) {  /* bitmap contains pixels */
632 	    paddedW = PAD(w, T1_pad);
633 	    memsize = h * paddedW / 8 + 1;
634 	    currchar->bits = (char *)malloc(memsize*sizeof( char));
635 	    if (currchar->bits == NULL) {
636 	      T1_errno=T1ERR_ALLOC_MEM;
637 	      /* Make sure to free up the region if it's non-NULL */
638 	      if (area){
639 		KillRegion (area);
640 	      }
641 	      return(NULL);
642 	    }
643 	    (void) memset(currchar->bits, 0, memsize);
644 	    fill(currchar->bits, h, paddedW, area,
645 		 T1_byte, T1_bit, T1_wordsize );
646 	  }
647 	  /* area valid -> set metrics in cache for that character */
648 	  currchar->metrics.leftSideBearing  = area->xmin;
649 	  currchar->metrics.advanceX   = NEARESTPEL(area->ending.x - area->origin.x);
650 	  currchar->metrics.advanceY   = - NEARESTPEL(area->ending.y - area->origin.y);
651 	  currchar->metrics.rightSideBearing = area->xmax;
652 	  currchar->metrics.descent          = - area->ymax;
653 	  currchar->metrics.ascent           = - area->ymin;
654 	  currchar->bpp=1;
655 
656 	  /* By this point, it's clear that the 'area' struct exists,
657 	     and that we no longer need it, so free it up. */
658 	  KillRegion (area);
659 	}
660       } /* end of if ( ... ), needed characters are now in cache! */
661     } /* end of for (i<no_chars) loop */
662     /* we still have to delete the Space */
663     KillSpace (Current_S);
664 
665     /* We've to compute the scale factor: */
666     factor=size*DeviceSpecifics.scale_x/1000;
667 
668     /* h_anchor is the horizontal position in the resulting bitmap;
669        it is incremented on the fly and of course initially 0! */
670     h_anchor=0;
671     /* These are the initial values for left and right sidebearing */
672     rsb_max=-30000;
673     lsb_min= 30000;
674     overallascent=-30000;
675     overalldescent=30000;
676     for (i=0;i<no_chars;i++){
677       /* first get index into AFM-tables */
678       afm_ind=pFontBase->pFontArray[FontID].pEncMap[(int) ustring[i]];
679       /* Advance to next character in high resolution */
680       if (ustring[i]==fontarrayP->space_position)
681 	h_anchor +=(int)spacewidth;
682       /* check for a substituted char or notdef and get missing escapement */
683       else if (afm_ind==0) {
684 	/* Setup apropriate charspace matrix */
685 	S=(struct XYspace *)IDENTITY;
686 	/* Make this permanent so that scaling it in fontfcnB_ByName will
687 	   make a duplicate of it, and this duplicate can thus be safely
688 	   destroyed.  Fixes the somewhat smaller memory leak */
689 	S=(struct XYspace *)Permanent
690 	  (Transform(S, pFontBase->pFontArray[FontID].FontTransform[0],
691 		     pFontBase->pFontArray[FontID].FontTransform[1],
692 		     pFontBase->pFontArray[FontID].FontTransform[2],
693 		     pFontBase->pFontArray[FontID].FontTransform[3]));
694 	/* Get metrics values */
695 	area=fontfcnB_ByName( FontID, 0, S, ".notdef", &mode,
696 			      pFontBase->pFontArray[FontID].pType1Data, DO_RASTER);
697 	if (area==NULL || mode!=0){
698 	  sprintf( err_warn_msg_buf,
699 		   "Could not get charspace representation of \".notdef\", Font %d, mode=%d!",
700 		   FontID, mode);
701 	  T1_PrintLog( "T1_SetString()", err_warn_msg_buf,
702 		       T1LOG_ERROR);
703 	  T1_errno=mode;
704 	  return( NULL);
705 	}
706 	/* value to add to hanchor */
707 	h_anchor +=NEARESTPEL(area->ending.x);
708 	/* make sure to free S */
709 	if (S) {
710 	  KillSpace (S);
711 	}
712 	/* make sure to free area */
713 	if (area) {
714 	  KillRegion (area);
715 	}
716       }
717       else{
718 	currchar=&(font_ptr->pFontCache[ustring[i]]);
719 	pixel_h_anchor_corr[i]=((int)floor(h_anchor*factor+0.5));
720 	/* Store maximum rsb ...*/
721 	if ( pixel_h_anchor_corr[i]+currchar->metrics.rightSideBearing > rsb_max){
722 	  rsb_max=pixel_h_anchor_corr[i]+currchar->metrics.rightSideBearing;
723 	}
724 	/* ... and minimum lsb */
725 	if ( pixel_h_anchor_corr[i]+currchar->metrics.leftSideBearing < lsb_min){
726 	  lsb_min=pixel_h_anchor_corr[i]+currchar->metrics.leftSideBearing;
727 	}
728 	/* Advance by current chars width */
729 	/*	h_anchor +=T1_GetCharWidth( FontID, ustring[i]); */
730 	if (afm_ind>0) { /* we have a standard character */
731 	  h_anchor +=(fontarrayP->pAFMData->cmi[afm_ind-1].wx) * fontarrayP->extend;
732 	}
733 	else { /* afm_ind must be negative so that we have a composite char */
734 	  h_anchor +=(fontarrayP->pAFMData->ccd[-(afm_ind+1)].wx) * fontarrayP->extend;
735 	}
736 	/* If kerning, insert kerning amount */
737 	if ((i<no_chars -1) && (modflag & T1_KERNING))
738 	  h_anchor +=T1_GetKerning( FontID, ustring[i], ustring[i+1]);
739 
740 	/* We still have to care for vertical metrics: */
741 	if (currchar->metrics.ascent>overallascent)
742 	  overallascent=currchar->metrics.ascent;
743 	if (currchar->metrics.descent<overalldescent)
744 	  overalldescent=currchar->metrics.descent;
745       }
746     }
747     string_glyph.metrics.advanceX=(int)floor(h_anchor*factor+0.5);
748 
749     /* We have to check for underlining and such things. They may affect the
750        bounding box of the glyph */
751     if (modflag & T1_UNDERLINE){
752       T1_ComputeLineParameters( FontID, T1_UNDERLINE,
753 				string_glyph.metrics.advanceX,
754 				size,
755 			        &underline_startx, &underline_endx,
756 			        &underline_starty, &underline_endy);
757       /* Check whether rsb is affected ...*/
758       if ( underline_endx > rsb_max){
759 	rsb_max=underline_endx;
760       }
761       /* ... and for lsb */
762       if ( underline_startx < lsb_min){
763 	lsb_min=underline_startx;
764       }
765 
766       /* Vertical metrics may also be affected. */
767       if (underline_starty > overallascent)
768 	overallascent=underline_starty;
769       if (underline_endy < overalldescent)
770 	overalldescent=underline_endy;
771     }
772     if (modflag & T1_OVERLINE){
773       T1_ComputeLineParameters( FontID, T1_OVERLINE,
774 				string_glyph.metrics.advanceX,
775 				size,
776 			        &overline_startx, &overline_endx,
777 			        &overline_starty, &overline_endy);
778       /* Check whether rsb is affected ...*/
779       if ( overline_endx > rsb_max){
780 	rsb_max=overline_endx;
781       }
782       /* ... and for lsb */
783       if ( overline_startx < lsb_min){
784 	lsb_min=overline_startx;
785       }
786 
787       /* Vertical metrics may also be affected. */
788       if (overline_starty > overallascent)
789 	overallascent=overline_starty;
790       if (overline_endy < overalldescent)
791 	overalldescent=overline_endy;
792     }
793     if (modflag & T1_OVERSTRIKE){
794       T1_ComputeLineParameters( FontID, T1_OVERSTRIKE,
795 				string_glyph.metrics.advanceX,
796 				size,
797 			        &overstrike_startx, &overstrike_endx,
798 			        &overstrike_starty, &overstrike_endy);
799       /* Check whether rsb is affected ...*/
800       if ( overstrike_endx > rsb_max){
801 	rsb_max=overstrike_endx;
802       }
803       /* ... and for lsb */
804       if ( overstrike_startx < lsb_min){
805 	lsb_min=overstrike_startx;
806       }
807 
808       /* Vertical metrics may also be affected. */
809       if (overstrike_starty > overallascent)
810 	overallascent=overstrike_starty;
811       if (overstrike_endy < overalldescent)
812 	overalldescent=overstrike_endy;
813     }
814 
815 
816 
817     /* Set the string-glyphs' metrics: */
818     /* Bearings: */
819     string_glyph.metrics.rightSideBearing=rsb_max;
820     string_glyph.metrics.leftSideBearing=lsb_min;
821     /* ascent and descent: */
822     string_glyph.metrics.ascent=overallascent;
823     string_glyph.metrics.descent=overalldescent;
824 
825 
826 
827     /* Now, allocate memory for the resulting bitmap and set it to 0: */
828     h=overallascent - overalldescent;
829     w=string_glyph.metrics.rightSideBearing-string_glyph.metrics.leftSideBearing;
830 
831     paddedW = PAD( w, T1_pad);
832     if ( h > 0 && w > 0){
833       memsize = h * paddedW / 8;
834       /* We alloc some amount more in order to avoid alignment check in
835 	 bit-blitting loop */
836       memsize += T1_pad/8;
837       string_glyph.bits = (char *)malloc( memsize);
838       if (string_glyph.bits == NULL) {
839 	T1_errno=T1ERR_ALLOC_MEM;
840 	return(NULL);
841       }
842 
843     }
844     else {
845     /* We have only characters without pixels in the string ->
846        we allow this and only set the advance width in the glyph.
847        The bits pointer will be NULL. We reset rsb and lsb */
848       string_glyph.metrics.rightSideBearing=0;
849       string_glyph.metrics.leftSideBearing=0;
850       string_glyph.metrics.ascent=0;
851       string_glyph.metrics.descent=0;
852     }
853 
854     if (string_glyph.bits != NULL) {
855 
856       memset(string_glyph.bits, 0, memsize);
857 
858       /* Now comes the loop for bitmap blitting: */
859       for (i=0;i<no_chars;i++){
860 	/* Get pointer to character number i of string: */
861 	currchar=&(font_ptr->pFontCache[ustring[i]]);
862 
863 	/* First, we have to correct the positioning values to refer to
864 	   the bitmap BBox */
865 	pixel_h_anchor_corr[i] -= lsb_min;
866 	pixel_h_anchor_corr[i] += currchar->metrics.leftSideBearing;
867 
868 	/* Compute vertical anchor for current char-bitmap: */
869 	v_anchor=overallascent - currchar->metrics.ascent;
870 	char_paddedW=PAD( currchar->metrics.rightSideBearing
871 			  - currchar->metrics.leftSideBearing , T1_pad);
872 	/* We have to check for Big Endian. In that case, we have to
873 	   act on byte-level */
874 	if (T1_byte){
875 	  BitShift =  pixel_h_anchor_corr[i] % 8;
876 	  ByteOffset = pixel_h_anchor_corr[i] / 8;
877 	}
878 	else {
879 	  BitShift =  pixel_h_anchor_corr[i] % T1_pad;
880 	  ByteOffset = pixel_h_anchor_corr[i] / T1_pad;
881 	  if (T1_pad==32)
882 	    ByteOffset *=4;
883 	  else if (T1_pad==16)
884 	    ByteOffset *=2;
885 	}
886 #ifdef T1_AA_TYPE64
887 	/* We compile this part only if long is 64 bits to be conform to ANSI C */
888 	if (T1_pad==32 && T1_byte==0){
889 	  /* The following loop steps through the lines of the character bitmap: */
890 	  for (j=0;j<currchar->metrics.ascent-currchar->metrics.descent;j++){
891 	    Target_l= (unsigned T1_AA_TYPE32 *)(string_glyph.bits +((v_anchor+j)*paddedW/8)
892 					+ByteOffset);
893 	    /* The following loop copies the scanline of a character bitmap: */
894 	    if (currchar->bits != NULL) {
895 	      p_l = (unsigned T1_AA_TYPE32 *)(currchar->bits+(char_paddedW/8*j));
896 	      if (BitShift == 0) {
897 		for (k=char_paddedW >> 5; k; k--)
898 		  *Target_l++ |= *p_l++;
899 	      } else {
900 		for (k=0; k < char_paddedW / 32 ; k++){
901 		  BitBuf_l= ((T1_AA_TYPE64)(*p_l++)) << BitShift;
902 		  *Target_l++ |= BitBuf_l;
903 		  *Target_l |= BitBuf_l>>l_shift;
904 		} /* End of for ( .. ) stepping through columns */
905 	      }
906 	    } /* End of if(currchar->bits != NULL) */
907 	  } /* End of for( .. ) steppin' through lines of char bitmap */
908 	}/* end if (T1_pad==32) */
909 	else
910 #endif
911 	  if (T1_pad==16 && T1_byte==0){
912 	    /* The following loop steps through the lines of the character bitmap: */
913 	    for (j=0;j<currchar->metrics.ascent-currchar->metrics.descent;j++){
914 	      Target_s= (unsigned T1_AA_TYPE16 *)(string_glyph.bits +((v_anchor+j)*paddedW/8)
915 					   +ByteOffset);
916 	      /* The following loop copies the scanline of a character bitmap: */
917 	      if (currchar->bits != NULL) {
918 		p_s = (unsigned  T1_AA_TYPE16 *)(currchar->bits+(char_paddedW/8*j));
919 		if (BitShift == 0) {
920 		  for (k=char_paddedW >> 4; k; k--)
921 		    *Target_s++ |= *p_s++;
922 		}
923 		else{
924 		  for (k=char_paddedW >> 4; k; k--){
925 		    BitBuf_s= ((T1_AA_TYPE32)(*p_s++))<<BitShift;
926 		    *Target_s++ |= BitBuf_s;
927 		    *Target_s |= BitBuf_s>>s_shift;
928 		  } /* End of for ( .. ) stepping through columns */
929 		}
930 	      } /* End of if(currchar->bits != NULL) */
931 	    } /* End of for( .. ) steppin' through lines of char bitmap */
932 	  }/* end if (T1_pad==16 */
933 	  else{ /* T1_pad = 8 or Big Endian machine */
934 	    /* The following loop steps through the lines of the character bitmap: */
935 	    for (j=0;j<currchar->metrics.ascent-currchar->metrics.descent;j++){
936 	      Target_c= (unsigned char *)(string_glyph.bits +((v_anchor+j)*paddedW/8)
937 					  +ByteOffset);
938 	      /* The following loop copies the scanline of a character bitmap: */
939 	      if (currchar->bits != NULL) {
940 		p_c = (unsigned char *)(currchar->bits+(char_paddedW/8*j));
941 		if (BitShift == 0){
942 		  for (k=char_paddedW >> 3; k; k--)
943 		    *Target_c++ |= *p_c++;
944 		}
945 		else{
946 		  for (k=char_paddedW >> 3; k; k--){
947 		    BitBuf_c = ((T1_AA_TYPE16)(*p_c++)) << BitShift;
948 		    *Target_c++ |= BitBuf_c;
949 		    *Target_c |= BitBuf_c>>c_shift;
950 		  } /* End of for ( .. ) stepping through columns */
951 		}
952 	      } /* End of if(currchar->bits != NULL) */
953 	    } /* End of for( .. ) steppin' through lines of char bitmap */
954 	  } /* end if (T1_pad==8) and/or BigEndian  */
955       }
956     } /* if (string_glyph.bits != NULL) */
957 
958 
959     /* We now put the underlining rule on the glyph */
960     if (modflag & T1_UNDERLINE){
961       start=-string_glyph.metrics.leftSideBearing;
962       for (i=string_glyph.metrics.ascent-underline_starty;
963 	   i<string_glyph.metrics.ascent-underline_endy; i++){
964 	start =-string_glyph.metrics.leftSideBearing +
965 	  (int) floor((double)(string_glyph.metrics.ascent-i)
966 		      *fontarrayP->slant+0.5);
967 	middle = ((start+string_glyph.metrics.advanceX) / 8) - (start / 8);
968 	startmask = 0xFF << (start % 8);
969 	endmask = (char) ~(0xFF << ((start+string_glyph.metrics.advanceX) % 8));
970 	Target_c= (unsigned char *)(string_glyph.bits +(i*paddedW/8)
971 				    + (start / 8));
972 	j=middle;
973 	if (j == 0)
974 	  *Target_c++ |= startmask & endmask;
975 	else {
976 	  *Target_c++ |= startmask;
977 	  while (--j > 0)
978 	    *Target_c++ = (unsigned char) 0xFF;
979 	  if ((endmask))
980 	    *Target_c |= endmask;
981 	}
982       }
983     }
984     /* Put an overstrike rule on the glyph */
985     if (modflag & T1_OVERSTRIKE){
986       start=-string_glyph.metrics.leftSideBearing;
987       for (i=string_glyph.metrics.ascent-overstrike_starty;
988 	   i<string_glyph.metrics.ascent-overstrike_endy; i++){
989 	start =-string_glyph.metrics.leftSideBearing +
990 	  (int) floor((double)(string_glyph.metrics.ascent-i)
991 		      *fontarrayP->slant+0.5);
992 	middle = ((start+string_glyph.metrics.advanceX) / 8) - (start / 8);
993 	startmask = 0xFF << (start % 8);
994 	endmask = (char) ~(0xFF << ((start+string_glyph.metrics.advanceX) % 8));
995 	Target_c= (unsigned char *)(string_glyph.bits +(i*paddedW/8)
996 				    + (start / 8));
997 	j=middle;
998 	if (j == 0)
999 	  *Target_c++ |= startmask & endmask;
1000 	else {
1001 	  *Target_c++ |= startmask;
1002 	  while (--j > 0)
1003 	    *Target_c++ = (unsigned char) 0xFF;
1004 	  if ((endmask))
1005 	    *Target_c |= endmask;
1006 	}
1007       }
1008     }
1009     /* Put an overline rule */
1010     if (modflag & T1_OVERLINE){
1011       start=-string_glyph.metrics.leftSideBearing;
1012       for (i=string_glyph.metrics.ascent-overline_starty;
1013 	   i<string_glyph.metrics.ascent-overline_endy; i++){
1014 	start =-string_glyph.metrics.leftSideBearing +
1015 	  (int) floor((double)(string_glyph.metrics.ascent-i)
1016 		      *fontarrayP->slant+0.5);
1017 	middle = ((start+string_glyph.metrics.advanceX) / 8) - (start / 8);
1018 	startmask = 0xFF << (start % 8);
1019 	endmask = (char) ~(0xFF << ((start+string_glyph.metrics.advanceX) % 8));
1020 	Target_c= (unsigned char *)(string_glyph.bits +(i*paddedW/8)
1021 				    + (start / 8));
1022 	j=middle;
1023 	if (j == 0)
1024 	  *Target_c++ |= startmask & endmask;
1025 	else {
1026 	  *Target_c++ |= startmask;
1027 	  while (--j > 0)
1028 	    *Target_c++ = (unsigned char) 0xFF;
1029 	  if ((endmask))
1030 	    *Target_c |= endmask;
1031 	}
1032       }
1033     }
1034 
1035     /* Check for writing direction and re-compute dimensions appropriately: */
1036     if (modflag & T1_RIGHT_TO_LEFT){
1037       string_glyph.metrics.advanceX *= -1;
1038       string_glyph.metrics.leftSideBearing += string_glyph.metrics.advanceX;
1039       string_glyph.metrics.rightSideBearing += string_glyph.metrics.advanceX;
1040     }
1041 
1042     return(&string_glyph);
1043   } /* end of "if (rot_flag==0.0)" */
1044 
1045 
1046   /* fnt_ptr now points to the correct FontSizeDeps-struct =>
1047      lets now raster the character */
1048   mode=0;
1049   kern_pairs=(int *)calloc(no_chars, sizeof(int));
1050   if ((modflag & T1_KERNING))
1051     for (i=0; i<no_chars -1; i++)
1052       kern_pairs[i]=T1_GetKerning( FontID, ustring[i], ustring[i+1]);
1053   area=fontfcnB_string( FontID, modflag, Current_S,
1054 			fontarrayP->pFontEnc,
1055 			ustring, no_chars, &mode,
1056 			fontarrayP->pType1Data,
1057 			kern_pairs, spacewidth,
1058 			DO_RASTER);
1059   KillSpace (Current_S);
1060 
1061   /* In all cases, free memory for kerning pairs */
1062   free(kern_pairs);
1063 
1064   /* fill the string_glyph-structure */
1065   if (mode > 0) {
1066     sprintf( err_warn_msg_buf, "fontfcnB() set mode=%d", mode);
1067     T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING);
1068     T1_errno=mode;
1069     /* make sure to get rid of area if it's there */
1070     if (area){
1071       KillRegion (area);
1072     }
1073     return(NULL);
1074   }
1075   if (area == NULL){
1076     T1_PrintLog( "T1_SetString()", "area=NULL returned by fontfcnB()", T1LOG_WARNING);
1077     T1_errno=mode;
1078     return(NULL);
1079   }
1080 
1081   if (mode == FF_NOTDEF_SUBST) {
1082     sprintf( err_warn_msg_buf,
1083 	     "\".notdef\" substituted somewhere in string from font %d",
1084 	     FontID);
1085     T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING);
1086     mode=0;
1087   }
1088 
1089   h = area->ymax - area->ymin;
1090   w = area->xmax - area->xmin;
1091   paddedW = PAD(w, T1_pad);
1092   if (h > 0 && w > 0) {
1093     memsize = h * paddedW / 8 + 1;
1094     /* This is for the users copy of the character, for security-reasons
1095        the original pointer to the cache area is not used. The entry string_glyph.bits
1096        is free'ed every time this function is called: */
1097     string_glyph.bits = (char *)malloc(memsize*sizeof( char));
1098     if (string_glyph.bits == NULL) {
1099       T1_errno=T1ERR_ALLOC_MEM;
1100       /* make sure to get rid of area if it's there */
1101       if (area){
1102 	KillRegion (area);
1103       }
1104       /* it's safe to free this, since this is a rotated glyph and
1105 	 therefore it's a copy of the original one */
1106       return(NULL);
1107     }
1108   }
1109   else {
1110     h = w = 0;
1111     area->xmin = area->xmax = 0;
1112     area->ymin = area->ymax = 0;
1113   }
1114 
1115   string_glyph.metrics.leftSideBearing=area->xmin;
1116   string_glyph.metrics.advanceX=NEARESTPEL(area->ending.x - area->origin.x);
1117   string_glyph.metrics.advanceY=-NEARESTPEL(area->ending.y - area->origin.y);
1118   string_glyph.metrics.rightSideBearing=area->xmax;
1119   string_glyph.metrics.descent=-area->ymax;
1120   string_glyph.metrics.ascent=-area->ymin;
1121 
1122   if (h > 0 && w > 0) {
1123     (void) memset(string_glyph.bits, 0, memsize);
1124     fill(string_glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize );
1125   }
1126   else { /* We have no black pixels */
1127     string_glyph.metrics.leftSideBearing=0;
1128     string_glyph.metrics.advanceX=NEARESTPEL(area->ending.x - area->origin.x);
1129     string_glyph.metrics.advanceY=-NEARESTPEL(area->ending.y - area->origin.y);
1130     string_glyph.metrics.rightSideBearing=0;
1131     string_glyph.metrics.descent=0;
1132     string_glyph.metrics.ascent=0;
1133   }
1134 
1135 
1136   /* make sure to get rid of area if it's there */
1137   if (area){
1138     KillRegion (area);
1139   }
1140   /* Check for writing direction and re-compute dimensions appropriately: */
1141   if (modflag & T1_RIGHT_TO_LEFT){
1142     string_glyph.metrics.advanceX *= -1;
1143     string_glyph.metrics.advanceY *= -1;
1144     string_glyph.metrics.leftSideBearing += string_glyph.metrics.advanceX;
1145     string_glyph.metrics.rightSideBearing += string_glyph.metrics.advanceX;
1146     string_glyph.metrics.descent += string_glyph.metrics.advanceY;
1147     string_glyph.metrics.ascent += string_glyph.metrics.advanceY;
1148   }
1149   return(&string_glyph);
1150 }
1151 
1152 
1153 
fill(dest,h,w,area,byte,bit,wordsize)1154 void fill(dest, h, w, area, byte, bit, wordsize)
1155      register char *dest;  /* destination bitmap                           */
1156      int h,w;              /* dimensions of 'dest', w padded               */
1157      register struct region *area;  /* region to write to 'dest'           */
1158      int byte,bit;         /* flags; LSBFirst or MSBFirst                  */
1159      int wordsize;         /* number of bits per word for LSB/MSB purposes */
1160 {
1161   register struct edgelist *edge;  /* for looping through edges         */
1162   register char *p;     /* current scan line in 'dest'                  */
1163   register int y;       /* for looping through scans                    */
1164   register int wbytes = w / 8;  /* number of bytes in width             */
1165   register pel *leftP,*rightP;  /* pointers to X values, left and right */
1166   int xmin = area->xmin;  /* upper left X                               */
1167   int ymin = area->ymin;  /* upper left Y                               */
1168 
1169   for (edge = area->anchor; VALIDEDGE(edge); edge = edge->link->link) {
1170 
1171     p = dest + (edge->ymin - ymin) * wbytes;
1172     leftP = edge->xvalues;
1173     rightP = edge->link->xvalues;
1174 
1175     for (y = edge->ymin; y < edge->ymax; y++) {
1176       fillrun(p, *leftP++ - xmin , *rightP++ - xmin, bit);
1177       p += wbytes;
1178     }
1179   }
1180   /*
1181     Now, as an afterthought, we'll go reorganize if odd byte order requires
1182     it:
1183     */
1184   /* We do not reorganize since t1lib internally always uses LSBFirst */
1185   /*
1186   if ( 0 && wordsize != 8) {
1187     register int i;
1188     printf("Reorganizing data ..\n");
1189 
1190     switch (wordsize) {
1191     case 16:
1192       {
1193 	register unsigned short data,*p;
1194 	p = (unsigned short *) dest;
1195 	for (i = h * w /16; --i >= 0;) {
1196 	  data = *p;
1197 	  *p++ = (data << 8) + (data >> 8);
1198 	}
1199 	break;
1200       }
1201     case 64:
1202     case 32:
1203       {
1204 	register ULONG data,*p;
1205 	p = (ULONG *) dest;
1206 	for (i = h * w / 32; --i >= 0;) {
1207 	  data = *p;
1208 	  *p++ = (data << 24) + (data >> 24)
1209 	    + (0xFF00 & (data >> 8))
1210 	    + (0xFF0000 & (data << 8));
1211 	}
1212 	if (wordsize == 64) {
1213 	  p = (ULONG *) dest;
1214 	  for (i = h * w / 64; --i >= 0;) {
1215 	    data = *p++;
1216 	    p[-1] = p[0];
1217 	    *p++ = data;
1218 	  }
1219 	}
1220 	break;
1221       }
1222     default:
1223       abort("xiFill: unknown format");
1224     }
1225   }
1226   */
1227 }
1228 
1229 #define  ALLONES  0xFF
1230 
fillrun(register char * p,pel x0,pel x1,int bit)1231 void fillrun(register char *p, pel x0, pel x1, int bit)
1232 {
1233   register int startmask,endmask;  /* bits to set in first and last char*/
1234   register int middle;  /* number of chars between start and end + 1    */
1235 
1236   if (x1 <= x0)
1237     return;
1238   middle = x1/8 - x0/8;
1239   p += x0/8;
1240   x0 &= 7;  x1 &= 7;
1241   if (bit == LSBFirst) {
1242     startmask = ALLONES << x0;
1243     endmask = ~(ALLONES << x1);
1244   }
1245   else {
1246     startmask = ALLONES >> x0;
1247     endmask = ~(ALLONES >> x1);
1248   }
1249   if (middle == 0)
1250     *p++ |= startmask & endmask;
1251   else {
1252     *p++ |= startmask;
1253     while (--middle > 0){
1254       *p++ = (unsigned char)ALLONES;
1255     }
1256     if (endmask)
1257       *p |= endmask;
1258   }
1259 }
1260 
1261 
1262 /* outline */
1263 #undef CHECK_OUTLINEFILL
1264 #ifdef CHECK_OUTLINEFILL
fill(dest,h,w,area,byte,bit,wordsize)1265 void fill(dest, h, w, area, byte, bit, wordsize)
1266      register char *dest;  /* destination bitmap                           */
1267      int h,w;              /* dimensions of 'dest', w padded               */
1268      register struct region *area;  /* region to write to 'dest'           */
1269      int byte,bit;         /* flags; LSBFirst or MSBFirst                  */
1270      int wordsize;         /* number of bits per word for LSB/MSB purposes */
1271 {
1272   register struct edgelist *edge;  /* for looping through edges         */
1273   register char *p;     /* current scan line in 'dest'                  */
1274   register int y;       /* for looping through scans                    */
1275   register int wbytes = w / 8;  /* number of bytes in width             */
1276   register pel *leftP,*rightP;  /* pointers to X values, left and right */
1277   int xmin = area->xmin;  /* upper left X                               */
1278   int ymin = area->ymin;  /* upper left Y                               */
1279 
1280   for (edge = area->anchor; VALIDEDGE(edge); edge = edge->link->link) {
1281 
1282     p = dest + (edge->ymin - ymin) * wbytes;
1283     leftP = edge->xvalues;
1284     rightP = edge->link->xvalues;
1285 
1286     printf("leftP=%d, RightP=%d,\n", *leftP, *rightP);
1287 
1288 
1289     for (y = edge->ymin; y < edge->ymax; y++) {
1290       printf("leftP=%d, RightP=%d,y=%d\n", *leftP, *rightP, y);
1291 
1292       fillrun(p, *leftP++ - xmin, *rightP++ - xmin, bit);
1293       p += wbytes;
1294     }
1295   }
1296 }
1297 #endif
1298 
1299 
1300 /* T1_CopyGlyph(): Make a copy of an existent glyph-structure to save it
1301    for later usage by the user. */
T1_CopyGlyph(GLYPH * glyph)1302 GLYPH *T1_CopyGlyph( GLYPH *glyph)
1303 {
1304   GLYPH *dest;
1305   long size;
1306 
1307 
1308   if (glyph==NULL){
1309     T1_errno=T1ERR_INVALID_PARAMETER;
1310     return(NULL);
1311   }
1312 
1313   /* Assign padding value */
1314   T1_pad=pFontBase->bitmap_pad;
1315   /* Allocate memory for struct: */
1316   if ((dest=(GLYPH *)malloc(sizeof(GLYPH)))==NULL){
1317     T1_errno=T1ERR_ALLOC_MEM;
1318     return(NULL);
1319   }
1320 
1321   /* Copy the structure members: */
1322   *dest=*glyph;
1323   /* Allocate memory for bitmap, initialize pointer to it and copy bitmap: */
1324   size=PAD((dest->metrics.rightSideBearing-dest->metrics.leftSideBearing)*
1325 	   glyph->bpp, T1_pad) / 8;
1326   size=size*(dest->metrics.ascent-dest->metrics.descent);
1327    /* We must check whether there's actually a bits-pointer different from
1328       NULL. If not omit the following step: */
1329   if (glyph->bits!=NULL){
1330     if ((dest->bits=(char *)malloc(size*sizeof(char)))==NULL){
1331       free(dest);
1332       T1_errno=T1ERR_ALLOC_MEM;
1333       return(NULL);
1334     }
1335     memcpy(dest->bits,glyph->bits,size);
1336   }
1337   return(dest);
1338 }
1339 
1340 /* T1_DumpGlyph(): Dump a glyph-representation to stdout: */
T1_DumpGlyph(GLYPH * glyph)1341 void T1_DumpGlyph( GLYPH *glyph)
1342 {
1343   int i,j,h,w;   /* i=line-index, j=column-index */
1344   long paddedW;
1345 
1346 
1347   printf("Dataformat: T1_bit=%d, T1_byte=%d, T1_wordsize=%d, T1_pad=%d\n",
1348 	 T1_bit, T1_byte, T1_pad, T1_pad);
1349 
1350   if (glyph==NULL){
1351     return;
1352   }
1353 
1354   h=glyph->metrics.ascent-glyph->metrics.descent;
1355   w=glyph->metrics.rightSideBearing-glyph->metrics.leftSideBearing;
1356 
1357   paddedW=PAD(w,T1_pad);
1358 
1359   printf("GlyphInfo: h=%d, w=%d, paddedW=%ld\n", h, w, paddedW);
1360 
1361   for ( i=0; i<h; i++){
1362     if (T1_pad==8)
1363       for (j=0; j<paddedW/T1_pad; j++)
1364 	bin_dump_c(glyph->bits[i*paddedW/T1_pad+j], 1);
1365     else if (T1_pad==16)
1366       for (j=0; j<paddedW/T1_pad; j++){
1367 	bin_dump_s(((unsigned short *)glyph->bits)[i*paddedW/T1_pad+j], 1);
1368       }
1369     else
1370       for (j=0; j<paddedW/T1_pad; j++){
1371 	bin_dump_l(((unsigned long *)glyph->bits)[i*paddedW/T1_pad+j], 1);
1372       }
1373     printf("\n");
1374   }
1375 }
1376 
1377 
1378 
1379 /* This function will essentially return the bounding box of the
1380    line-rule */
T1_ComputeLineParameters(int FontID,int mode,int width,float size,int * startx,int * endx,int * starty,int * endy)1381 void T1_ComputeLineParameters( int FontID, int mode,
1382 			       int width, float size,
1383 			       int *startx, int *endx,
1384 			       int *starty, int *endy)
1385 {
1386   float position=0.0, thickness=0.0;
1387   int startx1, startx2, endx1, endx2;
1388 
1389   if (mode & T1_UNDERLINE){
1390     position=pFontBase->pFontArray[FontID].UndrLnPos
1391       * DeviceSpecifics.scale_y;
1392     thickness=pFontBase->pFontArray[FontID].UndrLnThick
1393       * DeviceSpecifics.scale_y;
1394   }
1395   else if (mode & T1_OVERLINE){
1396     position=pFontBase->pFontArray[FontID].OvrLnPos
1397       * DeviceSpecifics.scale_y;
1398     thickness=pFontBase->pFontArray[FontID].OvrLnThick
1399       * DeviceSpecifics.scale_y;
1400   }
1401   else if (mode & T1_OVERSTRIKE){
1402     position=pFontBase->pFontArray[FontID].OvrStrkPos
1403       * DeviceSpecifics.scale_y;
1404     thickness=pFontBase->pFontArray[FontID].OvrStrkThick
1405       * DeviceSpecifics.scale_y;
1406   }
1407 
1408   *starty=(int) floor((position+0.5*(thickness-DeviceSpecifics.y_resolution/1000.0))
1409 		      *size/1000.0 +0.5 );
1410   startx1=(int) floor(*starty*pFontBase->pFontArray[FontID].slant+0.5);
1411   *endy  =*starty - (int) floor(thickness/1000.0*size+0.5);
1412   startx2=(int) floor(*endy*pFontBase->pFontArray[FontID].slant+0.5);
1413   *startx=startx1 < startx2 ? startx1 : startx2;
1414   endx1  = width +
1415     (int) floor(*starty*pFontBase->pFontArray[FontID].slant+0.5);
1416   endx2  = width +
1417     (int) floor(*endy*pFontBase->pFontArray[FontID].slant+0.5);
1418   *endx=endx1 < endx2 ? endx2 : endx1;
1419 
1420   /* We take care that at least one pixel is drawn */
1421   if (*starty==*endy)
1422     *endy -=1;
1423 
1424   return;
1425 
1426 }
1427 
1428 
1429 
1430 /* The following function concatenates two glyphs. Optional offsets
1431    x_off, y_off are respected. By the function.
1432    If either glyph is NULL or the glyphs have distinct depth, NULL is
1433    returned. */
T1_ConcatGlyphs(GLYPH * glyph_1,GLYPH * glyph_2,int x_off,int y_off,int modflag)1434 GLYPH *T1_ConcatGlyphs( GLYPH *glyph_1, GLYPH *glyph_2,
1435 			int x_off, int y_off, int modflag)
1436 {
1437 
1438   int lsb1, lsb2, rsb1, rsb2;
1439   int advanceX1, advanceX2, advanceY1, advanceY2;
1440   int ascent1, ascent2, descent1, descent2;
1441   int rsb, lsb, ascent, descent, advanceX, advanceY;
1442   int vanchor, w, h, wscanline, wscanline1, wscanline2, bpp;
1443   int memsize, BitShift;
1444   GLYPH *glyph1, *glyph2;
1445   unsigned T1_AA_TYPE16 BitBuf_c;
1446   unsigned T1_AA_TYPE32 BitBuf_s;
1447   unsigned long BitBuf_l;   /* This is only actually used if sizeof long = 8 */
1448   int i, j, k;
1449   int ByteOffset;
1450 
1451   unsigned char *Target_c, *p_c;
1452   unsigned T1_AA_TYPE16 *Target_s, *p_s;
1453   unsigned T1_AA_TYPE32 *Target_l, *p_l;
1454 
1455   static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1};
1456 
1457 
1458   /* We handle the Right-To-Left concatenation the simple way:
1459      1) Change the order of the two glyphs
1460      2) Invert the sign of the y-part of the offset
1461      3) Recalculate the dimensions of the resulating glyph.
1462   */
1463   /* Check for writing direction and reorganize appropriately: */
1464   if (modflag & T1_RIGHT_TO_LEFT){
1465     glyph1=glyph_2;
1466     glyph2=glyph_1;
1467     y_off=-y_off;
1468   }
1469   else {
1470     glyph1=glyph_1;
1471     glyph2=glyph_2;
1472   }
1473 
1474   if (glyph1==NULL){
1475     T1_errno=T1ERR_INVALID_PARAMETER;
1476     return( NULL);
1477   }
1478   if (glyph2==NULL){
1479     T1_errno=T1ERR_INVALID_PARAMETER;
1480     return( NULL);
1481   }
1482   if (glyph1->bpp != glyph2->bpp){
1483     T1_errno=T1ERR_INVALID_PARAMETER;
1484     return( NULL);
1485   }
1486 
1487   /* We have two glyph different from NULL */
1488   /* Reset glyph, if necessary */
1489   if (glyph.bits!=NULL){
1490     free(glyph.bits);
1491     glyph.bits=NULL;
1492   }
1493   glyph.metrics.leftSideBearing=0;
1494   glyph.metrics.rightSideBearing=0;
1495   glyph.metrics.advanceX=0;
1496   glyph.metrics.advanceY=0;
1497   glyph.metrics.ascent=0;
1498   glyph.metrics.descent=0;
1499   glyph.pFontCacheInfo=NULL;
1500   glyph.bpp=1;
1501 
1502   /* Assign dimens */
1503   lsb1=glyph1->metrics.leftSideBearing;
1504   rsb1=glyph1->metrics.rightSideBearing;
1505   ascent1=glyph1->metrics.ascent;
1506   descent1=glyph1->metrics.descent;
1507   advanceX1=glyph1->metrics.advanceX + x_off;
1508   advanceY1=glyph1->metrics.advanceY + y_off;
1509 
1510   lsb2=glyph2->metrics.leftSideBearing;
1511   rsb2=glyph2->metrics.rightSideBearing;
1512   ascent2=glyph2->metrics.ascent;
1513   descent2=glyph2->metrics.descent;
1514   advanceX2=glyph2->metrics.advanceX;
1515   advanceY2=glyph2->metrics.advanceY;
1516 
1517   lsb=lsb1 < lsb2+advanceX1 ? lsb1 : lsb2+advanceX1;
1518   rsb=rsb1 > rsb2+advanceX1 ? rsb1 : rsb2+advanceX1;
1519   ascent=ascent1 > ascent2+advanceY1 ? ascent1 : ascent2+advanceY1;
1520   descent=descent1 < descent2+advanceY1 ? descent1 : descent2+advanceY1;
1521   advanceX=advanceX1+advanceX2;
1522   advanceY=advanceY1+advanceY2;
1523 
1524   bpp=glyph1->bpp;
1525   w=rsb-lsb;
1526   h=ascent-descent;
1527   wscanline=PAD( w*bpp, T1_pad) / 8;
1528   wscanline1=PAD( (rsb1-lsb1)*bpp, T1_pad) / 8;
1529   wscanline2=PAD( (rsb2-lsb2)*bpp, T1_pad) / 8;
1530   memsize=wscanline*h;
1531   if ((glyph.bits=(char *)calloc( memsize + 1, sizeof(unsigned char)))==NULL){
1532     T1_errno=T1ERR_ALLOC_MEM;
1533     return(NULL);
1534   }
1535 
1536   if (bpp==1){
1537     if (T1_pad==32 && T1_byte==0 && sizeof(long)==8){
1538       /* The following loop steps through the lines of the first glyph: */
1539       vanchor=ascent-ascent1;
1540       BitShift=(lsb1-lsb) % 32;
1541       ByteOffset=(lsb1-lsb)/32*4;
1542       for ( i=0; i<ascent1-descent1; i++){
1543 	Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
1544 					    +ByteOffset);
1545 	p_l = (unsigned T1_AA_TYPE32 *)(glyph1->bits+(wscanline1*i));
1546 	if (BitShift == 0){
1547 	  for (k=wscanline1/4; k; k--)
1548 	    *Target_l++ |= *p_l++;
1549 	}
1550 	else{
1551 	  for (k=wscanline1/4; k; k--){
1552 	    BitBuf_l = ((long)*p_l++) << BitShift;
1553 	    *Target_l++ |= BitBuf_l;
1554 	    *Target_l |= BitBuf_l>>l_shift;
1555 	  }
1556 	}
1557       }
1558       /* The following loop steps through the lines of the second glyph: */
1559       vanchor=ascent-(ascent2+advanceY1);
1560       BitShift=(lsb2+advanceX1-lsb) % 32;
1561       ByteOffset=(lsb2+advanceX1-lsb)/32*4;
1562       for ( i=0; i<ascent2-descent2; i++){
1563 	Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
1564 					    +ByteOffset);
1565 	p_l = (unsigned T1_AA_TYPE32 *)(glyph2->bits+(wscanline2*i));
1566 	if (BitShift == 0){
1567 	  for (k=wscanline2/4; k; k--)
1568 	    *Target_l++ |= *p_l++;
1569 	}
1570 	else{
1571 	  for (k=wscanline2/4; k; k--){
1572 	    BitBuf_l = ((long)*p_l++) << BitShift;
1573 	    *Target_l++ |= BitBuf_l;
1574 	    *Target_l |= BitBuf_l>>l_shift;
1575 	  }
1576 	}
1577       }
1578     }
1579     else if(T1_pad==16 && T1_byte==0){
1580       /* The following loop steps through the lines of the first glyph: */
1581       vanchor=ascent-ascent1;
1582       BitShift=(lsb1-lsb) % 16;
1583       ByteOffset=(lsb1-lsb)/16*2;
1584       for ( i=0; i<ascent1-descent1; i++){
1585 	Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
1586 					    +ByteOffset);
1587 	p_s = (unsigned T1_AA_TYPE16 *)(glyph1->bits+(wscanline1*i));
1588 	if (BitShift == 0){
1589 	  for (k=wscanline1/2; k; k--)
1590 	    *Target_s++ |= *p_s++;
1591 	}
1592 	else{
1593 	  for (k=wscanline1/2; k; k--){
1594 	    BitBuf_s = ((T1_AA_TYPE32)*p_s++) << BitShift;
1595 	    *Target_s++ |= BitBuf_s;
1596 	    *Target_s |= BitBuf_s>>s_shift;
1597 	  }
1598 	}
1599       }
1600       /* The following loop steps through the lines of the second glyph: */
1601       vanchor=ascent-(ascent2+advanceY1);
1602       BitShift=(lsb2+advanceX1-lsb) % 16;
1603       ByteOffset=(lsb2+advanceX1-lsb)/16*2;
1604       for ( i=0; i<ascent2-descent2; i++){
1605 	Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
1606 					    +ByteOffset);
1607 	p_s = (unsigned T1_AA_TYPE16 *)(glyph2->bits+(wscanline2*i));
1608 	if (BitShift == 0){
1609 	  for (k=wscanline2/2; k; k--)
1610 	    *Target_s++ |= *p_s++;
1611 	}
1612 	else{
1613 	  for (k=wscanline2/2; k; k--){
1614 	    BitBuf_s = ((T1_AA_TYPE32)*p_s++) << BitShift;
1615 	    *Target_s++ |= BitBuf_s;
1616 	    *Target_s |= BitBuf_s>>s_shift;
1617 	  }
1618 	}
1619       }
1620     }
1621     else{ /* T1_pad==8 or Big Endian machine */
1622       /* The following loop steps through the lines of the first glyph: */
1623       vanchor=ascent-ascent1;
1624       BitShift=(lsb1-lsb) % 8;
1625       ByteOffset=(lsb1-lsb) / 8;
1626       for ( i=0; i<ascent1-descent1; i++){
1627 	Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
1628 				    +ByteOffset);
1629 	p_c = (unsigned char *)(glyph1->bits+(wscanline1*i));
1630 	if (BitShift == 0){
1631 	  for (k=wscanline1; k; k--)
1632 	    *Target_c++ |= *p_c++;
1633 	}
1634 	else{
1635 	  for (k=wscanline1; k; k--){
1636 	    BitBuf_c = ((T1_AA_TYPE16)*p_c++) << BitShift;
1637 	    *Target_c++ |= BitBuf_c;
1638 	    *Target_c |= BitBuf_c>>c_shift;
1639 	  }
1640 	}
1641       }
1642       /* The following loop steps through the lines of the second glyph: */
1643       vanchor=ascent-(ascent2+advanceY1);
1644       BitShift=(lsb2+advanceX1-lsb) % 8;
1645       ByteOffset=(lsb2+advanceX1-lsb) / 8;
1646       for ( i=0; i<ascent2-descent2; i++){
1647 	Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
1648 				    +ByteOffset);
1649 	p_c = (unsigned char *)(glyph2->bits+(wscanline2*i));
1650 	if (BitShift == 0){
1651 	  for (k=wscanline2; k; k--)
1652 	    *Target_c++ |= *p_c++;
1653 	}
1654 	else{
1655 	  for (k=wscanline2; k; k--){
1656 	    BitBuf_c = ((T1_AA_TYPE16)*p_c++) << BitShift;
1657 	    *Target_c++ |= BitBuf_c;
1658 	    *Target_c |= BitBuf_c>>c_shift;
1659 	  }
1660 	}
1661       }
1662     }
1663   } /* end of if (bpp==1) ... */
1664   else if (bpp==8){
1665     /* Set background */
1666     for ( i=0; i<memsize; i++)
1667       ((char *)glyph.bits)[i]=(char) T1aa_bg;
1668     /* The following loop steps through the lines of the first glyph: */
1669     vanchor=ascent-ascent1;
1670     for ( i=0; i<ascent1-descent1; i++){
1671       Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
1672 				  +(lsb1-lsb));
1673       p_c = (unsigned char *)(glyph1->bits+(wscanline1*i));
1674       memcpy( Target_c, p_c, (rsb1-lsb1));
1675     }
1676     /* The following loop steps through the lines of the second glyph.
1677        Note that we only set the pixel if it is not background! */
1678     vanchor=ascent-(ascent2+advanceY1);
1679     for ( i=0; i<ascent2-descent2; i++){
1680       Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
1681 				  +(lsb2+advanceX1-lsb));
1682       p_c = (unsigned char *)(glyph2->bits+(wscanline2*i));
1683       for (j=0; j<(rsb2-lsb2); j++)
1684 	if (p_c[j] != (unsigned char) T1aa_bg)
1685 	  Target_c[j]=p_c[j];
1686     }
1687   } /* end of if (bpp==8) ... */
1688   else if (bpp==16){
1689     /* Set background */
1690     for ( i=0; i<memsize/2; i++)
1691       ((T1_AA_TYPE16 *)glyph.bits)[i]=(T1_AA_TYPE16) T1aa_bg;
1692     /* The following loop steps through the lines of the first glyph: */
1693     vanchor=ascent-ascent1;
1694     for ( i=0; i<ascent1-descent1; i++){
1695       Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
1696 				  +(lsb1-lsb)*2);
1697       p_s = (unsigned T1_AA_TYPE16 *)(glyph1->bits+(wscanline1*i));
1698       memcpy( Target_s, p_s, (rsb1-lsb1)*2);
1699     }
1700     /* The following loop steps through the lines of the second glyph.
1701        Note that we only set the pixel if it is not background! */
1702     vanchor=ascent-(ascent2+advanceY1);
1703     for ( i=0; i<ascent2-descent2; i++){
1704       Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
1705 				  +(lsb2+advanceX1-lsb)*2);
1706       p_s = (unsigned T1_AA_TYPE16 *)(glyph2->bits+(wscanline2*i));
1707       for (j=0; j<(rsb2-lsb2); j++)
1708 	if (p_s[j] != (unsigned T1_AA_TYPE16) T1aa_bg)
1709 	  Target_s[j]=p_s[j];
1710     }
1711   } /* end of if (bpp==16) ... */
1712   else if (bpp==32){
1713     /* Set background */
1714     for ( i=0; i<memsize/4; i++)
1715       ((T1_AA_TYPE32 *)glyph.bits)[i]=(T1_AA_TYPE32) T1aa_bg;
1716     /* The following loop steps through the lines of the first glyph: */
1717     vanchor=ascent-ascent1;
1718     for ( i=0; i<ascent1-descent1; i++){
1719       Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
1720 				  +(lsb1-lsb)*4);
1721       p_l = (unsigned T1_AA_TYPE32 *)(glyph1->bits+(wscanline1*i));
1722       memcpy( Target_l, p_l, (rsb1-lsb1)*4);
1723     }
1724     /* The following loop steps through the lines of the second glyph.
1725        Note that we only set the pixel if it is not background! */
1726     vanchor=ascent-(ascent2+advanceY1);
1727     for ( i=0; i<ascent2-descent2; i++){
1728       Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
1729 				  +(lsb2+advanceX1-lsb)*4);
1730       p_l = (unsigned T1_AA_TYPE32 *)(glyph2->bits+(wscanline2*i));
1731       for (j=0; j<(rsb2-lsb2); j++)
1732 	if (p_l[j] != (unsigned T1_AA_TYPE32) T1aa_bg)
1733 	  Target_l[j]=p_l[j];
1734     }
1735   } /* end of if (bpp==32) ... */
1736 
1737 
1738   /* Check for writing direction and re-compute dimens appropriately: */
1739   if (modflag & T1_RIGHT_TO_LEFT){
1740     advanceX=-advanceX1-advanceX2;
1741     advanceY=-advanceY1-advanceY2;
1742     lsb=lsb1 < lsb2+advanceX1 ? advanceX+lsb1 : advanceX+lsb2+advanceX1;
1743     rsb=rsb1 > rsb2+advanceX1 ? advanceX+rsb1 : advanceX+rsb2+advanceX1;
1744     ascent=ascent1 > ascent2+advanceY1 ? ascent1 : ascent2+advanceY1;
1745     descent=descent1 < descent2+advanceY1 ? descent1 : descent2+advanceY1;
1746     ascent += advanceY;
1747     descent += advanceY;
1748   }
1749 
1750   glyph.metrics.leftSideBearing=lsb;
1751   glyph.metrics.rightSideBearing=rsb;
1752   glyph.metrics.advanceX=advanceX;
1753   glyph.metrics.advanceY=advanceY;
1754   glyph.metrics.ascent=ascent;
1755   glyph.metrics.descent=descent;
1756   glyph.bpp=bpp;
1757 
1758   /*
1759   printf("lsb=%d, rsb=%d, adX=%d, adY=%d asc=%d, desc=%d\n",
1760 	 glyph.metrics.leftSideBearing,
1761 	 glyph.metrics.rightSideBearing,
1762 	 glyph.metrics.advanceX,
1763 	 glyph.metrics.advanceY,
1764 	 glyph.metrics.ascent,
1765 	 glyph.metrics.descent );
1766 	 */
1767 
1768   return( &glyph);
1769 
1770 }
1771 
1772 
1773 
1774 /* T1_FillOutline(): Create a filled glyph from an outline description */
T1_FillOutline(T1_OUTLINE * path,int modflag)1775 GLYPH *T1_FillOutline( T1_OUTLINE *path, int modflag)
1776 {
1777   struct region *area=NULL;
1778 
1779   static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1};
1780   volatile int memsize=0;
1781   int i;
1782   LONG h,w;
1783   LONG paddedW;
1784 
1785 
1786   /* We return to this if something goes wrong deep in the rasterizer */
1787   if ((i=setjmp( stck_state))!=0) {
1788     T1_errno=T1ERR_TYPE1_ABORT;
1789     sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
1790 	     t1_get_abort_message( i));
1791     T1_PrintLog( "T1_FillOutline()", err_warn_msg_buf,
1792 	       T1LOG_ERROR);
1793     return( NULL);
1794   }
1795 
1796   /* Reset character glyph, if necessary */
1797   if (glyph.bits!=NULL){
1798     free(glyph.bits);
1799     glyph.bits=NULL;
1800   }
1801   glyph.metrics.leftSideBearing=0;
1802   glyph.metrics.rightSideBearing=0;
1803   glyph.metrics.advanceX=0;
1804   glyph.metrics.advanceY=0;
1805   glyph.metrics.ascent=0;
1806   glyph.metrics.descent=0;
1807   glyph.pFontCacheInfo=NULL;
1808   glyph.bpp=1;
1809 
1810 
1811   /* Assign padding value */
1812   T1_pad=pFontBase->bitmap_pad;
1813   if (pFontBase->endian)
1814     T1_byte=1;
1815   else
1816     T1_byte=0;
1817   T1_wordsize=T1_pad;
1818 
1819   /* Create a region from outline */
1820   area=(struct region *)Interior( (struct segment *)path,
1821 				  WINDINGRULE+CONTINUITY);
1822 
1823   /* fill the glyph-structure */
1824   if (area == NULL){
1825     T1_PrintLog( "T1_FillOutline()", "area=NULL returned by Interior()", T1LOG_WARNING);
1826     T1_errno=1000;
1827     return(NULL);
1828   }
1829   h = area->ymax - area->ymin;
1830   w = area->xmax - area->xmin;
1831 
1832 
1833   paddedW = PAD(w, T1_pad);
1834   if ( (area->xmin > area->xmax) || (area->ymin > area->ymax) ){
1835     /* There was a character like .notdef or space, that didn't
1836        produce any black pixels on the bitmap! -> we return a glyph with
1837        correct metrics and bitmap pointer set to NULL */
1838     sprintf( err_warn_msg_buf,
1839 	     "No black pixels in outline %p", path);
1840     T1_PrintLog( "T1_FillOutline()", err_warn_msg_buf, T1LOG_WARNING);
1841 
1842     glyph.metrics.leftSideBearing  = 0;
1843     glyph.metrics.advanceX   = NEARESTPEL(area->ending.x - area->origin.x);
1844     glyph.metrics.advanceY   = - NEARESTPEL(area->ending.y - area->origin.y);
1845     glyph.metrics.rightSideBearing = 0;
1846     glyph.metrics.descent          = 0;
1847     glyph.metrics.ascent           = 0;
1848     /* make sure to get rid of 'area' before leaving! */
1849     KillRegion (area);
1850     return( &glyph);
1851   }
1852   if (h > 0 && w > 0) {
1853     memsize = h * paddedW / 8 + 1;
1854     /* This is for the users copy of the character, for security-reasons
1855        the original pointer to the cache area is not used. The entry glyph.bits
1856        is free'ed every time this function is called: */
1857     glyph.bits = (char *)malloc(memsize*sizeof( char));
1858     if (glyph.bits == NULL){
1859       T1_errno=T1ERR_ALLOC_MEM;
1860       /* make sure to get rid of area if it's there */
1861       if (area){
1862 	KillRegion (area);
1863       }
1864       return(NULL);
1865     }
1866 
1867   }
1868   else {
1869     h = w = 0;
1870     area->xmin = area->xmax = 0;
1871     area->ymin = area->ymax = 0;
1872   }
1873 
1874   glyph.metrics.leftSideBearing  = area->xmin;
1875   glyph.metrics.advanceX   = NEARESTPEL(area->ending.x - area->origin.x);
1876   glyph.metrics.advanceY   = - NEARESTPEL(area->ending.y - area->origin.y);
1877   glyph.metrics.rightSideBearing = area->xmax;
1878   glyph.metrics.descent          = - area->ymax;
1879   glyph.metrics.ascent           = - area->ymin;
1880 
1881 
1882   if (h > 0 && w > 0) {
1883     (void) memset(glyph.bits, 0, memsize);
1884     fill(glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize );
1885   }
1886 
1887   /* Check for writing direction and re-compute dimensions appropriately: */
1888   if (modflag & T1_RIGHT_TO_LEFT){
1889     glyph.metrics.advanceX *= -1;
1890     glyph.metrics.advanceY *= -1;
1891     glyph.metrics.leftSideBearing += glyph.metrics.advanceX;
1892     glyph.metrics.rightSideBearing += glyph.metrics.advanceX;
1893     glyph.metrics.descent += glyph.metrics.advanceY;
1894     glyph.metrics.ascent += glyph.metrics.advanceY;
1895   }
1896 
1897   /* make sure to get rid of area if it's there */
1898   if (area){
1899     KillRegion (area);
1900   }
1901   return( &glyph);
1902 
1903 
1904 }
1905