2  ****************************************************************************** 
   3  * © 2016 and later: Unicode, Inc. and others.                    * 
   4  * License & terms of use: http://www.unicode.org/copyright.html#License      * 
   5  ****************************************************************************** 
   6  ****************************************************************************** 
   7  * Copyright (C) 1998-2006, International Business Machines Corporation and   * 
   8  * others. All Rights Reserved.                                               * 
   9  ****************************************************************************** 
  16 #include "unicode/utypes.h" 
  17 #include "unicode/uscript.h" 
  19 #include "layout/LETypes.h" 
  20 #include "layout/LEScripts.h" 
  21 #include "layout/LEFontInstance.h" 
  23 #include "GUISupport.h" 
  26 FontMap::FontMap(const char *fileName
, le_int16 pointSize
, GUISupport 
*guiSupport
, LEErrorCode 
&status
) 
  27     : fPointSize(pointSize
), fFontCount(0), fAscent(0), fDescent(0), fLeading(0), fGUISupport(guiSupport
) 
  29     le_int32 defaultFont 
= -1, i
, script
; 
  30     le_bool haveFonts 
= FALSE
; 
  33     for (i 
= 0; i 
< scriptCodeCount
; i 
+= 1) { 
  36         fFontInstances
[i
] = NULL
; 
  40     if (LE_FAILURE(status
)) { 
  44     char *c
, *scriptName
, *fontName
, *line
, buffer
[BUFFER_SIZE
]; 
  47     file 
= fopen(fileName
, "r"); 
  50         sprintf(errorMessage
, "Could not open the font map file: %s.", fileName
); 
  51         fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error"); 
  52         status 
= LE_FONT_FILE_NOT_FOUND_ERROR
; 
  56     while (fgets(buffer
, BUFFER_SIZE
, file
) != NULL
) { 
  57         UScriptCode scriptCode
; 
  58         UErrorCode scriptStatus 
= U_ZERO_ERROR
; 
  61         if (line
[0] == '#' || line
[0] == 0) { 
  65         c 
= strchr(line
, ':'); 
  68         fontName   
= strip(&c
[1]); 
  69         scriptName 
= strip(line
); 
  71         if (strcmp(scriptName
, "DEFAULT") == 0) { 
  72             defaultFont 
= getFontIndex(fontName
); 
  77         le_int32 fillCount 
= uscript_getCode(scriptName
, &scriptCode
, 1, &scriptStatus
); 
  79         if (U_FAILURE(scriptStatus
) || fillCount 
<= 0 || 
  80             scriptStatus 
== U_USING_FALLBACK_WARNING 
|| scriptStatus 
== U_USING_DEFAULT_WARNING
) { 
  81             sprintf(errorMessage
, "The script name %s is invalid.", line
); 
  82             fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error"); 
  86         script 
= (le_int32
) scriptCode
; 
  88         if (fFontIndices
[script
] >= 0) { 
  89             // FIXME: complain that this is a duplicate entry and bail (?) 
  90             fFontIndices
[script
] = -1; 
  93         fFontIndices
[script
] = getFontIndex(fontName
); 
  97     if (defaultFont 
>= 0) { 
  98         for (script 
= 0; script 
< scriptCodeCount
; script 
+= 1) { 
  99             if (fFontIndices
[script
] < 0) { 
 100                 fFontIndices
[script
] = defaultFont
; 
 106         sprintf(errorMessage
, "The font map file %s does not contain any valid scripts.", fileName
); 
 107         fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error"); 
 108         status 
= LE_ILLEGAL_ARGUMENT_ERROR
; 
 118     for (font 
= 0; font 
< fFontCount
; font 
+= 1) { 
 119         if (fFontNames
[font
] != NULL
) { 
 120             delete[] (char *) fFontNames
[font
]; 
 124     for (font 
= 0; font 
< fFontCount
; font 
+= 1) { 
 125         if (fFontInstances
[font
] != NULL
) { 
 126             delete fFontInstances
[font
]; 
 131 le_int32 
FontMap::getFontIndex(const char *fontName
) 
 135     for (index 
= 0; index 
< fFontCount
; index 
+= 1) { 
 136         if (strcmp(fontName
, fFontNames
[index
]) == 0) { 
 141     if (fFontCount 
< (le_int32
) scriptCodeCount
) { 
 142         index 
= fFontCount
++; 
 144         // The font name table is full. Since there can 
 145         // only be scriptCodeCount fonts in use at once, 
 146         // there should be at least one that's not being 
 147         // referenced; find it and resue it's index. 
 149         for (index 
= 0; index 
< fFontCount
; index 
+= 1) { 
 152             for (script 
= 0; script 
< scriptCodeCount
; script 
+= 1) { 
 153                 if (fFontIndices
[script
] == index
) { 
 158             if (script 
>= scriptCodeCount
) { 
 164     if (index 
>= scriptCodeCount
) { 
 168     le_int32 len 
= strlen(fontName
); 
 169     char *s 
= new char[len 
+ 1]; 
 171     fFontNames
[index
] = strcpy(s
, fontName
); 
 175 char *FontMap::strip(char *s
) 
 177     le_int32 start
, end
, len
; 
 182     while (start 
< len 
&& isspace(s
[start
])) { 
 188     while (end 
> start 
&& isspace(s
[end
])) { 
 199 const LEFontInstance 
*FontMap::getScriptFont(le_int32 scriptCode
, LEErrorCode 
&status
) 
 201     if (LE_FAILURE(status
)) { 
 205     if (scriptCode 
<= -1 || scriptCode 
>= scriptCodeCount
) { 
 206         status 
= LE_ILLEGAL_ARGUMENT_ERROR
; 
 211     le_int32 fontIndex 
= fFontIndices
[scriptCode
]; 
 214         sprintf(errorMessage
, "No font was set for script %s", uscript_getName((UScriptCode
) scriptCode
)); 
 215         fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error"); 
 216         status 
= LE_FONT_FILE_NOT_FOUND_ERROR
; 
 220     if (fFontInstances
[fontIndex
] == NULL
) { 
 221         fFontInstances
[fontIndex
] = openFont(fFontNames
[fontIndex
], fPointSize
, status
); 
 223         if (LE_FAILURE(status
)) { 
 224             sprintf(errorMessage
, "Could not open font file %s", fFontNames
[fontIndex
]); 
 225             fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error"); 
 230     return fFontInstances
[fontIndex
]; 
 233 le_int32 
FontMap::getAscent() const 
 236         ((FontMap 
*) this)->getMaxMetrics(); 
 242 le_int32 
FontMap::getDescent() const 
 245         ((FontMap 
*) this)->getMaxMetrics(); 
 251 le_int32 
FontMap::getLeading() const 
 254         ((FontMap 
*) this)->getMaxMetrics(); 
 260 void FontMap::getMaxMetrics() 
 262     for (le_int32 i 
= 0; i 
< fFontCount
; i 
+= 1) { 
 263         LEErrorCode status 
= LE_NO_ERROR
; 
 264         le_int32 ascent
, descent
, leading
; 
 266         if (fFontInstances
[i
] == NULL
) { 
 267             fFontInstances
[i
] = openFont(fFontNames
[i
], fPointSize
, status
); 
 269             if (LE_FAILURE(status
)) { 
 274         ascent  
= fFontInstances
[i
]->getAscent(); 
 275         descent 
= fFontInstances
[i
]->getDescent(); 
 276         leading 
= fFontInstances
[i
]->getLeading(); 
 278         if (ascent 
> fAscent
) { 
 282         if (descent 
> fDescent
) { 
 286         if (leading 
> fLeading
) {