NetSurf
font_haru.c
Go to the documentation of this file.
1/*
2 * Copyright 2008 Adam Blokus <adamblokus@gmail.com>
3 * Copyright 2009 John Tytgat <joty@netsurf-browser.org>
4 *
5 * This file is part of NetSurf, http://www.netsurf-browser.org/
6 *
7 * NetSurf is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * NetSurf is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /** \file
21 * Font handling in Haru pdf documents (implementation).
22 *
23 * The functions were written to implement the same interface as the Pango ones
24 * so that the usage of the latter wouldn't have to be modified.
25 */
26
27#include "utils/config.h"
28#ifdef WITH_PDF_EXPORT
29
30/*#define FONT_HARU_DEBUG */
31
32#include <assert.h>
33#include <float.h>
34#include <math.h>
35#include <string.h>
36
37#include <hpdf.h>
38
39#include "utils/nsoption.h"
40#include "desktop/save_pdf/font_haru.h"
41#include "desktop/font.h"
42#include "utils/log.h"
43
44
45static bool haru_nsfont_init(HPDF_Doc *pdf, HPDF_Page *page,
46 const char *string, char **string_nt, int length);
47
48static bool haru_nsfont_width(const plot_font_style_t *fstyle,
49 const char *string, size_t length,
50 int *width);
51
52static bool haru_nsfont_position_in_string(const plot_font_style_t *fstyle,
53 const char *string, size_t length,
54 int x, size_t *char_offset, int *actual_x);
55
56static bool haru_nsfont_split(const plot_font_style_t *fstyle,
57 const char *string, size_t length,
58 int x, size_t *char_offset, int *actual_x);
59
60static float pdf_text_scale = DEFAULT_EXPORT_SCALE;
61
62const struct font_functions haru_nsfont = {
63 haru_nsfont_width,
64 haru_nsfont_position_in_string,
65 haru_nsfont_split
66};
67
68/**
69 * Haru error handler
70 * for debugging purposes - it immediately exits the program on the first error,
71 * as it would otherwise flood the user with all resulting complications,
72 * covering the most important error source.
73 */
74static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no,
75 void *user_data)
76{
77 NSLOG(netsurf, INFO,
78 "ERROR: in font_haru \n\terror_no=%x\n\tdetail_no=%d\n",
79 (HPDF_UINT)error_no,
80 (HPDF_UINT)detail_no);
81#ifdef FONT_HARU_DEBUG
82 exit(1);
83#endif
84}
85
86static bool haru_nsfont_init(HPDF_Doc *pdf, HPDF_Page *page,
87 const char *string, char **string_nt, int length)
88{
89
90 *pdf = HPDF_New(error_handler, NULL);
91
92 if (*pdf == NULL)
93 return false;
94
95 *page = HPDF_AddPage(*pdf);
96
97 if (*page == NULL) {
98 HPDF_Free(*pdf);
99 return false;
100 }
101
102 *string_nt = malloc((length + 1) * sizeof(char));
103 if (*string_nt == NULL) {
104 HPDF_Free(*pdf);
105 return false;
106 }
107
108 memcpy(*string_nt, string, length);
109 (*string_nt)[length] = '\0';
110 return true;
111}
112
113/**
114 * Measure the width of a string.
115 *
116 * \param fstyle style for this text
117 * \param string string to measure (no UTF-8 currently)
118 * \param length length of string
119 * \param width updated to width of string[0..length]
120 * \return true on success, false on error and error reported
121 */
122bool haru_nsfont_width(const plot_font_style_t *fstyle,
123 const char *string, size_t length,
124 int *width)
125{
126 HPDF_Doc pdf;
127 HPDF_Page page;
128 char *string_nt;
129 HPDF_REAL width_real;
130
131 *width = 0;
132
133 if (length == 0)
134 return true;
135
136 if (!haru_nsfont_init(&pdf, &page, string, &string_nt, length))
137 return false;
138
139 if (!haru_nsfont_apply_style(fstyle, pdf, page, NULL, NULL)) {
140 free(string_nt);
141 HPDF_Free(pdf);
142 return false;
143 }
144
145 width_real = HPDF_Page_TextWidth(page, string_nt);
146 *width = width_real;
147
148#ifdef FONT_HARU_DEBUG
149 NSLOG(netsurf, INFO,
150 "Measuring string: %s ; Calculated width: %f %i", string_nt,
151 width_real, *width);
152#endif
153 free(string_nt);
154 HPDF_Free(pdf);
155
156 return true;
157}
158
159
160/**
161 * Find the position in a string where an x coordinate falls.
162 *
163 * \param fstyle style for this text
164 * \param string string to measure (no UTF-8 currently)
165 * \param length length of string
166 * \param x x coordinate to search for
167 * \param char_offset updated to offset in string of actual_x, [0..length]
168 * \param actual_x updated to x coordinate of character closest to x
169 * \return true on success, false on error and error reported
170 */
171
172bool haru_nsfont_position_in_string(const plot_font_style_t *fstyle,
173 const char *string, size_t length,
174 int x, size_t *char_offset, int *actual_x)
175{
176 HPDF_Doc pdf;
177 HPDF_Page page;
178 char *string_nt;
179 HPDF_UINT offset;
180 HPDF_REAL real_width;
181
182 if (!haru_nsfont_init(&pdf, &page, string, &string_nt, length))
183 return false;
184
185 if (HPDF_Page_SetWidth(page, x) != HPDF_OK
186 || !haru_nsfont_apply_style(fstyle, pdf, page, NULL, NULL)) {
187 free(string_nt);
188 HPDF_Free(pdf);
189 return false;
190 }
191
192
193 offset = HPDF_Page_MeasureText(page, string_nt, x,
194 HPDF_FALSE, &real_width);
195
196
197 if (real_width < x)
198 *char_offset = offset;
199 else {
200 assert(fabs(real_width - x) < FLT_EPSILON);
201 assert(offset > 0);
202 *char_offset = offset - 1;
203 }
204
205 /*TODO: this is only the right edge of the character*/
206 *actual_x = real_width;
207
208#ifdef FONT_HARU_DEBUG
209 NSLOG(netsurf, INFO,
210 "Position in string: %s at x: %i; Calculated position: %i",
211 string_nt,
212 x,
213 *char_offset);
214#endif
215 free(string_nt);
216 HPDF_Free(pdf);
217
218 return true;
219}
220
221/**
222 * Find where to split a string to make it fit a width.
223 *
224 * \param fstyle style for this text
225 * \param string string to measure (no UTF-8 currently)
226 * \param length length of string
227 * \param x width available
228 * \param char_offset updated to offset in string of actual_x, [0..length]
229 * \param actual_x updated to x coordinate of character closest to x
230 * \return true on success, false on error and error reported
231 */
232
233bool haru_nsfont_split(const plot_font_style_t *fstyle,
234 const char *string, size_t length,
235 int x, size_t *char_offset, int *actual_x)
236{
237 HPDF_Doc pdf;
238 HPDF_Page page;
239 char *string_nt;
240 HPDF_REAL real_width;
241 HPDF_UINT offset;
242
243
244 if (!haru_nsfont_init(&pdf, &page, string, &string_nt, length))
245 return false;
246
247 if (HPDF_Page_SetWidth(page, x) != HPDF_OK
248 || !haru_nsfont_apply_style(fstyle, pdf, page, NULL, NULL)) {
249 free(string_nt);
250 HPDF_Free(pdf);
251 return false;
252 }
253
254 offset = HPDF_Page_MeasureText(page, string_nt, x,
255 HPDF_TRUE, &real_width);
256
257#ifdef FONT_HARU_DEBUG
258 NSLOG(netsurf, INFO,
259 "Splitting string: %s for width: %i ; Calculated position: %i Calculated real_width: %f",
260 string_nt,
261 x,
262 *char_offset,
263 real_width);
264#endif
265 *char_offset = offset - 1;
266
267 /*TODO: this is only the right edge of the character*/
268 *actual_x = real_width;
269
270 free(string_nt);
271 HPDF_Free(pdf);
272
273 return true;
274}
275
276/**
277 * Apply font style to a Haru HPDF_Page
278 *
279 * \param fstyle plot style for this page
280 * \param doc document owning the page
281 * \param page the page to apply the style to
282 * \param font if this is non NULL it is updated to the font based
283 * on given style
284 * \param font_size if this is non NULL it is updated to the font size
285 * based on given style
286 * \return true on success, false on error and error reported
287 *
288 * When both font and font_size are NULL, the HPDF_Page is updated for given
289 * style, otherwise it is left to the called to do this.
290 */
292 HPDF_Doc doc, HPDF_Page page,
293 HPDF_Font *font, HPDF_REAL *font_size)
294{
295 HPDF_Font pdf_font;
296 HPDF_REAL size;
297 char font_name[50];
298 bool roman = false;
299 bool bold = false;
300 bool styled = false;
301
302 /*TODO: style handling, we are mapping the
303 styles on the basic 14 fonts only
304 */
305 switch (fstyle->family) {
307 strcpy(font_name, "Times");
308 roman = true;
309 break;
311 strcpy(font_name, "Courier");
312 break;
314 strcpy(font_name, "Helvetica");
315 break;
318 default:
319 strcpy(font_name, "Times");
320 roman=true;
321 break;
322 }
323
324 if (fstyle->weight == 700) {
325 strcat(font_name, "-Bold");
326 bold = true;
327 }
328
329 if ((fstyle->flags & FONTF_ITALIC) || (fstyle->flags & FONTF_OBLIQUE)) {
330 if (!bold)
331 strcat(font_name,"-");
332 if (roman)
333 strcat(font_name,"Italic");
334 else
335 strcat(font_name,"Oblique");
336
337 styled = true;
338 }
339
340 if (roman && !styled && !bold)
341 strcat(font_name, "-Roman");
342
343#ifdef FONT_HARU_DEBUG
344 NSLOG(netsurf, INFO, "Setting font: %s", font_name);
345#endif
346
347 size = fstyle->size;
348
349 if (font != NULL)
350 size *= pdf_text_scale;
351
352 if (size <= 0)
353 return true;
354
355 size /= PLOT_STYLE_SCALE;
356
357 if (size > HPDF_MAX_FONTSIZE)
358 size = HPDF_MAX_FONTSIZE;
359
360 if (font_size)
361 *font_size = size;
362
363 pdf_font = HPDF_GetFont(doc, font_name, "StandardEncoding");
364 if (pdf_font == NULL)
365 return false;
366 if (font != NULL)
367 *font = pdf_font;
368
369 if (font == NULL || font_size == NULL)
370 HPDF_Page_SetFontAndSize(page, pdf_font, size);
371
372 return true;
373}
374
375/**
376 * Sync the text scale with the scale for the whole content
377 */
378void haru_nsfont_set_scale(float s)
379{
380 pdf_text_scale = s;
381}
382
383#endif /* WITH_PDF_EXPORT */
bool haru_nsfont_apply_style(const plot_font_style_t *fstyle, HPDF_Doc doc, HPDF_Page page, HPDF_Font *font, HPDF_REAL *font_size)
const struct font_functions haru_nsfont
void haru_nsfont_set_scale(float s)
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
@ FONTF_ITALIC
Definition: plot_style.h:103
@ FONTF_OBLIQUE
Definition: plot_style.h:104
@ PLOT_FONT_FAMILY_CURSIVE
Definition: plot_style.h:92
@ PLOT_FONT_FAMILY_SANS_SERIF
Definition: plot_style.h:89
@ PLOT_FONT_FAMILY_FANTASY
Definition: plot_style.h:93
@ PLOT_FONT_FAMILY_MONOSPACE
Definition: plot_style.h:91
@ PLOT_FONT_FAMILY_SERIF
Definition: plot_style.h:90
#define PLOT_STYLE_SCALE
Scaling factor for plot styles.
Definition: plot_style.h:45
int width
Definition: gui.c:160
Interface to utility string handling.
Font style for plotting.
Definition: plot_style.h:111
plot_font_generic_family_t family
Generic family to plot with.
Definition: plot_style.h:118
plot_font_flags_t flags
Font flags.
Definition: plot_style.h:121
plot_style_fixed size
Font size, in pt.
Definition: plot_style.h:119
int weight
Font weight: value in range [100,900] as per CSS.
Definition: plot_style.h:120
Option reading and saving interface.
#define DEFAULT_EXPORT_SCALE
Definition: nsoption.h:94