Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS: switch cr-hint from enum to bitmap #359

Merged
merged 3 commits into from
Jul 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 48 additions & 22 deletions crengine/include/cssdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,28 +336,54 @@ enum css_generic_value_t {
css_generic_cover = -5 // (css_val_unspecified, css_generic_cover), for "background-size: cover"
};

// Non standard property for providing hints to crengine via style tweaks
// (see src/lvstsheet.cpp css_cr_hint_names[]= for explanations)
enum css_cr_hint_t {
css_cr_hint_inherit,
css_cr_hint_none,
css_cr_hint_noteref,
css_cr_hint_noteref_ignore,
css_cr_hint_footnote,
css_cr_hint_footnote_ignore,
css_cr_hint_footnote_inpage,
css_cr_hint_toc_level1,
css_cr_hint_toc_level2,
css_cr_hint_toc_level3,
css_cr_hint_toc_level4,
css_cr_hint_toc_level5,
css_cr_hint_toc_level6,
css_cr_hint_toc_ignore,
css_cr_hint_strut_confined,
css_cr_hint_text_selection_inline,
css_cr_hint_text_selection_block,
css_cr_hint_text_selection_skip
};
// -cr-hint is a non standard property for providing hints to crengine via style tweaks
// Handled as a bitmap, with a flag for each hint, as we might set multiple on a same node (max 31 bits)
#define CSS_CR_HINT_NONE 0x00000000 // default value

// Reset any hint previously set and don't inherit any from parent
#define CSS_CR_HINT_NONE_NO_INHERIT 0x00000001 // -cr-hint: none

// Text and images should not overflow/modify their paragraph strut baseline and height
// (it could have been a non-standard named value for line-height:, but we want to be
// able to not override existing line-height: values)
#define CSS_CR_HINT_STRUT_CONFINED 0x00000002 // -cr-hint: strut-confined (inheritable)

// A node with these should be considered as TOC item of level N when building alternate TOC
#define CSS_CR_HINT_TOC_LEVEL1 0x00000100 // -cr-hint: toc-level1
#define CSS_CR_HINT_TOC_LEVEL2 0x00000200 // -cr-hint: toc-level2
#define CSS_CR_HINT_TOC_LEVEL3 0x00000400 // -cr-hint: toc-level3
#define CSS_CR_HINT_TOC_LEVEL4 0x00000800 // -cr-hint: toc-level4
#define CSS_CR_HINT_TOC_LEVEL5 0x00001000 // -cr-hint: toc-level5
#define CSS_CR_HINT_TOC_LEVEL6 0x00002000 // -cr-hint: toc-level6
#define CSS_CR_HINT_TOC_LEVELS_MASK 0x00003F00
// Ignore H1...H6 that have this when building alternate TOC
#define CSS_CR_HINT_TOC_IGNORE 0x00004000 // -cr-hint: toc-ignore

// Tweak text selection behaviour when traversing a node with these hints
#define CSS_CR_HINT_TEXT_SELECTION_INLINE 0x00010000 // -cr-hint: text-selection-inline don't add a '\n' before inner text
// (even if the node happens to be block)
#define CSS_CR_HINT_TEXT_SELECTION_BLOCK 0x00020000 // -cr-hint: text-selection-block add a '\n' before inner text (even
// if the node happens to be inline)
#define CSS_CR_HINT_TEXT_SELECTION_SKIP 0x00040000 // -cr-hint: text-selection-skip don't include inner text in selection

// To be set on a block element: it is a footnote (must be a full footnote block container),
// and to be displayed at the bottom of all pages that contain a link to it.
#define CSS_CR_HINT_FOOTNOTE_INPAGE 0x00080000 // -cr-hint: footnote-inpage

// For footnote popup detection by koreader-base/cre.cpp
#define CSS_CR_HINT_NOTEREF 0x01000000 // -cr-hint: noteref link is to a footnote
#define CSS_CR_HINT_NOTEREF_IGNORE 0x02000000 // -cr-hint: noteref-ignore link is not to a footnote (even if
// everything else indicates it is)
#define CSS_CR_HINT_FOOTNOTE 0x04000000 // -cr-hint: footnote block is a footnote (must be a full
// footnote block container)
#define CSS_CR_HINT_FOOTNOTE_IGNORE 0x08000000 // -cr-hint: footnote-ignore block is not a footnote (even if
// everything else indicates it is)

// A few of them are inheritable, most are not.
#define CSS_CR_HINT_INHERITABLE_MASK 0x00000002

// Macro for easier checking
#define STYLE_HAS_CR_HINT(s, h) ( (bool)(s->cr_hint.value & CSS_CR_HINT_##h) )

/// css length value
typedef struct css_length_tag {
Expand Down
56 changes: 0 additions & 56 deletions crengine/include/lvstsheet.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,62 +89,6 @@ class LVCssDeclaration {

typedef LVRef<LVCssDeclaration> LVCssDeclRef;

// See https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes
enum LVCssSelectorPseudoClass
{
csspc_root, // :root
csspc_dir, // :dir(rtl), :dir(ltr)
csspc_first_child, // :first-child
csspc_first_of_type, // :first-of-type
csspc_nth_child, // :nth-child(even), :nth-child(3n+4)
csspc_nth_of_type, // :nth-of-type()
// Those after this won't be valid when checked in the initial
// document loading phase when the XML is being parsed, as at
// this point, the checked node is always the last node as we
// haven't yet parsed its following siblings. When meeting one,
// we'll need to re-render and re-check styles after load with
// a fully built DOM.
csspc_last_child, // :last-child
csspc_last_of_type, // :last-of-type
csspc_nth_last_child, // :nth-last-child()
csspc_nth_last_of_type, // :nth-last-of-type()
csspc_only_child, // :only-child
csspc_only_of_type, // :only-of-type
csspc_empty, // :empty
};

static const char * css_pseudo_classes[] =
{
"root",
"dir",
"first-child",
"first-of-type",
"nth-child",
"nth-of-type",
"last-child",
"last-of-type",
"nth-last-child",
"nth-last-of-type",
"only-child",
"only-of-type",
"empty",
NULL
};

// https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements
enum LVCssSelectorPseudoElement
{
csspe_before = 1, // ::before
csspe_after = 2, // ::after
};

static const char * css_pseudo_elements[] =
{
"before",
"after",
NULL
};

enum LVCssSelectorRuleType
{
cssrt_universal, // *
Expand Down
6 changes: 3 additions & 3 deletions crengine/include/lvstyles.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ struct css_style_rec_tag {
css_clear_t clear;
css_direction_t direction;
lString16 content;
css_cr_hint_t cr_hint;
css_length_t cr_hint;
// The following should only be used when applying stylesheets while in lvend.cpp setNodeStyle(),
// and cleaned up there, before the style is cached and shared. They are not serialized.
lInt8 flags; // bitmap of STYLE_REC_FLAG_*
Expand Down Expand Up @@ -202,7 +202,7 @@ struct css_style_rec_tag {
, float_(css_f_none)
, clear(css_c_none)
, direction(css_dir_inherit)
, cr_hint(css_cr_hint_none)
, cr_hint(css_val_inherited, 0)
, flags(0)
, pseudo_elem_before_style(NULL)
, pseudo_elem_after_style(NULL)
Expand Down Expand Up @@ -240,7 +240,7 @@ struct css_style_rec_tag {
if (is_important == 0x3) importance |= bit; // update importance flag (!important comes from higher_importance CSS)
}
}
// Similar to previous one, but logical-OR'ing values, for bitmaps (currently, only style->font_features)
// Similar to previous one, but logical-OR'ing values, for bitmaps (currently, only style->font_features and style->cr_hint)
inline void ApplyAsBitmapOr( css_length_t value, css_length_t *field, css_style_rec_important_bit bit, lUInt8 is_important ) {
if ( !(important & bit)
|| (is_important == 0x3)
Expand Down
23 changes: 18 additions & 5 deletions crengine/src/lvrend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2380,7 +2380,7 @@ lString16 renderListItemMarker( ldomNode * enode, int & marker_width, LFormatted
// Scale it according to gInterlineScaleFactor
if (style->line_height.type != css_val_screen_px && gInterlineScaleFactor != INTERLINE_SCALE_FACTOR_NO_SCALE)
line_h = (line_h * gInterlineScaleFactor) >> INTERLINE_SCALE_FACTOR_SHIFT;
if ( style->cr_hint == css_cr_hint_strut_confined )
if ( STYLE_HAS_CR_HINT(style, STRUT_CONFINED) )
flags |= LTEXT_STRUT_CONFINED;
}
marker += "\t";
Expand Down Expand Up @@ -2657,7 +2657,7 @@ void renderFinalBlock( ldomNode * enode, LFormattedText * txform, RenderRectAcce
int f_half_leading = (line_h - fh) / 2;
txform->setStrut(line_h, fb + f_half_leading);
}
else if ( style->cr_hint == css_cr_hint_strut_confined ) {
else if ( STYLE_HAS_CR_HINT(style, STRUT_CONFINED) ) {
// Previous branch for the top final node has set the strut.
// Inline nodes having "-cr-hint: strut-confined" will be confined
// inside that strut.
Expand Down Expand Up @@ -3533,7 +3533,8 @@ void copystyle( css_style_ref_t source, css_style_ref_t dest )
dest->clear = source->clear;
dest->direction = source->direction;
dest->content = source->content ;
dest->cr_hint = source->cr_hint;
dest->cr_hint.type = source->cr_hint.type ;
dest->cr_hint.value = source->cr_hint.value ;
}

// Only used by renderBlockElementLegacy()
Expand Down Expand Up @@ -3771,7 +3772,7 @@ int renderBlockElementLegacy( LVRendPageContext & context, ldomNode * enode, int
lString16 footnoteId;
// Allow displaying footnote content at the bottom of all pages that contain a link
// to it, when -cr-hint: footnote-inpage is set on the footnote block container.
if ( style->cr_hint == css_cr_hint_footnote_inpage &&
if ( STYLE_HAS_CR_HINT(style, FOOTNOTE_INPAGE) &&
enode->getDocument()->getDocFlag(DOC_FLAG_ENABLE_FOOTNOTES)) {
footnoteId = enode->getFirstInnerAttributeValue(attr_id);
if ( !footnoteId.empty() )
Expand Down Expand Up @@ -6080,7 +6081,7 @@ void renderBlockElementEnhanced( FlowState * flow, ldomNode * enode, int x, int
lString16 footnoteId;
// Allow displaying footnote content at the bottom of all pages that contain a link
// to it, when -cr-hint: footnote-inpage is set on the footnote block container.
if ( style->cr_hint == css_cr_hint_footnote_inpage &&
if ( STYLE_HAS_CR_HINT(style, FOOTNOTE_INPAGE) &&
enode->getDocument()->getDocFlag(DOC_FLAG_ENABLE_FOOTNOTES)) {
footnoteId = enode->getFirstInnerAttributeValue(attr_id);
if ( !footnoteId.empty() )
Expand Down Expand Up @@ -9036,6 +9037,18 @@ void setNodeStyle( ldomNode * enode, css_style_ref_t parent_style, LVFontRef par
pstyle->font_features.value |= parent_style->font_features.value;
pstyle->font_features.type = css_val_unspecified;

// cr_hint is also a bitmap, and only some bits are inherited.
// A node starts with (css_val_inherited, 0), but if some
// stylesheet has applied some -cr-hint to it, we meet it
// here with (css_val_unspecified, bitmap) and we report the
// inheritable bits from the parent.
// Unless "-cr-hint: none" has been applied to the node, which
// prevents inheritance
if ( !STYLE_HAS_CR_HINT(pstyle, NONE_NO_INHERIT) ) {
pstyle->cr_hint.value |= (parent_style->cr_hint.value & CSS_CR_HINT_INHERITABLE_MASK);
pstyle->cr_hint.type = css_val_unspecified;
}

//UPDATE_LEN_FIELD( text_indent );
spreadParent( pstyle->text_indent, parent_style->text_indent );
switch( pstyle->font_weight )
Expand Down
Loading