summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mupdf/html.h10
-rw-r--r--source/html/css-apply.c33
-rw-r--r--source/html/font.c52
-rw-r--r--source/html/layout.c106
4 files changed, 125 insertions, 76 deletions
diff --git a/include/mupdf/html.h b/include/mupdf/html.h
index 87640c3a..f5afafe5 100644
--- a/include/mupdf/html.h
+++ b/include/mupdf/html.h
@@ -11,6 +11,7 @@ struct html_document_s
fz_document super;
fz_context *ctx;
fz_xml *xml;
+ fz_font *fonts[16];
struct box *box;
};
@@ -123,13 +124,16 @@ struct computed_style
int text_align;
int vertical_align;
struct number line_height;
- const char *font_family;
- int bold, italic, smallcaps;
+ fz_font *font;
};
void apply_styles(fz_context *ctx, struct style *style, struct rule *rule, fz_xml *node);
void default_computed_style(struct computed_style *cstyle);
-void compute_style(struct computed_style *cstyle, struct style *style);
+void compute_style(html_document *doc, struct computed_style *cstyle, struct style *style);
float from_number(struct number, float em, float width);
+float from_number_scale(struct number number, float scale, float em, float width);
+
+fz_font *html_load_font(html_document *doc,
+ const char *family, const char *variant, const char *style, const char *weight);
#endif
diff --git a/source/html/css-apply.c b/source/html/css-apply.c
index 325b0dab..63a4941c 100644
--- a/source/html/css-apply.c
+++ b/source/html/css-apply.c
@@ -767,6 +767,17 @@ from_number(struct number number, float em, float width)
}
}
+float
+from_number_scale(struct number number, float scale, float em, float width)
+{
+ switch (number.unit) {
+ default:
+ case N_NUMBER: return number.value * scale;
+ case N_SCALE: return number.value * em;
+ case N_PERCENT: return number.value * 0.01 * width;
+ }
+}
+
int
get_style_property_display(struct style *node)
{
@@ -811,7 +822,7 @@ default_computed_style(struct computed_style *style)
}
void
-compute_style(struct computed_style *style, struct style *node)
+compute_style(html_document *doc, struct computed_style *style, struct style *node)
{
struct value *value;
@@ -879,20 +890,7 @@ compute_style(struct computed_style *style, struct style *node)
const char *font_variant = get_style_property_string(node, "font-variant", "normal");
const char *font_style = get_style_property_string(node, "font-style", "normal");
const char *font_weight = get_style_property_string(node, "font-weight", "normal");
-
- style->font_family = font_family;
-
- style->smallcaps = 0;
- if (!strcmp(font_variant, "small-caps"))
- style->smallcaps = 1;
-
- style->italic = 0;
- if (!strcmp(font_style, "italic") || !strcmp(font_style, "oblique"))
- style->italic = 1;
-
- style->bold = 0;
- if (!strcmp(font_weight, "bold") || !strcmp(font_weight, "bolder") || atoi(font_weight) > 400)
- style->bold = 1;
+ style->font = html_load_font(doc, font_family, font_variant, font_style, font_weight);
}
}
@@ -901,10 +899,7 @@ print_style(struct computed_style *style)
{
printf("style {\n");
printf("\tfont-size = %g%c;\n", style->font_size.value, style->font_size.unit);
- printf("\tfont = %s", style->font_family);
- printf(" %s", style->bold ? "bold" : "normal");
- printf(" %s", style->italic ? "italic" : "normal");
- printf(" %s;\n", style->smallcaps ? "small-caps" : "normal");
+ printf("\tfont = %s;\n", style->font->name);
printf("\tline-height = %g%c;\n", style->line_height.value, style->line_height.unit);
printf("\ttext-indent = %g%c;\n", style->text_indent.value, style->text_indent.unit);
printf("\ttext-align = %d;\n", style->text_align);
diff --git a/source/html/font.c b/source/html/font.c
index 102bb8df..9c408367 100644
--- a/source/html/font.c
+++ b/source/html/font.c
@@ -1,40 +1,36 @@
#include "mupdf/html.h"
-#include "mupdf/pdf.h" /* for pdf_lookup_substitute_font */
+#include "mupdf/pdf.h" /* for pdf_lookup_builtin_font */
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-static int ft_is_bold(FT_Face face)
-{
- return face->style_flags & FT_STYLE_FLAG_BOLD;
-}
-
-static int ft_is_italic(FT_Face face)
-{
- return face->style_flags & FT_STYLE_FLAG_ITALIC;
-}
+static const char *font_names[16] = {
+ "Times-Roman", "Times-Italic", "Times-Bold", "Times-BoldItalic",
+ "Helvetica", "Helvetica-Oblique", "Helvetica-Bold", "Helvetica-BoldOblique",
+ "Courier", "Courier-Oblique", "Courier-Bold", "Courier-BoldOblique",
+ "Courier", "Courier-Oblique", "Courier-Bold", "Courier-BoldOblique",
+};
fz_font *
-html_load_font(fz_context *ctx,
+html_load_font(html_document *doc,
const char *family, const char *variant, const char *style, const char *weight)
{
+ fz_context *ctx = doc->ctx;
unsigned char *data;
unsigned int size;
- fz_font *font;
-
- int is_bold = !strcmp(weight, "bold");
- int is_italic = !strcmp(style, "italic");
int is_mono = !strcmp(family, "monospace");
int is_sans = !strcmp(family, "sans-serif");
-
- // TODO: keep a cache of loaded fonts
-
- data = pdf_lookup_substitute_font(is_mono, !is_sans, is_bold, is_italic, &size);
-
- font = fz_new_font_from_memory(ctx, family, data, size, 0, 1);
- font->ft_bold = is_bold && !ft_is_bold(font->ft_face);
- font->ft_italic = is_italic && !ft_is_italic(font->ft_face);
-
- return font;
+ int is_bold = !strcmp(weight, "bold") || !strcmp(weight, "bolder") || atoi(weight) > 400;
+ int is_italic = !strcmp(style, "italic") || !strcmp(style, "oblique");
+
+ int idx = is_mono * 8 + is_sans * 4 + is_bold * 2 + is_italic;
+ if (!doc->fonts[idx])
+ {
+ data = pdf_lookup_builtin_font(font_names[idx], &size);
+ if (!data) {
+ printf("data=%p idx=%d s=%s\n", data, idx, font_names[idx]);
+ abort();
+ }
+ doc->fonts[idx] = fz_new_font_from_memory(ctx, font_names[idx], data, size, 0, 1);
+ }
+
+ return doc->fonts[idx];
}
diff --git a/source/html/layout.c b/source/html/layout.c
index 6d9753ba..d07b2dab 100644
--- a/source/html/layout.c
+++ b/source/html/layout.c
@@ -30,8 +30,6 @@ static const char *default_css =
"center{text-align:center}"
"svg{display:none}";
-static fz_font *font = NULL;
-
enum
{
BOX_BLOCK, /* block-level: contains block and flow boxes */
@@ -218,8 +216,9 @@ static void insert_inline_box(fz_context *ctx, struct box *box, struct box *top)
}
}
-static void generate_boxes(fz_context *ctx, fz_xml *node, struct box *top, struct rule *rule, struct style *up_style)
+static void generate_boxes(html_document *doc, fz_xml *node, struct box *top, struct rule *rule, struct style *up_style)
{
+ fz_context *ctx = doc->ctx;
struct style style;
struct box *box;
int display;
@@ -257,7 +256,7 @@ static void generate_boxes(fz_context *ctx, fz_xml *node, struct box *top, struc
}
if (fz_xml_down(node))
- generate_boxes(ctx, fz_xml_down(node), box, rule, &style);
+ generate_boxes(doc, fz_xml_down(node), box, rule, &style);
// TODO: remove empty flow boxes
}
@@ -268,60 +267,117 @@ static void generate_boxes(fz_context *ctx, fz_xml *node, struct box *top, struc
generate_text(ctx, box, fz_xml_text(node));
}
- compute_style(&box->style, &style);
+ compute_style(doc, &box->style, &style);
node = fz_xml_next(node);
}
}
-static void layout_text(fz_context *ctx, struct flow *node, struct box *top, float em)
+static void measure_word(fz_context *ctx, struct flow *node, float em)
{
const char *s;
int c, g;
float w;
em = from_number(node->style->font_size, em, em);
- node->x = top->x + top->w;
- node->y = top->y;
- node->h = em;
+ node->x = 0;
+ node->y = 0;
+ node->h = from_number_scale(node->style->line_height, em, em, em);
w = 0;
s = node->text;
while (*s)
{
s += fz_chartorune(&c, s);
- g = fz_encode_character(ctx, font, c);
- w += fz_advance_glyph(ctx, font, g) * em;
+ g = fz_encode_character(ctx, node->style->font, c);
+ w += fz_advance_glyph(ctx, node->style->font, g) * em;
}
node->w = w;
node->em = em;
}
+static float layout_line(fz_context *ctx, float indent, struct flow *node, struct flow *end, struct box *box)
+{
+ float x = box->x + indent;
+ float y = box->y + box->h;
+ float h = 0;
+
+ while (node != end)
+ {
+ node->x = x;
+ node->y = y;
+ x += node->w;
+ if (node->h > h)
+ h = node->h;
+ node = node->next;
+ }
+
+ return h;
+}
+
static void layout_flow(fz_context *ctx, struct box *box, struct box *top, float em)
{
- struct flow *node;
+ struct flow *node, *first_word, *last_glue;
+ float line_w, line_h;
+ float indent;
em = from_number(box->style.font_size, em, em);
+ indent = from_number(top->style.text_indent, em, top->w);
+
box->x = top->x;
box->y = top->y + top->h;
- box->h = 0;
box->w = 0;
+ box->h = 0;
+ first_word = box->flow_head;
+ last_glue = NULL;
+ line_w = indent;
for (node = box->flow_head; node; node = node->next)
{
- layout_text(ctx, node, box, em);
- if (node->h > box->h)
- box->h = node->h;
- box->w += node->w;
+ if (node->type == FLOW_GLUE)
+ last_glue = node;
+
+ measure_word(ctx, node, em);
+ if (last_glue && line_w + node->w > top->w)
+ {
+ line_h = layout_line(ctx, indent, first_word, last_glue, box);
+ if (line_w > box->w)
+ box->w = line_w;
+ box->h += line_h;
+
+ if (node == last_glue && node->next)
+ {
+ node = node->next;
+ measure_word(ctx, node, em);
+ }
+
+ first_word = node;
+ last_glue = NULL;
+ line_w = node->w;
+ indent = 0;
+ }
+ else if (line_w + node->w > top->w)
+ {
+ printf("WARNING: line overflow! (%s)\n", node->text);
+ line_w += node->w;
+ }
+ else
+ {
+ line_w += node->w;
+ }
}
+
+ line_h = layout_line(ctx, indent, first_word, NULL, box);
+ if (line_w > box->w)
+ box->w = line_w;
+ box->h += line_h;
}
static void layout_block(fz_context *ctx, struct box *box, struct box *top, float em, float top_collapse_margin)
{
struct box *child;
float box_collapse_margin;
- float bottom;
em = from_number(box->style.font_size, em, em);
@@ -422,8 +478,8 @@ static void print_box(fz_context *ctx, struct box *box, int level)
printf("\n");
if (box->down)
print_box(ctx, box->down, level + 1);
- if (box->flow_head)
- print_flow(ctx, box->flow_head, level + 1);
+// if (box->flow_head)
+// print_flow(ctx, box->flow_head, level + 1);
box = box->next;
}
}
@@ -446,7 +502,7 @@ draw_flow_box(fz_context *ctx, struct box *box, fz_device *dev, const fz_matrix
if (node->type == FLOW_WORD)
{
fz_scale(&trm, node->em, -node->em);
- text = fz_new_text(ctx, font, &trm, 0);
+ text = fz_new_text(ctx, node->style->font, &trm, 0);
x = node->x;
y = node->y + node->em * 0.8;
@@ -454,9 +510,9 @@ draw_flow_box(fz_context *ctx, struct box *box, fz_device *dev, const fz_matrix
while (*s)
{
s += fz_chartorune(&c, s);
- g = fz_encode_character(ctx, font, c);
+ g = fz_encode_character(ctx, node->style->font, c);
fz_add_text(ctx, text, g, c, x, y);
- x += fz_advance_glyph(ctx, font, g) * node->em;
+ x += fz_advance_glyph(ctx, node->style->font, g) * node->em;
}
fz_fill_text(dev, text, ctm, fz_device_gray(ctx), black, 1);
@@ -586,8 +642,6 @@ html_layout_document(html_document *doc, float w, float h)
else strcpy(dirname, "./");
#endif
- font = html_load_font(doc->ctx, "serif", "normal", "normal", "normal");
-
css = fz_parse_css(doc->ctx, NULL, default_css);
css = load_css(doc->ctx, css, doc->xml);
@@ -602,7 +656,7 @@ html_layout_document(html_document *doc, float w, float h)
win_box->w = w;
win_box->h = 0;
- generate_boxes(doc->ctx, doc->xml, root_box, css, &style);
+ generate_boxes(doc, doc->xml, root_box, css, &style);
layout_block(doc->ctx, root_box, win_box, 12, 0);