summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--riscos/font.c231
1 files changed, 158 insertions, 73 deletions
diff --git a/riscos/font.c b/riscos/font.c
index a33653ec9..5fb02e3b4 100644
--- a/riscos/font.c
+++ b/riscos/font.c
@@ -6,6 +6,12 @@
* Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
*/
+/** \file
+ * Font handling (RISC OS implementation).
+ *
+ * The Font Manager is used to handle and render fonts.
+ */
+
#include <assert.h>
#include <stdio.h>
#include "oslib/font.h"
@@ -25,8 +31,10 @@ struct font_set {
struct font_data *font[FONT_FAMILIES * 4];
};
-/**
+/** Table of font names.
+ *
* font id = font family * 4 + bold * 2 + slanted
+ *
* font family: 0 = sans-serif, 1 = serif, ...
*/
@@ -38,63 +46,13 @@ const char * const font_table[FONT_FAMILIES * 4] = {
"Homerton.Bold.Oblique\\ELatin1",
};
-static void font_close(struct font_data *data);
/**
- * functions
+ * Create an empty font_set.
+ *
+ * \return an opaque struct font_set.
*/
-unsigned long font_width(struct font_data *font, const char * text, unsigned int length)
-{
- int width;
- os_error * error;
-
- assert(font != 0 && text != 0);
-
- if (length == 0)
- return 0;
-
- error = xfont_scan_string((font_f)(font->handle), text,
- font_GIVEN_FONT | font_KERN | font_GIVEN_LENGTH,
- 0x7fffffff, 0x7fffffff,
- 0,
- 0, (int)length,
- 0, &width, 0, 0);
- if (error != 0) {
- fprintf(stderr, "%s\n", error->errmess);
- die("font_width: font_scan_string failed");
- }
-
- return width / 800;
-}
-
-void font_position_in_string(const char* text, struct font_data* font,
- unsigned int length, unsigned long x, int* char_offset, int* pixel_offset)
-{
- font_scan_block block;
- char* split_point;
- int x_out, y_out, length_out;
-
- assert(font != 0 && text != 0);
-
- block.space.x = block.space.y = 0;
- block.letter.x = block.letter.y = 0;
- block.split_char = -1;
-
- xfont_scan_string((font_f)(font->handle), text,
- font_GIVEN_BLOCK | font_GIVEN_FONT | font_KERN | font_RETURN_CARET_POS | font_GIVEN_LENGTH,
- ro_x_units(x) * 400,
- 0x7fffffff,
- &block, 0, (int)length,
- &split_point, &x_out, &y_out, &length_out);
-
- *char_offset = (int)(split_point - text);
- *pixel_offset = browser_x_units(x_out / 400);
-
- return;
-}
-
-
struct font_set *font_new_set()
{
struct font_set *set = xcalloc(1, sizeof(*set));
@@ -107,13 +65,26 @@ struct font_set *font_new_set()
}
+/**
+ * Open a font for use based on a css_style.
+ *
+ * \param set a font_set, as returned by font_new_set()
+ * \param style a css_style which describes the font
+ * \return a struct font_data, with a RISC OS font handle in handle
+ *
+ * The set is updated to include the font, if it was not present.
+ */
+
struct font_data *font_open(struct font_set *set, struct css_style *style)
{
struct font_data *data;
unsigned int size = 16 * 11;
unsigned int f = 0;
+ font_f handle;
+ os_error *error;
- assert(set != 0);
+ assert(set);
+ assert(style);
if (style->font_size.size == CSS_FONT_SIZE_LENGTH)
size = style->font_size.value.length.value * 16;
@@ -145,19 +116,14 @@ struct font_data *font_open(struct font_set *set, struct css_style *style)
data = xcalloc(1, sizeof(*data));
- {
- font_f handle;
- os_error *error;
-
- LOG(("font_find_font '%s' %i", font_table[f], size));
- error = xfont_find_font(font_table[f], (int)size, (int)size,
- 0, 0, &handle, 0, 0);
- if (error != 0) {
- fprintf(stderr, "%s\n", error->errmess);
- die("font_find_font failed");
- }
- data->handle = handle;
+ error = xfont_find_font(font_table[f], (int)size, (int)size,
+ 0, 0, &handle, 0, 0);
+ if (error) {
+ fprintf(stderr, "%i: %s\n", error->errnum, error->errmess);
+ die("font_find_font failed");
}
+
+ data->handle = handle;
data->size = size;
data->space_width = font_width(data, " ", 1);
@@ -168,6 +134,12 @@ struct font_data *font_open(struct font_set *set, struct css_style *style)
}
+/**
+ * Frees all the fonts in a font_set.
+ *
+ * \param set a font_set as returned by font_new_set()
+ */
+
void font_free_set(struct font_set *set)
{
unsigned int i;
@@ -178,7 +150,8 @@ void font_free_set(struct font_set *set)
for (i = 0; i < FONT_FAMILIES * 4; i++) {
for (data = set->font[i]; data != 0; data = next) {
next = data->next;
- font_close(data);
+ font_lose_font((font_f)(data->handle));
+ free(data);
}
}
@@ -186,14 +159,99 @@ void font_free_set(struct font_set *set)
}
-void font_close(struct font_data *data)
+/**
+ * Find the width of some text in a font.
+ *
+ * \param font a font_data, as returned by font_open()
+ * \param text string to measure
+ * \param length length of text
+ * \return width of text in pixels
+ */
+
+unsigned long font_width(struct font_data *font, const char * text, unsigned int length)
+{
+ int width;
+ os_error * error;
+
+ assert(font != 0 && text != 0);
+
+ if (length == 0)
+ return 0;
+
+ error = xfont_scan_string((font_f)(font->handle), text,
+ font_GIVEN_FONT | font_KERN | font_GIVEN_LENGTH,
+ 0x7fffffff, 0x7fffffff,
+ 0,
+ 0, (int)length,
+ 0, &width, 0, 0);
+ if (error != 0) {
+ fprintf(stderr, "%s\n", error->errmess);
+ die("font_width: font_scan_string failed");
+ }
+
+ return width / 800;
+}
+
+
+/**
+ * Find where in a string a x coordinate falls.
+ *
+ * For example, used to find where to position the caret in response to mouse
+ * click.
+ *
+ * \param text a string
+ * \param font a font_data, as returned by font_open()
+ * \param length length of text
+ * \param x horizontal position in pixels
+ * \param char_offset updated to give the offset in the string
+ * \param pixel_offset updated to give the coordinate of the character in pixels
+ */
+
+void font_position_in_string(const char *text, struct font_data *font,
+ unsigned int length, unsigned long x,
+ int *char_offset, int *pixel_offset)
{
- font_lose_font((font_f)(data->handle));
+ font_scan_block block;
+ char *split_point;
+ int x_out, y_out, length_out;
+ os_error *error;
+
+ assert(font != 0 && text != 0);
- free(data);
+ block.space.x = block.space.y = 0;
+ block.letter.x = block.letter.y = 0;
+ block.split_char = -1;
+
+ error = xfont_scan_string((font_f)(font->handle), text,
+ font_GIVEN_BLOCK | font_GIVEN_FONT | font_KERN |
+ font_RETURN_CARET_POS | font_GIVEN_LENGTH,
+ x * 2 * 400,
+ 0x7fffffff,
+ &block, 0, (int)length,
+ &split_point, &x_out, &y_out, &length_out);
+ if (error) {
+ fprintf(stderr, "%s\n", error->errmess);
+ die("font_width: font_scan_string failed");
+ }
+
+ *char_offset = (int)(split_point - text);
+ *pixel_offset = x_out / 2 / 400;
}
+/**
+ * Find where to split a string to fit in a width.
+ *
+ * For example, used when wrapping paragraphs.
+ *
+ * \param data a font_data, as returned by font_open()
+ * \param text string to split
+ * \param length length of text
+ * \param width available width
+ * \param used_width updated to actual width used
+ * \return pointer to character which does not fit
+ */
+
char * font_split(struct font_data *data, const char * text, unsigned int length,
unsigned int width, unsigned int *used_width)
{
@@ -206,7 +264,7 @@ char * font_split(struct font_data *data, const char * text, unsigned int length
error = xfont_scan_string((font_f)(data->handle), text,
font_GIVEN_BLOCK | font_GIVEN_FONT | font_KERN | font_GIVEN_LENGTH,
- ro_x_units(width) * 400, 0x7fffffff,
+ width * 2 * 400, 0x7fffffff,
&block,
0,
(int)length,
@@ -217,8 +275,35 @@ char * font_split(struct font_data *data, const char * text, unsigned int length
die("font_split: font_scan_string failed");
}
- *used_width = browser_x_units((int)(*used_width / 400));
+ *used_width = *used_width / 2 / 400;
return split;
}
+
+#ifdef TEST
+
+int main(void)
+{
+ unsigned int i;
+ struct font_set *set;
+ struct css_style style;
+
+ style.font_size.size = CSS_FONT_SIZE_LENGTH;
+ style.font_weight = CSS_FONT_WEIGHT_BOLD;
+ style.font_style = CSS_FONT_STYLE_ITALIC;
+
+ set = font_new_set();
+
+ for (i = 10; i != 100; i += 10) {
+ style.font_size.value.length.value = i;
+ font_open(set, &style);
+ }
+
+ font_free_set(set);
+
+ return 0;
+}
+
+#endif
+