summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2014-11-18 13:56:58 +0100
committerTor Andersson <tor.andersson@artifex.com>2014-12-03 12:25:52 +0100
commit3ba9c348795b3923ff65e917c23b454470698489 (patch)
treee01db0e03d60c2b010164be64928f2ca47b3badf
parentbb875f77f23ac4c51a072f4fc6692ce2dc352997 (diff)
downloadmupdf-3ba9c348795b3923ff65e917c23b454470698489.tar.xz
html: Borders.
-rw-r--r--include/mupdf/html.h4
-rw-r--r--source/html/css-apply.c88
-rw-r--r--source/html/handler.c2
-rw-r--r--source/html/layout.c126
4 files changed, 153 insertions, 67 deletions
diff --git a/include/mupdf/html.h b/include/mupdf/html.h
index 57249c03..8da4534c 100644
--- a/include/mupdf/html.h
+++ b/include/mupdf/html.h
@@ -122,12 +122,15 @@ struct computed_style
struct number font_size;
struct number margin[4];
struct number padding[4];
+ struct number border_width[4];
struct number text_indent;
int white_space;
int text_align;
int vertical_align;
+ int border_style;
struct number line_height;
struct color background_color;
+ struct color border_color;
struct color color;
fz_font *font;
};
@@ -155,6 +158,7 @@ struct box
float x, y, w, h; /* content */
float padding[4];
float margin[4];
+ float border[4];
struct box *up, *down, *last, *next;
fz_xml *node;
struct flow *flow_head, **flow_tail;
diff --git a/source/html/css-apply.c b/source/html/css-apply.c
index 351f05e6..d642d98c 100644
--- a/source/html/css-apply.c
+++ b/source/html/css-apply.c
@@ -500,10 +500,10 @@ add_shorthand_border_width(struct style *style, struct value *value, int spec)
if (n == 1)
{
- add_property(style, "border-top-width", value, spec);
- add_property(style, "border-right-width", value, spec);
- add_property(style, "border-bottom-width", value, spec);
- add_property(style, "border-left-width", value, spec);
+ add_property(style, "border-width-top", value, spec);
+ add_property(style, "border-width-right", value, spec);
+ add_property(style, "border-width-bottom", value, spec);
+ add_property(style, "border-width-left", value, spec);
}
if (n == 2)
@@ -511,10 +511,10 @@ add_shorthand_border_width(struct style *style, struct value *value, int spec)
struct value *a = new_value(value->type, value->data);
struct value *b = new_value(value->next->type, value->next->data);
- add_property(style, "border-top-width", a, spec);
- add_property(style, "border-right-width", b, spec);
- add_property(style, "border-bottom-width", a, spec);
- add_property(style, "border-left-width", b, spec);
+ add_property(style, "border-width-top", a, spec);
+ add_property(style, "border-width-right", b, spec);
+ add_property(style, "border-width-bottom", a, spec);
+ add_property(style, "border-width-left", b, spec);
}
if (n == 3)
@@ -523,10 +523,10 @@ add_shorthand_border_width(struct style *style, struct value *value, int spec)
struct value *b = new_value(value->next->type, value->next->data);
struct value *c = new_value(value->next->next->type, value->next->next->data);
- add_property(style, "border-top-width", a, spec);
- add_property(style, "border-right-width", b, spec);
- add_property(style, "border-bottom-width", c, spec);
- add_property(style, "border-left-width", b, spec);
+ add_property(style, "border-width-top", a, spec);
+ add_property(style, "border-width-right", b, spec);
+ add_property(style, "border-width-bottom", c, spec);
+ add_property(style, "border-width-left", b, spec);
}
if (n == 4)
@@ -536,14 +536,19 @@ add_shorthand_border_width(struct style *style, struct value *value, int spec)
struct value *c = new_value(value->next->next->type, value->next->next->data);
struct value *d = new_value(value->next->next->next->type, value->next->next->next->data);
- add_property(style, "border-top-width", a, spec);
- add_property(style, "border-right-width", b, spec);
- add_property(style, "border-bottom-width", c, spec);
- add_property(style, "border-left-width", d, spec);
+ add_property(style, "border-width-top", a, spec);
+ add_property(style, "border-width-right", b, spec);
+ add_property(style, "border-width-bottom", c, spec);
+ add_property(style, "border-width-left", d, spec);
}
}
static void
+add_shorthand_border(struct style *style, struct value *value, int spec)
+{
+}
+
+static void
add_property(struct style *style, const char *name, struct value *value, int spec)
{
int i;
@@ -563,10 +568,15 @@ add_property(struct style *style, const char *name, struct value *value, int spe
add_shorthand_border_width(style, value, spec);
return;
}
+ if (!strcmp(name, "border"))
+ {
+ add_shorthand_border(style, value, spec);
+ return;
+ }
+ /* shorthand expansions: */
/* TODO: border-color */
/* TODO: border-style */
- /* TODO: border */
/* TODO: font */
/* TODO: list-style */
/* TODO: background */
@@ -757,6 +767,23 @@ number_from_property(struct style *node, const char *property, float initial, in
return number_from_value(get_style_property(node, property), initial, initial_unit);
}
+static struct number
+border_width_from_property(struct style *node, const char *property)
+{
+ struct value *value = get_style_property(node, property);
+ if (value)
+ {
+ if (!strcmp(value->data, "thin"))
+ return make_number(1, N_NUMBER);
+ if (!strcmp(value->data, "medium"))
+ return make_number(2, N_NUMBER);
+ if (!strcmp(value->data, "thick"))
+ return make_number(4, N_NUMBER);
+ return number_from_value(value, 0, N_NUMBER);
+ }
+ return make_number(2, N_NUMBER); /* initial: 'medium' */
+}
+
float
from_number(struct number number, float em, float width)
{
@@ -798,10 +825,10 @@ static int tohex(int c)
}
static struct color
-color_from_value(struct value *value)
+color_from_value(struct value *value, struct color initial)
{
if (!value)
- return make_color(0, 0, 0, 0);
+ return initial;
if (value->type == CSS_COLOR)
{
int r = tohex(value->data[0]) * 16 + tohex(value->data[1]);
@@ -849,13 +876,13 @@ color_from_value(struct value *value)
return make_color(0x80, 0x80, 0x80, 255);
return make_color(0, 0, 0, 255);
}
- return make_color(0, 0, 0, 0);
+ return initial;
}
static struct color
-color_from_property(struct style *node, const char *property)
+color_from_property(struct style *node, const char *property, struct color initial)
{
- return color_from_value(get_style_property(node, property));
+ return color_from_value(get_style_property(node, property), initial);
}
int
@@ -899,8 +926,6 @@ default_computed_style(struct computed_style *style)
style->vertical_align = 0;
style->white_space = WS_NORMAL;
style->font_size = make_number(1, N_SCALE);
- style->background_color = make_color(0, 0, 0, 0);
- style->color = make_color(0, 0, 0, 255);
}
void
@@ -908,6 +933,9 @@ compute_style(html_document *doc, struct computed_style *style, struct style *no
{
struct value *value;
+ struct color black = { 0, 0, 0, 255 };
+ struct color transparent = { 0, 0, 0, 0 };
+
default_computed_style(style);
style->white_space = get_style_property_white_space(node);
@@ -967,8 +995,16 @@ compute_style(html_document *doc, struct computed_style *style, struct style *no
style->padding[2] = number_from_property(node, "padding-bottom", 0, N_NUMBER);
style->padding[3] = number_from_property(node, "padding-left", 0, N_NUMBER);
- style->color = color_from_property(node, "color");
- style->background_color = color_from_property(node, "background-color");
+ style->border_width[0] = border_width_from_property(node, "border-width-top");
+ style->border_width[1] = border_width_from_property(node, "border-width-right");
+ style->border_width[2] = border_width_from_property(node, "border-width-bottom");
+ style->border_width[3] = border_width_from_property(node, "border-width-left");
+
+ style->color = color_from_property(node, "color", black);
+ style->background_color = color_from_property(node, "background-color", transparent);
+ style->border_color = color_from_property(node, "border-color", style->color);
+
+ style->border_style = !strcmp(get_style_property_string(node, "border-style", "none"), "solid");
{
const char *font_family = get_style_property_string(node, "font-family", "serif");
diff --git a/source/html/handler.c b/source/html/handler.c
index cbce9409..fda21f5c 100644
--- a/source/html/handler.c
+++ b/source/html/handler.c
@@ -125,7 +125,7 @@ html_recognize(fz_context *doc, const char *magic)
if (ext)
{
- if (!fz_strcasecmp(ext, ".xhtml") || !fz_strcasecmp(ext, ".html"))
+ if (!fz_strcasecmp(ext, ".xml") || !fz_strcasecmp(ext, ".xhtml") || !fz_strcasecmp(ext, ".html"))
return 100;
}
if (!strcmp(magic, "application/html+xml") || !strcmp(magic, "application/xml") || !strcmp(magic, "text/xml"))
diff --git a/source/html/layout.c b/source/html/layout.c
index f5436b10..b5a22557 100644
--- a/source/html/layout.c
+++ b/source/html/layout.c
@@ -1,5 +1,10 @@
#include "mupdf/html.h"
+#define L LEFT
+#define R RIGHT
+#define T TOP
+#define B BOTTOM
+
static const char *default_css =
"html,address,blockquote,body,dd,div,dl,dt,h1,h2,h3,h4,h5,h6,ol,p,ul,center,hr,pre{display:block}"
"span{display:inline}"
@@ -22,7 +27,7 @@ static const char *default_css =
"sub{vertical-align:sub}"
"sup{vertical-align:super}"
"s,strike,del{text-decoration:line-through}"
-"hr{border-width:1px;border-color:black}"
+"hr{border-width:thin;border-color:black;border-style:solid;margin:.5em 0}"
"ol,ul,dir,menu,dd{margin-left:40px}"
"ol{list-style-type:decimal}"
"ol ul,ul ol,ul ul,ol ol{margin-top:0;margin-bottom:0}"
@@ -448,31 +453,45 @@ static void layout_block(fz_context *ctx, struct box *box, struct box *top, floa
float box_collapse_margin;
int prev_br;
+ float *margin = box->margin;
+ float *border = box->border;
+ float *padding = box->padding;
+
em = from_number(box->style.font_size, em, em);
- box->margin[0] = from_number(box->style.margin[0], em, top->w);
- box->margin[1] = from_number(box->style.margin[1], em, top->w);
- box->margin[2] = from_number(box->style.margin[2], em, top->w);
- box->margin[3] = from_number(box->style.margin[3], em, top->w);
+ margin[0] = from_number(box->style.margin[0], em, top->w);
+ margin[1] = from_number(box->style.margin[1], em, top->w);
+ margin[2] = from_number(box->style.margin[2], em, top->w);
+ margin[3] = from_number(box->style.margin[3], em, top->w);
+
+ padding[0] = from_number(box->style.padding[0], em, top->w);
+ padding[1] = from_number(box->style.padding[1], em, top->w);
+ padding[2] = from_number(box->style.padding[2], em, top->w);
+ padding[3] = from_number(box->style.padding[3], em, top->w);
- box->padding[0] = from_number(box->style.padding[0], em, top->w);
- box->padding[1] = from_number(box->style.padding[1], em, top->w);
- box->padding[2] = from_number(box->style.padding[2], em, top->w);
- box->padding[3] = from_number(box->style.padding[3], em, top->w);
+ if (box->style.border_style)
+ {
+ border[0] = from_number(box->style.border_width[0], em, top->w);
+ border[1] = from_number(box->style.border_width[1], em, top->w);
+ border[2] = from_number(box->style.border_width[2], em, top->w);
+ border[3] = from_number(box->style.border_width[3], em, top->w);
+ }
+ else
+ border[0] = border[1] = border[2] = border[3] = 0;
- if (box->padding[TOP] == 0)
- box_collapse_margin = box->margin[TOP];
+ if (padding[T] == 0 && border[T] == 0)
+ box_collapse_margin = margin[T];
else
box_collapse_margin = 0;
- if (box->margin[TOP] > top_collapse_margin)
- box->margin[TOP] -= top_collapse_margin;
+ if (margin[T] > top_collapse_margin)
+ margin[T] -= top_collapse_margin;
else
- box->margin[TOP] = 0;
+ margin[T] = 0;
- box->x = top->x + box->margin[LEFT] + box->padding[LEFT];
- box->y = top->y + top->h + box->margin[TOP] + box->padding[TOP];
- box->w = top->w - (box->margin[LEFT] + box->margin[RIGHT] + box->padding[LEFT] + box->padding[RIGHT]);
+ box->x = top->x + margin[L] + border[L] + padding[L];
+ box->y = top->y + top->h + margin[T] + border[T] + padding[T];
+ box->w = top->w - (margin[L] + margin[R] + border[L] + border[R] + padding[L] + padding[R]);
box->h = 0;
prev_br = 0;
@@ -481,8 +500,11 @@ static void layout_block(fz_context *ctx, struct box *box, struct box *top, floa
if (child->type == BOX_BLOCK)
{
layout_block(ctx, child, box, em, box_collapse_margin, page_h);
- box->h += child->h + child->padding[TOP] + child->padding[BOTTOM] + child->margin[TOP] + child->margin[BOTTOM];
- box_collapse_margin = child->margin[BOTTOM];
+ box->h += child->h +
+ child->padding[T] + child->padding[B] +
+ child->border[T] + child->border[B] +
+ child->margin[T] + child->margin[B];
+ box_collapse_margin = child->margin[B];
prev_br = 0;
}
else if (child->type == BOX_BREAK)
@@ -504,13 +526,13 @@ static void layout_block(fz_context *ctx, struct box *box, struct box *top, floa
}
}
- if (box->padding[BOTTOM] == 0)
+ if (padding[B] == 0 && border[B] == 0)
{
- if (box->margin[BOTTOM] > 0)
+ if (margin[B] > 0)
{
box->h -= box_collapse_margin;
- if (box->margin[BOTTOM] < box_collapse_margin)
- box->margin[BOTTOM] = box_collapse_margin;
+ if (margin[B] < box_collapse_margin)
+ margin[B] = box_collapse_margin;
}
}
}
@@ -608,40 +630,64 @@ draw_flow_box(fz_context *ctx, struct box *box, float page_top, float page_bot,
}
static void
+draw_rect(fz_context *ctx, fz_device *dev, const fz_matrix *ctm, float *rgba, float x0, float y0, float x1, float y1)
+{
+ fz_path *path = fz_new_path(ctx);
+
+ fz_moveto(ctx, path, x0, y0);
+ fz_lineto(ctx, path, x1, y0);
+ fz_lineto(ctx, path, x1, y1);
+ fz_lineto(ctx, path, x0, y1);
+ fz_closepath(ctx, path);
+
+ fz_fill_path(dev, path, 0, ctm, fz_device_rgb(ctx), rgba, rgba[3]);
+
+ fz_free_path(ctx, path);
+}
+
+static void
draw_block_box(fz_context *ctx, struct box *box, float page_top, float page_bot, fz_device *dev, const fz_matrix *ctm)
{
- fz_path *path;
float x0, y0, x1, y1;
+ float color[4];
// TODO: background fill
// TODO: border stroke
- x0 = box->x - box->padding[LEFT];
- y0 = box->y - box->padding[TOP];
- x1 = box->x + box->w + box->padding[RIGHT];
- y1 = box->y + box->h + box->padding[BOTTOM];
+ float *border = box->border;
+ float *padding = box->padding;
+
+ x0 = box->x - padding[L];
+ y0 = box->y - padding[T];
+ x1 = box->x + box->w + padding[R];
+ y1 = box->y + box->h + padding[B];
if (y0 > page_bot || y1 < page_top)
return;
if (box->style.background_color.a > 0)
{
- float color[3];
-
color[0] = box->style.background_color.r / 255.0f;
color[1] = box->style.background_color.g / 255.0f;
color[2] = box->style.background_color.b / 255.0f;
+ color[3] = box->style.background_color.a / 255.0f;
+ draw_rect(ctx, dev, ctm, color, x0, y0, x1, y1);
+ }
- path = fz_new_path(ctx);
- fz_moveto(ctx, path, x0, y0);
- fz_lineto(ctx, path, x1, y0);
- fz_lineto(ctx, path, x1, y1);
- fz_lineto(ctx, path, x0, y1);
- fz_closepath(ctx, path);
-
- fz_fill_path(dev, path, 0, ctm, fz_device_rgb(ctx), color, box->style.background_color.a / 255.0f);
-
- fz_free_path(ctx, path);
+ if (box->style.border_color.a > 0)
+ {
+ color[0] = box->style.border_color.r / 255.0f;
+ color[1] = box->style.border_color.g / 255.0f;
+ color[2] = box->style.border_color.b / 255.0f;
+ color[3] = box->style.border_color.a / 255.0f;
+ if (border[T] > 0)
+ draw_rect(ctx, dev, ctm, color, x0 - border[L], y0 - border[T], x1 + border[R], y0);
+ if (border[B] > 0)
+ draw_rect(ctx, dev, ctm, color, x0 - border[L], y1, x1 + border[R], y1 + border[B]);
+ if (border[L] > 0)
+ draw_rect(ctx, dev, ctm, color, x0 - border[L], y0 - border[T], x0, y1 + border[B]);
+ if (border[R] > 0)
+ draw_rect(ctx, dev, ctm, color, x1, y0 - border[T], x1 + border[R], y1 + border[B]);
}
for (box = box->down; box; box = box->next)