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)
1126
*Target_c++ |= startmask & endmask;
1128
*Target_c++ |= startmask;
1130
*Target_c++ = (unsigned char) 0xFF;
1132
*Target_c |= endmask;
1136
/* Put an overstrike rule on the glyph */
1137
if (modflag & T1_OVERSTRIKE){
1138
start=-string_glyph.metrics.leftSideBearing;
1139
for (i=string_glyph.metrics.ascent-overstrike_starty;
1140
i<string_glyph.metrics.ascent-overstrike_endy; i++){
1141
start =-string_glyph.metrics.leftSideBearing +
1142
(int) floor((double)(string_glyph.metrics.ascent-i)
1143
*fontarrayP->slant+0.5);
1144
middle = ((start+string_glyph.metrics.advanceX) / 8) - (start / 8);
1145
startmask = 0xFF << (start % 8);
1146
endmask = (char) ~(0xFF << ((start+string_glyph.metrics.advanceX) % 8));
1147
Target_c= (unsigned char *)(string_glyph.bits +(i*paddedW/8)
1151
*Target_c++ |= startmask & endmask;
1153
*Target_c++ |= startmask;
1155
*Target_c++ = (unsigned char) 0xFF;
1157
*Target_c |= endmask;
1161
/* Put an overline rule */
1162
if (modflag & T1_OVERLINE){
1163
start=-string_glyph.metrics.leftSideBearing;
1164
for (i=string_glyph.metrics.ascent-overline_starty;
1165
i<string_glyph.metrics.ascent-overline_endy; i++){
1166
start =-string_glyph.metrics.leftSideBearing +
1167
(int) floor((double)(string_glyph.metrics.ascent-i)
1168
*fontarrayP->slant+0.5);
1169
middle = ((start+string_glyph.metrics.advanceX) / 8) - (start / 8);
1170
startmask = 0xFF << (start % 8);
1171
endmask = (char) ~(0xFF << ((start+string_glyph.metrics.advanceX) % 8));
1172
Target_c= (unsigned char *)(string_glyph.bits +(i*paddedW/8)
1176
*Target_c++ |= startmask & endmask;
1178
*Target_c++ |= startmask;
1180
*Target_c++ = (unsigned char) 0xFF;
1182
*Target_c |= endmask;
1187
/* Check for writing direction and re-compute dimensions appropriately: */
1188
if (modflag & T1_RIGHT_TO_LEFT){
1189
string_glyph.metrics.advanceX *= -1;
1190
string_glyph.metrics.leftSideBearing += string_glyph.metrics.advanceX;
1191
string_glyph.metrics.rightSideBearing += string_glyph.metrics.advanceX;
1194
return(&string_glyph);
1195
} /* end of "if (rot_flag==0.0)" */
1198
/* fnt_ptr now points to the correct FontSizeDeps-struct =>
1199
lets now raster the character */
1201
kern_pairs=(int *)calloc(no_chars, sizeof(int));
1202
if ((modflag & T1_KERNING))
1203
for (i=0; i<no_chars -1; i++)
1204
kern_pairs[i]=T1_GetKerning( FontID, ustring[i], ustring[i+1]);
1205
area=fontfcnB_string( FontID, modflag, Current_S,
1206
fontarrayP->pFontEnc,
1207
ustring, no_chars, &mode,
1208
fontarrayP->pType1Data,
1209
kern_pairs, spacewidth,
1212
KillSpace (Current_S);
1214
/* In all cases, free memory for kerning pairs */
1217
/* fill the string_glyph-structure */
1219
sprintf( err_warn_msg_buf, "fontfcnB() set mode=%d", mode);
1220
T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING);
1222
/* make sure to get rid of area if it's there */
1229
T1_PrintLog( "T1_SetString()", "area=NULL returned by fontfcnB()", T1LOG_WARNING);
1234
if (mode == FF_NOTDEF_SUBST) {
1235
sprintf( err_warn_msg_buf,
1236
"\".notdef\" substituted somewhere in string from font %d",
1238
T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING);
1242
h = area->ymax - area->ymin;
1243
w = area->xmax - area->xmin;
1244
paddedW = PAD(w, T1_pad);
1245
if (h > 0 && w > 0) {
1246
memsize = h * paddedW / 8 + 1;
1247
/* This is for the users copy of the character, for security-reasons
1248
the original pointer to the cache area is not used. The entry string_glyph.bits
1249
is free'ed every time this function is called: */
1250
string_glyph.bits = (char *)malloc(memsize*sizeof( char));
1251
if (string_glyph.bits == NULL) {
1252
T1_errno=T1ERR_ALLOC_MEM;
1253
/* make sure to get rid of area if it's there */
1257
/* it's safe to free this, since this is a rotated glyph and
1258
therefore it's a copy of the original one */
1264
area->xmin = area->xmax = 0;
1265
area->ymin = area->ymax = 0;
1268
string_glyph.metrics.leftSideBearing=area->xmin;
1269
string_glyph.metrics.advanceX=NEARESTPEL(area->ending.x - area->origin.x);
1270
string_glyph.metrics.advanceY=-NEARESTPEL(area->ending.y - area->origin.y);
1271
string_glyph.metrics.rightSideBearing=area->xmax;
1272
string_glyph.metrics.descent=-area->ymax;
1273
string_glyph.metrics.ascent=-area->ymin;
1275
if (h > 0 && w > 0) {
1276
(void) memset(string_glyph.bits, 0, memsize);
1277
fill(string_glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize );
1279
else { /* We have no black pixels */
1280
string_glyph.metrics.leftSideBearing=0;
1281
string_glyph.metrics.advanceX=NEARESTPEL(area->ending.x - area->origin.x);
1282
string_glyph.metrics.advanceY=-NEARESTPEL(area->ending.y - area->origin.y);
1283
string_glyph.metrics.rightSideBearing=0;
1284
string_glyph.metrics.descent=0;
1285
string_glyph.metrics.ascent=0;
1289
/* make sure to get rid of area if it's there */
1293
/* Check for writing direction and re-compute dimensions appropriately: */
1294
if (modflag & T1_RIGHT_TO_LEFT){
1295
string_glyph.metrics.advanceX *= -1;
1296
string_glyph.metrics.advanceY *= -1;
1297
string_glyph.metrics.leftSideBearing += string_glyph.metrics.advanceX;
1298
string_glyph.metrics.rightSideBearing += string_glyph.metrics.advanceX;
1299
string_glyph.metrics.descent += string_glyph.metrics.advanceY;
1300
string_glyph.metrics.ascent += string_glyph.metrics.advanceY;
1302
return(&string_glyph);
1307
void fill(dest, h, w, area, byte, bit, wordsize)
1308
register char *dest; /* destination bitmap */
1309
int h,w; /* dimensions of 'dest', w padded */
1310
register struct region *area; /* region to write to 'dest' */
1311
int byte,bit; /* flags; LSBFirst or MSBFirst */
1312
int wordsize; /* number of bits per word for LSB/MSB purposes */
1314
register struct edgelist *edge; /* for looping through edges */
1315
register char *p; /* current scan line in 'dest' */
1316
register int y; /* for looping through scans */
1317
register int wbytes = w / 8; /* number of bytes in width */
1318
register pel *leftP,*rightP; /* pointers to X values, left and right */
1319
int xmin = area->xmin; /* upper left X */
1320
int ymin = area->ymin; /* upper left Y */
1322
for (edge = area->anchor; VALIDEDGE(edge); edge = edge->link->link) {
1324
p = dest + (edge->ymin - ymin) * wbytes;
1325
leftP = edge->xvalues;
1326
rightP = edge->link->xvalues;
1328
for (y = edge->ymin; y < edge->ymax; y++) {
1329
fillrun(p, *leftP++ - xmin , *rightP++ - xmin, bit);
1334
Now, as an afterthought, we'll go reorganize if odd byte order requires
1337
/* We do not reorganize since t1lib internally always uses LSBFirst */
1339
if ( 0 && wordsize != 8) {
1341
printf("Reorganizing data ..\n");
1346
register unsigned short data,*p;
1347
p = (unsigned short *) dest;
1348
for (i = h * w /16; --i >= 0;) {
1350
*p++ = (data << 8) + (data >> 8);
1357
register ULONG data,*p;
1359
for (i = h * w / 32; --i >= 0;) {
1361
*p++ = (data << 24) + (data >> 24)
1362
+ (0xFF00 & (data >> 8))
1363
+ (0xFF0000 & (data << 8));
1365
if (wordsize == 64) {
1367
for (i = h * w / 64; --i >= 0;) {
1376
abort("xiFill: unknown format");
1382
#define ALLONES 0xFF
1384
void fillrun(register char *p, pel x0, pel x1, int bit)
1386
register int startmask,endmask; /* bits to set in first and last char*/
1387
register int middle; /* number of chars between start and end + 1 */
1391
middle = x1/8 - x0/8;
1394
if (bit == LSBFirst) {
1395
startmask = ALLONES << x0;
1396
endmask = ~(ALLONES << x1);
1399
startmask = ALLONES >> x0;
1400
endmask = ~(ALLONES >> x1);
1403
*p++ |= startmask & endmask;
1406
while (--middle > 0){
1407
*p++ = (unsigned char)ALLONES;
1416
#undef CHECK_OUTLINEFILL
1417
#ifdef CHECK_OUTLINEFILL
1418
void fill(dest, h, w, area, byte, bit, wordsize)
1419
register char *dest; /* destination bitmap */
1420
int h,w; /* dimensions of 'dest', w padded */
1421
register struct region *area; /* region to write to 'dest' */
1422
int byte,bit; /* flags; LSBFirst or MSBFirst */
1423
int wordsize; /* number of bits per word for LSB/MSB purposes */
1425
register struct edgelist *edge; /* for looping through edges */
1426
register char *p; /* current scan line in 'dest' */
1427
register int y; /* for looping through scans */
1428
register int wbytes = w / 8; /* number of bytes in width */
1429
register pel *leftP,*rightP; /* pointers to X values, left and right */
1430
int xmin = area->xmin; /* upper left X */
1431
int ymin = area->ymin; /* upper left Y */
1433
for (edge = area->anchor; VALIDEDGE(edge); edge = edge->link->link) {
1435
p = dest + (edge->ymin - ymin) * wbytes;
1436
leftP = edge->xvalues;
1437
rightP = edge->link->xvalues;
1439
printf("leftP=%d, RightP=%d,\n", *leftP, *rightP);
1442
for (y = edge->ymin; y < edge->ymax; y++) {
1443
printf("leftP=%d, RightP=%d,y=%d\n", *leftP, *rightP, y);
1445
fillrun(p, *leftP++ - xmin, *rightP++ - xmin, bit);
1453
/* T1_CopyGlyph(): Make a copy of an existent glyph-structure to save it
1454
for later usage by the user. */
1455
GLYPH *T1_CopyGlyph( GLYPH *glyph)
1462
T1_errno=T1ERR_INVALID_PARAMETER;
1466
/* Assign padding value */
1467
T1_pad=pFontBase->bitmap_pad;
1468
/* Allocate memory for struct: */
1469
if ((dest=(GLYPH *)malloc(sizeof(GLYPH)))==NULL){
1470
T1_errno=T1ERR_ALLOC_MEM;
1474
/* Copy the structure members: */
1476
/* Allocate memory for bitmap, initialize pointer to it and copy bitmap: */
1477
size=PAD((dest->metrics.rightSideBearing-dest->metrics.leftSideBearing)*
1478
glyph->bpp, T1_pad) / 8;
1479
size=size*(dest->metrics.ascent-dest->metrics.descent);
1480
/* We must check whether there's actually a bits-pointer different from
1481
NULL. If not omit the following step: */
1482
if (glyph->bits!=NULL){
1483
if ((dest->bits=(char *)malloc(size*sizeof(char)))==NULL){
1485
T1_errno=T1ERR_ALLOC_MEM;
1488
memcpy(dest->bits,glyph->bits,size);
1493
/* T1_DumpGlyph(): Dump a glyph-representation to stdout: */
1494
void T1_DumpGlyph( GLYPH *glyph)
1496
int i,j,h,w; /* i=line-index, j=column-index */
1500
printf("Dataformat: T1_bit=%d, T1_byte=%d, T1_wordsize=%d, T1_pad=%d\n",
1501
T1_bit, T1_byte, T1_pad, T1_pad);
1507
h=glyph->metrics.ascent-glyph->metrics.descent;
1508
w=glyph->metrics.rightSideBearing-glyph->metrics.leftSideBearing;
1510
paddedW=PAD(w,T1_pad);
1512
printf("GlyphInfo: h=%d, w=%d, paddedW=%ld\n", h, w, paddedW);
1514
for ( i=0; i<h; i++){
1516
for (j=0; j<paddedW/T1_pad; j++)
1517
bin_dump_c(glyph->bits[i*paddedW/T1_pad+j], 1);
1518
else if (T1_pad==16)
1519
for (j=0; j<paddedW/T1_pad; j++){
1520
bin_dump_s(((unsigned short *)glyph->bits)[i*paddedW/T1_pad+j], 1);
1523
for (j=0; j<paddedW/T1_pad; j++){
1524
bin_dump_l(((unsigned long *)glyph->bits)[i*paddedW/T1_pad+j], 1);
1532
/* This function will essentially return the bounding box of the
1534
static void T1_ComputeLineParameters( int FontID, int mode,
1535
int width, float size,
1536
int *startx, int *endx,
1537
int *starty, int *endy)
1539
float position=0.0, thickness=0.0;
1540
int startx1, startx2, endx1, endx2;
1542
if (mode & T1_UNDERLINE){
1543
position=pFontBase->pFontArray[FontID].UndrLnPos
1544
* DeviceSpecifics.scale_y;
1545
thickness=pFontBase->pFontArray[FontID].UndrLnThick
1546
* DeviceSpecifics.scale_y;
1548
else if (mode & T1_OVERLINE){
1549
position=pFontBase->pFontArray[FontID].OvrLnPos
1550
* DeviceSpecifics.scale_y;
1551
thickness=pFontBase->pFontArray[FontID].OvrLnThick
1552
* DeviceSpecifics.scale_y;
1554
else if (mode & T1_OVERSTRIKE){
1555
position=pFontBase->pFontArray[FontID].OvrStrkPos
1556
* DeviceSpecifics.scale_y;
1557
thickness=pFontBase->pFontArray[FontID].OvrStrkThick
1558
* DeviceSpecifics.scale_y;
1561
*starty=(int) floor((position+0.5*(thickness-DeviceSpecifics.y_resolution/1000.0))
1562
*size/1000.0 +0.5 );
1563
startx1=(int) floor(*starty*pFontBase->pFontArray[FontID].slant+0.5);
1564
*endy =*starty - (int) floor(thickness/1000.0*size+0.5);
1565
startx2=(int) floor(*endy*pFontBase->pFontArray[FontID].slant+0.5);
1566
*startx=startx1 < startx2 ? startx1 : startx2;
1568
(int) floor(*starty*pFontBase->pFontArray[FontID].slant+0.5);
1570
(int) floor(*endy*pFontBase->pFontArray[FontID].slant+0.5);
1571
*endx=endx1 < endx2 ? endx2 : endx1;
1573
/* We take care that at least one pixel is drawn */
1583
/* The following function concatenates two glyphs. Optional offsets
1584
x_off, y_off are respected. By the function.
1585
If either glyph is NULL or the glyphs have distinct depth, NULL is
1587
GLYPH *T1_ConcatGlyphs( GLYPH *glyph_1, GLYPH *glyph_2,
1588
int x_off, int y_off, int modflag)
1591
int lsb1, lsb2, rsb1, rsb2;
1592
int advanceX1, advanceX2, advanceY1, advanceY2;
1593
int ascent1, ascent2, descent1, descent2;
1594
int rsb, lsb, ascent, descent, advanceX, advanceY;
1595
int vanchor, w, h, wscanline, wscanline1, wscanline2, bpp;
1596
int memsize, BitShift;
1597
GLYPH *glyph1, *glyph2;
1598
unsigned T1_AA_TYPE16 BitBuf_c;
1599
unsigned T1_AA_TYPE32 BitBuf_s;
1600
unsigned long BitBuf_l; /* This is only actually used if sizeof long = 8 */
1604
unsigned char *Target_c, *p_c;
1605
unsigned T1_AA_TYPE16 *Target_s, *p_s;
1606
unsigned T1_AA_TYPE32 *Target_l, *p_l;
1608
static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1};
1611
/* We handle the Right-To-Left concatenation the simple way:
1612
1) Change the order of the two glyphs
1613
2) Invert the sign of the y-part of the offset
1614
3) Recalculate the dimensions of the resulating glyph.
1616
/* Check for writing direction and reorganize appropriately: */
1617
if (modflag & T1_RIGHT_TO_LEFT){
1628
T1_errno=T1ERR_INVALID_PARAMETER;
1632
T1_errno=T1ERR_INVALID_PARAMETER;
1635
if (glyph1->bpp != glyph2->bpp){
1636
T1_errno=T1ERR_INVALID_PARAMETER;
1640
/* We have two glyph different from NULL */
1641
/* Reset glyph, if necessary */
1642
if (glyph.bits!=NULL){
1646
glyph.metrics.leftSideBearing=0;
1647
glyph.metrics.rightSideBearing=0;
1648
glyph.metrics.advanceX=0;
1649
glyph.metrics.advanceY=0;
1650
glyph.metrics.ascent=0;
1651
glyph.metrics.descent=0;
1652
glyph.pFontCacheInfo=NULL;
1656
lsb1=glyph1->metrics.leftSideBearing;
1657
rsb1=glyph1->metrics.rightSideBearing;
1658
ascent1=glyph1->metrics.ascent;
1659
descent1=glyph1->metrics.descent;
1660
advanceX1=glyph1->metrics.advanceX + x_off;
1661
advanceY1=glyph1->metrics.advanceY + y_off;
1663
lsb2=glyph2->metrics.leftSideBearing;
1664
rsb2=glyph2->metrics.rightSideBearing;
1665
ascent2=glyph2->metrics.ascent;
1666
descent2=glyph2->metrics.descent;
1667
advanceX2=glyph2->metrics.advanceX;
1668
advanceY2=glyph2->metrics.advanceY;
1670
lsb=lsb1 < lsb2+advanceX1 ? lsb1 : lsb2+advanceX1;
1671
rsb=rsb1 > rsb2+advanceX1 ? rsb1 : rsb2+advanceX1;
1672
ascent=ascent1 > ascent2+advanceY1 ? ascent1 : ascent2+advanceY1;
1673
descent=descent1 < descent2+advanceY1 ? descent1 : descent2+advanceY1;
1674
advanceX=advanceX1+advanceX2;
1675
advanceY=advanceY1+advanceY2;
1680
wscanline=PAD( w*bpp, T1_pad) / 8;
1681
wscanline1=PAD( (rsb1-lsb1)*bpp, T1_pad) / 8;
1682
wscanline2=PAD( (rsb2-lsb2)*bpp, T1_pad) / 8;
1683
memsize=wscanline*h;
1684
if ((glyph.bits=(char *)calloc( memsize + 1, sizeof(unsigned char)))==NULL){
1685
T1_errno=T1ERR_ALLOC_MEM;
1690
if (T1_pad==32 && T1_byte==0 && sizeof(long)==8){
1691
/* The following loop steps through the lines of the first glyph: */
1692
vanchor=ascent-ascent1;
1693
BitShift=(lsb1-lsb) % 32;
1694
ByteOffset=(lsb1-lsb)/32*4;
1695
for ( i=0; i<ascent1-descent1; i++){
1696
Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
1698
p_l = (unsigned T1_AA_TYPE32 *)(glyph1->bits+(wscanline1*i));
1700
for (k=wscanline1/4; k; k--)
1701
*Target_l++ |= *p_l++;
1704
for (k=wscanline1/4; k; k--){
1705
BitBuf_l = ((long)*p_l++) << BitShift;
1706
*Target_l++ |= BitBuf_l;
1707
*Target_l |= BitBuf_l>>l_shift;
1711
/* The following loop steps through the lines of the second glyph: */
1712
vanchor=ascent-(ascent2+advanceY1);
1713
BitShift=(lsb2+advanceX1-lsb) % 32;
1714
ByteOffset=(lsb2+advanceX1-lsb)/32*4;
1715
for ( i=0; i<ascent2-descent2; i++){
1716
Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
1718
p_l = (unsigned T1_AA_TYPE32 *)(glyph2->bits+(wscanline2*i));
1720
for (k=wscanline2/4; k; k--)
1721
*Target_l++ |= *p_l++;
1724
for (k=wscanline2/4; k; k--){
1725
BitBuf_l = ((long)*p_l++) << BitShift;
1726
*Target_l++ |= BitBuf_l;
1727
*Target_l |= BitBuf_l>>l_shift;
1732
else if(T1_pad==16 && T1_byte==0){
1733
/* The following loop steps through the lines of the first glyph: */
1734
vanchor=ascent-ascent1;
1735
BitShift=(lsb1-lsb) % 16;
1736
ByteOffset=(lsb1-lsb)/16*2;
1737
for ( i=0; i<ascent1-descent1; i++){
1738
Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
1740
p_s = (unsigned T1_AA_TYPE16 *)(glyph1->bits+(wscanline1*i));
1742
for (k=wscanline1/2; k; k--)
1743
*Target_s++ |= *p_s++;
1746
for (k=wscanline1/2; k; k--){
1747
BitBuf_s = ((T1_AA_TYPE32)*p_s++) << BitShift;
1748
*Target_s++ |= BitBuf_s;
1749
*Target_s |= BitBuf_s>>s_shift;
1753
/* The following loop steps through the lines of the second glyph: */
1754
vanchor=ascent-(ascent2+advanceY1);
1755
BitShift=(lsb2+advanceX1-lsb) % 16;
1756
ByteOffset=(lsb2+advanceX1-lsb)/16*2;
1757
for ( i=0; i<ascent2-descent2; i++){
1758
Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
1760
p_s = (unsigned T1_AA_TYPE16 *)(glyph2->bits+(wscanline2*i));
1762
for (k=wscanline2/2; k; k--)
1763
*Target_s++ |= *p_s++;
1766
for (k=wscanline2/2; k; k--){
1767
BitBuf_s = ((T1_AA_TYPE32)*p_s++) << BitShift;
1768
*Target_s++ |= BitBuf_s;
1769
*Target_s |= BitBuf_s>>s_shift;
1774
else{ /* T1_pad==8 or Big Endian machine */
1775
/* The following loop steps through the lines of the first glyph: */
1776
vanchor=ascent-ascent1;
1777
BitShift=(lsb1-lsb) % 8;
1778
ByteOffset=(lsb1-lsb) / 8;
1779
for ( i=0; i<ascent1-descent1; i++){
1780
Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
1782
p_c = (unsigned char *)(glyph1->bits+(wscanline1*i));
1784
for (k=wscanline1; k; k--)
1785
*Target_c++ |= *p_c++;
1788
for (k=wscanline1; k; k--){
1789
BitBuf_c = ((T1_AA_TYPE16)*p_c++) << BitShift;
1790
*Target_c++ |= BitBuf_c;
1791
*Target_c |= BitBuf_c>>c_shift;
1795
/* The following loop steps through the lines of the second glyph: */
1796
vanchor=ascent-(ascent2+advanceY1);
1797
BitShift=(lsb2+advanceX1-lsb) % 8;
1798
ByteOffset=(lsb2+advanceX1-lsb) / 8;
1799
for ( i=0; i<ascent2-descent2; i++){
1800
Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
1802
p_c = (unsigned char *)(glyph2->bits+(wscanline2*i));
1804
for (k=wscanline2; k; k--)
1805
*Target_c++ |= *p_c++;
1808
for (k=wscanline2; k; k--){
1809
BitBuf_c = ((T1_AA_TYPE16)*p_c++) << BitShift;
1810
*Target_c++ |= BitBuf_c;
1811
*Target_c |= BitBuf_c>>c_shift;
1816
} /* end of if (bpp==1) ... */
1818
/* Set background */
1819
for ( i=0; i<memsize; i++)
1820
((char *)glyph.bits)[i]=(char) T1aa_bg;
1821
/* The following loop steps through the lines of the first glyph: */
1822
vanchor=ascent-ascent1;
1823
for ( i=0; i<ascent1-descent1; i++){
1824
Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
1826
p_c = (unsigned char *)(glyph1->bits+(wscanline1*i));
1827
memcpy( Target_c, p_c, (rsb1-lsb1));
1829
/* The following loop steps through the lines of the second glyph.
1830
Note that we only set the pixel if it is not background! */
1831
vanchor=ascent-(ascent2+advanceY1);
1832
for ( i=0; i<ascent2-descent2; i++){
1833
Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
1834
+(lsb2+advanceX1-lsb));
1835
p_c = (unsigned char *)(glyph2->bits+(wscanline2*i));
1836
for (j=0; j<(rsb2-lsb2); j++)
1837
if (p_c[j] != (unsigned char) T1aa_bg)
1840
} /* end of if (bpp==8) ... */
1842
/* Set background */
1843
for ( i=0; i<memsize/2; i++)
1844
((T1_AA_TYPE16 *)glyph.bits)[i]=(T1_AA_TYPE16) T1aa_bg;
1845
/* The following loop steps through the lines of the first glyph: */
1846
vanchor=ascent-ascent1;
1847
for ( i=0; i<ascent1-descent1; i++){
1848
Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
1850
p_s = (unsigned T1_AA_TYPE16 *)(glyph1->bits+(wscanline1*i));
1851
memcpy( Target_s, p_s, (rsb1-lsb1)*2);
1853
/* The following loop steps through the lines of the second glyph.
1854
Note that we only set the pixel if it is not background! */
1855
vanchor=ascent-(ascent2+advanceY1);
1856
for ( i=0; i<ascent2-descent2; i++){
1857
Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
1858
+(lsb2+advanceX1-lsb)*2);
1859
p_s = (unsigned T1_AA_TYPE16 *)(glyph2->bits+(wscanline2*i));
1860
for (j=0; j<(rsb2-lsb2); j++)
1861
if (p_s[j] != (unsigned T1_AA_TYPE16) T1aa_bg)
1864
} /* end of if (bpp==16) ... */
1866
/* Set background */
1867
for ( i=0; i<memsize/4; i++)
1868
((T1_AA_TYPE32 *)glyph.bits)[i]=(T1_AA_TYPE32) T1aa_bg;
1869
/* The following loop steps through the lines of the first glyph: */
1870
vanchor=ascent-ascent1;
1871
for ( i=0; i<ascent1-descent1; i++){
1872
Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
1874
p_l = (unsigned T1_AA_TYPE32 *)(glyph1->bits+(wscanline1*i));
1875
memcpy( Target_l, p_l, (rsb1-lsb1)*4);
1877
/* The following loop steps through the lines of the second glyph.
1878
Note that we only set the pixel if it is not background! */
1879
vanchor=ascent-(ascent2+advanceY1);
1880
for ( i=0; i<ascent2-descent2; i++){
1881
Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
1882
+(lsb2+advanceX1-lsb)*4);
1883
p_l = (unsigned T1_AA_TYPE32 *)(glyph2->bits+(wscanline2*i));
1884
for (j=0; j<(rsb2-lsb2); j++)
1885
if (p_l[j] != (unsigned T1_AA_TYPE32) T1aa_bg)
1888
} /* end of if (bpp==32) ... */
1891
/* Check for writing direction and re-compute dimens appropriately: */
1892
if (modflag & T1_RIGHT_TO_LEFT){
1893
advanceX=-advanceX1-advanceX2;
1894
advanceY=-advanceY1-advanceY2;
1895
lsb=lsb1 < lsb2+advanceX1 ? advanceX+lsb1 : advanceX+lsb2+advanceX1;
1896
rsb=rsb1 > rsb2+advanceX1 ? advanceX+rsb1 : advanceX+rsb2+advanceX1;
1897
ascent=ascent1 > ascent2+advanceY1 ? ascent1 : ascent2+advanceY1;
1898
descent=descent1 < descent2+advanceY1 ? descent1 : descent2+advanceY1;
1900
descent += advanceY;
1903
glyph.metrics.leftSideBearing=lsb;
1904
glyph.metrics.rightSideBearing=rsb;
1905
glyph.metrics.advanceX=advanceX;
1906
glyph.metrics.advanceY=advanceY;
1907
glyph.metrics.ascent=ascent;
1908
glyph.metrics.descent=descent;
1912
printf("lsb=%d, rsb=%d, adX=%d, adY=%d asc=%d, desc=%d\n",
1913
glyph.metrics.leftSideBearing,
1914
glyph.metrics.rightSideBearing,
1915
glyph.metrics.advanceX,
1916
glyph.metrics.advanceY,
1917
glyph.metrics.ascent,
1918
glyph.metrics.descent );
1927
/* T1_FillOutline(): Create a filled glyph from an outline description */
1928
GLYPH *T1_FillOutline( T1_OUTLINE *path, int modflag)
1930
struct region *area=NULL;
1932
static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1};
1933
volatile int memsize=0;
1939
/* We return to this if something goes wrong deep in the rasterizer */
1940
if ((i=setjmp( stck_state))!=0) {
1941
T1_errno=T1ERR_TYPE1_ABORT;
1942
sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
1943
t1_get_abort_message( i));
1944
T1_PrintLog( "T1_FillOutline()", err_warn_msg_buf,
1949
/* Reset character glyph, if necessary */
1950
if (glyph.bits!=NULL){
1954
glyph.metrics.leftSideBearing=0;
1955
glyph.metrics.rightSideBearing=0;
1956
glyph.metrics.advanceX=0;
1957
glyph.metrics.advanceY=0;
1958
glyph.metrics.ascent=0;
1959
glyph.metrics.descent=0;
1960
glyph.pFontCacheInfo=NULL;
1964
/* Assign padding value */
1965
T1_pad=pFontBase->bitmap_pad;
1966
if (pFontBase->endian)
1972
/* Create a region from outline */
1973
area=(struct region *)Interior( (struct segment *)path,
1974
WINDINGRULE+CONTINUITY);
1976
/* fill the glyph-structure */
1978
T1_PrintLog( "T1_FillOutline()", "area=NULL returned by Interior()", T1LOG_WARNING);
1982
h = area->ymax - area->ymin;
1983
w = area->xmax - area->xmin;
1986
paddedW = PAD(w, T1_pad);
1987
if ( (area->xmin > area->xmax) || (area->ymin > area->ymax) ){
1988
/* There was a character like .notdef or space, that didn't
1989
produce any black pixels on the bitmap! -> we return a glyph with
1990
correct metrics and bitmap pointer set to NULL */
1991
sprintf( err_warn_msg_buf,
1992
"No black pixels in outline %p", path);
1993
T1_PrintLog( "T1_FillOutline()", err_warn_msg_buf, T1LOG_WARNING);
1995
glyph.metrics.leftSideBearing = 0;
1996
glyph.metrics.advanceX = NEARESTPEL(area->ending.x - area->origin.x);
1997
glyph.metrics.advanceY = - NEARESTPEL(area->ending.y - area->origin.y);
1998
glyph.metrics.rightSideBearing = 0;
1999
glyph.metrics.descent = 0;
2000
glyph.metrics.ascent = 0;
2001
/* make sure to get rid of 'area' before leaving! */
2005
if (h > 0 && w > 0) {
2006
memsize = h * paddedW / 8 + 1;
2007
/* This is for the users copy of the character, for security-reasons
2008
the original pointer to the cache area is not used. The entry glyph.bits
2009
is free'ed every time this function is called: */
2010
glyph.bits = (char *)malloc(memsize*sizeof( char));
2011
if (glyph.bits == NULL){
2012
T1_errno=T1ERR_ALLOC_MEM;
2013
/* make sure to get rid of area if it's there */
2023
area->xmin = area->xmax = 0;
2024
area->ymin = area->ymax = 0;
2027
glyph.metrics.leftSideBearing = area->xmin;
2028
glyph.metrics.advanceX = NEARESTPEL(area->ending.x - area->origin.x);
2029
glyph.metrics.advanceY = - NEARESTPEL(area->ending.y - area->origin.y);
2030
glyph.metrics.rightSideBearing = area->xmax;
2031
glyph.metrics.descent = - area->ymax;
2032
glyph.metrics.ascent = - area->ymin;
2035
if (h > 0 && w > 0) {
2036
(void) memset(glyph.bits, 0, memsize);
2037
fill(glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize );
2040
/* Check for writing direction and re-compute dimensions appropriately: */
2041
if (modflag & T1_RIGHT_TO_LEFT){
2042
glyph.metrics.advanceX *= -1;
2043
glyph.metrics.advanceY *= -1;
2044
glyph.metrics.leftSideBearing += glyph.metrics.advanceX;
2045
glyph.metrics.rightSideBearing += glyph.metrics.advanceX;
2046
glyph.metrics.descent += glyph.metrics.advanceY;
2047
glyph.metrics.ascent += glyph.metrics.advanceY;
2050
/* make sure to get rid of area if it's there */
2060
/* T1_SetRect(): Raster a rectangle, whose size is given in charspace units.
2061
The resulting glyph does not cause any escapement. */
2062
GLYPH* T1_SetRect( int FontID, float size,
2063
float width, float height, T1_TMATRIX *transform)
2067
struct region *area;
2068
struct XYspace *Current_S;
2069
float strokewidth = 0.0f;
2071
FONTSIZEDEPS *font_ptr;
2072
FONTPRIVATE *fontarrayP;
2074
volatile int memsize=0;
2078
static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1};
2081
/* We return to this if something goes wrong deep in the rasterizer */
2082
if ((i=setjmp( stck_state))!=0) {
2083
T1_errno=T1ERR_TYPE1_ABORT;
2084
sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
2085
t1_get_abort_message( i));
2086
T1_PrintLog( "T1_SetRect()", err_warn_msg_buf,
2093
/* Reset character glyph, if necessary */
2094
if (glyph.bits!=NULL){
2098
glyph.metrics.leftSideBearing=0;
2099
glyph.metrics.rightSideBearing=0;
2100
glyph.metrics.advanceX=0;
2101
glyph.metrics.advanceY=0;
2102
glyph.metrics.ascent=0;
2103
glyph.metrics.descent=0;
2104
glyph.pFontCacheInfo=NULL;
2107
/* First, check for a correct ID. */
2108
i=T1_CheckForFontID(FontID);
2112
/* if necessary load font into memory */
2114
if ( T1_LoadFont( FontID) )
2117
/* Check for valid size */
2119
T1_errno=T1ERR_INVALID_PARAMETER;
2123
/* Assign padding value */
2124
T1_pad=pFontBase->bitmap_pad;
2125
if (pFontBase->endian)
2132
/* FontID identifies a valid font */
2133
fontarrayP = &(pFontBase->pFontArray[FontID]);
2135
/* Check for size and create it if necessary */
2136
if ((font_ptr=T1int_QueryFontSize( FontID, size, NO_ANTIALIAS))==NULL){
2137
font_ptr=T1int_CreateNewFontSize( FontID, size, NO_ANTIALIAS);
2138
if (font_ptr==NULL){
2139
T1_errno=T1ERR_ALLOC_MEM;
2144
/* handle stroking stuff */
2145
if ( fontarrayP->info_flags & RASTER_STROKED) {
2146
strokewidth = pFontBase->pFontArray[FontID].StrokeWidth;
2158
/* Setup an appropriate charspace matrix. Note that the rasterizer
2159
assumes vertical values with inverted sign! Transformation should
2160
create a copy of the local charspace matrix which then still has
2161
to be made permanent. */
2162
if ( transform != NULL ) {
2163
Current_S = (struct XYspace *)
2164
Permanent(Scale(Transform (font_ptr->pCharSpaceLocal,
2165
transform->cxx, - transform->cxy,
2166
transform->cyx, - transform->cyy),
2167
DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
2170
Current_S = (struct XYspace *)
2171
Permanent(Scale(Transform(font_ptr->pCharSpaceLocal,
2172
1.0, 0.0, 0.0, -1.0),
2173
DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
2177
area=fontfcnRect( width,
2183
KillSpace (Current_S);
2185
/* fill the glyph-structure */
2187
sprintf( err_warn_msg_buf, "fontfcnRect() set mode=%d", mode);
2188
T1_PrintLog( "T1_SetRect()", err_warn_msg_buf, T1LOG_WARNING);
2192
if ( area == NULL ) {
2193
T1_PrintLog( "T1_SetRect()", "area=NULL returned by fontfcnRect()", T1LOG_WARNING);
2197
h = area->ymax - area->ymin;
2198
w = area->xmax - area->xmin;
2200
paddedW = PAD(w, T1_pad);
2202
if (h > 0 && w > 0) {
2203
memsize = h * paddedW / 8 + 1;
2204
/* This is for the users copy of the character, for security-reasons
2205
the original pointer to the cache area is not used. The entry glyph.bits
2206
is free'ed every time this function is called: */
2207
glyph.bits = (char *)malloc(memsize*sizeof( char));
2208
if ( glyph.bits == NULL ) {
2209
T1_errno=T1ERR_ALLOC_MEM;
2210
/* make sure to get rid of 'area' before leaving! */
2217
area->xmin = area->xmax = 0;
2218
area->ymin = area->ymax = 0;
2221
/* Assign metrics */
2222
glyph.metrics.leftSideBearing = area->xmin;
2223
glyph.metrics.advanceX = NEARESTPEL(area->ending.x - area->origin.x);
2224
glyph.metrics.advanceY = - NEARESTPEL(area->ending.y - area->origin.y);
2225
glyph.metrics.rightSideBearing = area->xmax;
2226
glyph.metrics.descent = - area->ymax;
2227
glyph.metrics.ascent = - area->ymin;
2230
if (h > 0 && w > 0) {
2231
(void) memset(glyph.bits, 0, memsize);
2232
fill(glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize );
2235
/* make sure to get rid of 'area' before leaving! */