/******************************************************************************* * ReadCharMetrics * * Reads metrics for each glyph in a TrueType font. Returns false for memory * allocation or FreeType error; sets *p_metrics to NULL for non-fatal error. * */ static BOOL ReadCharMetrics(FT_Face face, AFM *afm, AFMMETRICS **p_metrics) { FT_ULong charcode, index; AFMMETRICS *metrics; USHORT em_size = afm->WinMetrics.usUnitsPerEm; for (charcode = 0, index = 0; charcode < 65536; ++charcode) if (pFT_Get_Char_Index(face, charcode) != 0) ++index; /* count # of glyphs */ afm->NumofMetrics = index; *p_metrics = metrics = HeapAlloc(PSDRV_Heap, 0, index * sizeof(*metrics)); if (metrics == NULL) return FALSE; for (charcode = 0, index = 0; charcode < 65536; ++charcode) { FT_UInt glyph_index = pFT_Get_Char_Index(face, charcode); FT_Error error; CHAR buffer[128]; /* for glyph names */ if (glyph_index == 0) continue; error = pFT_Load_Glyph(face, glyph_index, GLYPH_LOAD_FLAGS); if (error != FT_Err_Ok) { ERR("%s returned %i\n", "FT_Load_Glyph", error); goto cleanup; } error = pFT_Get_Glyph_Name(face, glyph_index, buffer, sizeof(buffer)); if (error != FT_Err_Ok) { ERR("%s returned %i\n", "FT_Get_Glyph_Name", error); goto cleanup; } metrics[index].N = PSDRV_GlyphName(buffer); if (metrics[index].N == NULL) goto cleanup; metrics[index].C = metrics[index].UV = charcode; metrics[index].WX = PSUnits(face->glyph->metrics.horiAdvance, em_size); ++index; } if (afm->WinMetrics.sAvgCharWidth == 0) afm->WinMetrics.sAvgCharWidth = PSDRV_CalcAvgCharWidth(afm); return TRUE; cleanup: HeapFree(PSDRV_Heap, 0, metrics); return FALSE; }
static BOOL ReadCharMetrics(FILE *file, CHAR buffer[], INT bufsize, AFM *afm, AFMMETRICS **p_metrics) { BOOL retval, found; OLD_AFMMETRICS *old_metrics, *encoded_metrics; AFMMETRICS *metrics; INT i, len; retval = ReadInt(file, buffer, bufsize, "StartCharMetrics", &(afm->NumofMetrics), &found); if (retval == FALSE || found == FALSE) { *p_metrics = NULL; return retval; } old_metrics = HeapAlloc(PSDRV_Heap, 0, afm->NumofMetrics * sizeof(*old_metrics)); if (old_metrics == NULL) return FALSE; for (i = 0; i < afm->NumofMetrics; ++i) { retval = ReadLine(file, buffer, bufsize, &len); if (retval == FALSE) goto cleanup_old_metrics; if(len > 0) { retval = ParseCharMetrics(buffer, len, old_metrics + i); if (retval == FALSE || old_metrics[i].C == INT_MAX) goto cleanup_old_metrics; continue; } switch (len) { case 0: --i; continue; case INT_MIN: WARN("Ignoring long line '%32s...'\n", buffer); goto cleanup_old_metrics; /* retval == TRUE */ case EOF: WARN("Unexpected EOF\n"); goto cleanup_old_metrics; /* retval == TRUE */ } } Unicodify(afm, old_metrics); /* wait until glyph names have been read */ qsort(old_metrics, afm->NumofMetrics, sizeof(*old_metrics), OldAFMMetricsByUV); for (i = 0; old_metrics[i].UV == -1; ++i); /* count unencoded glyphs */ afm->NumofMetrics -= i; encoded_metrics = old_metrics + i; afm->Metrics = *p_metrics = metrics = HeapAlloc(PSDRV_Heap, 0, afm->NumofMetrics * sizeof(*metrics)); if (afm->Metrics == NULL) goto cleanup_old_metrics; /* retval == TRUE */ for (i = 0; i < afm->NumofMetrics; ++i, ++metrics, ++encoded_metrics) { metrics->C = encoded_metrics->C; metrics->UV = encoded_metrics->UV; metrics->WX = encoded_metrics->WX; metrics->N = encoded_metrics->N; } HeapFree(PSDRV_Heap, 0, old_metrics); afm->WinMetrics.sAvgCharWidth = PSDRV_CalcAvgCharWidth(afm); return TRUE; cleanup_old_metrics: /* handle fatal or non-fatal errors */ HeapFree(PSDRV_Heap, 0, old_metrics); *p_metrics = NULL; return retval; }