2 ******************************************************************************
3 * Copyright (C) 1998-2003, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 ******************************************************************************
12 #include "unicode/utypes.h"
13 #include "unicode/uscript.h"
15 #include "layout/LETypes.h"
16 #include "layout/LEScripts.h"
17 #include "layout/LEFontInstance.h"
19 #include "GUISupport.h"
22 FontMap::FontMap(const char *fileName
, le_int16 pointSize
, GUISupport
*guiSupport
, LEErrorCode
&status
)
23 : fPointSize(pointSize
), fFontCount(0), fAscent(0), fDescent(0), fLeading(0), fGUISupport(guiSupport
)
25 le_int32 defaultFont
= -1, i
, script
;
27 for (i
= 0; i
< scriptCodeCount
; i
+= 1) {
30 fFontInstances
[i
] = NULL
;
33 if (LE_FAILURE(status
)) {
37 char *c
, *scriptName
, *fontName
, *line
, buffer
[BUFFER_SIZE
];
40 file
= fopen(fileName
, "r");
43 sprintf(errorMessage
, "Could not open the font map file: %s.", fileName
);
44 fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error");
45 status
= LE_FONT_FILE_NOT_FOUND_ERROR
;
49 while (fgets(buffer
, BUFFER_SIZE
, file
) != NULL
) {
50 UScriptCode scriptCode
;
51 UErrorCode scriptStatus
= U_ZERO_ERROR
;
54 if (line
[0] == '#' || line
[0] == 0) {
58 c
= strchr(line
, ':');
61 fontName
= strip(&c
[1]);
62 scriptName
= strip(line
);
64 if (strcmp(scriptName
, "DEFAULT") == 0) {
65 defaultFont
= getFontIndex(fontName
);
69 uscript_getCode(scriptName
, &scriptCode
, 1, &scriptStatus
);
71 if (U_FAILURE(scriptStatus
) || scriptStatus
== U_USING_FALLBACK_WARNING
||
72 scriptStatus
== U_USING_DEFAULT_WARNING
) {
73 sprintf(errorMessage
, "The script name %s is invalid.", line
);
74 fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error");
75 status
= LE_ILLEGAL_ARGUMENT_ERROR
;
80 script
= (le_int32
) scriptCode
;
82 if (fFontIndices
[script
] >= 0) {
83 // FIXME: complain that this is a duplicate entry and bail (?)
84 fFontIndices
[script
] = -1;
87 fFontIndices
[script
] = getFontIndex(fontName
);
90 if (defaultFont
>= 0) {
91 for (script
= 0; script
< scriptCodeCount
; script
+= 1) {
92 if (fFontIndices
[script
] < 0) {
93 fFontIndices
[script
] = defaultFont
;
105 for (font
= 0; font
< fFontCount
; font
+= 1) {
106 if (fFontNames
[font
] != NULL
) {
107 delete[] (char *) fFontNames
[font
];
111 for (font
= 0; font
< fFontCount
; font
+= 1) {
112 if (fFontInstances
[font
] != NULL
) {
113 delete fFontInstances
[font
];
118 le_int32
FontMap::getFontIndex(const char *fontName
)
122 for (index
= 0; index
< fFontCount
; index
+= 1) {
123 if (strcmp(fontName
, fFontNames
[index
]) == 0) {
128 if (fFontCount
< (le_int32
) scriptCodeCount
) {
129 index
= fFontCount
++;
131 // The font name table is full. Since there can
132 // only be scriptCodeCount fonts in use at once,
133 // there should be at least one that's not being
134 // referenced; find it and resue it's index.
136 for (index
= 0; index
< fFontCount
; index
+= 1) {
139 for (script
= 0; script
< scriptCodeCount
; script
+= 1) {
140 if (fFontIndices
[script
] == index
) {
145 if (script
>= scriptCodeCount
) {
151 if (index
>= scriptCodeCount
) {
155 le_int32 len
= strlen(fontName
);
156 char *s
= new char[len
+ 1];
158 fFontNames
[index
] = strcpy(s
, fontName
);
162 char *FontMap::strip(char *s
)
164 le_int32 start
, end
, len
;
169 while (start
< len
&& isspace(s
[start
])) {
175 while (end
> start
&& isspace(s
[end
])) {
186 const LEFontInstance
*FontMap::getScriptFont(le_int32 scriptCode
, LEErrorCode
&status
)
188 if (LE_FAILURE(status
)) {
192 if (scriptCode
<= -1 || scriptCode
>= scriptCodeCount
) {
193 status
= LE_ILLEGAL_ARGUMENT_ERROR
;
198 le_int32 fontIndex
= fFontIndices
[scriptCode
];
201 sprintf(errorMessage
, "No font was set for script %s", uscript_getName((UScriptCode
) scriptCode
));
202 fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error");
203 status
= LE_FONT_FILE_NOT_FOUND_ERROR
;
207 if (fFontInstances
[fontIndex
] == NULL
) {
208 fFontInstances
[fontIndex
] = openFont(fFontNames
[fontIndex
], fPointSize
, status
);
210 if (LE_FAILURE(status
)) {
211 sprintf(errorMessage
, "Could not open font file %s", fFontNames
[fontIndex
]);
212 fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error");
217 return fFontInstances
[fontIndex
];
220 le_int32
FontMap::getAscent() const
223 ((FontMap
*) this)->getMaxMetrics();
229 le_int32
FontMap::getDescent() const
232 ((FontMap
*) this)->getMaxMetrics();
238 le_int32
FontMap::getLeading() const
241 ((FontMap
*) this)->getMaxMetrics();
247 void FontMap::getMaxMetrics()
249 for (le_int32 i
= 0; i
< fFontCount
; i
+= 1) {
250 LEErrorCode status
= LE_NO_ERROR
;
251 le_int32 ascent
, descent
, leading
;
253 if (fFontInstances
[i
] == NULL
) {
254 fFontInstances
[i
] = openFont(fFontNames
[i
], fPointSize
, status
);
256 if (LE_FAILURE(status
)) {
261 ascent
= fFontInstances
[i
]->getAscent();
262 descent
= fFontInstances
[i
]->getDescent();
263 leading
= fFontInstances
[i
]->getLeading();
265 if (ascent
> fAscent
) {
269 if (descent
> fDescent
) {
273 if (leading
> fLeading
) {