Imported from antiword-0.34.tar.gz.
[antiword.git] / fonts_u.c
blob51947f0474d2f26c64909030d38c67181657872d
1 /*
2 * fonts_u.c
3 * Copyright (C) 1999-2002 A.J. van Os; Released under 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;
31 const char *szGlobalFile;
32 char szEnvironmentFile[PATH_MAX+1];
33 char szLocalFile[PATH_MAX+1];
35 /* Try the environment version of the fontnames file */
36 szAntiword = szGetAntiwordDirectory();
37 if (szAntiword != NULL && szAntiword[0] != '\0') {
38 if (strlen(szAntiword) +
39 sizeof(FILE_SEPARATOR FONTNAMES_FILE) >=
40 sizeof(szEnvironmentFile)) {
41 werr(0,
42 "The name of your ANTIWORDHOME directory is too long");
43 return NULL;
45 sprintf(szEnvironmentFile, "%s%s",
46 szAntiword,
47 FILE_SEPARATOR FONTNAMES_FILE);
48 DBG_MSG(szEnvironmentFile);
50 pFile = fopen(szLocalFile, "r");
51 if (pFile != NULL) {
52 return pFile;
56 /* Try the local version of the fontnames file */
57 szHome = szGetHomeDirectory();
58 if (strlen(szHome) +
59 sizeof(FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE) >=
60 sizeof(szLocalFile)) {
61 werr(0, "The name of your HOME directory is too long");
62 return NULL;
65 sprintf(szLocalFile, "%s%s",
66 szHome,
67 FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE);
68 DBG_MSG(szLocalFile);
70 pFile = fopen(szLocalFile, "r");
71 if (pFile != NULL) {
72 return pFile;
75 /* Try the global version of the fontnames file */
76 szGlobalFile = GLOBAL_ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE;
77 DBG_MSG(szGlobalFile);
79 pFile = fopen(szGlobalFile, "r");
80 if (pFile != NULL) {
81 return pFile;
84 werr(0, "I can not open your fontnames file.\n"
85 "Neither '%s' nor\n"
86 "'%s' can be opened for reading.",
87 szLocalFile, szGlobalFile);
88 return NULL;
89 } /* end of pOpenFontTableFile */
92 * vCloseFont - close the current font, if any
94 void
95 vCloseFont(void)
97 NO_DBG_MSG("vCloseFont");
98 /* For safety: to be overwritten at the next call of tOpenfont() */
99 bUsePlainText = TRUE;
100 eEncoding = encoding_neutral;
101 } /* end of vCloseFont */
104 * tOpenFont - make the specified font the current font
106 * Returns the font reference number
108 draw_fontref
109 tOpenFont(UCHAR ucWordFontNumber, USHORT usFontStyle, USHORT usWordFontSize)
111 options_type tOptions;
112 const char *szOurFontname;
113 int iIndex, iFontnumber;
115 NO_DBG_MSG("tOpenFont");
116 NO_DBG_DEC(ucWordFontNumber);
117 NO_DBG_HEX(usFontStyle);
118 NO_DBG_DEC(usWordFontSize);
120 /* Keep the relevant bits */
121 usFontStyle &= FONT_BOLD|FONT_ITALIC;
122 NO_DBG_HEX(usFontStyle);
124 vGetOptions(&tOptions);
125 bUsePlainText = tOptions.eConversionType != conversion_draw &&
126 tOptions.eConversionType != conversion_ps;
127 eEncoding = tOptions.eEncoding;
129 if (bUsePlainText) {
130 /* Plain text, no fonts */
131 return (draw_fontref)0;
134 iFontnumber = iGetFontByNumber(ucWordFontNumber, usFontStyle);
135 szOurFontname = szGetOurFontname(iFontnumber);
136 if (szOurFontname == NULL || szOurFontname[0] == '\0') {
137 DBG_DEC(iFontnumber);
138 return (draw_fontref)0;
140 NO_DBG_MSG(szOurFontname);
142 for (iIndex = 0; iIndex < (int)elementsof(szFontnames); iIndex++) {
143 if (STREQ(szFontnames[iIndex], szOurFontname)) {
144 NO_DBG_DEC(iIndex);
145 return (draw_fontref)iIndex;
148 return (draw_fontref)0;
149 } /* end of tOpenFont */
152 * tOpenTableFont - make the table font the current font
154 * Returns the font reference number
156 draw_fontref
157 tOpenTableFont(USHORT usWordFontSize)
159 options_type tOptions;
160 int iWordFontnumber;
162 NO_DBG_MSG("tOpenTableFont");
164 vGetOptions(&tOptions);
165 bUsePlainText = tOptions.eConversionType != conversion_draw &&
166 tOptions.eConversionType != conversion_ps;
167 eEncoding = tOptions.eEncoding;
169 if (bUsePlainText) {
170 /* Plain text, no fonts */
171 return (draw_fontref)0;
174 iWordFontnumber = iFontname2Fontnumber(TABLE_FONT, FONT_REGULAR);
175 if (iWordFontnumber < 0 || iWordFontnumber > (int)UCHAR_MAX) {
176 DBG_DEC(iWordFontnumber);
177 return (draw_fontref)0;
180 return tOpenFont((UCHAR)iWordFontnumber, FONT_REGULAR, usWordFontSize);
181 } /* end of tOpenTableFont */
184 * szGetFontname - get the fontname
186 const char *
187 szGetFontname(draw_fontref tFontRef)
189 fail((size_t)(UCHAR)tFontRef >= elementsof(szFontnames));
190 return szFontnames[(int)(UCHAR)tFontRef];
191 } /* end of szGetFontname */
194 * lComputeStringWidth - compute the string width
196 * Note: the fontsize is specified in half-points!
197 * the stringlength is specified in bytes, not characters!
199 * Returns the string width in millipoints
201 long
202 lComputeStringWidth(const char *szString, size_t tStringLength,
203 draw_fontref tFontRef, USHORT usFontSize)
205 USHORT *ausCharWidths;
206 UCHAR *pucChar;
207 long lRelWidth;
208 size_t tIndex;
209 int iFontRef;
211 fail(szString == NULL);
212 fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
214 if (szString[0] == '\0' || tStringLength == 0) {
215 /* Empty string */
216 return 0;
219 if (eEncoding == encoding_utf8) {
220 fail(!bUsePlainText);
221 return lChar2MilliPoints(
222 utf8_strwidth(szString, tStringLength));
225 if (bUsePlainText) {
226 /* No current font, use "systemfont" */
227 return lChar2MilliPoints(tStringLength);
230 DBG_DEC_C(eEncoding != encoding_iso_8859_1 &&
231 eEncoding != encoding_iso_8859_2, eEncoding);
232 fail(eEncoding != encoding_iso_8859_1 &&
233 eEncoding != encoding_iso_8859_2);
235 /* Compute the relative string width */
236 iFontRef = (int)(UCHAR)tFontRef;
237 if (eEncoding == encoding_iso_8859_2) {
238 ausCharWidths = ausCharacterWidths2[iFontRef];
239 } else {
240 ausCharWidths = ausCharacterWidths1[iFontRef];
242 lRelWidth = 0;
243 for (tIndex = 0, pucChar = (UCHAR *)szString;
244 tIndex < tStringLength;
245 tIndex++, pucChar++) {
246 lRelWidth += (long)ausCharWidths[(int)*pucChar];
249 /* Compute the absolute string width */
250 return (lRelWidth * usFontSize + 1) / 2;
251 } /* end of lComputeStringWidth */
254 * tCountColumns - count the number of columns in a string
256 * Note: the length is specified in bytes!
257 * A UTF-8 a character can be 0, 1 or 2 columns wide.
259 * Returns the number of columns
261 size_t
262 tCountColumns(const char *szString, size_t tLength)
264 fail(szString == NULL);
266 if (eEncoding != encoding_utf8) {
267 /* One byte, one character, one column */
268 return tLength;
270 return (size_t)utf8_strwidth(szString, tLength);
271 } /* end of tCountColumns */
274 * tGetCharacterLength - the length of the specified character in bytes
276 * Returns the length in bytes
278 size_t
279 tGetCharacterLength(const char *szString)
281 fail(szString == NULL);
283 if (eEncoding != encoding_utf8) {
284 return 1;
286 return (size_t)utf8_chrlength(szString);
287 } /* end of tGetCharacterLength */