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