📄 t1set.c
字号:
/*-------------------------------------------------------------------------- ----- File: t1set.c ----- Author: Rainer Menzner (Rainer.Menzner@web.de) ----- Date: 2001-05-27 ----- Description: This file is part of the t1-library. It contains functions for setting characters and strings of characters. ----- Copyright: t1lib is copyrighted (c) Rainer Menzner, 1996-2001. As of version 0.5, t1lib is distributed under the GNU General Public Library Lincense. The conditions can be found in the files LICENSE and LGPL, which should reside in the toplevel directory of the distribution. Please note that there are parts of t1lib that are subject to other licenses: The parseAFM-package is copyrighted by Adobe Systems Inc. The type1 rasterizer is copyrighted by IBM and the X11-consortium. ----- Warranties: Of course, there's NO WARRANTY OF ANY KIND :-) ----- Credits: I want to thank IBM and the X11-consortium for making their rasterizer freely available. Also thanks to Piet Tutelaers for his ps2pk, from which I took the rasterizer sources in a format independent from X11. Thanks to all people who make free software living!--------------------------------------------------------------------------*/ #define T1SET_C#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#if defined(_MSC_VER)# include <io.h># include <sys/types.h># include <sys/stat.h>#else# include <unistd.h>#endif#include <stdlib.h>#include <math.h>#include <string.h>#include <setjmp.h>#include "../type1/ffilest.h" #include "../type1/types.h"#include "parseAFM.h" #include "../type1/objects.h"#include "../type1/spaces.h"#include "../type1/util.h"#include "../type1/fontfcn.h"#include "../type1/regions.h"#include "t1types.h"#include "t1extern.h"#include "t1set.h"#include "t1load.h"#include "t1finfo.h"#include "t1misc.h"#include "t1base.h"/* As a fall back */#ifndef T1_AA_TYPE16 #define T1_AA_TYPE16 short#endif#ifndef T1_AA_TYPE32 #define T1_AA_TYPE32 int#endifextern char *t1_get_abort_message( int number);extern struct region *Interior(struct segment *path, int fillrule);extern unsigned T1_AA_TYPE32 T1aa_bg; /* white value */ static int T1_bit=T1GLYPH_BIT;static int T1_byte;static int T1_pad;static int T1_wordsize;static int c_shift=8;static int s_shift=16;static int l_shift=32;/* T1_SetChar(...): Generate the bitmap for a character */GLYPH *T1_SetChar( int FontID, char charcode, float size, T1_TMATRIX *transform){ int i; int mode; struct region *area; struct XYspace *Current_S; int cache_flag=1; int rot_flag=0; unsigned char ucharcode; FONTSIZEDEPS *font_ptr; FONTPRIVATE *fontarrayP; volatile int memsize=0; LONG h,w; LONG paddedW; /* We don't implement underlining for characters, but the rasterer implements it. Thus, we use a modflag of constant 0 */ int modflag=0; static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1}; /* We return to this if something goes wrong deep in the rasterizer */ if ((i=setjmp( stck_state))!=0) { T1_errno=T1ERR_TYPE1_ABORT; sprintf( err_warn_msg_buf, "t1_abort: Reason: %s", t1_get_abort_message( i)); T1_PrintLog( "T1_SetChar()", err_warn_msg_buf, T1LOG_ERROR); return( NULL); } ucharcode=(unsigned char)charcode; /* Reset character glyph, if necessary */ if (glyph.bits!=NULL){ free(glyph.bits); glyph.bits=NULL; } glyph.metrics.leftSideBearing=0; glyph.metrics.rightSideBearing=0; glyph.metrics.advanceX=0; glyph.metrics.advanceY=0; glyph.metrics.ascent=0; glyph.metrics.descent=0; glyph.pFontCacheInfo=NULL; glyph.bpp=1; /* First, check for a correct ID */ i=CheckForFontID(FontID); if (i==-1){ T1_errno=T1ERR_INVALID_FONTID; return(NULL); } /* if necessary load font into memory */ if (i==0) if (T1_LoadFont(FontID)) return(NULL); /* Check for valid size */ if (size<=0.0){ T1_errno=T1ERR_INVALID_PARAMETER; return(NULL); } /* Assign padding value */ T1_pad=pFontBase->bitmap_pad; if (pFontBase->endian) T1_byte=1; else T1_byte=0; T1_wordsize=T1_pad; fontarrayP=&(pFontBase->pFontArray[FontID]); /* Check if rotation is requested */ if (transform!=NULL){ /* there's rotation requested => do not cache the resulting bitmap */ rot_flag=1; cache_flag=0; } else { rot_flag=0; cache_flag=1; } /* font is now loaded into memory => Check for size: */ if ((font_ptr=QueryFontSize( FontID, size, NO_ANTIALIAS))==NULL){ font_ptr=CreateNewFontSize( FontID, size, NO_ANTIALIAS); if (font_ptr==NULL){ T1_errno=T1ERR_ALLOC_MEM; return(NULL); } } else {/* size is already existent in cache */ /* If no rotation, try to get character from cache */ if (rot_flag==0){ /* we don't use the .bits entry to check because in newer releases also white glyphs (bits=NULL) are allowed. Rather, we check whether bpp > 0! */ if (font_ptr->pFontCache[ucharcode].bpp > 0){ /* Character is already in Chache -> create a copy of cache and return a pointer to the result: */ memcpy( &glyph, &(font_ptr->pFontCache[ucharcode]), sizeof(GLYPH)); paddedW = PAD((glyph.metrics.rightSideBearing-glyph.metrics.leftSideBearing), T1_pad); if (font_ptr->pFontCache[ucharcode].bits!=NULL) { memsize = (glyph.metrics.ascent-glyph.metrics.descent)*paddedW / 8; glyph.bits = (char *)malloc(memsize*sizeof( char)); if (glyph.bits == NULL){ T1_errno=T1ERR_ALLOC_MEM; return(NULL); } memcpy( glyph.bits, font_ptr->pFontCache[ucharcode].bits, memsize); } return(&(glyph)); } } } /* Setup an appropriate charspace matrix. Note that the rasterizer assumes vertical values with inverted sign! Transformation should create a copy of the local charspace matrix which then still has to be made permanent. */ if (rot_flag){ Current_S=(struct XYspace *) Permanent(Scale(Transform (font_ptr->pCharSpaceLocal, transform->cxx, - transform->cxy, transform->cyx, - transform->cyy), DeviceSpecifics.scale_x, DeviceSpecifics.scale_y)); } else{ Current_S=(struct XYspace *) Permanent(Scale(Transform(font_ptr->pCharSpaceLocal, 1.0, 0.0, 0.0, -1.0), DeviceSpecifics.scale_x, DeviceSpecifics.scale_y)); } /* fnt_ptr now points to the correct FontSizeDeps-struct => lets now raster the character */ mode=0; area=fontfcnB( FontID, modflag, Current_S, fontarrayP->pFontEnc, ucharcode, &mode, fontarrayP->pType1Data, DO_RASTER); KillSpace (Current_S); /* fill the glyph-structure */ if (mode > 0) { sprintf( err_warn_msg_buf, "fontfcnB() set mode=%d", mode); T1_PrintLog( "T1_SetChar()", err_warn_msg_buf, T1LOG_WARNING); T1_errno=mode; return(NULL); } if (area == NULL){ T1_PrintLog( "T1_SetChar()", "area=NULL returned by fontfcnB()", T1LOG_WARNING); T1_errno=mode; return(NULL); } h = area->ymax - area->ymin; w = area->xmax - area->xmin; if (mode == FF_NOTDEF_SUBST) { sprintf( err_warn_msg_buf, "\".notdef\" substituted for character %d from font %d", ucharcode, FontID); T1_PrintLog( "T1_SetChar()", err_warn_msg_buf, T1LOG_WARNING); mode=0; } paddedW = PAD(w, T1_pad); if (h > 0 && w > 0) { memsize = h * paddedW / 8 + 1; /* This is for the users copy of the character, for security-reasons the original pointer to the cache area is not used. The entry glyph.bits is free'ed every time this function is called: */ glyph.bits = (char *)malloc(memsize*sizeof( char)); if (glyph.bits == NULL){ T1_errno=T1ERR_ALLOC_MEM; /* make sure to get rid of 'area' before leaving! */ KillRegion (area); return(NULL); } } else { h = w = 0; area->xmin = area->xmax = 0; area->ymin = area->ymax = 0; } /* Assign metrics */ glyph.metrics.leftSideBearing = area->xmin; glyph.metrics.advanceX = NEARESTPEL(area->ending.x - area->origin.x); glyph.metrics.advanceY = - NEARESTPEL(area->ending.y - area->origin.y); glyph.metrics.rightSideBearing = area->xmax; glyph.metrics.descent = - area->ymax; glyph.metrics.ascent = - area->ymin; if (h > 0 && w > 0) { (void) memset(glyph.bits, 0, memsize); fill(glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize ); } /* make sure to get rid of 'area' before leaving! */ KillRegion (area); /* Cache glyph if requested, also if it contains only white space */ if (cache_flag){ /* Copy glyph to cache but be careful not to modify the pixmap entry */ font_ptr->pFontCache[ucharcode].metrics.leftSideBearing=glyph.metrics.leftSideBearing; font_ptr->pFontCache[ucharcode].metrics.rightSideBearing=glyph.metrics.rightSideBearing; font_ptr->pFontCache[ucharcode].metrics.advanceX=glyph.metrics.advanceX; font_ptr->pFontCache[ucharcode].metrics.advanceY=glyph.metrics.advanceY; font_ptr->pFontCache[ucharcode].metrics.ascent=glyph.metrics.ascent; font_ptr->pFontCache[ucharcode].metrics.descent=glyph.metrics.descent; font_ptr->pFontCache[ucharcode].pFontCacheInfo=glyph.pFontCacheInfo; font_ptr->pFontCache[ucharcode].bpp=glyph.bpp; if (glyph.bits==NULL) { font_ptr->pFontCache[ucharcode].bits=NULL; } else { font_ptr->pFontCache[ucharcode].bits = (char *)malloc(memsize*sizeof( char)); if (font_ptr->pFontCache[ucharcode].bits == NULL){ T1_errno=T1ERR_ALLOC_MEM; return(NULL); } /* ... and copy bitmap to cache area: */ memcpy( font_ptr->pFontCache[ucharcode].bits, glyph.bits, memsize); } } return(&glyph);}/* T1_SetString(...): Generate the bitmap for a string of characters */GLYPH *T1_SetString( int FontID, char *string, volatile int len, long spaceoff, int modflag, float size, T1_TMATRIX *transform){ volatile int i, j=0, k; int mode; /* initialize this to NULL just to be on the safe side */ struct region *area = NULL; struct XYspace *Current_S, *S; int cache_flag=1; volatile int rot_flag=0; int *kern_pairs; /* use for accessing the kern pairs if kerning is requested */ int no_chars=0; /* The number of characters in the string */ static int lastno_chars=0; float factor; long spacewidth; /* This is given to fontfcnb_string() */ FONTSIZEDEPS *font_ptr; FONTPRIVATE *fontarrayP; volatile int memsize=0; long h,w; long paddedW, char_paddedW; int h_anchor, v_anchor; static int *pixel_h_anchor_corr=NULL; static int *flags=NULL; int lsb_min, rsb_max; long overallwidth=0; long overallascent=0; long overalldescent=0; int underline_startx, underline_starty, underline_endx, underline_endy; int overline_startx, overline_starty, overline_endx, overline_endy; int overstrike_startx, overstrike_starty, overstrike_endx, overstrike_endy; int start, middle; int afm_ind; char startmask, endmask; static unsigned char *r2lstring; static int r2l_len=0; static GLYPH string_glyph={NULL,{0,0,0,0,0,0},NULL,1}; GLYPH *currchar; /* The following are for bitmap blitting */ long BitShift; long ByteOffset; /* pad=8 */ unsigned T1_AA_TYPE16 BitBuf_c; unsigned char *p_c; unsigned char *Target_c; /* pad=16 */ unsigned T1_AA_TYPE32 BitBuf_s; unsigned T1_AA_TYPE16 *p_s; unsigned T1_AA_TYPE16 *Target_s;#ifdef T1_AA_TYPE64 /* pad=32 */ unsigned T1_AA_TYPE64 BitBuf_l; unsigned T1_AA_TYPE32 *p_l; unsigned T1_AA_TYPE32 *Target_l;#endif unsigned char *ustring; /* We return to this if something goes wrong deep in the rasterizer */ if ((i=setjmp( stck_state))!=0) { T1_errno=T1ERR_TYPE1_ABORT; sprintf( err_warn_msg_buf, "t1_abort: Reason: %s", t1_get_abort_message( i)); T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_ERROR); return( NULL); } /* force string elements into unsigned */ ustring=(unsigned char*)string; /* Check for valid string */ if (string==NULL){ T1_errno=T1ERR_INVALID_PARAMETER; return(NULL); } /* Reorganize if required */ if (modflag & T1_RIGHT_TO_LEFT){ if (len) i=len; else i=j=strlen( string); if (i+1>r2l_len){ if (r2lstring!=NULL) free( r2lstring); r2lstring=(unsigned char *)malloc( (i+1)*sizeof(char)); r2l_len=i+1; } j--; while ( i--) { r2lstring[j-i]=ustring[i]; } ustring=r2lstring; len=j+1; } /* Reset string glyph, if necessary */ if (string_glyph.bits!=NULL){ free(string_glyph.bits); string_glyph.bits=NULL; } string_glyph.metrics.leftSideBearing=0; string_glyph.metrics.rightSideBearing=0; string_glyph.metrics.advanceX=0; string_glyph.metrics.advanceY=0; string_glyph.metrics.ascent=0; string_glyph.metrics.descent=0; string_glyph.pFontCacheInfo=NULL; string_glyph.bpp=1; /* We don't want to cache the resulting bitmap: */ cache_flag=0; /* First, check for a correct ID */ i=CheckForFontID(FontID); if (i==-1){ T1_errno=T1ERR_INVALID_FONTID; return(NULL); } /* if necessary load font into memory */ if (i==0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -