struct.c revision 43f32c10
143f32c10Smrg/* 243f32c10SmrgCopyright (c) 2002-2003 by Juliusz Chroboczek 343f32c10Smrg 443f32c10SmrgPermission is hereby granted, free of charge, to any person obtaining a copy 543f32c10Smrgof this software and associated documentation files (the "Software"), to deal 643f32c10Smrgin the Software without restriction, including without limitation the rights 743f32c10Smrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell 843f32c10Smrgcopies of the Software, and to permit persons to whom the Software is 943f32c10Smrgfurnished to do so, subject to the following conditions: 1043f32c10Smrg 1143f32c10SmrgThe above copyright notice and this permission notice shall be included in 1243f32c10Smrgall copies or substantial portions of the Software. 1343f32c10Smrg 1443f32c10SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1543f32c10SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1643f32c10SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1743f32c10SmrgAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1843f32c10SmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1943f32c10SmrgOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 2043f32c10SmrgTHE SOFTWARE. 2143f32c10Smrg*/ 2243f32c10Smrg/* $XFree86: xc/programs/fonttosfnt/struct.c,v 1.3 2003/10/24 20:38:11 tsi Exp $ */ 2343f32c10Smrg 2443f32c10Smrg#include <stdlib.h> 2543f32c10Smrg#include <stdio.h> 2643f32c10Smrg#include <ft2build.h> 2743f32c10Smrg#include FT_FREETYPE_H 2843f32c10Smrg#include "fonttosfnt.h" 2943f32c10Smrg 3043f32c10SmrgFontPtr 3143f32c10SmrgmakeFont() 3243f32c10Smrg{ 3343f32c10Smrg FontPtr font; 3443f32c10Smrg 3543f32c10Smrg font = malloc(sizeof(FontRec)); 3643f32c10Smrg if(font == NULL) 3743f32c10Smrg return NULL; 3843f32c10Smrg 3943f32c10Smrg font->numNames = 0; 4043f32c10Smrg font->names = NULL; 4143f32c10Smrg font->flags = 0; 4243f32c10Smrg font->weight = 500; 4343f32c10Smrg font->width = 5; 4443f32c10Smrg font->italicAngle = 0; 4543f32c10Smrg font->underlinePosition = - TWO_SIXTEENTH; 4643f32c10Smrg font->underlineThickness = TWO_SIXTEENTH; 4743f32c10Smrg font->foundry = makeName("UNKN"); 4843f32c10Smrg font->strikes = NULL; 4943f32c10Smrg return font; 5043f32c10Smrg} 5143f32c10Smrg 5243f32c10SmrgStrikePtr 5343f32c10SmrgmakeStrike(FontPtr font, int sizeX, int sizeY) 5443f32c10Smrg{ 5543f32c10Smrg StrikePtr strike, last_strike; 5643f32c10Smrg 5743f32c10Smrg strike = font->strikes; 5843f32c10Smrg last_strike = NULL; 5943f32c10Smrg while(strike) { 6043f32c10Smrg if(strike->sizeX == sizeX && strike->sizeY == sizeY) 6143f32c10Smrg return strike; 6243f32c10Smrg last_strike = strike; 6343f32c10Smrg strike = strike->next; 6443f32c10Smrg } 6543f32c10Smrg 6643f32c10Smrg strike = malloc(sizeof(StrikeRec)); 6743f32c10Smrg if(strike == NULL) 6843f32c10Smrg return NULL; 6943f32c10Smrg strike->sizeX = sizeX; 7043f32c10Smrg strike->sizeY = sizeY; 7143f32c10Smrg strike->bitmaps = 7243f32c10Smrg calloc(FONT_CODES / FONT_SEGMENT_SIZE, sizeof(BitmapPtr*)); 7343f32c10Smrg if(strike->bitmaps == NULL) { 7443f32c10Smrg free(strike); 7543f32c10Smrg return NULL; 7643f32c10Smrg } 7743f32c10Smrg strike->numSbits = 0; 7843f32c10Smrg strike->next = NULL; 7943f32c10Smrg strike->bitmapSizeTableLocation = 0xDEADFACE; 8043f32c10Smrg strike->indexSubTables = NULL; 8143f32c10Smrg if(last_strike) 8243f32c10Smrg last_strike->next = strike; 8343f32c10Smrg else 8443f32c10Smrg font->strikes = strike; 8543f32c10Smrg return strike; 8643f32c10Smrg} 8743f32c10Smrg 8843f32c10SmrgBitmapPtr 8943f32c10SmrgmakeBitmap(StrikePtr strike, int code, 9043f32c10Smrg int advanceWidth, int horiBearingX, int horiBearingY, 9143f32c10Smrg int width, int height, int stride, unsigned char *raster, int crop) 9243f32c10Smrg{ 9343f32c10Smrg BitmapPtr bitmap; 9443f32c10Smrg int i, j, x, y; 9543f32c10Smrg int dx, dy, new_width, new_height; 9643f32c10Smrg 9743f32c10Smrg bitmap = malloc(sizeof(BitmapRec)); 9843f32c10Smrg if(bitmap == NULL) 9943f32c10Smrg return NULL; 10043f32c10Smrg 10143f32c10Smrg bitmap->index = -1; 10243f32c10Smrg bitmap->width = 0; 10343f32c10Smrg bitmap->height = 0; 10443f32c10Smrg bitmap->stride = 0; 10543f32c10Smrg bitmap->raster = NULL; 10643f32c10Smrg bitmap->location = 0xDEADFACE; 10743f32c10Smrg 10843f32c10Smrg i = code / FONT_SEGMENT_SIZE; 10943f32c10Smrg j = code % FONT_SEGMENT_SIZE; 11043f32c10Smrg 11143f32c10Smrg if(strike->bitmaps[i] == NULL) { 11243f32c10Smrg strike->bitmaps[i] = calloc(FONT_SEGMENT_SIZE, sizeof(BitmapPtr)); 11343f32c10Smrg } 11443f32c10Smrg if(strike->bitmaps[i] == NULL) { 11543f32c10Smrg free(bitmap); 11643f32c10Smrg return NULL; 11743f32c10Smrg } 11843f32c10Smrg if(strike->bitmaps[i][j] != NULL) { 11943f32c10Smrg if(verbose_flag) 12043f32c10Smrg fprintf(stderr, "Duplicate bitmap %d.\n", code); 12143f32c10Smrg free(bitmap); 12243f32c10Smrg return strike->bitmaps[i][j]; 12343f32c10Smrg } 12443f32c10Smrg 12543f32c10Smrg dx = 0; 12643f32c10Smrg dy = 0; 12743f32c10Smrg new_width = width; 12843f32c10Smrg new_height = height; 12943f32c10Smrg 13043f32c10Smrg if(crop) { 13143f32c10Smrg int empty; 13243f32c10Smrg while(new_width > 0) { 13343f32c10Smrg empty = 1; 13443f32c10Smrg x = new_width - 1; 13543f32c10Smrg for(y = 0; y < new_height; y++) { 13643f32c10Smrg if(BITREF(raster, stride, x + dx, y + dy)) { 13743f32c10Smrg empty = 0; 13843f32c10Smrg break; 13943f32c10Smrg } 14043f32c10Smrg } 14143f32c10Smrg if(empty) 14243f32c10Smrg new_width--; 14343f32c10Smrg else 14443f32c10Smrg break; 14543f32c10Smrg } 14643f32c10Smrg while(new_height > 0) { 14743f32c10Smrg empty = 1; 14843f32c10Smrg y = new_height - 1; 14943f32c10Smrg for(x = 0; x < new_width; x++) { 15043f32c10Smrg if(BITREF(raster, stride, x + dx, y + dy)) { 15143f32c10Smrg empty = 0; 15243f32c10Smrg break; 15343f32c10Smrg } 15443f32c10Smrg } 15543f32c10Smrg if(empty) 15643f32c10Smrg new_height--; 15743f32c10Smrg else 15843f32c10Smrg break; 15943f32c10Smrg } 16043f32c10Smrg while(new_width > 0) { 16143f32c10Smrg empty = 1; 16243f32c10Smrg x = 0; 16343f32c10Smrg for(y = 0; y < new_height; y++) { 16443f32c10Smrg if(BITREF(raster, stride, x + dx, y + dy)) { 16543f32c10Smrg empty = 0; 16643f32c10Smrg break; 16743f32c10Smrg } 16843f32c10Smrg } 16943f32c10Smrg if(empty) { 17043f32c10Smrg dx++; 17143f32c10Smrg new_width--; 17243f32c10Smrg } else 17343f32c10Smrg break; 17443f32c10Smrg } 17543f32c10Smrg while(new_height > 0) { 17643f32c10Smrg empty = 1; 17743f32c10Smrg y = 0; 17843f32c10Smrg for(x = 0; x < new_width; x++) { 17943f32c10Smrg if(BITREF(raster, stride, x + dx, y + dy)) { 18043f32c10Smrg empty = 0; 18143f32c10Smrg break; 18243f32c10Smrg } 18343f32c10Smrg } 18443f32c10Smrg if(empty) { 18543f32c10Smrg dy++; 18643f32c10Smrg new_height--; 18743f32c10Smrg } else 18843f32c10Smrg break; 18943f32c10Smrg } 19043f32c10Smrg } 19143f32c10Smrg 19243f32c10Smrg 19343f32c10Smrg bitmap->advanceWidth = advanceWidth; 19443f32c10Smrg bitmap->horiBearingX = horiBearingX + dx; 19543f32c10Smrg bitmap->horiBearingY = horiBearingY - dy; 19643f32c10Smrg bitmap->width = new_width; 19743f32c10Smrg bitmap->height = new_height; 19843f32c10Smrg bitmap->stride = (new_width + 7) / 8; 19943f32c10Smrg 20043f32c10Smrg bitmap->raster = malloc(bitmap->height * bitmap->stride); 20143f32c10Smrg if(bitmap->raster == NULL) { 20243f32c10Smrg free(bitmap); 20343f32c10Smrg return NULL; 20443f32c10Smrg } 20543f32c10Smrg memset(bitmap->raster, 0, bitmap->height * bitmap->stride); 20643f32c10Smrg for(y = 0; y < new_height; y++) { 20743f32c10Smrg for(x = 0; x < new_width; x++) { 20843f32c10Smrg if(BITREF(raster, stride, x + dx, y + dy)) 20943f32c10Smrg bitmap->raster[y * bitmap->stride + x / 8] |= 21043f32c10Smrg 1 << (7 - (x % 8)); 21143f32c10Smrg } 21243f32c10Smrg } 21343f32c10Smrg strike->bitmaps[i][j] = bitmap; 21443f32c10Smrg strike->numSbits++; 21543f32c10Smrg 21643f32c10Smrg return bitmap; 21743f32c10Smrg} 21843f32c10Smrg 21943f32c10SmrgIndexSubTablePtr 22043f32c10SmrgmakeIndexSubTables(StrikePtr strike, CmapPtr cmap) 22143f32c10Smrg{ 22243f32c10Smrg IndexSubTablePtr table, first, last; 22343f32c10Smrg BitmapPtr bitmap0, bitmap; 22443f32c10Smrg int index, n; 22543f32c10Smrg 22643f32c10Smrg first = NULL; 22743f32c10Smrg last = NULL; 22843f32c10Smrg 22943f32c10Smrg /* Assuming that we're writing bit-aligned data, small metrics 23043f32c10Smrg and short offsets, a constant metrics segment saves 5 bytes 23143f32c10Smrg per glyph in the EBDT table, and 2 bytes per glyph in the EBLC 23243f32c10Smrg table. On the other hand, the overhead for a supplementary 23343f32c10Smrg type 2 indexSubTable is 8 bytes for the indexSubTableArray 23443f32c10Smrg entry and 20 bytes for the subtable itself. It's worth 23543f32c10Smrg splitting at 5 glyphs. There's no analogue of a type 2 23643f32c10Smrg indexSubTable with byte-aligned data, so we don't bother 23743f32c10Smrg splitting when byte-aligning. */ 23843f32c10Smrg index = 0; 23943f32c10Smrg while(index < 0xFFFF) { 24043f32c10Smrg int constantMetrics = 1; 24143f32c10Smrg bitmap0 = strikeBitmapIndex(strike, cmap, index); 24243f32c10Smrg if(bitmap0 == NULL) { 24343f32c10Smrg index++; 24443f32c10Smrg continue; 24543f32c10Smrg } 24643f32c10Smrg n = 1; 24743f32c10Smrg while((bitmap = strikeBitmapIndex(strike, cmap, index + n)) != NULL) { 24843f32c10Smrg if(constantMetrics) { 24943f32c10Smrg if(!SAME_METRICS(bitmap0, bitmap)) { 25043f32c10Smrg if(bit_aligned_flag && n >= 4) 25143f32c10Smrg break; 25243f32c10Smrg else 25343f32c10Smrg constantMetrics = 0; 25443f32c10Smrg } 25543f32c10Smrg } else if(bit_aligned_flag) { 25643f32c10Smrg BitmapPtr b1 = strikeBitmapIndex(strike, cmap, index + n + 1); 25743f32c10Smrg BitmapPtr b2 = strikeBitmapIndex(strike, cmap, index + n + 2); 25843f32c10Smrg BitmapPtr b3 = strikeBitmapIndex(strike, cmap, index + n + 3); 25943f32c10Smrg BitmapPtr b4 = strikeBitmapIndex(strike, cmap, index + n + 4); 26043f32c10Smrg if(b1 && b2 && b3 && b4 && 26143f32c10Smrg SAME_METRICS(bitmap, b1) && 26243f32c10Smrg SAME_METRICS(bitmap, b2) && 26343f32c10Smrg SAME_METRICS(bitmap, b3) && 26443f32c10Smrg SAME_METRICS(bitmap, b4)) { 26543f32c10Smrg break; 26643f32c10Smrg } 26743f32c10Smrg } 26843f32c10Smrg n++; 26943f32c10Smrg } 27043f32c10Smrg if(n <= 1) 27143f32c10Smrg constantMetrics = 0; 27243f32c10Smrg 27343f32c10Smrg table = malloc(sizeof(IndexSubTableRec)); 27443f32c10Smrg table->firstGlyphIndex = index; 27543f32c10Smrg table->lastGlyphIndex = index + n - 1; 27643f32c10Smrg table->constantMetrics = constantMetrics; 27743f32c10Smrg table->location = 0xDEADFACE; 27843f32c10Smrg table->lastLocation = 0xDEADFACE; 27943f32c10Smrg table->next = NULL; 28043f32c10Smrg 28143f32c10Smrg if(first == NULL) { 28243f32c10Smrg first = table; 28343f32c10Smrg last = table; 28443f32c10Smrg } else { 28543f32c10Smrg last->next = table; 28643f32c10Smrg last = table; 28743f32c10Smrg } 28843f32c10Smrg index += n; 28943f32c10Smrg } 29043f32c10Smrg return first; 29143f32c10Smrg} 29243f32c10Smrg 29343f32c10Smrgint 29443f32c10SmrgfontIndex(FontPtr font, int code) 29543f32c10Smrg{ 29643f32c10Smrg StrikePtr strike; 29743f32c10Smrg BitmapPtr bitmap; 29843f32c10Smrg 29943f32c10Smrg if(code == 0) 30043f32c10Smrg return 0; 30143f32c10Smrg strike = font->strikes; 30243f32c10Smrg while(strike) { 30343f32c10Smrg bitmap = STRIKE_BITMAP(strike, code); 30443f32c10Smrg if(bitmap) 30543f32c10Smrg return bitmap->index; 30643f32c10Smrg strike = strike->next; 30743f32c10Smrg } 30843f32c10Smrg return -1; 30943f32c10Smrg} 31043f32c10Smrg 31143f32c10SmrgCmapPtr 31243f32c10SmrgmakeCmap(FontPtr font) 31343f32c10Smrg{ 31443f32c10Smrg CmapPtr cmap_head = NULL; 31543f32c10Smrg CmapPtr cmap_last = NULL; 31643f32c10Smrg CmapPtr cmap; 31743f32c10Smrg int code, i, index, maxindex = 0; 31843f32c10Smrg 31943f32c10Smrg code = 0; 32043f32c10Smrg while(code < FONT_CODES) { 32143f32c10Smrg index = fontIndex(font, code); 32243f32c10Smrg if(index < 0) { 32343f32c10Smrg code++; 32443f32c10Smrg continue; 32543f32c10Smrg } 32643f32c10Smrg i = 1; 32743f32c10Smrg while(code + i < FONT_CODES && 32843f32c10Smrg fontIndex(font, code + i) == index + i) { 32943f32c10Smrg i++; 33043f32c10Smrg } 33143f32c10Smrg cmap = malloc(sizeof(CmapRec)); 33243f32c10Smrg if(cmap == NULL) 33343f32c10Smrg return NULL; 33443f32c10Smrg cmap->startCode = code; 33543f32c10Smrg cmap->endCode = code + i - 1; 33643f32c10Smrg cmap->index = index; 33743f32c10Smrg cmap->next = NULL; 33843f32c10Smrg cmap->maxindex = 0; 33943f32c10Smrg if(maxindex < index + i - 1) 34043f32c10Smrg maxindex = index + i - 1; 34143f32c10Smrg if(cmap_head == NULL) 34243f32c10Smrg cmap_head = cmap; 34343f32c10Smrg else 34443f32c10Smrg cmap_last->next = cmap; 34543f32c10Smrg cmap_last = cmap; 34643f32c10Smrg 34743f32c10Smrg code += i; 34843f32c10Smrg } 34943f32c10Smrg cmap_head->maxindex = maxindex; 35043f32c10Smrg cmap_head->inverse = calloc(maxindex + 1, sizeof(int)); 35143f32c10Smrg cmap = cmap_head; 35243f32c10Smrg while(cmap) { 35343f32c10Smrg for(i = cmap->index; 35443f32c10Smrg i <= cmap->endCode - cmap->startCode + cmap->index; i++) { 35543f32c10Smrg cmap_head->inverse[i] = 35643f32c10Smrg i - cmap->index + cmap->startCode; 35743f32c10Smrg } 35843f32c10Smrg cmap = cmap->next; 35943f32c10Smrg } 36043f32c10Smrg 36143f32c10Smrg return cmap_head; 36243f32c10Smrg} 36343f32c10Smrg 36443f32c10Smrgint 36543f32c10SmrgfindIndex(CmapPtr cmap_head, int code) 36643f32c10Smrg{ 36743f32c10Smrg CmapPtr cmap; 36843f32c10Smrg cmap = cmap_head; 36943f32c10Smrg while(cmap) { 37043f32c10Smrg if(cmap->endCode > code) 37143f32c10Smrg return -1; 37243f32c10Smrg if(cmap->startCode <= code) 37343f32c10Smrg return cmap->index + code - cmap->startCode; 37443f32c10Smrg cmap = cmap->next; 37543f32c10Smrg } 37643f32c10Smrg return -1; 37743f32c10Smrg} 37843f32c10Smrg 37943f32c10Smrgint 38043f32c10SmrgfindCode(CmapPtr cmap_head, int index) 38143f32c10Smrg{ 38243f32c10Smrg if(index < 0 || index > cmap_head->maxindex) 38343f32c10Smrg return -1; 38443f32c10Smrg return cmap_head->inverse[index]; 38543f32c10Smrg 38643f32c10Smrg} 38743f32c10Smrg 38843f32c10Smrgint 38943f32c10SmrgmaxIndex(CmapPtr cmap_head) 39043f32c10Smrg{ 39143f32c10Smrg return cmap_head->maxindex; 39243f32c10Smrg} 39343f32c10Smrg 39443f32c10SmrgBitmapPtr 39543f32c10SmrgstrikeBitmapIndex(StrikePtr strike, CmapPtr cmap, int index) 39643f32c10Smrg{ 39743f32c10Smrg int code = findCode(cmap, index); 39843f32c10Smrg if(code < 0) 39943f32c10Smrg return NULL; 40043f32c10Smrg 40143f32c10Smrg return STRIKE_BITMAP(strike, code); 40243f32c10Smrg} 40343f32c10Smrg 40443f32c10Smrgvoid 40543f32c10SmrgstrikeMetrics(StrikePtr strike, 40643f32c10Smrg int *width_max_return, 40743f32c10Smrg int *x_min_return, int *y_min_return, 40843f32c10Smrg int *x_max_return, int *y_max_return) 40943f32c10Smrg{ 41043f32c10Smrg BitmapPtr bitmap; 41143f32c10Smrg int i; 41243f32c10Smrg int width_max = 0; 41343f32c10Smrg int x_min = 10000; 41443f32c10Smrg int y_min = 10000; 41543f32c10Smrg int x_max = -10000; 41643f32c10Smrg int y_max = -10000; 41743f32c10Smrg 41843f32c10Smrg for(i = 0; i < FONT_CODES; i++) { 41943f32c10Smrg bitmap = STRIKE_BITMAP(strike, i); 42043f32c10Smrg if(!bitmap) 42143f32c10Smrg continue; 42243f32c10Smrg if(bitmap->advanceWidth > width_max) 42343f32c10Smrg width_max = bitmap->advanceWidth; 42443f32c10Smrg if(bitmap->horiBearingX < x_min) 42543f32c10Smrg x_min = bitmap->horiBearingX; 42643f32c10Smrg if(bitmap->horiBearingY > y_max) 42743f32c10Smrg y_max = bitmap->horiBearingY; 42843f32c10Smrg if(bitmap->horiBearingX + bitmap->width > x_max) 42943f32c10Smrg x_max = bitmap->horiBearingX + bitmap->width; 43043f32c10Smrg if(bitmap->horiBearingY - bitmap->height < y_min) 43143f32c10Smrg y_min = bitmap->horiBearingY - bitmap->height; 43243f32c10Smrg } 43343f32c10Smrg 43443f32c10Smrg if(width_max_return) *width_max_return = width_max; 43543f32c10Smrg if(x_min_return) *x_min_return = x_min; 43643f32c10Smrg if(y_min_return) *y_min_return = y_min; 43743f32c10Smrg if(x_max_return) *x_max_return = x_max; 43843f32c10Smrg if(y_max_return) *y_max_return = y_max; 43943f32c10Smrg} 44043f32c10Smrg 44143f32c10Smrgint 44243f32c10SmrgglyphMetrics(FontPtr font, int code, 44343f32c10Smrg int *width_return, 44443f32c10Smrg int *x_min_return, int *y_min_return, 44543f32c10Smrg int *x_max_return, int *y_max_return) 44643f32c10Smrg{ 44743f32c10Smrg StrikePtr strike; 44843f32c10Smrg BitmapPtr bitmap; 44943f32c10Smrg 45043f32c10Smrg strike = font->strikes; 45143f32c10Smrg while(strike) { 45243f32c10Smrg bitmap = STRIKE_BITMAP(strike, code); 45343f32c10Smrg if(bitmap) { 45443f32c10Smrg if(width_return) 45543f32c10Smrg *width_return = 45643f32c10Smrg (((float)bitmap->advanceWidth + 0.5) / strike->sizeX) * 45743f32c10Smrg TWO_SIXTEENTH; 45843f32c10Smrg if(x_min_return) 45943f32c10Smrg *x_min_return = 46043f32c10Smrg ((float)bitmap->horiBearingX / strike->sizeX) * 46143f32c10Smrg TWO_SIXTEENTH; 46243f32c10Smrg if(y_min_return) 46343f32c10Smrg *y_min_return = 46443f32c10Smrg (((float)bitmap->horiBearingY - bitmap->height) 46543f32c10Smrg / strike->sizeY) * TWO_SIXTEENTH; 46643f32c10Smrg /* For the following two, 0.9 instead of 0.5 might make 46743f32c10Smrg more sense. However, using different rounding rules 46843f32c10Smrg for x_max and awidth causes problems for detecting 46943f32c10Smrg charcell fonts. */ 47043f32c10Smrg if(x_max_return) 47143f32c10Smrg *x_max_return = 47243f32c10Smrg (((float)bitmap->horiBearingX + bitmap->width + 0.5) 47343f32c10Smrg / strike->sizeX) * TWO_SIXTEENTH; 47443f32c10Smrg if(y_max_return) 47543f32c10Smrg *y_max_return = 47643f32c10Smrg (((float)bitmap->horiBearingY + 0.5) / strike->sizeY) * 47743f32c10Smrg TWO_SIXTEENTH; 47843f32c10Smrg return 1; 47943f32c10Smrg } 48043f32c10Smrg strike = strike->next; 48143f32c10Smrg } 48243f32c10Smrg 48343f32c10Smrg return -1; 48443f32c10Smrg} 48543f32c10Smrg 48643f32c10Smrgvoid 48743f32c10SmrgfontMetrics(FontPtr font, 48843f32c10Smrg int *max_awidth_return, 48943f32c10Smrg int *min_x_return, int *min_y_return, 49043f32c10Smrg int *max_x_return, int *max_y_return) 49143f32c10Smrg{ 49243f32c10Smrg int i, rc; 49343f32c10Smrg int max_awidth = 0; 49443f32c10Smrg int min_x = 10000 << 16, min_y = 10000 << 16; 49543f32c10Smrg int max_x = -10000 << 16, max_y = -10000 << 16; 49643f32c10Smrg for(i = 0; i < FONT_CODES; i++) { 49743f32c10Smrg int awidth, x0, y0, x1, y1; 49843f32c10Smrg rc = glyphMetrics(font, i, &awidth, &x0, &y0, &x1, &y1); 49943f32c10Smrg if(rc < 0) 50043f32c10Smrg continue; 50143f32c10Smrg if(awidth > max_awidth) 50243f32c10Smrg max_awidth = awidth; 50343f32c10Smrg if(x0 < min_x) min_x = x0; 50443f32c10Smrg if(y0 < min_y) min_y = y0; 50543f32c10Smrg if(x1 > max_x) max_x = x1; 50643f32c10Smrg if(y1 > max_y) max_y = y1; 50743f32c10Smrg } 50843f32c10Smrg if(max_awidth_return) *max_awidth_return = max_awidth; 50943f32c10Smrg if(min_x_return) *min_x_return = min_x; 51043f32c10Smrg if(min_y_return) *min_y_return = min_y; 51143f32c10Smrg if(max_x_return) *max_x_return = max_x; 51243f32c10Smrg if(max_y_return) *max_y_return = max_y; 51343f32c10Smrg} 51443f32c10Smrg 515