Imported from antiword-0.37.tar.gz.
[antiword.git] / fonts_u.c
bloba99f7d2e63a09562d840431648de77bc2aadb038
1 /*
2 * fonts_u.c
3 * Copyright (C) 1999-2004 A.J. van Os; Released under GNU GPL
5 * Description:
6 * Functions to deal with fonts (Unix version)
7 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "antiword.h"
13 #include "fontinfo.h"
15 /* Don't use fonts, just plain text */
16 static BOOL bUsePlainText = TRUE;
17 /* Which character set should be used */
18 static encoding_type eEncoding = encoding_neutral;
22 * pOpenFontTableFile - open the Font translation file
24 * Returns the file pointer or NULL
26 FILE *
27 pOpenFontTableFile(void)
29 FILE *pFile;
30 const char *szHome, *szAntiword, *szGlobalFile;
31 char szEnvironmentFile[PATH_MAX+1];
32 char szLocalFile[PATH_MAX+1];
34 szEnvironmentFile[0] = '\0';
35 szLocalFile[0] = '\0';
37 /* Try the environment version of the fontnames file */
38 szAntiword = szGetAntiwordDirectory();
39 if (szAntiword != NULL && szAntiword[0] != '\0') {
40 if (strlen(szAntiword) +
41 sizeof(FILE_SEPARATOR FONTNAMES_FILE) >=
42 sizeof(szEnvironmentFile)) {
43 werr(0,
44 "The name of your ANTIWORDHOME directory is too long");
45 return NULL;
47 sprintf(szEnvironmentFile, "%s%s",
48 szAntiword,
49 FILE_SEPARATOR FONTNAMES_FILE);
50 DBG_MSG(szEnvironmentFile);
52 pFile = fopen(szEnvironmentFile, "r");
53 if (pFile != NULL) {
54 return pFile;
58 /* Try the local version of the fontnames file */
59 szHome = szGetHomeDirectory();
60 if (strlen(szHome) +
61 sizeof(FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE) >=
62 sizeof(szLocalFile)) {
63 werr(0, "The name of your HOME directory is too long");
64 return NULL;
67 sprintf(szLocalFile, "%s%s",
68 szHome,
69 FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE);
70 DBG_MSG(szLocalFile);
72 pFile = fopen(szLocalFile, "r");
73 if (pFile != NULL) {
74 return pFile;
77 /* Try the global version of the fontnames file */
78 szGlobalFile = GLOBAL_ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE;
79 DBG_MSG(szGlobalFile);
81 pFile = fopen(szGlobalFile, "r");
82 if (pFile != NULL) {
83 return pFile;
86 if (szEnvironmentFile[0] != '\0') {
87 werr(0, "I can not open your fontnames file.\n"
88 "Neither '%s' nor\n"
89 "'%s' nor\n"
90 "'%s' can be opened for reading.",
91 szEnvironmentFile, szLocalFile, szGlobalFile);
92 } else {
93 werr(0, "I can not open your fontnames file.\n"
94 "Neither '%s' nor\n"
95 "'%s' can be opened for reading.",
96 szLocalFile, szGlobalFile);
98 return NULL;
99 } /* end of pOpenFontTableFile */
102 * vCloseFont - close the current font, if any
104 void
105 vCloseFont(void)
107 NO_DBG_MSG("vCloseFont");
108 /* For safety: to be overwritten at the next call of tOpenfont() */
109 eEncoding = encoding_neutral;
110 bUsePlainText = TRUE;
111 } /* end of vCloseFont */
114 * tOpenFont - make the specified font the current font
116 * Returns the font reference number
118 drawfile_fontref
119 tOpenFont(UCHAR ucWordFontNumber, USHORT usFontStyle, USHORT usWordFontSize)
121 options_type tOptions;
122 const char *szOurFontname;
123 size_t tIndex;
124 int iFontnumber;
126 NO_DBG_MSG("tOpenFont");
127 NO_DBG_DEC(ucWordFontNumber);
128 NO_DBG_HEX(usFontStyle);
129 NO_DBG_DEC(usWordFontSize);
131 /* Keep the relevant bits */
132 usFontStyle &= FONT_BOLD|FONT_ITALIC;
133 NO_DBG_HEX(usFontStyle);
135 vGetOptions(&tOptions);
136 eEncoding = tOptions.eEncoding;
137 bUsePlainText = tOptions.eConversionType != conversion_draw &&
138 tOptions.eConversionType != conversion_ps &&
139 tOptions.eConversionType != conversion_pdf;
141 if (bUsePlainText) {
142 /* Plain text, no fonts */
143 return (drawfile_fontref)0;
146 iFontnumber = iGetFontByNumber(ucWordFontNumber, usFontStyle);
147 szOurFontname = szGetOurFontname(iFontnumber);
148 if (szOurFontname == NULL || szOurFontname[0] == '\0') {
149 DBG_DEC(iFontnumber);
150 return (drawfile_fontref)0;
152 NO_DBG_MSG(szOurFontname);
154 for (tIndex = 0; tIndex < elementsof(szFontnames); tIndex++) {
155 if (STREQ(szFontnames[tIndex], szOurFontname)) {
156 NO_DBG_DEC(tIndex);
157 return (drawfile_fontref)tIndex;
160 return (drawfile_fontref)0;
161 } /* end of tOpenFont */
164 * tOpenTableFont - make the table font the current font
166 * Returns the font reference number
168 drawfile_fontref
169 tOpenTableFont(USHORT usWordFontSize)
171 options_type tOptions;
172 int iWordFontnumber;
174 NO_DBG_MSG("tOpenTableFont");
176 vGetOptions(&tOptions);
177 eEncoding = tOptions.eEncoding;
178 bUsePlainText = tOptions.eConversionType != conversion_draw &&
179 tOptions.eConversionType != conversion_ps &&
180 tOptions.eConversionType != conversion_pdf;
182 if (bUsePlainText) {
183 /* Plain text, no fonts */
184 return (drawfile_fontref)0;
187 iWordFontnumber = iFontname2Fontnumber(TABLE_FONT, FONT_REGULAR);
188 if (iWordFontnumber < 0 || iWordFontnumber > (int)UCHAR_MAX) {
189 DBG_DEC(iWordFontnumber);
190 return (drawfile_fontref)0;
193 return tOpenFont((UCHAR)iWordFontnumber, FONT_REGULAR, usWordFontSize);
194 } /* end of tOpenTableFont */
197 * szGetFontname - get the fontname
199 const char *
200 szGetFontname(drawfile_fontref tFontRef)
202 fail((size_t)(UCHAR)tFontRef >= elementsof(szFontnames));
203 return szFontnames[(int)(UCHAR)tFontRef];
204 } /* end of szGetFontname */
207 * lComputeStringWidth - compute the string width
209 * Note: the fontsize is specified in half-points!
210 * the stringlength is specified in bytes, not characters!
212 * Returns the string width in millipoints
214 long
215 lComputeStringWidth(const char *szString, size_t tStringLength,
216 drawfile_fontref tFontRef, USHORT usFontSize)
218 USHORT *ausCharWidths;
219 UCHAR *pucChar;
220 long lRelWidth;
221 size_t tIndex;
222 int iFontRef;
224 fail(szString == NULL);
225 fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
227 if (szString[0] == '\0' || tStringLength == 0) {
228 /* Empty string */
229 return 0;
232 if (eEncoding == encoding_utf_8) {
233 fail(!bUsePlainText);
234 return lChar2MilliPoints(
235 utf8_strwidth(szString, tStringLength));
238 if (bUsePlainText) {
239 /* No current font, use "systemfont" */
240 return lChar2MilliPoints(tStringLength);
243 if (eEncoding == encoding_cyrillic) {
244 /* FIXME: until the character tables are available */
245 return (tStringLength * 600L * (long)usFontSize + 1) / 2;
248 DBG_DEC_C(eEncoding != encoding_latin_1 &&
249 eEncoding != encoding_latin_2, eEncoding);
250 fail(eEncoding != encoding_latin_1 &&
251 eEncoding != encoding_latin_2);
253 /* Compute the relative string width */
254 iFontRef = (int)(UCHAR)tFontRef;
255 if (eEncoding == encoding_latin_2) {
256 ausCharWidths = ausCharacterWidths2[iFontRef];
257 } else {
258 ausCharWidths = ausCharacterWidths1[iFontRef];
260 lRelWidth = 0;
261 for (tIndex = 0, pucChar = (UCHAR *)szString;
262 tIndex < tStringLength;
263 tIndex++, pucChar++) {
264 lRelWidth += (long)ausCharWidths[(int)*pucChar];
267 /* Compute the absolute string width */
268 return (lRelWidth * (long)usFontSize + 1) / 2;
269 } /* end of lComputeStringWidth */
272 * tCountColumns - count the number of columns in a string
274 * Note: the length is specified in bytes!
275 * A UTF-8 a character can be 0, 1 or 2 columns wide.
277 * Returns the number of columns
279 size_t
280 tCountColumns(const char *szString, size_t tLength)
282 fail(szString == NULL);
284 if (eEncoding != encoding_utf_8) {
285 /* One byte, one character, one column */
286 return tLength;
288 return (size_t)utf8_strwidth(szString, tLength);
289 } /* end of tCountColumns */
292 * tGetCharacterLength - the length of the specified character in bytes
294 * Returns the length in bytes
296 size_t
297 tGetCharacterLength(const char *szString)
299 fail(szString == NULL);
301 if (eEncoding != encoding_utf_8) {
302 return 1;
304 return (size_t)utf8_chrlength(szString);
305 } /* end of tGetCharacterLength */