diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2016-04-11 16:58:20 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2016-04-26 15:12:57 +0200 |
commit | 6c6964373ee61805577a7f5374f658dc64098c70 (patch) | |
tree | 81999f47b6a372c416396998d78399ebb35a9177 | |
parent | b935334975d13548379b58d1883eea98dc0f4eda (diff) | |
download | mupdf-6c6964373ee61805577a7f5374f658dc64098c70.tar.xz |
epub: Support page-break-before/after: always, left and right.
Does not support page-break-before/after: avoid.
-rw-r--r-- | include/mupdf/html.h | 3 | ||||
-rw-r--r-- | source/html/css-apply.c | 17 | ||||
-rw-r--r-- | source/html/html-layout.c | 30 |
3 files changed, 50 insertions, 0 deletions
diff --git a/include/mupdf/html.h b/include/mupdf/html.h index 3adbf8e0..af1fe463 100644 --- a/include/mupdf/html.h +++ b/include/mupdf/html.h @@ -110,6 +110,7 @@ enum { TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY }; enum { VA_BASELINE, VA_SUB, VA_SUPER, VA_TOP, VA_BOTTOM, VA_TEXT_TOP, VA_TEXT_BOTTOM }; enum { BS_NONE, BS_SOLID }; enum { V_VISIBLE, V_HIDDEN, V_COLLAPSE }; +enum { PB_AUTO, PB_ALWAYS, PB_AVOID, PB_LEFT, PB_RIGHT }; enum { WS_COLLAPSE = 1, @@ -160,6 +161,8 @@ struct fz_css_style_s char vertical_align; char list_style_type; char border_style[4]; + char page_break_before; + char page_break_after; fz_css_number line_height; fz_css_color background_color; fz_css_color border_color[4]; diff --git a/source/html/css-apply.c b/source/html/css-apply.c index 3daff6b4..bf082f0d 100644 --- a/source/html/css-apply.c +++ b/source/html/css-apply.c @@ -1144,6 +1144,21 @@ visibility_from_property(fz_css_match *match) return V_VISIBLE; } +static int +page_break_from_property(fz_css_match *match, char *prop) +{ + fz_css_value *value = value_from_property(match, prop); + if (value) + { + if (!strcmp(value->data, "auto")) return PB_AUTO; + else if (!strcmp(value->data, "always")) return PB_ALWAYS; + else if (!strcmp(value->data, "avoid")) return PB_AVOID; + else if (!strcmp(value->data, "left")) return PB_LEFT; + else if (!strcmp(value->data, "right")) return PB_RIGHT; + } + return PB_AUTO; +} + void fz_default_css_style(fz_context *ctx, fz_css_style *style) { @@ -1170,6 +1185,8 @@ fz_apply_css_style(fz_context *ctx, fz_html_font_set *set, fz_css_style *style, style->visibility = visibility_from_property(match); style->white_space = white_space_from_property(match); + style->page_break_before = page_break_from_property(match, "page-break-before"); + style->page_break_after = page_break_from_property(match, "page-break-after"); value = value_from_property(match, "text-align"); if (value) diff --git a/source/html/html-layout.c b/source/html/html-layout.c index c0a660ae..bb4dd21c 100644 --- a/source/html/html-layout.c +++ b/source/html/html-layout.c @@ -1177,6 +1177,25 @@ static void layout_flow(fz_context *ctx, fz_html *box, fz_html *top, float page_ } } +static int layout_block_page_break(fz_context *ctx, fz_html *box, float page_h, float vertical, int page_break) +{ + if (page_break == PB_ALWAYS || page_break == PB_LEFT || page_break == PB_RIGHT) + { + float avail = page_h - fmodf(box->y + box->h - vertical, page_h); + int number = (box->y + box->h + (page_h * 0.1f)) / page_h; + if (avail > 0 && avail < page_h) + { + box->h += avail - vertical; + if (page_break == PB_LEFT && (number & 1) == 0) /* right side pages are even */ + box->h += page_h; + if (page_break == PB_RIGHT && (number & 1) == 1) /* left side pages are odd */ + box->h += page_h; + return 1; + } + } + return 0; +} + static float layout_block(fz_context *ctx, fz_html *box, fz_html *top, float page_h, float vertical, hb_buffer_t *hb_buf) { fz_html *child; @@ -1204,6 +1223,11 @@ static float layout_block(fz_context *ctx, fz_html *box, fz_html *top, float pag border[2] = style->border_style[2] ? fz_from_css_number(style->border_width[2], em, top->w) : 0; border[3] = style->border_style[3] ? fz_from_css_number(style->border_width[3], em, top->w) : 0; + /* TODO: remove 'vertical' margin adjustments across automatic page breaks */ + + if (layout_block_page_break(ctx, top, page_h, vertical, style->page_break_before)) + vertical = 0; + box->x = top->x + margin[L] + border[L] + padding[L]; box->w = top->w - (margin[L] + margin[R] + border[L] + border[R] + padding[L] + padding[R]); @@ -1264,6 +1288,12 @@ static float layout_block(fz_context *ctx, fz_html *box, fz_html *top, float pag vertical = 0; } + if (layout_block_page_break(ctx, box, page_h, 0, style->page_break_after)) + { + vertical = 0; + margin[B] = 0; + } + if (box->h == 0) { if (margin[B] > vertical) |