From 0b6d7198f4fc46961c57530e654691b5a66b36f0 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Tue, 23 Aug 2011 20:12:41 +0000 Subject: Add support for selecting page-break-{before, after, inside} Credit: James Montgomerie svn path=/trunk/libcss/; revision=12645 --- src/select/computed.c | 64 +++++++++++++++++++++++++ src/select/computed.h | 13 ++++- src/select/properties/helpers.c | 16 +++++-- src/select/properties/helpers.h | 4 +- src/select/properties/page_break_after.c | 24 +++++----- src/select/properties/page_break_before.c | 27 +++++------ src/select/properties/page_break_inside.c | 41 +++++----------- src/select/propget.h | 63 ++++++++++++++++++++++++ src/select/propset.h | 79 +++++++++++++++++++++++++++++++ 9 files changed, 267 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/src/select/computed.c b/src/select/computed.c index 198b243..991a9a8 100644 --- a/src/select/computed.c +++ b/src/select/computed.c @@ -2160,6 +2160,70 @@ uint8_t css_computed_text_align( #undef CSS_TEXT_ALIGN_SHIFT #undef CSS_TEXT_ALIGN_INDEX +#define CSS_PAGE_BREAK_AFTER_INDEX 0 +#define CSS_PAGE_BREAK_AFTER_SHIFT 0 +#define CSS_PAGE_BREAK_AFTER_MASK 0x7 +uint8_t css_computed_page_break_after( + const css_computed_style *style) +{ + if (style->page != NULL) { + uint8_t bits = style->page->bits[CSS_PAGE_BREAK_AFTER_INDEX]; + bits &= CSS_PAGE_BREAK_AFTER_MASK; + bits >>= CSS_PAGE_BREAK_AFTER_SHIFT; + + /* 3bits: type */ + return bits; + } + + return CSS_PAGE_BREAK_AFTER_AUTO; +} +#undef CSS_PAGE_BREAK_AFTER_MASK +#undef CSS_PAGE_BREAK_AFTER_SHIFT +#undef CSS_PAGE_BREAK_AFTER_INDEX + +#define CSS_PAGE_BREAK_BEFORE_INDEX 0 +#define CSS_PAGE_BREAK_BEFORE_SHIFT 3 +#define CSS_PAGE_BREAK_BEFORE_MASK 0x38 +uint8_t css_computed_page_break_before( + const css_computed_style *style) +{ + if (style->page != NULL) { + uint8_t bits = style->page->bits[CSS_PAGE_BREAK_BEFORE_INDEX]; + bits &= CSS_PAGE_BREAK_BEFORE_MASK; + bits >>= CSS_PAGE_BREAK_BEFORE_SHIFT; + + /* 3bits: type */ + return bits; + } + + return CSS_PAGE_BREAK_BEFORE_AUTO; +} +#undef CSS_PAGE_BREAK_BEFORE_MASK +#undef CSS_PAGE_BREAK_BEFORE_SHIFT +#undef CSS_PAGE_BREAK_BEFORE_INDEX + +#define CSS_PAGE_BREAK_INSIDE_INDEX 0 +#define CSS_PAGE_BREAK_INSIDE_SHIFT 6 +#define CSS_PAGE_BREAK_INSIDE_MASK 0xc0 +uint8_t css_computed_page_break_inside( + const css_computed_style *style) +{ + if (style->page != NULL) { + uint8_t bits = style->page->bits[CSS_PAGE_BREAK_INSIDE_INDEX]; + bits &= CSS_PAGE_BREAK_INSIDE_MASK; + bits >>= CSS_PAGE_BREAK_INSIDE_SHIFT; + + /* 2bits: type */ + return bits; + } + + return CSS_PAGE_BREAK_INSIDE_AUTO; +} +#undef CSS_PAGE_BREAK_INSIDE_MASK +#undef CSS_PAGE_BREAK_INSIDE_SHIFT +#undef CSS_PAGE_BREAK_INSIDE_INDEX + + /****************************************************************************** * Library internals * diff --git a/src/select/computed.h b/src/select/computed.h index e77c0cc..6f19051 100644 --- a/src/select/computed.h +++ b/src/select/computed.h @@ -85,6 +85,17 @@ typedef struct css_computed_uncommon { css_computed_content_item *content; } css_computed_uncommon; +typedef struct css_computed_page { +/* + * page_break_after 3 + * page_break_before 3 + * page_break_inside 2 + * --- + * 8 bits + */ + uint8_t bits[1]; +} css_computed_page; + struct css_computed_style { /* * background_attachment 2 @@ -270,7 +281,7 @@ struct css_computed_style { css_computed_uncommon *uncommon;/**< Uncommon properties */ void *aural; /**< Aural properties */ - void *page; /**< Page properties */ + css_computed_page *page; /**< Page properties */ css_allocator_fn alloc; void *pw; diff --git a/src/select/properties/helpers.c b/src/select/properties/helpers.c index 3851b36..24e193d 100644 --- a/src/select/properties/helpers.c +++ b/src/select/properties/helpers.c @@ -356,22 +356,30 @@ css_error css__cascade_number(uint32_t opv, css_style *style, return CSS_OK; } -css_error css__cascade_page_break_after_before(uint32_t opv, css_style *style, - css_select_state *state, +css_error css__cascade_page_break_after_before_inside(uint32_t opv, + css_style *style, css_select_state *state, css_error (*fun)(css_computed_style *, uint8_t)) { - uint16_t value = 0; + uint16_t value = CSS_PAGE_BREAK_AFTER_INHERIT; UNUSED(style); if (isInherit(opv) == false) { switch (getValue(opv)) { case PAGE_BREAK_AFTER_AUTO: + value = CSS_PAGE_BREAK_AFTER_AUTO; + break; case PAGE_BREAK_AFTER_ALWAYS: + value = CSS_PAGE_BREAK_AFTER_ALWAYS; + break; case PAGE_BREAK_AFTER_AVOID: + value = CSS_PAGE_BREAK_AFTER_AVOID; + break; case PAGE_BREAK_AFTER_LEFT: + value = CSS_PAGE_BREAK_AFTER_LEFT; + break; case PAGE_BREAK_AFTER_RIGHT: - /** \todo convert to public values */ + value = CSS_PAGE_BREAK_AFTER_RIGHT; break; } } diff --git a/src/select/properties/helpers.h b/src/select/properties/helpers.h index 9e3e327..098fe1e 100644 --- a/src/select/properties/helpers.h +++ b/src/select/properties/helpers.h @@ -48,8 +48,8 @@ css_error css__cascade_length(uint32_t opv, css_style *style, css_error css__cascade_number(uint32_t opv, css_style *style, css_select_state *state, css_error (*fun)(css_computed_style *, uint8_t, css_fixed)); -css_error css__cascade_page_break_after_before(uint32_t opv, css_style *style, - css_select_state *state, +css_error css__cascade_page_break_after_before_inside(uint32_t opv, + css_style *style, css_select_state *state, css_error (*fun)(css_computed_style *, uint8_t)); css_error css__cascade_counter_increment_reset(uint32_t opv, css_style *style, css_select_state *state, diff --git a/src/select/properties/page_break_after.c b/src/select/properties/page_break_after.c index c2c3051..0fd44c4 100644 --- a/src/select/properties/page_break_after.c +++ b/src/select/properties/page_break_after.c @@ -17,34 +17,32 @@ css_error css__cascade_page_break_after(uint32_t opv, css_style *style, css_select_state *state) { - /** \todo page-break-after */ - return css__cascade_page_break_after_before(opv, style, state, NULL); + return css__cascade_page_break_after_before_inside(opv, style, state, + set_page_break_after); } css_error css__set_page_break_after_from_hint(const css_hint *hint, css_computed_style *style) { - UNUSED(hint); - UNUSED(style); - - return CSS_OK; + return set_page_break_after(style, hint->status); } css_error css__initial_page_break_after(css_select_state *state) { - UNUSED(state); - - return CSS_OK; + return set_page_break_after(state->computed, + CSS_PAGE_BREAK_AFTER_AUTO); } css_error css__compose_page_break_after(const css_computed_style *parent, const css_computed_style *child, css_computed_style *result) { - UNUSED(parent); - UNUSED(child); - UNUSED(result); + uint8_t type = get_page_break_after(child); + + if (type == CSS_PAGE_BREAK_AFTER_INHERIT) { + type = get_page_break_after(parent); + } - return CSS_OK; + return set_page_break_after(result, type); } diff --git a/src/select/properties/page_break_before.c b/src/select/properties/page_break_before.c index a0799fd..0acae48 100644 --- a/src/select/properties/page_break_before.c +++ b/src/select/properties/page_break_before.c @@ -17,34 +17,31 @@ css_error css__cascade_page_break_before(uint32_t opv, css_style *style, css_select_state *state) { - /** \todo page-break-before */ - return css__cascade_page_break_after_before(opv, style, state, NULL); + return css__cascade_page_break_after_before_inside(opv, style, state, + set_page_break_before); } css_error css__set_page_break_before_from_hint(const css_hint *hint, css_computed_style *style) { - UNUSED(hint); - UNUSED(style); - - return CSS_OK; + return set_page_break_before(style, hint->status); } css_error css__initial_page_break_before(css_select_state *state) { - UNUSED(state); - - return CSS_OK; + return set_page_break_before(state->computed, + CSS_PAGE_BREAK_BEFORE_AUTO); } css_error css__compose_page_break_before(const css_computed_style *parent, const css_computed_style *child, css_computed_style *result) { - UNUSED(parent); - UNUSED(child); - UNUSED(result); - - return CSS_OK; + uint8_t type = get_page_break_before(child); + + if (type == CSS_PAGE_BREAK_BEFORE_INHERIT) { + type = get_page_break_before(parent); + } + + return set_page_break_before(result, type); } - diff --git a/src/select/properties/page_break_inside.c b/src/select/properties/page_break_inside.c index 2e27298..20b8bf5 100644 --- a/src/select/properties/page_break_inside.c +++ b/src/select/properties/page_break_inside.c @@ -17,49 +17,32 @@ css_error css__cascade_page_break_inside(uint32_t opv, css_style *style, css_select_state *state) { - UNUSED(style); - - if (isInherit(opv) == false) { - switch (getValue(opv)) { - case PAGE_BREAK_INSIDE_AUTO: - case PAGE_BREAK_INSIDE_AVOID: - /** \todo convert to public values */ - break; - } - } - - if (css__outranks_existing(getOpcode(opv), isImportant(opv), state, - isInherit(opv))) { - /** \todo page-break-inside */ - } - - return CSS_OK; + return css__cascade_page_break_after_before_inside(opv, style, state, + set_page_break_inside); } css_error css__set_page_break_inside_from_hint(const css_hint *hint, css_computed_style *style) { - UNUSED(hint); - UNUSED(style); - - return CSS_OK; + return set_page_break_inside(style, hint->status); } css_error css__initial_page_break_inside(css_select_state *state) { - UNUSED(state); - - return CSS_OK; + return set_page_break_inside(state->computed, + CSS_PAGE_BREAK_INSIDE_AUTO); } css_error css__compose_page_break_inside(const css_computed_style *parent, const css_computed_style *child, css_computed_style *result) { - UNUSED(parent); - UNUSED(child); - UNUSED(result); - - return CSS_OK; + uint8_t type = get_page_break_inside(child); + + if (type == CSS_PAGE_BREAK_INSIDE_INHERIT) { + type = get_page_break_inside(parent); + } + + return set_page_break_inside(result, type); } diff --git a/src/select/propget.h b/src/select/propget.h index 05bdba6..d1350ee 100644 --- a/src/select/propget.h +++ b/src/select/propget.h @@ -1744,4 +1744,67 @@ static inline uint8_t get_text_align( #undef TEXT_ALIGN_SHIFT #undef TEXT_ALIGN_INDEX +#define PAGE_BREAK_AFTER_INDEX 0 +#define PAGE_BREAK_AFTER_SHIFT 0 +#define PAGE_BREAK_AFTER_MASK 0x7 +static inline uint8_t get_page_break_after( + const css_computed_style *style) +{ + if (style->page != NULL) { + uint8_t bits = style->page->bits[PAGE_BREAK_AFTER_INDEX]; + bits &= PAGE_BREAK_AFTER_MASK; + bits >>= PAGE_BREAK_AFTER_SHIFT; + + /* 3bits: type */ + return bits; + } + + return CSS_PAGE_BREAK_AFTER_AUTO; +} +#undef PAGE_BREAK_AFTER_MASK +#undef PAGE_BREAK_AFTER_SHIFT +#undef PAGE_BREAK_AFTER_INDEX + +#define PAGE_BREAK_BEFORE_INDEX 0 +#define PAGE_BREAK_BEFORE_SHIFT 3 +#define PAGE_BREAK_BEFORE_MASK 0x38 +static inline uint8_t get_page_break_before( + const css_computed_style *style) +{ + if (style->page != NULL) { + uint8_t bits = style->page->bits[PAGE_BREAK_BEFORE_INDEX]; + bits &= PAGE_BREAK_BEFORE_MASK; + bits >>= PAGE_BREAK_BEFORE_SHIFT; + + /* 3bits: type */ + return bits; + } + + return CSS_PAGE_BREAK_BEFORE_AUTO; +} +#undef PAGE_BREAK_BEFORE_MASK +#undef PAGE_BREAK_BEFORE_SHIFT +#undef PAGE_BREAK_BEFORE_INDEX + +#define PAGE_BREAK_INSIDE_INDEX 0 +#define PAGE_BREAK_INSIDE_SHIFT 6 +#define PAGE_BREAK_INSIDE_MASK 0xc0 +static inline uint8_t get_page_break_inside( + const css_computed_style *style) +{ + if (style->page != NULL) { + uint8_t bits = style->page->bits[PAGE_BREAK_INSIDE_INDEX]; + bits &= PAGE_BREAK_INSIDE_MASK; + bits >>= PAGE_BREAK_INSIDE_SHIFT; + + /* 2bits: type */ + return bits; + } + + return CSS_PAGE_BREAK_INSIDE_AUTO; +} +#undef PAGE_BREAK_INSIDE_MASK +#undef PAGE_BREAK_INSIDE_SHIFT +#undef PAGE_BREAK_INSIDE_INDEX + #endif diff --git a/src/select/propset.h b/src/select/propset.h index 7c29db4..6337536 100644 --- a/src/select/propset.h +++ b/src/select/propset.h @@ -51,6 +51,25 @@ static const css_computed_uncommon default_uncommon = { } \ } while(0) +static const css_computed_page default_page = { + { (CSS_PAGE_BREAK_INSIDE_AUTO << 6) | + (CSS_PAGE_BREAK_BEFORE_AUTO << 3) | + CSS_PAGE_BREAK_AFTER_AUTO + } +}; + +#define ENSURE_PAGE do { \ + if (style->page == NULL) { \ + style->page = style->alloc(NULL, \ + sizeof(css_computed_page), style->pw); \ + if (style->page == NULL) \ + return CSS_NOMEM; \ + \ + memcpy(style->page, &default_page, \ + sizeof(css_computed_page)); \ + } \ +} while(0) + #define LETTER_SPACING_INDEX 0 #define LETTER_SPACING_SHIFT 2 #define LETTER_SPACING_MASK 0xfc @@ -1835,4 +1854,64 @@ static inline uint8_t set_text_align( #undef TEXT_ALIGN_SHIFT #undef TEXT_ALIGN_INDEX +#define PAGE_BREAK_AFTER_INDEX 0 +#define PAGE_BREAK_AFTER_SHIFT 0 +#define PAGE_BREAK_AFTER_MASK 0x7 +static inline css_error set_page_break_after( + css_computed_style *style, uint8_t type) +{ + ENSURE_PAGE; + + uint8_t *bits = &style->page->bits[PAGE_BREAK_AFTER_INDEX]; + + /* 3bits: type */ + *bits = (*bits & ~PAGE_BREAK_AFTER_MASK) | + ((type & 0x7) << PAGE_BREAK_AFTER_SHIFT); + + return CSS_OK; +} +#undef PAGE_BREAK_AFTER_INDEX +#undef PAGE_BREAK_AFTER_SHIFT +#undef PAGE_BREAK_AFTER_MASK + +#define PAGE_BREAK_BEFORE_INDEX 0 +#define PAGE_BREAK_BEFORE_SHIFT 3 +#define PAGE_BREAK_BEFORE_MASK 0x38 +static inline css_error set_page_break_before( + css_computed_style *style, uint8_t type) +{ + ENSURE_PAGE; + + uint8_t *bits = &style->page->bits[PAGE_BREAK_BEFORE_INDEX]; + + /* 3bits: type */ + *bits = (*bits & ~PAGE_BREAK_BEFORE_MASK) | + ((type & 0x7) << PAGE_BREAK_BEFORE_SHIFT); + + return CSS_OK; +} +#undef PAGE_BREAK_BEFORE_INDEX +#undef PAGE_BREAK_BEFORE_SHIFT +#undef PAGE_BREAK_BEFORE_MASK + +#define PAGE_BREAK_INSIDE_INDEX 0 +#define PAGE_BREAK_INSIDE_SHIFT 6 +#define PAGE_BREAK_INSIDE_MASK 0xc0 +static inline css_error set_page_break_inside( + css_computed_style *style, uint8_t type) +{ + ENSURE_PAGE; + + uint8_t *bits = &style->page->bits[PAGE_BREAK_INSIDE_INDEX]; + + /* 2bits: type */ + *bits = (*bits & ~PAGE_BREAK_INSIDE_MASK) | + ((type & 0x3) << PAGE_BREAK_INSIDE_SHIFT); + + return CSS_OK; +} +#undef PAGE_BREAK_INSIDE_INDEX +#undef PAGE_BREAK_INSIDE_SHIFT +#undef PAGE_BREAK_INSIDE_MASK + #endif -- cgit v1.2.3