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