Back to index

tetex-bin  3.0
t1x11.c
Go to the documentation of this file.
00001 /*--------------------------------------------------------------------------
00002   ----- File:        t1x11.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 generating glyphs with data in
00007                    X11-Pixmap format.
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 T1X11_C
00030 
00031 
00032 #include <stdio.h>
00033 #include <string.h>
00034 #include <sys/types.h>
00035 #include <sys/stat.h>
00036 #include <fcntl.h>
00037 #include <unistd.h>
00038 #include <stdlib.h>
00039 #include <math.h>
00040 
00041 #include <X11/Xlib.h>
00042 #include <X11/Xutil.h>
00043 
00044 #include "../type1/types.h"
00045 #include "parseAFM.h" 
00046 #include "../type1/objects.h" 
00047 #include "../type1/spaces.h"  
00048 #include "../type1/util.h" 
00049 #include "../type1/fontfcn.h"
00050 #include "../type1/regions.h"
00051 
00052 #include "t1types.h"
00053 #include "t1extern.h"
00054 #include "t1set.h"
00055 #include "t1aaset.h"
00056 #include "t1load.h"
00057 #include "t1finfo.h"
00058 #include "t1misc.h"
00059 #include "t1x11.h"
00060 #include "t1base.h"
00061 
00062 
00063 
00064 #define T1GCMASK GCForeground | GCBackground 
00065 
00066 /* As a fall back */
00067 #ifndef T1_AA_TYPE16 
00068 #define T1_AA_TYPE16    short
00069 #endif
00070 #ifndef T1_AA_TYPE32 
00071 #define T1_AA_TYPE32    int
00072 #endif
00073 
00074 
00075 
00076 /* The three important X11 parameters t1lib has to deal with: */
00077 static Display  *T1_display=NULL;  /* Must be accessible from t1delete.c */
00078 static Visual   *T1_visual=NULL;
00079 static Colormap T1_colormap;
00080 static unsigned int T1_depth=0;
00081 static int T1_byte_order;
00082 static int lastlevel=0;
00083 static unsigned long oldfg_n=0, oldbg_n=0, oldfg_l=0, oldbg_l=0;
00084 static unsigned long oldfg_h=0, oldbg_h=0, oldfg=0, oldbg=0;
00085 
00086 
00087 extern int T1aa_SmartOn;        /* from t1aaset.c */
00088 extern float T1aa_smartlimit1;
00089 extern float T1aa_smartlimit2;
00090 
00091 
00092 
00093 static XColor aacolors[AAMAXPLANES];
00094 static unsigned long aapixels[AAMAXPLANES];
00095 
00096 
00097 /* The following parameter determines whether t1lib will use logical
00098    positioning of chars and string (place the origin at specified
00099    destination-point) or absolute positioning with respect to the
00100    origin (upper left corner) of the generated bitmap/pixmap. */
00101 static int T1_lposition=1;
00102 
00103 
00104 
00105 /* T1_SetX11Params(): Set X11-parameters which t1lib has to know in order
00106    to properly generate pixmaps from characters */
00107 int T1_SetX11Params( Display *display,
00108                    Visual *visual,
00109                    unsigned int depth,
00110                    Colormap colormap)
00111 {
00112 
00113   T1_display  =display;
00114   T1_visual   =visual;
00115   T1_depth    =depth;
00116   T1_colormap =colormap;
00117 
00118   if (T1_CheckEndian()==0)
00119     T1_byte_order=0;
00120   else
00121     T1_byte_order=1;
00122 
00123   /* For bug hunting: */
00124   if (ImageByteOrder( T1_display)==0)
00125     T1_PrintLog( "T1_SetX11Params()",
00126                "X-Server uses Little Endian data representation",
00127                T1LOG_DEBUG);
00128   else
00129     T1_PrintLog( "T1_SetX11Params()",
00130                "X-Server uses Big Endian data representation",
00131                T1LOG_DEBUG);
00132   
00133   return(0);
00134 }
00135 
00136 
00137 
00138 /* T1_SetCharX(): Generate an object of type GLYPH, i.e, a glyph with
00139    a pixmap ID instead of a pointer to a bitmap: */
00140 
00141 GLYPH *T1_SetCharX( Drawable d, GC gc, int mode, int x_dest, int y_dest,
00142                   int FontID, char charcode,
00143                   float size, T1_TMATRIX *transform)
00144 {
00145   GLYPH  *pglyph;
00146   static GLYPH xglyph={NULL,{0,0,0,0,0,0},NULL,0};
00147  
00148   int height, width;
00149   Pixmap clipmask=0;
00150   int opaque;
00151   
00152 
00153   xglyph.metrics.leftSideBearing=0;
00154   xglyph.metrics.rightSideBearing=0;
00155   xglyph.metrics.advanceX=0;
00156   xglyph.metrics.advanceY=0;
00157   xglyph.metrics.ascent=0;
00158   xglyph.metrics.descent=0;
00159   xglyph.pFontCacheInfo=NULL;
00160   
00161 
00162   opaque=mode;
00163   
00164   
00165   if ((pglyph=T1_SetChar( FontID, charcode, size, transform))==NULL){
00166     T1_PrintLog( "T1_SetCharX()",
00167                "T1_SetChar() returned NULL-pointer!",
00168                T1LOG_WARNING);
00169     return(NULL);
00170   }
00171 
00172   /* Check for empty bitmap */
00173   if (pglyph->bits==NULL) {
00174     xglyph=*pglyph;
00175     return( &xglyph);
00176   }
00177   
00178   width=pglyph->metrics.rightSideBearing-pglyph->metrics.leftSideBearing;
00179   height=pglyph->metrics.ascent-pglyph->metrics.descent;
00180   
00181   
00182   clipmask=XCreateBitmapFromData( T1_display,
00183                               d,
00184                               (char *)pglyph->bits,
00185                               PAD(width, pFontBase->bitmap_pad),  
00186                               height
00187                               );
00188                               
00189   /* Correct position */
00190   if (T1_lposition){
00191     x_dest += pglyph->metrics.leftSideBearing;
00192     y_dest -= pglyph->metrics.ascent;
00193   }
00194 
00195   if (opaque==0){
00196     XSetClipMask(T1_display, gc, clipmask);
00197     XSetClipOrigin(T1_display, gc, x_dest, y_dest);
00198   }
00199   
00200   XCopyPlane( T1_display, clipmask, d, gc, 0, 0,
00201              width, height, x_dest, y_dest, 0x01);
00202   
00203   if (clipmask){
00204     XFreePixmap( T1_display, clipmask);
00205     clipmask=0;
00206     XSetClipMask(T1_display, gc, None);
00207     XSetClipOrigin(T1_display, gc, 0, 0);
00208   }
00209   
00210   pglyph->bits=NULL;    /* Since XDestroyImage() free's this also! */
00211   xglyph.metrics.leftSideBearing=pglyph->metrics.leftSideBearing;
00212   xglyph.metrics.rightSideBearing=pglyph->metrics.rightSideBearing;
00213   xglyph.metrics.advanceX=pglyph->metrics.advanceX;
00214   xglyph.metrics.advanceY=pglyph->metrics.advanceY;
00215   xglyph.metrics.ascent=pglyph->metrics.ascent;
00216   xglyph.metrics.descent=pglyph->metrics.descent;
00217   xglyph.bpp=pglyph->bpp;
00218   
00219   return( &xglyph);
00220   
00221   
00222 }
00223 
00224 
00225 
00226 /* T1_SetStringX(...): Draw a string of characters into an X11 drawable */
00227 GLYPH *T1_SetStringX( Drawable d, GC gc, int mode, int x_dest, int y_dest,
00228                     int FontID, char *string, int len, 
00229                     long spaceoff, int modflag, float size,
00230                     T1_TMATRIX *transform)
00231 {
00232   GLYPH  *pglyph;
00233   static GLYPH xglyph={NULL,{0,0,0,0,0,0},NULL,0};
00234  
00235   int height, width;
00236   Pixmap clipmask=0;
00237   int opaque;
00238   
00239 
00240   xglyph.metrics.leftSideBearing=0;
00241   xglyph.metrics.rightSideBearing=0;
00242   xglyph.metrics.advanceX=0;
00243   xglyph.metrics.advanceY=0;
00244   xglyph.metrics.ascent=0;
00245   xglyph.metrics.descent=0;
00246   xglyph.pFontCacheInfo=NULL;
00247   
00248 
00249   opaque=mode;
00250   
00251 
00252   if ((pglyph=T1_SetString( FontID, string, len, 
00253                          spaceoff, modflag, size,
00254                          transform))==NULL){
00255     T1_PrintLog( "T1_SetStringX()",
00256                "T1_SetString() returned NULL-pointer!",
00257                T1LOG_WARNING);
00258     return(NULL);
00259   }
00260 
00261   /* Check for empty bitmap */
00262   if (pglyph->bits==NULL) {
00263     xglyph=*pglyph;
00264     return( &xglyph);
00265   }
00266 
00267   width=pglyph->metrics.rightSideBearing-pglyph->metrics.leftSideBearing;
00268   height=pglyph->metrics.ascent-pglyph->metrics.descent;
00269   
00270   clipmask=XCreateBitmapFromData( T1_display,
00271                               d,
00272                               (char *)pglyph->bits,
00273                               PAD(width, pFontBase->bitmap_pad), /* width */
00274                               height
00275                               );
00276   
00277   /* Correct position */
00278   if (T1_lposition){
00279     x_dest += pglyph->metrics.leftSideBearing;
00280     y_dest -= pglyph->metrics.ascent;
00281   }
00282 
00283   if (opaque==0){
00284     XSetClipMask(T1_display, gc, clipmask);
00285     XSetClipOrigin(T1_display, gc, x_dest, y_dest);
00286   }
00287   
00288   XCopyPlane( T1_display, clipmask, d, gc, 0, 0,
00289              width, height, x_dest, y_dest, 0x01);
00290   
00291   if (clipmask){
00292     XFreePixmap( T1_display, clipmask);
00293     clipmask=0;
00294     XSetClipMask(T1_display, gc, None);
00295     XSetClipOrigin(T1_display, gc, 0, 0);
00296   }
00297   
00298   pglyph->bits=NULL;    /* Since XDestroyImage() free's this also! */
00299   xglyph.metrics.leftSideBearing=pglyph->metrics.leftSideBearing;
00300   xglyph.metrics.rightSideBearing=pglyph->metrics.rightSideBearing;
00301   xglyph.metrics.advanceX=pglyph->metrics.advanceX;
00302   xglyph.metrics.advanceY=pglyph->metrics.advanceY;
00303   xglyph.metrics.ascent=pglyph->metrics.ascent;
00304   xglyph.metrics.descent=pglyph->metrics.descent;
00305   xglyph.bpp=pglyph->bpp;
00306   
00307   return( &xglyph);
00308   
00309   
00310 }
00311 
00312 
00313 /* T1_SetRectX(): Draw a rectangle into an x11 drawable */
00314 
00315 GLYPH *T1_SetRectX( Drawable d, GC gc, int mode, int x_dest, int y_dest,
00316                   int FontID, float size,
00317                   float rwidth, float rheight,
00318                   T1_TMATRIX *transform)
00319 {
00320   GLYPH  *pglyph;
00321   static GLYPH xglyph={NULL,{0,0,0,0,0,0},NULL,0};
00322  
00323   int height, width;
00324   Pixmap clipmask=0;
00325   int opaque;
00326   
00327 
00328   xglyph.metrics.leftSideBearing=0;
00329   xglyph.metrics.rightSideBearing=0;
00330   xglyph.metrics.advanceX=0;
00331   xglyph.metrics.advanceY=0;
00332   xglyph.metrics.ascent=0;
00333   xglyph.metrics.descent=0;
00334   xglyph.pFontCacheInfo=NULL;
00335   
00336 
00337   opaque=mode;
00338   
00339   
00340   if ((pglyph=T1_SetRect( FontID, size, rwidth, rheight, transform))==NULL){
00341     T1_PrintLog( "T1_SetRectrX()",
00342                "T1_SetRect() returned NULL-pointer!",
00343                T1LOG_WARNING);
00344     return(NULL);
00345   }
00346 
00347   /* Check for empty bitmap */
00348   if (pglyph->bits==NULL) {
00349     xglyph=*pglyph;
00350     return( &xglyph);
00351   }
00352   
00353   width=pglyph->metrics.rightSideBearing-pglyph->metrics.leftSideBearing;
00354   height=pglyph->metrics.ascent-pglyph->metrics.descent;
00355   
00356   
00357   clipmask=XCreateBitmapFromData( T1_display,
00358                               d,
00359                               (char *)pglyph->bits,
00360                               PAD(width, pFontBase->bitmap_pad),  
00361                               height
00362                               );
00363                               
00364   /* Correct position */
00365   if (T1_lposition){
00366     x_dest += pglyph->metrics.leftSideBearing;
00367     y_dest -= pglyph->metrics.ascent;
00368   }
00369 
00370   if (opaque==0){
00371     XSetClipMask(T1_display, gc, clipmask);
00372     XSetClipOrigin(T1_display, gc, x_dest, y_dest);
00373   }
00374   
00375   XCopyPlane( T1_display, clipmask, d, gc, 0, 0,
00376              width, height, x_dest, y_dest, 0x01);
00377   
00378   if (clipmask){
00379     XFreePixmap( T1_display, clipmask);
00380     clipmask=0;
00381     XSetClipMask(T1_display, gc, None);
00382     XSetClipOrigin(T1_display, gc, 0, 0);
00383   }
00384   
00385   pglyph->bits=NULL;    /* Since XDestroyImage() free's this also! */
00386   xglyph.metrics.leftSideBearing=pglyph->metrics.leftSideBearing;
00387   xglyph.metrics.rightSideBearing=pglyph->metrics.rightSideBearing;
00388   xglyph.metrics.advanceX=pglyph->metrics.advanceX;
00389   xglyph.metrics.advanceY=pglyph->metrics.advanceY;
00390   xglyph.metrics.ascent=pglyph->metrics.ascent;
00391   xglyph.metrics.descent=pglyph->metrics.descent;
00392   xglyph.bpp=pglyph->bpp;
00393   
00394   return( &xglyph);
00395   
00396   
00397 }
00398 
00399 
00400 
00401 /* T1_AASetCharX(): Generate an object of type GLYPH, i.e, a glyph with
00402    a pixmap ID instead of a pointer to a bitmap: */
00403 GLYPH *T1_AASetCharX( Drawable d, GC gc, int mode, int x_dest, int y_dest,
00404                     int FontID, char charcode,
00405                     float size, T1_TMATRIX *transform)
00406 {
00407   int j, k;
00408 
00409   GLYPH  *pglyph;
00410   XImage *ximage;
00411 
00412   static GLYPH xglyph={NULL,{0,0,0,0,0,0},NULL,0};
00413  
00414   int height, width, width_pad;
00415   
00416   XGCValues xgcvalues;
00417   static unsigned long fg, bg;
00418 
00419   Pixmap clipmask=0;
00420   int clipmask_h, clipmask_v, line_off;
00421   char *clipmask_ptr;
00422   
00423   int opaque;
00424   
00425 
00426               
00427   xglyph.metrics.leftSideBearing=0;
00428   xglyph.metrics.rightSideBearing=0;
00429   xglyph.metrics.advanceX=0;
00430   xglyph.metrics.advanceY=0;
00431   xglyph.metrics.ascent=0;
00432   xglyph.metrics.descent=0;
00433   xglyph.pFontCacheInfo=NULL;
00434   
00435 
00436   opaque=mode;
00437   
00438   xglyph.bpp=T1_depth;
00439   
00440   /* In order to be able to contruct the pixmap we need to know
00441      foreground and background color as well the copy function */
00442   XGetGCValues( T1_display, gc, T1GCMASK, &xgcvalues);
00443   fg=xgcvalues.foreground;
00444   bg=xgcvalues.background;
00445   
00446 
00447   /* At this point we must compute the colors that are needed to do
00448      antialiasing between fore- and background. The following function
00449      fills the static aacolors */
00450   if (T1aa_SmartOn==0)
00451     j=T1_AAGetLevel();
00452   else if (size>=T1aa_smartlimit2)
00453     j=1;
00454   else if (size>=T1aa_smartlimit1)
00455     j=2;
00456   else
00457     j=4;
00458   if ( j!=lastlevel || fg!=oldfg || bg!=oldbg ){
00459     switch ( j){
00460     case 1:
00461       if ( fg!=oldfg_n || bg!=oldbg_n){
00462        oldfg_n=fg;
00463        oldbg_n=bg;
00464        /* computing colors is not necessary here */
00465        T1_AANSetGrayValues( bg, fg);
00466       }
00467       break;
00468     case 2:
00469       if ( fg!=oldfg_l || bg!=oldbg_l){
00470        T1_ComputeAAColorsX( fg, bg, AAMAXPLANES);
00471        /*~derekn*/
00472        /* If fg=bg, the clipmask will be messed up; in this case  */
00473        /* we can arbitrarily change bg to get a correct clipmask. */
00474        if (opaque == 0 && fg == bg)
00475          aapixels[0] = bg = (fg > 0) ? fg - 1 : fg + 1;
00476        oldfg_l=fg;
00477        oldbg_l=bg;
00478        T1_AASetGrayValues(aapixels[0],   /* white */
00479                         aapixels[4],
00480                         aapixels[8],
00481                         aapixels[12],
00482                         aapixels[16] ); /* black */
00483       }
00484       break;
00485     case 4:
00486       if ( fg!=oldfg_h || bg!=oldbg_h){
00487        T1_ComputeAAColorsX( fg, bg, AAMAXPLANES);
00488        /*~derekn*/
00489        /* If fg=bg, the clipmask will be messed up; in this case  */
00490        /* we can arbitrarily change bg to get a correct clipmask. */
00491        if (opaque == 0 && fg == bg)
00492          aapixels[0] = bg = (fg > 0) ? fg - 1 : fg + 1;
00493        oldfg_h=fg;
00494        oldbg_h=bg;
00495        T1_AAHSetGrayValues( aapixels); 
00496       }
00497       break;
00498     }
00499     lastlevel=j;
00500     oldfg=fg;
00501     oldbg=bg;
00502   }
00503 
00504   if ((pglyph=T1_AASetChar( FontID, charcode, size,
00505                          transform))==NULL){
00506     T1_PrintLog( "T1_AASetCharX()",
00507                "T1_AASetChar() returned NULL-pointer!",
00508                T1LOG_WARNING);
00509     return(NULL);
00510   }
00511 
00512   /* Check for empty bitmap */
00513   if (pglyph->bits==NULL) {
00514     xglyph=*pglyph;
00515     return( &xglyph);
00516   }
00517 
00518   width=pglyph->metrics.rightSideBearing-pglyph->metrics.leftSideBearing;
00519   height=pglyph->metrics.ascent-pglyph->metrics.descent;
00520   
00521               
00522   /* Correct position */
00523   if (T1_lposition){
00524     x_dest += pglyph->metrics.leftSideBearing;
00525     y_dest -= pglyph->metrics.ascent;
00526   }
00527 
00528   if (opaque==0){
00529     clipmask_v=height;
00530     clipmask_h=width;
00531     width_pad=PAD(width*T1aa_bpp, pFontBase->bitmap_pad)/T1aa_bpp;
00532     clipmask_ptr=(char *)calloc((PAD(clipmask_h, 8)>>3) * clipmask_v, sizeof( char)); 
00533     if (clipmask_ptr==NULL){
00534       T1_errno=T1ERR_ALLOC_MEM;
00535       return(NULL);
00536     }
00537     /* Note: We pad the clipmask always to byte boundary */
00538     if (pglyph->bpp==8)
00539       for ( k=0; k<clipmask_v; k++){
00540        line_off=k*(PAD(clipmask_h, 8)>>3);
00541        for (j=0; j<clipmask_h; j++){
00542          if (((char *)(pglyph->bits))[k*width_pad+j]!=bg)
00543            clipmask_ptr[line_off+(j>>3)] |= (0x01<<(j%8));
00544        }
00545       }
00546     else if (pglyph->bpp==16)
00547       for ( k=0; k<clipmask_v; k++){
00548        line_off=k*(PAD(clipmask_h, 8)>>3);
00549        for (j=0; j<clipmask_h; j++){
00550          if (((T1_AA_TYPE16 *)(pglyph->bits))[k*width_pad+j]!=(T1_AA_TYPE16)bg)
00551            clipmask_ptr[line_off+(j>>3)] |= (0x01<<(j%8));
00552        }
00553       }
00554     else 
00555       for ( k=0; k<clipmask_v; k++){
00556        line_off=k*(PAD(clipmask_h, 8)>>3);
00557        for (j=0; j<clipmask_h; j++){
00558          if (((T1_AA_TYPE32 *)(pglyph->bits))[k*width_pad+j]!=(T1_AA_TYPE32)bg)
00559            clipmask_ptr[line_off+(j>>3)] |= (0x01<<(j%8));
00560        }
00561       }
00562     
00563     clipmask=XCreateBitmapFromData( T1_display,
00564                                 d,
00565                                 (char *)clipmask_ptr,
00566                                 width,
00567                                 height
00568                                 );
00569     free( clipmask_ptr);
00570     XSetClipMask(T1_display, gc, clipmask);
00571     XSetClipOrigin(T1_display, gc, x_dest, y_dest);
00572 
00573   }
00574   ximage=XCreateImage( T1_display,
00575                      T1_visual,
00576                      T1_depth, 
00577                      ZPixmap, /* XYBitmap or XYPixmap */
00578                      0, /* No offset */
00579                      (char *)pglyph->bits,
00580                      width,
00581                      height,
00582                      pFontBase->bitmap_pad,  
00583                      0 /*PAD(width,8)/8*/  /* number of bytes per line */
00584                      );
00585   ximage->byte_order=T1_byte_order;
00586   XPutImage(T1_display,
00587            d,
00588            gc,
00589            ximage,
00590            0,  
00591            0,  
00592            x_dest,  
00593            y_dest,  
00594            width,
00595            height
00596            );
00597   XDestroyImage(ximage);
00598   if (clipmask){
00599     XFreePixmap( T1_display, clipmask);
00600     clipmask=0;
00601     XSetClipMask(T1_display, gc, None);
00602     XSetClipOrigin(T1_display, gc, 0, 0);
00603   }
00604   
00605   pglyph->bits=NULL;    /* Since XDestroyImage() free's this also! */
00606   xglyph.metrics.leftSideBearing=pglyph->metrics.leftSideBearing;
00607   xglyph.metrics.rightSideBearing=pglyph->metrics.rightSideBearing;
00608   xglyph.metrics.advanceX=pglyph->metrics.advanceX;
00609   xglyph.metrics.advanceY=pglyph->metrics.advanceY;
00610   xglyph.metrics.ascent=pglyph->metrics.ascent;
00611   xglyph.metrics.descent=pglyph->metrics.descent;
00612   xglyph.bpp=pglyph->bpp;
00613   
00614   return( &xglyph);
00615   
00616   
00617 }
00618 
00619 
00620 
00621 /* T1_AASetStringX(...): Draw a string of characters into an X11 drawable */
00622 GLYPH *T1_AASetStringX( Drawable d, GC gc, int mode, int x_dest, int y_dest,
00623                      int FontID, char *string, int len, 
00624                      long spaceoff, int modflag, float size,
00625                      T1_TMATRIX *transform)
00626 {
00627   int  j, k;
00628 
00629   GLYPH  *pglyph;
00630   XImage *ximage;
00631 
00632   
00633   static GLYPH xglyph={NULL,{0,0,0,0,0,0},NULL,0};
00634 
00635   int height, width, width_pad;
00636   
00637   XGCValues xgcvalues;
00638   static unsigned long fg, bg;
00639   
00640 
00641   Pixmap clipmask=0;
00642   int clipmask_h, clipmask_v, line_off;
00643   char *clipmask_ptr;
00644   
00645   int opaque;
00646   
00647 
00648   xglyph.metrics.leftSideBearing=0;
00649   xglyph.metrics.rightSideBearing=0;
00650   xglyph.metrics.advanceX=0;
00651   xglyph.metrics.advanceY=0;
00652   xglyph.metrics.ascent=0;
00653   xglyph.metrics.descent=0;
00654   xglyph.pFontCacheInfo=NULL;
00655   
00656 
00657   opaque=mode;
00658   
00659   
00660   /* In order to be able to contruct the pixmap we need to know
00661      foreground and background color as well the copy function */
00662   XGetGCValues( T1_display, gc, T1GCMASK, &xgcvalues);
00663   fg=xgcvalues.foreground;
00664   bg=xgcvalues.background;
00665   
00666   xglyph.bpp=T1_depth;
00667   
00668   /* At this point we must compute the colors that are needed to do
00669      antialiasing between fore- and background. The following function
00670      fills the static aacolors */
00671   if (T1aa_SmartOn==0)
00672     j=T1_AAGetLevel();
00673   else if (size>=T1aa_smartlimit2)
00674     j=1;
00675   else if (size>=T1aa_smartlimit1)
00676     j=2;
00677   else
00678     j=4;
00679   if ( j!=lastlevel || fg!=oldfg || bg!=oldbg ){
00680     switch ( j){
00681     case 1:
00682       if ( fg!=oldfg_n || bg!=oldbg_n){
00683        oldfg_n=fg;
00684        oldbg_n=bg;
00685        /* computing colors is not necessary here */
00686        T1_AANSetGrayValues( bg, fg);
00687       }
00688       break;
00689     case 2:
00690       if ( fg!=oldfg_l || bg!=oldbg_l){
00691        T1_ComputeAAColorsX( fg, bg, AAMAXPLANES);
00692        /*~derekn*/
00693        /* If fg=bg, the clipmask will be messed up; in this case  */
00694        /* we can arbitrarily change bg to get a correct clipmask. */
00695        if (opaque == 0 && fg == bg)
00696          aapixels[0] = bg = (fg > 0) ? fg - 1 : fg + 1;
00697        oldfg_l=fg;
00698        oldbg_l=bg;
00699        T1_AASetGrayValues(aapixels[0],   /* white */
00700                         aapixels[4],
00701                         aapixels[8],
00702                         aapixels[12],
00703                         aapixels[16] ); /* black */
00704       }
00705       break;
00706     case 4:
00707       if ( fg!=oldfg_h || bg!=oldbg_h){
00708        T1_ComputeAAColorsX( fg, bg, AAMAXPLANES);
00709        /*~derekn*/
00710        /* If fg=bg, the clipmask will be messed up; in this case  */
00711        /* we can arbitrarily change bg to get a correct clipmask. */
00712        if (opaque == 0 && fg == bg)
00713          aapixels[0] = bg = (fg > 0) ? fg - 1 : fg + 1;
00714        oldfg_h=fg;
00715        oldbg_h=bg;
00716        T1_AAHSetGrayValues( aapixels); 
00717       }
00718       break;
00719     }
00720     lastlevel=j;
00721     oldfg=fg;
00722     oldbg=bg;
00723   }
00724 
00725   
00726   if ((pglyph=T1_AASetString( FontID, string, len, 
00727                            spaceoff, modflag, size,
00728                            transform))==NULL){
00729     T1_PrintLog( "T1_AASetStringX()",
00730                "T1_AASetString() returned NULL-pointer!",
00731                T1LOG_WARNING);
00732     return(NULL);
00733   }
00734 
00735   /* Check for empty bitmap */
00736   if (pglyph->bits==NULL) {
00737     xglyph=*pglyph;
00738     return( &xglyph);
00739   }
00740 
00741   width=pglyph->metrics.rightSideBearing-pglyph->metrics.leftSideBearing;
00742   height=pglyph->metrics.ascent-pglyph->metrics.descent;
00743   
00744   
00745   /* Correct position */
00746   if (T1_lposition){
00747     x_dest += pglyph->metrics.leftSideBearing;
00748     y_dest -= pglyph->metrics.ascent;
00749   }
00750 
00751   if (opaque==0){
00752     clipmask_v=height;
00753     clipmask_h=width;
00754     width_pad=PAD(width*T1aa_bpp, pFontBase->bitmap_pad)/T1aa_bpp;
00755     clipmask_ptr=(char *)calloc((PAD(clipmask_h, 8)>>3) * clipmask_v, sizeof( char));
00756     if (clipmask_ptr==NULL){
00757       T1_errno=T1ERR_ALLOC_MEM;
00758       return(NULL);
00759     }
00760     /* Note: We pad the clipmask always to byte boundary */
00761     if (pglyph->bpp==8)
00762       for ( k=0; k<clipmask_v; k++){
00763        line_off=k*(PAD(clipmask_h, 8)>>3);
00764        for (j=0; j<clipmask_h; j++){
00765          if (((char *)(pglyph->bits))[k*width_pad+j]!=bg)
00766            clipmask_ptr[line_off+(j>>3)] |= (0x01<<(j%8));
00767        }
00768       }
00769     else if (pglyph->bpp==16)
00770       for ( k=0; k<clipmask_v; k++){
00771        line_off=k*(PAD(clipmask_h, 8)>>3);
00772        for (j=0; j<clipmask_h; j++){
00773          if (((T1_AA_TYPE16 *)(pglyph->bits))[k*width_pad+j]!=(T1_AA_TYPE16)bg)
00774            clipmask_ptr[line_off+(j>>3)] |= (0x01<<(j%8));
00775        }
00776       }
00777     else 
00778       for ( k=0; k<clipmask_v; k++){
00779        line_off=k*(PAD(clipmask_h, 8)>>3);
00780        for (j=0; j<clipmask_h; j++){
00781          if (((T1_AA_TYPE32 *)(pglyph->bits))[k*width_pad+j]!=(T1_AA_TYPE32)bg)
00782            clipmask_ptr[line_off+(j>>3)] |= (0x01<<(j%8));
00783        }
00784       }
00785     
00786     clipmask=XCreateBitmapFromData( T1_display,
00787                                 d,
00788                                 (char *)clipmask_ptr,
00789                                 width,
00790                                 height
00791                                 );
00792     free( clipmask_ptr);
00793     XSetClipMask(T1_display, gc, clipmask);
00794     XSetClipOrigin(T1_display, gc, x_dest, y_dest);
00795 
00796   }
00797   ximage=XCreateImage( T1_display,
00798                      T1_visual,
00799                      T1_depth, 
00800                      ZPixmap, /* XYBitmap or XYPixmap */
00801                      0, /* No offset */
00802                      (char *)pglyph->bits,
00803                      width,
00804                      height,
00805                      pFontBase->bitmap_pad,  /* lines padded to bytes */
00806                      0 /*PAD(width,8)/8*/  /* number of bytes per line */
00807                      );
00808   ximage->byte_order=T1_byte_order;
00809   XPutImage(T1_display,
00810            d,
00811            gc,
00812            ximage,
00813            0,  
00814            0,  
00815            x_dest,  
00816            y_dest,  
00817            width,
00818            height
00819            );
00820   XDestroyImage(ximage);
00821   if (clipmask){
00822     XFreePixmap( T1_display, clipmask);
00823     clipmask=0;
00824     XSetClipMask(T1_display, gc, None);
00825     XSetClipOrigin(T1_display, gc, 0, 0);
00826   }
00827   
00828   pglyph->bits=NULL;    /* Since XDestroyImage() free's this also! */
00829   xglyph.metrics.leftSideBearing=pglyph->metrics.leftSideBearing;
00830   xglyph.metrics.rightSideBearing=pglyph->metrics.rightSideBearing;
00831   xglyph.metrics.advanceX=pglyph->metrics.advanceX;
00832   xglyph.metrics.advanceY=pglyph->metrics.advanceY;
00833   xglyph.metrics.ascent=pglyph->metrics.ascent;
00834   xglyph.metrics.descent=pglyph->metrics.descent;
00835   xglyph.bpp=pglyph->bpp;
00836   
00837   return( &xglyph);
00838   
00839   
00840 }
00841 
00842 
00843 
00844 /* T1_AASetCharX(): Draw a rectangle into an x11 drawable */
00845 GLYPH *T1_AASetRectX( Drawable d, GC gc, int mode, int x_dest, int y_dest,
00846                     int FontID, float size,
00847                     float rwidth, float rheight,
00848                     T1_TMATRIX *transform)
00849 {
00850   int j, k;
00851 
00852   GLYPH  *pglyph;
00853   XImage *ximage;
00854 
00855   static GLYPH xglyph={NULL,{0,0,0,0,0,0},NULL,0};
00856  
00857   int height, width, width_pad;
00858   
00859   XGCValues xgcvalues;
00860   static unsigned long fg, bg;
00861 
00862   Pixmap clipmask=0;
00863   int clipmask_h, clipmask_v, line_off;
00864   char *clipmask_ptr;
00865   
00866   int opaque;
00867   
00868 
00869               
00870   xglyph.metrics.leftSideBearing=0;
00871   xglyph.metrics.rightSideBearing=0;
00872   xglyph.metrics.advanceX=0;
00873   xglyph.metrics.advanceY=0;
00874   xglyph.metrics.ascent=0;
00875   xglyph.metrics.descent=0;
00876   xglyph.pFontCacheInfo=NULL;
00877   
00878 
00879   opaque=mode;
00880   
00881   xglyph.bpp=T1_depth;
00882   
00883   /* In order to be able to contruct the pixmap we need to know
00884      foreground and background color as well the copy function */
00885   XGetGCValues( T1_display, gc, T1GCMASK, &xgcvalues);
00886   fg=xgcvalues.foreground;
00887   bg=xgcvalues.background;
00888   
00889 
00890   /* At this point we must compute the colors that are needed to do
00891      antialiasing between fore- and background. The following function
00892      fills the static aacolors */
00893   if (T1aa_SmartOn==0)
00894     j=T1_AAGetLevel();
00895   else if (size>=T1aa_smartlimit2)
00896     j=1;
00897   else if (size>=T1aa_smartlimit1)
00898     j=2;
00899   else
00900     j=4;
00901   if ( j!=lastlevel || fg!=oldfg || bg!=oldbg ){
00902     switch ( j){
00903     case 1:
00904       if ( fg!=oldfg_n || bg!=oldbg_n){
00905        oldfg_n=fg;
00906        oldbg_n=bg;
00907        /* computing colors is not necessary here */
00908        T1_AANSetGrayValues( bg, fg);
00909       }
00910       break;
00911     case 2:
00912       if ( fg!=oldfg_l || bg!=oldbg_l){
00913        T1_ComputeAAColorsX( fg, bg, AAMAXPLANES);
00914        /*~derekn*/
00915        /* If fg=bg, the clipmask will be messed up; in this case  */
00916        /* we can arbitrarily change bg to get a correct clipmask. */
00917        if (opaque == 0 && fg == bg)
00918          aapixels[0] = bg = (fg > 0) ? fg - 1 : fg + 1;
00919        oldfg_l=fg;
00920        oldbg_l=bg;
00921        T1_AASetGrayValues(aapixels[0],   /* white */
00922                         aapixels[4],
00923                         aapixels[8],
00924                         aapixels[12],
00925                         aapixels[16] ); /* black */
00926       }
00927       break;
00928     case 4:
00929       if ( fg!=oldfg_h || bg!=oldbg_h){
00930        T1_ComputeAAColorsX( fg, bg, AAMAXPLANES);
00931        /*~derekn*/
00932        /* If fg=bg, the clipmask will be messed up; in this case  */
00933        /* we can arbitrarily change bg to get a correct clipmask. */
00934        if (opaque == 0 && fg == bg)
00935          aapixels[0] = bg = (fg > 0) ? fg - 1 : fg + 1;
00936        oldfg_h=fg;
00937        oldbg_h=bg;
00938        T1_AAHSetGrayValues( aapixels); 
00939       }
00940       break;
00941     }
00942     lastlevel=j;
00943     oldfg=fg;
00944     oldbg=bg;
00945   }
00946 
00947   if ((pglyph=T1_AASetRect( FontID, size, rwidth, rheight, transform))==NULL){
00948     T1_PrintLog( "T1_AASetRectX()",
00949                "T1_AASetRect() returned NULL-pointer!",
00950                T1LOG_WARNING);
00951     return(NULL);
00952   }
00953 
00954   /* Check for empty bitmap */
00955   if (pglyph->bits==NULL) {
00956     xglyph=*pglyph;
00957     return( &xglyph);
00958   }
00959 
00960   width=pglyph->metrics.rightSideBearing-pglyph->metrics.leftSideBearing;
00961   height=pglyph->metrics.ascent-pglyph->metrics.descent;
00962   
00963               
00964   /* Correct position */
00965   if (T1_lposition){
00966     x_dest += pglyph->metrics.leftSideBearing;
00967     y_dest -= pglyph->metrics.ascent;
00968   }
00969 
00970   if (opaque==0){
00971     clipmask_v=height;
00972     clipmask_h=width;
00973     width_pad=PAD(width*T1aa_bpp, pFontBase->bitmap_pad)/T1aa_bpp;
00974     clipmask_ptr=(char *)calloc((PAD(clipmask_h, 8)>>3) * clipmask_v, sizeof( char)); 
00975     if (clipmask_ptr==NULL){
00976       T1_errno=T1ERR_ALLOC_MEM;
00977       return(NULL);
00978     }
00979     /* Note: We pad the clipmask always to byte boundary */
00980     if (pglyph->bpp==8)
00981       for ( k=0; k<clipmask_v; k++){
00982        line_off=k*(PAD(clipmask_h, 8)>>3);
00983        for (j=0; j<clipmask_h; j++){
00984          if (((char *)(pglyph->bits))[k*width_pad+j]!=bg)
00985            clipmask_ptr[line_off+(j>>3)] |= (0x01<<(j%8));
00986        }
00987       }
00988     else if (pglyph->bpp==16)
00989       for ( k=0; k<clipmask_v; k++){
00990        line_off=k*(PAD(clipmask_h, 8)>>3);
00991        for (j=0; j<clipmask_h; j++){
00992          if (((T1_AA_TYPE16 *)(pglyph->bits))[k*width_pad+j]!=(T1_AA_TYPE16)bg)
00993            clipmask_ptr[line_off+(j>>3)] |= (0x01<<(j%8));
00994        }
00995       }
00996     else 
00997       for ( k=0; k<clipmask_v; k++){
00998        line_off=k*(PAD(clipmask_h, 8)>>3);
00999        for (j=0; j<clipmask_h; j++){
01000          if (((T1_AA_TYPE32 *)(pglyph->bits))[k*width_pad+j]!=(T1_AA_TYPE32)bg)
01001            clipmask_ptr[line_off+(j>>3)] |= (0x01<<(j%8));
01002        }
01003       }
01004     
01005     clipmask=XCreateBitmapFromData( T1_display,
01006                                 d,
01007                                 (char *)clipmask_ptr,
01008                                 width,
01009                                 height
01010                                 );
01011     free( clipmask_ptr);
01012     XSetClipMask(T1_display, gc, clipmask);
01013     XSetClipOrigin(T1_display, gc, x_dest, y_dest);
01014 
01015   }
01016   ximage=XCreateImage( T1_display,
01017                      T1_visual,
01018                      T1_depth, 
01019                      ZPixmap, /* XYBitmap or XYPixmap */
01020                      0, /* No offset */
01021                      (char *)pglyph->bits,
01022                      width,
01023                      height,
01024                      pFontBase->bitmap_pad,  
01025                      0 /*PAD(width,8)/8*/  /* number of bytes per line */
01026                      );
01027   ximage->byte_order=T1_byte_order;
01028   XPutImage(T1_display,
01029            d,
01030            gc,
01031            ximage,
01032            0,  
01033            0,  
01034            x_dest,  
01035            y_dest,  
01036            width,
01037            height
01038            );
01039   XDestroyImage(ximage);
01040   if (clipmask){
01041     XFreePixmap( T1_display, clipmask);
01042     clipmask=0;
01043     XSetClipMask(T1_display, gc, None);
01044     XSetClipOrigin(T1_display, gc, 0, 0);
01045   }
01046   
01047   pglyph->bits=NULL;    /* Since XDestroyImage() free's this also! */
01048   xglyph.metrics.leftSideBearing=pglyph->metrics.leftSideBearing;
01049   xglyph.metrics.rightSideBearing=pglyph->metrics.rightSideBearing;
01050   xglyph.metrics.advanceX=pglyph->metrics.advanceX;
01051   xglyph.metrics.advanceY=pglyph->metrics.advanceY;
01052   xglyph.metrics.ascent=pglyph->metrics.ascent;
01053   xglyph.metrics.descent=pglyph->metrics.descent;
01054   xglyph.bpp=pglyph->bpp;
01055   
01056   return( &xglyph);
01057   
01058   
01059 }
01060 
01061 
01062 
01063 /* T1_ComputeAAColorsX(): Compute the antialiasing colors in dependency
01064    of foreground and background */
01065 int T1_ComputeAAColorsX( unsigned long fg, unsigned long bg, int nolevels)
01066 {
01067 
01068   static unsigned long last_fg;
01069   static unsigned long last_bg;
01070   long delta_red, delta_green, delta_blue;
01071   int i;
01072   int nocolors=0;
01073   
01074   
01075   aacolors[0].pixel=bg;
01076   aacolors[nolevels-1].pixel=fg;
01077 
01078   if ((fg==last_fg)&&(bg==last_bg))
01079     return(nocolors);
01080   
01081   /* Get RGB values for fore- and background */
01082   XQueryColor( T1_display, T1_colormap, &aacolors[0]);
01083   XQueryColor( T1_display, T1_colormap, &aacolors[nolevels-1]);
01084   delta_red   = (aacolors[nolevels-1].red - aacolors[0].red)/(nolevels-1);
01085   delta_green = (aacolors[nolevels-1].green - aacolors[0].green)/(nolevels-1);
01086   delta_blue  = (aacolors[nolevels-1].blue - aacolors[0].blue)/(nolevels-1);
01087   aapixels[0]=aacolors[0].pixel;
01088   aapixels[nolevels-1]=aacolors[nolevels-1].pixel;
01089 
01090   for (i=1; i<nolevels-1; i++){
01091     aacolors[i].red   = aacolors[0].red + i*delta_red;
01092     aacolors[i].green = aacolors[0].green + i*delta_green;
01093     aacolors[i].blue  = aacolors[0].blue + i*delta_blue;
01094     aacolors[i].flags = DoRed | DoGreen | DoBlue;
01095     aacolors[i].pad   = aacolors[0].pad;
01096     /* Allocate color in current palette */
01097     if (XAllocColor( T1_display, T1_colormap, &aacolors[i])!=0){
01098       aapixels[i]=aacolors[i].pixel;
01099       nocolors++;
01100     }
01101   }
01102   
01103   return(nocolors);
01104 
01105 }
01106 
01107 
01108 
01109 /* Set the positioning switch */
01110 void T1_LogicalPositionX( int pos_switch)
01111 {
01112   if (pos_switch)
01113     T1_lposition=1;
01114   else
01115     T1_lposition=0;
01116   return;
01117 }
01118 
01119 
01120 
01121 XImage *T1_XImageFromGlyph( GLYPH *pglyph)
01122 {
01123   XImage *ximage;
01124   
01125   /* Check for empty bitmap */
01126   if (pglyph->bits==NULL) {
01127     T1_errno=T1ERR_INVALID_PARAMETER;
01128     return( NULL);
01129   }
01130 
01131   if (pglyph->bpp==1) { /* we have a bitmap glyph */
01132     ximage=XCreateImage( T1_display,
01133                       T1_visual,
01134                       1, 
01135                       XYBitmap, /* XYBitmap or XYPixmap */
01136                       0, /* No offset */
01137                       (char *)pglyph->bits,
01138                       pglyph->metrics.rightSideBearing-pglyph->metrics.leftSideBearing,
01139                       pglyph->metrics.ascent-pglyph->metrics.descent,
01140                       pFontBase->bitmap_pad,  
01141                       0  /* number of bytes per line */
01142                       );
01143   }
01144   else { /* we have an anztialiased glyph */
01145     ximage=XCreateImage( T1_display,
01146                       T1_visual,
01147                       T1_depth, 
01148                       ZPixmap, /* XYBitmap or XYPixmap */
01149                       0, /* No offset */
01150                       (char *)pglyph->bits,
01151                       pglyph->metrics.rightSideBearing-pglyph->metrics.leftSideBearing,
01152                       pglyph->metrics.ascent-pglyph->metrics.descent,
01153                       pFontBase->bitmap_pad,  
01154                       0  /* number of bytes per line */
01155                       );
01156   }
01157   
01158   if (ximage==NULL) {
01159     T1_errno=T1ERR_X11;
01160     return( NULL);
01161   }
01162   ximage->byte_order=T1_byte_order; /* Set t1libīs byteorder */
01163 
01164   return( ximage);
01165 
01166 }
01167