summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mupdf/html.h3
-rw-r--r--source/html/css-apply.c17
-rw-r--r--source/html/html-layout.c30
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)