1 /** \file lvrend.h
2     \brief DOM document rendering (formatting) functions
3 
4     CoolReader Engine
5 
6     (c) Vadim Lopatin, 2000-2006
7     This source code is distributed under the terms of
8     GNU General Public License.
9 
10     See LICENSE file for details.
11 
12 */
13 
14 #ifndef __LV_REND_H_INCLUDED__
15 #define __LV_REND_H_INCLUDED__
16 
17 #include "lvtinydom.h"
18 #include "textlang.h"
19 
20 // Current direction, from dir="ltr" or dir="rtl" element attribute
21 // Should map directly to the RENDER_RECT_FLAG_DIRECTION_* below
22 // (bit 0: 0=unset 1=set - bit 1: 0=normal 1=inverted - bit 2: 0=horizontal 1=vertical)
23 #define REND_DIRECTION_UNSET  0X00
24 #define REND_DIRECTION_LTR    0X01 // 0b001
25 #define REND_DIRECTION_RTL    0X03 // 0b011
26 // Not supported:
27 // #define REND_DIRECTION_TTB 0X05 // 0b101
28 // #define REND_DIRECTION_BTT 0X07 // 0b111
29 
30 // Flags for RenderRectAccessor
31 #define RENDER_RECT_FLAG_DIRECTION_SET                      0x0001
32 #define RENDER_RECT_FLAG_DIRECTION_INVERTED                 0x0002
33 #define RENDER_RECT_FLAG_DIRECTION_VERTICAL                 0x0004 // not used (only horizontal currently supported)
34 #define RENDER_RECT_FLAG_INNER_FIELDS_SET                   0x0008
35 #define RENDER_RECT_FLAG_BOX_IS_RENDERED                    0x0010 // for floatBox and inlineBox
36 #define RENDER_RECT_FLAG_NO_CLEAR_OWN_FLOATS                0x0020
37 #define RENDER_RECT_FLAG_FINAL_FOOTPRINT_AS_SAVED_FLOAT_IDS 0x0040
38 #define RENDER_RECT_FLAG_FLOATBOX_IS_RIGHT                  0x0080
39 #define RENDER_RECT_FLAG_NO_INTERLINE_SCALE_UP              0x0100 // for ruby elements to not scale up
40 #define RENDER_RECT_FLAG_CHILDREN_RENDERING_REORDERED       0x0200 // for table rows/thead/tfoot reordering
41 #define RENDER_RECT_FLAG_TEMP_USED_AS_CSS_CHECK_CACHE       0x8000 // has been cleared and is used as a CSS checks cache
42 
43 #define RENDER_RECT_SET_FLAG(r, f)     ( r.setFlags( r.getFlags() | RENDER_RECT_FLAG_##f ) )
44 #define RENDER_RECT_UNSET_FLAG(r, f)   ( r.setFlags( r.getFlags() & ~RENDER_RECT_FLAG_##f ) )
45 #define RENDER_RECT_HAS_FLAG(r, f)     ( (bool)(r.getFlags() & RENDER_RECT_FLAG_##f) )
46 #define RENDER_RECT_PTR_HAS_FLAG(r, f) ( (bool)(r->getFlags() & RENDER_RECT_FLAG_##f) )
47 
48 #define RENDER_RECT_FLAG_DIRECTION_MASK                     0x0007
49 #define RENDER_RECT_SET_DIRECTION(r, d)   ( r.setFlags( r.getFlags() | d ) )
50 #define RENDER_RECT_GET_DIRECTION(r)      ( r.getFlags() & RENDER_RECT_FLAG_DIRECTION_MASK )
51 #define RENDER_RECT_PTR_GET_DIRECTION(r)  ( r->getFlags() & RENDER_RECT_FLAG_DIRECTION_MASK )
52 #define RENDER_RECT_HAS_DIRECTION(r)      ( (bool)(r.getFlags() & RENDER_RECT_FLAG_DIRECTION_SET) )
53 #define RENDER_RECT_HAS_DIRECTION_RTL(r)  ( (bool)(r.getFlags() & RENDER_RECT_FLAG_DIRECTION_MASK == REND_DIRECTION_RTL) )
54 #define RENDER_RECT_PTR_HAS_DIRECTION_RTL(r)  ( (bool)(r->getFlags() & RENDER_RECT_FLAG_DIRECTION_MASK == REND_DIRECTION_RTL) )
55 
56 // To be provided via the initial value to renderBlockElement(... int *baseline ...) to
57 // have FlowState compute baseline (different rules whether inline-block or inline-table).
58 #define REQ_BASELINE_NOT_NEEDED       0
59 #define REQ_BASELINE_FOR_INLINE_BLOCK 1    // use last baseline fed
60 #define REQ_BASELINE_FOR_TABLE        2    // keep first baseline fed
61 
62 class FlowState;
63 
64 // Footprint of block floats (from FlowState) on a final block,
65 // to be passed to lvtextfm LFormattedText::Format().
66 // Also allows LFormattedText to pass back information about
67 // its own embedded floats if they overflow the final block
68 // own height.
69 class BlockFloatFootprint {
70 private:
71     FlowState * flow;
72     int d_left;
73     int d_top;
74     int used_min_y;
75     int used_max_y;
76 public:
77     // Forwarded from BLOCK_RENDERING_DO_NOT_CLEAR_OWN_FLOATS
78     // (or not when table cell erm_final)
79     bool no_clear_own_floats;
80     bool use_floatIds;
81     // Footprints, used when they are more than 5 floats involved,
82     // or ALLOW_EXACT_FLOATS_FOOTPRINTS not enabled.
83     int left_w;
84     int left_h;
85     int right_w;
86     int right_h;
87     int left_min_y;
88     int right_min_y;
89     // FloatIds, used when less than 5 floats involved
90     // and ALLOW_EXACT_FLOATS_FOOTPRINTS enabled
91     int nb_floatIds;
92     lUInt32 floatIds[5];
93     // Floats to transfer to final block for it to
94     // start with these 5 "fake" embedded floats
95     int floats_cnt;
96     int floats[5][6]; // max 5 floats, with (x,y,w,h,is_right,inward_margin) each
97 
getFinalMinY()98     int getFinalMinY() { return used_min_y; };
getFinalMaxY()99     int getFinalMaxY() { return used_max_y; };
100     void store( ldomNode * node );
101     void restore( ldomNode * node, int final_width );
102     void generateEmbeddedFloatsFromFootprints( int final_width );
103     void generateEmbeddedFloatsFromFloatIds( ldomNode * node, int final_width );
104     void forwardOverflowingFloat( int x, int y, int w, int h, bool r, ldomNode * node );
105     int getTopShiftX(int final_width, bool get_right_shift=false);
106 
107     BlockFloatFootprint( FlowState * fl=NULL, int dleft=0, int dtop=0, bool noclearownfloats=false ) :
flow(fl)108         flow(fl), d_left(dleft), d_top(dtop), no_clear_own_floats(noclearownfloats),
109         used_min_y(0), used_max_y(0),
110         left_w(0), left_h(0), right_w(0), right_h(0), left_min_y(0), right_min_y(0),
111         use_floatIds(false), nb_floatIds(0), floats_cnt(0)
112         { }
113 };
114 
115 /// returns true if styles are identical
116 bool isSameFontStyle( css_style_rec_t * style1, css_style_rec_t * style2 );
117 /// removes format data from node
118 void freeFormatData( ldomNode * node );
119 /// returns best suitable font for style
120 LVFontRef getFont(css_style_rec_t * style, int documentId);
121 /// initializes format data for node
122 void initFormatData( ldomNode * node );
123 /// initializes rendering method for node
124 int initRendMethod( ldomNode * node, bool recurseChildren, bool allowAutoboxing );
125 /// converts style to text formatting API flags
126 lUInt32 styleToTextFmtFlags( bool is_block, const css_style_ref_t & style, lUInt32 oldflags, int direction=REND_DIRECTION_UNSET );
127 /// renders block as single text formatter object
128 void renderFinalBlock( ldomNode * node, LFormattedText * txform, RenderRectAccessor * fmt, lUInt32 & flags,
129                        int indent, int line_h, TextLangCfg * lang_cfg=NULL, int valign_dy=0, bool * is_link_start=NULL );
130 /// renders block which contains subblocks (with enode document's rendering flags)
131 int renderBlockElement( LVRendPageContext & context, ldomNode * enode, int x, int y, int width,
132         int usable_left_overflow=0, int usable_right_overflow=0, int direction=REND_DIRECTION_UNSET, int * baseline=NULL );
133 /// renders block which contains subblocks
134 int renderBlockElement( LVRendPageContext & context, ldomNode * enode, int x, int y, int width,
135         int usable_left_overflow, int usable_right_overflow, int direction, int * baseline, lUInt32 rend_flags );
136 /// renders table element
137 int renderTable( LVRendPageContext & context, ldomNode * element, int x, int y, int width,
138                  bool shrink_to_fit, int & fitted_width, int direction=REND_DIRECTION_UNSET,
139                  bool pb_inside_avoid=false, bool enhanced_rendering=false, bool is_ruby_table=false );
140 /// sets node style
141 void setNodeStyle( ldomNode * node, css_style_ref_t parent_style, LVFontRef parent_font );
142 /// copy style
143 void copystyle( css_style_ref_t sourcestyle, css_style_ref_t deststyle );
144 
145 /// draws formatted document to drawing buffer
146 void DrawDocument( LVDrawBuf & drawbuf, ldomNode * node, int x0, int y0, int dx, int dy, int doc_x, int doc_y,
147                    int page_height, ldomMarkedRangeList * marks, ldomMarkedRangeList * bookmarks = NULL,
148                    bool draw_content=true, bool draw_background=true );
149 
150 // Estimate width of node when rendered:
151 //   maxWidth: width if it would be rendered on an infinite width area
152 //   minWidth: width with a wrap on all spaces (no hyphenation), so width taken by the longest word
153 // full function for recursive use:
154 void getRenderedWidths(ldomNode * node, int &maxWidth, int &minWidth, int direction, bool ignorePadding, int rendFlags,
155             int &curMaxWidth, int &curWordWidth, bool &collapseNextSpace, int &lastSpaceWidth,
156             int indent, TextLangCfg * lang_cfg, bool processNodeAsText=false, bool isStartNode=false);
157 // simpler function for first call:
158 void getRenderedWidths(ldomNode * node, int &maxWidth, int &minWidth, int direction=REND_DIRECTION_UNSET, bool ignorePadding=false, int rendFlags=0);
159 
160 #define STYLE_FONT_EMBOLD_MODE_NORMAL 0
161 #define STYLE_FONT_EMBOLD_MODE_EMBOLD 300
162 
163 /// set global document font style embolden mode (0=off, 300=on)
164 void LVRendSetFontEmbolden( int addWidth=STYLE_FONT_EMBOLD_MODE_EMBOLD );
165 /// get global document font style embolden mode
166 int LVRendGetFontEmbolden();
167 
168 int measureBorder(ldomNode *enode,int border);
169 int lengthToPx( css_length_t val, int base_px, int base_em, bool unspecified_as_em=false );
170 int scaleForRenderDPI( int value );
171 
172 #define BASE_CSS_DPI 96 // at 96 dpi, 1 css px = 1 screen px
173 #define DEF_RENDER_DPI 96
174 #define DEF_RENDER_SCALE_FONT_WITH_DPI 0
175 extern int gRenderDPI;
176 extern bool gRenderScaleFontWithDPI;
177 extern int gRootFontSize;
178 
179 #define INTERLINE_SCALE_FACTOR_NO_SCALE 1024
180 #define INTERLINE_SCALE_FACTOR_SHIFT 10
181 
182 // Enhanced rendering flags
183 #define BLOCK_RENDERING_ENHANCED                           0x00000001
184 #define BLOCK_RENDERING_ALLOW_PAGE_BREAK_WHEN_NO_CONTENT   0x00000002 // Allow consecutive page breaks when only separated
185                                                                       // by margin/padding/border.
186 // Vertical margins
187 #define BLOCK_RENDERING_COLLAPSE_VERTICAL_MARGINS          0x00000010 // Collapse vertical margins
188 #define BLOCK_RENDERING_ALLOW_VERTICAL_NEGATIVE_MARGINS    0x00000020 // Allow individual negative margins in the calculation, the
189                                                                       // final collapsed margin is ensure to be zero or positive.
190 #define BLOCK_RENDERING_ALLOW_NEGATIVE_COLLAPSED_MARGINS   0x00000040 // Allow the final vertical collapsed margin to be negative
191                                                                       // (may mess with page splitting and text selection).
192 // Horizontal margins
193 #define BLOCK_RENDERING_ENSURE_MARGIN_AUTO_ALIGNMENT       0x00000100 // Ensure CSS "margin: auto", for aligning blocks.
194 #define BLOCK_RENDERING_ALLOW_HORIZONTAL_NEGATIVE_MARGINS  0x00000200 // Allow negative margins (otherwise, they are set to 0)
195 #define BLOCK_RENDERING_ALLOW_HORIZONTAL_BLOCK_OVERFLOW    0x00000400 // Allow block content to overflow its block container.
196 #define BLOCK_RENDERING_ALLOW_HORIZONTAL_PAGE_OVERFLOW     0x00000800 // Allow block content to overflow the page rect, showing
197                                                                       // in the margin, and possibly clipped out.
198 // Widths and heights
199 #define BLOCK_RENDERING_USE_W3C_BOX_MODEL                  0x00001000 // Use W3C box model (CSS width and height do not include
200                                                                       // paddings and borders)
201 #define BLOCK_RENDERING_ALLOW_STYLE_W_H_ABSOLUTE_UNITS     0x00002000 // Allow widths and heights in absolute units (when ensured)
202 #define BLOCK_RENDERING_ENSURE_STYLE_WIDTH                 0x00004000 // Ensure CSS widths and heights on all elements (otherwise
203 #define BLOCK_RENDERING_ENSURE_STYLE_HEIGHT                0x00008000 // only on <HR> and images, and when sizing floats).
204 // Floats
205 #define BLOCK_RENDERING_WRAP_FLOATS                        0x00010000 // Wrap floats in an internal floatBox element.
206 #define BLOCK_RENDERING_PREPARE_FLOATBOXES                 0x00020000 // Avoid style hash mismatch when toggling FLOAT_FLOATBOXES,
207                                                                       // but make embedded floats inline when no more floating.
208 #define BLOCK_RENDERING_FLOAT_FLOATBOXES                   0x00040000 // Actually render floatBoxes floating.
209 // These 2, although allowing a more correct rendering of floats, can impact drawing performances and text/links selection:
210 #define BLOCK_RENDERING_DO_NOT_CLEAR_OWN_FLOATS            0x00100000 // Prevent blocks from clearing their own floats.
211 #define BLOCK_RENDERING_ALLOW_EXACT_FLOATS_FOOTPRINTS      0x00200000 // When 5 or less outer floats have impact on a final
212                                                                       // block, store their ids instead of the 2 top left/right
213                                                                       // rectangle, allowing text layout staircase-like.
214 // Inline block/table
215 #define BLOCK_RENDERING_BOX_INLINE_BLOCKS                  0x01000000 // Wrap inline-block in an internal inlineBox element.
216 #define BLOCK_RENDERING_COMPLETE_INCOMPLETE_TABLES         0x02000000 // Add anonymous missing elements to a table without proper
217                                                                       // children and table-cells without proper parents
218 
219 // Enable everything
220 #define BLOCK_RENDERING_FULL_FEATURED                      0x7FFFFFFF
221 
222 // Some macros (for shorter lines of code)
223 #define BLOCK_RENDERING(v, f) ((bool)( v & BLOCK_RENDERING_##f ))
224 #define BLOCK_RENDERING_D(d, f) ((bool)( d->getRenderBlockRenderingFlags() & BLOCK_RENDERING_##f ))
225 #define BLOCK_RENDERING_N(n, f) ((bool)( n->getDocument()->getRenderBlockRenderingFlags() & BLOCK_RENDERING_##f ))
226 
227 // rendering flags presets
228 #define BLOCK_RENDERING_FLAGS_LEGACY     0
229 #define BLOCK_RENDERING_FLAGS_FLAT       ( BLOCK_RENDERING_ENHANCED | \
230                                            BLOCK_RENDERING_COLLAPSE_VERTICAL_MARGINS | \
231                                            BLOCK_RENDERING_ALLOW_VERTICAL_NEGATIVE_MARGINS | \
232                                            BLOCK_RENDERING_USE_W3C_BOX_MODEL | \
233                                            BLOCK_RENDERING_WRAP_FLOATS | \
234                                            BLOCK_RENDERING_PREPARE_FLOATBOXES | \
235                                            BLOCK_RENDERING_BOX_INLINE_BLOCKS )
236 #define BLOCK_RENDERING_FLAGS_BOOK       ( BLOCK_RENDERING_ENHANCED | \
237                                            BLOCK_RENDERING_COLLAPSE_VERTICAL_MARGINS | \
238                                            BLOCK_RENDERING_ALLOW_VERTICAL_NEGATIVE_MARGINS | \
239                                            BLOCK_RENDERING_ENSURE_MARGIN_AUTO_ALIGNMENT | \
240                                            BLOCK_RENDERING_USE_W3C_BOX_MODEL | \
241                                            BLOCK_RENDERING_ENSURE_STYLE_WIDTH | \
242                                            BLOCK_RENDERING_WRAP_FLOATS | \
243                                            BLOCK_RENDERING_PREPARE_FLOATBOXES | \
244                                            BLOCK_RENDERING_FLOAT_FLOATBOXES | \
245                                            BLOCK_RENDERING_DO_NOT_CLEAR_OWN_FLOATS | \
246                                            BLOCK_RENDERING_ALLOW_EXACT_FLOATS_FOOTPRINTS | \
247                                            BLOCK_RENDERING_BOX_INLINE_BLOCKS )
248 #define BLOCK_RENDERING_FLAGS_WEB        BLOCK_RENDERING_FULL_FEATURED
249 #define BLOCK_RENDERING_FLAGS_DEFAULT    BLOCK_RENDERING_FLAGS_WEB
250 
251 #endif
252