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
) {