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