Back to index

tetex-bin  3.0
t1set.c
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------------
00002   ----- File:        t1set.c 
00003   ----- Author:      Rainer Menzner (Rainer.Menzner@web.de)
00004   ----- Date:        2003-01-02
00005   ----- Description: This file is part of the t1-library. It contains
00006                      functions for setting characters and strings of
00007                    characters.
00008   ----- Copyright:   t1lib is copyrighted (c) Rainer Menzner, 1996-2003.
00009                      As of version 0.5, t1lib is distributed under the
00010                    GNU General Public Library Lincense. The
00011                    conditions can be found in the files LICENSE and
00012                    LGPL, which should reside in the toplevel
00013                    directory of the distribution.  Please note that 
00014                    there are parts of t1lib that are subject to
00015                    other licenses:
00016                    The parseAFM-package is copyrighted by Adobe Systems
00017                    Inc.
00018                    The type1 rasterizer is copyrighted by IBM and the
00019                    X11-consortium.
00020   ----- Warranties:  Of course, there's NO WARRANTY OF ANY KIND :-)
00021   ----- Credits:     I want to thank IBM and the X11-consortium for making
00022                      their rasterizer freely available.
00023                    Also thanks to Piet Tutelaers for his ps2pk, from
00024                    which I took the rasterizer sources in a format
00025                    independent from X11.
00026                      Thanks to all people who make free software living!
00027 --------------------------------------------------------------------------*/
00028   
00029 #define T1SET_C
00030 
00031 
00032 #include <stdio.h>
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <fcntl.h>
00036 #if defined(_MSC_VER)
00037 # include <io.h>
00038 # include <sys/types.h>
00039 # include <sys/stat.h>
00040 #else
00041 # include <unistd.h>
00042 #endif
00043 #include <stdlib.h>
00044 #include <math.h>
00045 #include <string.h>
00046 #include <setjmp.h>
00047 
00048 #include "../type1/ffilest.h" 
00049 #include "../type1/types.h"
00050 #include "parseAFM.h" 
00051 #include "../type1/objects.h"
00052 #include "../type1/spaces.h"
00053 #include "../type1/util.h"
00054 #include "../type1/fontfcn.h"
00055 #include "../type1/regions.h"
00056 
00057 
00058 #include "t1types.h"
00059 #include "t1extern.h"
00060 #include "t1set.h"
00061 #include "t1load.h"
00062 #include "t1finfo.h"
00063 #include "t1misc.h"
00064 #include "t1base.h"
00065 
00066 
00067 /* As a fall back */
00068 #ifndef T1_AA_TYPE16 
00069 #define T1_AA_TYPE16    short
00070 #endif
00071 #ifndef T1_AA_TYPE32 
00072 #define T1_AA_TYPE32    int
00073 #endif
00074 
00075 
00076 extern char *t1_get_abort_message( int number);
00077 extern struct region *Interior(struct segment *path, int fillrule);
00078 extern unsigned T1_AA_TYPE32 T1aa_bg;          /* white value */
00079 
00080 
00081 static void T1_ComputeLineParameters( int FontID, int width,
00082                                   int mode, float size,
00083                                   int *startx, int *endx,
00084                                   int *starty, int *endy);
00085   
00086   
00087 
00088 static int T1_bit=T1GLYPH_BIT;
00089 static int T1_byte;
00090 static int T1_pad;
00091 static int T1_wordsize;
00092 
00093 static int c_shift=8;
00094 static int s_shift=16;
00095 static int l_shift=32;
00096 
00097 
00098 
00099 /* bin_dump(): Print a binary dump of a byte, short and
00100    long variable (used for debug purposes only): */
00101 static void bin_dump_c(unsigned char value, char space_flag)
00102 {
00103   int i,j;
00104   
00105   for (i=0;i<=7;i++){
00106     if ((j=((value)>>i)&0x01))
00107       printf("X");
00108     else
00109       printf(".");
00110   }
00111   if (space_flag)
00112     printf(" ");
00113 
00114 }
00115 
00116 static void bin_dump_s(unsigned short value, char space_flag)
00117 {
00118   int i,j;
00119 
00120   if (T1_CheckEndian()){
00121     for (i=8;i<=15;i++){
00122       if ((j=((value)>>i)&0x01))
00123        printf("X");
00124       else
00125        printf(".");
00126     }
00127     for (i=0;i<=7;i++){
00128       if ((j=((value)>>i)&0x01))
00129        printf("X");
00130       else
00131        printf(".");
00132     }
00133   }
00134   else{
00135     for (i=0;i<=15;i++){
00136       if ((j=((value)>>i)&0x01))
00137        printf("X");
00138       else
00139        printf(".");
00140     }
00141   }
00142   if (space_flag)
00143     printf(" ");
00144   
00145 }
00146 
00147 static void bin_dump_l(unsigned long value, char space_flag)
00148 {
00149   int i,j;
00150   
00151   if (T1_CheckEndian()){
00152     for (i=24;i<=31;i++){
00153       if ((j=((value)>>i)&0x01))
00154        printf("X");
00155       else
00156        printf(".");
00157     }
00158     for (i=16;i<=23;i++){
00159       if ((j=((value)>>i)&0x01))
00160        printf("X");
00161       else
00162        printf(".");
00163     }
00164     for (i=8;i<=15;i++){
00165       if ((j=((value)>>i)&0x01))
00166        printf("X");
00167       else
00168        printf(".");
00169     }
00170     for (i=0;i<=7;i++){
00171       if ((j=((value)>>i)&0x01))
00172        printf("X");
00173       else
00174        printf(".");
00175     }
00176   }
00177   else{
00178     for (i=0;i<=31;i++){
00179       if ((j=((value)>>i)&0x01))
00180        printf("X");
00181       else
00182        printf(".");
00183     }
00184   }
00185   if (space_flag)
00186     printf(" ");
00187 
00188 }
00189 
00190 
00191 
00192 /* T1_SetChar(...): Generate the bitmap for a character */
00193 GLYPH *T1_SetChar( int FontID, char charcode, float size,
00194                  T1_TMATRIX *transform)
00195 {
00196   int i;
00197   int mode;
00198   struct region *area;
00199   struct XYspace *Current_S;
00200   int cache_flag    = 1;
00201   int rot_flag      = 0;
00202   unsigned char ucharcode;
00203   float strokewidth = 0.0f;
00204   volatile int strokeextraflag = 0;
00205   
00206   
00207   FONTSIZEDEPS *font_ptr;
00208   FONTPRIVATE  *fontarrayP;
00209   
00210   volatile int memsize=0;
00211   LONG h,w;
00212   LONG paddedW;
00213 
00214   /* We don't implement underlining for characters, but the rasterer
00215      implements it. Thus, we use a modflag of constant 0 */
00216   int modflag=0;
00217 
00218   static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1};
00219 
00220 
00221   /* We return to this if something goes wrong deep in the rasterizer */
00222   if ((i=setjmp( stck_state))!=0) {
00223     T1_errno=T1ERR_TYPE1_ABORT;
00224     sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
00225             t1_get_abort_message( i));
00226     T1_PrintLog( "T1_SetChar()", err_warn_msg_buf,
00227               T1LOG_ERROR);
00228     return( NULL);
00229   }
00230 
00231   ucharcode=(unsigned char)charcode;
00232 
00233   
00234   /* Reset character glyph, if necessary */
00235   if (glyph.bits!=NULL){
00236     free(glyph.bits);
00237     glyph.bits=NULL;
00238   }
00239   glyph.metrics.leftSideBearing=0;
00240   glyph.metrics.rightSideBearing=0;
00241   glyph.metrics.advanceX=0;
00242   glyph.metrics.advanceY=0;
00243   glyph.metrics.ascent=0;
00244   glyph.metrics.descent=0;
00245   glyph.pFontCacheInfo=NULL;
00246   glyph.bpp=1;  
00247   
00248   /* First, check for a correct ID */
00249   i=T1_CheckForFontID(FontID);
00250   if (i==-1){
00251     T1_errno=T1ERR_INVALID_FONTID;
00252     return(NULL);
00253   }
00254   /* if necessary load font into memory */
00255   if (i==0)
00256     if (T1_LoadFont(FontID))
00257       return(NULL);
00258 
00259   /* Check for valid size */
00260   if (size<=0.0){
00261     T1_errno=T1ERR_INVALID_PARAMETER;
00262     return(NULL);
00263   }
00264 
00265   /* Assign padding value */
00266   T1_pad=pFontBase->bitmap_pad;
00267   if (pFontBase->endian)
00268     T1_byte=1;
00269   else
00270     T1_byte=0;
00271   T1_wordsize=T1_pad;
00272 
00273   fontarrayP=&(pFontBase->pFontArray[FontID]);
00274   
00275   /* Check if rotation is requested */
00276   if (transform!=NULL){
00277     /* there's rotation requested => do not cache the resulting bitmap */
00278     rot_flag=1;
00279     cache_flag=0;
00280   }
00281   else {
00282     rot_flag=0;
00283     cache_flag=1;
00284   }
00285   
00286   /* handle stroking stuff */
00287   if ( pFontBase->pFontArray[FontID].info_flags & RASTER_STROKED) {
00288     /* Stroking requested. If caching is not desired, clear cache_flag.
00289        Otherwise, leave it unaffected. */
00290     if ( (pFontBase->pFontArray[FontID].info_flags & CACHE_STROKED) == 0 ) {
00291       /* filled glyphs are cached, indicate that character is to be rendered
00292         on the fly and not to be cached */
00293       strokeextraflag = 1;
00294       cache_flag = 0;
00295     }
00296     strokewidth = pFontBase->pFontArray[FontID].StrokeWidth;
00297   }
00298   else {
00299     /* filling requested. */
00300     if ( (pFontBase->pFontArray[FontID].info_flags & CACHE_STROKED) != 0 ) {
00301       /* stroked glyphs are cached, indicate that character is to be rendered
00302         on the fly and not to be cached */
00303       strokeextraflag = 1;
00304       cache_flag = 0;
00305     }
00306     strokewidth = 0.0f;
00307   }
00308   
00309   /* font is now loaded into memory =>
00310      Check for size: */
00311   if ((font_ptr=T1int_QueryFontSize( FontID, size, NO_ANTIALIAS))==NULL){
00312     font_ptr=T1int_CreateNewFontSize( FontID, size, NO_ANTIALIAS);
00313     if (font_ptr==NULL){
00314       T1_errno=T1ERR_ALLOC_MEM;
00315       return(NULL);
00316     }
00317   }
00318   else {/* size is already existent in cache */
00319     /* If no rotation and no noncached stroking , try to get character from cache */
00320     if ( (rot_flag==0) && (strokeextraflag==0) ) {
00321       /* we don't use the .bits entry to check because in newer releases
00322         also white glyphs (bits=NULL) are allowed. Rather, we check
00323         whether bpp > 0! */
00324       if (font_ptr->pFontCache[ucharcode].bpp > 0){
00325        /* Character is already in Chache -> create a copy of cache
00326           and return a pointer to the result: */
00327        memcpy( &glyph, &(font_ptr->pFontCache[ucharcode]), sizeof(GLYPH));
00328        paddedW = PAD((glyph.metrics.rightSideBearing-glyph.metrics.leftSideBearing),
00329                     T1_pad);
00330        if (font_ptr->pFontCache[ucharcode].bits!=NULL) {
00331          memsize = (glyph.metrics.ascent-glyph.metrics.descent)*paddedW / 8;
00332          glyph.bits = (char *)malloc(memsize*sizeof( char));
00333          if (glyph.bits == NULL){
00334            T1_errno=T1ERR_ALLOC_MEM;
00335            return(NULL);
00336          }
00337          memcpy( glyph.bits, font_ptr->pFontCache[ucharcode].bits, memsize);
00338        }
00339        return(&(glyph));
00340       }
00341     }
00342   }
00343   /* Setup an appropriate charspace matrix. Note that the rasterizer
00344      assumes vertical values with inverted sign! Transformation should
00345      create a copy of the local charspace matrix which then still has
00346      to be made permanent. */
00347   if (rot_flag){
00348     Current_S=(struct XYspace *) 
00349       Permanent(Scale(Transform (font_ptr->pCharSpaceLocal,
00350                              transform->cxx, - transform->cxy,
00351                              transform->cyx, - transform->cyy),
00352                     DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
00353   }
00354   else{
00355     Current_S=(struct XYspace *)
00356       Permanent(Scale(Transform(font_ptr->pCharSpaceLocal,
00357                             1.0, 0.0, 0.0, -1.0),
00358                     DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
00359   }
00360   
00361   /* fnt_ptr now points to the correct FontSizeDeps-struct =>
00362      lets now raster the character */
00363   mode=0;
00364   area=fontfcnB( FontID, modflag, Current_S,
00365                fontarrayP->pFontEnc,
00366                ucharcode, &mode,
00367                fontarrayP->pType1Data,
00368                DO_RASTER,
00369                strokewidth);
00370   KillSpace (Current_S);
00371 
00372   /* fill the glyph-structure */
00373   if (mode > 0) {
00374     sprintf( err_warn_msg_buf, "fontfcnB() set mode=%d", mode);
00375     T1_PrintLog( "T1_SetChar()", err_warn_msg_buf, T1LOG_WARNING);
00376     T1_errno=mode;
00377     return(NULL);
00378   }
00379   if (area == NULL){
00380     T1_PrintLog( "T1_SetChar()", "area=NULL returned by fontfcnB()", T1LOG_WARNING);
00381     T1_errno=mode;
00382     return(NULL);
00383   }
00384   h = area->ymax - area->ymin;
00385   w = area->xmax - area->xmin;
00386 
00387   if (mode == FF_NOTDEF_SUBST) {
00388     sprintf( err_warn_msg_buf,
00389             "\".notdef\" substituted for character %d from font %d",
00390             ucharcode, FontID);
00391     T1_PrintLog( "T1_SetChar()", err_warn_msg_buf, T1LOG_WARNING);
00392     mode=0;
00393   }
00394   
00395   paddedW = PAD(w, T1_pad);
00396   
00397   if (h > 0 && w > 0) {
00398     memsize = h * paddedW / 8 + 1;
00399     /* This is for the users copy of the character, for security-reasons
00400        the original pointer to the cache area is not used. The entry glyph.bits
00401        is free'ed every time this function is called: */
00402     glyph.bits = (char *)malloc(memsize*sizeof( char));
00403     if (glyph.bits == NULL){
00404       T1_errno=T1ERR_ALLOC_MEM;
00405       /* make sure to get rid of 'area' before leaving! */
00406       KillRegion (area);
00407       return(NULL);
00408     }
00409   }
00410   else {
00411     h = w = 0;
00412     area->xmin = area->xmax = 0;
00413     area->ymin = area->ymax = 0;
00414   }
00415 
00416   /* Assign metrics */
00417   glyph.metrics.leftSideBearing  = area->xmin;
00418   glyph.metrics.advanceX   = NEARESTPEL(area->ending.x - area->origin.x);
00419   glyph.metrics.advanceY   = - NEARESTPEL(area->ending.y - area->origin.y);
00420   glyph.metrics.rightSideBearing = area->xmax;
00421   glyph.metrics.descent          = - area->ymax;
00422   glyph.metrics.ascent           = - area->ymin;
00423 
00424   
00425   if (h > 0 && w > 0) {
00426     (void) memset(glyph.bits, 0, memsize);
00427     fill(glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize );
00428   }
00429   
00430   /* make sure to get rid of 'area' before leaving! */
00431   KillRegion (area);
00432   
00433   /* Cache glyph if requested, also if it contains only white space */
00434   if (cache_flag){
00435     /* Copy glyph to cache but be careful not to modify the pixmap
00436        entry */
00437     font_ptr->pFontCache[ucharcode].metrics.leftSideBearing=glyph.metrics.leftSideBearing;
00438     font_ptr->pFontCache[ucharcode].metrics.rightSideBearing=glyph.metrics.rightSideBearing;
00439     font_ptr->pFontCache[ucharcode].metrics.advanceX=glyph.metrics.advanceX;
00440     font_ptr->pFontCache[ucharcode].metrics.advanceY=glyph.metrics.advanceY;
00441     font_ptr->pFontCache[ucharcode].metrics.ascent=glyph.metrics.ascent;
00442     font_ptr->pFontCache[ucharcode].metrics.descent=glyph.metrics.descent;
00443     font_ptr->pFontCache[ucharcode].pFontCacheInfo=glyph.pFontCacheInfo;
00444     font_ptr->pFontCache[ucharcode].bpp=glyph.bpp;
00445     if (glyph.bits==NULL) {
00446       font_ptr->pFontCache[ucharcode].bits=NULL;
00447     }
00448     else {
00449       font_ptr->pFontCache[ucharcode].bits = (char *)malloc(memsize*sizeof( char));
00450       if (font_ptr->pFontCache[ucharcode].bits == NULL){
00451        T1_errno=T1ERR_ALLOC_MEM;
00452        return(NULL);
00453       }
00454       /* ... and copy bitmap to cache area: */
00455       memcpy( font_ptr->pFontCache[ucharcode].bits, glyph.bits, memsize);
00456     }
00457     
00458   }
00459 
00460 
00461   return(&glyph);
00462 }
00463 
00464 
00465 
00466 /* T1_SetString(...): Generate the bitmap for a string of characters */
00467 GLYPH *T1_SetString( int FontID, char *string, volatile int len, 
00468                    long spaceoff, int modflag, float size,
00469                    T1_TMATRIX *transform)
00470 {
00471   volatile int i, j=0, k;
00472   int mode;
00473   /* initialize this to NULL just to be on the safe side */
00474   struct region *area = NULL;
00475   struct XYspace *Current_S, *S;
00476   int cache_flag=1;
00477   volatile int rot_flag=0;
00478   int *kern_pairs;       /* use for accessing the kern pairs if kerning is
00479                          requested */
00480   int no_chars=0;        /* The number of characters in the string */
00481   static int lastno_chars=0;
00482   float factor;
00483   long spacewidth;       /* This is given to fontfcnb_string() */
00484   float strokewidth = 0.0f;
00485   volatile int strokeextraflag = 0;
00486   
00487   
00488   FONTSIZEDEPS *font_ptr;
00489   FONTPRIVATE  *fontarrayP;
00490   
00491 
00492   volatile int memsize=0;
00493 
00494   long h,w;
00495   long paddedW, char_paddedW;
00496   int h_anchor, v_anchor;
00497   static int *pixel_h_anchor_corr=NULL;
00498   static int *flags=NULL;
00499   int lsb_min, rsb_max;
00500   long overallwidth=0;
00501   long overallascent=0;
00502   long overalldescent=0;
00503 
00504   int underline_startx, underline_starty, underline_endx, underline_endy;
00505   int overline_startx, overline_starty, overline_endx, overline_endy;
00506   int overstrike_startx, overstrike_starty, overstrike_endx, overstrike_endy;
00507   int start, middle;
00508   int afm_ind;
00509   
00510   char startmask, endmask;
00511   static unsigned char *r2lstring;
00512   static int r2l_len=0;
00513   
00514   static GLYPH string_glyph={NULL,{0,0,0,0,0,0},NULL,1};
00515   GLYPH *currchar;
00516 
00517   
00518   
00519   /* The following are for bitmap blitting */
00520   long BitShift;
00521   long ByteOffset;
00522   /* pad=8 */
00523   unsigned T1_AA_TYPE16 BitBuf_c;
00524   unsigned char *p_c;
00525   unsigned char *Target_c;
00526   /* pad=16 */
00527   unsigned T1_AA_TYPE32 BitBuf_s;
00528   unsigned T1_AA_TYPE16 *p_s;
00529   unsigned T1_AA_TYPE16 *Target_s;
00530 #ifdef T1_AA_TYPE64 
00531   /* pad=32 */
00532   unsigned T1_AA_TYPE64 BitBuf_l;
00533   unsigned T1_AA_TYPE32 *p_l;
00534   unsigned T1_AA_TYPE32 *Target_l;
00535 #endif
00536   unsigned char *ustring;
00537   
00538 
00539   /* We return to this if something goes wrong deep in the rasterizer */
00540   if ((i=setjmp( stck_state))!=0) {
00541     T1_errno=T1ERR_TYPE1_ABORT;
00542     sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
00543             t1_get_abort_message( i));
00544     T1_PrintLog( "T1_SetString()", err_warn_msg_buf,
00545               T1LOG_ERROR);
00546     return( NULL);
00547   }
00548 
00549   /* force string elements into unsigned */
00550   ustring=(unsigned char*)string;
00551 
00552 
00553   /* Check for valid string */
00554   if (string==NULL){
00555     T1_errno=T1ERR_INVALID_PARAMETER;
00556     return(NULL);
00557   }
00558 
00559   /* Reorganize if required */
00560   if (modflag & T1_RIGHT_TO_LEFT){
00561     if (len)
00562       i=len;
00563     else
00564       i=j=strlen( string);
00565     if (i+1>r2l_len){
00566       if (r2lstring!=NULL)
00567        free( r2lstring);
00568       r2lstring=(unsigned char *)malloc( (i+1)*sizeof(char));
00569       r2l_len=i+1;
00570     }
00571     j--;
00572     while ( i--) {
00573       r2lstring[j-i]=ustring[i];
00574     }
00575     ustring=r2lstring;
00576     len=j+1;
00577   }
00578   
00579   
00580   /* Reset string glyph, if necessary */
00581   if (string_glyph.bits!=NULL){
00582     free(string_glyph.bits);
00583     string_glyph.bits=NULL;
00584   }
00585   string_glyph.metrics.leftSideBearing=0;
00586   string_glyph.metrics.rightSideBearing=0;
00587   string_glyph.metrics.advanceX=0;
00588   string_glyph.metrics.advanceY=0;
00589   string_glyph.metrics.ascent=0;
00590   string_glyph.metrics.descent=0;
00591   string_glyph.pFontCacheInfo=NULL;
00592   string_glyph.bpp=1;
00593   
00594   /* We don't want to cache the resulting bitmap: */
00595   cache_flag=0;
00596   
00597   /* First, check for a correct ID */
00598   i=T1_CheckForFontID(FontID);
00599   if (i==-1){
00600     T1_errno=T1ERR_INVALID_FONTID;
00601     return(NULL);
00602   }
00603   
00604   /* if necessary load font into memory */
00605   if (i==0)
00606     if (T1_LoadFont(FontID))
00607       return(NULL);
00608 
00609   /* If no AFM info is present, we return an error */
00610   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
00611     T1_errno=T1ERR_NO_AFM_DATA;
00612     return(NULL);
00613   }
00614 
00615   /* Check for valid size */
00616   if (size<=0.0){
00617     T1_errno=T1ERR_INVALID_PARAMETER;
00618     return(NULL);
00619   }
00620 
00621   /* Assign padding value */
00622   T1_pad=pFontBase->bitmap_pad;
00623   if (pFontBase->endian)
00624     T1_byte=1;
00625   else
00626     T1_byte=0;
00627   T1_wordsize=T1_pad;
00628 
00629   fontarrayP=&(pFontBase->pFontArray[FontID]);
00630   
00631   /* Check if rotation is requested */
00632   if (transform!=NULL){
00633     /* there's rotation requested => do not cache the resulting bitmap */
00634     rot_flag=1;
00635     cache_flag=0;
00636   }
00637   
00638   /* handle stroking stuff */
00639   if ( pFontBase->pFontArray[FontID].info_flags & RASTER_STROKED) {
00640     /* Stroking requested. If caching is not desired, clear cache_flag.
00641        Otherwise, leave it unaffected. */
00642     if ( (pFontBase->pFontArray[FontID].info_flags & CACHE_STROKED) == 0 ) {
00643       /* filled glyphs are cached, indicate that character is to be rendered
00644         on the fly and not to be cached */
00645       strokeextraflag = 1;
00646       cache_flag = 0;
00647     }
00648     strokewidth = pFontBase->pFontArray[FontID].StrokeWidth;
00649   }
00650   else {
00651     /* filling requested. */
00652     if ( (pFontBase->pFontArray[FontID].info_flags & CACHE_STROKED) != 0 ) {
00653       /* stroked glyphs are cached, indicate that character is to be rendered
00654         on the fly and not to be cached */
00655       strokeextraflag = 1;
00656       cache_flag = 0;
00657     }
00658     strokewidth = 0.0f;
00659   }
00660   
00661   /* font is now loaded into memory =>
00662      Check for size: */
00663   if ((font_ptr=T1int_QueryFontSize( FontID, size, NO_ANTIALIAS))==NULL){
00664     font_ptr=T1int_CreateNewFontSize( FontID, size, NO_ANTIALIAS);
00665     if (font_ptr==NULL){
00666       T1_errno=T1ERR_ALLOC_MEM;
00667       return(NULL);
00668     }
00669   }
00670   
00671   /* Now comes string specific stuff: Get length of string and create an
00672      array of integers where to store the bitmap positioning dimens: */
00673   if (len<0){  /* invalid length */
00674     T1_errno=T1ERR_INVALID_PARAMETER;
00675     return(NULL);
00676   }
00677   
00678   if (len==0) /* should be computed assuming "normal" 0-terminated string,
00679                or R2L-part has already been computed! */
00680     no_chars=strlen(string);
00681   else        /* use value given on command line */
00682     no_chars=len;
00683 
00684   /* If necessary, allocate memory */
00685   if (no_chars>lastno_chars){
00686     if (pixel_h_anchor_corr!=NULL){
00687       free(pixel_h_anchor_corr);
00688     }
00689     if (flags!=NULL){
00690       free(flags);
00691     }
00692     pixel_h_anchor_corr=(int *)calloc(no_chars, sizeof(int));
00693     flags=(int *)calloc(no_chars, sizeof(int));
00694     lastno_chars=no_chars;
00695   }
00696   else{
00697     /* Reset flags  and position array */
00698     for (i=0; i<no_chars; i++){
00699       flags[i]=0;
00700       pixel_h_anchor_corr[i]=0;
00701     }
00702   }
00703   
00704   /* Setup an appropriate charspace matrix. Note that the rasterizer
00705      assumes vertical values with inverted sign! Transformation should
00706      create a copy of the local charspace matrix which then still has
00707      to be made permanent. */
00708   if (rot_flag){
00709     Current_S=(struct XYspace *) 
00710       Permanent(Scale(Transform (font_ptr->pCharSpaceLocal,
00711                              transform->cxx, - transform->cxy,
00712                              transform->cyx, - transform->cyy),
00713                     DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
00714   }
00715   else{
00716     Current_S=(struct XYspace *)
00717       Permanent(Scale(Transform(font_ptr->pCharSpaceLocal,
00718                             1.0, 0.0, 0.0, -1.0),
00719                     DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
00720   }
00721   
00722   /* Compute the correct spacewidth value (in charspace units). The
00723      value supplied by the user is interpreted as an offset in
00724      char space units:
00725      */
00726   spacewidth=T1_GetCharWidth(FontID,fontarrayP->space_position)+spaceoff;
00727   
00728   
00729   /* The following if (rot_flag==0){ ... } contains the whole code
00730      to execute when the string is oriented horizontal. Then, there's
00731      the possibility of concatenating most probably existent bitmaps
00732      from the Cache, which should be much faster than every time raster
00733      all the characters.
00734      */
00735   /* First, ensure that all needed characters are in the Cache; if not,
00736      generate them */
00737   if ( (rot_flag==0) && (strokeextraflag==0) ){
00738     overallwidth=0;
00739     for (i=0; i<no_chars; i++) {
00740       currchar= &(font_ptr->pFontCache[ustring[i]]);
00741       if (currchar->bpp<1) {
00742        flags[i]=0;
00743        mode=0;
00744        /*  Don't try to generate space-character: */
00745        if (ustring[i]!=fontarrayP->space_position){
00746          /* Note: Never underline etc. cached chars --> modflag=0 */ 
00747          area=fontfcnB( FontID, 0, Current_S,
00748                       fontarrayP->pFontEnc,
00749                       ustring[i], &mode,
00750                       fontarrayP->pType1Data,
00751                       DO_RASTER,
00752                       strokewidth);
00753 
00754          /* fill the glyph-structure */
00755          if (mode > 0) {
00756            sprintf( err_warn_msg_buf, "fontfcnB() set mode=%d", mode);
00757            T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING);
00758            T1_errno=mode;
00759            /* Make sure to free the region if it's non-NULL */
00760            if (area){
00761              KillRegion (area);
00762            }
00763            return(NULL);
00764          }
00765          if (area == NULL){
00766            T1_PrintLog( "T1_SetString()", "area=NULL returned by fontfcnB()", T1LOG_WARNING);
00767            T1_errno=mode;
00768            return(NULL);
00769          }
00770          
00771          if (mode == FF_NOTDEF_SUBST) {
00772            sprintf( err_warn_msg_buf,
00773                    "\".notdef\" substituted in string[%d] (=character %d) from font %d",
00774                    i, ustring[i], FontID);
00775            T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING);
00776            mode=0;
00777            flags[i]=1; /* indicates that .notdef has been substituted */
00778          }
00779          
00780          h = area->ymax - area->ymin;
00781          w = area->xmax - area->xmin;
00782          
00783          if (h > 0 && w > 0) {  /* bitmap contains pixels */
00784            paddedW = PAD(w, T1_pad);
00785            memsize = h * paddedW / 8 + 1;
00786            currchar->bits = (char *)malloc(memsize*sizeof( char));
00787            if (currchar->bits == NULL) {
00788              T1_errno=T1ERR_ALLOC_MEM;
00789              /* Make sure to free up the region if it's non-NULL */
00790              if (area){
00791               KillRegion (area);
00792              }
00793              return(NULL);
00794            }
00795            (void) memset(currchar->bits, 0, memsize);
00796            fill(currchar->bits, h, paddedW, area,
00797                T1_byte, T1_bit, T1_wordsize );
00798          }
00799          /* area valid -> set metrics in cache for that character */ 
00800          currchar->metrics.leftSideBearing  = area->xmin;
00801          currchar->metrics.advanceX   = NEARESTPEL(area->ending.x - area->origin.x);
00802          currchar->metrics.advanceY   = - NEARESTPEL(area->ending.y - area->origin.y);
00803          currchar->metrics.rightSideBearing = area->xmax;
00804          currchar->metrics.descent          = - area->ymax;
00805          currchar->metrics.ascent           = - area->ymin;
00806          currchar->bpp=1;
00807          
00808          /* By this point, it's clear that the 'area' struct exists,
00809             and that we no longer need it, so free it up. */
00810          KillRegion (area);
00811        }
00812       } /* end of if ( ... ), needed characters are now in cache! */
00813     } /* end of for (i<no_chars) loop */
00814     /* we still have to delete the Space */
00815     KillSpace (Current_S);
00816 
00817     /* We've to compute the scale factor: */
00818     factor=size*DeviceSpecifics.scale_x/1000;
00819 
00820     /* h_anchor is the horizontal position in the resulting bitmap;
00821        it is incremented on the fly and of course initially 0! */
00822     h_anchor=0;
00823     /* These are the initial values for left and right sidebearing */
00824     rsb_max=-30000;
00825     lsb_min= 30000;
00826     overallascent=-30000;
00827     overalldescent=30000;
00828     for (i=0;i<no_chars;i++){
00829       /* first get index into AFM-tables */
00830       afm_ind=pFontBase->pFontArray[FontID].pEncMap[(int) ustring[i]];
00831       /* Advance to next character in high resolution */
00832       if (ustring[i]==fontarrayP->space_position)
00833        h_anchor +=(int)spacewidth;
00834       /* check for a substituted char or notdef and get missing escapement */
00835       else if (afm_ind==0) {
00836        /* Setup apropriate charspace matrix */
00837        S=(struct XYspace *)IDENTITY;
00838        /* Make this permanent so that scaling it in fontfcnB_ByName will
00839           make a duplicate of it, and this duplicate can thus be safely
00840           destroyed.  Fixes the somewhat smaller memory leak */
00841        S=(struct XYspace *)Permanent
00842          (Transform(S, pFontBase->pFontArray[FontID].FontTransform[0],
00843                    pFontBase->pFontArray[FontID].FontTransform[1],
00844                    pFontBase->pFontArray[FontID].FontTransform[2],
00845                    pFontBase->pFontArray[FontID].FontTransform[3]));
00846        /* Get metrics values */
00847        area=fontfcnB_ByName( FontID, 0, S, ".notdef", &mode,
00848                            pFontBase->pFontArray[FontID].pType1Data, DO_RASTER);
00849        if (area==NULL || mode!=0){
00850          sprintf( err_warn_msg_buf,
00851                  "Could not get charspace representation of \".notdef\", Font %d, mode=%d!",
00852                  FontID, mode);
00853          T1_PrintLog( "T1_SetString()", err_warn_msg_buf,
00854                      T1LOG_ERROR);
00855          T1_errno=mode;
00856          return( NULL);
00857        }
00858        /* value to add to hanchor */ 
00859        h_anchor +=NEARESTPEL(area->ending.x);
00860        /* make sure to free S */
00861        if (S) {
00862          KillSpace (S);
00863        }
00864        /* make sure to free area */
00865        if (area) {
00866          KillRegion (area);
00867        }
00868       }
00869       else{
00870        currchar=&(font_ptr->pFontCache[ustring[i]]);
00871        pixel_h_anchor_corr[i]=((int)floor(h_anchor*factor+0.5));
00872        /* Store maximum rsb ...*/
00873        if ( pixel_h_anchor_corr[i]+currchar->metrics.rightSideBearing > rsb_max){
00874          rsb_max=pixel_h_anchor_corr[i]+currchar->metrics.rightSideBearing;
00875        }
00876        /* ... and minimum lsb */
00877        if ( pixel_h_anchor_corr[i]+currchar->metrics.leftSideBearing < lsb_min){
00878          lsb_min=pixel_h_anchor_corr[i]+currchar->metrics.leftSideBearing;
00879        }
00880        /* Advance by current chars width */
00881        /*     h_anchor +=T1_GetCharWidth( FontID, ustring[i]); */
00882        if (afm_ind>0) { /* we have a standard character */
00883          h_anchor +=(fontarrayP->pAFMData->cmi[afm_ind-1].wx) * fontarrayP->extend;
00884        }
00885        else { /* afm_ind must be negative so that we have a composite char */
00886          h_anchor +=(fontarrayP->pAFMData->ccd[-(afm_ind+1)].wx) * fontarrayP->extend;
00887        }
00888        /* If kerning, insert kerning amount */
00889        if ((i<no_chars -1) && (modflag & T1_KERNING))
00890          h_anchor +=T1_GetKerning( FontID, ustring[i], ustring[i+1]);
00891        
00892        /* We still have to care for vertical metrics: */
00893        if (currchar->metrics.ascent>overallascent)
00894          overallascent=currchar->metrics.ascent;
00895        if (currchar->metrics.descent<overalldescent)
00896          overalldescent=currchar->metrics.descent;
00897       }
00898     }
00899     string_glyph.metrics.advanceX=(int)floor(h_anchor*factor+0.5);
00900 
00901     /* We have to check for underlining and such things. They may affect the
00902        bounding box of the glyph */
00903     if (modflag & T1_UNDERLINE){
00904       T1_ComputeLineParameters( FontID, T1_UNDERLINE,
00905                             string_glyph.metrics.advanceX,
00906                             size,
00907                              &underline_startx, &underline_endx,
00908                              &underline_starty, &underline_endy);
00909       /* Check whether rsb is affected ...*/
00910       if ( underline_endx > rsb_max){
00911        rsb_max=underline_endx;
00912       }
00913       /* ... and for lsb */
00914       if ( underline_startx < lsb_min){
00915        lsb_min=underline_startx;
00916       }
00917 
00918       /* Vertical metrics may also be affected. */
00919       if (underline_starty > overallascent)
00920        overallascent=underline_starty;
00921       if (underline_endy < overalldescent)
00922        overalldescent=underline_endy;
00923     }
00924     if (modflag & T1_OVERLINE){
00925       T1_ComputeLineParameters( FontID, T1_OVERLINE,
00926                             string_glyph.metrics.advanceX,
00927                             size,
00928                              &overline_startx, &overline_endx,
00929                              &overline_starty, &overline_endy);
00930       /* Check whether rsb is affected ...*/
00931       if ( overline_endx > rsb_max){
00932        rsb_max=overline_endx;
00933       }
00934       /* ... and for lsb */
00935       if ( overline_startx < lsb_min){
00936        lsb_min=overline_startx;
00937       }
00938 
00939       /* Vertical metrics may also be affected. */
00940       if (overline_starty > overallascent)
00941        overallascent=overline_starty;
00942       if (overline_endy < overalldescent)
00943        overalldescent=overline_endy;
00944     }
00945     if (modflag & T1_OVERSTRIKE){
00946       T1_ComputeLineParameters( FontID, T1_OVERSTRIKE,
00947                             string_glyph.metrics.advanceX,
00948                             size,
00949                              &overstrike_startx, &overstrike_endx,
00950                              &overstrike_starty, &overstrike_endy);
00951       /* Check whether rsb is affected ...*/
00952       if ( overstrike_endx > rsb_max){
00953        rsb_max=overstrike_endx;
00954       }
00955       /* ... and for lsb */
00956       if ( overstrike_startx < lsb_min){
00957        lsb_min=overstrike_startx;
00958       }
00959 
00960       /* Vertical metrics may also be affected. */
00961       if (overstrike_starty > overallascent)
00962        overallascent=overstrike_starty;
00963       if (overstrike_endy < overalldescent)
00964        overalldescent=overstrike_endy;
00965     }
00966     
00967 
00968     
00969     /* Set the string-glyphs' metrics: */
00970     /* Bearings: */
00971     string_glyph.metrics.rightSideBearing=rsb_max;      
00972     string_glyph.metrics.leftSideBearing=lsb_min;
00973     /* ascent and descent: */
00974     string_glyph.metrics.ascent=overallascent;
00975     string_glyph.metrics.descent=overalldescent;
00976 
00977     
00978 
00979     /* Now, allocate memory for the resulting bitmap and set it to 0: */
00980     h=overallascent - overalldescent;
00981     w=string_glyph.metrics.rightSideBearing-string_glyph.metrics.leftSideBearing;
00982     
00983     paddedW = PAD( w, T1_pad);
00984     if ( h > 0 && w > 0){
00985       memsize = h * paddedW / 8;
00986       /* We alloc some amount more in order to avoid alignment check in
00987         bit-blitting loop */
00988       memsize += T1_pad/8;
00989       string_glyph.bits = (char *)malloc( memsize);
00990       if (string_glyph.bits == NULL) {
00991        T1_errno=T1ERR_ALLOC_MEM;
00992        return(NULL);
00993       }
00994       
00995     }
00996     else {
00997     /* We have only characters without pixels in the string ->
00998        we allow this and only set the advance width in the glyph.
00999        The bits pointer will be NULL. We reset rsb and lsb */
01000       string_glyph.metrics.rightSideBearing=0;      
01001       string_glyph.metrics.leftSideBearing=0;
01002       string_glyph.metrics.ascent=0;      
01003       string_glyph.metrics.descent=0;
01004     }
01005     
01006     if (string_glyph.bits != NULL) {
01007       
01008       memset(string_glyph.bits, 0, memsize);
01009       
01010       /* Now comes the loop for bitmap blitting: */
01011       for (i=0;i<no_chars;i++){
01012        /* Get pointer to character number i of string: */
01013        currchar=&(font_ptr->pFontCache[ustring[i]]);
01014        
01015        /* First, we have to correct the positioning values to refer to
01016           the bitmap BBox */
01017        pixel_h_anchor_corr[i] -= lsb_min;
01018        pixel_h_anchor_corr[i] += currchar->metrics.leftSideBearing;   
01019        
01020        /* Compute vertical anchor for current char-bitmap: */
01021        v_anchor=overallascent - currchar->metrics.ascent;
01022        char_paddedW=PAD( currchar->metrics.rightSideBearing
01023                        - currchar->metrics.leftSideBearing , T1_pad);
01024        /* We have to check for Big Endian. In that case, we have to
01025           act on byte-level */
01026        if (T1_byte){
01027          BitShift =  pixel_h_anchor_corr[i] % 8;
01028          ByteOffset = pixel_h_anchor_corr[i] / 8;
01029        }
01030        else { 
01031          BitShift =  pixel_h_anchor_corr[i] % T1_pad;
01032          ByteOffset = pixel_h_anchor_corr[i] / T1_pad;
01033          if (T1_pad==32)
01034            ByteOffset *=4;
01035          else if (T1_pad==16)
01036            ByteOffset *=2;
01037        }  
01038 #ifdef T1_AA_TYPE64
01039        /* We compile this part only if long is 64 bits to be conform to ANSI C */
01040        if (T1_pad==32 && T1_byte==0){
01041          /* The following loop steps through the lines of the character bitmap: */
01042          for (j=0;j<currchar->metrics.ascent-currchar->metrics.descent;j++){
01043            Target_l= (unsigned T1_AA_TYPE32 *)(string_glyph.bits +((v_anchor+j)*paddedW/8)
01044                                    +ByteOffset);
01045            /* The following loop copies the scanline of a character bitmap: */
01046            if (currchar->bits != NULL) {
01047              p_l = (unsigned T1_AA_TYPE32 *)(currchar->bits+(char_paddedW/8*j));
01048              if (BitShift == 0) {
01049               for (k=char_paddedW >> 5; k; k--)
01050                 *Target_l++ |= *p_l++;
01051              } else {
01052               for (k=0; k < char_paddedW / 32 ; k++){
01053                 BitBuf_l= ((T1_AA_TYPE64)(*p_l++)) << BitShift;
01054                 *Target_l++ |= BitBuf_l;
01055                 *Target_l |= BitBuf_l>>l_shift;
01056               } /* End of for ( .. ) stepping through columns */
01057              }
01058            } /* End of if(currchar->bits != NULL) */
01059          } /* End of for( .. ) steppin' through lines of char bitmap */
01060        }/* end if (T1_pad==32) */
01061        else
01062 #endif 
01063          if (T1_pad==16 && T1_byte==0){
01064            /* The following loop steps through the lines of the character bitmap: */
01065            for (j=0;j<currchar->metrics.ascent-currchar->metrics.descent;j++){
01066              Target_s= (unsigned T1_AA_TYPE16 *)(string_glyph.bits +((v_anchor+j)*paddedW/8)
01067                                       +ByteOffset);
01068              /* The following loop copies the scanline of a character bitmap: */
01069              if (currchar->bits != NULL) {
01070               p_s = (unsigned  T1_AA_TYPE16 *)(currchar->bits+(char_paddedW/8*j));
01071               if (BitShift == 0) {
01072                 for (k=char_paddedW >> 4; k; k--)
01073                   *Target_s++ |= *p_s++;
01074               }
01075               else{
01076                 for (k=char_paddedW >> 4; k; k--){
01077                   BitBuf_s= ((T1_AA_TYPE32)(*p_s++))<<BitShift;
01078                   *Target_s++ |= BitBuf_s;
01079                   *Target_s |= BitBuf_s>>s_shift;
01080                 } /* End of for ( .. ) stepping through columns */
01081               }
01082              } /* End of if(currchar->bits != NULL) */
01083            } /* End of for( .. ) steppin' through lines of char bitmap */
01084          }/* end if (T1_pad==16 */
01085          else{ /* T1_pad = 8 or Big Endian machine */
01086            /* The following loop steps through the lines of the character bitmap: */
01087            for (j=0;j<currchar->metrics.ascent-currchar->metrics.descent;j++){
01088              Target_c= (unsigned char *)(string_glyph.bits +((v_anchor+j)*paddedW/8)
01089                                      +ByteOffset);
01090              /* The following loop copies the scanline of a character bitmap: */
01091              if (currchar->bits != NULL) {
01092               p_c = (unsigned char *)(currchar->bits+(char_paddedW/8*j));
01093               if (BitShift == 0){
01094                 for (k=char_paddedW >> 3; k; k--)
01095                   *Target_c++ |= *p_c++;
01096               }
01097               else{
01098                 for (k=char_paddedW >> 3; k; k--){
01099                   BitBuf_c = ((T1_AA_TYPE16)(*p_c++)) << BitShift;
01100                   *Target_c++ |= BitBuf_c;
01101                   *Target_c |= BitBuf_c>>c_shift;
01102                 } /* End of for ( .. ) stepping through columns */
01103               }
01104              } /* End of if(currchar->bits != NULL) */
01105            } /* End of for( .. ) steppin' through lines of char bitmap */
01106          } /* end if (T1_pad==8) and/or BigEndian  */
01107       }
01108     } /* if (string_glyph.bits != NULL) */
01109     
01110     
01111     /* We now put the underlining rule on the glyph */
01112     if (modflag & T1_UNDERLINE){
01113       start=-string_glyph.metrics.leftSideBearing;
01114       for (i=string_glyph.metrics.ascent-underline_starty;
01115           i<string_glyph.metrics.ascent-underline_endy; i++){
01116        start =-string_glyph.metrics.leftSideBearing +
01117          (int) floor((double)(string_glyph.metrics.ascent-i)
01118                     *fontarrayP->slant+0.5);
01119        middle = ((start+string_glyph.metrics.advanceX) / 8) - (start / 8);
01120        startmask = 0xFF << (start % 8);
01121        endmask = (char) ~(0xFF << ((start+string_glyph.metrics.advanceX) % 8));
01122        Target_c= (unsigned char *)(string_glyph.bits +(i*paddedW/8)
01123                                 + (start / 8));
01124        j=middle;
01125        if (j == 0)
01126          *Target_c++ |= startmask & endmask;
01127        else {
01128          *Target_c++ |= startmask;
01129          while (--j > 0)
01130            *Target_c++ = (unsigned char) 0xFF;
01131          if ((endmask))
01132            *Target_c |= endmask;
01133        }
01134       }
01135     }
01136     /* Put an overstrike rule on the glyph */
01137     if (modflag & T1_OVERSTRIKE){
01138       start=-string_glyph.metrics.leftSideBearing;
01139       for (i=string_glyph.metrics.ascent-overstrike_starty;
01140           i<string_glyph.metrics.ascent-overstrike_endy; i++){
01141        start =-string_glyph.metrics.leftSideBearing +
01142          (int) floor((double)(string_glyph.metrics.ascent-i)
01143                     *fontarrayP->slant+0.5);
01144        middle = ((start+string_glyph.metrics.advanceX) / 8) - (start / 8);
01145        startmask = 0xFF << (start % 8);
01146        endmask = (char) ~(0xFF << ((start+string_glyph.metrics.advanceX) % 8));
01147        Target_c= (unsigned char *)(string_glyph.bits +(i*paddedW/8)
01148                                 + (start / 8));
01149        j=middle;
01150        if (j == 0)
01151          *Target_c++ |= startmask & endmask;
01152        else {
01153          *Target_c++ |= startmask;
01154          while (--j > 0)
01155            *Target_c++ = (unsigned char) 0xFF;
01156          if ((endmask))
01157            *Target_c |= endmask;
01158        }
01159       }
01160     }
01161     /* Put an overline rule */
01162     if (modflag & T1_OVERLINE){
01163       start=-string_glyph.metrics.leftSideBearing;
01164       for (i=string_glyph.metrics.ascent-overline_starty;
01165           i<string_glyph.metrics.ascent-overline_endy; i++){
01166        start =-string_glyph.metrics.leftSideBearing +
01167          (int) floor((double)(string_glyph.metrics.ascent-i)
01168                     *fontarrayP->slant+0.5);
01169        middle = ((start+string_glyph.metrics.advanceX) / 8) - (start / 8);
01170        startmask = 0xFF << (start % 8);
01171        endmask = (char) ~(0xFF << ((start+string_glyph.metrics.advanceX) % 8));
01172        Target_c= (unsigned char *)(string_glyph.bits +(i*paddedW/8)
01173                                 + (start / 8));
01174        j=middle;
01175        if (j == 0)
01176          *Target_c++ |= startmask & endmask;
01177        else {
01178          *Target_c++ |= startmask;
01179          while (--j > 0)
01180            *Target_c++ = (unsigned char) 0xFF;
01181          if ((endmask))
01182            *Target_c |= endmask;
01183        }
01184       }
01185     }
01186 
01187     /* Check for writing direction and re-compute dimensions appropriately: */
01188     if (modflag & T1_RIGHT_TO_LEFT){
01189       string_glyph.metrics.advanceX *= -1;
01190       string_glyph.metrics.leftSideBearing += string_glyph.metrics.advanceX;
01191       string_glyph.metrics.rightSideBearing += string_glyph.metrics.advanceX;
01192     } 
01193     
01194     return(&string_glyph);
01195   } /* end of "if (rot_flag==0.0)" */
01196 
01197 
01198   /* fnt_ptr now points to the correct FontSizeDeps-struct =>
01199      lets now raster the character */
01200   mode=0;
01201   kern_pairs=(int *)calloc(no_chars, sizeof(int));
01202   if ((modflag & T1_KERNING))
01203     for (i=0; i<no_chars -1; i++)
01204       kern_pairs[i]=T1_GetKerning( FontID, ustring[i], ustring[i+1]);
01205   area=fontfcnB_string( FontID, modflag, Current_S,
01206                      fontarrayP->pFontEnc,
01207                      ustring, no_chars, &mode,
01208                      fontarrayP->pType1Data,
01209                      kern_pairs, spacewidth,
01210                      DO_RASTER,
01211                      strokewidth);
01212   KillSpace (Current_S);
01213   
01214   /* In all cases, free memory for kerning pairs */
01215   free(kern_pairs);
01216   
01217   /* fill the string_glyph-structure */
01218   if (mode > 0) {
01219     sprintf( err_warn_msg_buf, "fontfcnB() set mode=%d", mode);
01220     T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING);
01221     T1_errno=mode;
01222     /* make sure to get rid of area if it's there */
01223     if (area){
01224       KillRegion (area);
01225     }
01226     return(NULL);
01227   }
01228   if (area == NULL){
01229     T1_PrintLog( "T1_SetString()", "area=NULL returned by fontfcnB()", T1LOG_WARNING);
01230     T1_errno=mode;
01231     return(NULL);
01232   }
01233   
01234   if (mode == FF_NOTDEF_SUBST) {
01235     sprintf( err_warn_msg_buf,
01236             "\".notdef\" substituted somewhere in string from font %d",
01237             FontID);
01238     T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING);
01239     mode=0;
01240   }
01241   
01242   h = area->ymax - area->ymin;
01243   w = area->xmax - area->xmin;
01244   paddedW = PAD(w, T1_pad);
01245   if (h > 0 && w > 0) {
01246     memsize = h * paddedW / 8 + 1;
01247     /* This is for the users copy of the character, for security-reasons
01248        the original pointer to the cache area is not used. The entry string_glyph.bits
01249        is free'ed every time this function is called: */
01250     string_glyph.bits = (char *)malloc(memsize*sizeof( char));
01251     if (string_glyph.bits == NULL) {
01252       T1_errno=T1ERR_ALLOC_MEM;
01253       /* make sure to get rid of area if it's there */
01254       if (area){
01255        KillRegion (area);
01256       }
01257       /* it's safe to free this, since this is a rotated glyph and
01258         therefore it's a copy of the original one */
01259       return(NULL);
01260     }
01261   }
01262   else {
01263     h = w = 0;
01264     area->xmin = area->xmax = 0;
01265     area->ymin = area->ymax = 0;
01266   }
01267   
01268   string_glyph.metrics.leftSideBearing=area->xmin;
01269   string_glyph.metrics.advanceX=NEARESTPEL(area->ending.x - area->origin.x);
01270   string_glyph.metrics.advanceY=-NEARESTPEL(area->ending.y - area->origin.y);
01271   string_glyph.metrics.rightSideBearing=area->xmax; 
01272   string_glyph.metrics.descent=-area->ymax;  
01273   string_glyph.metrics.ascent=-area->ymin; 
01274 
01275   if (h > 0 && w > 0) {
01276     (void) memset(string_glyph.bits, 0, memsize);
01277     fill(string_glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize );
01278   }
01279   else { /* We have no black pixels */
01280     string_glyph.metrics.leftSideBearing=0;
01281     string_glyph.metrics.advanceX=NEARESTPEL(area->ending.x - area->origin.x);
01282     string_glyph.metrics.advanceY=-NEARESTPEL(area->ending.y - area->origin.y);
01283     string_glyph.metrics.rightSideBearing=0; 
01284     string_glyph.metrics.descent=0;  
01285     string_glyph.metrics.ascent=0; 
01286   }
01287   
01288 
01289   /* make sure to get rid of area if it's there */
01290   if (area){
01291     KillRegion (area);
01292   }
01293   /* Check for writing direction and re-compute dimensions appropriately: */
01294   if (modflag & T1_RIGHT_TO_LEFT){
01295     string_glyph.metrics.advanceX *= -1;
01296     string_glyph.metrics.advanceY *= -1;
01297     string_glyph.metrics.leftSideBearing += string_glyph.metrics.advanceX;
01298     string_glyph.metrics.rightSideBearing += string_glyph.metrics.advanceX;
01299     string_glyph.metrics.descent += string_glyph.metrics.advanceY;
01300     string_glyph.metrics.ascent += string_glyph.metrics.advanceY;
01301   } 
01302   return(&string_glyph);
01303 }
01304 
01305 
01306 
01307 void fill(dest, h, w, area, byte, bit, wordsize)
01308      register char *dest;  /* destination bitmap                           */
01309      int h,w;              /* dimensions of 'dest', w padded               */
01310      register struct region *area;  /* region to write to 'dest'           */
01311      int byte,bit;         /* flags; LSBFirst or MSBFirst                  */
01312      int wordsize;         /* number of bits per word for LSB/MSB purposes */
01313 {
01314   register struct edgelist *edge;  /* for looping through edges         */
01315   register char *p;     /* current scan line in 'dest'                  */
01316   register int y;       /* for looping through scans                    */
01317   register int wbytes = w / 8;  /* number of bytes in width             */
01318   register pel *leftP,*rightP;  /* pointers to X values, left and right */
01319   int xmin = area->xmin;  /* upper left X                               */
01320   int ymin = area->ymin;  /* upper left Y                               */
01321   
01322   for (edge = area->anchor; VALIDEDGE(edge); edge = edge->link->link) {
01323     
01324     p = dest + (edge->ymin - ymin) * wbytes;
01325     leftP = edge->xvalues;
01326     rightP = edge->link->xvalues;
01327     
01328     for (y = edge->ymin; y < edge->ymax; y++) {
01329       fillrun(p, *leftP++ - xmin , *rightP++ - xmin, bit);
01330       p += wbytes;
01331     }
01332   }
01333   /* 
01334     Now, as an afterthought, we'll go reorganize if odd byte order requires
01335     it:
01336     */
01337   /* We do not reorganize since t1lib internally always uses LSBFirst */
01338   /*
01339   if ( 0 && wordsize != 8) {
01340     register int i; 
01341     printf("Reorganizing data ..\n");
01342     
01343     switch (wordsize) { 
01344     case 16: 
01345       { 
01346        register unsigned short data,*p; 
01347        p = (unsigned short *) dest; 
01348        for (i = h * w /16; --i >= 0;) { 
01349          data = *p; 
01350          *p++ = (data << 8) + (data >> 8); 
01351        } 
01352        break; 
01353       } 
01354     case 64: 
01355     case 32: 
01356       { 
01357        register ULONG data,*p; 
01358        p = (ULONG *) dest; 
01359        for (i = h * w / 32; --i >= 0;) { 
01360          data = *p; 
01361          *p++ = (data << 24) + (data >> 24) 
01362            + (0xFF00 & (data >> 8)) 
01363            + (0xFF0000 & (data << 8)); 
01364        } 
01365        if (wordsize == 64) { 
01366          p = (ULONG *) dest; 
01367          for (i = h * w / 64; --i >= 0;) { 
01368            data = *p++; 
01369            p[-1] = p[0]; 
01370            *p++ = data; 
01371          } 
01372        }
01373        break; 
01374       } 
01375     default: 
01376       abort("xiFill: unknown format"); 
01377     } 
01378   }
01379   */
01380 }
01381 
01382 #define  ALLONES  0xFF
01383 
01384 void fillrun(register char *p, pel x0, pel x1, int bit)
01385 {
01386   register int startmask,endmask;  /* bits to set in first and last char*/
01387   register int middle;  /* number of chars between start and end + 1    */
01388 
01389   if (x1 <= x0)
01390     return;
01391   middle = x1/8 - x0/8;
01392   p += x0/8;
01393   x0 &= 7;  x1 &= 7;
01394   if (bit == LSBFirst) {
01395     startmask = ALLONES << x0;
01396     endmask = ~(ALLONES << x1);
01397   }
01398   else {
01399     startmask = ALLONES >> x0;
01400     endmask = ~(ALLONES >> x1);
01401   }
01402   if (middle == 0)
01403     *p++ |= startmask & endmask;
01404   else {
01405     *p++ |= startmask;
01406     while (--middle > 0){
01407       *p++ = (unsigned char)ALLONES;
01408     }
01409     if (endmask)
01410       *p |= endmask;
01411   }
01412 }
01413 
01414 
01415 /* outline */
01416 #undef CHECK_OUTLINEFILL
01417 #ifdef CHECK_OUTLINEFILL
01418 void fill(dest, h, w, area, byte, bit, wordsize)
01419      register char *dest;  /* destination bitmap                           */
01420      int h,w;              /* dimensions of 'dest', w padded               */
01421      register struct region *area;  /* region to write to 'dest'           */
01422      int byte,bit;         /* flags; LSBFirst or MSBFirst                  */
01423      int wordsize;         /* number of bits per word for LSB/MSB purposes */
01424 {
01425   register struct edgelist *edge;  /* for looping through edges         */
01426   register char *p;     /* current scan line in 'dest'                  */
01427   register int y;       /* for looping through scans                    */
01428   register int wbytes = w / 8;  /* number of bytes in width             */
01429   register pel *leftP,*rightP;  /* pointers to X values, left and right */
01430   int xmin = area->xmin;  /* upper left X                               */
01431   int ymin = area->ymin;  /* upper left Y                               */
01432   
01433   for (edge = area->anchor; VALIDEDGE(edge); edge = edge->link->link) {
01434     
01435     p = dest + (edge->ymin - ymin) * wbytes;
01436     leftP = edge->xvalues;
01437     rightP = edge->link->xvalues;
01438 
01439     printf("leftP=%d, RightP=%d,\n", *leftP, *rightP);
01440     
01441     
01442     for (y = edge->ymin; y < edge->ymax; y++) {
01443       printf("leftP=%d, RightP=%d,y=%d\n", *leftP, *rightP, y);
01444       
01445       fillrun(p, *leftP++ - xmin, *rightP++ - xmin, bit);
01446       p += wbytes;
01447     }
01448   }
01449 }
01450 #endif
01451 
01452 
01453 /* T1_CopyGlyph(): Make a copy of an existent glyph-structure to save it
01454    for later usage by the user. */
01455 GLYPH *T1_CopyGlyph( GLYPH *glyph)
01456 {
01457   GLYPH *dest;
01458   long size;
01459   
01460 
01461   if (glyph==NULL){
01462     T1_errno=T1ERR_INVALID_PARAMETER;
01463     return(NULL);
01464   }
01465   
01466   /* Assign padding value */
01467   T1_pad=pFontBase->bitmap_pad;
01468   /* Allocate memory for struct: */
01469   if ((dest=(GLYPH *)malloc(sizeof(GLYPH)))==NULL){
01470     T1_errno=T1ERR_ALLOC_MEM;
01471     return(NULL);
01472   }
01473   
01474   /* Copy the structure members: */
01475   *dest=*glyph;
01476   /* Allocate memory for bitmap, initialize pointer to it and copy bitmap: */
01477   size=PAD((dest->metrics.rightSideBearing-dest->metrics.leftSideBearing)*
01478           glyph->bpp, T1_pad) / 8;
01479   size=size*(dest->metrics.ascent-dest->metrics.descent);
01480    /* We must check whether there's actually a bits-pointer different from
01481       NULL. If not omit the following step: */
01482   if (glyph->bits!=NULL){
01483     if ((dest->bits=(char *)malloc(size*sizeof(char)))==NULL){
01484       free(dest);
01485       T1_errno=T1ERR_ALLOC_MEM;
01486       return(NULL);
01487     }
01488     memcpy(dest->bits,glyph->bits,size);
01489   }
01490   return(dest);
01491 }
01492 
01493 /* T1_DumpGlyph(): Dump a glyph-representation to stdout: */
01494 void T1_DumpGlyph( GLYPH *glyph)
01495 {
01496   int i,j,h,w;   /* i=line-index, j=column-index */ 
01497   long paddedW;
01498   
01499   
01500   printf("Dataformat: T1_bit=%d, T1_byte=%d, T1_wordsize=%d, T1_pad=%d\n",
01501         T1_bit, T1_byte, T1_pad, T1_pad);
01502 
01503   if (glyph==NULL){
01504     return;
01505   }
01506   
01507   h=glyph->metrics.ascent-glyph->metrics.descent;
01508   w=glyph->metrics.rightSideBearing-glyph->metrics.leftSideBearing;
01509   
01510   paddedW=PAD(w,T1_pad);
01511   
01512   printf("GlyphInfo: h=%d, w=%d, paddedW=%ld\n", h, w, paddedW);
01513   
01514   for ( i=0; i<h; i++){
01515     if (T1_pad==8)
01516       for (j=0; j<paddedW/T1_pad; j++)
01517        bin_dump_c(glyph->bits[i*paddedW/T1_pad+j], 1);
01518     else if (T1_pad==16)
01519       for (j=0; j<paddedW/T1_pad; j++){
01520        bin_dump_s(((unsigned short *)glyph->bits)[i*paddedW/T1_pad+j], 1);
01521       }
01522     else
01523       for (j=0; j<paddedW/T1_pad; j++){
01524        bin_dump_l(((unsigned long *)glyph->bits)[i*paddedW/T1_pad+j], 1);
01525       }
01526     printf("\n");
01527   } 
01528 } 
01529 
01530 
01531 
01532 /* This function will essentially return the bounding box of the
01533    line-rule */
01534 static void T1_ComputeLineParameters( int FontID, int mode,
01535                                   int width, float size,
01536                                   int *startx, int *endx,
01537                                   int *starty, int *endy)
01538 {
01539   float position=0.0, thickness=0.0;
01540   int startx1, startx2, endx1, endx2;
01541   
01542   if (mode & T1_UNDERLINE){
01543     position=pFontBase->pFontArray[FontID].UndrLnPos
01544       * DeviceSpecifics.scale_y;
01545     thickness=pFontBase->pFontArray[FontID].UndrLnThick
01546       * DeviceSpecifics.scale_y;
01547   }
01548   else if (mode & T1_OVERLINE){
01549     position=pFontBase->pFontArray[FontID].OvrLnPos
01550       * DeviceSpecifics.scale_y;
01551     thickness=pFontBase->pFontArray[FontID].OvrLnThick
01552       * DeviceSpecifics.scale_y;
01553   }
01554   else if (mode & T1_OVERSTRIKE){
01555     position=pFontBase->pFontArray[FontID].OvrStrkPos
01556       * DeviceSpecifics.scale_y;
01557     thickness=pFontBase->pFontArray[FontID].OvrStrkThick
01558       * DeviceSpecifics.scale_y;
01559   }
01560   
01561   *starty=(int) floor((position+0.5*(thickness-DeviceSpecifics.y_resolution/1000.0))
01562                     *size/1000.0 +0.5 );
01563   startx1=(int) floor(*starty*pFontBase->pFontArray[FontID].slant+0.5);
01564   *endy  =*starty - (int) floor(thickness/1000.0*size+0.5);
01565   startx2=(int) floor(*endy*pFontBase->pFontArray[FontID].slant+0.5);
01566   *startx=startx1 < startx2 ? startx1 : startx2;
01567   endx1  = width +
01568     (int) floor(*starty*pFontBase->pFontArray[FontID].slant+0.5);
01569   endx2  = width +
01570     (int) floor(*endy*pFontBase->pFontArray[FontID].slant+0.5);
01571   *endx=endx1 < endx2 ? endx2 : endx1;
01572 
01573   /* We take care that at least one pixel is drawn */
01574   if (*starty==*endy)
01575     *endy -=1;
01576   
01577   return;
01578 
01579 }
01580 
01581 
01582 
01583 /* The following function concatenates two glyphs. Optional offsets
01584    x_off, y_off are respected. By the function.
01585    If either glyph is NULL or the glyphs have distinct depth, NULL is
01586    returned. */
01587 GLYPH *T1_ConcatGlyphs( GLYPH *glyph_1, GLYPH *glyph_2,
01588                      int x_off, int y_off, int modflag)
01589 {
01590 
01591   int lsb1, lsb2, rsb1, rsb2;
01592   int advanceX1, advanceX2, advanceY1, advanceY2;
01593   int ascent1, ascent2, descent1, descent2;
01594   int rsb, lsb, ascent, descent, advanceX, advanceY;
01595   int vanchor, w, h, wscanline, wscanline1, wscanline2, bpp;
01596   int memsize, BitShift;
01597   GLYPH *glyph1, *glyph2;
01598   unsigned T1_AA_TYPE16 BitBuf_c;
01599   unsigned T1_AA_TYPE32 BitBuf_s;
01600   unsigned long BitBuf_l;   /* This is only actually used if sizeof long = 8 */
01601   int i, j, k;
01602   int ByteOffset;
01603   
01604   unsigned char *Target_c, *p_c;
01605   unsigned T1_AA_TYPE16 *Target_s, *p_s;
01606   unsigned T1_AA_TYPE32 *Target_l, *p_l;
01607   
01608   static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1};
01609   
01610 
01611   /* We handle the Right-To-Left concatenation the simple way:
01612      1) Change the order of the two glyphs
01613      2) Invert the sign of the y-part of the offset
01614      3) Recalculate the dimensions of the resulating glyph.
01615   */
01616   /* Check for writing direction and reorganize appropriately: */
01617   if (modflag & T1_RIGHT_TO_LEFT){
01618     glyph1=glyph_2;
01619     glyph2=glyph_1;
01620     y_off=-y_off;
01621   }
01622   else {
01623     glyph1=glyph_1;
01624     glyph2=glyph_2;
01625   }
01626   
01627   if (glyph1==NULL){
01628     T1_errno=T1ERR_INVALID_PARAMETER;
01629     return( NULL);
01630   }
01631   if (glyph2==NULL){
01632     T1_errno=T1ERR_INVALID_PARAMETER;
01633     return( NULL);
01634   }
01635   if (glyph1->bpp != glyph2->bpp){
01636     T1_errno=T1ERR_INVALID_PARAMETER;
01637     return( NULL);
01638   }
01639   
01640   /* We have two glyph different from NULL */
01641   /* Reset glyph, if necessary */
01642   if (glyph.bits!=NULL){
01643     free(glyph.bits);
01644     glyph.bits=NULL;
01645   }
01646   glyph.metrics.leftSideBearing=0;
01647   glyph.metrics.rightSideBearing=0;
01648   glyph.metrics.advanceX=0;
01649   glyph.metrics.advanceY=0;
01650   glyph.metrics.ascent=0;
01651   glyph.metrics.descent=0;
01652   glyph.pFontCacheInfo=NULL;
01653   glyph.bpp=1;
01654 
01655   /* Assign dimens */
01656   lsb1=glyph1->metrics.leftSideBearing;
01657   rsb1=glyph1->metrics.rightSideBearing;
01658   ascent1=glyph1->metrics.ascent;
01659   descent1=glyph1->metrics.descent;
01660   advanceX1=glyph1->metrics.advanceX + x_off;
01661   advanceY1=glyph1->metrics.advanceY + y_off;
01662   
01663   lsb2=glyph2->metrics.leftSideBearing;
01664   rsb2=glyph2->metrics.rightSideBearing;
01665   ascent2=glyph2->metrics.ascent;
01666   descent2=glyph2->metrics.descent;
01667   advanceX2=glyph2->metrics.advanceX;
01668   advanceY2=glyph2->metrics.advanceY;
01669   
01670   lsb=lsb1 < lsb2+advanceX1 ? lsb1 : lsb2+advanceX1;
01671   rsb=rsb1 > rsb2+advanceX1 ? rsb1 : rsb2+advanceX1;
01672   ascent=ascent1 > ascent2+advanceY1 ? ascent1 : ascent2+advanceY1;
01673   descent=descent1 < descent2+advanceY1 ? descent1 : descent2+advanceY1;
01674   advanceX=advanceX1+advanceX2;
01675   advanceY=advanceY1+advanceY2;
01676 
01677   bpp=glyph1->bpp;
01678   w=rsb-lsb;
01679   h=ascent-descent;
01680   wscanline=PAD( w*bpp, T1_pad) / 8;
01681   wscanline1=PAD( (rsb1-lsb1)*bpp, T1_pad) / 8;
01682   wscanline2=PAD( (rsb2-lsb2)*bpp, T1_pad) / 8;
01683   memsize=wscanline*h;
01684   if ((glyph.bits=(char *)calloc( memsize + 1, sizeof(unsigned char)))==NULL){
01685     T1_errno=T1ERR_ALLOC_MEM;
01686     return(NULL);
01687   }
01688   
01689   if (bpp==1){
01690     if (T1_pad==32 && T1_byte==0 && sizeof(long)==8){
01691       /* The following loop steps through the lines of the first glyph: */
01692       vanchor=ascent-ascent1;
01693       BitShift=(lsb1-lsb) % 32;
01694       ByteOffset=(lsb1-lsb)/32*4;
01695       for ( i=0; i<ascent1-descent1; i++){
01696        Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
01697                                        +ByteOffset);
01698        p_l = (unsigned T1_AA_TYPE32 *)(glyph1->bits+(wscanline1*i));
01699        if (BitShift == 0){
01700          for (k=wscanline1/4; k; k--)
01701            *Target_l++ |= *p_l++;
01702        }
01703        else{
01704          for (k=wscanline1/4; k; k--){
01705            BitBuf_l = ((long)*p_l++) << BitShift;
01706            *Target_l++ |= BitBuf_l;
01707            *Target_l |= BitBuf_l>>l_shift;
01708          }
01709        }
01710       }
01711       /* The following loop steps through the lines of the second glyph: */
01712       vanchor=ascent-(ascent2+advanceY1);
01713       BitShift=(lsb2+advanceX1-lsb) % 32;
01714       ByteOffset=(lsb2+advanceX1-lsb)/32*4;
01715       for ( i=0; i<ascent2-descent2; i++){
01716        Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
01717                                        +ByteOffset);
01718        p_l = (unsigned T1_AA_TYPE32 *)(glyph2->bits+(wscanline2*i));
01719        if (BitShift == 0){
01720          for (k=wscanline2/4; k; k--)
01721            *Target_l++ |= *p_l++;
01722        }
01723        else{
01724          for (k=wscanline2/4; k; k--){
01725            BitBuf_l = ((long)*p_l++) << BitShift;
01726            *Target_l++ |= BitBuf_l;
01727            *Target_l |= BitBuf_l>>l_shift;
01728          } 
01729        } 
01730       }
01731     }
01732     else if(T1_pad==16 && T1_byte==0){
01733       /* The following loop steps through the lines of the first glyph: */
01734       vanchor=ascent-ascent1;
01735       BitShift=(lsb1-lsb) % 16;
01736       ByteOffset=(lsb1-lsb)/16*2;
01737       for ( i=0; i<ascent1-descent1; i++){
01738        Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
01739                                        +ByteOffset);
01740        p_s = (unsigned T1_AA_TYPE16 *)(glyph1->bits+(wscanline1*i));
01741        if (BitShift == 0){
01742          for (k=wscanline1/2; k; k--)
01743            *Target_s++ |= *p_s++;
01744        }
01745        else{
01746          for (k=wscanline1/2; k; k--){
01747            BitBuf_s = ((T1_AA_TYPE32)*p_s++) << BitShift;
01748            *Target_s++ |= BitBuf_s;
01749            *Target_s |= BitBuf_s>>s_shift;
01750          }
01751        }
01752       }
01753       /* The following loop steps through the lines of the second glyph: */
01754       vanchor=ascent-(ascent2+advanceY1);
01755       BitShift=(lsb2+advanceX1-lsb) % 16;
01756       ByteOffset=(lsb2+advanceX1-lsb)/16*2;
01757       for ( i=0; i<ascent2-descent2; i++){
01758        Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
01759                                        +ByteOffset);
01760        p_s = (unsigned T1_AA_TYPE16 *)(glyph2->bits+(wscanline2*i));
01761        if (BitShift == 0){
01762          for (k=wscanline2/2; k; k--)
01763            *Target_s++ |= *p_s++;
01764        }
01765        else{
01766          for (k=wscanline2/2; k; k--){
01767            BitBuf_s = ((T1_AA_TYPE32)*p_s++) << BitShift;
01768            *Target_s++ |= BitBuf_s;
01769            *Target_s |= BitBuf_s>>s_shift;
01770          } 
01771        } 
01772       }
01773     }
01774     else{ /* T1_pad==8 or Big Endian machine */
01775       /* The following loop steps through the lines of the first glyph: */
01776       vanchor=ascent-ascent1;
01777       BitShift=(lsb1-lsb) % 8;
01778       ByteOffset=(lsb1-lsb) / 8;
01779       for ( i=0; i<ascent1-descent1; i++){
01780        Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
01781                                 +ByteOffset);
01782        p_c = (unsigned char *)(glyph1->bits+(wscanline1*i));
01783        if (BitShift == 0){
01784          for (k=wscanline1; k; k--)
01785            *Target_c++ |= *p_c++;
01786        }
01787        else{
01788          for (k=wscanline1; k; k--){
01789            BitBuf_c = ((T1_AA_TYPE16)*p_c++) << BitShift;
01790            *Target_c++ |= BitBuf_c;
01791            *Target_c |= BitBuf_c>>c_shift;
01792          }
01793        }
01794       }
01795       /* The following loop steps through the lines of the second glyph: */
01796       vanchor=ascent-(ascent2+advanceY1);
01797       BitShift=(lsb2+advanceX1-lsb) % 8;
01798       ByteOffset=(lsb2+advanceX1-lsb) / 8;
01799       for ( i=0; i<ascent2-descent2; i++){
01800        Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
01801                                 +ByteOffset);
01802        p_c = (unsigned char *)(glyph2->bits+(wscanline2*i));
01803        if (BitShift == 0){
01804          for (k=wscanline2; k; k--)
01805            *Target_c++ |= *p_c++;
01806        }
01807        else{
01808          for (k=wscanline2; k; k--){
01809            BitBuf_c = ((T1_AA_TYPE16)*p_c++) << BitShift;
01810            *Target_c++ |= BitBuf_c;
01811            *Target_c |= BitBuf_c>>c_shift;
01812          } 
01813        } 
01814       }
01815     }
01816   } /* end of if (bpp==1) ... */
01817   else if (bpp==8){
01818     /* Set background */
01819     for ( i=0; i<memsize; i++)
01820       ((char *)glyph.bits)[i]=(char) T1aa_bg;
01821     /* The following loop steps through the lines of the first glyph: */
01822     vanchor=ascent-ascent1;
01823     for ( i=0; i<ascent1-descent1; i++){
01824       Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
01825                               +(lsb1-lsb));
01826       p_c = (unsigned char *)(glyph1->bits+(wscanline1*i));
01827       memcpy( Target_c, p_c, (rsb1-lsb1));
01828     }
01829     /* The following loop steps through the lines of the second glyph.
01830        Note that we only set the pixel if it is not background! */
01831     vanchor=ascent-(ascent2+advanceY1);
01832     for ( i=0; i<ascent2-descent2; i++){
01833       Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
01834                               +(lsb2+advanceX1-lsb));
01835       p_c = (unsigned char *)(glyph2->bits+(wscanline2*i));
01836       for (j=0; j<(rsb2-lsb2); j++)
01837        if (p_c[j] != (unsigned char) T1aa_bg)
01838          Target_c[j]=p_c[j];
01839     }
01840   } /* end of if (bpp==8) ... */
01841   else if (bpp==16){
01842     /* Set background */
01843     for ( i=0; i<memsize/2; i++)
01844       ((T1_AA_TYPE16 *)glyph.bits)[i]=(T1_AA_TYPE16) T1aa_bg;
01845     /* The following loop steps through the lines of the first glyph: */
01846     vanchor=ascent-ascent1;
01847     for ( i=0; i<ascent1-descent1; i++){
01848       Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
01849                               +(lsb1-lsb)*2);
01850       p_s = (unsigned T1_AA_TYPE16 *)(glyph1->bits+(wscanline1*i));
01851       memcpy( Target_s, p_s, (rsb1-lsb1)*2);
01852     }
01853     /* The following loop steps through the lines of the second glyph.
01854        Note that we only set the pixel if it is not background! */
01855     vanchor=ascent-(ascent2+advanceY1);
01856     for ( i=0; i<ascent2-descent2; i++){
01857       Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
01858                               +(lsb2+advanceX1-lsb)*2);
01859       p_s = (unsigned T1_AA_TYPE16 *)(glyph2->bits+(wscanline2*i));
01860       for (j=0; j<(rsb2-lsb2); j++)
01861        if (p_s[j] != (unsigned T1_AA_TYPE16) T1aa_bg)
01862          Target_s[j]=p_s[j];
01863     }
01864   } /* end of if (bpp==16) ... */
01865   else if (bpp==32){
01866     /* Set background */
01867     for ( i=0; i<memsize/4; i++)
01868       ((T1_AA_TYPE32 *)glyph.bits)[i]=(T1_AA_TYPE32) T1aa_bg;
01869     /* The following loop steps through the lines of the first glyph: */
01870     vanchor=ascent-ascent1;
01871     for ( i=0; i<ascent1-descent1; i++){
01872       Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
01873                               +(lsb1-lsb)*4);
01874       p_l = (unsigned T1_AA_TYPE32 *)(glyph1->bits+(wscanline1*i));
01875       memcpy( Target_l, p_l, (rsb1-lsb1)*4);
01876     }
01877     /* The following loop steps through the lines of the second glyph.
01878        Note that we only set the pixel if it is not background! */
01879     vanchor=ascent-(ascent2+advanceY1);
01880     for ( i=0; i<ascent2-descent2; i++){
01881       Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
01882                               +(lsb2+advanceX1-lsb)*4);
01883       p_l = (unsigned T1_AA_TYPE32 *)(glyph2->bits+(wscanline2*i));
01884       for (j=0; j<(rsb2-lsb2); j++)
01885        if (p_l[j] != (unsigned T1_AA_TYPE32) T1aa_bg)
01886          Target_l[j]=p_l[j];
01887     }
01888   } /* end of if (bpp==32) ... */
01889   
01890   
01891   /* Check for writing direction and re-compute dimens appropriately: */
01892   if (modflag & T1_RIGHT_TO_LEFT){
01893     advanceX=-advanceX1-advanceX2;
01894     advanceY=-advanceY1-advanceY2;
01895     lsb=lsb1 < lsb2+advanceX1 ? advanceX+lsb1 : advanceX+lsb2+advanceX1;
01896     rsb=rsb1 > rsb2+advanceX1 ? advanceX+rsb1 : advanceX+rsb2+advanceX1;
01897     ascent=ascent1 > ascent2+advanceY1 ? ascent1 : ascent2+advanceY1;
01898     descent=descent1 < descent2+advanceY1 ? descent1 : descent2+advanceY1;
01899     ascent += advanceY;
01900     descent += advanceY;
01901   } 
01902   
01903   glyph.metrics.leftSideBearing=lsb;
01904   glyph.metrics.rightSideBearing=rsb;
01905   glyph.metrics.advanceX=advanceX;
01906   glyph.metrics.advanceY=advanceY;
01907   glyph.metrics.ascent=ascent;
01908   glyph.metrics.descent=descent;
01909   glyph.bpp=bpp;
01910   
01911   /*
01912   printf("lsb=%d, rsb=%d, adX=%d, adY=%d asc=%d, desc=%d\n",
01913         glyph.metrics.leftSideBearing,
01914         glyph.metrics.rightSideBearing,
01915         glyph.metrics.advanceX,
01916         glyph.metrics.advanceY,
01917         glyph.metrics.ascent,
01918         glyph.metrics.descent );
01919         */
01920   
01921   return( &glyph);
01922   
01923 }
01924 
01925 
01926 
01927 /* T1_FillOutline(): Create a filled glyph from an outline description */
01928 GLYPH *T1_FillOutline( T1_OUTLINE *path, int modflag)
01929 {
01930   struct region *area=NULL;
01931 
01932   static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1};
01933   volatile int memsize=0;
01934   int i;
01935   LONG h,w;
01936   LONG paddedW;
01937 
01938   
01939   /* We return to this if something goes wrong deep in the rasterizer */
01940   if ((i=setjmp( stck_state))!=0) {
01941     T1_errno=T1ERR_TYPE1_ABORT;
01942     sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
01943             t1_get_abort_message( i));
01944     T1_PrintLog( "T1_FillOutline()", err_warn_msg_buf,
01945               T1LOG_ERROR);
01946     return( NULL);
01947   }
01948 
01949   /* Reset character glyph, if necessary */
01950   if (glyph.bits!=NULL){
01951     free(glyph.bits);
01952     glyph.bits=NULL;
01953   }
01954   glyph.metrics.leftSideBearing=0;
01955   glyph.metrics.rightSideBearing=0;
01956   glyph.metrics.advanceX=0;
01957   glyph.metrics.advanceY=0;
01958   glyph.metrics.ascent=0;
01959   glyph.metrics.descent=0;
01960   glyph.pFontCacheInfo=NULL;
01961   glyph.bpp=1;  
01962   
01963   
01964   /* Assign padding value */
01965   T1_pad=pFontBase->bitmap_pad;
01966   if (pFontBase->endian)
01967     T1_byte=1;
01968   else
01969     T1_byte=0;
01970   T1_wordsize=T1_pad;
01971 
01972   /* Create a region from outline */
01973   area=(struct region *)Interior( (struct segment *)path,
01974                               WINDINGRULE+CONTINUITY);
01975 
01976   /* fill the glyph-structure */
01977   if (area == NULL){
01978     T1_PrintLog( "T1_FillOutline()", "area=NULL returned by Interior()", T1LOG_WARNING);
01979     T1_errno=1000;
01980     return(NULL);
01981   }
01982   h = area->ymax - area->ymin;
01983   w = area->xmax - area->xmin;
01984 
01985   
01986   paddedW = PAD(w, T1_pad);
01987   if ( (area->xmin > area->xmax) || (area->ymin > area->ymax) ){
01988     /* There was a character like .notdef or space, that didn't
01989        produce any black pixels on the bitmap! -> we return a glyph with
01990        correct metrics and bitmap pointer set to NULL */
01991     sprintf( err_warn_msg_buf,
01992             "No black pixels in outline %p", path);
01993     T1_PrintLog( "T1_FillOutline()", err_warn_msg_buf, T1LOG_WARNING);
01994     
01995     glyph.metrics.leftSideBearing  = 0;
01996     glyph.metrics.advanceX   = NEARESTPEL(area->ending.x - area->origin.x);
01997     glyph.metrics.advanceY   = - NEARESTPEL(area->ending.y - area->origin.y);
01998     glyph.metrics.rightSideBearing = 0;
01999     glyph.metrics.descent          = 0;
02000     glyph.metrics.ascent           = 0;
02001     /* make sure to get rid of 'area' before leaving! */
02002     KillRegion (area);
02003     return( &glyph);
02004   }
02005   if (h > 0 && w > 0) {
02006     memsize = h * paddedW / 8 + 1;
02007     /* This is for the users copy of the character, for security-reasons
02008        the original pointer to the cache area is not used. The entry glyph.bits
02009        is free'ed every time this function is called: */
02010     glyph.bits = (char *)malloc(memsize*sizeof( char));
02011     if (glyph.bits == NULL){
02012       T1_errno=T1ERR_ALLOC_MEM;
02013       /* make sure to get rid of area if it's there */
02014       if (area){
02015        KillRegion (area);
02016       }
02017       return(NULL);
02018     }
02019     
02020   }
02021   else {
02022     h = w = 0;
02023     area->xmin = area->xmax = 0;
02024     area->ymin = area->ymax = 0;
02025   }
02026   
02027   glyph.metrics.leftSideBearing  = area->xmin;
02028   glyph.metrics.advanceX   = NEARESTPEL(area->ending.x - area->origin.x);
02029   glyph.metrics.advanceY   = - NEARESTPEL(area->ending.y - area->origin.y);
02030   glyph.metrics.rightSideBearing = area->xmax;
02031   glyph.metrics.descent          = - area->ymax;
02032   glyph.metrics.ascent           = - area->ymin;
02033   
02034   
02035   if (h > 0 && w > 0) {
02036     (void) memset(glyph.bits, 0, memsize);
02037     fill(glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize );
02038   }
02039 
02040   /* Check for writing direction and re-compute dimensions appropriately: */
02041   if (modflag & T1_RIGHT_TO_LEFT){
02042     glyph.metrics.advanceX *= -1;
02043     glyph.metrics.advanceY *= -1;
02044     glyph.metrics.leftSideBearing += glyph.metrics.advanceX;
02045     glyph.metrics.rightSideBearing += glyph.metrics.advanceX;
02046     glyph.metrics.descent += glyph.metrics.advanceY;
02047     glyph.metrics.ascent += glyph.metrics.advanceY;
02048   } 
02049   
02050   /* make sure to get rid of area if it's there */
02051   if (area){
02052     KillRegion (area);
02053   }
02054   return( &glyph);
02055   
02056   
02057 }
02058 
02059 
02060 /* T1_SetRect(): Raster a rectangle, whose size is given in charspace units.
02061    The resulting glyph does not cause any escapement. */
02062 GLYPH* T1_SetRect( int FontID, float size,
02063                  float width, float height, T1_TMATRIX *transform)
02064 {
02065   int i;
02066   int mode;
02067   struct region *area;
02068   struct XYspace *Current_S;
02069   float strokewidth = 0.0f;
02070   
02071   FONTSIZEDEPS *font_ptr;
02072   FONTPRIVATE  *fontarrayP;
02073   
02074   volatile int memsize=0;
02075   LONG h,w;
02076   LONG paddedW;
02077 
02078   static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1};
02079 
02080 
02081   /* We return to this if something goes wrong deep in the rasterizer */
02082   if ((i=setjmp( stck_state))!=0) {
02083     T1_errno=T1ERR_TYPE1_ABORT;
02084     sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
02085             t1_get_abort_message( i));
02086     T1_PrintLog( "T1_SetRect()", err_warn_msg_buf,
02087               T1LOG_ERROR);
02088     return( NULL);
02089   }
02090 
02091   font_ptr = NULL;
02092   
02093   /* Reset character glyph, if necessary */
02094   if (glyph.bits!=NULL){
02095     free(glyph.bits);
02096     glyph.bits=NULL;
02097   }
02098   glyph.metrics.leftSideBearing=0;
02099   glyph.metrics.rightSideBearing=0;
02100   glyph.metrics.advanceX=0;
02101   glyph.metrics.advanceY=0;
02102   glyph.metrics.ascent=0;
02103   glyph.metrics.descent=0;
02104   glyph.pFontCacheInfo=NULL;
02105   glyph.bpp=1;  
02106   
02107   /* First, check for a correct ID. */
02108   i=T1_CheckForFontID(FontID);
02109   if ( i == -1 ) {
02110     return NULL;
02111   }
02112   /* if necessary load font into memory */
02113   if ( i == 0 )
02114     if ( T1_LoadFont( FontID) )
02115       return NULL;
02116 
02117   /* Check for valid size */
02118   if (size<=0.0){
02119     T1_errno=T1ERR_INVALID_PARAMETER;
02120     return(NULL);
02121   }
02122 
02123   /* Assign padding value */
02124   T1_pad=pFontBase->bitmap_pad;
02125   if (pFontBase->endian)
02126     T1_byte=1;
02127   else
02128     T1_byte=0;
02129   T1_wordsize=T1_pad;
02130 
02131   if ( i > 0 ) {
02132     /* FontID identifies a valid font */
02133     fontarrayP = &(pFontBase->pFontArray[FontID]);
02134     
02135     /* Check for size and create it if necessary */
02136     if ((font_ptr=T1int_QueryFontSize( FontID, size, NO_ANTIALIAS))==NULL){
02137       font_ptr=T1int_CreateNewFontSize( FontID, size, NO_ANTIALIAS);
02138       if (font_ptr==NULL){
02139        T1_errno=T1ERR_ALLOC_MEM;
02140        return(NULL);
02141       }
02142     }
02143     
02144     /* handle stroking stuff */
02145     if ( fontarrayP->info_flags & RASTER_STROKED) {
02146       strokewidth = pFontBase->pFontArray[FontID].StrokeWidth;
02147     }
02148     else {
02149       strokewidth = 0.0f;
02150     }
02151   }
02152   else {
02153     fontarrayP = NULL;
02154     strokewidth = 0.0f;
02155   }
02156   
02157   
02158   /* Setup an appropriate charspace matrix. Note that the rasterizer
02159      assumes vertical values with inverted sign! Transformation should
02160      create a copy of the local charspace matrix which then still has
02161      to be made permanent. */
02162   if ( transform != NULL ) {
02163     Current_S = (struct XYspace *) 
02164       Permanent(Scale(Transform (font_ptr->pCharSpaceLocal,
02165                              transform->cxx, - transform->cxy,
02166                              transform->cyx, - transform->cyy),
02167                     DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
02168   }
02169   else{
02170     Current_S = (struct XYspace *)
02171       Permanent(Scale(Transform(font_ptr->pCharSpaceLocal,
02172                             1.0, 0.0, 0.0, -1.0),
02173                     DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
02174   }
02175   
02176   mode=0;
02177   area=fontfcnRect( width,
02178                   height,
02179                   Current_S,
02180                   &mode,
02181                   DO_RASTER,
02182                   strokewidth);
02183   KillSpace (Current_S);
02184   
02185   /* fill the glyph-structure */
02186   if ( mode > 0 ) {
02187     sprintf( err_warn_msg_buf, "fontfcnRect() set mode=%d", mode);
02188     T1_PrintLog( "T1_SetRect()", err_warn_msg_buf, T1LOG_WARNING);
02189     T1_errno=mode;
02190     return(NULL);
02191   }
02192   if ( area == NULL ) {
02193     T1_PrintLog( "T1_SetRect()", "area=NULL returned by fontfcnRect()", T1LOG_WARNING);
02194     T1_errno=mode;
02195     return(NULL);
02196   }
02197   h = area->ymax - area->ymin;
02198   w = area->xmax - area->xmin;
02199 
02200   paddedW = PAD(w, T1_pad);
02201   
02202   if (h > 0 && w > 0) {
02203     memsize = h * paddedW / 8 + 1;
02204     /* This is for the users copy of the character, for security-reasons
02205        the original pointer to the cache area is not used. The entry glyph.bits
02206        is free'ed every time this function is called: */
02207     glyph.bits = (char *)malloc(memsize*sizeof( char));
02208     if ( glyph.bits == NULL ) {
02209       T1_errno=T1ERR_ALLOC_MEM;
02210       /* make sure to get rid of 'area' before leaving! */
02211       KillRegion (area);
02212       return(NULL);
02213     }
02214   }
02215   else {
02216     h = w = 0;
02217     area->xmin = area->xmax = 0;
02218     area->ymin = area->ymax = 0;
02219   }
02220 
02221   /* Assign metrics */
02222   glyph.metrics.leftSideBearing  = area->xmin;
02223   glyph.metrics.advanceX   = NEARESTPEL(area->ending.x - area->origin.x);
02224   glyph.metrics.advanceY   = - NEARESTPEL(area->ending.y - area->origin.y);
02225   glyph.metrics.rightSideBearing = area->xmax;
02226   glyph.metrics.descent          = - area->ymax;
02227   glyph.metrics.ascent           = - area->ymin;
02228 
02229   
02230   if (h > 0 && w > 0) {
02231     (void) memset(glyph.bits, 0, memsize);
02232     fill(glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize );
02233   }
02234   
02235   /* make sure to get rid of 'area' before leaving! */
02236   KillRegion (area);
02237   
02238   return(&glyph);
02239 }