Back to index

tetex-bin  3.0
t1outline.c
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------------
00002   ----- File:        t1outline.c 
00003   ----- Author:      Rainer Menzner (Rainer.Menzner@web.de)
00004   ----- Date:        2002-12-02
00005   ----- Description: This file is part of the t1-library. It contains
00006                      functions for getting glyph outline descriptions of
00007                    strings and characters.
00008   ----- Copyright:   t1lib is copyrighted (c) Rainer Menzner, 1996-2002.
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 T1OUTLINE_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 #include "../type1/paths.h"
00057 
00058 
00059 #include "t1types.h"
00060 #include "t1extern.h"
00061 #include "t1set.h"
00062 #include "t1load.h"
00063 #include "t1finfo.h"
00064 #include "t1misc.h"
00065 #include "t1base.h"
00066 #include "t1outline.h"
00067 
00068 
00069 /* As a fall back */
00070 #ifndef T1_AA_TYPE16 
00071 #define T1_AA_TYPE16    short
00072 #endif
00073 #ifndef T1_AA_TYPE32 
00074 #define T1_AA_TYPE32    int
00075 #endif
00076 
00077 
00078 extern char *t1_get_abort_message( int number);
00079 extern struct segment *Type1Line(psfont *env, struct XYspace *S,
00080                              float line_position,
00081                              float line_thickness,
00082                              float line_length);
00083 extern struct segment *t1_Join( struct segment *path1,
00084                             struct segment *path2);
00085 extern struct segment *CopyPath( struct segment *p);
00086 extern void KillPath( struct segment *p);
00087 
00088 
00089 
00090 
00091 /* T1_SetChar(...): Generate the bitmap for a character */
00092 T1_OUTLINE *T1_GetCharOutline( int FontID, char charcode, float size,
00093                             T1_TMATRIX *transform)
00094 {
00095   int i;
00096   int mode;
00097   T1_PATHSEGMENT *charpath;
00098   struct XYspace *Current_S;
00099   unsigned char ucharcode;
00100   
00101   
00102   FONTSIZEDEPS *font_ptr;
00103   FONTPRIVATE  *fontarrayP;
00104   
00105   /* We don't implement underlining for characters, but the rasterer
00106      implements it. Thus, we use a modflag of constant 0 */
00107   int modflag=0;
00108 
00109   
00110   /* We return to this if something goes wrong deep in the rasterizer */
00111   if ((i=setjmp( stck_state))!=0) {
00112     T1_errno=T1ERR_TYPE1_ABORT;
00113     sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
00114             t1_get_abort_message( i));
00115     T1_PrintLog( "T1_GetCharOutline()", err_warn_msg_buf,
00116               T1LOG_ERROR);
00117     return( NULL);
00118   }
00119 
00120   ucharcode=(unsigned char)charcode;
00121 
00122   
00123   /* First, check for a correct ID */
00124   i=T1_CheckForFontID(FontID);
00125   if (i==-1){
00126     T1_errno=T1ERR_INVALID_FONTID;
00127     return(NULL);
00128   }
00129   /* if necessary load font into memory */
00130   if (i==0)
00131     if (T1_LoadFont(FontID))
00132       return(NULL);
00133 
00134   /* Check for valid size */
00135   if (size<=0.0){
00136     T1_errno=T1ERR_INVALID_PARAMETER;
00137     return(NULL);
00138   }
00139 
00140   fontarrayP=&(pFontBase->pFontArray[FontID]);
00141   
00142   /* font is now loaded into memory =>
00143      Check for size: */
00144   if ((font_ptr=T1int_QueryFontSize( FontID, size, NO_ANTIALIAS))==NULL){
00145     font_ptr=T1int_CreateNewFontSize( FontID, size, NO_ANTIALIAS);
00146     if (font_ptr==NULL){
00147       T1_errno=T1ERR_ALLOC_MEM;
00148       return(NULL);
00149     }
00150   }
00151   
00152   /* Setup an appropriate charspace matrix. Note that the rasterizer
00153      assumes vertical values with inverted sign! Transformation should
00154      create a copy of the local charspace matrix which then still has
00155      to be made permanent. */
00156   if (transform!=NULL) {
00157     Current_S=(struct XYspace *) 
00158       Permanent(Scale(Transform (font_ptr->pCharSpaceLocal,
00159                              transform->cxx, - transform->cxy,
00160                              transform->cyx, - transform->cyy),
00161                     DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
00162   }
00163   else{
00164     Current_S=(struct XYspace *)
00165       Permanent(Scale(Transform(font_ptr->pCharSpaceLocal,
00166                             1.0, 0.0, 0.0, -1.0),
00167                     DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
00168   }
00169 
00170   
00171   /* fnt_ptr now points to the correct FontSizeDeps-struct =>
00172      lets now raster the character */
00173   mode=0;
00174   charpath=(T1_PATHSEGMENT *)fontfcnB( FontID, modflag, Current_S,
00175                                    fontarrayP->pFontEnc,
00176                                    ucharcode, &mode,
00177                                    fontarrayP->pType1Data,
00178                                    DO_NOT_RASTER,0.0f);
00179   KillSpace (Current_S);
00180 
00181   return((T1_OUTLINE *)charpath);
00182 }
00183 
00184 
00185 
00186 /* T1_GetStringOutline(...): Generate the outline for a string of
00187                              characters */
00188 T1_OUTLINE *T1_GetStringOutline( int FontID, char *string, int len, 
00189                              long spaceoff, int modflag, float size,
00190                              T1_TMATRIX *transform)
00191 {
00192   int i;
00193   int mode;
00194   /* initialize this to NULL just to be on the safe side */
00195   T1_PATHSEGMENT *charpath = NULL;
00196   struct XYspace *Current_S;
00197   int *kern_pairs;       /* use for accessing the kern pairs if kerning is
00198                          requested */
00199   int no_chars=0;        /* The number of characters in the string */
00200   static int lastno_chars=0;
00201   long spacewidth;       /* This is given to fontfcnb_string() */
00202   
00203   
00204   FONTSIZEDEPS *font_ptr;
00205   FONTPRIVATE  *fontarrayP;
00206   
00207   static int *pixel_h_anchor_corr=NULL;
00208   static int *flags=NULL;
00209 
00210   unsigned char *ustring;
00211 
00212 
00213   /* We return to this if something goes wrong deep in the rasterizer */
00214   if ((i=setjmp( stck_state))!=0) {
00215     T1_errno=T1ERR_TYPE1_ABORT;
00216     sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
00217             t1_get_abort_message( i));
00218     T1_PrintLog( "T1_GetStringOutline()", err_warn_msg_buf,
00219               T1LOG_ERROR);
00220     return( NULL);
00221   }
00222 
00223   /* force string elements into unsigned */
00224   ustring=(unsigned char*)string;
00225   
00226   /* First, check for a correct ID */
00227   i=T1_CheckForFontID(FontID);
00228   if (i==-1){
00229     T1_errno=T1ERR_INVALID_FONTID;
00230     return(NULL);
00231   }
00232   /* if necessary load font into memory */
00233   if (i==0)
00234     if (T1_LoadFont(FontID))
00235       return(NULL);
00236 
00237   /* If no AFM info is present, we return an error */
00238   if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
00239     T1_errno=T1ERR_NO_AFM_DATA;
00240     return(NULL);
00241   }
00242 
00243   /* Check for valid size */
00244   if (size<=0.0){
00245     T1_errno=T1ERR_INVALID_PARAMETER;
00246     return(NULL);
00247   }
00248 
00249   fontarrayP=&(pFontBase->pFontArray[FontID]);
00250   
00251   /* font is now loaded into memory =>
00252      Check for size: */
00253   if ((font_ptr=T1int_QueryFontSize( FontID, size, NO_ANTIALIAS))==NULL){
00254     font_ptr=T1int_CreateNewFontSize( FontID, size, NO_ANTIALIAS);
00255     if (font_ptr==NULL){
00256       T1_errno=T1ERR_ALLOC_MEM;
00257       return(NULL);
00258     }
00259   }
00260   
00261   /* Now comes string specific stuff: Get length of string and create an
00262      array of integers where to store the bitmap positioning dimens: */
00263   if (len<0){  /* invalid length */
00264     T1_errno=T1ERR_INVALID_PARAMETER;
00265     return(NULL);
00266   }
00267   
00268   if (len==0) /* should be computed assuming "normal" 0-terminated string */
00269     no_chars=strlen(string);
00270   else        /* use value given on command line */
00271     no_chars=len;
00272 
00273   /* If necessary, allocate memory */
00274   if (no_chars>lastno_chars){
00275     if (pixel_h_anchor_corr!=NULL){
00276       free(pixel_h_anchor_corr);
00277     }
00278     if (flags!=NULL){
00279       free(flags);
00280     }
00281     
00282     pixel_h_anchor_corr=(int *)calloc(no_chars, sizeof(int));
00283     flags=(int *)calloc(no_chars, sizeof(int));
00284     lastno_chars=no_chars;
00285   }
00286   else{
00287     /* Reset flags  and position array */
00288     for (i=0; i<no_chars; i++){
00289       flags[i]=0;
00290       pixel_h_anchor_corr[i]=0;
00291     }
00292   }
00293   
00294   /* Setup an appropriate charspace matrix. Note that the rasterizer
00295      assumes vertical values with inverted sign! Transformation should
00296      create a copy of the local charspace matrix which then still has
00297      to be made permanent. */
00298   if (transform!=NULL){
00299     Current_S=(struct XYspace *) 
00300       Permanent(Scale(Transform (font_ptr->pCharSpaceLocal,
00301                              transform->cxx, - transform->cxy,
00302                              transform->cyx, - transform->cyy),
00303                     DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
00304   }
00305   else{
00306     Current_S=(struct XYspace *)
00307       Permanent(Scale(Transform(font_ptr->pCharSpaceLocal,
00308                             1.0, 0.0, 0.0, -1.0),
00309                     DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
00310   }
00311   
00312   /* Compute the correct spacewidth value (in charspace units). The
00313      value supplied by the user is interpreted as an offset in
00314      char space units:
00315      */
00316   spacewidth=T1_GetCharWidth(FontID,fontarrayP->space_position)+spaceoff;
00317   
00318   mode=0;
00319   kern_pairs=(int *)calloc(no_chars, sizeof(int));
00320   if ((modflag & T1_KERNING))
00321     for (i=0; i<no_chars -1; i++)
00322       kern_pairs[i]=T1_GetKerning( FontID, ustring[i], ustring[i+1]);
00323   charpath=(T1_PATHSEGMENT *) fontfcnB_string( FontID, modflag, Current_S,
00324                                           fontarrayP->pFontEnc,
00325                                           (unsigned char *)string,
00326                                           no_chars, &mode,
00327                                           fontarrayP->pType1Data,
00328                                           kern_pairs, spacewidth,
00329                                           DO_NOT_RASTER,0.0f);
00330   KillSpace (Current_S);
00331   
00332   /* In all cases, free memory for kerning pairs */
00333   free(kern_pairs);
00334   
00335   /* fill the string_glyph-structure */
00336   if (mode != 0) {
00337     sprintf( err_warn_msg_buf, "fontfcnB_string() set mode=%d", mode);
00338     T1_PrintLog( "T1_GetStringOutline()", err_warn_msg_buf, T1LOG_WARNING);
00339     T1_errno=mode;
00340     /* make sure to get rid of path if it's there */
00341     if (charpath){
00342       KillRegion (charpath);
00343     }
00344     return(NULL);
00345   }
00346   if (charpath == NULL){
00347     T1_PrintLog( "T1_GetStringOutline()", "path=NULL returned by fontfcnB_string()", T1LOG_WARNING);
00348     T1_errno=mode;
00349     return(NULL);
00350   }
00351   
00352   return( (T1_OUTLINE *)charpath);
00353 }
00354 
00355 
00356 /* T1_GetMoveOutline(...): Generate the "outline" for a movement
00357                            */
00358 T1_OUTLINE *T1_GetMoveOutline( int FontID, int deltax, int deltay, int modflag,
00359                             float size, T1_TMATRIX *transform)
00360 {
00361   int i;
00362   FONTSIZEDEPS *font_ptr;
00363   struct segment *path, *tmppath;
00364   struct XYspace *Current_S;
00365   psfont *FontP;
00366   float length;
00367   
00368 
00369   /* We return to this if something goes wrong deep in the rasterizer */
00370   if ((i=setjmp( stck_state))!=0) {
00371     T1_errno=T1ERR_TYPE1_ABORT;
00372     sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
00373             t1_get_abort_message( i));
00374     T1_PrintLog( "T1_GetMoveOutline()", err_warn_msg_buf,
00375               T1LOG_ERROR);
00376     return( NULL);
00377   }
00378 
00379 
00380   /* First, check for a correct ID */
00381   i=T1_CheckForFontID(FontID);
00382   if (i==-1){
00383     T1_errno=T1ERR_INVALID_FONTID;
00384     return(NULL);
00385   }
00386   /* if necessary load font into memory */
00387   if (i==0)
00388     if (T1_LoadFont(FontID))
00389       return(NULL);
00390 
00391   /* Check for valid size */
00392   if (size<=0.0){
00393     T1_errno=T1ERR_INVALID_PARAMETER;
00394     return(NULL);
00395   }
00396 
00397   FontP=pFontBase->pFontArray[i].pType1Data;
00398   
00399   /* font is now loaded into memory =>
00400      Check for size: */
00401   if ((font_ptr=T1int_QueryFontSize( FontID, size, NO_ANTIALIAS))==NULL){
00402     font_ptr=T1int_CreateNewFontSize( FontID, size, NO_ANTIALIAS);
00403     if (font_ptr==NULL){
00404       T1_errno=T1ERR_ALLOC_MEM;
00405       return(NULL);
00406     }
00407   }
00408 
00409   /* Setup an appropriate charspace matrix. Note that the rasterizer
00410      assumes vertical values with inverted sign! Transformation should
00411      create a copy of the local charspace matrix which then still has
00412      to be made permanent. */
00413   if (transform!=NULL){
00414     Current_S=(struct XYspace *) 
00415       Permanent(Scale(Transform (font_ptr->pCharSpaceLocal,
00416                              transform->cxx, - transform->cxy,
00417                              transform->cyx, - transform->cyy),
00418                     DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
00419   }
00420   else{
00421     Current_S=(struct XYspace *)
00422       Permanent(Scale(Transform(font_ptr->pCharSpaceLocal,
00423                             1.0, 0.0, 0.0, -1.0),
00424                     DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
00425   }
00426   
00427   
00428   path=(struct segment *)ILoc( Current_S, deltax, deltay); 
00429 
00430   /* Take care for underlining and such */
00431   length=(float) deltax;
00432   if (modflag & T1_UNDERLINE){
00433     tmppath=(struct segment *)Type1Line(FontP,Current_S,
00434                                    pFontBase->pFontArray[FontID].UndrLnPos,
00435                                    pFontBase->pFontArray[FontID].UndrLnThick,
00436                                    length);
00437     path=(struct segment *)Join(path,tmppath);
00438   }
00439   if (modflag & T1_OVERLINE){
00440     tmppath=(struct segment *)Type1Line(FontP,Current_S,
00441                                    pFontBase->pFontArray[FontID].OvrLnPos,
00442                                    pFontBase->pFontArray[FontID].OvrLnThick,
00443                                    length);
00444     path=(struct segment *)Join(path,tmppath);
00445   }
00446   if (modflag & T1_OVERSTRIKE){
00447     tmppath=(struct segment *)Type1Line(FontP,Current_S,
00448                                    pFontBase->pFontArray[FontID].OvrStrkPos,
00449                                    pFontBase->pFontArray[FontID].OvrStrkThick,
00450                                    length);
00451     path=(struct segment *)Join(path,tmppath);
00452   }
00453       
00454   KillSpace( Current_S);
00455   
00456   return( (T1_OUTLINE *)path);
00457   
00458 }
00459 
00460 
00461 /* T1_ConcatOutlines(): Concatenate two outline to one path */
00462 T1_OUTLINE *T1_ConcatOutlines( T1_OUTLINE *path1, T1_OUTLINE *path2)
00463 {
00464 
00465   return( (T1_OUTLINE *) t1_Join( (struct segment *) path1,
00466                               (struct segment *) path2));
00467   
00468 }
00469 
00470 
00471 /* T1_ScaleOutline(): Scale an outline */
00472 T1_OUTLINE *T1_ScaleOutline( T1_OUTLINE *path, float scale)
00473 {
00474   struct segment *ipath;
00475 
00476   /* Step through the path list */
00477   ipath=(struct segment *)path;
00478 
00479   do {
00480     if (ipath->type==LINETYPE){
00481       ipath->dest.x = (fractpel) (ipath->dest.x * scale);
00482       ipath->dest.y = (fractpel) (ipath->dest.y * scale);
00483     }
00484     if (ipath->type==CONICTYPE){
00485       ((struct conicsegment *)ipath)->dest.x =
00486        (fractpel) ((struct conicsegment *)ipath)->dest.x * scale;
00487       ((struct conicsegment *)ipath)->dest.y =
00488        (fractpel) ((struct conicsegment *)ipath)->dest.y * scale;
00489       ((struct conicsegment *)ipath)->M.x =
00490        (fractpel) ((struct conicsegment *)ipath)->M.x * scale;
00491       ((struct conicsegment *)ipath)->M.y =
00492        (fractpel) ((struct conicsegment *)ipath)->M.y * scale;
00493     }
00494     if (ipath->type==MOVETYPE){
00495       ipath->dest.x = (fractpel) (ipath->dest.x * scale);
00496       ipath->dest.y = (fractpel) (ipath->dest.y * scale);
00497     }
00498     if (ipath->type==BEZIERTYPE){
00499       ((struct beziersegment *)ipath)->B.x =
00500        (fractpel) (((struct beziersegment *)ipath)->B.x * scale);
00501       ((struct beziersegment *)ipath)->B.y =
00502        (fractpel) (((struct beziersegment *)ipath)->B.y * scale);
00503       ((struct beziersegment *)ipath)->C.x =
00504        (fractpel) (((struct beziersegment *)ipath)->C.x * scale);
00505       ((struct beziersegment *)ipath)->C.y =
00506        (fractpel) (((struct beziersegment *)ipath)->C.y * scale);
00507       ((struct beziersegment *)ipath)->dest.x =
00508        (fractpel) (((struct beziersegment *)ipath)->dest.x * scale);
00509       ((struct beziersegment *)ipath)->dest.y =
00510        (fractpel) (((struct beziersegment *)ipath)->dest.y * scale);
00511     }
00512     if (ipath->type==HINTTYPE){
00513       ((struct hintsegment *)ipath)->dest.x =
00514        (fractpel) (((struct hintsegment *)ipath)->dest.x * scale);
00515       ((struct hintsegment *)ipath)->dest.y =
00516        (fractpel) (((struct hintsegment *)ipath)->dest.y * scale);
00517       ((struct hintsegment *)ipath)->ref.x =
00518        (fractpel) (((struct hintsegment *)ipath)->ref.x * scale);
00519       ((struct hintsegment *)ipath)->ref.y =
00520        (fractpel) (((struct hintsegment *)ipath)->ref.y * scale);
00521       ((struct hintsegment *)ipath)->width.x =
00522        (fractpel) (((struct hintsegment *)ipath)->width.x * scale);
00523       ((struct hintsegment *)ipath)->width.y =
00524        (fractpel) (((struct hintsegment *)ipath)->width.y * scale);
00525     }
00526     if (ipath->type==TEXTTYPE)
00527       ;
00528     ipath=ipath->link;
00529 
00530   } while (ipath!=NULL);
00531   
00532   return( path);
00533   
00534 }
00535 
00536 
00537 /* dump a description of path elements to stdout */
00538 void T1_DumpPath( T1_OUTLINE *path)
00539 {
00540 
00541   struct segment *ipath;
00542 
00543   /* Step through the path list */
00544   ipath=(struct segment *)path;
00545 
00546   do {
00547     if (ipath->type==LINETYPE){
00548       printf("Line-Segment: -> (%f,%f)\n",
00549             (ipath->dest.x)/(double)(0xFFFF),
00550             -(ipath->dest.y)/(double)(0xFFFF));
00551     }
00552     if (ipath->type==MOVETYPE){
00553       printf("Move-Segment: -> (%f,%f)\n",
00554             (ipath->dest.x)/(double)(0xFFFF),
00555             -(ipath->dest.y)/(double)(0xFFFF));
00556     }
00557     if (ipath->type==BEZIERTYPE){
00558       printf("Bezier-Segment: ... (%f,%f) ... (%f,%f) -> (%f,%f)\n",
00559             (((struct beziersegment *)ipath)->B.x)/(double)(0xFFFF),
00560             -(((struct beziersegment *)ipath)->B.y)/(double)(0xFFFF),
00561             (((struct beziersegment *)ipath)->C.x)/(double)(0xFFFF),
00562             -(((struct beziersegment *)ipath)->C.y)/(double)(0xFFFF),
00563             (((struct beziersegment *)ipath)->dest.x)/(double)(0xFFFF),
00564             -(((struct beziersegment *)ipath)->dest.y)/(double)(0xFFFF));
00565     }
00566     ipath=ipath->link;
00567   } while (ipath!=NULL);
00568   
00569 }
00570 
00571 
00572 /* convert a relative path to an absolute path */
00573 void T1_AbsolutePath( T1_OUTLINE *rpath)
00574 {
00575 
00576   struct segment *ipath;
00577   fractpel xcurr=0, ycurr=0;
00578   
00579   /* Step through the path list */
00580   ipath=(struct segment *)rpath;
00581 
00582   do {
00583     if (ipath->type==LINETYPE){
00584       ipath->dest.x +=xcurr;
00585       ipath->dest.y +=ycurr;
00586 #ifdef PRINT_PATHS_TO_STDOUT      
00587       printf("Line-Segment: -> (%f,%f)\n",
00588             (ipath->dest.x)/(double)(0xFFFF),
00589             -(ipath->dest.y)/(double)(0xFFFF));
00590 #endif
00591       xcurr=ipath->dest.x;
00592       ycurr=ipath->dest.y;
00593     }
00594     if (ipath->type==MOVETYPE){
00595       ipath->dest.x +=xcurr;
00596       ipath->dest.y +=ycurr;
00597 #ifdef PRINT_PATHS_TO_STDOUT      
00598       printf("Move-Segment: -> (%f,%f)\n",
00599             (ipath->dest.x)/(double)(0xFFFF),
00600             -(ipath->dest.y)/(double)(0xFFFF));
00601 #endif
00602       xcurr=ipath->dest.x;
00603       ycurr=ipath->dest.y;
00604     }
00605     if (ipath->type==BEZIERTYPE){
00606       ((struct beziersegment *)ipath)->B.x +=xcurr;
00607       ((struct beziersegment *)ipath)->B.y +=ycurr;
00608       ((struct beziersegment *)ipath)->C.x +=xcurr;
00609       ((struct beziersegment *)ipath)->C.y +=ycurr;
00610       ipath->dest.x +=xcurr;
00611       ipath->dest.y +=ycurr;
00612 #ifdef PRINT_PATHS_TO_STDOUT      
00613       printf("Bezier-Segment: ... (%f,%f) ... (%f,%f) -> (%f,%f)\n",
00614             (((struct beziersegment *)ipath)->B.x)/(double)(0xFFFF),
00615             -(((struct beziersegment *)ipath)->B.y)/(double)(0xFFFF),
00616             (((struct beziersegment *)ipath)->C.x)/(double)(0xFFFF),
00617             -(((struct beziersegment *)ipath)->C.y)/(double)(0xFFFF),
00618             (((struct beziersegment *)ipath)->dest.x)/(double)(0xFFFF),
00619             -(((struct beziersegment *)ipath)->dest.y)/(double)(0xFFFF));
00620 #endif
00621       xcurr=ipath->dest.x;
00622       ycurr=ipath->dest.y;
00623     }
00624     ipath=ipath->link;
00625   } while (ipath!=NULL);
00626   
00627 }
00628 
00629 
00630 
00631 /* convert path into a relative path as needed by the rasterizer */
00632 void T1_RelativePath( T1_OUTLINE *apath)
00633 {
00634   
00635   struct segment *ipath;
00636   fractpel xcurr=0, ycurr=0;
00637   
00638   
00639   /* Step through the path list */
00640   ipath=(struct segment *)apath;
00641   
00642   do {
00643     if (ipath->type==LINETYPE){
00644       ipath->dest.x -=xcurr;
00645       ipath->dest.y -=ycurr;
00646       xcurr +=ipath->dest.x;
00647       ycurr +=ipath->dest.y;
00648 #ifdef PRINT_PATHS_TO_STDOUT      
00649       printf("Line-Segment: -> (%f,%f), curr=(%f,%f)\n",
00650             (ipath->dest.x)/(double)(0xFFFF),
00651             -(ipath->dest.y)/(double)(0xFFFF),
00652             xcurr/(double)(0xFFFF), -ycurr/(double)(0xFFFF));
00653 #endif
00654     }
00655     if (ipath->type==MOVETYPE){
00656       ipath->dest.x -=xcurr;
00657       ipath->dest.y -=ycurr;
00658       xcurr +=ipath->dest.x;
00659       ycurr +=ipath->dest.y;
00660 #ifdef PRINT_PATHS_TO_STDOUT      
00661       printf("Move-Segment: -> (%f,%f), curr=(%f,%f)\n",
00662             (ipath->dest.x)/(double)(0xFFFF),
00663             -(ipath->dest.y)/(double)(0xFFFF),
00664             xcurr/(double)(0xFFFF), -ycurr/(double)(0xFFFF));
00665 #endif
00666     }
00667     if (ipath->type==BEZIERTYPE){
00668       ipath->dest.x -=xcurr;
00669       ipath->dest.y -=ycurr;
00670       ((struct beziersegment *)ipath)->C.x -=xcurr;
00671       ((struct beziersegment *)ipath)->C.y -=ycurr;
00672       ((struct beziersegment *)ipath)->B.x -=xcurr;
00673       ((struct beziersegment *)ipath)->B.y -=ycurr;
00674       xcurr +=ipath->dest.x;
00675       ycurr +=ipath->dest.y;
00676 #ifdef PRINT_PATHS_TO_STDOUT      
00677       printf("Bezier-Segment: ... (%f,%f) ... (%f,%f) -> (%f,%f)\n",
00678             (((struct beziersegment *)ipath)->B.x)/(double)(0xFFFF),
00679             -(((struct beziersegment *)ipath)->B.y)/(double)(0xFFFF),
00680             (((struct beziersegment *)ipath)->C.x)/(double)(0xFFFF),
00681             -(((struct beziersegment *)ipath)->C.y)/(double)(0xFFFF),
00682             (((struct beziersegment *)ipath)->dest.x)/(double)(0xFFFF),
00683             -(((struct beziersegment *)ipath)->dest.y)/(double)(0xFFFF));
00684 #endif
00685     }
00686     ipath=ipath->link;
00687   } while (ipath!=NULL);
00688   
00689 }
00690 
00691 
00692 /* maniuplate the coordinata points of a path */
00693 void T1_ManipulatePath( T1_OUTLINE *path,
00694                      void (*manipulate)(fractpel *x,fractpel *y,int type))
00695 {
00696 
00697   struct segment *ipath;
00698   
00699   
00700   /* Step through the path list */
00701   ipath=(struct segment *)path;
00702 
00703   do {
00704     if (ipath->type==LINETYPE){
00705       manipulate( &(ipath->dest.x), &ipath->dest.y, LINETYPE);
00706 #ifdef PRINT_PATHS_TO_STDOUT      
00707       printf("Line-Segment: -> (%f,%f)\n",
00708             (ipath->dest.x)/(double)(0xFFFF),
00709             -(ipath->dest.y)/(double)(0xFFFF));
00710 #endif
00711     }
00712     if (ipath->type==MOVETYPE){
00713       manipulate( &(ipath->dest.x), &ipath->dest.y, MOVETYPE);
00714 #ifdef PRINT_PATHS_TO_STDOUT      
00715       printf("Move-Segment: -> (%f,%f)\n",
00716             (ipath->dest.x)/(double)(0xFFFF),
00717             -(ipath->dest.y)/(double)(0xFFFF));
00718 #endif
00719     }
00720     if (ipath->type==BEZIERTYPE){
00721       manipulate( &((struct beziersegment *)ipath)->B.x,
00722                 &((struct beziersegment *)ipath)->B.y,
00723                 BEZIERTYPE);
00724       manipulate( &((struct beziersegment *)ipath)->C.x,
00725                 &((struct beziersegment *)ipath)->C.y,
00726                 BEZIERTYPE);
00727       manipulate( &((struct beziersegment *)ipath)->dest.x,
00728                 &((struct beziersegment *)ipath)->dest.y,
00729                 BEZIERTYPE);
00730 #ifdef PRINT_PATHS_TO_STDOUT      
00731       printf("Bezier-Segment: ... (%f,%f) ... (%f,%f) -> (%f,%f)\n",
00732             (((struct beziersegment *)ipath)->B.x)/(double)(0xFFFF),
00733             -(((struct beziersegment *)ipath)->B.y)/(double)(0xFFFF),
00734             (((struct beziersegment *)ipath)->C.x)/(double)(0xFFFF),
00735             -(((struct beziersegment *)ipath)->C.y)/(double)(0xFFFF),
00736             (((struct beziersegment *)ipath)->dest.x)/(double)(0xFFFF),
00737             -(((struct beziersegment *)ipath)->dest.y)/(double)(0xFFFF));
00738 #endif
00739     }
00740     ipath=ipath->link;
00741   } while (ipath!=NULL);
00742   
00743 }
00744 
00745 
00746 
00747 /* T1_CopyOutline(): Copy an outline physically.
00748                      Returns a pointer to the path or NULL */
00749 T1_OUTLINE *T1_CopyOutline( T1_OUTLINE *path)
00750 {
00751 
00752   return( (T1_OUTLINE *) CopyPath( (struct segment *)path));
00753          
00754 }
00755 
00756 
00757 
00758 /* T1_FreeOutline(): Free an outline. */
00759 void T1_FreeOutline( T1_OUTLINE *path)
00760 {
00761   
00762   KillPath( (struct segment *)path);
00763   return;
00764   
00765 }
00766