NetSurf
font_bullet.c
Go to the documentation of this file.
1/*
2 * Copyright 2008 - 2019 Chris Young <chris@unsatisfactorysoftware.co.uk>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * Amiga font handling implementation
22 */
23
24#include "amiga/os3support.h"
25
26#include <stdlib.h>
27
28#ifndef __amigaos4__
29#include <proto/bullet.h>
30#endif
31#include <proto/diskfont.h>
32#include <proto/exec.h>
33#include <proto/graphics.h>
34#include <proto/utility.h>
35
36#include <diskfont/diskfonttag.h>
37#include <diskfont/oterrors.h>
38
39#include "utils/log.h"
40#include "utils/nsoption.h"
41#include "utils/utf8.h"
42#include "utils/utils.h"
43
44#include "amiga/memory.h"
45#include "amiga/misc.h"
46#include "amiga/font.h"
47#include "amiga/font_bullet.h"
48#include "amiga/font_cache.h"
49#include "amiga/font_scan.h"
50
51
52#define NSA_UNICODE_FONT PLOT_FONT_FAMILY_COUNT
53
54#define NSA_NORMAL 0
55#define NSA_ITALIC 1
56#define NSA_BOLD 2
57#define NSA_BOLDITALIC 3
58#define NSA_OBLIQUE 4
59#define NSA_BOLDOBLIQUE 6
60
61#define NSA_VALUE_BOLDX (1 << 12)
62#define NSA_VALUE_BOLDY 0
63#define NSA_VALUE_SHEARSIN (1 << 14)
64#define NSA_VALUE_SHEARCOS (1 << 16)
65
66#define NSA_FONT_EMWIDTH(s) (s / PLOT_STYLE_SCALE) * (ami_font_dpi_get_xdpi() / 72.0)
67
68const uint16 sc_table[] = {
69 0x0061, 0x1D00, /* a */
70 0x0062, 0x0299, /* b */
71 0x0063, 0x1D04, /* c */
72 0x0064, 0x1D05, /* d */
73 0x0065, 0x1D07, /* e */
74 0x0066, 0xA730, /* f */
75 0x0067, 0x0262, /* g */
76 0x0068, 0x029C, /* h */
77 0x0069, 0x026A, /* i */
78 0x006A, 0x1D0A, /* j */
79 0x006B, 0x1D0B, /* k */
80 0x006C, 0x029F, /* l */
81 0x006D, 0x1D0D, /* m */
82 0x006E, 0x0274, /* n */
83 0x006F, 0x1D0F, /* o */
84 0x0070, 0x1D18, /* p */
85 0x0071, 0xA7AF, /* q */
86 0x0072, 0x0280, /* r */
87 0x0073, 0xA731, /* s */
88 0x0074, 0x1D1B, /* t */
89 0x0075, 0x1D1C, /* u */
90 0x0076, 0x1D20, /* v */
91 0x0077, 0x1D21, /* w */
92 0x0078, 0xA7EF, /* x (proposed) (Adobe codepoint 0xF778) */
93 0x0079, 0x028F, /* y */
94 0x007A, 0x1D22, /* z */
95
96 0x00C6, 0x1D01, /* ae */
97 0x0153, 0x0276, /* oe */
98
99#if 0
100/* TODO: fill in the non-small caps character ids for these */
101 0x0000, 0x1D03, /* barred b */
102 0x0000, 0x0281, /* inverted r */
103 0x0000, 0x1D19, /* reversed r */
104 0x0000, 0x1D1A, /* turned r */
105 0x0000, 0x029B, /* g with hook */
106 0x0000, 0x1D06, /* eth Ð */
107 0x0000, 0x1D0C, /* l with stroke */
108 0x0000, 0xA7FA, /* turned m */
109 0x0000, 0x1D0E, /* reversed n */
110 0x0000, 0x1D10, /* open o */
111 0x0000, 0x1D15, /* ou */
112 0x0000, 0x1D23, /* ezh */
113 0x0000, 0x1D26, /* gamma */
114 0x0000, 0x1D27, /* lamda */
115 0x0000, 0x1D28, /* pi */
116 0x0000, 0x1D29, /* rho */
117 0x0000, 0x1D2A, /* psi */
118 0x0000, 0x1D2B, /* el */
119 0x0000, 0xA776, /* rum */
120
121 0x0000, 0x1DDB, /* combining g */
122 0x0000, 0x1DDE, /* combining l */
123 0x0000, 0x1DDF, /* combining m */
124 0x0000, 0x1DE1, /* combining n */
125 0x0000, 0x1DE2, /* combining r */
126
127 0x0000, 0x1DA6, /* modifier i */
128 0x0000, 0x1DA7, /* modifier i with stroke */
129 0x0000, 0x1DAB, /* modifier l */
130 0x0000, 0x1DB0, /* modifier n */
131 0x0000, 0x1DB8, /* modifier u */
132#endif
133 0, 0};
134
135static lwc_string *glypharray[0xffff + 1];
136
137static struct List ami_diskfontlib_list;
138
139static inline int32 ami_font_plot_glyph(struct OutlineFont *ofont, struct RastPort *rp,
140 uint16 *restrict char1, uint16 *restrict char2, uint32 x, uint32 y, uint32 emwidth, bool aa);
141static inline int32 ami_font_width_glyph(struct OutlineFont *ofont,
142 const uint16 *restrict char1, const uint16 *restrict char2, uint32 emwidth);
143static struct OutlineFont *ami_open_outline_font(const plot_font_style_t *fstyle,
144 const uint16 *codepoint);
145static inline ULONG ami_font_unicode_width(const char *string, ULONG length,
146 const plot_font_style_t *fstyle, ULONG x, ULONG y, bool aa);
147
148static inline int amiga_nsfont_utf16_char_length(const uint16 *char1)
149{
150 if (__builtin_expect(((*char1 < 0xD800) || (0xDBFF < *char1)), 1)) {
151 return 1;
152 } else {
153 return 2;
154 }
155}
156
157static inline uint32 amiga_nsfont_decode_surrogate(const uint16 *char1)
158{
159 if(__builtin_expect((amiga_nsfont_utf16_char_length(char1) == 2), 0)) {
160 return ((uint32)char1[0] << 10) + char1[1] - 0x35FDC00;
161 } else {
162 return (uint32)*char1;
163 }
164}
165
167 const char *string, size_t length,
168 int *width)
169{
170 *width = ami_font_unicode_width(string, length, fstyle, 0, 0, false);
171
172 if(*width <= 0) {
173 *width = length; /* fudge */
174 }
175
176 return NSERROR_OK;
177}
178
179/**
180 * Find the position in a string where an x coordinate falls.
181 *
182 * \param fstyle style for this text
183 * \param string UTF-8 string to measure
184 * \param length length of string
185 * \param x x coordinate to search for
186 * \param char_offset updated to offset in string of actual_x, [0..length]
187 * \param actual_x updated to x coordinate of character closest to x
188 * \return true on success, false on error and error reported
189 */
190
192 const char *string, size_t length,
193 int x, size_t *char_offset, int *actual_x)
194{
195 uint16 *utf16 = NULL, *outf16 = NULL;
196 uint16 *utf16next = NULL;
197 struct OutlineFont *ofont, *ufont = NULL;
198 int tx = 0;
199 uint32 utf8_pos = 0;
200 int utf16charlen;
201 ULONG emwidth = (ULONG)NSA_FONT_EMWIDTH(fstyle->size);
202 int32 tempx;
203
204 if(utf8_to_enc(string,"UTF-16",length,(char **)&utf16) != NSERROR_OK) return NSERROR_INVALID;
205 outf16 = utf16;
206 if(!(ofont = ami_open_outline_font(fstyle, 0))) return NSERROR_INVALID;
207
208 *char_offset = 0;
209 *actual_x = 0;
210
211 while (utf8_pos < length) {
212 utf16charlen = amiga_nsfont_utf16_char_length(utf16);
213 utf16next = &utf16[utf16charlen];
214
215 tempx = ami_font_width_glyph(ofont, utf16, utf16next, emwidth);
216
217 if (tempx == 0) {
218 if (ufont == NULL)
219 ufont = ami_open_outline_font(fstyle, utf16);
220
221 if (ufont)
222 tempx = ami_font_width_glyph(ufont, utf16,
223 utf16next, emwidth);
224 }
225
226 tx += tempx;
227 utf16 = utf16next;
228 utf8_pos = utf8_next(string, length, utf8_pos);
229
230 if(tx < x) {
231 *actual_x = tx;
232 *char_offset = utf8_pos;
233 } else {
234 if((x - *actual_x) > (tx - x)) {
235 *actual_x = tx;
236 *char_offset = utf8_pos;
237 }
238 free(outf16);
239 return NSERROR_OK;
240 }
241 }
242
243 *actual_x = tx;
244 *char_offset = length;
245
246 free(outf16);
247 return NSERROR_OK;
248}
249
250
251/**
252 * Find where to split a string to make it fit a width.
253 *
254 * \param fstyle style for this text
255 * \param string UTF-8 string to measure
256 * \param length length of string
257 * \param x width available
258 * \param char_offset updated to offset in string of actual_x, [1..length]
259 * \param actual_x updated to x coordinate of character closest to x
260 * \return true on success, false on error and error reported
261 *
262 * On exit, char_offset indicates first character after split point.
263 *
264 * Note: char_offset of 0 should never be returned.
265 *
266 * Returns:
267 * char_offset giving split point closest to x, where actual_x <= x
268 * else
269 * char_offset giving split point closest to x, where actual_x > x
270 *
271 * Returning char_offset == length means no split possible
272 */
273
275 const char *string, size_t length,
276 int x, size_t *char_offset, int *actual_x)
277{
278 uint16 *utf16_str = NULL;
279 const uint16 *utf16 = NULL;
280 const uint16 *utf16next = NULL;
281 struct OutlineFont *ofont, *ufont = NULL;
282 int tx = 0;
283 uint32 utf8_pos = 0;
284 int32 tempx = 0;
285 ULONG emwidth = (ULONG)NSA_FONT_EMWIDTH(fstyle->size);
286
287 /* Get utf16 conversion of string for glyph measuring routines */
288 if (utf8_to_enc(string, "UTF-16", length, (char **)&utf16_str) !=
290 return NSERROR_INVALID;
291
292 utf16 = utf16_str;
293 if (!(ofont = ami_open_outline_font(fstyle, 0)))
294 return NSERROR_INVALID;
295
296 *char_offset = 0;
297 *actual_x = 0;
298
299 if (*utf16 == 0xFEFF) utf16++;
300
301 while (utf8_pos < length) {
302 if ((*utf16 < 0xD800) || (0xDBFF < *utf16))
303 utf16next = utf16 + 1;
304 else
305 utf16next = utf16 + 2;
306
307 tempx = ami_font_width_glyph(ofont, utf16, utf16next, emwidth);
308
309 if (tempx == 0) {
310 if (ufont == NULL)
311 ufont = ami_open_outline_font(fstyle, utf16);
312
313 if (ufont)
314 tempx = ami_font_width_glyph(ufont, utf16,
315 utf16next, emwidth);
316 }
317
318 /* Check whether we have a space */
319 if (*(string + utf8_pos) == ' ') {
320 /* Got a space */
321 *actual_x = tx;
322 *char_offset = utf8_pos;
323 }
324
325 tx += tempx;
326 if ((x < tx) && (*char_offset != 0)) {
327 /* Reached available width, and a space was found;
328 * split there. */
329 free(utf16_str);
330 return NSERROR_OK;
331 }
332
333 utf16 = utf16next;
334 utf8_pos = utf8_next(string, length, utf8_pos);
335 }
336
337 free(utf16_str);
338
339 /* No spaces to split at, or everything fits */
340 assert(*char_offset == 0 || x >= tx);
341
342 *char_offset = length;
343 *actual_x = tx;
344 return NSERROR_OK;
345}
346
347/**
348 * Search for a font in the list and load from disk if not present
349 */
350static struct ami_font_cache_node *ami_font_open(const char *font, bool critical)
351{
352 if(font == NULL) {
353 NSLOG(netsurf, INFO, "Requested NULL font");
354 return NULL;
355 }
356
358 if(nodedata) return nodedata;
359
361
362 if(nodedata == NULL) {
363 amiga_warn_user("NoMemory", "");
364 return NULL;
365 }
366
368
369 if(!nodedata->font)
370 {
371 NSLOG(netsurf, INFO, "Requested font not found: %s", font);
372 if(critical == true) amiga_warn_user("CompError", font);
373 free(nodedata);
374 return NULL;
375 }
376
377 nodedata->bold = (char *)GetTagData(OT_BName, 0, nodedata->font->olf_OTagList);
378 if(nodedata->bold)
379 NSLOG(netsurf, INFO, "Bold font defined for %s is %s", font,
380 nodedata->bold);
381 else
382 NSLOG(netsurf, INFO,
383 "Warning: No designed bold font defined for %s", font);
384
385 nodedata->italic = (char *)GetTagData(OT_IName, 0, nodedata->font->olf_OTagList);
386 if(nodedata->italic)
387 NSLOG(netsurf, INFO, "Italic font defined for %s is %s",
388 font, nodedata->italic);
389 else
390 NSLOG(netsurf, INFO,
391 "Warning: No designed italic font defined for %s", font);
392
393 nodedata->bolditalic = (char *)GetTagData(OT_BIName, 0, nodedata->font->olf_OTagList);
394 if(nodedata->bolditalic)
395 NSLOG(netsurf, INFO, "Bold-italic font defined for %s is %s",
396 font, nodedata->bolditalic);
397 else
398 NSLOG(netsurf, INFO,
399 "Warning: No designed bold-italic font defined for %s",
400 font);
401
402 ami_font_cache_insert(nodedata, font);
403 return nodedata;
404}
405
406/**
407 * Open an outline font in the specified size and style
408 *
409 * \param fstyle font style structure
410 * \param codepoint open a default font instead of the one specified by fstyle
411 * \return outline font or NULL on error
412 */
414 const uint16 *codepoint)
415{
416 struct ami_font_cache_node *node;
417 struct ami_font_cache_node *designed_node = NULL;
418 struct OutlineFont *ofont;
419 char *fontname;
420 ULONG ysize;
421 int tstyle = 0;
423 ULONG emboldenx = 0;
424 ULONG emboldeny = 0;
425 ULONG shearsin = 0;
426 ULONG shearcos = (1 << 16);
427
428 if(codepoint) fontfamily = NSA_UNICODE_FONT;
429 else fontfamily = fstyle->family;
430
431 switch(fontfamily)
432 {
434 fontname = nsoption_charp(font_sans);
435 break;
437 fontname = nsoption_charp(font_serif);
438 break;
440 fontname = nsoption_charp(font_mono);
441 break;
443 fontname = nsoption_charp(font_cursive);
444 break;
446 fontname = nsoption_charp(font_fantasy);
447 break;
448 case NSA_UNICODE_FONT:
449 default:
450 if(__builtin_expect((amiga_nsfont_utf16_char_length(codepoint) == 2), 0)) {
451 /* Multi-byte character */
452 fontname = nsoption_charp(font_surrogate);
453 } else {
454 fontname = (char *)ami_font_scan_lookup(codepoint, glypharray);
455 }
456 if(fontname == NULL) return NULL;
457 break;
458 }
459
460 node = ami_font_open(fontname, true);
461 if(!node) return NULL;
462
463 if (fstyle->flags & FONTF_OBLIQUE)
464 tstyle = NSA_OBLIQUE;
465
466 if (fstyle->flags & FONTF_ITALIC)
467 tstyle = NSA_ITALIC;
468
469 if (fstyle->weight >= 700)
470 tstyle += NSA_BOLD;
471
472 switch(tstyle)
473 {
474 case NSA_ITALIC:
475 if(node->italic) designed_node = ami_font_open(node->italic, false);
476
477 if(designed_node == NULL) {
478 shearsin = NSA_VALUE_SHEARSIN;
479 shearcos = NSA_VALUE_SHEARCOS;
480 }
481 break;
482
483 case NSA_OBLIQUE:
484 shearsin = NSA_VALUE_SHEARSIN;
485 shearcos = NSA_VALUE_SHEARCOS;
486 break;
487
488 case NSA_BOLD:
489 if(node->bold) designed_node = ami_font_open(node->bold, false);
490
491 if(designed_node == NULL) {
492 emboldenx = NSA_VALUE_BOLDX;
493 emboldeny = NSA_VALUE_BOLDY;
494 }
495 break;
496
497 case NSA_BOLDOBLIQUE:
498 shearsin = NSA_VALUE_SHEARSIN;
499 shearcos = NSA_VALUE_SHEARCOS;
500
501 if(node->bold) designed_node = ami_font_open(node->bold, false);
502
503 if(designed_node == NULL) {
504 emboldenx = NSA_VALUE_BOLDX;
505 emboldeny = NSA_VALUE_BOLDY;
506 }
507 break;
508
509 case NSA_BOLDITALIC:
510 if(node->bolditalic) designed_node = ami_font_open(node->bolditalic, false);
511
512 if(designed_node == NULL) {
513 emboldenx = NSA_VALUE_BOLDX;
514 emboldeny = NSA_VALUE_BOLDY;
515 shearsin = NSA_VALUE_SHEARSIN;
516 shearcos = NSA_VALUE_SHEARCOS;
517 }
518 break;
519 }
520
521 /* Scale to 16.16 fixed point */
522 ysize = fstyle->size * ((1 << 16) / PLOT_STYLE_SCALE);
523
524 if(designed_node == NULL) {
525 ofont = node->font;
526 } else {
527 ofont = designed_node->font;
528 }
529
530#ifndef __amigaos4__
531 struct BulletBase *BulletBase = ofont->BulletBase;
532#endif
533
535 OT_DeviceDPI, ami_font_dpi_get_devicedpi(),
536 OT_PointHeight, ysize,
537 OT_EmboldenX, emboldenx,
538 OT_EmboldenY, emboldeny,
539 OT_ShearSin, shearsin,
540 OT_ShearCos, shearcos,
541 TAG_END) == OTERR_Success)
542 return ofont;
543
544 return NULL;
545}
546
547static inline int32 ami_font_plot_glyph(struct OutlineFont *ofont, struct RastPort *rp,
548 uint16 *restrict char1, uint16 *restrict char2, uint32 x, uint32 y,
549 uint32 emwidth, bool aa)
550{
551 struct GlyphMap *glyph;
552 UBYTE *glyphbm;
553 int32 char_advance = 0;
554 FIXED kern = 0;
555 ULONG glyphmaptag;
556 ULONG template_type;
557 bool skip_c2 = false;
558 uint32 long_char_1 = 0, long_char_2 = 0;
559#ifndef __amigaos4__
560 struct BulletBase *BulletBase = ofont->BulletBase;
561#endif
562
563#ifndef __amigaos4__
564 if (__builtin_expect(((*char1 >= 0xD800) && (*char1 <= 0xDBFF)), 0)) {
565 /* We don't support UTF-16 surrogates yet, so just return. */
566 return 0;
567 }
568
569 if (__builtin_expect(((*char2 >= 0xD800) && (*char2 <= 0xDBFF)), 0)) {
570 /* Don't attempt to kern a UTF-16 surrogate */
571 *char2 = 0;
572 }
573#endif
574
575 if (*char2 < 0x0020) skip_c2 = true;
576
577#ifdef __amigaos4__
578 if(__builtin_expect(aa == true, 1)) {
579 glyphmaptag = OT_GlyphMap8Bit;
580 template_type = BLITT_ALPHATEMPLATE;
581 } else {
582#endif
583 glyphmaptag = OT_GlyphMap;
584#ifdef __amigaos4__
585 template_type = BLITT_TEMPLATE;
586 }
587#endif
588
589 long_char_1 = amiga_nsfont_decode_surrogate(char1);
590 long_char_2 = amiga_nsfont_decode_surrogate(char2);
591 /**\todo use OT_GlyphCode_32 so we get an error for old font engines */
592
594 OT_GlyphCode, long_char_1,
595 OT_GlyphCode2, long_char_2,
596 TAG_END) == OTERR_Success)
597 {
599 glyphmaptag, &glyph,
600 TAG_END) == 0)
601 {
602 glyphbm = glyph->glm_BitMap;
603 if(!glyphbm) return 0;
604
605 if(rp) {
606#ifdef __amigaos4__
607 BltBitMapTags(BLITA_SrcX, glyph->glm_BlackLeft,
608 BLITA_SrcY, glyph->glm_BlackTop,
609 BLITA_DestX, x - glyph->glm_X0 + glyph->glm_BlackLeft,
610 BLITA_DestY, y - glyph->glm_Y0 + glyph->glm_BlackTop,
611 BLITA_Width, glyph->glm_BlackWidth,
612 BLITA_Height, glyph->glm_BlackHeight,
613 BLITA_Source, glyphbm,
614 BLITA_SrcType, template_type,
615 BLITA_Dest, rp,
616 BLITA_DestType, BLITT_RASTPORT,
617 BLITA_SrcBytesPerRow, glyph->glm_BMModulo,
618 TAG_DONE);
619#else
620 /* On OS3 the glyph needs to be in chip RAM */
621 void *chip_glyph = ami_memory_chip_alloc(glyph->glm_BMModulo * glyph->glm_BMRows);
622 if(chip_glyph != NULL) {
623 CopyMem(glyphbm, chip_glyph, glyph->glm_BMModulo * glyph->glm_BMRows);
624
625 BltTemplate(chip_glyph + (glyph->glm_BMModulo * glyph->glm_BlackTop) +
626 ((glyph->glm_BlackLeft >> 4) << 1),
627 glyph->glm_BlackLeft & 0xF, glyph->glm_BMModulo, rp,
628 x - glyph->glm_X0 + glyph->glm_BlackLeft,
629 y - glyph->glm_Y0 + glyph->glm_BlackTop,
630 glyph->glm_BlackWidth, glyph->glm_BlackHeight);
631
632 ami_memory_chip_free(chip_glyph);
633 }
634#endif
635 }
636
637 kern = 0;
638
639 if((*char2) && (!skip_c2)) EObtainInfo(AMI_OFONT_ENGINE,
640 OT_TextKernPair, &kern,
641 TAG_END);
642
643 char_advance = (ULONG)(((glyph->glm_Width - kern) * emwidth) / 65536);
644
646 glyphmaptag, glyph,
647 TAG_END);
648
649 if((*char2) && (!skip_c2)) EReleaseInfo(AMI_OFONT_ENGINE,
650 OT_TextKernPair, kern,
651 TAG_END);
652 }
653 }
654
655 return char_advance;
656}
657
658static inline int32 ami_font_width_glyph(struct OutlineFont *ofont,
659 const uint16 *restrict char1, const uint16 *restrict char2, uint32 emwidth)
660{
661 int32 char_advance = 0;
662 FIXED kern = 0;
663 struct MinList *gwlist = NULL;
664 struct GlyphWidthEntry *gwnode;
665 bool skip_c2 = false;
666 uint32 long_char_1 = 0;
667 uint32 long_char_2;
668#ifndef __amigaos4__
669 struct BulletBase *BulletBase = ofont->BulletBase;
670#endif
671
672#ifndef __amigaos4__
673 if (__builtin_expect(((*char1 >= 0xD800) && (*char1 <= 0xDBFF)), 0)) {
674 /* We don't support UTF-16 surrogates yet, so just return. */
675 return 0;
676 }
677
678 if (__builtin_expect(((*char2 >= 0xD800) && (*char2 <= 0xDBFF)), 0)) {
679 /* Don't attempt to kern a UTF-16 surrogate */
680 skip_c2 = true;
681 }
682#endif
683
684 if (*char2 < 0x0020) skip_c2 = true;
685
686 long_char_1 = amiga_nsfont_decode_surrogate(char1);
687 /**\todo use OT_GlyphCode_32 so we get an error for old font engines */
688
690 OT_GlyphCode, long_char_1,
691 OT_GlyphCode2, long_char_1,
692 TAG_END) == OTERR_Success)
693 {
695 OT_WidthList, &gwlist,
696 TAG_END) == 0)
697 {
698 FIXED char1w = 0;
699 gwnode = (struct GlyphWidthEntry *)GetHead((struct List *)gwlist);
700 if(gwnode) char1w = gwnode->gwe_Width;
701
702 kern = 0;
703
704 if(!skip_c2) {
705 long_char_2 = amiga_nsfont_decode_surrogate(char2);
707 OT_GlyphCode, long_char_1,
708 OT_GlyphCode2, long_char_2,
709 TAG_END) == OTERR_Success)
710 {
712 OT_TextKernPair, &kern,
713 TAG_END);
714 }
715 }
716 char_advance = (ULONG)(((char1w - kern) * emwidth) / 65536);
717
718 if(!skip_c2) EReleaseInfo(AMI_OFONT_ENGINE,
719 OT_TextKernPair, kern,
720 TAG_END);
721
723 OT_WidthList, gwlist,
724 TAG_END);
725 }
726 }
727
728 return char_advance;
729}
730
732{
733 const uint16 *p;
734 p = &sc_table[0];
735
736 while (*p != 0)
737 {
738 if(*p == *utf16char) return &p[1];
739 p++;
740 }
741
742 return utf16char;
743}
744
745static ULONG amiga_nsfont_text(struct RastPort *rp, const char *string, ULONG length,
746 const plot_font_style_t *fstyle, ULONG dx, ULONG dy, bool aa)
747{
748 uint16 *restrict utf16 = NULL, *restrict outf16 = NULL;
749 uint16 *restrict utf16charsc = 0, *restrict utf16nextsc = 0;
750 uint16 *restrict utf16next = 0;
751 int utf16charlen;
752 struct OutlineFont *restrict ofont, *restrict ufont = NULL;
753 uint32 x=0;
754 int32 tempx = 0;
755 ULONG emwidth = (ULONG)NSA_FONT_EMWIDTH(fstyle->size);
756 uint16 utf16_a = 0x41;
757
758 if(!string || string[0]=='\0') return 0;
759 if(!length) return 0;
760 if(rp == NULL) return 0;
761
762 if(utf8_to_enc(string,"UTF-16",length,(char **)&utf16) != NSERROR_OK) return 0;
763 outf16 = utf16;
764 if(!(ofont = ami_open_outline_font(fstyle, 0))) {
765 if(!(ofont = ami_open_outline_font(fstyle, &utf16_a))) return 0;
766 }
767
768 while(*utf16 != 0)
769 {
770 utf16charlen = amiga_nsfont_utf16_char_length(utf16);
771 utf16next = &utf16[utf16charlen];
772
773 if(fstyle->flags & FONTF_SMALLCAPS)
774 {
775 utf16charsc = (uint16 *)ami_font_translate_smallcaps(utf16);
776 utf16nextsc = (uint16 *)ami_font_translate_smallcaps(utf16next);
777
778 tempx = ami_font_plot_glyph(ofont, rp, utf16charsc, utf16nextsc,
779 dx + x, dy, emwidth, aa);
780 }
781 else tempx = 0;
782
783 if(tempx == 0) {
784 tempx = ami_font_plot_glyph(ofont, rp, utf16, utf16next,
785 dx + x, dy, emwidth, aa);
786 }
787
788 if(tempx == 0)
789 {
790 if(ufont == NULL)
791 {
792 ufont = ami_open_outline_font(fstyle, utf16);
793 }
794
795 if(ufont) {
796 tempx = ami_font_plot_glyph(ufont, rp, utf16, utf16next,
797 dx + x, dy, emwidth, aa);
798 }
799 }
800
801 x += tempx;
802
803 utf16 += utf16charlen;
804 }
805
806 free(outf16);
807 return x;
808}
809
810static inline ULONG ami_font_unicode_width(const char *string, ULONG length,
811 const plot_font_style_t *fstyle, ULONG dx, ULONG dy, bool aa)
812{
813 uint16 *restrict utf16 = NULL, *restrict outf16 = NULL;
814 uint16 *restrict utf16charsc = 0, *restrict utf16nextsc = 0;
815 uint16 *restrict utf16next = 0;
816 int utf16charlen;
817 struct OutlineFont *restrict ofont, *restrict ufont = NULL;
818 uint32 x=0;
819 int32 tempx = 0;
820 ULONG emwidth = (ULONG)NSA_FONT_EMWIDTH(fstyle->size);
821 uint16 utf16_a = 0x41;
822
823 if(!string || string[0]=='\0') return 0;
824 if(!length) return 0;
825
826 if(utf8_to_enc(string,"UTF-16",length,(char **)&utf16) != NSERROR_OK) return 0;
827 outf16 = utf16;
828 if(!(ofont = ami_open_outline_font(fstyle, 0))) {
829 if(!(ofont = ami_open_outline_font(fstyle, &utf16_a))) return 0;
830 }
831
832 while(*utf16 != 0)
833 {
834 utf16charlen = amiga_nsfont_utf16_char_length(utf16);
835 utf16next = &utf16[utf16charlen];
836
837 if(fstyle->flags & FONTF_SMALLCAPS)
838 {
839 utf16charsc = (uint16 *)ami_font_translate_smallcaps(utf16);
840 utf16nextsc = (uint16 *)ami_font_translate_smallcaps(utf16next);
841
842 tempx = ami_font_width_glyph(ofont, utf16charsc, utf16nextsc, emwidth);
843 }
844 else tempx = 0;
845
846 if(tempx == 0) {
847 tempx = ami_font_width_glyph(ofont, utf16, utf16next, emwidth);
848 }
849
850 if(tempx == 0)
851 {
852 if(ufont == NULL)
853 {
854 ufont = ami_open_outline_font(fstyle, utf16);
855 }
856
857 if(ufont)
858 {
859 tempx = ami_font_width_glyph(ufont, utf16, utf16next, emwidth);
860 }
861 }
862
863 x += tempx;
864
865 utf16 += utf16charlen;
866 }
867
868 free(outf16);
869 return x;
870}
871
873{
874 struct ami_font_cache_node *node = (struct ami_font_cache_node *)nso;
876}
877
883};
884
886{
887 /* Initialise Unicode font scanner */
888 ami_font_initscanner(false, true);
889
890 /* Initialise font caching etc lists */
892
893 /* List for diskfont internal cache */
894 NewList(&ami_diskfontlib_list);
895
896 /* Set up table */
898}
899
901{
904}
905
906/* Font scanner */
907void ami_font_initscanner(bool force, bool save)
908{
909 ami_font_scan_init(nsoption_charp(font_unicode_file), force, save, glypharray);
910}
911
913{
915}
916
918{
919 ami_font_scan_save(nsoption_charp(font_unicode_file), glypharray);
920}
921
nserror amiga_warn_user(const char *warning, const char *detail)
Warn the user of an event.
Definition: misc.c:79
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_INVALID
Invalid data.
Definition: errors.h:49
@ NSERROR_OK
No error.
Definition: errors.h:30
static ULONG amiga_nsfont_text(struct RastPort *rp, const char *string, ULONG length, const plot_font_style_t *fstyle, ULONG dx, ULONG dy, bool aa)
Definition: font_bullet.c:745
static struct ami_font_cache_node * ami_font_open(const char *font, bool critical)
Search for a font in the list and load from disk if not present.
Definition: font_bullet.c:350
static uint32 amiga_nsfont_decode_surrogate(const uint16 *char1)
Definition: font_bullet.c:157
void ami_font_finiscanner(void)
Definition: font_bullet.c:912
const struct ami_font_functions ami_font_bullet_table
Definition: font_bullet.c:878
#define NSA_VALUE_SHEARSIN
Definition: font_bullet.c:63
#define NSA_VALUE_BOLDY
Definition: font_bullet.c:62
static int amiga_nsfont_utf16_char_length(const uint16 *char1)
Definition: font_bullet.c:148
#define NSA_FONT_EMWIDTH(s)
Definition: font_bullet.c:66
static lwc_string * glypharray[0xffff+1]
Definition: font_bullet.c:135
#define NSA_VALUE_SHEARCOS
Definition: font_bullet.c:64
static int32 ami_font_plot_glyph(struct OutlineFont *ofont, struct RastPort *rp, uint16 *restrict char1, uint16 *restrict char2, uint32 x, uint32 y, uint32 emwidth, bool aa)
Definition: font_bullet.c:547
#define NSA_BOLDITALIC
Definition: font_bullet.c:57
static nserror amiga_nsfont_width(const plot_font_style_t *fstyle, const char *string, size_t length, int *width)
Definition: font_bullet.c:166
#define NSA_BOLDOBLIQUE
Definition: font_bullet.c:59
static const uint16 * ami_font_translate_smallcaps(uint16 *utf16char)
Definition: font_bullet.c:731
#define NSA_VALUE_BOLDX
Definition: font_bullet.c:61
static ULONG ami_font_unicode_width(const char *string, ULONG length, const plot_font_style_t *fstyle, ULONG x, ULONG y, bool aa)
Definition: font_bullet.c:810
static struct List ami_diskfontlib_list
Definition: font_bullet.c:137
#define NSA_OBLIQUE
Definition: font_bullet.c:58
static int32 ami_font_width_glyph(struct OutlineFont *ofont, const uint16 *restrict char1, const uint16 *restrict char2, uint32 emwidth)
Definition: font_bullet.c:658
#define NSA_BOLD
Definition: font_bullet.c:56
void ami_font_initscanner(bool force, bool save)
Definition: font_bullet.c:907
static nserror amiga_nsfont_split(const plot_font_style_t *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x)
Find where to split a string to make it fit a width.
Definition: font_bullet.c:274
const uint16 sc_table[]
Definition: font_bullet.c:68
void ami_font_bullet_fini(void)
Definition: font_bullet.c:900
void ami_font_bullet_close(void *nso)
Definition: font_bullet.c:872
void ami_font_bullet_init(void)
Definition: font_bullet.c:885
static nserror amiga_nsfont_position_in_string(const plot_font_style_t *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x)
Find the position in a string where an x coordinate falls.
Definition: font_bullet.c:191
#define NSA_ITALIC
Definition: font_bullet.c:55
void ami_font_savescanner(void)
Definition: font_bullet.c:917
#define NSA_UNICODE_FONT
Definition: font_bullet.c:52
static struct OutlineFont * ami_open_outline_font(const plot_font_style_t *fstyle, const uint16 *codepoint)
Open an outline font in the specified size and style.
Definition: font_bullet.c:413
void ami_font_cache_fini(void)
Definition: font_cache.c:187
struct ami_font_cache_node * ami_font_cache_alloc_entry(const char *font)
Definition: font_cache.c:159
void ami_font_cache_insert(struct ami_font_cache_node *nodedata, const char *font)
Definition: font_cache.c:175
void ami_font_cache_init(void)
Definition: font_cache.c:199
struct ami_font_cache_node * ami_font_cache_locate(const char *font)
Definition: font_cache.c:137
const char * ami_font_scan_lookup(const uint16 *code, lwc_string **glypharray)
Lookup a font that contains a UTF-16 codepoint.
Definition: font_scan.c:82
void ami_font_scan_init(const char *filename, bool force_scan, bool save, lwc_string **glypharray)
Initialise the font glyph cache.
Definition: font_scan.c:474
void ami_font_scan_save(const char *filename, lwc_string **glypharray)
Save a font glyph cache.
Definition: font_scan.c:425
void ami_font_scan_fini(lwc_string **glypharray)
Finalise the font glyph cache.
Definition: font_scan.c:452
#define AMI_OFONT_ENGINE
Definition: font_scan.h:29
ULONG ami_font_dpi_get_devicedpi(void)
Definition: font.c:38
const struct ami_font_functions * ami_nsfont
Definition: font.h:58
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
#define ami_memory_chip_free(p)
Definition: memory.h:30
#define ami_memory_chip_alloc(s)
Definition: memory.h:29
void CloseOutlineFont(struct OutlineFont *of, struct List *list)
Definition: os3support.c:323
struct OutlineFont * OpenOutlineFont(STRPTR fileName, struct List *list, ULONG flags)
Definition: os3support.c:204
struct Node * GetHead(struct List *list)
Definition: os3support.c:364
Minimal compatibility header for AmigaOS 3.
#define OFF_OPEN
Definition: os3support.h:125
#define ESetInfo
Definition: os3support.h:151
#define EObtainInfo
Definition: os3support.h:150
#define EReleaseInfo
Definition: os3support.h:149
int32_t int32
Definition: os3support.h:183
uint16_t uint16
Definition: os3support.h:182
uint32_t uint32
Definition: os3support.h:184
@ FONTF_ITALIC
Definition: plot_style.h:103
@ FONTF_SMALLCAPS
Definition: plot_style.h:105
@ FONTF_OBLIQUE
Definition: plot_style.h:104
plot_font_generic_family_t
Generic font family type.
Definition: plot_style.h:88
@ 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:159
struct TagItem * olf_OTagList
Definition: os3support.h:205
struct BulletBase * BulletBase
Definition: os3support.h:202
struct OutlineFont * font
Definition: font_cache.h:29
char *restrict bolditalic
Definition: font_cache.h:32
char *restrict bold
Definition: font_cache.h:30
char *restrict italic
Definition: font_cache.h:31
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 nsoption_charp(OPTION)
Get the value of a string option.
Definition: nsoption.h:297
size_t utf8_next(const char *s, size_t l, size_t o)
Find next legal UTF-8 char in string.
Definition: utf8.c:129
nserror utf8_to_enc(const char *string, const char *encname, size_t len, char **result)
Convert a UTF8 string into the named encoding.
Definition: utf8.c:314
UTF-8 manipulation functions (interface).
Interface to a number of general purpose functionality.