📄 t1set.c
字号:
if (T1_LoadFont(FontID)) return(NULL); /* If no AFM info is present, we return an error */ if (pFontBase->pFontArray[FontID].pAFMData==NULL) { T1_errno=T1ERR_NO_AFM_DATA; 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; } /* 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); } } /* Now comes string specific stuff: Get length of string and create an array of integers where to store the bitmap positioning dimens: */ if (len<0){ /* invalid length */ T1_errno=T1ERR_INVALID_PARAMETER; return(NULL); } if (len==0) /* should be computed assuming "normal" 0-terminated string, or R2L-part has already been computed! */ no_chars=strlen(string); else /* use value given on command line */ no_chars=len; /* If necessary, allocate memory */ if (no_chars>lastno_chars){ if (pixel_h_anchor_corr!=NULL){ free(pixel_h_anchor_corr); } if (flags!=NULL){ free(flags); } pixel_h_anchor_corr=(int *)calloc(no_chars, sizeof(int)); flags=(int *)calloc(no_chars, sizeof(int)); lastno_chars=no_chars; } else{ /* Reset flags and position array */ for (i=0; i<no_chars; i++){ flags[i]=0; pixel_h_anchor_corr[i]=0; } } /* 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)); } /* Compute the correct spacewidth value (in charspace units). The value supplied by the user is interpreted as an offset in char space units: */ spacewidth=T1_GetCharWidth(FontID,fontarrayP->space_position)+spaceoff; /* The following if (rot_flag==0){ ... } contains the whole code to execute when the string is oriented horizontal. Then, there's the possibility of concatenating most probably existent bitmaps from the Cache, which should be much faster than every time raster all the characters. */ /* First, ensure that all needed characters are in the Cache; if not, generate them */ if ((rot_flag==0)){ overallwidth=0; for (i=0; i<no_chars; i++) { currchar= &(font_ptr->pFontCache[ustring[i]]); if (currchar->bpp<1) { flags[i]=0; mode=0; /* Don't try to generate space-character: */ if (ustring[i]!=fontarrayP->space_position){ /* Note: Never underline etc. cached chars --> modflag=0 */ area=fontfcnB( FontID, 0, Current_S, fontarrayP->pFontEnc, ustring[i], &mode, fontarrayP->pType1Data, DO_RASTER); /* fill the glyph-structure */ if (mode > 0) { sprintf( err_warn_msg_buf, "fontfcnB() set mode=%d", mode); T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING); T1_errno=mode; /* Make sure to free the region if it's non-NULL */ if (area){ KillRegion (area); } return(NULL); } if (area == NULL){ T1_PrintLog( "T1_SetString()", "area=NULL returned by fontfcnB()", T1LOG_WARNING); T1_errno=mode; return(NULL); } if (mode == FF_NOTDEF_SUBST) { sprintf( err_warn_msg_buf, "\".notdef\" substituted in string[%d] (=character %d) from font %d", i, ustring[i], FontID); T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING); mode=0; flags[i]=1; /* indicates that .notdef has been substituted */ } h = area->ymax - area->ymin; w = area->xmax - area->xmin; if (h > 0 && w > 0) { /* bitmap contains pixels */ paddedW = PAD(w, T1_pad); memsize = h * paddedW / 8 + 1; currchar->bits = (char *)malloc(memsize*sizeof( char)); if (currchar->bits == NULL) { T1_errno=T1ERR_ALLOC_MEM; /* Make sure to free up the region if it's non-NULL */ if (area){ KillRegion (area); } return(NULL); } (void) memset(currchar->bits, 0, memsize); fill(currchar->bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize ); } /* area valid -> set metrics in cache for that character */ currchar->metrics.leftSideBearing = area->xmin; currchar->metrics.advanceX = NEARESTPEL(area->ending.x - area->origin.x); currchar->metrics.advanceY = - NEARESTPEL(area->ending.y - area->origin.y); currchar->metrics.rightSideBearing = area->xmax; currchar->metrics.descent = - area->ymax; currchar->metrics.ascent = - area->ymin; currchar->bpp=1; /* By this point, it's clear that the 'area' struct exists, and that we no longer need it, so free it up. */ KillRegion (area); } } /* end of if ( ... ), needed characters are now in cache! */ } /* end of for (i<no_chars) loop */ /* we still have to delete the Space */ KillSpace (Current_S); /* We've to compute the scale factor: */ factor=size*DeviceSpecifics.scale_x/1000; /* h_anchor is the horizontal position in the resulting bitmap; it is incremented on the fly and of course initially 0! */ h_anchor=0; /* These are the initial values for left and right sidebearing */ rsb_max=-30000; lsb_min= 30000; overallascent=-30000; overalldescent=30000; for (i=0;i<no_chars;i++){ /* first get index into AFM-tables */ afm_ind=pFontBase->pFontArray[FontID].pEncMap[(int) ustring[i]]; /* Advance to next character in high resolution */ if (ustring[i]==fontarrayP->space_position) h_anchor +=(int)spacewidth; /* check for a substituted char or notdef and get missing escapement */ else if (afm_ind==0) { /* Setup apropriate charspace matrix */ S=(struct XYspace *)IDENTITY; /* Make this permanent so that scaling it in fontfcnB_ByName will make a duplicate of it, and this duplicate can thus be safely destroyed. Fixes the somewhat smaller memory leak */ S=(struct XYspace *)Permanent (Transform(S, pFontBase->pFontArray[FontID].FontTransform[0], pFontBase->pFontArray[FontID].FontTransform[1], pFontBase->pFontArray[FontID].FontTransform[2], pFontBase->pFontArray[FontID].FontTransform[3])); /* Get metrics values */ area=fontfcnB_ByName( FontID, 0, S, ".notdef", &mode, pFontBase->pFontArray[FontID].pType1Data, DO_RASTER); if (area==NULL || mode!=0){ sprintf( err_warn_msg_buf, "Could not get charspace representation of \".notdef\", Font %d, mode=%d!", FontID, mode); T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_ERROR); T1_errno=mode; return( NULL); } /* value to add to hanchor */ h_anchor +=NEARESTPEL(area->ending.x); /* make sure to free S */ if (S) { KillSpace (S); } /* make sure to free area */ if (area) { KillRegion (area); } } else{ currchar=&(font_ptr->pFontCache[ustring[i]]); pixel_h_anchor_corr[i]=((int)floor(h_anchor*factor+0.5)); /* Store maximum rsb ...*/ if ( pixel_h_anchor_corr[i]+currchar->metrics.rightSideBearing > rsb_max){ rsb_max=pixel_h_anchor_corr[i]+currchar->metrics.rightSideBearing; } /* ... and minimum lsb */ if ( pixel_h_anchor_corr[i]+currchar->metrics.leftSideBearing < lsb_min){ lsb_min=pixel_h_anchor_corr[i]+currchar->metrics.leftSideBearing; } /* Advance by current chars width */ /* h_anchor +=T1_GetCharWidth( FontID, ustring[i]); */ if (afm_ind>0) { /* we have a standard character */ h_anchor +=(fontarrayP->pAFMData->cmi[afm_ind-1].wx) * fontarrayP->extend; } else { /* afm_ind must be negative so that we have a composite char */ h_anchor +=(fontarrayP->pAFMData->ccd[-(afm_ind+1)].wx) * fontarrayP->extend; } /* If kerning, insert kerning amount */ if ((i<no_chars -1) && (modflag & T1_KERNING)) h_anchor +=T1_GetKerning( FontID, ustring[i], ustring[i+1]); /* We still have to care for vertical metrics: */ if (currchar->metrics.ascent>overallascent) overallascent=currchar->metrics.ascent; if (currchar->metrics.descent<overalldescent) overalldescent=currchar->metrics.descent; } } string_glyph.metrics.advanceX=(int)floor(h_anchor*factor+0.5); /* We have to check for underlining and such things. They may affect the bounding box of the glyph */ if (modflag & T1_UNDERLINE){ T1_ComputeLineParameters( FontID, T1_UNDERLINE, string_glyph.metrics.advanceX, size, &underline_startx, &underline_endx, &underline_starty, &underline_endy); /* Check whether rsb is affected ...*/ if ( underline_endx > rsb_max){ rsb_max=underline_endx; } /* ... and for lsb */ if ( underline_startx < lsb_min){ lsb_min=underline_startx; } /* Vertical metrics may also be affected. */ if (underline_starty > overallascent) overallascent=underline_starty; if (underline_endy < overalldescent) overalldescent=underline_endy; } if (modflag & T1_OVERLINE){ T1_ComputeLineParameters( FontID, T1_OVERLINE, string_glyph.metrics.advanceX, size, &overline_startx, &overline_endx, &overline_starty, &overline_endy); /* Check whether rsb is affected ...*/ if ( overline_endx > rsb_max){ rsb_max=overline_endx; } /* ... and for lsb */ if ( overline_startx < lsb_min){ lsb_min=overline_startx; } /* Vertical metrics may also be affected. */ if (overline_starty > overallascent) overallascent=overline_starty; if (overline_endy < overalldescent) overalldescent=overline_endy; } if (modflag & T1_OVERSTRIKE){ T1_ComputeLineParameters( FontID, T1_OVERSTRIKE, string_glyph.metrics.advanceX, size, &overstrike_startx, &overstrike_endx, &overstrike_starty, &overstrike_endy); /* Check whether rsb is affected ...*/ if ( overstrike_endx > rsb_max){ rsb_max=overstrike_endx; } /* ... and for lsb */ if ( overstrike_startx < lsb_min){ lsb_min=overstrike_startx; } /* Vertical metrics may also be affected. */ if (overstrike_starty > overallascent) overallascent=overstrike_starty; if (overstrike_endy < overalldescent) overalldescent=overstrike_endy; } /* Set the string-glyphs' metrics: */ /* Bearings: */ string_glyph.metrics.rightSideBearing=rsb_max; string_glyph.metrics.leftSideBearing=lsb_min; /* ascent and descent: */ string_glyph.metrics.ascent=overallascent; string_glyph.metrics.descent=overalldescent; /* Now, allocate memory for the resulting bitmap and set it to 0: */ h=overallascent - overalldescent; w=string_glyph.metrics.rightSideBearing-string_glyph.metrics.leftSideBearing; paddedW = PAD( w, T1_pad); if ( h > 0 && w > 0){ memsize = h * paddedW / 8; /* We alloc some amount more in order to avoid alignment check in bit-blitting loop */ memsize += T1_pad/8; string_glyph.bits = (char *)malloc( memsize); if (string_glyph.bits == NULL) { T1_errno=T1ERR_ALLOC_MEM; return(NULL); } } else { /* We have only characters without pixels in the string -> we allow this and only set the advance width in the glyph. The bits pointer will be NULL. We reset rsb and lsb */ string_glyph.metrics.rightSideBearing=0; string_glyph.metrics.leftSideBearing=0; string_glyph.metrics.ascent=0; string_glyph.metrics.descent=0; } if (string_glyph.bits != NULL) { memset(string_glyph.bits, 0, memsize); /* Now comes the loop for bitmap blitting: */ for (i=0;i<no_chars;i++){ /* Get pointer to character number i of string: */ currchar=&(font_ptr->pFontCache[ustring[i]]); /* First, we have to correct the positioning values to refer to the bitmap BBox */ pixel_h_anchor_corr[i] -= lsb_min; pixel_h_anchor_corr[i] += currchar->metrics.leftSideBearing; /* Compute vertical anchor for current char-bitmap: */ v_anchor=overallascent - currchar->metrics.ascent; char_paddedW=PAD( currchar->metrics.rightSideBearing - currchar->metrics.leftSideBearing , T1_pad); /* We have to check for Big Endian. In that case, we have to act on byte-level */ if (T1_byte){ BitShift = pixel_h_anchor_corr[i] % 8; ByteOffset = pixel_h_anchor_corr[i] / 8; } else { BitShift = pixel_h_anchor_corr[i] % T1_pad; ByteOffset = pixel_h_anchor_corr[i] / T1_pad; if (T1_pad==32) ByteOffset *=4; else if (T1_pad==16) ByteOffset *=2; } #ifdef T1_AA_TYPE64 /* We compile this part only if long is 64 bits to be conform to ANSI C */ if (T1_pad==32 && T1_byte==0){ /* The following loop steps through the lines of the character bitmap: */ for (j=0;j<currchar->metrics.ascent-currchar->metrics.descent;j++){ Target_l= (unsigned T1_AA_TYPE32 *)(string_glyph.bits +((v_anchor+j)*paddedW/8) +ByteOffset); /* The following loop copies the scanline of a character bitmap: */ if (currchar->bits != NULL) { p_l = (unsigned T1_AA_TYPE32 *)(currchar->bits+(char_paddedW/8*j)); if (BitShift == 0) { for (k=char_paddedW >> 5; k; k--) *Target_l++ |= *p_l++; } else { for (k=0; k < char_paddedW / 32 ; k++){ BitBuf_l= ((T1_AA_TYPE64)(*p_l++)) << BitShift; *Target_l++ |= BitBuf_l; *Target_l |= BitBuf_l>>l_shift; } /* End of for ( .. ) stepping through columns */ } } /* End of if(currchar->bits != NULL) */ } /* End of for( .. ) steppin' through lines of char bitmap */ }/* end if (T1_pad==32) */ else#endif if (T1_pad==16 && T1_byte==0){ /* The following loop steps through the lines of the character bitmap: */ for (j=0;j<currchar->metrics.ascent-currchar->metrics.descent;j++){ Target_s= (unsigned T1_AA_TYPE16 *)(string_glyph.bits +((v_anchor+j)*paddedW/8) +ByteOffset); /* The following loop copies the scanline of a character bitmap: */ if (currchar->bits != NULL) { p_s = (unsigned T1_AA_TYPE16 *)(currchar->bits+(char_paddedW/8*j)); if (BitShift == 0) { for (k=char_paddedW >> 4; k; k--) *Target_s++ |= *p_s++; } else{ for (k=char_paddedW >> 4; k; k--){ BitBuf_s= ((T1_AA_TYPE32)(*p_s++))<<BitShift; *Target_s++ |= BitBuf_s; *Target_s |= BitBuf_s>>s_shift; } /* End of for ( .. ) stepping through columns */ } } /* End of if(currchar->bits != NULL) */ } /* End of for( .. ) steppin' through lines of char bitmap */ }/* end if (T1_pad==16 */ else{ /* T1_pad = 8 or Big Endian machine */ /* The following loop steps through the lines of the character bitmap: */ for (j=0;j<currchar->metrics.ascent-currchar->metrics.descent;j++){ Target_c= (unsigned char *)(string_glyph.bits +((v_anchor+j)*paddedW/8) +ByteOffset); /* The following loop copies the scanline of a character bitmap: */ if (currchar->bits != NULL) { p_c = (unsigned char *)(currchar->bits+(char_paddedW/8*j)); if (BitShift == 0){ for (k=char_paddedW >> 3; k; k--) *Target_c++ |= *p_c++; } else{ for (k=char_paddedW >> 3; k; k--){ BitBuf_c = ((T1_AA_TYPE16)(*p_c++)) << BitShift; *Target_c++ |= BitBuf_c; *Target_c |= BitBuf_c>>c_shift; } /* End of for ( .. ) stepping through columns */ } } /* End of if(currchar->bits != NULL) */ } /* End of for( .. ) steppin' through lines of char bitmap */ } /* end if (T1_pad==8) and/or BigEndian */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -