📄 font.c
字号:
// looking in kernTable // XXX - kernTable should be sorted to make this faster if ( i < len-1 && font->kernTable.k ) { glyph2 = SWFFont_findGlyphCode(font, string[i+1]); if ( glyph2 == -1 ) continue; // XXX - ??? j = font->kernCount; if(font->flags & SWF_FONT_WIDECODES) while ( --j >= 0 ) { if ( glyph == font->kernTable.w[j].code1 && glyph2 == font->kernTable.w[j].code2 ) { width += font->kernTable.w[j].adjustment; break; } } else while ( --j >= 0 ) { if ( glyph == font->kernTable.k[j].code1 && glyph2 == font->kernTable.k[j].code2 ) { width += font->kernTable.k[j].adjustment; break; } } } } return width;}intSWFFont_getScaledStringWidth(SWFFont font, const char* string){ unsigned short* widestr; int len = strlen(string); int n, width; widestr = (unsigned short*) malloc(2 * len); for(n = 0 ; n < len ; n++) widestr[n] = (unsigned char)string[n]; width = SWFFont_getScaledWideStringWidth(font, widestr, len); free(widestr); return width;}intSWFFont_getScaledUTF8StringWidth(SWFFont font, const char* string){ unsigned short* widestr; int len = UTF8ExpandString(string, &widestr); int width = SWFFont_getScaledWideStringWidth(font, widestr, len); free(widestr); return width;}/* get some font metrics */shortSWFFont_getScaledAscent(SWFFont font){ return font->ascent;}shortSWFFont_getScaledDescent(SWFFont font){ return font->descent;}shortSWFFont_getScaledLeading(SWFFont font){ return font->leading;}unsigned shortSWFFontCharacter_getGlyphCode(SWFFontCharacter font, unsigned short c){ return font->codeTable[c];}SWFRectSWFFont_getGlyphBounds(SWFFont font, unsigned short glyphcode){ if ( glyphcode >= font->nGlyphs ) SWF_error("SWFFont_getGlyphBounds: glyphcode >= nGlyphs"); return &font->bounds[glyphcode];}intSWFFont_getCharacterAdvance(SWFFont font, unsigned short glyphcode){ if ( font->advances ) { if ( glyphcode >= font->nGlyphs ) SWF_error("SWFFont_getCharacterAdvance: glyphcode >= nGlyphs"); return font->advances[glyphcode]; } return 0;}intSWFFont_getCharacterKern(SWFFont font, unsigned short code1, unsigned short code2){ int j = font->kernCount; if( !font->kernTable.k ) return 0; if ( code1 >= font->nGlyphs || code2 >= font->nGlyphs ) SWF_error("SWFFont_getCharacterKern: glyphcode >= nGlyphs"); // XXX - kernTable should be sorted to make this faster if(font->flags & SWF_FONT_WIDECODES) while ( --j >= 0 ) { if ( code1 == font->kernTable.w[j].code1 && code2 == font->kernTable.w[j].code2 ) { return font->kernTable.w[j].adjustment; } } else while ( --j >= 0 ) { if ( code1 == font->kernTable.k[j].code1 && code2 == font->kernTable.k[j].code2 ) { return font->kernTable.k[j].adjustment; } } return 0;}/* font loader */#define SWF_LOAD_FONT_HASLAYOUT (1<<7)#define SWF_LOAD_FONT_SHIFTJIS (1<<6)#define SWF_LOAD_FONT_UNICODE (1<<5)#define SWF_LOAD_FONT_ANSI (1<<4)#define SWF_LOAD_FONT_WIDEOFFSETS (1<<3)#define SWF_LOAD_FONT_WIDECODES (1<<2)#define SWF_LOAD_FONT_ITALIC (1<<1)#define SWF_LOAD_FONT_BOLD (1<<0)static intreadUInt16(FILE *f){ int low = fgetc(f); int high = fgetc(f); return low + (high<<8);}static intreadSInt16(FILE *f){ int low = fgetc(f); int high = fgetc(f); return low + high*256;}static unsigned longreadUInt32(FILE *f){ return (unsigned long)(fgetc(f) + (fgetc(f)<<8) + (fgetc(f)<<16) + (fgetc(f)<<24));}static int buffer;static int bufbits = 0; /* # of bits in buffer */static voidbyteAlign(){ if ( bufbits > 0 ) { bufbits = 0; buffer = 0; }}static intreadBits(FILE *f, int number){ int ret = buffer; if ( number == bufbits ) { bufbits = 0; buffer = 0; return ret; } if ( number > bufbits ) { number -= bufbits; while( number > 8 ) { ret <<= 8; ret += fgetc(f); number -= 8; } buffer = fgetc(f); if ( number > 0 ) { ret <<= number; bufbits = 8-number; ret += buffer >> (8-number); buffer &= (1<<bufbits)-1; } return ret; } ret = buffer >> (bufbits-number); bufbits -= number; buffer &= (1<<bufbits)-1; return ret;}static intreadSBits(FILE *f, int number){ int num = readBits(f, number); if ( num & (1<<(number-1)) ) return num - (1<<number); else return num;}static voidreadBounds(FILE *file, struct SWFRect_s* bounds){ int nBits; byteAlign(); nBits = readBits(file, 5); bounds->minX = readSBits(file, nBits); bounds->maxX = readSBits(file, nBits); bounds->minY = readSBits(file, nBits); bounds->maxY = readSBits(file, nBits);}static voidreadKernInfo(FILE *file, struct kernInfo *kern){ kern->code1 = fgetc(file); kern->code2 = fgetc(file); kern->adjustment = readSInt16(file);}static voidreadKernInfo16(FILE *file, struct kernInfo16 *kern){ kern->code1 = readUInt16(file); kern->code2 = readUInt16(file); kern->adjustment = readSInt16(file);}SWFFontloadSWFFontFromFile(FILE *file){ /* pull font definition from fdb (font def block) file */ SWFFont font = newSWFFont(); int namelen, flags, i, nGlyphs; int shapeTableLen; byte *p; if ( file == NULL ) return NULL; fgetc(file); /* header whatever */ fgetc(file); fgetc(file); fgetc(file); flags = fgetc(file);/* this isn't right, and I don't know why.. */ if(flags & SWF_LOAD_FONT_HASLAYOUT) font->flags |= SWF_FONT_HASLAYOUT; if(flags & SWF_LOAD_FONT_SHIFTJIS) font->flags |= SWF_FONT_SHIFTJIS; if(flags & SWF_LOAD_FONT_ANSI) font->flags |= SWF_FONT_ANSI; if(flags & SWF_LOAD_FONT_UNICODE) font->flags |= SWF_FONT_UNICODE; if(flags & SWF_LOAD_FONT_ITALIC) font->flags |= SWF_FONT_ISITALIC; if(flags & SWF_LOAD_FONT_BOLD) font->flags |= SWF_FONT_ISBOLD; if(flags & SWF_LOAD_FONT_WIDEOFFSETS) font->flags |= SWF_FONT_WIDEOFFSETS; if(flags & SWF_LOAD_FONT_WIDECODES) font->flags |= SWF_FONT_WIDECODES;// font->flags = flags; // XXX - ???// new rules... SWF6 said to require unicode, no ansi, no shiftjis// font->flags |= SWF_FONT_SHIFTJIS; fgetc(file); /* "reserved" */ namelen = fgetc(file); font->name = (byte*) malloc(namelen+1); for ( i=0; i<namelen; ++i ) font->name[i] = fgetc(file); font->name[namelen] = '\0'; nGlyphs = readUInt16(file); font->nGlyphs = nGlyphs; font->bounds = (struct SWFRect_s*) malloc(nGlyphs * sizeof(struct SWFRect_s)); font->glyphOffset = (byte**)malloc((nGlyphs + 1) * sizeof(*font->glyphOffset)); font->glyphToCode = (unsigned short*)malloc(nGlyphs * sizeof(*font->glyphToCode)); font->advances = (short*) malloc(nGlyphs * sizeof(*font->advances)); if ( flags & SWF_LOAD_FONT_WIDEOFFSETS ) { for ( i=0; i<=nGlyphs; ++i ) font->glyphOffset[i] = (byte *)(readUInt32(file) - 4*nGlyphs - 4); } else { for(i=0; i<=nGlyphs; ++i) font->glyphOffset[i] = (byte *)(readUInt16(file) - 2*nGlyphs - 2); } shapeTableLen = font->glyphOffset[nGlyphs] - font->glyphOffset[0];#if HAS_MMAP font->shapes = mmap(NULL, shapeTableLen + 1, PROT_READ, MAP_PRIVATE, fileno(file), ftell(file)); if ( (void*)font->shapes != MAP_FAILED ) { fseek(file, shapeTableLen, SEEK_CUR); } else {#endif /* it helps to allocate the right amount. (thanks, Tim!) */ font->shapes = (byte*)malloc(font->glyphOffset[nGlyphs] - font->glyphOffset[0] + 1); p = font->shapes; while ( shapeTableLen > 0 ) { int count = fread(p, 1, shapeTableLen, file); shapeTableLen -= count; p += count; }#if HAS_MMAP }#endif /* adjust offset table to point to shapes */ for ( i=0; i<=nGlyphs; ++i ) font->glyphOffset[i] += (unsigned long)font->shapes; /* read glyph-to-code table */ if ( flags & SWF_LOAD_FONT_WIDECODES ) { for ( i=0; i<nGlyphs; ++i ) font->glyphToCode[i] = readUInt16(file); } else { for ( i=0; i<nGlyphs; ++i ) font->glyphToCode[i] = fgetc(file); } // build code-to-glyph table // XXX - make new version of FDB with reverse map? SWFFont_buildReverseMapping(font); /* read metrics */ if ( flags & SWF_LOAD_FONT_HASLAYOUT ) { font->ascent = readSInt16(file); font->descent = readSInt16(file); font->leading = readSInt16(file); /* get advances */ for ( i=0; i<nGlyphs; ++i ) font->advances[i] = readSInt16(file); /* get bounds */ for ( i=0; i<nGlyphs; ++i ) readBounds(file, &font->bounds[i]); /* get kern table */ font->kernCount = readUInt16(file); if ( font->kernCount > 0 ) if(font->flags & SWF_FONT_WIDECODES) font->kernTable.w = (struct kernInfo16*) malloc(sizeof(struct kernInfo16) * font->kernCount); else font->kernTable.k = (struct kernInfo*)malloc(sizeof(struct kernInfo) * font->kernCount); else font->kernTable.k = NULL; if(font->flags & SWF_FONT_WIDECODES) for ( i=0; i<font->kernCount; ++i ) readKernInfo16(file, &(font->kernTable.w[i])); else for ( i=0; i<font->kernCount; ++i ) readKernInfo(file, &(font->kernTable.k[i])); } return font;}/* retrieve glyph shape of a font */#include <stdio.h>#include <stdarg.h>/* basic IO */struct out{ char *buf, *ptr; int len;};static void oprintf(struct out *op, const char *fmt, ...){ va_list ap; char buf[256]; int d, l; va_start(ap, fmt); l = vsprintf(buf, fmt, ap); while((d = op->ptr - op->buf) + l >= op->len-1) { op->buf = (char *) realloc(op->buf, op->len += 100); op->ptr = op->buf + d; } for(d = 0 ; d < l ; d++) *op->ptr++ = buf[d];}static int readBitsP(byte **p, int number){ byte *ptr = *p; int ret = buffer; if(number == bufbits) { ret = buffer; bufbits = 0; buffer = 0; } else if(number > bufbits) { number -= bufbits; while(number>8) { ret <<= 8; ret += *ptr++; number -= 8; } buffer = *ptr++; if(number>0) { ret <<= number; bufbits = 8-number; ret += buffer >> (8-number); buffer &= (1<<bufbits)-1; } } else { ret = buffer >> (bufbits-number); bufbits -= number; buffer &= (1<<bufbits)-1; } *p = ptr; return ret;}static int readSBitsP(byte **p, int number){ int num = readBitsP(p, number); if(num & (1<<(number-1))) return num - (1<<number); else return num;}// return a malloc'ed string describing the glyph shapechar *SWFFont_getShape(SWFFont font, unsigned short c){ byte *p = SWFFont_findGlyph(font, c); byte **f = &p; struct out o; int moveBits, x, y; int straight, numBits; int numFillBits, numLineBits; int startX = 0; int startY = 0; int style; o.len = 0; o.ptr = o.buf = (char *)malloc(1); *o.ptr = 0; byteAlign(); if ( (numFillBits = readBitsP(f, 4)) != 1 ) /* fill bits */ SWF_error("SWFFont_getShape: bad file format (was expecting fill bits = 1)"); if ( (numLineBits = readBitsP(f, 4)) > 1 ) /* line bits */ SWF_error("SWFFont_getShape: bad file format (was expecting line bits = 0)"); /* now we get to parse the shape commands. Oh boy. the first one will be a non-edge block- grab the moveto loc */ readBitsP(f, 2); /* type 0, newstyles */ style = readBitsP(f, 3); if(readBitsP(f, 1)) { moveBits = readBitsP(f, 5); x = startX + readSBitsP(f, moveBits); y = startY + readSBitsP(f, moveBits); oprintf(&o, "moveto %d,%d\n", x, y); } else if(style == 0) /* no style, no move => space character */ return o.buf; if ( style & 1 ) if ( readBitsP(f, numFillBits) != 0 ) /* fill0 = 0 */ SWF_error("SWFFont_getShape: bad file format (was expecting fill0 = 0)"); if ( style & 2 ) if ( readBitsP(f, numFillBits) != 1 ) /* fill1 = 1 */ SWF_error("SWFFont_getShape: bad file format (was expecting fill1 = 1)"); if ( style & 4 ) if ( readBitsP(f, numLineBits) != 0 ) /* line = 1 */ SWF_error("SWFFont_getShape: bad file format (was expecting line = 0)"); /* translate the glyph's shape records into drawing commands */ for ( ;; ) { if ( readBitsP(f, 1) == 0 ) { /* it's a moveTo or a shape end */ if ( readBitsP(f, 5) == 0 ) break; moveBits = readBitsP(f, 5); x = startX + readSBitsP(f, moveBits); y = startY + readSBitsP(f, moveBits); oprintf(&o, "moveto %d,%d\n", x, y); continue; } straight = readBitsP(f, 1); numBits = readBitsP(f, 4)+2; if ( straight==1 ) { if ( readBitsP(f, 1) ) /* general line */ { x += readSBitsP(f, numBits); y += readSBitsP(f, numBits); } else { if ( readBitsP(f, 1) ) /* vert = 1 */ y += readSBitsP(f, numBits); else x += readSBitsP(f, numBits); } oprintf(&o, "lineto %d,%d\n", x, y); } else { int controlX = readSBitsP(f, numBits); int controlY = readSBitsP(f, numBits); int anchorX = readSBitsP(f, numBits); int anchorY = readSBitsP(f, numBits); oprintf(&o, "curveto %d,%d %d,%d\n", x+controlX, y+controlY, x+controlX+anchorX, y+controlY+anchorY); x += controlX + anchorX; y += controlY + anchorY; } } *o.ptr = 0; return o.buf;}/* * Local variables: * tab-width: 2 * c-basic-offset: 2 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -