2 ******************************************************************************
3 * Copyright (C) 1998-2006, 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
;
26 le_bool haveFonts
= FALSE
;
29 for (i
= 0; i
< scriptCodeCount
; i
+= 1) {
32 fFontInstances
[i
] = NULL
;
36 if (LE_FAILURE(status
)) {
40 char *c
, *scriptName
, *fontName
, *line
, buffer
[BUFFER_SIZE
];
43 file
= fopen(fileName
, "r");
46 sprintf(errorMessage
, "Could not open the font map file: %s.", fileName
);
47 fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error");
48 status
= LE_FONT_FILE_NOT_FOUND_ERROR
;
52 while (fgets(buffer
, BUFFER_SIZE
, file
) != NULL
) {
53 UScriptCode scriptCode
;
54 UErrorCode scriptStatus
= U_ZERO_ERROR
;
57 if (line
[0] == '#' || line
[0] == 0) {
61 c
= strchr(line
, ':');
64 fontName
= strip(&c
[1]);
65 scriptName
= strip(line
);
67 if (strcmp(scriptName
, "DEFAULT") == 0) {
68 defaultFont
= getFontIndex(fontName
);
73 le_int32 fillCount
= uscript_getCode(scriptName
, &scriptCode
, 1, &scriptStatus
);
75 if (U_FAILURE(scriptStatus
) || fillCount
<= 0 ||
76 scriptStatus
== U_USING_FALLBACK_WARNING
|| scriptStatus
== U_USING_DEFAULT_WARNING
) {
77 sprintf(errorMessage
, "The script name %s is invalid.", line
);
78 fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error");
82 script
= (le_int32
) scriptCode
;
84 if (fFontIndices
[script
] >= 0) {
85 // FIXME: complain that this is a duplicate entry and bail (?)
86 fFontIndices
[script
] = -1;
89 fFontIndices
[script
] = getFontIndex(fontName
);
93 if (defaultFont
>= 0) {
94 for (script
= 0; script
< scriptCodeCount
; script
+= 1) {
95 if (fFontIndices
[script
] < 0) {
96 fFontIndices
[script
] = defaultFont
;
102 sprintf(errorMessage
, "The font map file %s does not contain any valid scripts.", fileName
);
103 fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error");
104 status
= LE_ILLEGAL_ARGUMENT_ERROR
;
114 for (font
= 0; font
< fFontCount
; font
+= 1) {
115 if (fFontNames
[font
] != NULL
) {
116 delete[] (char *) fFontNames
[font
];
120 for (font
= 0; font
< fFontCount
; font
+= 1) {
121 if (fFontInstances
[font
] != NULL
) {
122 delete fFontInstances
[font
];
127 le_int32
FontMap::getFontIndex(const char *fontName
)
131 for (index
= 0; index
< fFontCount
; index
+= 1) {
132 if (strcmp(fontName
, fFontNames
[index
]) == 0) {
137 if (fFontCount
< (le_int32
) scriptCodeCount
) {
138 index
= fFontCount
++;
140 // The font name table is full. Since there can
141 // only be scriptCodeCount fonts in use at once,
142 // there should be at least one that's not being
143 // referenced; find it and resue it's index.
145 for (index
= 0; index
< fFontCount
; index
+= 1) {
148 for (script
= 0; script
< scriptCodeCount
; script
+= 1) {
149 if (fFontIndices
[script
] == index
) {
154 if (script
>= scriptCodeCount
) {
160 if (index
>= scriptCodeCount
) {
164 le_int32 len
= strlen(fontName
);
165 char *s
= new char[len
+ 1];
167 fFontNames
[index
] = strcpy(s
, fontName
);
171 char *FontMap::strip(char *s
)
173 le_int32 start
, end
, len
;
178 while (start
< len
&& isspace(s
[start
])) {
184 while (end
> start
&& isspace(s
[end
])) {
195 const LEFontInstance
*FontMap::getScriptFont(le_int32 scriptCode
, LEErrorCode
&status
)
197 if (LE_FAILURE(status
)) {
201 if (scriptCode
<= -1 || scriptCode
>= scriptCodeCount
) {
202 status
= LE_ILLEGAL_ARGUMENT_ERROR
;
207 le_int32 fontIndex
= fFontIndices
[scriptCode
];
210 sprintf(errorMessage
, "No font was set for script %s", uscript_getName((UScriptCode
) scriptCode
));
211 fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error");
212 status
= LE_FONT_FILE_NOT_FOUND_ERROR
;
216 if (fFontInstances
[fontIndex
] == NULL
) {
217 fFontInstances
[fontIndex
] = openFont(fFontNames
[fontIndex
], fPointSize
, status
);
219 if (LE_FAILURE(status
)) {
220 sprintf(errorMessage
, "Could not open font file %s", fFontNames
[fontIndex
]);
221 fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error");
226 return fFontInstances
[fontIndex
];
229 le_int32
FontMap::getAscent() const
232 ((FontMap
*) this)->getMaxMetrics();
238 le_int32
FontMap::getDescent() const
241 ((FontMap
*) this)->getMaxMetrics();
247 le_int32
FontMap::getLeading() const
250 ((FontMap
*) this)->getMaxMetrics();
256 void FontMap::getMaxMetrics()
258 for (le_int32 i
= 0; i
< fFontCount
; i
+= 1) {
259 LEErrorCode status
= LE_NO_ERROR
;
260 le_int32 ascent
, descent
, leading
;
262 if (fFontInstances
[i
] == NULL
) {
263 fFontInstances
[i
] = openFont(fFontNames
[i
], fPointSize
, status
);
265 if (LE_FAILURE(status
)) {
270 ascent
= fFontInstances
[i
]->getAscent();
271 descent
= fFontInstances
[i
]->getDescent();
272 leading
= fFontInstances
[i
]->getLeading();
274 if (ascent
> fAscent
) {
278 if (descent
> fDescent
) {
282 if (leading
> fLeading
) {