diff options
Diffstat (limited to 'Build/source/libs/icu-xetex/samples/layout/FontMap.cpp')
-rw-r--r-- | Build/source/libs/icu-xetex/samples/layout/FontMap.cpp | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/Build/source/libs/icu-xetex/samples/layout/FontMap.cpp b/Build/source/libs/icu-xetex/samples/layout/FontMap.cpp new file mode 100644 index 00000000000..00e3c4dcc96 --- /dev/null +++ b/Build/source/libs/icu-xetex/samples/layout/FontMap.cpp @@ -0,0 +1,278 @@ +/* + ****************************************************************************** + * Copyright (C) 1998-2003, International Business Machines Corporation and * + * others. All Rights Reserved. * + ****************************************************************************** + */ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#include "unicode/utypes.h" +#include "unicode/uscript.h" + +#include "layout/LETypes.h" +#include "layout/LEScripts.h" +#include "layout/LEFontInstance.h" + +#include "GUISupport.h" +#include "FontMap.h" + +FontMap::FontMap(const char *fileName, le_int16 pointSize, GUISupport *guiSupport, LEErrorCode &status) + : fPointSize(pointSize), fFontCount(0), fAscent(0), fDescent(0), fLeading(0), fGUISupport(guiSupport) +{ + le_int32 defaultFont = -1, i, script; + + for (i = 0; i < scriptCodeCount; i += 1) { + fFontIndices[i] = -1; + fFontNames[i] = NULL; + fFontInstances[i] = NULL; + } + + if (LE_FAILURE(status)) { + return; + } + + char *c, *scriptName, *fontName, *line, buffer[BUFFER_SIZE]; + FILE *file; + + file = fopen(fileName, "r"); + + if (file == NULL) { + sprintf(errorMessage, "Could not open the font map file: %s.", fileName); + fGUISupport->postErrorMessage(errorMessage, "Font Map Error"); + status = LE_FONT_FILE_NOT_FOUND_ERROR; + return; + } + + while (fgets(buffer, BUFFER_SIZE, file) != NULL) { + UScriptCode scriptCode; + UErrorCode scriptStatus = U_ZERO_ERROR; + + line = strip(buffer); + if (line[0] == '#' || line[0] == 0) { + continue; + } + + c = strchr(line, ':'); + c[0] = 0; + + fontName = strip(&c[1]); + scriptName = strip(line); + + if (strcmp(scriptName, "DEFAULT") == 0) { + defaultFont = getFontIndex(fontName); + continue; + } + + uscript_getCode(scriptName, &scriptCode, 1, &scriptStatus); + + if (U_FAILURE(scriptStatus) || scriptStatus == U_USING_FALLBACK_WARNING || + scriptStatus == U_USING_DEFAULT_WARNING) { + sprintf(errorMessage, "The script name %s is invalid.", line); + fGUISupport->postErrorMessage(errorMessage, "Font Map Error"); + status = LE_ILLEGAL_ARGUMENT_ERROR; + fclose(file); + return; + } + + script = (le_int32) scriptCode; + + if (fFontIndices[script] >= 0) { + // FIXME: complain that this is a duplicate entry and bail (?) + fFontIndices[script] = -1; + } + + fFontIndices[script] = getFontIndex(fontName); + } + + if (defaultFont >= 0) { + for (script = 0; script < scriptCodeCount; script += 1) { + if (fFontIndices[script] < 0) { + fFontIndices[script] = defaultFont; + } + } + } + + fclose(file); +} + +FontMap::~FontMap() +{ + le_int32 font; + + for (font = 0; font < fFontCount; font += 1) { + if (fFontNames[font] != NULL) { + delete[] (char *) fFontNames[font]; + } + } + + for (font = 0; font < fFontCount; font += 1) { + if (fFontInstances[font] != NULL) { + delete fFontInstances[font]; + } + } +} + +le_int32 FontMap::getFontIndex(const char *fontName) +{ + le_int32 index; + + for (index = 0; index < fFontCount; index += 1) { + if (strcmp(fontName, fFontNames[index]) == 0) { + return index; + } + } + + if (fFontCount < (le_int32) scriptCodeCount) { + index = fFontCount++; + } else { + // The font name table is full. Since there can + // only be scriptCodeCount fonts in use at once, + // there should be at least one that's not being + // referenced; find it and resue it's index. + + for (index = 0; index < fFontCount; index += 1) { + le_int32 script; + + for (script = 0; script < scriptCodeCount; script += 1) { + if (fFontIndices[script] == index) { + break; + } + } + + if (script >= scriptCodeCount) { + break; + } + } + } + + if (index >= scriptCodeCount) { + return -1; + } + + le_int32 len = strlen(fontName); + char *s = new char[len + 1]; + + fFontNames[index] = strcpy(s, fontName); + return index; +} + +char *FontMap::strip(char *s) +{ + le_int32 start, end, len; + + start = 0; + len = strlen(s); + + while (start < len && isspace(s[start])) { + start += 1; + } + + end = len - 1; + + while (end > start && isspace(s[end])) { + end -= 1; + } + + if (end < len) { + s[end + 1] = '\0'; + } + + return &s[start]; +} + +const LEFontInstance *FontMap::getScriptFont(le_int32 scriptCode, LEErrorCode &status) +{ + if (LE_FAILURE(status)) { + return NULL; + } + + if (scriptCode <= -1 || scriptCode >= scriptCodeCount) { + status = LE_ILLEGAL_ARGUMENT_ERROR; + return NULL; + } + + + le_int32 fontIndex = fFontIndices[scriptCode]; + + if (fontIndex < 0) { + sprintf(errorMessage, "No font was set for script %s", uscript_getName((UScriptCode) scriptCode)); + fGUISupport->postErrorMessage(errorMessage, "Font Map Error"); + status = LE_FONT_FILE_NOT_FOUND_ERROR; + return NULL; + } + + if (fFontInstances[fontIndex] == NULL) { + fFontInstances[fontIndex] = openFont(fFontNames[fontIndex], fPointSize, status); + + if (LE_FAILURE(status)) { + sprintf(errorMessage, "Could not open font file %s", fFontNames[fontIndex]); + fGUISupport->postErrorMessage(errorMessage, "Font Map Error"); + return NULL; + } + } + + return fFontInstances[fontIndex]; +} + +le_int32 FontMap::getAscent() const +{ + if (fAscent <= 0) { + ((FontMap *) this)->getMaxMetrics(); + } + + return fAscent; +} + +le_int32 FontMap::getDescent() const +{ + if (fDescent <= 0) { + ((FontMap *) this)->getMaxMetrics(); + } + + return fDescent; +} + +le_int32 FontMap::getLeading() const +{ + if (fLeading <= 0) { + ((FontMap *) this)->getMaxMetrics(); + } + + return fLeading; +} + +void FontMap::getMaxMetrics() +{ + for (le_int32 i = 0; i < fFontCount; i += 1) { + LEErrorCode status = LE_NO_ERROR; + le_int32 ascent, descent, leading; + + if (fFontInstances[i] == NULL) { + fFontInstances[i] = openFont(fFontNames[i], fPointSize, status); + + if (LE_FAILURE(status)) { + continue; + } + } + + ascent = fFontInstances[i]->getAscent(); + descent = fFontInstances[i]->getDescent(); + leading = fFontInstances[i]->getLeading(); + + if (ascent > fAscent) { + fAscent = ascent; + } + + if (descent > fDescent) { + fDescent = descent; + } + + if (leading > fLeading) { + fLeading = leading; + } + } +} + |