summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2009-07-21 10:59:53 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2009-07-21 10:59:53 +0000
commit2565a37a52a5c714e7c6bbd1808db0d6d37c6ea3 (patch)
treef3fe5f224c9e0e4089aca2d9012dfe1a74cf9c90 /render
parent1930989f8ccdd574472ed72990b6a82fdcf9d5f4 (diff)
downloadnetsurf-2565a37a52a5c714e7c6bbd1808db0d6d37c6ea3.tar.gz
netsurf-2565a37a52a5c714e7c6bbd1808db0d6d37c6ea3.tar.bz2
Refactor text plotter and other font functions to remove dependency on CSS.
svn path=/trunk/netsurf/; revision=8641
Diffstat (limited to 'render')
-rw-r--r--render/font.c150
-rw-r--r--render/font.h14
-rw-r--r--render/html.h5
-rw-r--r--render/html_redraw.c63
-rw-r--r--render/layout.c51
-rw-r--r--render/loosen.c6
-rw-r--r--render/textplain.c47
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;
+}
+