2 ******************************************************************************
3 * Copyright (C) 1998-2005, 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
;
28 for (i
= 0; i
< scriptCodeCount
; i
+= 1) {
31 fFontInstances
[i
] = NULL
;
34 if (LE_FAILURE(status
)) {
38 char *c
, *scriptName
, *fontName
, *line
, buffer
[BUFFER_SIZE
];
41 file
= fopen(fileName
, "r");
44 sprintf(errorMessage
, "Could not open the font map file: %s.", fileName
);
45 fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error");
46 status
= LE_FONT_FILE_NOT_FOUND_ERROR
;
50 while (fgets(buffer
, BUFFER_SIZE
, file
) != NULL
) {
51 UScriptCode scriptCode
;
52 UErrorCode scriptStatus
= U_ZERO_ERROR
;
55 if (line
[0] == '#' || line
[0] == 0) {
59 c
= strchr(line
, ':');
62 fontName
= strip(&c
[1]);
63 scriptName
= strip(line
);
65 if (strcmp(scriptName
, "DEFAULT") == 0) {
66 defaultFont
= getFontIndex(fontName
);
71 le_int32 fillCount
= uscript_getCode(scriptName
, &scriptCode
, 1, &scriptStatus
);
73 if (U_FAILURE(scriptStatus
) || fillCount
<= 0 ||
74 scriptStatus
== U_USING_FALLBACK_WARNING
|| scriptStatus
== U_USING_DEFAULT_WARNING
) {
75 sprintf(errorMessage
, "The script name %s is invalid.", line
);
76 fGUISupport
->postErrorMessage(errorMessage
, "Font Map 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
);
91 if (defaultFont
>= 0) {
92 for (script
= 0; script
< scriptCodeCount
; script
+= 1) {
93 if (fFontIndices
[script
] < 0) {
94 fFontIndices
[script
] = defaultFont
;
100 sprintf(errorMessage
, "The font map file %s does not contain any valid scripts.", fileName
);
101 fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error");
102 status
= LE_ILLEGAL_ARGUMENT_ERROR
;
112 for (font
= 0; font
< fFontCount
; font
+= 1) {
113 if (fFontNames
[font
] != NULL
) {
114 delete[] (char *) fFontNames
[font
];
118 for (font
= 0; font
< fFontCount
; font
+= 1) {
119 if (fFontInstances
[font
] != NULL
) {
120 delete fFontInstances
[font
];
125 le_int32
FontMap::getFontIndex(const char *fontName
)
129 for (index
= 0; index
< fFontCount
; index
+= 1) {
130 if (strcmp(fontName
, fFontNames
[index
]) == 0) {
135 if (fFontCount
< (le_int32
) scriptCodeCount
) {
136 index
= fFontCount
++;
138 // The font name table is full. Since there can
139 // only be scriptCodeCount fonts in use at once,
140 // there should be at least one that's not being
141 // referenced; find it and resue it's index.
143 for (index
= 0; index
< fFontCount
; index
+= 1) {
146 for (script
= 0; script
< scriptCodeCount
; script
+= 1) {
147 if (fFontIndices
[script
] == index
) {
152 if (script
>= scriptCodeCount
) {
158 if (index
>= scriptCodeCount
) {
162 le_int32 len
= strlen(fontName
);
163 char *s
= new char[len
+ 1];
165 fFontNames
[index
] = strcpy(s
, fontName
);
169 char *FontMap::strip(char *s
)
171 le_int32 start
, end
, len
;
176 while (start
< len
&& isspace(s
[start
])) {
182 while (end
> start
&& isspace(s
[end
])) {
193 const LEFontInstance
*FontMap::getScriptFont(le_int32 scriptCode
, LEErrorCode
&status
)
195 if (LE_FAILURE(status
)) {
199 if (scriptCode
<= -1 || scriptCode
>= scriptCodeCount
) {
200 status
= LE_ILLEGAL_ARGUMENT_ERROR
;
205 le_int32 fontIndex
= fFontIndices
[scriptCode
];
208 sprintf(errorMessage
, "No font was set for script %s", uscript_getName((UScriptCode
) scriptCode
));
209 fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error");
210 status
= LE_FONT_FILE_NOT_FOUND_ERROR
;
214 if (fFontInstances
[fontIndex
] == NULL
) {
215 fFontInstances
[fontIndex
] = openFont(fFontNames
[fontIndex
], fPointSize
, status
);
217 if (LE_FAILURE(status
)) {
218 sprintf(errorMessage
, "Could not open font file %s", fFontNames
[fontIndex
]);
219 fGUISupport
->postErrorMessage(errorMessage
, "Font Map Error");
224 return fFontInstances
[fontIndex
];
227 le_int32
FontMap::getAscent() const
230 ((FontMap
*) this)->getMaxMetrics();
236 le_int32
FontMap::getDescent() const
239 ((FontMap
*) this)->getMaxMetrics();
245 le_int32
FontMap::getLeading() const
248 ((FontMap
*) this)->getMaxMetrics();
254 void FontMap::getMaxMetrics()
256 for (le_int32 i
= 0; i
< fFontCount
; i
+= 1) {
257 LEErrorCode status
= LE_NO_ERROR
;
258 le_int32 ascent
, descent
, leading
;
260 if (fFontInstances
[i
] == NULL
) {
261 fFontInstances
[i
] = openFont(fFontNames
[i
], fPointSize
, status
);
263 if (LE_FAILURE(status
)) {
268 ascent
= fFontInstances
[i
]->getAscent();
269 descent
= fFontInstances
[i
]->getDescent();
270 leading
= fFontInstances
[i
]->getLeading();
272 if (ascent
> fAscent
) {
276 if (descent
> fDescent
) {
280 if (leading
> fLeading
) {