1 /*--------------------------------------------------------------------------
3 ----- Author: Rainer Menzner (Rainer.Menzner@web.de)
5 ----- Description: This file is part of the t1-library. It contains
6 functions for setting characters and strings of
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
16 The parseAFM-package is copyrighted by Adobe Systems
18 The type1 rasterizer is copyrighted by IBM and the
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
26 Thanks to all people who make free software living!
27 --------------------------------------------------------------------------*/
33 #include <sys/types.h>
38 # include <sys/types.h>
39 # include <sys/stat.h>
48 #include "../type1/ffilest.h"
49 #include "../type1/types.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"
69 #define T1_AA_TYPE16 short
72 #define T1_AA_TYPE32 int
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
,
83 int *startx
, int *endx
,
84 int *starty
, int *endy
);
88 static int T1_bit
=T1GLYPH_BIT
;
91 static int T1_wordsize
;
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
)
106 if ((j
=((value
)>>i
)&0x01))
116 static void bin_dump_s(unsigned short value
, char space_flag
)
120 if (T1_CheckEndian()){
122 if ((j
=((value
)>>i
)&0x01))
128 if ((j
=((value
)>>i
)&0x01))
136 if ((j
=((value
)>>i
)&0x01))
147 static void bin_dump_l(unsigned long value
, char space_flag
)
151 if (T1_CheckEndian()){
152 for (i
=24;i
<=31;i
++){
153 if ((j
=((value
)>>i
)&0x01))
158 for (i
=16;i
<=23;i
++){
159 if ((j
=((value
)>>i
)&0x01))
165 if ((j
=((value
)>>i
)&0x01))
171 if ((j
=((value
)>>i
)&0x01))
179 if ((j
=((value
)>>i
)&0x01))
192 /* T1_SetChar(...): Generate the bitmap for a character */
193 GLYPH
*T1_SetChar( int FontID
, char charcode
, float size
,
194 T1_TMATRIX
*transform
)
199 struct XYspace
*Current_S
;
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;
214 /* We don't implement underlining for characters, but the rasterer
215 implements it. Thus, we use a modflag of constant 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
,
231 ucharcode
=(unsigned char)charcode
;
234 /* Reset character glyph, if necessary */
235 if (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
;
248 /* First, check for a correct ID */
249 i
=T1_CheckForFontID(FontID
);
251 T1_errno
=T1ERR_INVALID_FONTID
;
254 /* if necessary load font into memory */
256 if (T1_LoadFont(FontID
))
259 /* Check for valid size */
261 T1_errno
=T1ERR_INVALID_PARAMETER
;
265 /* Assign padding value */
266 T1_pad
=pFontBase
->bitmap_pad
;
267 if (pFontBase
->endian
)
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 */
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 */
296 strokewidth
= pFontBase
->pFontArray
[FontID
].StrokeWidth
;
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 */
309 /* font is now loaded into memory =>
311 if ((font_ptr
=T1int_QueryFontSize( FontID
, size
, NO_ANTIALIAS
))==NULL
){
312 font_ptr
=T1int_CreateNewFontSize( FontID
, size
, NO_ANTIALIAS
);
314 T1_errno
=T1ERR_ALLOC_MEM
;
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
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
),
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
;
337 memcpy( glyph
.bits
, font_ptr
->pFontCache
[ucharcode
].bits
, memsize
);
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. */
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
));
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 */
364 area
=fontfcnB( FontID
, modflag
, Current_S
,
365 fontarrayP
->pFontEnc
,
367 fontarrayP
->pType1Data
,
370 KillSpace (Current_S
);
372 /* fill the glyph-structure */
374 sprintf( err_warn_msg_buf
, "fontfcnB() set mode=%d", mode
);
375 T1_PrintLog( "T1_SetChar()", err_warn_msg_buf
, T1LOG_WARNING
);
380 T1_PrintLog( "T1_SetChar()", "area=NULL returned by fontfcnB()", T1LOG_WARNING
);
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",
391 T1_PrintLog( "T1_SetChar()", err_warn_msg_buf
, T1LOG_WARNING
);
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! */
412 area
->xmin
= area
->xmax
= 0;
413 area
->ymin
= area
->ymax
= 0;
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! */
433 /* Cache glyph if requested, also if it contains only white space */
435 /* Copy glyph to cache but be careful not to modify the pixmap
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
;
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
;
454 /* ... and copy bitmap to cache area: */
455 memcpy( font_ptr
->pFontCache
[ucharcode
].bits
, glyph
.bits
, memsize
);
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
;
473 /* initialize this to NULL just to be on the safe side */
474 struct region
*area
= NULL
;
475 struct XYspace
*Current_S
, *S
;
477 volatile int rot_flag
=0;
478 int *kern_pairs
; /* use for accessing the kern pairs if kerning is
480 int no_chars
=0; /* The number of characters in the string */
481 static int lastno_chars
=0;
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;
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
;
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
;
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};
519 /* The following are for bitmap blitting */
523 unsigned T1_AA_TYPE16 BitBuf_c
;
525 unsigned char *Target_c
;
527 unsigned T1_AA_TYPE32 BitBuf_s
;
528 unsigned T1_AA_TYPE16
*p_s
;
529 unsigned T1_AA_TYPE16
*Target_s
;
532 unsigned T1_AA_TYPE64 BitBuf_l
;
533 unsigned T1_AA_TYPE32
*p_l
;
534 unsigned T1_AA_TYPE32
*Target_l
;
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
,
549 /* force string elements into unsigned */
550 ustring
=(unsigned char*)string
;
553 /* Check for valid string */
555 T1_errno
=T1ERR_INVALID_PARAMETER
;
559 /* Reorganize if required */
560 if (modflag
& T1_RIGHT_TO_LEFT
){
568 r2lstring
=(unsigned char *)malloc( (i
+1)*sizeof(char));
573 r2lstring
[j
-i
]=ustring
[i
];
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
;
594 /* We don't want to cache the resulting bitmap: */
597 /* First, check for a correct ID */
598 i
=T1_CheckForFontID(FontID
);
600 T1_errno
=T1ERR_INVALID_FONTID
;
604 /* if necessary load font into memory */
606 if (T1_LoadFont(FontID
))
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
;
615 /* Check for valid size */
617 T1_errno
=T1ERR_INVALID_PARAMETER
;
621 /* Assign padding value */
622 T1_pad
=pFontBase
->bitmap_pad
;
623 if (pFontBase
->endian
)
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 */
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 */
648 strokewidth
= pFontBase
->pFontArray
[FontID
].StrokeWidth
;
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 */
661 /* font is now loaded into memory =>
663 if ((font_ptr
=T1int_QueryFontSize( FontID
, size
, NO_ANTIALIAS
))==NULL
){
664 font_ptr
=T1int_CreateNewFontSize( FontID
, size
, NO_ANTIALIAS
);
666 T1_errno
=T1ERR_ALLOC_MEM
;
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
;
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 */
684 /* If necessary, allocate memory */
685 if (no_chars
>lastno_chars
){
686 if (pixel_h_anchor_corr
!=NULL
){
687 free(pixel_h_anchor_corr
);
692 pixel_h_anchor_corr
=(int *)calloc(no_chars
, sizeof(int));
693 flags
=(int *)calloc(no_chars
, sizeof(int));
694 lastno_chars
=no_chars
;
697 /* Reset flags and position array */
698 for (i
=0; i
<no_chars
; i
++){
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. */
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
));
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
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
735 /* First, ensure that all needed characters are in the Cache; if not,
737 if ( (rot_flag
==0) && (strokeextraflag
==0) ){
739 for (i
=0; i
<no_chars
; i
++) {
740 currchar
= &(font_ptr
->pFontCache
[ustring
[i
]]);
741 if (currchar
->bpp
<1) {
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
,
750 fontarrayP
->pType1Data
,
754 /* fill the glyph-structure */
756 sprintf( err_warn_msg_buf
, "fontfcnB() set mode=%d", mode
);
757 T1_PrintLog( "T1_SetString()", err_warn_msg_buf
, T1LOG_WARNING
);
759 /* Make sure to free the region if it's non-NULL */
766 T1_PrintLog( "T1_SetString()", "area=NULL returned by fontfcnB()", T1LOG_WARNING
);
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
);
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 */
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
;
808 /* By this point, it's clear that the 'area' struct exists,
809 and that we no longer need it, so free it up. */
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! */
823 /* These are the initial values for left and right sidebearing */
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!",
853 T1_PrintLog( "T1_SetString()", err_warn_msg_buf
,
858 /* value to add to hanchor */
859 h_anchor
+=NEARESTPEL(area
->ending
.x
);
860 /* make sure to free S */
864 /* make sure to free area */
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
,
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
,
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
,
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: */
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
989 string_glyph
.bits
= (char *)malloc( memsize
);
990 if (string_glyph
.bits
== NULL
) {
991 T1_errno
=T1ERR_ALLOC_MEM
;
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
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 */
1027 BitShift
= pixel_h_anchor_corr
[i
] % 8;
1028 ByteOffset
= pixel_h_anchor_corr
[i
] / 8;
1031 BitShift
= pixel_h_anchor_corr
[i
] % T1_pad
;
1032 ByteOffset
= pixel_h_anchor_corr
[i
] / T1_pad
;
1035 else if (T1_pad
==16)
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)
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
++;
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) */
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)
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
++;
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)
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
));
1094 for (k
=char_paddedW
>> 3; k
; k
--)
1095 *Target_c
++ |= *p_c
++;
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)
1129 *Target_c
++ |= startmask
& endmask
;
1131 *Target_c
++ |= startmask
;
1133 *Target_c
++ = (unsigned char) 0xFF;
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)
1157 *Target_c
++ |= startmask
& endmask
;
1159 *Target_c
++ |= startmask
;
1161 *Target_c
++ = (unsigned char) 0xFF;
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)
1185 *Target_c
++ |= startmask
& endmask
;
1187 *Target_c
++ |= startmask
;
1189 *Target_c
++ = (unsigned char) 0xFF;
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 */
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
,
1221 KillSpace (Current_S
);
1223 /* In all cases, free memory for kerning pairs */
1226 /* fill the string_glyph-structure */
1228 sprintf( err_warn_msg_buf
, "fontfcnB() set mode=%d", mode
);
1229 T1_PrintLog( "T1_SetString()", err_warn_msg_buf
, T1LOG_WARNING
);
1231 /* make sure to get rid of area if it's there */
1238 T1_PrintLog( "T1_SetString()", "area=NULL returned by fontfcnB()", T1LOG_WARNING
);
1243 if (mode
== FF_NOTDEF_SUBST
) {
1244 sprintf( err_warn_msg_buf
,
1245 "\".notdef\" substituted somewhere in string from font %d",
1247 T1_PrintLog( "T1_SetString()", err_warn_msg_buf
, T1LOG_WARNING
);
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 */
1266 /* it's safe to free this, since this is a rotated glyph and
1267 therefore it's a copy of the original one */
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 */
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
);
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) {
1350 printf("Reorganizing data ..\n");
1355 register unsigned short data,*p;
1356 p = (unsigned short *) dest;
1357 for (i = h * w /16; --i >= 0;) {
1359 *p++ = (data << 8) + (data >> 8);
1366 register ULONG data,*p;
1368 for (i = h * w / 32; --i >= 0;) {
1370 *p++ = (data << 24) + (data >> 24)
1371 + (0xFF00 & (data >> 8))
1372 + (0xFF0000 & (data << 8));
1374 if (wordsize == 64) {
1376 for (i = h * w / 64; --i >= 0;) {
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 */
1400 middle
= x1
/8 - x0
/8;
1403 if (bit
== LSBFirst
) {
1404 startmask
= ALLONES
<< x0
;
1405 endmask
= ~(ALLONES
<< x1
);
1408 startmask
= ALLONES
>> x0
;
1409 endmask
= ~(ALLONES
>> x1
);
1412 *p
++ |= startmask
& endmask
;
1415 while (--middle
> 0){
1416 *p
++ = (unsigned char)ALLONES
;
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
);
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
)
1471 T1_errno
=T1ERR_INVALID_PARAMETER
;
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
;
1483 /* Copy the structure members: */
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
){
1494 T1_errno
=T1ERR_ALLOC_MEM
;
1497 memcpy(dest
->bits
,glyph
->bits
,size
);
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 */
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
);
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
++){
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);
1532 for (j
=0; j
<paddedW
/T1_pad
; j
++){
1533 bin_dump_l(((unsigned long *)glyph
->bits
)[i
*paddedW
/T1_pad
+j
], 1);
1541 /* This function will essentially return the bounding box of the
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
;
1577 (int) floor(*starty
*pFontBase
->pFontArray
[FontID
].slant
+0.5);
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 */
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
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 */
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
){
1637 T1_errno
=T1ERR_INVALID_PARAMETER
;
1641 T1_errno
=T1ERR_INVALID_PARAMETER
;
1644 if (glyph1
->bpp
!= glyph2
->bpp
){
1645 T1_errno
=T1ERR_INVALID_PARAMETER
;
1649 /* We have two glyph different from NULL */
1650 /* Reset glyph, if necessary */
1651 if (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
;
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
;
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
;
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
)
1707 p_l
= (unsigned T1_AA_TYPE32
*)(glyph1
->bits
+(wscanline1
*i
));
1709 for (k
=wscanline1
/4; k
; k
--)
1710 *Target_l
++ |= *p_l
++;
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
)
1727 p_l
= (unsigned T1_AA_TYPE32
*)(glyph2
->bits
+(wscanline2
*i
));
1729 for (k
=wscanline2
/4; k
; k
--)
1730 *Target_l
++ |= *p_l
++;
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
)
1749 p_s
= (unsigned T1_AA_TYPE16
*)(glyph1
->bits
+(wscanline1
*i
));
1751 for (k
=wscanline1
/2; k
; k
--)
1752 *Target_s
++ |= *p_s
++;
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
)
1769 p_s
= (unsigned T1_AA_TYPE16
*)(glyph2
->bits
+(wscanline2
*i
));
1771 for (k
=wscanline2
/2; k
; k
--)
1772 *Target_s
++ |= *p_s
++;
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
)
1791 p_c
= (unsigned char *)(glyph1
->bits
+(wscanline1
*i
));
1793 for (k
=wscanline1
; k
; k
--)
1794 *Target_c
++ |= *p_c
++;
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
)
1811 p_c
= (unsigned char *)(glyph2
->bits
+(wscanline2
*i
));
1813 for (k
=wscanline2
; k
; k
--)
1814 *Target_c
++ |= *p_c
++;
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) ... */
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
)
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
)
1849 } /* end of if (bpp==8) ... */
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
)
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
)
1873 } /* end of if (bpp==16) ... */
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
)
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
)
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
;
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
;
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 );
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;
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
,
1958 /* Reset character glyph, if necessary */
1959 if (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
;
1973 /* Assign padding value */
1974 T1_pad
=pFontBase
->bitmap_pad
;
1975 if (pFontBase
->endian
)
1981 /* Create a region from outline */
1982 area
=(struct region
*)Interior( (struct segment
*)path
,
1983 WINDINGRULE
+CONTINUITY
);
1985 /* fill the glyph-structure */
1987 T1_PrintLog( "T1_FillOutline()", "area=NULL returned by Interior()", T1LOG_WARNING
);
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! */
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 */
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 */
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
)
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;
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
,
2102 /* Reset character glyph, if necessary */
2103 if (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
;
2116 /* First, check for a correct ID. */
2117 i
=T1_CheckForFontID(FontID
);
2121 /* if necessary load font into memory */
2123 if ( T1_LoadFont( FontID
) )
2126 /* Check for valid size */
2128 T1_errno
=T1ERR_INVALID_PARAMETER
;
2132 /* Assign padding value */
2133 T1_pad
=pFontBase
->bitmap_pad
;
2134 if (pFontBase
->endian
)
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
;
2153 /* handle stroking stuff */
2154 if ( fontarrayP
->info_flags
& RASTER_STROKED
) {
2155 strokewidth
= pFontBase
->pFontArray
[FontID
].StrokeWidth
;
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
));
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
));
2186 area
=fontfcnRect( width
,
2192 KillSpace (Current_S
);
2194 /* fill the glyph-structure */
2196 sprintf( err_warn_msg_buf
, "fontfcnRect() set mode=%d", mode
);
2197 T1_PrintLog( "T1_SetRect()", err_warn_msg_buf
, T1LOG_WARNING
);
2201 if ( area
== NULL
) {
2202 T1_PrintLog( "T1_SetRect()", "area=NULL returned by fontfcnRect()", T1LOG_WARNING
);
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! */
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! */