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