12e5b6d6dSopenharmony_ci/* 22e5b6d6dSopenharmony_ci ****************************************************************************** 32e5b6d6dSopenharmony_ci * © 2016 and later: Unicode, Inc. and others. * 42e5b6d6dSopenharmony_ci * License & terms of use: http://www.unicode.org/copyright.html * 52e5b6d6dSopenharmony_ci ****************************************************************************** 62e5b6d6dSopenharmony_ci ****************************************************************************** 72e5b6d6dSopenharmony_ci * Copyright (C) 1998-2006, International Business Machines Corporation and * 82e5b6d6dSopenharmony_ci * others. All Rights Reserved. * 92e5b6d6dSopenharmony_ci ****************************************************************************** 102e5b6d6dSopenharmony_ci */ 112e5b6d6dSopenharmony_ci 122e5b6d6dSopenharmony_ci#include <stdio.h> 132e5b6d6dSopenharmony_ci#include <string.h> 142e5b6d6dSopenharmony_ci#include <ctype.h> 152e5b6d6dSopenharmony_ci 162e5b6d6dSopenharmony_ci#include "unicode/utypes.h" 172e5b6d6dSopenharmony_ci#include "unicode/uscript.h" 182e5b6d6dSopenharmony_ci 192e5b6d6dSopenharmony_ci#include "layout/LETypes.h" 202e5b6d6dSopenharmony_ci#include "layout/LEScripts.h" 212e5b6d6dSopenharmony_ci#include "layout/LEFontInstance.h" 222e5b6d6dSopenharmony_ci 232e5b6d6dSopenharmony_ci#include "GUISupport.h" 242e5b6d6dSopenharmony_ci#include "FontMap.h" 252e5b6d6dSopenharmony_ci 262e5b6d6dSopenharmony_ciFontMap::FontMap(const char *fileName, le_int16 pointSize, GUISupport *guiSupport, LEErrorCode &status) 272e5b6d6dSopenharmony_ci : fPointSize(pointSize), fFontCount(0), fAscent(0), fDescent(0), fLeading(0), fGUISupport(guiSupport) 282e5b6d6dSopenharmony_ci{ 292e5b6d6dSopenharmony_ci le_int32 defaultFont = -1, i, script; 302e5b6d6dSopenharmony_ci le_bool haveFonts = false; 312e5b6d6dSopenharmony_ci 322e5b6d6dSopenharmony_ci/**/ 332e5b6d6dSopenharmony_ci for (i = 0; i < scriptCodeCount; i += 1) { 342e5b6d6dSopenharmony_ci fFontIndices[i] = -1; 352e5b6d6dSopenharmony_ci fFontNames[i] = NULL; 362e5b6d6dSopenharmony_ci fFontInstances[i] = NULL; 372e5b6d6dSopenharmony_ci } 382e5b6d6dSopenharmony_ci /**/ 392e5b6d6dSopenharmony_ci 402e5b6d6dSopenharmony_ci if (LE_FAILURE(status)) { 412e5b6d6dSopenharmony_ci return; 422e5b6d6dSopenharmony_ci } 432e5b6d6dSopenharmony_ci 442e5b6d6dSopenharmony_ci char *c, *scriptName, *fontName, *line, buffer[BUFFER_SIZE]; 452e5b6d6dSopenharmony_ci FILE *file; 462e5b6d6dSopenharmony_ci 472e5b6d6dSopenharmony_ci file = fopen(fileName, "r"); 482e5b6d6dSopenharmony_ci 492e5b6d6dSopenharmony_ci if (file == NULL) { 502e5b6d6dSopenharmony_ci sprintf(errorMessage, "Could not open the font map file: %s.", fileName); 512e5b6d6dSopenharmony_ci fGUISupport->postErrorMessage(errorMessage, "Font Map Error"); 522e5b6d6dSopenharmony_ci status = LE_FONT_FILE_NOT_FOUND_ERROR; 532e5b6d6dSopenharmony_ci return; 542e5b6d6dSopenharmony_ci } 552e5b6d6dSopenharmony_ci 562e5b6d6dSopenharmony_ci while (fgets(buffer, BUFFER_SIZE, file) != NULL) { 572e5b6d6dSopenharmony_ci UScriptCode scriptCode; 582e5b6d6dSopenharmony_ci UErrorCode scriptStatus = U_ZERO_ERROR; 592e5b6d6dSopenharmony_ci 602e5b6d6dSopenharmony_ci line = strip(buffer); 612e5b6d6dSopenharmony_ci if (line[0] == '#' || line[0] == 0) { 622e5b6d6dSopenharmony_ci continue; 632e5b6d6dSopenharmony_ci } 642e5b6d6dSopenharmony_ci 652e5b6d6dSopenharmony_ci c = strchr(line, ':'); 662e5b6d6dSopenharmony_ci c[0] = 0; 672e5b6d6dSopenharmony_ci 682e5b6d6dSopenharmony_ci fontName = strip(&c[1]); 692e5b6d6dSopenharmony_ci scriptName = strip(line); 702e5b6d6dSopenharmony_ci 712e5b6d6dSopenharmony_ci if (strcmp(scriptName, "DEFAULT") == 0) { 722e5b6d6dSopenharmony_ci defaultFont = getFontIndex(fontName); 732e5b6d6dSopenharmony_ci haveFonts = true; 742e5b6d6dSopenharmony_ci continue; 752e5b6d6dSopenharmony_ci } 762e5b6d6dSopenharmony_ci 772e5b6d6dSopenharmony_ci le_int32 fillCount = uscript_getCode(scriptName, &scriptCode, 1, &scriptStatus); 782e5b6d6dSopenharmony_ci 792e5b6d6dSopenharmony_ci if (U_FAILURE(scriptStatus) || fillCount <= 0 || 802e5b6d6dSopenharmony_ci scriptStatus == U_USING_FALLBACK_WARNING || scriptStatus == U_USING_DEFAULT_WARNING) { 812e5b6d6dSopenharmony_ci sprintf(errorMessage, "The script name %s is invalid.", line); 822e5b6d6dSopenharmony_ci fGUISupport->postErrorMessage(errorMessage, "Font Map Error"); 832e5b6d6dSopenharmony_ci continue; 842e5b6d6dSopenharmony_ci } 852e5b6d6dSopenharmony_ci 862e5b6d6dSopenharmony_ci script = (le_int32) scriptCode; 872e5b6d6dSopenharmony_ci 882e5b6d6dSopenharmony_ci if (fFontIndices[script] >= 0) { 892e5b6d6dSopenharmony_ci // FIXME: complain that this is a duplicate entry and bail (?) 902e5b6d6dSopenharmony_ci fFontIndices[script] = -1; 912e5b6d6dSopenharmony_ci } 922e5b6d6dSopenharmony_ci 932e5b6d6dSopenharmony_ci fFontIndices[script] = getFontIndex(fontName); 942e5b6d6dSopenharmony_ci haveFonts = true; 952e5b6d6dSopenharmony_ci } 962e5b6d6dSopenharmony_ci 972e5b6d6dSopenharmony_ci if (defaultFont >= 0) { 982e5b6d6dSopenharmony_ci for (script = 0; script < scriptCodeCount; script += 1) { 992e5b6d6dSopenharmony_ci if (fFontIndices[script] < 0) { 1002e5b6d6dSopenharmony_ci fFontIndices[script] = defaultFont; 1012e5b6d6dSopenharmony_ci } 1022e5b6d6dSopenharmony_ci } 1032e5b6d6dSopenharmony_ci } 1042e5b6d6dSopenharmony_ci 1052e5b6d6dSopenharmony_ci if (! haveFonts) { 1062e5b6d6dSopenharmony_ci sprintf(errorMessage, "The font map file %s does not contain any valid scripts.", fileName); 1072e5b6d6dSopenharmony_ci fGUISupport->postErrorMessage(errorMessage, "Font Map Error"); 1082e5b6d6dSopenharmony_ci status = LE_ILLEGAL_ARGUMENT_ERROR; 1092e5b6d6dSopenharmony_ci } 1102e5b6d6dSopenharmony_ci 1112e5b6d6dSopenharmony_ci fclose(file); 1122e5b6d6dSopenharmony_ci} 1132e5b6d6dSopenharmony_ci 1142e5b6d6dSopenharmony_ciFontMap::~FontMap() 1152e5b6d6dSopenharmony_ci{ 1162e5b6d6dSopenharmony_ci le_int32 font; 1172e5b6d6dSopenharmony_ci 1182e5b6d6dSopenharmony_ci for (font = 0; font < fFontCount; font += 1) { 1192e5b6d6dSopenharmony_ci if (fFontNames[font] != NULL) { 1202e5b6d6dSopenharmony_ci delete[] (char *) fFontNames[font]; 1212e5b6d6dSopenharmony_ci } 1222e5b6d6dSopenharmony_ci } 1232e5b6d6dSopenharmony_ci 1242e5b6d6dSopenharmony_ci for (font = 0; font < fFontCount; font += 1) { 1252e5b6d6dSopenharmony_ci if (fFontInstances[font] != NULL) { 1262e5b6d6dSopenharmony_ci delete fFontInstances[font]; 1272e5b6d6dSopenharmony_ci } 1282e5b6d6dSopenharmony_ci } 1292e5b6d6dSopenharmony_ci} 1302e5b6d6dSopenharmony_ci 1312e5b6d6dSopenharmony_cile_int32 FontMap::getFontIndex(const char *fontName) 1322e5b6d6dSopenharmony_ci{ 1332e5b6d6dSopenharmony_ci le_int32 index; 1342e5b6d6dSopenharmony_ci 1352e5b6d6dSopenharmony_ci for (index = 0; index < fFontCount; index += 1) { 1362e5b6d6dSopenharmony_ci if (strcmp(fontName, fFontNames[index]) == 0) { 1372e5b6d6dSopenharmony_ci return index; 1382e5b6d6dSopenharmony_ci } 1392e5b6d6dSopenharmony_ci } 1402e5b6d6dSopenharmony_ci 1412e5b6d6dSopenharmony_ci if (fFontCount < (le_int32) scriptCodeCount) { 1422e5b6d6dSopenharmony_ci index = fFontCount++; 1432e5b6d6dSopenharmony_ci } else { 1442e5b6d6dSopenharmony_ci // The font name table is full. Since there can 1452e5b6d6dSopenharmony_ci // only be scriptCodeCount fonts in use at once, 1462e5b6d6dSopenharmony_ci // there should be at least one that's not being 1472e5b6d6dSopenharmony_ci // referenced; find it and reuse it's index. 1482e5b6d6dSopenharmony_ci 1492e5b6d6dSopenharmony_ci for (index = 0; index < fFontCount; index += 1) { 1502e5b6d6dSopenharmony_ci le_int32 script; 1512e5b6d6dSopenharmony_ci 1522e5b6d6dSopenharmony_ci for (script = 0; script < scriptCodeCount; script += 1) { 1532e5b6d6dSopenharmony_ci if (fFontIndices[script] == index) { 1542e5b6d6dSopenharmony_ci break; 1552e5b6d6dSopenharmony_ci } 1562e5b6d6dSopenharmony_ci } 1572e5b6d6dSopenharmony_ci 1582e5b6d6dSopenharmony_ci if (script >= scriptCodeCount) { 1592e5b6d6dSopenharmony_ci break; 1602e5b6d6dSopenharmony_ci } 1612e5b6d6dSopenharmony_ci } 1622e5b6d6dSopenharmony_ci } 1632e5b6d6dSopenharmony_ci 1642e5b6d6dSopenharmony_ci if (index >= scriptCodeCount) { 1652e5b6d6dSopenharmony_ci return -1; 1662e5b6d6dSopenharmony_ci } 1672e5b6d6dSopenharmony_ci 1682e5b6d6dSopenharmony_ci le_int32 len = strlen(fontName); 1692e5b6d6dSopenharmony_ci char *s = new char[len + 1]; 1702e5b6d6dSopenharmony_ci 1712e5b6d6dSopenharmony_ci fFontNames[index] = strcpy(s, fontName); 1722e5b6d6dSopenharmony_ci return index; 1732e5b6d6dSopenharmony_ci} 1742e5b6d6dSopenharmony_ci 1752e5b6d6dSopenharmony_cichar *FontMap::strip(char *s) 1762e5b6d6dSopenharmony_ci{ 1772e5b6d6dSopenharmony_ci le_int32 start, end, len; 1782e5b6d6dSopenharmony_ci 1792e5b6d6dSopenharmony_ci start = 0; 1802e5b6d6dSopenharmony_ci len = strlen(s); 1812e5b6d6dSopenharmony_ci 1822e5b6d6dSopenharmony_ci while (start < len && isspace(s[start])) { 1832e5b6d6dSopenharmony_ci start += 1; 1842e5b6d6dSopenharmony_ci } 1852e5b6d6dSopenharmony_ci 1862e5b6d6dSopenharmony_ci end = len - 1; 1872e5b6d6dSopenharmony_ci 1882e5b6d6dSopenharmony_ci while (end > start && isspace(s[end])) { 1892e5b6d6dSopenharmony_ci end -= 1; 1902e5b6d6dSopenharmony_ci } 1912e5b6d6dSopenharmony_ci 1922e5b6d6dSopenharmony_ci if (end < len) { 1932e5b6d6dSopenharmony_ci s[end + 1] = '\0'; 1942e5b6d6dSopenharmony_ci } 1952e5b6d6dSopenharmony_ci 1962e5b6d6dSopenharmony_ci return &s[start]; 1972e5b6d6dSopenharmony_ci} 1982e5b6d6dSopenharmony_ci 1992e5b6d6dSopenharmony_ciconst LEFontInstance *FontMap::getScriptFont(le_int32 scriptCode, LEErrorCode &status) 2002e5b6d6dSopenharmony_ci{ 2012e5b6d6dSopenharmony_ci if (LE_FAILURE(status)) { 2022e5b6d6dSopenharmony_ci return NULL; 2032e5b6d6dSopenharmony_ci } 2042e5b6d6dSopenharmony_ci 2052e5b6d6dSopenharmony_ci if (scriptCode <= -1 || scriptCode >= scriptCodeCount) { 2062e5b6d6dSopenharmony_ci status = LE_ILLEGAL_ARGUMENT_ERROR; 2072e5b6d6dSopenharmony_ci return NULL; 2082e5b6d6dSopenharmony_ci } 2092e5b6d6dSopenharmony_ci 2102e5b6d6dSopenharmony_ci 2112e5b6d6dSopenharmony_ci le_int32 fontIndex = fFontIndices[scriptCode]; 2122e5b6d6dSopenharmony_ci 2132e5b6d6dSopenharmony_ci if (fontIndex < 0) { 2142e5b6d6dSopenharmony_ci sprintf(errorMessage, "No font was set for script %s", uscript_getName((UScriptCode) scriptCode)); 2152e5b6d6dSopenharmony_ci fGUISupport->postErrorMessage(errorMessage, "Font Map Error"); 2162e5b6d6dSopenharmony_ci status = LE_FONT_FILE_NOT_FOUND_ERROR; 2172e5b6d6dSopenharmony_ci return NULL; 2182e5b6d6dSopenharmony_ci } 2192e5b6d6dSopenharmony_ci 2202e5b6d6dSopenharmony_ci if (fFontInstances[fontIndex] == NULL) { 2212e5b6d6dSopenharmony_ci fFontInstances[fontIndex] = openFont(fFontNames[fontIndex], fPointSize, status); 2222e5b6d6dSopenharmony_ci 2232e5b6d6dSopenharmony_ci if (LE_FAILURE(status)) { 2242e5b6d6dSopenharmony_ci sprintf(errorMessage, "Could not open font file %s", fFontNames[fontIndex]); 2252e5b6d6dSopenharmony_ci fGUISupport->postErrorMessage(errorMessage, "Font Map Error"); 2262e5b6d6dSopenharmony_ci return NULL; 2272e5b6d6dSopenharmony_ci } 2282e5b6d6dSopenharmony_ci } 2292e5b6d6dSopenharmony_ci 2302e5b6d6dSopenharmony_ci return fFontInstances[fontIndex]; 2312e5b6d6dSopenharmony_ci} 2322e5b6d6dSopenharmony_ci 2332e5b6d6dSopenharmony_cile_int32 FontMap::getAscent() const 2342e5b6d6dSopenharmony_ci{ 2352e5b6d6dSopenharmony_ci if (fAscent <= 0) { 2362e5b6d6dSopenharmony_ci ((FontMap *) this)->getMaxMetrics(); 2372e5b6d6dSopenharmony_ci } 2382e5b6d6dSopenharmony_ci 2392e5b6d6dSopenharmony_ci return fAscent; 2402e5b6d6dSopenharmony_ci} 2412e5b6d6dSopenharmony_ci 2422e5b6d6dSopenharmony_cile_int32 FontMap::getDescent() const 2432e5b6d6dSopenharmony_ci{ 2442e5b6d6dSopenharmony_ci if (fDescent <= 0) { 2452e5b6d6dSopenharmony_ci ((FontMap *) this)->getMaxMetrics(); 2462e5b6d6dSopenharmony_ci } 2472e5b6d6dSopenharmony_ci 2482e5b6d6dSopenharmony_ci return fDescent; 2492e5b6d6dSopenharmony_ci} 2502e5b6d6dSopenharmony_ci 2512e5b6d6dSopenharmony_cile_int32 FontMap::getLeading() const 2522e5b6d6dSopenharmony_ci{ 2532e5b6d6dSopenharmony_ci if (fLeading <= 0) { 2542e5b6d6dSopenharmony_ci ((FontMap *) this)->getMaxMetrics(); 2552e5b6d6dSopenharmony_ci } 2562e5b6d6dSopenharmony_ci 2572e5b6d6dSopenharmony_ci return fLeading; 2582e5b6d6dSopenharmony_ci} 2592e5b6d6dSopenharmony_ci 2602e5b6d6dSopenharmony_civoid FontMap::getMaxMetrics() 2612e5b6d6dSopenharmony_ci{ 2622e5b6d6dSopenharmony_ci for (le_int32 i = 0; i < fFontCount; i += 1) { 2632e5b6d6dSopenharmony_ci LEErrorCode status = LE_NO_ERROR; 2642e5b6d6dSopenharmony_ci le_int32 ascent, descent, leading; 2652e5b6d6dSopenharmony_ci 2662e5b6d6dSopenharmony_ci if (fFontInstances[i] == NULL) { 2672e5b6d6dSopenharmony_ci fFontInstances[i] = openFont(fFontNames[i], fPointSize, status); 2682e5b6d6dSopenharmony_ci 2692e5b6d6dSopenharmony_ci if (LE_FAILURE(status)) { 2702e5b6d6dSopenharmony_ci continue; 2712e5b6d6dSopenharmony_ci } 2722e5b6d6dSopenharmony_ci } 2732e5b6d6dSopenharmony_ci 2742e5b6d6dSopenharmony_ci ascent = fFontInstances[i]->getAscent(); 2752e5b6d6dSopenharmony_ci descent = fFontInstances[i]->getDescent(); 2762e5b6d6dSopenharmony_ci leading = fFontInstances[i]->getLeading(); 2772e5b6d6dSopenharmony_ci 2782e5b6d6dSopenharmony_ci if (ascent > fAscent) { 2792e5b6d6dSopenharmony_ci fAscent = ascent; 2802e5b6d6dSopenharmony_ci } 2812e5b6d6dSopenharmony_ci 2822e5b6d6dSopenharmony_ci if (descent > fDescent) { 2832e5b6d6dSopenharmony_ci fDescent = descent; 2842e5b6d6dSopenharmony_ci } 2852e5b6d6dSopenharmony_ci 2862e5b6d6dSopenharmony_ci if (leading > fLeading) { 2872e5b6d6dSopenharmony_ci fLeading = leading; 2882e5b6d6dSopenharmony_ci } 2892e5b6d6dSopenharmony_ci } 2902e5b6d6dSopenharmony_ci} 2912e5b6d6dSopenharmony_ci 292