diff options
Diffstat (limited to 'render')
-rw-r--r-- | render/font.c | 150 | ||||
-rw-r--r-- | render/font.h | 14 | ||||
-rw-r--r-- | render/html.h | 5 | ||||
-rw-r--r-- | render/html_redraw.c | 63 | ||||
-rw-r--r-- | render/layout.c | 51 | ||||
-rw-r--r-- | render/loosen.c | 6 | ||||
-rw-r--r-- | render/textplain.c | 47 |
7 files changed, 266 insertions, 70 deletions
diff --git a/render/font.c b/render/font.c new file mode 100644 index 000000000..089fcff5a --- /dev/null +++ b/render/font.c @@ -0,0 +1,150 @@ +/* + * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "css/css.h" +#include "render/font.h" + +static plot_font_generic_family_t plot_font_generic_family( + css_font_family css); +static int plot_font_weight(css_font_weight css); +static plot_font_flags_t plot_font_flags(css_font_style style, + css_font_variant variant); + +/** + * Populate a font style using data from a computed CSS style + * + * \param css Computed style to consider + * \param fstyle Font style to populate + */ +void font_plot_style_from_css(const struct css_style *css, + plot_font_style_t *fstyle) +{ + fstyle->family = plot_font_generic_family(css->font_family); + fstyle->size = css_len2pt(&css->font_size.value.length, css); + fstyle->weight = plot_font_weight(css->font_weight); + fstyle->flags = plot_font_flags(css->font_style, css->font_variant); + fstyle->foreground = css->color; + fstyle->background = 0; +} + +/****************************************************************************** + * Helper functions * + ******************************************************************************/ + +/** + * Map a generic CSS font family to a generic plot font family + * + * \param css Generic CSS font family + * \return Plot font family + */ +plot_font_generic_family_t plot_font_generic_family( + css_font_family css) +{ + plot_font_generic_family_t plot; + + switch (css) { + case CSS_FONT_FAMILY_SERIF: + plot = PLOT_FONT_FAMILY_SERIF; + break; + case CSS_FONT_FAMILY_MONOSPACE: + plot = PLOT_FONT_FAMILY_MONOSPACE; + break; + case CSS_FONT_FAMILY_CURSIVE: + plot = PLOT_FONT_FAMILY_CURSIVE; + break; + case CSS_FONT_FAMILY_FANTASY: + plot = PLOT_FONT_FAMILY_FANTASY; + break; + case CSS_FONT_FAMILY_SANS_SERIF: + default: + plot = PLOT_FONT_FAMILY_SANS_SERIF; + break; + } + + return plot; +} + +/** + * Map a CSS font weight to a plot weight value + * + * \param css CSS font weight + * \return Plot weight + */ +int plot_font_weight(css_font_weight css) +{ + int weight; + + switch (css) { + case CSS_FONT_WEIGHT_100: + weight = 100; + break; + case CSS_FONT_WEIGHT_200: + weight = 200; + break; + case CSS_FONT_WEIGHT_300: + weight = 300; + break; + case CSS_FONT_WEIGHT_400: + case CSS_FONT_WEIGHT_NORMAL: + default: + weight = 400; + break; + case CSS_FONT_WEIGHT_500: + weight = 500; + break; + case CSS_FONT_WEIGHT_600: + weight = 600; + break; + case CSS_FONT_WEIGHT_700: + case CSS_FONT_WEIGHT_BOLD: + weight = 700; + break; + case CSS_FONT_WEIGHT_800: + weight = 800; + break; + case CSS_FONT_WEIGHT_900: + weight = 900; + break; + } + + return weight; +} + +/** + * Map a CSS font style and font variant to plot font flags + * + * \param style CSS font style + * \param variant CSS font variant + * \return Computed plot flags + */ +plot_font_flags_t plot_font_flags(css_font_style style, + css_font_variant variant) +{ + plot_font_flags_t flags = FONTF_NONE; + + if (style == CSS_FONT_STYLE_ITALIC) + flags |= FONTF_ITALIC; + else if (style == CSS_FONT_STYLE_OBLIQUE) + flags |= FONTF_OBLIQUE; + + if (variant == CSS_FONT_VARIANT_SMALL_CAPS) + flags |= FONTF_SMALLCAPS; + + return flags; +} + diff --git a/render/font.h b/render/font.h index acfd7c727..9a80af329 100644 --- a/render/font.h +++ b/render/font.h @@ -35,23 +35,25 @@ #include <stdbool.h> #include <stddef.h> - -struct css_style; - +#include "css/css.h" +#include "desktop/plot_style.h" struct font_functions { - bool (*font_width)(const struct css_style *style, + bool (*font_width)(const plot_font_style_t *fstyle, const char *string, size_t length, int *width); - bool (*font_position_in_string)(const struct css_style *style, + bool (*font_position_in_string)(const plot_font_style_t *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x); - bool (*font_split)(const struct css_style *style, + bool (*font_split)(const plot_font_style_t *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x); }; extern const struct font_functions nsfont; +void font_plot_style_from_css(const struct css_style *css, + plot_font_style_t *fstyle); + #endif diff --git a/render/html.h b/render/html.h index f1ab9d86d..e6c322e14 100644 --- a/render/html.h +++ b/render/html.h @@ -28,6 +28,7 @@ #include <stdbool.h> #include "content/content_type.h" #include "css/css.h" +#include "desktop/plot_style.h" #include "render/parser_binding.h" struct box; @@ -197,11 +198,11 @@ bool html_redraw(struct content *c, int x, int y, bool text_redraw(const char *utf8_text, size_t utf8_len, size_t offset, bool space, - struct css_style *style, + const plot_font_style_t *fstyle, int x, int y, struct rect *clip, int height, - float scale, colour current_background_color, + float scale, bool excluded); #endif diff --git a/render/html_redraw.c b/render/html_redraw.c index 0fc10cb6c..64fc6066b 100644 --- a/render/html_redraw.c +++ b/render/html_redraw.c @@ -747,6 +747,10 @@ bool html_redraw_text_box(struct box *box, int x, int y, { bool excluded = (box->object != NULL); struct rect clip; + plot_font_style_t fstyle; + + font_plot_style_from_css(box->style, &fstyle); + fstyle.background = current_background_color; clip.x0 = x0; clip.y0 = y0; @@ -754,9 +758,8 @@ bool html_redraw_text_box(struct box *box, int x, int y, clip.y1 = y1; if (!text_redraw(box->text, box->length, box->byte_offset, - box->space, box->style, x, y, - &clip, box->height, scale, - current_background_color, excluded)) + box->space, &fstyle, x, y, + &clip, box->height, scale, excluded)) return false; /* does this textbox contain the ghost caret? */ @@ -769,7 +772,6 @@ bool html_redraw_text_box(struct box *box, int x, int y, return true; } - /** * Redraw a short text string, complete with highlighting * (for selection/search) and ghost caret @@ -778,22 +780,21 @@ bool html_redraw_text_box(struct box *box, int x, int y, * \param utf8_len length of string, in bytes * \param offset byte offset within textual representation * \param space indicates whether string is followed by a space - * \param style text style to use + * \param fstyle text style to use * \param x x ordinate at which to plot text * \param y y ordinate at which to plot text * \param clip pointer to current clip rectangle * \param height height of text string * \param scale current display scale (1.0 = 100%) - * \param current_background_color * \param excluded exclude this text string from the selection * \return true iff successful and redraw should proceed */ bool text_redraw(const char *utf8_text, size_t utf8_len, - size_t offset, bool space, struct css_style *style, + size_t offset, bool space, const plot_font_style_t *fstyle, int x, int y, struct rect *clip, int height, - float scale, colour current_background_color, + float scale, bool excluded) { bool highlighted = false; @@ -828,6 +829,7 @@ bool text_redraw(const char *utf8_text, size_t utf8_len, bool text_visible = true; int startx, endx; plot_style_t *pstyle_fill_hback = plot_style_fill_white; + plot_font_style_t fstyle_hback = *fstyle; if (end_idx > utf8_len) { /* adjust for trailing space, not present in @@ -836,11 +838,11 @@ bool text_redraw(const char *utf8_text, size_t utf8_len, endtxt_idx = utf8_len; } - if (!nsfont.font_width(style, utf8_text, start_idx, + if (!nsfont.font_width(fstyle, utf8_text, start_idx, &startx)) startx = 0; - if (!nsfont.font_width(style, utf8_text, endtxt_idx, + if (!nsfont.font_width(fstyle, utf8_text, endtxt_idx, &endx)) endx = 0; @@ -850,7 +852,7 @@ bool text_redraw(const char *utf8_text, size_t utf8_len, int spc_width; /* \todo is there a more elegant/efficient * solution? */ - if (nsfont.font_width(style, " ", 1, + if (nsfont.font_width(fstyle, " ", 1, &spc_width)) endx += spc_width; } @@ -863,15 +865,13 @@ bool text_redraw(const char *utf8_text, size_t utf8_len, /* draw any text preceding highlighted portion */ if (start_idx > 0 && !plot.text(x, y + (int) (height * 0.75 * scale), - style, utf8_text, start_idx, - current_background_color, - /*print_text_black ? 0 :*/ - style->color)) + utf8_text, start_idx, + fstyle)) return false; /* decide whether highlighted portion is to be * white-on-black or black-on-white */ - if ((current_background_color & 0x808080) == 0x808080) + if ((fstyle->background & 0x808080) == 0x808080) pstyle_fill_hback = plot_style_fill_black; /* highlighted portion */ @@ -894,11 +894,15 @@ bool text_redraw(const char *utf8_text, size_t utf8_len, } } + fstyle_hback.background = + pstyle_fill_hback->fill_colour ^ 0xffffff; + fstyle_hback.foreground = + pstyle_fill_hback->fill_colour; + if (text_visible && !plot.text(x, y + (int) (height * 0.75 * scale), - style, utf8_text, endtxt_idx, - pstyle_fill_hback->fill_colour, - pstyle_fill_hback->fill_colour ^ 0xffffff)) + utf8_text, endtxt_idx, + &fstyle_hback)) return false; /* draw any text succeeding highlighted portion */ @@ -914,10 +918,8 @@ bool text_redraw(const char *utf8_text, size_t utf8_len, if (!plot.text(x, y + (int) (height * 0.75 * scale), - style, utf8_text, utf8_len, - current_background_color, - /*print_text_black ? 0 :*/ - style->color)) + utf8_text, utf8_len, + fstyle)) return false; } } @@ -931,9 +933,8 @@ bool text_redraw(const char *utf8_text, size_t utf8_len, if (!highlighted) { if (!plot.text(x, y + (int) (height * 0.75 * scale), - style, utf8_text, utf8_len, - current_background_color, - /*print_text_black ? 0 :*/ style->color)) + utf8_text, utf8_len, + fstyle)) return false; } return true; @@ -1396,6 +1397,10 @@ bool html_redraw_file(int x, int y, int width, int height, int text_width; const char *text; size_t length; + plot_font_style_t fstyle; + + font_plot_style_from_css(box->style, &fstyle); + fstyle.background = background_colour; if (box->gadget->value) text = box->gadget->value; @@ -1403,7 +1408,7 @@ bool html_redraw_file(int x, int y, int width, int height, text = messages_get("Form_Drop"); length = strlen(text); - if (!nsfont.font_width(box->style, text, length, &text_width)) + if (!nsfont.font_width(&fstyle, text, length, &text_width)) return false; text_width *= scale; if (width < text_width + 8) @@ -1411,9 +1416,7 @@ bool html_redraw_file(int x, int y, int width, int height, else x = x + 4; - return plot.text(x, y + height * 0.75, box->style, text, length, - background_colour, - /*print_text_black ? 0 :*/ box->style->color); + return plot.text(x, y + height * 0.75, text, length, &fstyle); } diff --git a/render/layout.c b/render/layout.c index 96a9b6168..5bf03a157 100644 --- a/render/layout.c +++ b/render/layout.c @@ -1668,6 +1668,7 @@ bool layout_line(struct box *first, int *width, int *y, unsigned int i; struct css_length gadget_size; /* Checkbox / radio buttons */ const struct font_functions *font_func = content->data.html.font_func; + plot_font_style_t fstyle; gadget_size.unit = CSS_UNIT_EM; gadget_size.value = 1; @@ -1722,6 +1723,9 @@ bool layout_line(struct box *first, int *width, int *y, b->style->position == CSS_POSITION_FIXED)) continue; + assert(b->style != NULL); + font_plot_style_from_css(b->style, &fstyle); + x += space_after; if (b->type == BOX_INLINE_BLOCK) { @@ -1763,7 +1767,7 @@ bool layout_line(struct box *first, int *width, int *y, b->width = 0; if (b->space) { /** \todo optimize out */ - font_func->font_width(b->style, " ", 1, + font_func->font_width(&fstyle, " ", 1, &space_after); } else { space_after = 0; @@ -1801,7 +1805,7 @@ bool layout_line(struct box *first, int *width, int *y, data.select.items; o; o = o->next) { int opt_width; - font_func->font_width(b->style, + font_func->font_width(&fstyle, o->text, strlen(o->text), &opt_width); @@ -1812,7 +1816,7 @@ bool layout_line(struct box *first, int *width, int *y, b->width = opt_maxwidth; } else { - font_func->font_width(b->style, b->text, + font_func->font_width(&fstyle, b->text, b->length, &b->width); } } @@ -1820,7 +1824,7 @@ bool layout_line(struct box *first, int *width, int *y, x += b->width; if (b->space) /** \todo optimize out */ - font_func->font_width(b->style, " ", 1, + font_func->font_width(&fstyle, " ", 1, &space_after); else space_after = 0; @@ -1957,10 +1961,13 @@ bool layout_line(struct box *first, int *width, int *y, space_after = 0; else if (b->text || b->type == BOX_INLINE_END) { space_after = 0; - if (b->space) + if (b->space) { + font_plot_style_from_css(b->style, + &fstyle); /** \todo handle errors, optimize */ - font_func->font_width(b->style, " ", 1, + font_func->font_width(&fstyle, " ", 1, &space_after); + } } else space_after = 0; split_box = b; @@ -2099,10 +2106,12 @@ bool layout_line(struct box *first, int *width, int *y, if (space == 0) w = split_box->width; - else + else { + font_plot_style_from_css(split_box->style, &fstyle); /** \todo handle errors */ - font_func->font_width(split_box->style, split_box->text, + font_func->font_width(&fstyle, split_box->text, space, &w); + } LOG(("splitting: split_box %p \"%.*s\", space %zu, w %i, " "left %p, right %p, inline_count %u", @@ -2171,8 +2180,9 @@ bool layout_line(struct box *first, int *width, int *y, } else { /* fit as many words as possible */ assert(space != 0); + font_plot_style_from_css(split_box->style, &fstyle); /** \todo handle errors */ - font_func->font_split(split_box->style, + font_func->font_split(&fstyle, split_box->text, split_box->length, x1 - x0 - x - space_before, &space, &w); LOG(("'%.*s' %i %zu %i", (int) split_box->length, @@ -2294,6 +2304,8 @@ struct box *layout_minmax_line(struct box *first, size_t i, j; struct box *b; struct css_length gadget_size; /* Checkbox / radio buttons */ + plot_font_style_t fstyle; + gadget_size.unit = CSS_UNIT_EM; gadget_size.value = 1; @@ -2334,6 +2346,9 @@ struct box *layout_minmax_line(struct box *first, continue; } + assert(b->style); + font_plot_style_from_css(b->style, &fstyle); + if (b->type == BOX_INLINE && !b->object) { fixed = frac = 0; calculate_mbp_width(b->style, LEFT, true, true, true, @@ -2353,7 +2368,7 @@ struct box *layout_minmax_line(struct box *first, if (0 < fixed) max += fixed; if (b->next && b->space) { - font_func->font_width(b->style, " ", 1, &width); + font_func->font_width(&fstyle, " ", 1, &width); max += width; } continue; @@ -2379,7 +2394,7 @@ struct box *layout_minmax_line(struct box *first, data.select.items; o; o = o->next) { int opt_width; - font_func->font_width(b->style, + font_func->font_width(&fstyle, o->text, strlen(o->text), &opt_width); @@ -2390,13 +2405,13 @@ struct box *layout_minmax_line(struct box *first, b->width = opt_maxwidth; } else { - font_func->font_width(b->style, b->text, + font_func->font_width(&fstyle, b->text, b->length, &b->width); } } max += b->width; if (b->next && b->space) { - font_func->font_width(b->style, " ", 1, &width); + font_func->font_width(&fstyle, " ", 1, &width); max += width; } @@ -2406,7 +2421,7 @@ struct box *layout_minmax_line(struct box *first, for (j = i; j != b->length && b->text[j] != ' '; j++) ; - font_func->font_width(b->style, b->text + i, + font_func->font_width(&fstyle, b->text + i, j - i, &width); if (min < width) min = width; @@ -3327,6 +3342,7 @@ void layout_lists(struct box *box, { struct box *child; struct box *marker; + plot_font_style_t fstyle; for (child = box->children; child; child = child->next) { if (child->list_marker) { @@ -3338,11 +3354,14 @@ void layout_lists(struct box *box, marker->y = (line_height(marker->style) - marker->height) / 2; } else if (marker->text) { - if (marker->width == UNKNOWN_WIDTH) - font_func->font_width(marker->style, + if (marker->width == UNKNOWN_WIDTH) { + font_plot_style_from_css(marker->style, + &fstyle); + font_func->font_width(&fstyle, marker->text, marker->length, &marker->width); + } marker->x = -marker->width; marker->y = 0; marker->height = line_height(marker->style); diff --git a/render/loosen.c b/render/loosen.c index 80f64bdcb..85136d89b 100644 --- a/render/loosen.c +++ b/render/loosen.c @@ -115,6 +115,10 @@ bool loosen_text(struct box *text, int width, struct content *content) unsigned int position; const struct font_functions *font_func; + plot_font_style_t fstyle; + + font_plot_style_from_css(text->style, &fstyle); + if (content->type == CONTENT_HTML) font_func = content->data.html.font_func; else @@ -134,7 +138,7 @@ bool loosen_text(struct box *text, int width, struct content *content) position = 0; while (position < text->length) { - font_func->font_position_in_string(text->style, + font_func->font_position_in_string(&fstyle, text->text + position, text->length - position, width, &offset, &actual_x); diff --git a/render/textplain.c b/render/textplain.c index c1ee1cf43..dd3d168f9 100644 --- a/render/textplain.c +++ b/render/textplain.c @@ -49,11 +49,20 @@ #define TAB_WIDTH 8 /* must be power of 2 currently */ -static struct css_style textplain_style; +static plot_font_style_t textplain_style = { + .family = PLOT_FONT_FAMILY_MONOSPACE, + .size = 10, + .weight = 400, + .flags = FONTF_NONE, + .background = 0xffffff, + .foreground = 0x000000, +}; + static int textplain_tab_width = 256; /* try for a sensible default */ static int textplain_coord_from_offset(const char *text, size_t offset, size_t length); +static float textplain_line_height(void); /** @@ -68,9 +77,6 @@ bool textplain_create(struct content *c, const char *params[]) iconv_t iconv_cd; union content_msg_data msg_data; - textplain_style = css_base_style; - textplain_style.font_family = CSS_FONT_FAMILY_MONOSPACE; - utf8_data = talloc_array(c, char, CHUNK); if (!utf8_data) goto no_memory; @@ -281,9 +287,7 @@ void textplain_reformat(struct content *c, int width, int height) c->data.textplain.physical_line_count = line_count; c->width = width; - c->height = line_count * - css_len2px(&textplain_style.font_size.value.length, - &textplain_style) * 1.2 + MARGIN + MARGIN; + c->height = line_count * textplain_line_height() + MARGIN + MARGIN; return; @@ -332,8 +336,7 @@ bool textplain_redraw(struct content *c, int x, int y, char *utf8_data = c->data.textplain.utf8_data; long lineno; unsigned long line_count = c->data.textplain.physical_line_count; - float line_height = css_len2px(&textplain_style.font_size.value.length, - &textplain_style) * 1.2; + float line_height = textplain_line_height(); float scaled_line_height = line_height * scale; long line0 = clip_y0 / scaled_line_height - 1; long line1 = clip_y1 / scaled_line_height + 1; @@ -370,6 +373,9 @@ bool textplain_redraw(struct content *c, int x, int y, else plot_style_highlight = plot_style_fill_white; + /* Set background colour to plot with */ + textplain_style.background = background_colour; + x += MARGIN * scale; y += MARGIN * scale; for (lineno = line0; lineno != line1; lineno++) { @@ -396,8 +402,7 @@ bool textplain_redraw(struct content *c, int x, int y, line[lineno].start + offset, false, &textplain_style, tx, y + (lineno * scaled_line_height), - &clip, line_height, scale, - background_colour, false)) + &clip, line_height, scale, false)) return false; if (next_offset >= length) @@ -468,8 +473,7 @@ bool textplain_redraw(struct content *c, int x, int y, size_t textplain_offset_from_coords(struct content *c, int x, int y, int dir) { - float line_height = css_len2px(&textplain_style.font_size.value.length, - &textplain_style) * 1.2; + float line_height = textplain_line_height(); struct textplain_line *line; const char *text; unsigned nlines; @@ -618,8 +622,7 @@ int textplain_coord_from_offset(const char *text, size_t offset, size_t length) void textplain_coords_from_range(struct content *c, unsigned start, unsigned end, struct rect *r) { - float line_height = css_len2px(&textplain_style.font_size.value.length, - &textplain_style) * 1.2; + float line_height = textplain_line_height(); char *utf8_data = c->data.textplain.utf8_data; struct textplain_line *line; unsigned lineno = 0; @@ -719,3 +722,17 @@ char *textplain_get_raw_data(struct content *c, unsigned start, unsigned end, return c->data.textplain.utf8_data + start; } + +/** + * Calculate the line height, in pixels + * + * \return Line height, in pixels + */ +float textplain_line_height(void) +{ + /* Size is in points, so convert to pixels. + * Then use a constant line height of 1.2 x font size. + */ + return (textplain_style.size * css_screen_dpi / 72) * 1.2; +} + |