2002-07-28 01:10:45 +04:00
|
|
|
/**
|
2002-10-05 21:50:21 +04:00
|
|
|
* $Id: font.c,v 1.4 2002/10/05 17:50:21 bursa Exp $
|
2002-07-28 01:10:45 +04:00
|
|
|
*/
|
|
|
|
|
2002-09-27 01:38:33 +04:00
|
|
|
#include <assert.h>
|
2002-07-28 01:10:45 +04:00
|
|
|
#include <stdio.h>
|
2002-09-27 01:38:33 +04:00
|
|
|
#include "utf-8.h"
|
2002-07-28 01:10:45 +04:00
|
|
|
#include "netsurf/render/css.h"
|
2002-09-27 01:38:33 +04:00
|
|
|
#include "netsurf/riscos/font.h"
|
2002-07-28 01:10:45 +04:00
|
|
|
#include "netsurf/render/utils.h"
|
2002-09-11 18:24:02 +04:00
|
|
|
#include "netsurf/desktop/gui.h"
|
2002-10-05 21:50:21 +04:00
|
|
|
#include "netsurf/utils/log.h"
|
2002-07-28 01:10:45 +04:00
|
|
|
#include "oslib/font.h"
|
|
|
|
|
|
|
|
/**
|
2002-09-27 01:38:33 +04:00
|
|
|
* RISC OS fonts are 8-bit, so Unicode is displayed by combining many
|
|
|
|
* font manager fonts. Each font manager font must have 128 characters of
|
|
|
|
* Unicode in order, starting at character 128.
|
2002-07-28 01:10:45 +04:00
|
|
|
*/
|
|
|
|
|
2002-09-27 01:38:33 +04:00
|
|
|
/**
|
|
|
|
* font id = font family * 4 + bold * 2 + slanted
|
|
|
|
* font family: 0 = sans-serif, 1 = serif, ...
|
|
|
|
*/
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2002-09-27 01:38:33 +04:00
|
|
|
const char * const font_table[FONT_FAMILIES * 4][FONT_CHUNKS] = {
|
|
|
|
/* sans-serif */
|
|
|
|
{ "Homerton.Medium\\EU0000",
|
|
|
|
"Homerton.Medium\\EU0080",
|
|
|
|
"Homerton.Medium\\EU0100" },
|
|
|
|
{ "Homerton.Medium.Oblique\\EU0000",
|
|
|
|
"Homerton.Medium.Oblique\\EU0080",
|
|
|
|
"Homerton.Medium.Oblique\\EU0100" },
|
|
|
|
{ "Homerton.Bold\\EU0000",
|
|
|
|
"Homerton.Bold\\EU0080",
|
|
|
|
"Homerton.Bold\\EU0100" },
|
|
|
|
{ "Homerton.Bold.Oblique\\EU0000",
|
|
|
|
"Homerton.Bold.Oblique\\EU0080",
|
|
|
|
"Homerton.Bold.Oblique\\EU0100" },
|
|
|
|
};
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2002-09-27 01:38:33 +04:00
|
|
|
/* a font_set is just a linked list of font_data for each face for now */
|
|
|
|
struct font_set {
|
|
|
|
struct font_data *font[FONT_FAMILIES * 4];
|
|
|
|
};
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2002-09-27 01:38:33 +04:00
|
|
|
void font_close(struct font_data *data);
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2002-09-27 01:38:33 +04:00
|
|
|
/**
|
|
|
|
* functions
|
|
|
|
*/
|
2002-07-28 01:10:45 +04:00
|
|
|
|
2002-09-27 01:38:33 +04:00
|
|
|
unsigned long font_width(struct font_data *font, const char * text, unsigned int length)
|
2002-07-28 01:10:45 +04:00
|
|
|
{
|
|
|
|
font_scan_block block;
|
|
|
|
os_error * error;
|
2002-09-27 01:38:33 +04:00
|
|
|
char *text2;
|
|
|
|
|
|
|
|
assert(font != 0 && text != 0);
|
2002-07-28 01:10:45 +04:00
|
|
|
|
2002-09-11 18:24:02 +04:00
|
|
|
if (length == 0)
|
|
|
|
return 0;
|
2002-07-28 01:10:45 +04:00
|
|
|
|
|
|
|
block.space.x = block.space.y = 0;
|
|
|
|
block.letter.x = block.letter.y = 0;
|
|
|
|
block.split_char = -1;
|
|
|
|
|
2002-09-27 01:38:33 +04:00
|
|
|
text2 = font_utf8_to_string(font, text, length);
|
|
|
|
error = xfont_scan_string(font->handle[0], text2,
|
|
|
|
font_GIVEN_BLOCK | font_GIVEN_FONT | font_KERN | font_RETURN_BBOX,
|
2002-07-28 01:10:45 +04:00
|
|
|
0x7fffffff, 0x7fffffff,
|
|
|
|
&block,
|
2002-09-27 01:38:33 +04:00
|
|
|
0, 0,
|
2002-07-28 01:10:45 +04:00
|
|
|
0, 0, 0, 0);
|
|
|
|
if (error != 0) {
|
|
|
|
fprintf(stderr, "%s\n", error->errmess);
|
|
|
|
die("font_scan_string failed");
|
|
|
|
}
|
2002-09-11 18:24:02 +04:00
|
|
|
|
2002-09-27 01:38:33 +04:00
|
|
|
/* fprintf(stderr, "font_width: '%.*s' => '%s' => %i %i %i %i\n", length, text, text2, */
|
|
|
|
/* block.bbox.x0, block.bbox.y0, block.bbox.x1, block.bbox.y1); */
|
|
|
|
free(text2);
|
2002-09-11 18:24:02 +04:00
|
|
|
|
|
|
|
if (length < 0x7fffffff)
|
|
|
|
{
|
|
|
|
if (text[length - 1] == ' ')
|
|
|
|
// {
|
|
|
|
block.bbox.x1 += 4*800;
|
|
|
|
/* int minx,miny,maxx,maxy;
|
|
|
|
char space = ' ';
|
|
|
|
// fprintf(stderr, "Space at the end!\n");
|
|
|
|
error = xfont_char_bbox(font, space, 0, &minx, &miny, &maxx, &maxy);
|
|
|
|
if (error != 0) {
|
|
|
|
fprintf(stderr, "%s\n", error->errmess);
|
|
|
|
die("font_char_bbox failed");
|
|
|
|
}
|
|
|
|
block.bbox.x1 += maxx;
|
|
|
|
}
|
|
|
|
// else
|
|
|
|
// fprintf(stderr, "No space\n");*/
|
|
|
|
}
|
|
|
|
|
2002-07-28 01:10:45 +04:00
|
|
|
return block.bbox.x1 / 800;
|
|
|
|
}
|
|
|
|
|
2002-09-27 01:38:33 +04:00
|
|
|
void font_position_in_string(const char* text, struct font_data* font,
|
|
|
|
int length, int x, int* char_offset, int* pixel_offset)
|
2002-09-11 18:24:02 +04:00
|
|
|
{
|
|
|
|
font_scan_block block;
|
|
|
|
char* split_point;
|
|
|
|
int x_out, y_out, length_out;
|
2002-09-27 01:38:33 +04:00
|
|
|
char *text2;
|
|
|
|
|
|
|
|
assert(font != 0 && text != 0);
|
2002-09-11 18:24:02 +04:00
|
|
|
|
|
|
|
block.space.x = block.space.y = 0;
|
|
|
|
block.letter.x = block.letter.y = 0;
|
|
|
|
block.split_char = -1;
|
|
|
|
|
2002-09-27 01:38:33 +04:00
|
|
|
text2 = font_utf8_to_string(font, text, length);
|
|
|
|
xfont_scan_string(font, text2,
|
|
|
|
font_GIVEN_BLOCK | font_GIVEN_FONT | font_KERN | font_RETURN_CARET_POS,
|
2002-09-11 18:24:02 +04:00
|
|
|
ro_x_units(x) * 400,
|
|
|
|
0x7fffffff,
|
2002-09-27 01:38:33 +04:00
|
|
|
&block, 0, 0,
|
2002-09-11 18:24:02 +04:00
|
|
|
&split_point, &x_out, &y_out, &length_out);
|
2002-09-27 01:38:33 +04:00
|
|
|
free(text2);
|
2002-09-11 18:24:02 +04:00
|
|
|
|
|
|
|
*char_offset = (int)(split_point - text);
|
|
|
|
*pixel_offset = browser_x_units(x_out / 400);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-09-27 01:38:33 +04:00
|
|
|
|
|
|
|
struct font_set *font_new_set()
|
|
|
|
{
|
|
|
|
struct font_set *set = xcalloc(1, sizeof(*set));
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < FONT_FAMILIES * 4; i++)
|
|
|
|
set->font[i] = 0;
|
|
|
|
|
|
|
|
return set;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct font_data *font_open(struct font_set *set, struct css_style *style)
|
|
|
|
{
|
|
|
|
struct font_data *data;
|
|
|
|
unsigned int i;
|
|
|
|
unsigned int size = 16 * 11;
|
|
|
|
unsigned int f = 0;
|
|
|
|
|
|
|
|
assert(set != 0);
|
|
|
|
|
|
|
|
if (style->font_size.size == CSS_FONT_SIZE_LENGTH)
|
|
|
|
size = style->font_size.value.length.value * 16;
|
|
|
|
|
|
|
|
switch (style->font_weight) {
|
|
|
|
case CSS_FONT_WEIGHT_BOLD:
|
|
|
|
case CSS_FONT_WEIGHT_600:
|
|
|
|
case CSS_FONT_WEIGHT_700:
|
|
|
|
case CSS_FONT_WEIGHT_800:
|
|
|
|
case CSS_FONT_WEIGHT_900:
|
|
|
|
f += FONT_BOLD;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (style->font_style) {
|
|
|
|
case CSS_FONT_STYLE_ITALIC:
|
|
|
|
case CSS_FONT_STYLE_OBLIQUE:
|
|
|
|
f += FONT_SLANTED;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (data = set->font[f]; data != 0; data = data->next)
|
|
|
|
if (data->size == size)
|
|
|
|
return data;
|
|
|
|
|
|
|
|
data = xcalloc(1, sizeof(*data));
|
|
|
|
|
|
|
|
for (i = 0; i < FONT_CHUNKS; i++) {
|
2002-10-05 21:50:21 +04:00
|
|
|
font_f handle;
|
|
|
|
os_error *error;
|
|
|
|
|
|
|
|
LOG(("font_find_font '%s' %i", font_table[f][i], size));
|
|
|
|
error = xfont_find_font(font_table[f][i], size, size, 0, 0, &handle, 0, 0);
|
|
|
|
if (error != 0) {
|
|
|
|
fprintf(stderr, "%s\n", error->errmess);
|
|
|
|
die("font_find_font failed");
|
|
|
|
}
|
2002-09-27 01:38:33 +04:00
|
|
|
data->handle[i] = handle;
|
|
|
|
}
|
|
|
|
data->size = size;
|
|
|
|
|
|
|
|
data->next = set->font[f];
|
|
|
|
set->font[f] = data;
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void font_free_set(struct font_set *set)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
struct font_data *data, *next;
|
|
|
|
|
|
|
|
assert(set != 0);
|
|
|
|
|
|
|
|
for (i = 0; i < FONT_FAMILIES * 4; i++) {
|
|
|
|
for (data = set->font[i]; data != 0; data = next) {
|
|
|
|
next = data->next;
|
|
|
|
font_close(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(set);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void font_close(struct font_data *data)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < FONT_CHUNKS; i++)
|
|
|
|
font_lose_font(data->handle[i]);
|
|
|
|
|
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define BUFFER_CHUNK 100
|
|
|
|
|
|
|
|
char *font_utf8_to_string(struct font_data *font, const char *s, unsigned int length)
|
|
|
|
{
|
|
|
|
unsigned long buffer_len = BUFFER_CHUNK;
|
|
|
|
char *d = xcalloc(buffer_len, sizeof(char));
|
|
|
|
unsigned int chunk0 = 0, chunk1;
|
|
|
|
unsigned int u, chars, i = 0, j = 0;
|
|
|
|
|
|
|
|
assert(font != 0 && s != 0);
|
|
|
|
|
|
|
|
/* fprintf(stderr, "font_utf8_to_string: '%s'", s); */
|
|
|
|
|
|
|
|
while (j < length && s[j] != 0) {
|
|
|
|
u = sgetu8(s + j, &chars);
|
|
|
|
j += chars;
|
|
|
|
if (buffer_len < i + 5) {
|
|
|
|
buffer_len += BUFFER_CHUNK;
|
|
|
|
d = xrealloc(d, buffer_len * sizeof(char));
|
|
|
|
}
|
|
|
|
chunk1 = u / 0x80;
|
|
|
|
if (FONT_CHUNKS <= chunk1 || (u < 0x20 || (0x80 <= u && u <= 0x9f))) {
|
|
|
|
d[i++] = '?';
|
|
|
|
} else {
|
|
|
|
if (chunk0 != chunk1) {
|
|
|
|
d[i++] = font_COMMAND_FONT;
|
|
|
|
d[i++] = font->handle[chunk1];
|
|
|
|
chunk0 = chunk1;
|
|
|
|
}
|
|
|
|
d[i++] = 0x80 + (u % 0x80);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
d[i] = 0;
|
|
|
|
|
|
|
|
/* fprintf(stderr, " => '%s'\n", d); */
|
|
|
|
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|