diff options
-rw-r--r-- | include/mupdf/html.h | 4 | ||||
-rw-r--r-- | source/html/css-apply.c | 88 | ||||
-rw-r--r-- | source/html/handler.c | 2 | ||||
-rw-r--r-- | source/html/layout.c | 126 |
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) |