2003-06-30 16:44:03 +04:00
/*
2005-01-11 00:35:34 +03:00
* Copyright 2005 Richard Wilson < info @ tinct . net >
2006-01-16 01:25:40 +03:00
* Copyright 2006 James Bursa < bursa @ users . sourceforge . net >
2008-03-09 22:39:17 +03:00
* Copyright 2008 Michael Drake < tlsa @ netsurf - browser . org >
2003-06-30 16:44:03 +04:00
* Copyright 2003 Phil Mellor < monkeyson @ users . sourceforge . net >
2007-08-08 20:16:03 +04:00
*
* This file is part of NetSurf , http : //www.netsurf-browser.org/
*
* NetSurf is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; version 2 of the License .
*
* NetSurf is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
2002-05-04 23:57:18 +04:00
*/
2016-04-24 01:32:21 +03:00
/**
* \ file
* HTML layout implementation .
2004-02-11 20:15:36 +03:00
*
2005-07-02 22:17:51 +04:00
* Layout is carried out in two stages :
*
2011-03-12 21:44:43 +03:00
* 1. + calculation of minimum / maximum box widths , and
* + determination of whether block level boxes will have > zero height
*
* 2. + layout ( position and dimensions )
2005-07-02 22:17:51 +04:00
*
* In most cases the functions for the two stages are a corresponding pair
* layout_minmax_X ( ) and layout_X ( ) .
2004-02-11 20:15:36 +03:00
*/
2002-05-04 23:57:18 +04:00
# include <assert.h>
2003-07-18 21:08:39 +04:00
# include <limits.h>
2004-02-02 01:42:40 +03:00
# include <stdbool.h>
2002-05-04 23:57:18 +04:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
2008-07-29 00:32:51 +04:00
# include <math.h>
2012-03-25 00:55:22 +04:00
# include <dom/dom.h>
2014-10-13 14:56:31 +04:00
# include "utils/log.h"
# include "utils/talloc.h"
# include "utils/utils.h"
2007-05-31 02:39:54 +04:00
# include "css/css.h"
2009-07-24 03:05:34 +04:00
# include "css/utils.h"
2010-03-28 16:56:39 +04:00
# include "content/content_protected.h"
2013-05-26 01:46:27 +04:00
# include "utils/nsoption.h"
2014-10-17 15:21:06 +04:00
# include "desktop/browser.h"
2011-05-10 02:49:17 +04:00
# include "desktop/scrollbar.h"
2013-02-07 02:39:45 +04:00
# include "desktop/textarea.h"
2016-04-24 01:32:21 +03:00
# include "desktop/gui_layout.h"
2014-10-13 14:56:31 +04:00
2007-05-31 02:39:54 +04:00
# include "render/box.h"
# include "render/font.h"
2014-11-14 00:52:08 +03:00
# include "render/form_internal.h"
2011-05-07 00:40:09 +04:00
# include "render/html_internal.h"
2007-05-31 02:39:54 +04:00
# include "render/layout.h"
2009-07-24 03:05:34 +04:00
# include "render/table.h"
2002-08-06 00:34:45 +04:00
2004-02-02 03:22:59 +03:00
2011-04-04 02:23:14 +04:00
/* Define to enable layout debugging */
# undef LAYOUT_DEBUG
2004-02-02 03:22:59 +03:00
# define AUTO INT_MIN
2015-08-25 00:42:54 +03:00
/* Fixed point percentage (a) of an integer (b), to an integer */
# define FPCT_OF_INT_TOINT(a, b) (FIXTOINT(FDIV((a * b), F_100)))
2011-02-15 17:31:18 +03:00
2016-04-24 01:32:21 +03:00
/* forward declaration to break cycles */
static bool layout_block_context ( struct box * block , int viewport_height , html_content * content ) ;
static void layout_minmax_block ( struct box * block , const struct gui_layout_table * font_func ) ;
2004-07-17 05:36:21 +04:00
2002-05-04 23:57:18 +04:00
/**
2016-04-24 01:32:21 +03:00
* Compute the size of replaced boxes with auto dimensions , according to
* content .
*
* \ param box Box with object
* \ param width Width value in px or AUTO . If AUTO , updated to value in px .
* \ param height Height value in px or AUTO . If AUTO , updated to value in px .
* \ param min_width Box ' s min width , as given by layout_find_dimensions .
* \ param max_width Box ' s max width , as given by layout_find_dimensions .
* \ param min_height Box ' s min height , as given by layout_find_dimensions .
* \ param max_height Box ' s max height , as given by layout_find_dimensions .
2002-06-19 01:24:21 +04:00
*
2016-04-24 01:32:21 +03:00
* See CSS 2.1 sections 10.3 and 10.6 .
2002-06-19 01:24:21 +04:00
*/
2016-04-24 01:32:21 +03:00
static void
layout_get_object_dimensions ( struct box * box ,
int * width , int * height ,
int min_width , int max_width ,
int min_height , int max_height )
2002-05-28 03:21:11 +04:00
{
2016-04-24 01:32:21 +03:00
assert ( box - > object ! = NULL ) ;
assert ( width ! = NULL & & height ! = NULL ) ;
2004-08-01 17:08:19 +04:00
2016-04-24 01:32:21 +03:00
if ( * width = = AUTO & & * height = = AUTO ) {
/* No given dimensions */
2004-02-11 20:15:36 +03:00
2016-04-24 01:32:21 +03:00
bool scaled = false ;
int intrinsic_width = content_get_width ( box - > object ) ;
int intrinsic_height = content_get_height ( box - > object ) ;
2004-08-01 17:08:19 +04:00
2016-04-24 01:32:21 +03:00
/* use intrinsic dimensions */
* width = intrinsic_width ;
* height = intrinsic_height ;
2004-08-01 17:08:19 +04:00
2016-04-24 01:32:21 +03:00
/* Deal with min/max-width first */
if ( min_width > 0 & & min_width > * width ) {
* width = min_width ;
scaled = true ;
}
if ( max_width > = 0 & & max_width < * width ) {
* width = max_width ;
scaled = true ;
}
2005-07-02 22:17:51 +04:00
2016-04-24 01:32:21 +03:00
if ( scaled & & ( intrinsic_width ! = 0 ) ) {
/* Update height */
* height = ( * width * intrinsic_height ) /
intrinsic_width ;
}
2005-07-31 15:21:46 +04:00
2016-04-24 01:32:21 +03:00
scaled = false ;
/* Deal with min/max-height */
if ( min_height > 0 & & min_height > * height ) {
* height = min_height ;
scaled = true ;
}
if ( max_height > = 0 & & max_height < * height ) {
* height = max_height ;
scaled = true ;
}
2004-08-01 17:08:19 +04:00
2016-04-24 01:32:21 +03:00
if ( scaled & & ( intrinsic_height ! = 0 ) ) {
/* Update width */
* width = ( * height * intrinsic_width ) /
intrinsic_height ;
}
} else if ( * width = = AUTO ) {
/* Have given height; width is calculated from the given height
* and ratio of intrinsic dimensions */
int intrinsic_width = content_get_width ( box - > object ) ;
int intrinsic_height = content_get_height ( box - > object ) ;
if ( intrinsic_height ! = 0 )
* width = ( * height * intrinsic_width ) /
intrinsic_height ;
else
* width = intrinsic_width ;
if ( min_width > 0 & & min_width > * width )
* width = min_width ;
if ( max_width > = 0 & & max_width < * width )
* width = max_width ;
} else if ( * height = = AUTO ) {
/* Have given width; height is calculated from the given width
* and ratio of intrinsic dimensions */
int intrinsic_width = content_get_width ( box - > object ) ;
int intrinsic_height = content_get_height ( box - > object ) ;
if ( intrinsic_width ! = 0 )
* height = ( * width * intrinsic_height ) /
intrinsic_width ;
else
* height = intrinsic_height ;
}
2002-05-28 03:21:11 +04:00
}
2002-06-19 01:24:21 +04:00
2004-02-02 03:22:59 +03:00
/**
2016-04-24 01:32:21 +03:00
* Calculate the text - indent length .
2002-06-19 01:24:21 +04:00
*
2016-04-24 01:32:21 +03:00
* \ param style style of block
* \ param width width of containing block
* \ return length of indent
2002-06-19 01:24:21 +04:00
*/
2016-04-24 01:32:21 +03:00
static int layout_text_indent ( const css_computed_style * style , int width )
{
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
2002-06-19 01:24:21 +04:00
2016-04-24 01:32:21 +03:00
css_computed_text_indent ( style , & value , & unit ) ;
if ( unit = = CSS_UNIT_PCT ) {
return FPCT_OF_INT_TOINT ( value , width ) ;
} else {
return FIXTOINT ( nscss_len2px ( value , unit , style ) ) ;
}
}
/**
* Determine width of margin , borders , and padding on one side of a box .
*
* \ param style style to measure
* \ param side side of box to measure
* \ param margin whether margin width is required
* \ param border whether border width is required
* \ param padding whether padding width is required
* \ param fixed increased by sum of fixed margin , border , and padding
* \ param frac increased by sum of fractional margin and padding
*/
static void
calculate_mbp_width ( const css_computed_style * style ,
unsigned int side ,
bool margin ,
bool border ,
bool padding ,
int * fixed ,
float * frac )
2002-05-04 23:57:18 +04:00
{
2016-04-24 01:32:21 +03:00
typedef uint8_t ( * len_func ) ( const css_computed_style * style ,
css_fixed * length , css_unit * unit ) ;
2004-04-12 04:00:47 +04:00
2016-04-24 01:32:21 +03:00
static len_func margin_funcs [ 4 ] = {
css_computed_margin_top ,
css_computed_margin_right ,
css_computed_margin_bottom ,
css_computed_margin_left
} ;
static len_func padding_funcs [ 4 ] = {
css_computed_padding_top ,
css_computed_padding_right ,
css_computed_padding_bottom ,
css_computed_padding_left
} ;
static struct {
len_func width ;
uint8_t ( * style ) ( const css_computed_style * style ) ;
} border_funcs [ 4 ] = {
{ css_computed_border_top_width ,
css_computed_border_top_style } ,
{ css_computed_border_right_width ,
css_computed_border_right_style } ,
{ css_computed_border_bottom_width ,
css_computed_border_bottom_style } ,
{ css_computed_border_left_width ,
css_computed_border_left_style }
} ;
2004-04-12 04:00:47 +04:00
2016-04-24 01:32:21 +03:00
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
2005-11-06 14:00:33 +03:00
2016-04-24 01:32:21 +03:00
assert ( style ) ;
2005-10-31 00:23:24 +03:00
2016-04-24 01:32:21 +03:00
/* margin */
if ( margin ) {
enum css_margin_e type ;
type = margin_funcs [ side ] ( style , & value , & unit ) ;
if ( type = = CSS_MARGIN_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
* frac + = FIXTOINT ( FDIV ( value , F_100 ) ) ;
} else {
* fixed + = FIXTOINT ( nscss_len2px ( value , unit ,
style ) ) ;
}
}
2008-09-21 03:25:37 +04:00
}
2016-04-24 01:32:21 +03:00
/* border */
if ( border ) {
if ( border_funcs [ side ] . style ( style ) ! =
CSS_BORDER_STYLE_NONE ) {
border_funcs [ side ] . width ( style , & value , & unit ) ;
2004-04-12 04:00:47 +04:00
2016-04-24 01:32:21 +03:00
* fixed + = FIXTOINT ( nscss_len2px ( value , unit , style ) ) ;
2009-01-19 13:17:44 +03:00
}
2016-04-24 01:32:21 +03:00
}
2006-10-09 02:46:25 +04:00
2016-04-24 01:32:21 +03:00
/* padding */
if ( padding ) {
padding_funcs [ side ] ( style , & value , & unit ) ;
if ( unit = = CSS_UNIT_PCT ) {
* frac + = FIXTOINT ( FDIV ( value , F_100 ) ) ;
} else {
* fixed + = FIXTOINT ( nscss_len2px ( value , unit , style ) ) ;
2011-04-23 01:57:18 +04:00
}
2016-04-24 01:32:21 +03:00
}
}
2011-04-23 01:57:18 +04:00
2014-06-01 21:36:22 +04:00
2016-04-24 01:32:21 +03:00
/**
* Calculate minimum and maximum width of a line .
*
* \ param first a box in an inline container
* \ param line_min updated to minimum width of line starting at first
* \ param line_max updated to maximum width of line starting at first
* \ param first_line true iff this is the first line in the inline container
* \ param line_has_height updated to true or false , depending on line
* \ param font_func Font functions .
* \ return first box in next line , or 0 if no more lines
* \ post 0 < = * line_min < = * line_max
*/
static struct box *
layout_minmax_line ( struct box * first ,
int * line_min ,
int * line_max ,
bool first_line ,
bool * line_has_height ,
const struct gui_layout_table * font_func )
{
int min = 0 , max = 0 , width , height , fixed ;
float frac ;
size_t i , j ;
struct box * b ;
struct box * block ;
plot_font_style_t fstyle ;
bool no_wrap ;
2009-01-22 18:39:06 +03:00
2016-04-24 01:32:21 +03:00
assert ( first - > parent ) ;
assert ( first - > parent - > parent ) ;
assert ( first - > parent - > parent - > style ) ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
block = first - > parent - > parent ;
no_wrap = ( css_computed_white_space ( block - > style ) = =
CSS_WHITE_SPACE_NOWRAP | |
css_computed_white_space ( block - > style ) = =
CSS_WHITE_SPACE_PRE ) ;
2009-11-22 16:28:30 +03:00
2016-04-24 01:32:21 +03:00
* line_has_height = false ;
2002-06-19 01:24:21 +04:00
2016-04-24 01:32:21 +03:00
/* corresponds to the pass 1 loop in layout_line() */
for ( b = first ; b ; b = b - > next ) {
enum css_width_e wtype ;
enum css_height_e htype ;
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
2004-04-12 04:00:47 +04:00
2016-04-24 01:32:21 +03:00
assert ( b - > type = = BOX_INLINE | | b - > type = = BOX_INLINE_BLOCK | |
b - > type = = BOX_FLOAT_LEFT | |
b - > type = = BOX_FLOAT_RIGHT | |
b - > type = = BOX_BR | | b - > type = = BOX_TEXT | |
b - > type = = BOX_INLINE_END ) ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
# ifdef LAYOUT_DEBUG
LOG ( " %p: min %i, max %i " , b , min , max ) ;
# endif
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
if ( b - > type = = BOX_BR ) {
b = b - > next ;
break ;
2011-04-23 01:57:18 +04:00
}
2016-04-24 01:32:21 +03:00
if ( b - > type = = BOX_FLOAT_LEFT | | b - > type = = BOX_FLOAT_RIGHT ) {
assert ( b - > children ) ;
if ( b - > children - > type = = BOX_BLOCK )
layout_minmax_block ( b - > children , font_func ) ;
else
layout_minmax_table ( b - > children , font_func ) ;
b - > min_width = b - > children - > min_width ;
b - > max_width = b - > children - > max_width ;
if ( min < b - > min_width )
min = b - > min_width ;
max + = b - > max_width ;
continue ;
2004-04-12 04:00:47 +04:00
}
2002-06-19 01:24:21 +04:00
2016-04-24 01:32:21 +03:00
if ( b - > type = = BOX_INLINE_BLOCK ) {
layout_minmax_block ( b , font_func ) ;
if ( min < b - > min_width )
min = b - > min_width ;
max + = b - > max_width ;
2008-06-30 19:53:28 +04:00
2016-04-24 01:32:21 +03:00
if ( b - > flags & HAS_HEIGHT )
* line_has_height = true ;
continue ;
}
2008-06-06 18:54:19 +04:00
2016-04-24 01:32:21 +03:00
assert ( b - > style ) ;
font_plot_style_from_css ( b - > style , & fstyle ) ;
2008-06-06 18:54:19 +04:00
2016-04-24 01:32:21 +03:00
if ( b - > type = = BOX_INLINE & & ! b - > object & &
! ( b - > flags & REPLACE_DIM ) & &
! ( b - > flags & IFRAME ) ) {
fixed = frac = 0 ;
calculate_mbp_width ( b - > style , LEFT , true , true , true ,
& fixed , & frac ) ;
if ( ! b - > inline_end )
calculate_mbp_width ( b - > style , RIGHT ,
true , true , true ,
& fixed , & frac ) ;
if ( 0 < fixed )
max + = fixed ;
* line_has_height = true ;
/* \todo update min width, consider fractional extra */
} else if ( b - > type = = BOX_INLINE_END ) {
fixed = frac = 0 ;
calculate_mbp_width ( b - > inline_end - > style , RIGHT ,
true , true , true ,
& fixed , & frac ) ;
if ( 0 < fixed )
max + = fixed ;
2008-06-06 18:54:19 +04:00
2016-04-24 01:32:21 +03:00
if ( b - > next ) {
if ( b - > space = = UNKNOWN_WIDTH ) {
font_func - > width ( & fstyle , " " , 1 ,
& b - > space ) ;
}
max + = b - > space ;
}
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
* line_has_height = true ;
continue ;
2011-01-09 03:09:57 +03:00
}
2008-06-06 18:54:19 +04:00
2016-04-24 01:32:21 +03:00
if ( ! b - > object & & ! ( b - > flags & IFRAME ) & & ! b - > gadget & &
! ( b - > flags & REPLACE_DIM ) ) {
/* inline non-replaced, 10.3.1 and 10.6.1 */
bool no_wrap_box ;
if ( ! b - > text )
continue ;
2005-08-07 03:34:30 +04:00
2016-04-24 01:32:21 +03:00
no_wrap_box = ( css_computed_white_space ( b - > style ) = =
CSS_WHITE_SPACE_NOWRAP | |
css_computed_white_space ( b - > style ) = =
CSS_WHITE_SPACE_PRE ) ;
2011-06-15 00:00:18 +04:00
2016-04-24 01:32:21 +03:00
if ( b - > width = = UNKNOWN_WIDTH ) {
/** \todo handle errors */
2011-06-15 00:00:18 +04:00
2016-04-24 01:32:21 +03:00
/* If it's a select element, we must use the
* width of the widest option text */
if ( b - > parent - > parent - > gadget & &
b - > parent - > parent - > gadget - > type
= = GADGET_SELECT ) {
int opt_maxwidth = 0 ;
struct form_option * o ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
for ( o = b - > parent - > parent - > gadget - >
data . select . items ; o ;
o = o - > next ) {
int opt_width ;
font_func - > width ( & fstyle ,
o - > text ,
strlen ( o - > text ) ,
& opt_width ) ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
if ( opt_maxwidth < opt_width )
opt_maxwidth = opt_width ;
}
b - > width = opt_maxwidth ;
if ( nsoption_bool ( core_select_menu ) )
b - > width + = SCROLLBAR_WIDTH ;
} else {
font_func - > width ( & fstyle , b - > text ,
b - > length , & b - > width ) ;
b - > flags | = MEASURED ;
}
}
max + = b - > width ;
if ( b - > next ) {
if ( b - > space = = UNKNOWN_WIDTH ) {
font_func - > width ( & fstyle , " " , 1 ,
& b - > space ) ;
}
max + = b - > space ;
2004-06-14 11:28:27 +04:00
}
2002-08-06 00:34:45 +04:00
2016-04-24 01:32:21 +03:00
if ( no_wrap ) {
/* Don't wrap due to block style,
* so min is the same as max */
min = max ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
} else if ( no_wrap_box ) {
/* This inline box can't be wrapped,
* for min , consider box ' s width */
if ( min < b - > width )
min = b - > width ;
} else if ( b - > parent - > flags & NEED_MIN ) {
/* If we care what the minimum width is,
* calculate it . ( It ' s only needed if we ' re
* shrinking - to - fit . ) */
/* min = widest single word */
i = 0 ;
do {
for ( j = i ; j ! = b - > length & &
b - > text [ j ] ! = ' ' ; j + + )
;
font_func - > width ( & fstyle , b - > text + i ,
j - i , & width ) ;
if ( min < width )
min = width ;
i = j + 1 ;
} while ( j ! = b - > length ) ;
2011-04-23 01:57:18 +04:00
}
2016-04-24 01:32:21 +03:00
* line_has_height = true ;
2007-03-25 03:47:44 +04:00
2016-04-24 01:32:21 +03:00
continue ;
2007-03-25 03:47:44 +04:00
}
2016-04-24 01:32:21 +03:00
/* inline replaced, 10.3.2 and 10.6.2 */
assert ( b - > style ) ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
/* calculate box width */
wtype = css_computed_width ( b - > style , & value , & unit ) ;
if ( wtype = = CSS_WIDTH_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
/*
b - > width = FPCT_OF_INT_TOINT ( value , width ) ;
*/
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
width = AUTO ;
} else {
width = FIXTOINT ( nscss_len2px ( value , unit ,
b - > style ) ) ;
if ( width < 0 )
width = 0 ;
}
} else {
width = AUTO ;
}
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
/* height */
htype = css_computed_height ( b - > style , & value , & unit ) ;
if ( htype = = CSS_HEIGHT_SET ) {
height = FIXTOINT ( nscss_len2px ( value , unit , b - > style ) ) ;
} else {
height = AUTO ;
}
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
if ( b - > object | | ( b - > flags & REPLACE_DIM ) ) {
if ( b - > object ) {
int temp_height = height ;
layout_get_object_dimensions ( b ,
& width , & temp_height ,
INT_MIN , INT_MAX ,
INT_MIN , INT_MAX ) ;
}
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
fixed = frac = 0 ;
calculate_mbp_width ( b - > style , LEFT , true , true , true ,
& fixed , & frac ) ;
calculate_mbp_width ( b - > style , RIGHT , true , true , true ,
& fixed , & frac ) ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
if ( 0 < width + fixed )
width + = fixed ;
} else if ( b - > flags & IFRAME ) {
/* TODO: handle percentage widths properly */
if ( width = = AUTO )
width = 400 ;
2008-03-10 02:41:08 +03:00
2016-04-24 01:32:21 +03:00
fixed = frac = 0 ;
calculate_mbp_width ( b - > style , LEFT , true , true , true ,
& fixed , & frac ) ;
calculate_mbp_width ( b - > style , RIGHT , true , true , true ,
& fixed , & frac ) ;
2008-03-21 02:07:55 +03:00
2016-04-24 01:32:21 +03:00
if ( 0 < width + fixed )
width + = fixed ;
} else {
/* form control with no object */
if ( width = = AUTO )
width = FIXTOINT ( nscss_len2px ( INTTOFIX ( 1 ) ,
CSS_UNIT_EM , b - > style ) ) ;
}
2008-03-21 02:07:55 +03:00
2016-04-24 01:32:21 +03:00
if ( min < width )
min = width ;
max + = width ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
* line_has_height = true ;
}
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
if ( first_line ) {
/* todo: handle percentage values properly */
/* todo: handle text-indent interaction with floats */
int text_indent = layout_text_indent (
first - > parent - > parent - > style , 100 ) ;
min = ( min + text_indent < 0 ) ? 0 : min + text_indent ;
max = ( max + text_indent < 0 ) ? 0 : max + text_indent ;
}
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
* line_min = min ;
* line_max = max ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
# ifdef LAYOUT_DEBUG
LOG ( " line_min %i, line_max %i " , min , max ) ;
# endif
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
assert ( b ! = first ) ;
assert ( 0 < = * line_min ) ;
assert ( * line_min < = * line_max ) ;
return b ;
}
2004-04-17 02:29:10 +04:00
2011-01-26 18:14:38 +03:00
2016-04-24 01:32:21 +03:00
/**
* Calculate minimum and maximum width of an inline container .
*
* \ param inline_container box of type INLINE_CONTAINER
* \ param [ out ] has_height set to true if container has height
* \ param font_func Font functions .
* \ post inline_container - > min_width and inline_container - > max_width filled in ,
* 0 < = inline_container - > min_width < = inline_container - > max_width
*/
static void
layout_minmax_inline_container ( struct box * inline_container ,
bool * has_height ,
const struct gui_layout_table * font_func )
{
struct box * child ;
int line_min = 0 , line_max = 0 ;
int min = 0 , max = 0 ;
bool first_line = true ;
bool line_has_height ;
2004-04-17 02:29:10 +04:00
2016-04-24 01:32:21 +03:00
assert ( inline_container - > type = = BOX_INLINE_CONTAINER ) ;
2009-05-28 15:14:32 +04:00
2016-04-24 01:32:21 +03:00
/* check if the widths have already been calculated */
if ( inline_container - > max_width ! = UNKNOWN_MAX_WIDTH )
return ;
2004-06-03 01:21:13 +04:00
2016-04-24 01:32:21 +03:00
* has_height = false ;
for ( child = inline_container - > children ; child ; ) {
child = layout_minmax_line ( child , & line_min , & line_max ,
first_line , & line_has_height , font_func ) ;
if ( min < line_min )
min = line_min ;
if ( max < line_max )
max = line_max ;
first_line = false ;
* has_height | = line_has_height ;
2013-02-07 02:39:45 +04:00
}
2016-04-24 01:32:21 +03:00
inline_container - > min_width = min ;
inline_container - > max_width = max ;
assert ( 0 < = inline_container - > min_width & &
inline_container - > min_width < =
inline_container - > max_width ) ;
2004-02-02 03:22:59 +03:00
}
2005-07-02 22:17:51 +04:00
/**
* Calculate minimum and maximum width of a block .
*
2014-11-13 01:36:11 +03:00
* \ param block box of type BLOCK , INLINE_BLOCK , or TABLE_CELL
* \ param font_func font functions
2005-07-22 01:48:41 +04:00
* \ post block - > min_width and block - > max_width filled in ,
* 0 < = block - > min_width < = block - > max_width
2005-07-02 22:17:51 +04:00
*/
2016-04-24 01:32:21 +03:00
static void
layout_minmax_block ( struct box * block , const struct gui_layout_table * font_func )
2005-07-02 22:17:51 +04:00
{
struct box * child ;
int min = 0 , max = 0 ;
int extra_fixed = 0 ;
float extra_frac = 0 ;
2009-11-22 16:46:23 +03:00
enum css_width_e wtype = CSS_WIDTH_AUTO ;
2009-07-24 03:05:34 +04:00
css_fixed width = 0 ;
css_unit wunit = CSS_UNIT_PX ;
2011-05-16 14:29:34 +04:00
enum css_height_e htype = CSS_HEIGHT_AUTO ;
2011-03-12 21:44:43 +03:00
css_fixed height = 0 ;
css_unit hunit = CSS_UNIT_PX ;
bool child_has_height = false ;
2005-07-02 22:17:51 +04:00
assert ( block - > type = = BOX_BLOCK | |
block - > type = = BOX_INLINE_BLOCK | |
2006-11-05 15:58:24 +03:00
block - > type = = BOX_TABLE_CELL ) ;
2005-07-02 22:17:51 +04:00
/* check if the widths have already been calculated */
if ( block - > max_width ! = UNKNOWN_MAX_WIDTH )
return ;
2011-03-12 21:44:43 +03:00
if ( block - > style ! = NULL ) {
2009-11-22 16:28:30 +03:00
wtype = css_computed_width ( block - > style , & width , & wunit ) ;
2011-03-12 21:44:43 +03:00
htype = css_computed_height ( block - > style , & height , & hunit ) ;
}
2009-07-24 03:05:34 +04:00
2011-04-26 19:03:44 +04:00
/* set whether the minimum width is of any interest for this box */
if ( ( ( block - > parent & & ( block - > parent - > type = = BOX_FLOAT_LEFT | |
block - > parent - > type = = BOX_FLOAT_RIGHT ) ) | |
block - > type = = BOX_INLINE_BLOCK ) & &
wtype ! = CSS_WIDTH_SET ) {
/* box shrinks to fit; need minimum width */
block - > flags | = NEED_MIN ;
2012-03-23 20:30:50 +04:00
} else if ( block - > type = = BOX_TABLE_CELL ) {
2011-04-26 19:03:44 +04:00
/* box shrinks to fit; need minimum width */
block - > flags | = NEED_MIN ;
} else if ( block - > parent & & ( block - > parent - > flags & NEED_MIN ) & &
2012-03-23 20:30:50 +04:00
wtype ! = CSS_WIDTH_SET ) {
2011-04-26 19:03:44 +04:00
/* box inside shrink-to-fit context; need minimum width */
block - > flags | = NEED_MIN ;
}
2008-04-25 18:15:18 +04:00
if ( block - > gadget & & ( block - > gadget - > type = = GADGET_TEXTBOX | |
block - > gadget - > type = = GADGET_PASSWORD | |
block - > gadget - > type = = GADGET_FILE | |
2008-04-25 18:57:36 +04:00
block - > gadget - > type = = GADGET_TEXTAREA ) & &
2009-07-24 03:05:34 +04:00
block - > style & & wtype = = CSS_WIDTH_AUTO ) {
css_fixed size = INTTOFIX ( 10 ) ;
css_unit unit = CSS_UNIT_EM ;
min = max = FIXTOINT ( nscss_len2px ( size , unit , block - > style ) ) ;
2011-03-12 21:44:43 +03:00
block - > flags | = HAS_HEIGHT ;
2008-04-25 18:15:18 +04:00
}
2008-09-21 03:25:37 +04:00
if ( block - > gadget & & ( block - > gadget - > type = = GADGET_RADIO | |
block - > gadget - > type = = GADGET_CHECKBOX ) & &
2009-07-24 03:05:34 +04:00
block - > style & & wtype = = CSS_WIDTH_AUTO ) {
css_fixed size = INTTOFIX ( 1 ) ;
css_unit unit = CSS_UNIT_EM ;
2008-09-21 03:25:37 +04:00
/* form checkbox or radio button
* if width is AUTO , set it to 1 em */
2009-07-24 03:05:34 +04:00
min = max = FIXTOINT ( nscss_len2px ( size , unit , block - > style ) ) ;
2011-03-12 21:44:43 +03:00
block - > flags | = HAS_HEIGHT ;
2008-09-21 03:25:37 +04:00
}
2005-10-31 00:23:24 +03:00
if ( block - > object ) {
2010-03-28 16:56:39 +04:00
if ( content_get_type ( block - > object ) = = CONTENT_HTML ) {
layout_minmax_block ( html_get_box_tree ( block - > object ) ,
First merge of Adam Blokus' GSoC work from his branch 'branches/adamblokus/netsurf'.
Merged revisions 4212-4552,4554-4709,4711-4724 via svnmerge from
svn://svn.netsurf-browser.org/branches/adamblokus/netsurf
........
r4212 | adamblokus | 2008-05-26 19:42:31 +0200 (Mon, 26 May 2008) | 4 lines
Pdf plotting skeleton pinned on Print Preview in GTK.
Just creates a file and draws lines.
........
r4213 | adamblokus | 2008-05-27 00:11:03 +0200 (Tue, 27 May 2008) | 4 lines
Pdf plotter - added drawing some graphic primitives.
Still with limited functionality, but a snapshot of the
currently viewed page can be made and resembles the original.
........
r4214 | adamblokus | 2008-05-27 11:43:31 +0200 (Tue, 27 May 2008) | 2 lines
Corrected encoding name
........
r4215 | adamblokus | 2008-05-27 12:47:26 +0200 (Tue, 27 May 2008) | 3 lines
Colours and polygons added.
........
r4217 | adamblokus | 2008-05-27 21:39:35 +0200 (Tue, 27 May 2008) | 6 lines
Added rectangles, filled boxes and clipping.
Taken into consideration joty's comments.
Added a todo list for this part.
Added some debug stuff and checking boundaries.
........
r4218 | adamblokus | 2008-05-28 12:37:30 +0200 (Wed, 28 May 2008) | 2 lines
Added path ploting (not sure if valid argument order for bezier) and dashed/dotted line styles
........
r4221 | adamblokus | 2008-05-28 22:11:05 +0200 (Wed, 28 May 2008) | 3 lines
Some more options in graphic primitives and normalizing some parameters.
........
r4235 | adamblokus | 2008-05-31 22:54:56 +0200 (Sat, 31 May 2008) | 4 lines
Plotting changed as jmb suggested (is the least invasive one from the possible)
Added dummy bitmap plotting - way of plotting an image is determined by its type.
........
r4251 | adamblokus | 2008-06-03 17:12:15 +0200 (Tue, 03 Jun 2008) | 3 lines
Added plotting jpg and png images - quite a lot to improve in this code, but it seems to work ;)
........
r4263 | adamblokus | 2008-06-05 14:20:32 +0200 (Thu, 05 Jun 2008) | 3 lines
Added hadling images other than png and jpeg - with transparency.
........
r4267 | adamblokus | 2008-06-06 15:36:34 +0200 (Fri, 06 Jun 2008) | 5 lines
Added handling NULL-returns from all mallocs.
Added plot_bitmap_tile handling.
Changed code style a little.
........
r4327 | adamblokus | 2008-06-12 17:46:34 +0200 (Thu, 12 Jun 2008) | 5 lines
Added a first prototype of the paged-output organization.
Still not sure about naming, file locations etc.
Works with the same pdf plotting as before.
........
r4328 | adamblokus | 2008-06-13 13:52:15 +0200 (Fri, 13 Jun 2008) | 4 lines
Added primitive width adjustment and outputing the whole
website in multiple pages.
........
r4336 | joty | 2008-06-15 15:06:57 +0200 (Sun, 15 Jun 2008) | 1 line
Fix RISC OS build failure (change r4235 wasn't complete).
........
r4337 | joty | 2008-06-15 18:15:32 +0200 (Sun, 15 Jun 2008) | 16 lines
This enables "Export PDF" in RISC OS build:
- Docs/Doxyfile(PREDEFINED): Added WITH_PDF_EXPORT
- Makefile.sources(S_PDF): Add to RISC OS target as well.
- utils/config.h: Define WITH_PDF_EXPORT which controls if we want to have
PDF export functionality or not.
- riscos/save_pdf.c,riscos/save_pdf.h(save_as_pdf): Use PDF print API made
by Adam Blokus to write a PDF file under RISC OS.
- riscos/save.c: Call save_as_pdf added.
- riscos/menus.c: Add 'Export->PDF' menu entry.
- riscos/menus.h(menu_action): Added BROWSER_EXPORT_PDF.
- desktop/gui.h(gui_save_type): Added GUI_SAVE_PDF.
- desktop/print.c(print_run): Added return value.
- Makefile(CCACHE): Moved closed to the place where CC is set for the first time.
(LDFLAGS): Centralised adding all non-pkgconfig libraries and added Haru + PNG libs.
........
r4343 | adamblokus | 2008-06-16 01:08:52 +0200 (Mon, 16 Jun 2008) | 3 lines
Added margins and page size adjustment.
........
r4412 | adamblokus | 2008-06-21 20:22:07 +0200 (Sat, 21 Jun 2008) | 4 lines
Added 'fuzzy' margins on page bottom.
Disabled direct png embedding, because it is too unstable in Haru now.
........
r4421 | adamblokus | 2008-06-22 18:52:28 +0200 (Sun, 22 Jun 2008) | 2 lines
Added "Save as.." dialog and Export->PDF menu entry. Print preview still works with default path.
........
r4437 | adamblokus | 2008-06-25 02:44:46 +0200 (Wed, 25 Jun 2008) | 4 lines
Added skeleton of applying loose layout.
Minor code cleaning-up.
........
r4492 | adamblokus | 2008-07-02 09:02:42 +0200 (Wed, 02 Jul 2008) | 5 lines
Implemented the elementar ideas of the loose layout.
Added scaling in the printing routine.
Added some basic demonstrations.
........
r4493 | adamblokus | 2008-07-02 09:05:55 +0200 (Wed, 02 Jul 2008) | 3 lines
Cleaned up the loosing code - commited to much of leftover rubbish code.
........
r4507 | adamblokus | 2008-07-04 14:25:48 +0200 (Fri, 04 Jul 2008) | 4 lines
Added duplicating box tree and current content - window flickering during printing solved.
Minor error checking after new HPDF_Image_AddSMask call.
........
r4515 | adamblokus | 2008-07-06 22:28:16 +0200 (Sun, 06 Jul 2008) | 2 lines
Changes in loosen layout (image resizing).
........
r4517 | adamblokus | 2008-07-06 22:38:23 +0200 (Sun, 06 Jul 2008) | 2 lines
Added pdf font handling and rendering functions with the use of Haru functions.
........
r4555 | adamblokus | 2008-07-10 00:59:05 +0200 (Thu, 10 Jul 2008) | 2 lines
Added a very basic and still buggy GTK print implementation.
........
r4565 | adamblokus | 2008-07-10 14:50:16 +0200 (Thu, 10 Jul 2008) | 2 lines
Added gtk printing one more time - I have forgotten to add the main file.
........
r4566 | adamblokus | 2008-07-10 14:57:02 +0200 (Thu, 10 Jul 2008) | 2 lines
removed error with comment
........
r4569 | adamblokus | 2008-07-10 15:52:55 +0200 (Thu, 10 Jul 2008) | 5 lines
Major style improvements - added a lot of doxygen comments,
followed tlsa's style guide.
Added some more error checking, too.
........
r4575 | adamblokus | 2008-07-10 18:48:26 +0200 (Thu, 10 Jul 2008) | 2 lines
Cleaned up the code.
........
r4687 | adamblokus | 2008-07-17 14:17:19 +0200 (Thu, 17 Jul 2008) | 2 lines
Changed everything according to jmb's review plus some minor bug fixes to gtk_print.
........
r4688 | adamblokus | 2008-07-17 17:16:34 +0200 (Thu, 17 Jul 2008) | 2 lines
Solved the netsurf.glade clash from r4421.
........
r4693 | adamblokus | 2008-07-18 18:11:51 +0200 (Fri, 18 Jul 2008) | 2 lines
Fixed bug with wrong number of pages in gtk printing.
........
r4695 | adamblokus | 2008-07-18 19:59:24 +0200 (Fri, 18 Jul 2008) | 3 lines
- fixed uncommented line from the previous commit
- fixed bug with scale bigger than 1.0 (incorretly clipped page)
........
r4696 | adamblokus | 2008-07-18 23:28:00 +0200 (Fri, 18 Jul 2008) | 2 lines
Fixed bug in gtk_print_font_paint (and nsfont_paint).
........
r4697 | adamblokus | 2008-07-18 23:35:38 +0200 (Fri, 18 Jul 2008) | 2 lines
Bug fix in nsfont_paint.
........
r4711 | adamblokus | 2008-07-19 22:44:15 +0200 (Sat, 19 Jul 2008) | 2 lines
Added gtk_selection files.
........
r4712 | adamblokus | 2008-07-20 11:15:06 +0200 (Sun, 20 Jul 2008) | 2 lines
Addam missing glade files.
........
r4713 | joty | 2008-07-20 17:13:10 +0200 (Sun, 20 Jul 2008) | 1 line
Follow change r4517 for RISC OS and BeOS platforms : Added pdf font handling and rendering functions with the use of Haru functions.
........
r4714 | joty | 2008-07-20 18:19:50 +0200 (Sun, 20 Jul 2008) | 1 line
Declare haru_nsfont iso define an instance for each C source including the font_haru.h header. This fixes breakage of PDF export on RISC OS.
........
r4724 | adamblokus | 2008-07-23 03:30:08 +0200 (Wed, 23 Jul 2008) | 6 lines
Applied changes according to joty's review.
Added checking the dimensions of a plotted image to pdf plotter.
Commented out jpg embedding (it seems to cause some problems
I'll bring it back when I figure out what's wrong) .
Added back some files removed by mistake.
........
svn path=/trunk/netsurf/; revision=4741
2008-07-26 20:01:59 +04:00
font_func ) ;
2010-03-28 16:56:39 +04:00
min = html_get_box_tree ( block - > object ) - > min_width ;
max = html_get_box_tree ( block - > object ) - > max_width ;
2005-10-31 00:23:24 +03:00
} else {
2010-03-28 16:56:39 +04:00
min = max = content_get_width ( block - > object ) ;
2005-10-31 00:23:24 +03:00
}
2011-03-12 21:44:43 +03:00
block - > flags | = HAS_HEIGHT ;
2011-06-15 00:00:18 +04:00
} else if ( block - > flags & IFRAME ) {
2014-11-13 01:36:11 +03:00
/** \todo do we need to know the min/max width of the iframe's
2011-06-15 00:00:18 +04:00
* content ? */
block - > flags | = HAS_HEIGHT ;
2005-10-31 00:23:24 +03:00
} else {
/* recurse through children */
for ( child = block - > children ; child ; child = child - > next ) {
switch ( child - > type ) {
case BOX_BLOCK :
First merge of Adam Blokus' GSoC work from his branch 'branches/adamblokus/netsurf'.
Merged revisions 4212-4552,4554-4709,4711-4724 via svnmerge from
svn://svn.netsurf-browser.org/branches/adamblokus/netsurf
........
r4212 | adamblokus | 2008-05-26 19:42:31 +0200 (Mon, 26 May 2008) | 4 lines
Pdf plotting skeleton pinned on Print Preview in GTK.
Just creates a file and draws lines.
........
r4213 | adamblokus | 2008-05-27 00:11:03 +0200 (Tue, 27 May 2008) | 4 lines
Pdf plotter - added drawing some graphic primitives.
Still with limited functionality, but a snapshot of the
currently viewed page can be made and resembles the original.
........
r4214 | adamblokus | 2008-05-27 11:43:31 +0200 (Tue, 27 May 2008) | 2 lines
Corrected encoding name
........
r4215 | adamblokus | 2008-05-27 12:47:26 +0200 (Tue, 27 May 2008) | 3 lines
Colours and polygons added.
........
r4217 | adamblokus | 2008-05-27 21:39:35 +0200 (Tue, 27 May 2008) | 6 lines
Added rectangles, filled boxes and clipping.
Taken into consideration joty's comments.
Added a todo list for this part.
Added some debug stuff and checking boundaries.
........
r4218 | adamblokus | 2008-05-28 12:37:30 +0200 (Wed, 28 May 2008) | 2 lines
Added path ploting (not sure if valid argument order for bezier) and dashed/dotted line styles
........
r4221 | adamblokus | 2008-05-28 22:11:05 +0200 (Wed, 28 May 2008) | 3 lines
Some more options in graphic primitives and normalizing some parameters.
........
r4235 | adamblokus | 2008-05-31 22:54:56 +0200 (Sat, 31 May 2008) | 4 lines
Plotting changed as jmb suggested (is the least invasive one from the possible)
Added dummy bitmap plotting - way of plotting an image is determined by its type.
........
r4251 | adamblokus | 2008-06-03 17:12:15 +0200 (Tue, 03 Jun 2008) | 3 lines
Added plotting jpg and png images - quite a lot to improve in this code, but it seems to work ;)
........
r4263 | adamblokus | 2008-06-05 14:20:32 +0200 (Thu, 05 Jun 2008) | 3 lines
Added hadling images other than png and jpeg - with transparency.
........
r4267 | adamblokus | 2008-06-06 15:36:34 +0200 (Fri, 06 Jun 2008) | 5 lines
Added handling NULL-returns from all mallocs.
Added plot_bitmap_tile handling.
Changed code style a little.
........
r4327 | adamblokus | 2008-06-12 17:46:34 +0200 (Thu, 12 Jun 2008) | 5 lines
Added a first prototype of the paged-output organization.
Still not sure about naming, file locations etc.
Works with the same pdf plotting as before.
........
r4328 | adamblokus | 2008-06-13 13:52:15 +0200 (Fri, 13 Jun 2008) | 4 lines
Added primitive width adjustment and outputing the whole
website in multiple pages.
........
r4336 | joty | 2008-06-15 15:06:57 +0200 (Sun, 15 Jun 2008) | 1 line
Fix RISC OS build failure (change r4235 wasn't complete).
........
r4337 | joty | 2008-06-15 18:15:32 +0200 (Sun, 15 Jun 2008) | 16 lines
This enables "Export PDF" in RISC OS build:
- Docs/Doxyfile(PREDEFINED): Added WITH_PDF_EXPORT
- Makefile.sources(S_PDF): Add to RISC OS target as well.
- utils/config.h: Define WITH_PDF_EXPORT which controls if we want to have
PDF export functionality or not.
- riscos/save_pdf.c,riscos/save_pdf.h(save_as_pdf): Use PDF print API made
by Adam Blokus to write a PDF file under RISC OS.
- riscos/save.c: Call save_as_pdf added.
- riscos/menus.c: Add 'Export->PDF' menu entry.
- riscos/menus.h(menu_action): Added BROWSER_EXPORT_PDF.
- desktop/gui.h(gui_save_type): Added GUI_SAVE_PDF.
- desktop/print.c(print_run): Added return value.
- Makefile(CCACHE): Moved closed to the place where CC is set for the first time.
(LDFLAGS): Centralised adding all non-pkgconfig libraries and added Haru + PNG libs.
........
r4343 | adamblokus | 2008-06-16 01:08:52 +0200 (Mon, 16 Jun 2008) | 3 lines
Added margins and page size adjustment.
........
r4412 | adamblokus | 2008-06-21 20:22:07 +0200 (Sat, 21 Jun 2008) | 4 lines
Added 'fuzzy' margins on page bottom.
Disabled direct png embedding, because it is too unstable in Haru now.
........
r4421 | adamblokus | 2008-06-22 18:52:28 +0200 (Sun, 22 Jun 2008) | 2 lines
Added "Save as.." dialog and Export->PDF menu entry. Print preview still works with default path.
........
r4437 | adamblokus | 2008-06-25 02:44:46 +0200 (Wed, 25 Jun 2008) | 4 lines
Added skeleton of applying loose layout.
Minor code cleaning-up.
........
r4492 | adamblokus | 2008-07-02 09:02:42 +0200 (Wed, 02 Jul 2008) | 5 lines
Implemented the elementar ideas of the loose layout.
Added scaling in the printing routine.
Added some basic demonstrations.
........
r4493 | adamblokus | 2008-07-02 09:05:55 +0200 (Wed, 02 Jul 2008) | 3 lines
Cleaned up the loosing code - commited to much of leftover rubbish code.
........
r4507 | adamblokus | 2008-07-04 14:25:48 +0200 (Fri, 04 Jul 2008) | 4 lines
Added duplicating box tree and current content - window flickering during printing solved.
Minor error checking after new HPDF_Image_AddSMask call.
........
r4515 | adamblokus | 2008-07-06 22:28:16 +0200 (Sun, 06 Jul 2008) | 2 lines
Changes in loosen layout (image resizing).
........
r4517 | adamblokus | 2008-07-06 22:38:23 +0200 (Sun, 06 Jul 2008) | 2 lines
Added pdf font handling and rendering functions with the use of Haru functions.
........
r4555 | adamblokus | 2008-07-10 00:59:05 +0200 (Thu, 10 Jul 2008) | 2 lines
Added a very basic and still buggy GTK print implementation.
........
r4565 | adamblokus | 2008-07-10 14:50:16 +0200 (Thu, 10 Jul 2008) | 2 lines
Added gtk printing one more time - I have forgotten to add the main file.
........
r4566 | adamblokus | 2008-07-10 14:57:02 +0200 (Thu, 10 Jul 2008) | 2 lines
removed error with comment
........
r4569 | adamblokus | 2008-07-10 15:52:55 +0200 (Thu, 10 Jul 2008) | 5 lines
Major style improvements - added a lot of doxygen comments,
followed tlsa's style guide.
Added some more error checking, too.
........
r4575 | adamblokus | 2008-07-10 18:48:26 +0200 (Thu, 10 Jul 2008) | 2 lines
Cleaned up the code.
........
r4687 | adamblokus | 2008-07-17 14:17:19 +0200 (Thu, 17 Jul 2008) | 2 lines
Changed everything according to jmb's review plus some minor bug fixes to gtk_print.
........
r4688 | adamblokus | 2008-07-17 17:16:34 +0200 (Thu, 17 Jul 2008) | 2 lines
Solved the netsurf.glade clash from r4421.
........
r4693 | adamblokus | 2008-07-18 18:11:51 +0200 (Fri, 18 Jul 2008) | 2 lines
Fixed bug with wrong number of pages in gtk printing.
........
r4695 | adamblokus | 2008-07-18 19:59:24 +0200 (Fri, 18 Jul 2008) | 3 lines
- fixed uncommented line from the previous commit
- fixed bug with scale bigger than 1.0 (incorretly clipped page)
........
r4696 | adamblokus | 2008-07-18 23:28:00 +0200 (Fri, 18 Jul 2008) | 2 lines
Fixed bug in gtk_print_font_paint (and nsfont_paint).
........
r4697 | adamblokus | 2008-07-18 23:35:38 +0200 (Fri, 18 Jul 2008) | 2 lines
Bug fix in nsfont_paint.
........
r4711 | adamblokus | 2008-07-19 22:44:15 +0200 (Sat, 19 Jul 2008) | 2 lines
Added gtk_selection files.
........
r4712 | adamblokus | 2008-07-20 11:15:06 +0200 (Sun, 20 Jul 2008) | 2 lines
Addam missing glade files.
........
r4713 | joty | 2008-07-20 17:13:10 +0200 (Sun, 20 Jul 2008) | 1 line
Follow change r4517 for RISC OS and BeOS platforms : Added pdf font handling and rendering functions with the use of Haru functions.
........
r4714 | joty | 2008-07-20 18:19:50 +0200 (Sun, 20 Jul 2008) | 1 line
Declare haru_nsfont iso define an instance for each C source including the font_haru.h header. This fixes breakage of PDF export on RISC OS.
........
r4724 | adamblokus | 2008-07-23 03:30:08 +0200 (Wed, 23 Jul 2008) | 6 lines
Applied changes according to joty's review.
Added checking the dimensions of a plotted image to pdf plotter.
Commented out jpg embedding (it seems to cause some problems
I'll bring it back when I figure out what's wrong) .
Added back some files removed by mistake.
........
svn path=/trunk/netsurf/; revision=4741
2008-07-26 20:01:59 +04:00
layout_minmax_block ( child , font_func ) ;
2011-03-12 21:44:43 +03:00
if ( child - > flags & HAS_HEIGHT )
child_has_height = true ;
2005-10-31 00:23:24 +03:00
break ;
case BOX_INLINE_CONTAINER :
2011-04-26 19:03:44 +04:00
if ( block - > flags & NEED_MIN )
child - > flags | = NEED_MIN ;
First merge of Adam Blokus' GSoC work from his branch 'branches/adamblokus/netsurf'.
Merged revisions 4212-4552,4554-4709,4711-4724 via svnmerge from
svn://svn.netsurf-browser.org/branches/adamblokus/netsurf
........
r4212 | adamblokus | 2008-05-26 19:42:31 +0200 (Mon, 26 May 2008) | 4 lines
Pdf plotting skeleton pinned on Print Preview in GTK.
Just creates a file and draws lines.
........
r4213 | adamblokus | 2008-05-27 00:11:03 +0200 (Tue, 27 May 2008) | 4 lines
Pdf plotter - added drawing some graphic primitives.
Still with limited functionality, but a snapshot of the
currently viewed page can be made and resembles the original.
........
r4214 | adamblokus | 2008-05-27 11:43:31 +0200 (Tue, 27 May 2008) | 2 lines
Corrected encoding name
........
r4215 | adamblokus | 2008-05-27 12:47:26 +0200 (Tue, 27 May 2008) | 3 lines
Colours and polygons added.
........
r4217 | adamblokus | 2008-05-27 21:39:35 +0200 (Tue, 27 May 2008) | 6 lines
Added rectangles, filled boxes and clipping.
Taken into consideration joty's comments.
Added a todo list for this part.
Added some debug stuff and checking boundaries.
........
r4218 | adamblokus | 2008-05-28 12:37:30 +0200 (Wed, 28 May 2008) | 2 lines
Added path ploting (not sure if valid argument order for bezier) and dashed/dotted line styles
........
r4221 | adamblokus | 2008-05-28 22:11:05 +0200 (Wed, 28 May 2008) | 3 lines
Some more options in graphic primitives and normalizing some parameters.
........
r4235 | adamblokus | 2008-05-31 22:54:56 +0200 (Sat, 31 May 2008) | 4 lines
Plotting changed as jmb suggested (is the least invasive one from the possible)
Added dummy bitmap plotting - way of plotting an image is determined by its type.
........
r4251 | adamblokus | 2008-06-03 17:12:15 +0200 (Tue, 03 Jun 2008) | 3 lines
Added plotting jpg and png images - quite a lot to improve in this code, but it seems to work ;)
........
r4263 | adamblokus | 2008-06-05 14:20:32 +0200 (Thu, 05 Jun 2008) | 3 lines
Added hadling images other than png and jpeg - with transparency.
........
r4267 | adamblokus | 2008-06-06 15:36:34 +0200 (Fri, 06 Jun 2008) | 5 lines
Added handling NULL-returns from all mallocs.
Added plot_bitmap_tile handling.
Changed code style a little.
........
r4327 | adamblokus | 2008-06-12 17:46:34 +0200 (Thu, 12 Jun 2008) | 5 lines
Added a first prototype of the paged-output organization.
Still not sure about naming, file locations etc.
Works with the same pdf plotting as before.
........
r4328 | adamblokus | 2008-06-13 13:52:15 +0200 (Fri, 13 Jun 2008) | 4 lines
Added primitive width adjustment and outputing the whole
website in multiple pages.
........
r4336 | joty | 2008-06-15 15:06:57 +0200 (Sun, 15 Jun 2008) | 1 line
Fix RISC OS build failure (change r4235 wasn't complete).
........
r4337 | joty | 2008-06-15 18:15:32 +0200 (Sun, 15 Jun 2008) | 16 lines
This enables "Export PDF" in RISC OS build:
- Docs/Doxyfile(PREDEFINED): Added WITH_PDF_EXPORT
- Makefile.sources(S_PDF): Add to RISC OS target as well.
- utils/config.h: Define WITH_PDF_EXPORT which controls if we want to have
PDF export functionality or not.
- riscos/save_pdf.c,riscos/save_pdf.h(save_as_pdf): Use PDF print API made
by Adam Blokus to write a PDF file under RISC OS.
- riscos/save.c: Call save_as_pdf added.
- riscos/menus.c: Add 'Export->PDF' menu entry.
- riscos/menus.h(menu_action): Added BROWSER_EXPORT_PDF.
- desktop/gui.h(gui_save_type): Added GUI_SAVE_PDF.
- desktop/print.c(print_run): Added return value.
- Makefile(CCACHE): Moved closed to the place where CC is set for the first time.
(LDFLAGS): Centralised adding all non-pkgconfig libraries and added Haru + PNG libs.
........
r4343 | adamblokus | 2008-06-16 01:08:52 +0200 (Mon, 16 Jun 2008) | 3 lines
Added margins and page size adjustment.
........
r4412 | adamblokus | 2008-06-21 20:22:07 +0200 (Sat, 21 Jun 2008) | 4 lines
Added 'fuzzy' margins on page bottom.
Disabled direct png embedding, because it is too unstable in Haru now.
........
r4421 | adamblokus | 2008-06-22 18:52:28 +0200 (Sun, 22 Jun 2008) | 2 lines
Added "Save as.." dialog and Export->PDF menu entry. Print preview still works with default path.
........
r4437 | adamblokus | 2008-06-25 02:44:46 +0200 (Wed, 25 Jun 2008) | 4 lines
Added skeleton of applying loose layout.
Minor code cleaning-up.
........
r4492 | adamblokus | 2008-07-02 09:02:42 +0200 (Wed, 02 Jul 2008) | 5 lines
Implemented the elementar ideas of the loose layout.
Added scaling in the printing routine.
Added some basic demonstrations.
........
r4493 | adamblokus | 2008-07-02 09:05:55 +0200 (Wed, 02 Jul 2008) | 3 lines
Cleaned up the loosing code - commited to much of leftover rubbish code.
........
r4507 | adamblokus | 2008-07-04 14:25:48 +0200 (Fri, 04 Jul 2008) | 4 lines
Added duplicating box tree and current content - window flickering during printing solved.
Minor error checking after new HPDF_Image_AddSMask call.
........
r4515 | adamblokus | 2008-07-06 22:28:16 +0200 (Sun, 06 Jul 2008) | 2 lines
Changes in loosen layout (image resizing).
........
r4517 | adamblokus | 2008-07-06 22:38:23 +0200 (Sun, 06 Jul 2008) | 2 lines
Added pdf font handling and rendering functions with the use of Haru functions.
........
r4555 | adamblokus | 2008-07-10 00:59:05 +0200 (Thu, 10 Jul 2008) | 2 lines
Added a very basic and still buggy GTK print implementation.
........
r4565 | adamblokus | 2008-07-10 14:50:16 +0200 (Thu, 10 Jul 2008) | 2 lines
Added gtk printing one more time - I have forgotten to add the main file.
........
r4566 | adamblokus | 2008-07-10 14:57:02 +0200 (Thu, 10 Jul 2008) | 2 lines
removed error with comment
........
r4569 | adamblokus | 2008-07-10 15:52:55 +0200 (Thu, 10 Jul 2008) | 5 lines
Major style improvements - added a lot of doxygen comments,
followed tlsa's style guide.
Added some more error checking, too.
........
r4575 | adamblokus | 2008-07-10 18:48:26 +0200 (Thu, 10 Jul 2008) | 2 lines
Cleaned up the code.
........
r4687 | adamblokus | 2008-07-17 14:17:19 +0200 (Thu, 17 Jul 2008) | 2 lines
Changed everything according to jmb's review plus some minor bug fixes to gtk_print.
........
r4688 | adamblokus | 2008-07-17 17:16:34 +0200 (Thu, 17 Jul 2008) | 2 lines
Solved the netsurf.glade clash from r4421.
........
r4693 | adamblokus | 2008-07-18 18:11:51 +0200 (Fri, 18 Jul 2008) | 2 lines
Fixed bug with wrong number of pages in gtk printing.
........
r4695 | adamblokus | 2008-07-18 19:59:24 +0200 (Fri, 18 Jul 2008) | 3 lines
- fixed uncommented line from the previous commit
- fixed bug with scale bigger than 1.0 (incorretly clipped page)
........
r4696 | adamblokus | 2008-07-18 23:28:00 +0200 (Fri, 18 Jul 2008) | 2 lines
Fixed bug in gtk_print_font_paint (and nsfont_paint).
........
r4697 | adamblokus | 2008-07-18 23:35:38 +0200 (Fri, 18 Jul 2008) | 2 lines
Bug fix in nsfont_paint.
........
r4711 | adamblokus | 2008-07-19 22:44:15 +0200 (Sat, 19 Jul 2008) | 2 lines
Added gtk_selection files.
........
r4712 | adamblokus | 2008-07-20 11:15:06 +0200 (Sun, 20 Jul 2008) | 2 lines
Addam missing glade files.
........
r4713 | joty | 2008-07-20 17:13:10 +0200 (Sun, 20 Jul 2008) | 1 line
Follow change r4517 for RISC OS and BeOS platforms : Added pdf font handling and rendering functions with the use of Haru functions.
........
r4714 | joty | 2008-07-20 18:19:50 +0200 (Sun, 20 Jul 2008) | 1 line
Declare haru_nsfont iso define an instance for each C source including the font_haru.h header. This fixes breakage of PDF export on RISC OS.
........
r4724 | adamblokus | 2008-07-23 03:30:08 +0200 (Wed, 23 Jul 2008) | 6 lines
Applied changes according to joty's review.
Added checking the dimensions of a plotted image to pdf plotter.
Commented out jpg embedding (it seems to cause some problems
I'll bring it back when I figure out what's wrong) .
Added back some files removed by mistake.
........
svn path=/trunk/netsurf/; revision=4741
2008-07-26 20:01:59 +04:00
layout_minmax_inline_container ( child ,
2011-03-12 21:44:43 +03:00
& child_has_height , font_func ) ;
2011-04-23 01:57:18 +04:00
if ( child_has_height & &
child = =
child - > parent - > children ) {
block - > flags | = MAKE_HEIGHT ;
}
2005-10-31 00:23:24 +03:00
break ;
case BOX_TABLE :
First merge of Adam Blokus' GSoC work from his branch 'branches/adamblokus/netsurf'.
Merged revisions 4212-4552,4554-4709,4711-4724 via svnmerge from
svn://svn.netsurf-browser.org/branches/adamblokus/netsurf
........
r4212 | adamblokus | 2008-05-26 19:42:31 +0200 (Mon, 26 May 2008) | 4 lines
Pdf plotting skeleton pinned on Print Preview in GTK.
Just creates a file and draws lines.
........
r4213 | adamblokus | 2008-05-27 00:11:03 +0200 (Tue, 27 May 2008) | 4 lines
Pdf plotter - added drawing some graphic primitives.
Still with limited functionality, but a snapshot of the
currently viewed page can be made and resembles the original.
........
r4214 | adamblokus | 2008-05-27 11:43:31 +0200 (Tue, 27 May 2008) | 2 lines
Corrected encoding name
........
r4215 | adamblokus | 2008-05-27 12:47:26 +0200 (Tue, 27 May 2008) | 3 lines
Colours and polygons added.
........
r4217 | adamblokus | 2008-05-27 21:39:35 +0200 (Tue, 27 May 2008) | 6 lines
Added rectangles, filled boxes and clipping.
Taken into consideration joty's comments.
Added a todo list for this part.
Added some debug stuff and checking boundaries.
........
r4218 | adamblokus | 2008-05-28 12:37:30 +0200 (Wed, 28 May 2008) | 2 lines
Added path ploting (not sure if valid argument order for bezier) and dashed/dotted line styles
........
r4221 | adamblokus | 2008-05-28 22:11:05 +0200 (Wed, 28 May 2008) | 3 lines
Some more options in graphic primitives and normalizing some parameters.
........
r4235 | adamblokus | 2008-05-31 22:54:56 +0200 (Sat, 31 May 2008) | 4 lines
Plotting changed as jmb suggested (is the least invasive one from the possible)
Added dummy bitmap plotting - way of plotting an image is determined by its type.
........
r4251 | adamblokus | 2008-06-03 17:12:15 +0200 (Tue, 03 Jun 2008) | 3 lines
Added plotting jpg and png images - quite a lot to improve in this code, but it seems to work ;)
........
r4263 | adamblokus | 2008-06-05 14:20:32 +0200 (Thu, 05 Jun 2008) | 3 lines
Added hadling images other than png and jpeg - with transparency.
........
r4267 | adamblokus | 2008-06-06 15:36:34 +0200 (Fri, 06 Jun 2008) | 5 lines
Added handling NULL-returns from all mallocs.
Added plot_bitmap_tile handling.
Changed code style a little.
........
r4327 | adamblokus | 2008-06-12 17:46:34 +0200 (Thu, 12 Jun 2008) | 5 lines
Added a first prototype of the paged-output organization.
Still not sure about naming, file locations etc.
Works with the same pdf plotting as before.
........
r4328 | adamblokus | 2008-06-13 13:52:15 +0200 (Fri, 13 Jun 2008) | 4 lines
Added primitive width adjustment and outputing the whole
website in multiple pages.
........
r4336 | joty | 2008-06-15 15:06:57 +0200 (Sun, 15 Jun 2008) | 1 line
Fix RISC OS build failure (change r4235 wasn't complete).
........
r4337 | joty | 2008-06-15 18:15:32 +0200 (Sun, 15 Jun 2008) | 16 lines
This enables "Export PDF" in RISC OS build:
- Docs/Doxyfile(PREDEFINED): Added WITH_PDF_EXPORT
- Makefile.sources(S_PDF): Add to RISC OS target as well.
- utils/config.h: Define WITH_PDF_EXPORT which controls if we want to have
PDF export functionality or not.
- riscos/save_pdf.c,riscos/save_pdf.h(save_as_pdf): Use PDF print API made
by Adam Blokus to write a PDF file under RISC OS.
- riscos/save.c: Call save_as_pdf added.
- riscos/menus.c: Add 'Export->PDF' menu entry.
- riscos/menus.h(menu_action): Added BROWSER_EXPORT_PDF.
- desktop/gui.h(gui_save_type): Added GUI_SAVE_PDF.
- desktop/print.c(print_run): Added return value.
- Makefile(CCACHE): Moved closed to the place where CC is set for the first time.
(LDFLAGS): Centralised adding all non-pkgconfig libraries and added Haru + PNG libs.
........
r4343 | adamblokus | 2008-06-16 01:08:52 +0200 (Mon, 16 Jun 2008) | 3 lines
Added margins and page size adjustment.
........
r4412 | adamblokus | 2008-06-21 20:22:07 +0200 (Sat, 21 Jun 2008) | 4 lines
Added 'fuzzy' margins on page bottom.
Disabled direct png embedding, because it is too unstable in Haru now.
........
r4421 | adamblokus | 2008-06-22 18:52:28 +0200 (Sun, 22 Jun 2008) | 2 lines
Added "Save as.." dialog and Export->PDF menu entry. Print preview still works with default path.
........
r4437 | adamblokus | 2008-06-25 02:44:46 +0200 (Wed, 25 Jun 2008) | 4 lines
Added skeleton of applying loose layout.
Minor code cleaning-up.
........
r4492 | adamblokus | 2008-07-02 09:02:42 +0200 (Wed, 02 Jul 2008) | 5 lines
Implemented the elementar ideas of the loose layout.
Added scaling in the printing routine.
Added some basic demonstrations.
........
r4493 | adamblokus | 2008-07-02 09:05:55 +0200 (Wed, 02 Jul 2008) | 3 lines
Cleaned up the loosing code - commited to much of leftover rubbish code.
........
r4507 | adamblokus | 2008-07-04 14:25:48 +0200 (Fri, 04 Jul 2008) | 4 lines
Added duplicating box tree and current content - window flickering during printing solved.
Minor error checking after new HPDF_Image_AddSMask call.
........
r4515 | adamblokus | 2008-07-06 22:28:16 +0200 (Sun, 06 Jul 2008) | 2 lines
Changes in loosen layout (image resizing).
........
r4517 | adamblokus | 2008-07-06 22:38:23 +0200 (Sun, 06 Jul 2008) | 2 lines
Added pdf font handling and rendering functions with the use of Haru functions.
........
r4555 | adamblokus | 2008-07-10 00:59:05 +0200 (Thu, 10 Jul 2008) | 2 lines
Added a very basic and still buggy GTK print implementation.
........
r4565 | adamblokus | 2008-07-10 14:50:16 +0200 (Thu, 10 Jul 2008) | 2 lines
Added gtk printing one more time - I have forgotten to add the main file.
........
r4566 | adamblokus | 2008-07-10 14:57:02 +0200 (Thu, 10 Jul 2008) | 2 lines
removed error with comment
........
r4569 | adamblokus | 2008-07-10 15:52:55 +0200 (Thu, 10 Jul 2008) | 5 lines
Major style improvements - added a lot of doxygen comments,
followed tlsa's style guide.
Added some more error checking, too.
........
r4575 | adamblokus | 2008-07-10 18:48:26 +0200 (Thu, 10 Jul 2008) | 2 lines
Cleaned up the code.
........
r4687 | adamblokus | 2008-07-17 14:17:19 +0200 (Thu, 17 Jul 2008) | 2 lines
Changed everything according to jmb's review plus some minor bug fixes to gtk_print.
........
r4688 | adamblokus | 2008-07-17 17:16:34 +0200 (Thu, 17 Jul 2008) | 2 lines
Solved the netsurf.glade clash from r4421.
........
r4693 | adamblokus | 2008-07-18 18:11:51 +0200 (Fri, 18 Jul 2008) | 2 lines
Fixed bug with wrong number of pages in gtk printing.
........
r4695 | adamblokus | 2008-07-18 19:59:24 +0200 (Fri, 18 Jul 2008) | 3 lines
- fixed uncommented line from the previous commit
- fixed bug with scale bigger than 1.0 (incorretly clipped page)
........
r4696 | adamblokus | 2008-07-18 23:28:00 +0200 (Fri, 18 Jul 2008) | 2 lines
Fixed bug in gtk_print_font_paint (and nsfont_paint).
........
r4697 | adamblokus | 2008-07-18 23:35:38 +0200 (Fri, 18 Jul 2008) | 2 lines
Bug fix in nsfont_paint.
........
r4711 | adamblokus | 2008-07-19 22:44:15 +0200 (Sat, 19 Jul 2008) | 2 lines
Added gtk_selection files.
........
r4712 | adamblokus | 2008-07-20 11:15:06 +0200 (Sun, 20 Jul 2008) | 2 lines
Addam missing glade files.
........
r4713 | joty | 2008-07-20 17:13:10 +0200 (Sun, 20 Jul 2008) | 1 line
Follow change r4517 for RISC OS and BeOS platforms : Added pdf font handling and rendering functions with the use of Haru functions.
........
r4714 | joty | 2008-07-20 18:19:50 +0200 (Sun, 20 Jul 2008) | 1 line
Declare haru_nsfont iso define an instance for each C source including the font_haru.h header. This fixes breakage of PDF export on RISC OS.
........
r4724 | adamblokus | 2008-07-23 03:30:08 +0200 (Wed, 23 Jul 2008) | 6 lines
Applied changes according to joty's review.
Added checking the dimensions of a plotted image to pdf plotter.
Commented out jpg embedding (it seems to cause some problems
I'll bring it back when I figure out what's wrong) .
Added back some files removed by mistake.
........
svn path=/trunk/netsurf/; revision=4741
2008-07-26 20:01:59 +04:00
layout_minmax_table ( child , font_func ) ;
2011-03-12 21:44:43 +03:00
/* todo: fix for zero height tables */
child_has_height = true ;
2011-04-23 01:57:18 +04:00
child - > flags | = MAKE_HEIGHT ;
2005-10-31 00:23:24 +03:00
break ;
default :
assert ( 0 ) ;
}
assert ( child - > max_width ! = UNKNOWN_MAX_WIDTH ) ;
2009-07-13 19:37:54 +04:00
if ( child - > style & &
2009-07-24 03:05:34 +04:00
( css_computed_position ( child - > style ) = =
2009-07-13 19:37:54 +04:00
CSS_POSITION_ABSOLUTE | |
2009-07-24 03:05:34 +04:00
css_computed_position ( child - > style ) = =
2009-07-13 19:37:54 +04:00
CSS_POSITION_FIXED ) ) {
/* This child is positioned out of normal flow,
* so it will have no affect on width */
continue ;
}
2005-10-31 00:23:24 +03:00
if ( min < child - > min_width )
min = child - > min_width ;
if ( max < child - > max_width )
max = child - > max_width ;
2011-03-12 21:44:43 +03:00
if ( child_has_height )
block - > flags | = HAS_HEIGHT ;
2005-07-02 22:17:51 +04:00
}
}
if ( max < min ) {
2014-07-13 21:07:12 +04:00
box_dump ( stderr , block , 0 , true ) ;
2005-07-02 22:17:51 +04:00
assert ( 0 ) ;
}
/* fixed width takes priority */
2009-07-24 03:05:34 +04:00
if ( block - > type ! = BOX_TABLE_CELL & & wtype = = CSS_WIDTH_SET & &
wunit ! = CSS_UNIT_PCT ) {
min = max = FIXTOINT ( nscss_len2px ( width , wunit , block - > style ) ) ;
2009-05-01 22:00:01 +04:00
}
2005-07-02 22:17:51 +04:00
2011-05-16 14:29:34 +04:00
if ( htype = = CSS_HEIGHT_SET & & hunit ! = CSS_UNIT_PCT & &
height > INTTOFIX ( 0 ) ) {
2011-04-23 01:57:18 +04:00
block - > flags | = MAKE_HEIGHT ;
2011-03-12 21:44:43 +03:00
block - > flags | = HAS_HEIGHT ;
2011-04-23 01:57:18 +04:00
}
2011-03-12 21:44:43 +03:00
2005-07-02 22:17:51 +04:00
/* add margins, border, padding to min, max widths */
2010-04-27 21:45:07 +04:00
/* Note: we don't know available width here so percentage margin
* and paddings are wrong . */
2009-07-24 03:05:34 +04:00
if ( block - > gadget & & wtype = = CSS_WIDTH_SET & &
2009-05-01 22:00:01 +04:00
( block - > gadget - > type = = GADGET_SUBMIT | |
block - > gadget - > type = = GADGET_RESET | |
2009-07-24 03:05:34 +04:00
block - > gadget - > type = = GADGET_BUTTON ) ) {
2009-05-01 22:00:01 +04:00
/* some gadgets with specified width already include border and
* padding , so just get margin */
calculate_mbp_width ( block - > style , LEFT , true , false , false ,
& extra_fixed , & extra_frac ) ;
calculate_mbp_width ( block - > style , RIGHT , true , false , false ,
& extra_fixed , & extra_frac ) ;
} else {
calculate_mbp_width ( block - > style , LEFT , true , true , true ,
& extra_fixed , & extra_frac ) ;
calculate_mbp_width ( block - > style , RIGHT , true , true , true ,
& extra_fixed , & extra_frac ) ;
}
2005-07-22 01:48:41 +04:00
if ( extra_fixed < 0 )
extra_fixed = 0 ;
if ( extra_frac < 0 )
extra_frac = 0 ;
2005-07-02 22:17:51 +04:00
if ( 1.0 < = extra_frac )
extra_frac = 0.9 ;
2010-04-27 21:45:07 +04:00
if ( block - > style ! = NULL & &
( css_computed_float ( block - > style ) = = CSS_FLOAT_LEFT | |
css_computed_float ( block - > style ) = = CSS_FLOAT_RIGHT ) ) {
/* floated boxs */
block - > min_width = min + extra_fixed ;
block - > max_width = max + extra_fixed ;
} else {
/* not floated */
block - > min_width = ( min + extra_fixed ) / ( 1.0 - extra_frac ) ;
block - > max_width = ( max + extra_fixed ) / ( 1.0 - extra_frac ) ;
}
2005-07-22 01:48:41 +04:00
assert ( 0 < = block - > min_width & & block - > min_width < = block - > max_width ) ;
2005-07-02 22:17:51 +04:00
}
2011-04-23 01:57:18 +04:00
/**
2016-04-24 01:32:21 +03:00
* Under some circumstances , specified dimensions for form elements include
* borders and padding .
2011-04-23 01:57:18 +04:00
*
2016-04-24 01:32:21 +03:00
* \ param box gadget to adjust dimensions of
* \ param percentage whether the gadget has its dimension specified as a
* percentage
* \ param available_width width of containing block
* \ param setwidth set true if the dimension to be tweaked is a width ,
* else set false for a height
* \ param dimension current value for given width / height dimension .
* updated to new value after consideration of
* gadget properties .
2011-04-23 01:57:18 +04:00
*/
2016-04-24 01:32:21 +03:00
static void layout_tweak_form_dimensions ( struct box * box , bool percentage ,
int available_width , bool setwidth , int * dimension )
2011-04-23 01:57:18 +04:00
{
2016-04-24 01:32:21 +03:00
int fixed = 0 ;
float frac = 0 ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
assert ( box & & box - > gadget ) ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
/* specified gadget widths include borders and padding in some
* cases */
if ( percentage | | box - > gadget - > type = = GADGET_SUBMIT | |
box - > gadget - > type = = GADGET_RESET | |
box - > gadget - > type = = GADGET_BUTTON ) {
calculate_mbp_width ( box - > style , setwidth ? LEFT : TOP ,
false , true , true , & fixed , & frac ) ;
calculate_mbp_width ( box - > style , setwidth ? RIGHT : BOTTOM ,
false , true , true , & fixed , & frac ) ;
* dimension - = frac * available_width + fixed ;
* dimension = * dimension > 0 ? * dimension : 0 ;
}
}
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
/**
* Calculate width , height , and thickness of margins , paddings , and borders .
*
* \ param available_width width of containing block
* \ param viewport_height height of viewport in pixels or - ve if unknown
* \ param box current box
* \ param style style giving width , height , margins , paddings ,
* and borders
* \ param width updated to width , may be NULL
* \ param height updated to height , may be NULL
* \ param max_width updated to max - width , may be NULL
* \ param min_width updated to min - width , may be NULL
* \ param max_height updated to max - height , may be NULL
* \ param min_height updated to min - height , may be NULL
* \ param margin filled with margins , may be NULL
* \ param padding filled with paddings , may be NULL
* \ param border filled with border widths , may be NULL
*/
static void
layout_find_dimensions ( int available_width ,
int viewport_height ,
struct box * box ,
const css_computed_style * style ,
int * width ,
int * height ,
int * max_width ,
int * min_width ,
int * max_height ,
int * min_height ,
int margin [ 4 ] ,
int padding [ 4 ] ,
struct box_border border [ 4 ] )
{
struct box * containing_block = NULL ;
unsigned int i ;
bool percentage ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
if ( width ) {
enum css_width_e wtype ;
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
wtype = css_computed_width ( style , & value , & unit ) ;
if ( wtype = = CSS_WIDTH_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
* width = FPCT_OF_INT_TOINT (
value , available_width ) ;
} else {
* width = FIXTOINT ( nscss_len2px ( value , unit ,
style ) ) ;
2011-04-23 01:57:18 +04:00
}
2016-04-24 01:32:21 +03:00
} else {
* width = AUTO ;
2011-04-23 01:57:18 +04:00
}
2016-04-24 01:32:21 +03:00
/* specified gadget widths include borders and padding in some
* cases */
if ( box - > gadget & & * width ! = AUTO ) {
percentage = unit = = CSS_UNIT_PCT ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
layout_tweak_form_dimensions ( box , percentage ,
available_width , true , width ) ;
}
}
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
if ( height ) {
enum css_height_e htype ;
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
htype = css_computed_height ( style , & value , & unit ) ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
if ( htype = = CSS_HEIGHT_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
enum css_height_e cbhtype ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
if ( css_computed_position ( box - > style ) = =
CSS_POSITION_ABSOLUTE & &
box - > parent ) {
/* Box is absolutely positioned */
assert ( box - > float_container ) ;
containing_block = box - > float_container ;
} else if ( box - > float_container & &
css_computed_position ( box - > style ) ! =
CSS_POSITION_ABSOLUTE & &
( css_computed_float ( box - > style ) = =
CSS_FLOAT_LEFT | |
css_computed_float ( box - > style ) = =
CSS_FLOAT_RIGHT ) ) {
/* Box is a float */
assert ( box - > parent & &
box - > parent - > parent & &
box - > parent - > parent - > parent ) ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
containing_block =
box - > parent - > parent - > parent ;
} else if ( box - > parent & & box - > parent - > type ! =
BOX_INLINE_CONTAINER ) {
/* Box is a block level element */
containing_block = box - > parent ;
} else if ( box - > parent & & box - > parent - > type = =
BOX_INLINE_CONTAINER ) {
/* Box is an inline block */
assert ( box - > parent - > parent ) ;
containing_block = box - > parent - > parent ;
}
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
if ( containing_block ) {
css_fixed f = 0 ;
css_unit u = CSS_UNIT_PX ;
2011-04-23 01:57:18 +04:00
2016-04-24 01:32:21 +03:00
cbhtype = css_computed_height (
containing_block - > style ,
& f , & u ) ;
}
2006-09-17 01:48:28 +04:00
2016-04-24 01:32:21 +03:00
if ( containing_block & &
containing_block - > height ! = AUTO & &
( css_computed_position ( box - > style ) = =
CSS_POSITION_ABSOLUTE | |
cbhtype = = CSS_HEIGHT_SET ) ) {
/* Box is absolutely positioned or its
* containing block has a valid
* specified height .
* ( CSS 2.1 Section 10.5 ) */
* height = FPCT_OF_INT_TOINT ( value ,
containing_block - > height ) ;
} else if ( ( ! box - > parent | |
! box - > parent - > parent ) & &
viewport_height > = 0 ) {
/* If root element or it's child
* ( HTML or BODY ) */
* height = FPCT_OF_INT_TOINT ( value ,
viewport_height ) ;
} else {
/* precentage height not permissible
* treat height as auto */
* height = AUTO ;
}
} else {
* height = FIXTOINT ( nscss_len2px ( value , unit ,
style ) ) ;
}
} else {
* height = AUTO ;
}
2006-09-17 01:48:28 +04:00
2016-04-24 01:32:21 +03:00
/* specified gadget heights include borders and padding in
* some cases */
if ( box - > gadget & & * height ! = AUTO ) {
percentage = unit = = CSS_UNIT_PCT ;
2006-09-17 01:48:28 +04:00
2016-04-24 01:32:21 +03:00
layout_tweak_form_dimensions ( box , percentage ,
available_width , false , height ) ;
}
2006-09-17 01:48:28 +04:00
}
2016-04-24 01:32:21 +03:00
if ( max_width ) {
enum css_max_width_e type ;
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
2006-09-17 01:48:28 +04:00
2016-04-24 01:32:21 +03:00
type = css_computed_max_width ( style , & value , & unit ) ;
2006-09-17 01:48:28 +04:00
2016-04-24 01:32:21 +03:00
if ( type = = CSS_MAX_WIDTH_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
* max_width = FPCT_OF_INT_TOINT ( value ,
available_width ) ;
} else {
* max_width = FIXTOINT ( nscss_len2px ( value , unit ,
style ) ) ;
}
} else {
/* Inadmissible */
* max_width = - 1 ;
}
2011-02-14 17:39:42 +03:00
2016-04-24 01:32:21 +03:00
/* specified gadget widths include borders and padding in some
* cases */
if ( box - > gadget & & * max_width ! = - 1 ) {
percentage = unit = = CSS_UNIT_PCT ;
2011-02-14 17:39:42 +03:00
2016-04-24 01:32:21 +03:00
layout_tweak_form_dimensions ( box , percentage ,
available_width , true , max_width ) ;
}
}
2011-09-23 21:34:04 +04:00
2016-04-24 01:32:21 +03:00
if ( min_width ) {
enum css_min_width_e type ;
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
2011-09-23 21:34:04 +04:00
2016-04-24 01:32:21 +03:00
type = css_computed_min_width ( style , & value , & unit ) ;
2011-09-23 21:34:04 +04:00
2016-04-24 01:32:21 +03:00
if ( type = = CSS_MIN_WIDTH_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
* min_width = FPCT_OF_INT_TOINT ( value ,
available_width ) ;
} else {
* min_width = FIXTOINT ( nscss_len2px ( value , unit ,
style ) ) ;
}
} else {
/* Inadmissible */
* min_width = 0 ;
2011-09-23 21:34:04 +04:00
}
2016-04-24 01:32:21 +03:00
/* specified gadget widths include borders and padding in some
* cases */
if ( box - > gadget & & * min_width ! = 0 ) {
percentage = unit = = CSS_UNIT_PCT ;
2011-02-14 17:39:42 +03:00
2016-04-24 01:32:21 +03:00
layout_tweak_form_dimensions ( box , percentage ,
available_width , true , min_width ) ;
2014-01-04 18:00:16 +04:00
}
2008-10-13 23:22:16 +04:00
}
2016-04-24 01:32:21 +03:00
if ( max_height ) {
enum css_max_height_e type ;
2011-02-15 17:31:18 +03:00
css_fixed value = 0 ;
2009-07-24 03:05:34 +04:00
css_unit unit = CSS_UNIT_PX ;
2016-04-24 01:32:21 +03:00
type = css_computed_max_height ( style , & value , & unit ) ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
if ( type = = CSS_MAX_HEIGHT_SET ) {
2009-07-24 03:05:34 +04:00
if ( unit = = CSS_UNIT_PCT ) {
2016-04-24 01:32:21 +03:00
/* TODO: handle percentage */
* max_height = - 1 ;
2009-07-24 03:05:34 +04:00
} else {
2016-04-24 01:32:21 +03:00
* max_height = FIXTOINT ( nscss_len2px ( value , unit ,
style ) ) ;
2008-10-13 23:22:16 +04:00
}
2016-04-24 01:32:21 +03:00
} else {
/* Inadmissible */
* max_height = - 1 ;
2008-03-09 22:39:17 +03:00
}
2016-04-24 01:32:21 +03:00
}
2008-03-09 22:39:17 +03:00
2016-04-24 01:32:21 +03:00
if ( min_height ) {
enum css_min_height_e type ;
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
type = css_computed_min_height ( style , & value , & unit ) ;
if ( type = = CSS_MIN_HEIGHT_SET ) {
2009-07-24 03:05:34 +04:00
if ( unit = = CSS_UNIT_PCT ) {
2016-04-24 01:32:21 +03:00
/* TODO: handle percentage */
* min_height = 0 ;
2009-07-24 03:05:34 +04:00
} else {
2016-04-24 01:32:21 +03:00
* min_height = FIXTOINT ( nscss_len2px ( value , unit ,
style ) ) ;
2008-10-13 23:22:16 +04:00
}
2016-04-24 01:32:21 +03:00
} else {
/* Inadmissible */
* min_height = 0 ;
2008-03-09 22:39:17 +03:00
}
}
2007-03-25 03:47:44 +04:00
2016-04-24 01:32:21 +03:00
for ( i = 0 ; i ! = 4 ; i + + ) {
if ( margin ) {
enum css_margin_e type = CSS_MARGIN_AUTO ;
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
switch ( i ) {
case TOP :
type = css_computed_margin_top ( style ,
& value , & unit ) ;
break ;
case RIGHT :
type = css_computed_margin_right ( style ,
& value , & unit ) ;
break ;
case BOTTOM :
type = css_computed_margin_bottom ( style ,
& value , & unit ) ;
break ;
case LEFT :
type = css_computed_margin_left ( style ,
& value , & unit ) ;
break ;
}
2007-03-25 03:47:44 +04:00
2016-04-24 01:32:21 +03:00
if ( type = = CSS_MARGIN_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
margin [ i ] = FPCT_OF_INT_TOINT ( value ,
available_width ) ;
} else {
margin [ i ] = FIXTOINT ( nscss_len2px ( value ,
unit , style ) ) ;
}
} else {
margin [ i ] = AUTO ;
}
}
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
if ( padding ) {
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
2014-06-01 21:36:22 +04:00
2016-04-24 01:32:21 +03:00
switch ( i ) {
case TOP :
css_computed_padding_top ( style , & value , & unit ) ;
break ;
case RIGHT :
css_computed_padding_right ( style , & value ,
& unit ) ;
break ;
case BOTTOM :
css_computed_padding_bottom ( style , & value ,
& unit ) ;
break ;
case LEFT :
css_computed_padding_left ( style , & value , & unit ) ;
break ;
}
if ( unit = = CSS_UNIT_PCT ) {
padding [ i ] = FPCT_OF_INT_TOINT ( value ,
available_width ) ;
} else {
padding [ i ] = FIXTOINT ( nscss_len2px ( value , unit ,
style ) ) ;
}
2014-06-01 21:36:22 +04:00
}
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
/* Table cell borders are populated in table.c */
if ( border & & box - > type ! = BOX_TABLE_CELL ) {
enum css_border_style_e bstyle = CSS_BORDER_STYLE_NONE ;
css_color color = 0 ;
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
2011-11-24 21:22:25 +04:00
2016-04-24 01:32:21 +03:00
switch ( i ) {
case TOP :
css_computed_border_top_width ( style , & value ,
& unit ) ;
bstyle = css_computed_border_top_style ( style ) ;
css_computed_border_top_color ( style , & color ) ;
break ;
case RIGHT :
css_computed_border_right_width ( style , & value ,
& unit ) ;
bstyle = css_computed_border_right_style ( style ) ;
css_computed_border_right_color ( style , & color ) ;
break ;
case BOTTOM :
css_computed_border_bottom_width ( style , & value ,
& unit ) ;
bstyle = css_computed_border_bottom_style (
style ) ;
css_computed_border_bottom_color ( style , & color ) ;
break ;
case LEFT :
css_computed_border_left_width ( style , & value ,
& unit ) ;
bstyle = css_computed_border_left_style ( style ) ;
css_computed_border_left_color ( style , & color ) ;
break ;
}
border [ i ] . style = bstyle ;
border [ i ] . c = color ;
if ( bstyle = = CSS_BORDER_STYLE_HIDDEN | |
bstyle = = CSS_BORDER_STYLE_NONE )
/* spec unclear: following Mozilla */
border [ i ] . width = 0 ;
else
border [ i ] . width = FIXTOINT ( nscss_len2px ( value ,
unit , style ) ) ;
/* Special case for border-collapse: make all borders
* on table / table - row - group / table - row zero width . */
if ( css_computed_border_collapse ( style ) = =
CSS_BORDER_COLLAPSE_COLLAPSE & &
( box - > type = = BOX_TABLE | |
box - > type = = BOX_TABLE_ROW_GROUP | |
box - > type = = BOX_TABLE_ROW ) )
border [ i ] . width = 0 ;
2006-09-10 17:27:08 +04:00
}
2004-10-18 01:10:19 +04:00
}
2004-04-12 04:00:47 +04:00
}
2016-04-24 01:32:21 +03:00
2004-04-12 04:00:47 +04:00
/**
2016-04-24 01:32:21 +03:00
* Find next block that current margin collapses to .
2009-08-21 21:05:22 +04:00
*
2016-04-24 01:32:21 +03:00
* \ param box box to start tree - order search from ( top margin is included )
* \ param block box responsible for current block fromatting context
* \ param viewport_height height of viewport in px
* \ param max_pos_margin updated to to maximum positive margin encountered
* \ param max_neg_margin updated to to maximum negative margin encountered
* \ return next box that current margin collapses to , or NULL if none .
2004-04-12 04:00:47 +04:00
*/
2016-04-24 01:32:21 +03:00
static struct box *
layout_next_margin_block ( struct box * box ,
struct box * block ,
int viewport_height ,
int * max_pos_margin ,
int * max_neg_margin )
2004-04-12 04:00:47 +04:00
{
2016-04-24 01:32:21 +03:00
assert ( block ! = NULL ) ;
2009-08-21 21:05:22 +04:00
2016-04-24 01:32:21 +03:00
while ( box ! = NULL ) {
2009-08-21 21:05:22 +04:00
2016-04-24 01:32:21 +03:00
if ( box - > type = = BOX_INLINE_CONTAINER | | ( box - > style & &
( css_computed_position ( box - > style ) ! =
CSS_POSITION_ABSOLUTE & &
css_computed_position ( box - > style ) ! =
CSS_POSITION_FIXED ) ) ) {
/* Not positioned */
2008-09-28 00:19:46 +04:00
2016-04-24 01:32:21 +03:00
/* Get margins */
if ( box - > style ) {
layout_find_dimensions ( box - > parent - > width ,
viewport_height , box ,
box - > style ,
NULL , NULL , NULL , NULL ,
NULL , NULL , box - > margin ,
box - > padding , box - > border ) ;
2009-08-21 21:05:22 +04:00
2016-04-24 01:32:21 +03:00
/* Apply top margin */
if ( * max_pos_margin < box - > margin [ TOP ] )
* max_pos_margin = box - > margin [ TOP ] ;
else if ( * max_neg_margin < - box - > margin [ TOP ] )
* max_neg_margin = - box - > margin [ TOP ] ;
}
2009-08-21 21:05:22 +04:00
2016-04-24 01:32:21 +03:00
/* Check whether box is the box current margin collapses
* to */
if ( box - > flags & MAKE_HEIGHT | |
box - > border [ TOP ] . width | |
box - > padding [ TOP ] | |
( box - > style & &
css_computed_overflow_y ( box - > style ) ! =
CSS_OVERFLOW_VISIBLE ) | |
( box - > type = = BOX_INLINE_CONTAINER & &
box ! = box - > parent - > children ) ) {
/* Collapse to this box; return it */
return box ;
}
2009-08-21 21:05:22 +04:00
}
2009-01-26 03:15:25 +03:00
2009-08-21 21:05:22 +04:00
2016-04-24 01:32:21 +03:00
/* Find next box */
if ( box - > type = = BOX_BLOCK & & ! box - > object & & box - > children & &
box - > style & &
css_computed_overflow_y ( box - > style ) = =
CSS_OVERFLOW_VISIBLE ) {
/* Down into children. */
box = box - > children ;
} else {
if ( ! box - > next ) {
/* No more siblings:
* Go up to first ancestor with a sibling . */
do {
/* Apply bottom margin */
if ( * max_pos_margin <
box - > margin [ BOTTOM ] )
* max_pos_margin =
box - > margin [ BOTTOM ] ;
else if ( * max_neg_margin <
- box - > margin [ BOTTOM ] )
* max_neg_margin =
- box - > margin [ BOTTOM ] ;
2009-01-26 03:15:25 +03:00
2016-04-24 01:32:21 +03:00
box = box - > parent ;
} while ( box ! = block & & ! box - > next ) ;
2009-01-26 03:15:25 +03:00
2016-04-24 01:32:21 +03:00
if ( box = = block ) {
/* Margins don't collapse with stuff
* outside the block formatting context
*/
return block ;
}
}
/* Apply bottom margin */
if ( * max_pos_margin < box - > margin [ BOTTOM ] )
* max_pos_margin = box - > margin [ BOTTOM ] ;
else if ( * max_neg_margin < - box - > margin [ BOTTOM ] )
* max_neg_margin = - box - > margin [ BOTTOM ] ;
/* To next sibling. */
box = box - > next ;
/* Get margins */
if ( box - > style ) {
layout_find_dimensions ( box - > parent - > width ,
viewport_height , box ,
box - > style ,
NULL , NULL , NULL , NULL ,
NULL , NULL , box - > margin ,
box - > padding , box - > border ) ;
}
}
}
return NULL ;
}
/**
* Find y coordinate which clears all floats on left and / or right .
*
* \ param fl first float in float list
* \ param clear type of clear
* \ return y coordinate relative to ancestor box for floats
*/
static int layout_clear ( struct box * fl , enum css_clear_e clear )
{
int y = 0 ;
for ( ; fl ; fl = fl - > next_float ) {
if ( ( clear = = CSS_CLEAR_LEFT | | clear = = CSS_CLEAR_BOTH ) & &
fl - > type = = BOX_FLOAT_LEFT )
if ( y < fl - > y + fl - > height )
y = fl - > y + fl - > height ;
if ( ( clear = = CSS_CLEAR_RIGHT | | clear = = CSS_CLEAR_BOTH ) & &
fl - > type = = BOX_FLOAT_RIGHT )
if ( y < fl - > y + fl - > height )
y = fl - > y + fl - > height ;
}
return y ;
}
/**
* Find left and right edges in a vertical range .
*
* \ param fl first float in float list
* \ param y0 start of y range to search
* \ param y1 end of y range to search
* \ param x0 start left edge , updated to available left edge
* \ param x1 start right edge , updated to available right edge
* \ param left returns float on left if present
* \ param right returns float on right if present
*/
static void
find_sides ( struct box * fl ,
int y0 , int y1 ,
int * x0 , int * x1 ,
struct box * * left ,
struct box * * right )
{
int fy0 , fy1 , fx0 , fx1 ;
# ifdef LAYOUT_DEBUG
LOG ( " y0 %i, y1 %i, x0 %i, x1 %i " , y0 , y1 , * x0 , * x1 ) ;
# endif
* left = * right = 0 ;
for ( ; fl ; fl = fl - > next_float ) {
fy1 = fl - > y + fl - > height ;
if ( fy1 < y0 ) {
/* Floats are sorted in order of decreasing bottom pos.
* Past here , all floats will be too high to concern us .
*/
return ;
}
fy0 = fl - > y ;
if ( y0 < fy1 & & fy0 < = y1 ) {
if ( fl - > type = = BOX_FLOAT_LEFT ) {
fx1 = fl - > x + fl - > width ;
if ( * x0 < fx1 ) {
* x0 = fx1 ;
* left = fl ;
}
} else {
fx0 = fl - > x ;
if ( fx0 < * x1 ) {
* x1 = fx0 ;
* right = fl ;
}
}
}
}
# ifdef LAYOUT_DEBUG
LOG ( " x0 %i, x1 %i, left %p, right %p " , * x0 , * x1 , * left , * right ) ;
# endif
}
/**
* Solve the width constraint as given in CSS 2.1 section 10.3 .3 .
*
* \ param box Box to solve constraint for
* \ param available_width Max width available in pixels
* \ param width Current box width
* \ param lm Min left margin required to avoid floats in px .
* zero if not applicable
* \ param rm Min right margin required to avoid floats in px .
* zero if not applicable
* \ param max_width Box max - width ( - ve means no max - width to apply )
* \ param min_width Box min - width ( < = 0 means no min - width to apply )
* \ return New box width
*
* \ post \ a box ' s left / right margins will be updated .
*/
static int
layout_solve_width ( struct box * box ,
int available_width ,
int width ,
int lm ,
int rm ,
int max_width ,
int min_width )
{
bool auto_width = false ;
/* Increase specified left/right margins */
if ( box - > margin [ LEFT ] ! = AUTO & & box - > margin [ LEFT ] < lm & &
box - > margin [ LEFT ] > = 0 )
box - > margin [ LEFT ] = lm ;
if ( box - > margin [ RIGHT ] ! = AUTO & & box - > margin [ RIGHT ] < rm & &
box - > margin [ RIGHT ] > = 0 )
box - > margin [ RIGHT ] = rm ;
/* Find width */
if ( width = = AUTO ) {
/* any other 'auto' become 0 or the minimum required values */
if ( box - > margin [ LEFT ] = = AUTO )
box - > margin [ LEFT ] = lm ;
if ( box - > margin [ RIGHT ] = = AUTO )
box - > margin [ RIGHT ] = rm ;
width = available_width -
( box - > margin [ LEFT ] + box - > border [ LEFT ] . width +
box - > padding [ LEFT ] + box - > padding [ RIGHT ] +
box - > border [ RIGHT ] . width + box - > margin [ RIGHT ] ) ;
width = width < 0 ? 0 : width ;
auto_width = true ;
}
if ( max_width > = 0 & & width > max_width ) {
/* max-width is admissable and width exceeds max-width */
width = max_width ;
auto_width = false ;
}
if ( min_width > 0 & & width < min_width ) {
/* min-width is admissable and width is less than max-width */
width = min_width ;
auto_width = false ;
}
/* Width was auto, and unconstrained by min/max width, so we're done */
if ( auto_width )
return width ;
/* Width was not auto, or was constrained by min/max width
* Need to compute left / right margins */
/* HTML alignment (only applies to over-constrained boxes) */
if ( box - > margin [ LEFT ] ! = AUTO & & box - > margin [ RIGHT ] ! = AUTO & &
box - > parent ! = NULL & & box - > parent - > style ! = NULL ) {
switch ( css_computed_text_align ( box - > parent - > style ) ) {
case CSS_TEXT_ALIGN_LIBCSS_RIGHT :
box - > margin [ LEFT ] = AUTO ;
box - > margin [ RIGHT ] = 0 ;
break ;
case CSS_TEXT_ALIGN_LIBCSS_CENTER :
box - > margin [ LEFT ] = box - > margin [ RIGHT ] = AUTO ;
break ;
case CSS_TEXT_ALIGN_LIBCSS_LEFT :
box - > margin [ LEFT ] = 0 ;
box - > margin [ RIGHT ] = AUTO ;
break ;
default :
/* Leave it alone; no HTML alignment */
break ;
}
}
if ( box - > margin [ LEFT ] = = AUTO & & box - > margin [ RIGHT ] = = AUTO ) {
/* make the margins equal, centering the element */
box - > margin [ LEFT ] = box - > margin [ RIGHT ] =
( available_width - lm - rm -
( box - > border [ LEFT ] . width + box - > padding [ LEFT ] +
width + box - > padding [ RIGHT ] +
box - > border [ RIGHT ] . width ) ) / 2 ;
if ( box - > margin [ LEFT ] < 0 ) {
box - > margin [ RIGHT ] + = box - > margin [ LEFT ] ;
box - > margin [ LEFT ] = 0 ;
}
box - > margin [ LEFT ] + = lm ;
} else if ( box - > margin [ LEFT ] = = AUTO ) {
box - > margin [ LEFT ] = available_width - lm -
2009-08-31 14:39:32 +04:00
( box - > border [ LEFT ] . width + box - > padding [ LEFT ] +
width + box - > padding [ RIGHT ] +
2009-08-21 21:05:22 +04:00
box - > border [ RIGHT ] . width + box - > margin [ RIGHT ] ) ;
2009-08-31 14:39:32 +04:00
box - > margin [ LEFT ] = box - > margin [ LEFT ] < lm
2009-08-21 21:05:22 +04:00
? lm : box - > margin [ LEFT ] ;
} else {
2005-07-31 03:32:48 +04:00
/* margin-right auto or "over-constrained" */
2009-08-21 21:05:22 +04:00
box - > margin [ RIGHT ] = available_width - rm -
( box - > margin [ LEFT ] + box - > border [ LEFT ] . width +
2009-08-31 14:39:32 +04:00
box - > padding [ LEFT ] + width +
box - > padding [ RIGHT ] +
2009-08-21 21:05:22 +04:00
box - > border [ RIGHT ] . width ) ;
2004-02-11 20:15:36 +03:00
}
2004-04-12 04:00:47 +04:00
return width ;
2004-02-11 20:15:36 +03:00
}
2006-05-07 21:20:18 +04:00
2004-02-11 20:15:36 +03:00
/**
2016-04-24 01:32:21 +03:00
* Compute dimensions of box , margins , paddings , and borders for a block - level
* element .
2009-04-15 17:22:28 +04:00
*
* \ param available_width Max width available in pixels
2016-04-24 01:32:21 +03:00
* \ param viewport_height Height of viewport in pixels or - ve if unknown
* \ param lm min left margin required to avoid floats in px .
* zero if not applicable
* \ param rm min right margin required to avoid floats in px .
* zero if not applicable
* \ param box box to find dimensions of . updated with new width ,
* height , margins , borders and paddings
*
* See CSS 2.1 10.3 .3 , 10.3 .4 , 10.6 .2 , and 10.6 .3 .
2004-02-11 20:15:36 +03:00
*/
2016-04-24 01:32:21 +03:00
static void
layout_block_find_dimensions ( int available_width ,
int viewport_height ,
int lm ,
int rm ,
struct box * box )
2004-02-11 20:15:36 +03:00
{
2016-04-24 01:32:21 +03:00
int width , max_width , min_width ;
int height , max_height , min_height ;
2006-06-26 08:52:34 +04:00
int * margin = box - > margin ;
int * padding = box - > padding ;
2009-07-24 03:05:34 +04:00
struct box_border * border = box - > border ;
2016-04-24 01:32:21 +03:00
const css_computed_style * style = box - > style ;
2004-02-11 20:15:36 +03:00
2016-04-24 01:32:21 +03:00
layout_find_dimensions ( available_width , viewport_height , box , style ,
& width , & height , & max_width , & min_width ,
& max_height , & min_height , margin , padding , border ) ;
2004-10-18 01:10:19 +04:00
2011-04-27 17:50:49 +04:00
if ( box - > object & & ! ( box - > flags & REPLACE_DIM ) & &
content_get_type ( box - > object ) ! = CONTENT_HTML ) {
2016-04-24 01:32:21 +03:00
/* block-level replaced element, see 10.3.4 and 10.6.2 */
2011-09-23 21:34:04 +04:00
layout_get_object_dimensions ( box , & width , & height ,
2014-01-04 18:00:16 +04:00
min_width , max_width , min_height , max_height ) ;
2004-05-21 18:26:59 +04:00
}
2016-04-24 01:32:21 +03:00
box - > width = layout_solve_width ( box , available_width , width , lm , rm ,
max_width , min_width ) ;
2006-06-26 08:52:34 +04:00
box - > height = height ;
if ( margin [ TOP ] = = AUTO )
margin [ TOP ] = 0 ;
if ( margin [ BOTTOM ] = = AUTO )
margin [ BOTTOM ] = 0 ;
2004-02-11 20:15:36 +03:00
}
/**
2016-04-24 01:32:21 +03:00
* Manipulate a block ' s [ RB ] padding / height / width to accommodate scrollbars
2004-12-02 00:48:11 +03:00
*
2016-04-24 01:32:21 +03:00
* \ param box Box to apply scrollbar space too . Must be BOX_BLOCK .
* \ param which Which scrollbar to make space for . Must be RIGHT or BOTTOM .
2004-02-11 20:15:36 +03:00
*/
2016-04-24 01:32:21 +03:00
static void layout_block_add_scrollbar ( struct box * box , int which )
2004-02-11 20:15:36 +03:00
{
2016-04-24 01:32:21 +03:00
enum css_overflow_e overflow_x , overflow_y ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
assert ( box - > type = = BOX_BLOCK & & ( which = = RIGHT | | which = = BOTTOM ) ) ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
if ( box - > style = = NULL )
return ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
overflow_x = css_computed_overflow_x ( box - > style ) ;
overflow_y = css_computed_overflow_y ( box - > style ) ;
if ( which = = BOTTOM & &
( overflow_x = = CSS_OVERFLOW_SCROLL | |
overflow_x = = CSS_OVERFLOW_AUTO | |
( box - > object & &
content_get_type ( box - > object ) = = CONTENT_HTML ) ) ) {
/* make space for scrollbar, unless height is AUTO */
if ( box - > height ! = AUTO & &
( overflow_x = = CSS_OVERFLOW_SCROLL | |
box_hscrollbar_present ( box ) ) ) {
box - > padding [ BOTTOM ] + = SCROLLBAR_WIDTH ;
2006-06-26 08:52:34 +04:00
}
2009-05-01 22:00:01 +04:00
2016-04-24 01:32:21 +03:00
} else if ( which = = RIGHT & &
( overflow_y = = CSS_OVERFLOW_SCROLL | |
overflow_y = = CSS_OVERFLOW_AUTO | |
( box - > object & &
content_get_type ( box - > object ) = = CONTENT_HTML ) ) ) {
/* make space for scrollbars, unless width is AUTO */
enum css_height_e htype ;
css_fixed height = 0 ;
css_unit hunit = CSS_UNIT_PX ;
htype = css_computed_height ( box - > style , & height , & hunit ) ;
2009-05-06 15:16:06 +04:00
2016-04-24 01:32:21 +03:00
if ( which = = RIGHT & & box - > width ! = AUTO & &
htype = = CSS_HEIGHT_SET & &
( overflow_y = = CSS_OVERFLOW_SCROLL | |
box_vscrollbar_present ( box ) ) ) {
box - > width - = SCROLLBAR_WIDTH ;
box - > padding [ RIGHT ] + = SCROLLBAR_WIDTH ;
2009-05-01 22:00:01 +04:00
}
2006-06-26 08:52:34 +04:00
}
2016-04-24 01:32:21 +03:00
}
2006-06-26 08:52:34 +04:00
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
/**
* Moves the children of a box by a specified amount
*
* \ param box top of tree of boxes
* \ param x the amount to move children by horizontally
* \ param y the amount to move children by vertically
*/
static void layout_move_children ( struct box * box , int x , int y )
{
assert ( box ) ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
for ( box = box - > children ; box ; box = box - > next ) {
box - > x + = x ;
box - > y + = y ;
}
}
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
/**
* Layout a table .
*
* \ param table table to layout
* \ param available_width width of containing block
* \ param content memory pool for any new boxes
* \ return true on success , false on memory exhaustion
*/
static bool layout_table ( struct box * table , int available_width ,
html_content * content )
{
unsigned int columns = table - > columns ; /* total columns */
unsigned int i ;
unsigned int * row_span ;
int * excess_y ;
int table_width , min_width = 0 , max_width = 0 ;
int required_width = 0 ;
int x , remainder = 0 , count = 0 ;
int table_height = 0 ;
int min_height = 0 ;
int * xs ; /* array of column x positions */
int auto_width ;
int spare_width ;
int relative_sum = 0 ;
int border_spacing_h = 0 , border_spacing_v = 0 ;
int spare_height ;
int positioned_columns = 0 ;
struct box * containing_block = NULL ;
struct box * c ;
struct box * row ;
struct box * row_group ;
struct box * * row_span_cell ;
struct column * col ;
const css_computed_style * style = table - > style ;
enum css_width_e wtype ;
enum css_height_e htype ;
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
assert ( table - > type = = BOX_TABLE ) ;
assert ( style ) ;
assert ( table - > children & & table - > children - > children ) ;
assert ( columns ) ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
/* allocate working buffers */
col = malloc ( columns * sizeof col [ 0 ] ) ;
excess_y = malloc ( columns * sizeof excess_y [ 0 ] ) ;
row_span = malloc ( columns * sizeof row_span [ 0 ] ) ;
row_span_cell = malloc ( columns * sizeof row_span_cell [ 0 ] ) ;
xs = malloc ( ( columns + 1 ) * sizeof xs [ 0 ] ) ;
if ( ! col | | ! xs | | ! row_span | | ! excess_y | | ! row_span_cell ) {
free ( col ) ;
free ( excess_y ) ;
free ( row_span ) ;
free ( row_span_cell ) ;
free ( xs ) ;
return false ;
2006-06-26 08:52:34 +04:00
}
2016-04-24 01:32:21 +03:00
memcpy ( col , table - > col , sizeof ( col [ 0 ] ) * columns ) ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
/* find margins, paddings, and borders for table and cells */
layout_find_dimensions ( available_width , - 1 , table , style , 0 , 0 , 0 , 0 ,
0 , 0 , table - > margin , table - > padding , table - > border ) ;
for ( row_group = table - > children ; row_group ;
row_group = row_group - > next ) {
for ( row = row_group - > children ; row ; row = row - > next ) {
for ( c = row - > children ; c ; c = c - > next ) {
enum css_overflow_e overflow_x ;
enum css_overflow_e overflow_y ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
assert ( c - > style ) ;
table_used_border_for_cell ( c ) ;
layout_find_dimensions ( available_width , - 1 ,
c , c - > style , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , c - > padding , c - > border ) ;
2009-05-01 22:00:01 +04:00
2016-04-24 01:32:21 +03:00
overflow_x = css_computed_overflow_x ( c - > style ) ;
overflow_y = css_computed_overflow_y ( c - > style ) ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
if ( overflow_x = = CSS_OVERFLOW_SCROLL | |
overflow_x = =
CSS_OVERFLOW_AUTO ) {
c - > padding [ BOTTOM ] + = SCROLLBAR_WIDTH ;
}
if ( overflow_y = = CSS_OVERFLOW_SCROLL | |
overflow_y = =
CSS_OVERFLOW_AUTO ) {
c - > padding [ RIGHT ] + = SCROLLBAR_WIDTH ;
}
}
2009-05-01 22:00:01 +04:00
}
2008-09-28 00:19:46 +04:00
}
2016-04-24 01:32:21 +03:00
/* border-spacing is used in the separated borders model */
if ( css_computed_border_collapse ( style ) = =
CSS_BORDER_COLLAPSE_SEPARATE ) {
css_fixed h = 0 , v = 0 ;
css_unit hu = CSS_UNIT_PX , vu = CSS_UNIT_PX ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
css_computed_border_spacing ( style , & h , & hu , & v , & vu ) ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
border_spacing_h = FIXTOINT ( nscss_len2px ( h , hu , style ) ) ;
border_spacing_v = FIXTOINT ( nscss_len2px ( v , vu , style ) ) ;
}
/* find specified table width, or available width if auto-width */
wtype = css_computed_width ( style , & value , & unit ) ;
if ( wtype = = CSS_WIDTH_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
table_width = FPCT_OF_INT_TOINT ( value , available_width ) ;
2009-07-24 03:05:34 +04:00
} else {
2016-04-24 01:32:21 +03:00
table_width =
FIXTOINT ( nscss_len2px ( value , unit , style ) ) ;
2008-09-28 00:19:46 +04:00
}
2009-05-01 22:00:01 +04:00
2016-04-24 01:32:21 +03:00
/* specified width includes border */
table_width - = table - > border [ LEFT ] . width +
table - > border [ RIGHT ] . width ;
table_width = table_width < 0 ? 0 : table_width ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
auto_width = table_width ;
} else {
table_width = AUTO ;
auto_width = available_width -
( ( table - > margin [ LEFT ] = = AUTO ? 0 :
table - > margin [ LEFT ] ) +
table - > border [ LEFT ] . width +
table - > padding [ LEFT ] +
table - > padding [ RIGHT ] +
table - > border [ RIGHT ] . width +
( table - > margin [ RIGHT ] = = AUTO ? 0 :
table - > margin [ RIGHT ] ) ) ;
2008-09-28 00:19:46 +04:00
}
2016-04-24 01:32:21 +03:00
/* Find any table height specified within CSS/HTML */
htype = css_computed_height ( style , & value , & unit ) ;
if ( htype = = CSS_HEIGHT_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
/* This is the minimum height for the table
* ( see 17.5 .3 ) */
if ( css_computed_position ( table - > style ) = =
CSS_POSITION_ABSOLUTE ) {
/* Table is absolutely positioned */
assert ( table - > float_container ) ;
containing_block = table - > float_container ;
} else if ( table - > float_container & &
css_computed_position ( table - > style ) ! =
CSS_POSITION_ABSOLUTE & &
( css_computed_float ( table - > style ) = =
CSS_FLOAT_LEFT | |
css_computed_float ( table - > style ) = =
CSS_FLOAT_RIGHT ) ) {
/* Table is a float */
assert ( table - > parent & & table - > parent - > parent & &
table - > parent - > parent - > parent ) ;
containing_block =
table - > parent - > parent - > parent ;
} else if ( table - > parent & & table - > parent - > type ! =
BOX_INLINE_CONTAINER ) {
/* Table is a block level element */
containing_block = table - > parent ;
} else if ( table - > parent & & table - > parent - > type = =
BOX_INLINE_CONTAINER ) {
/* Table is an inline block */
assert ( table - > parent - > parent ) ;
containing_block = table - > parent - > parent ;
2014-01-04 18:00:16 +04:00
}
2016-04-24 01:32:21 +03:00
if ( containing_block ) {
css_fixed ignored = 0 ;
2014-01-04 18:00:16 +04:00
2016-04-24 01:32:21 +03:00
htype = css_computed_height (
containing_block - > style ,
& ignored , & unit ) ;
}
2014-01-04 18:00:16 +04:00
2016-04-24 01:32:21 +03:00
if ( containing_block & &
containing_block - > height ! = AUTO & &
( css_computed_position ( table - > style ) = =
CSS_POSITION_ABSOLUTE | |
htype = = CSS_HEIGHT_SET ) ) {
/* Table is absolutely positioned or its
* containing block has a valid specified
* height . ( CSS 2.1 Section 10.5 ) */
min_height = FPCT_OF_INT_TOINT ( value ,
containing_block - > height ) ;
2014-01-04 18:00:16 +04:00
}
} else {
2016-04-24 01:32:21 +03:00
/* This is the minimum height for the table
* ( see 17.5 .3 ) */
min_height = FIXTOINT ( nscss_len2px ( value , unit , style ) ) ;
2014-01-04 18:00:16 +04:00
}
}
2016-04-24 01:32:21 +03:00
/* calculate width required by cells */
for ( i = 0 ; i ! = columns ; i + + ) {
2011-04-04 02:23:14 +04:00
# ifdef LAYOUT_DEBUG
2016-04-24 01:32:21 +03:00
LOG ( " table %p, column %u: type %s, width %i, min %i, max %i " , table , i , ( ( const char * [ ] ) {
" UNKNOWN " ,
" FIXED " ,
" AUTO " ,
" PERCENT " ,
" RELATIVE "
} ) [ col [ i ] . type ] , col [ i ] . width , col [ i ] . min , col [ i ] . max ) ;
2011-04-04 02:23:14 +04:00
# endif
2002-06-19 19:17:45 +04:00
2016-04-24 01:32:21 +03:00
if ( col [ i ] . positioned ) {
positioned_columns + + ;
continue ;
} else if ( col [ i ] . type = = COLUMN_WIDTH_FIXED ) {
if ( col [ i ] . width < col [ i ] . min )
col [ i ] . width = col [ i ] . max = col [ i ] . min ;
else
col [ i ] . min = col [ i ] . max = col [ i ] . width ;
required_width + = col [ i ] . width ;
} else if ( col [ i ] . type = = COLUMN_WIDTH_PERCENT ) {
int width = col [ i ] . width * auto_width / 100 ;
required_width + = col [ i ] . min < width ? width :
col [ i ] . min ;
} else
required_width + = col [ i ] . min ;
2006-03-27 01:41:18 +04:00
2011-04-04 02:23:14 +04:00
# ifdef LAYOUT_DEBUG
2016-04-24 01:32:21 +03:00
LOG ( " required_width %i " , required_width ) ;
2011-04-04 02:23:14 +04:00
# endif
2016-04-24 01:32:21 +03:00
}
required_width + = ( columns + 1 - positioned_columns ) *
border_spacing_h ;
2011-04-04 02:23:14 +04:00
# ifdef LAYOUT_DEBUG
2016-04-24 01:32:21 +03:00
LOG ( " width %i, min %i, max %i, auto %i, required %i " , table_width , table - > min_width , table - > max_width , auto_width , required_width ) ;
2011-04-04 02:23:14 +04:00
# endif
2004-03-26 04:35:35 +03:00
2016-04-24 01:32:21 +03:00
if ( auto_width < required_width ) {
/* table narrower than required width for columns:
* treat percentage widths as maximums */
for ( i = 0 ; i ! = columns ; i + + ) {
if ( col [ i ] . type = = COLUMN_WIDTH_RELATIVE )
continue ;
if ( col [ i ] . type = = COLUMN_WIDTH_PERCENT ) {
col [ i ] . max = auto_width * col [ i ] . width / 100 ;
if ( col [ i ] . max < col [ i ] . min )
col [ i ] . max = col [ i ] . min ;
2005-06-06 00:54:37 +04:00
}
2016-04-24 01:32:21 +03:00
min_width + = col [ i ] . min ;
max_width + = col [ i ] . max ;
2005-05-24 02:14:09 +04:00
}
2016-04-24 01:32:21 +03:00
} else {
/* take percentages exactly */
for ( i = 0 ; i ! = columns ; i + + ) {
if ( col [ i ] . type = = COLUMN_WIDTH_RELATIVE )
2005-07-02 22:17:51 +04:00
continue ;
2016-04-24 01:32:21 +03:00
if ( col [ i ] . type = = COLUMN_WIDTH_PERCENT ) {
int width = auto_width * col [ i ] . width / 100 ;
if ( width < col [ i ] . min )
width = col [ i ] . min ;
col [ i ] . min = col [ i ] . width = col [ i ] . max = width ;
col [ i ] . type = COLUMN_WIDTH_FIXED ;
2005-04-02 22:24:47 +04:00
}
2016-04-24 01:32:21 +03:00
min_width + = col [ i ] . min ;
max_width + = col [ i ] . max ;
}
}
2003-01-07 02:53:40 +03:00
2016-04-24 01:32:21 +03:00
/* allocate relative widths */
spare_width = auto_width ;
for ( i = 0 ; i ! = columns ; i + + ) {
if ( col [ i ] . type = = COLUMN_WIDTH_RELATIVE )
relative_sum + = col [ i ] . width ;
else if ( col [ i ] . type = = COLUMN_WIDTH_FIXED )
spare_width - = col [ i ] . width ;
else
spare_width - = col [ i ] . min ;
}
spare_width - = ( columns + 1 ) * border_spacing_h ;
if ( relative_sum ! = 0 ) {
if ( spare_width < 0 )
spare_width = 0 ;
for ( i = 0 ; i ! = columns ; i + + ) {
if ( col [ i ] . type = = COLUMN_WIDTH_RELATIVE ) {
col [ i ] . min = ceil ( col [ i ] . max =
( float ) spare_width
* ( float ) col [ i ] . width
/ relative_sum ) ;
min_width + = col [ i ] . min ;
max_width + = col [ i ] . max ;
2008-02-11 20:53:00 +03:00
}
2016-04-24 01:32:21 +03:00
}
}
min_width + = ( columns + 1 ) * border_spacing_h ;
max_width + = ( columns + 1 ) * border_spacing_h ;
2008-02-11 20:53:00 +03:00
2016-04-24 01:32:21 +03:00
if ( auto_width < = min_width ) {
/* not enough space: minimise column widths */
for ( i = 0 ; i < columns ; i + + ) {
col [ i ] . width = col [ i ] . min ;
}
table_width = min_width ;
} else if ( max_width < = auto_width ) {
/* more space than maximum width */
if ( table_width = = AUTO ) {
/* for auto-width tables, make columns max width */
for ( i = 0 ; i < columns ; i + + ) {
col [ i ] . width = col [ i ] . max ;
2011-03-06 01:18:06 +03:00
}
2016-04-24 01:32:21 +03:00
table_width = max_width ;
} else {
/* for fixed-width tables, distribute the extra space
* too */
unsigned int flexible_columns = 0 ;
for ( i = 0 ; i ! = columns ; i + + )
if ( col [ i ] . type ! = COLUMN_WIDTH_FIXED )
flexible_columns + + ;
if ( flexible_columns = = 0 ) {
int extra = ( table_width - max_width ) / columns ;
remainder = ( table_width - max_width ) -
( extra * columns ) ;
for ( i = 0 ; i ! = columns ; i + + ) {
col [ i ] . width = col [ i ] . max + extra ;
count - = remainder ;
if ( count < 0 ) {
col [ i ] . width + + ;
count + = columns ;
}
}
2011-03-06 01:18:06 +03:00
2016-04-24 01:32:21 +03:00
} else {
int extra = ( table_width - max_width ) /
flexible_columns ;
remainder = ( table_width - max_width ) -
( extra * flexible_columns ) ;
for ( i = 0 ; i ! = columns ; i + + )
if ( col [ i ] . type ! = COLUMN_WIDTH_FIXED ) {
col [ i ] . width = col [ i ] . max +
extra ;
count - = remainder ;
if ( count < 0 ) {
col [ i ] . width + + ;
count + = flexible_columns ;
}
}
2011-03-01 23:00:41 +03:00
}
2004-05-21 18:26:59 +04:00
}
2016-04-24 01:32:21 +03:00
} else {
/* space between min and max: fill it exactly */
float scale = ( float ) ( auto_width - min_width ) /
( float ) ( max_width - min_width ) ;
/* fprintf(stderr, "filling, scale %f\n", scale); */
for ( i = 0 ; i < columns ; i + + ) {
col [ i ] . width = col [ i ] . min + ( int ) ( 0.5 +
( col [ i ] . max - col [ i ] . min ) * scale ) ;
2004-05-21 18:26:59 +04:00
}
2016-04-24 01:32:21 +03:00
table_width = auto_width ;
2002-06-19 01:24:21 +04:00
}
2002-06-19 19:17:45 +04:00
2016-04-24 01:32:21 +03:00
xs [ 0 ] = x = border_spacing_h ;
for ( i = 0 ; i ! = columns ; i + + ) {
if ( ! col [ i ] . positioned )
x + = col [ i ] . width + border_spacing_h ;
xs [ i + 1 ] = x ;
row_span [ i ] = 0 ;
excess_y [ i ] = 0 ;
row_span_cell [ i ] = 0 ;
}
2002-06-19 01:24:21 +04:00
2016-04-24 01:32:21 +03:00
/* position cells */
table_height = border_spacing_v ;
for ( row_group = table - > children ; row_group ;
row_group = row_group - > next ) {
int row_group_height = 0 ;
for ( row = row_group - > children ; row ; row = row - > next ) {
int row_height = 0 ;
2004-02-02 01:42:40 +03:00
2016-04-24 01:32:21 +03:00
htype = css_computed_height ( row - > style , & value , & unit ) ;
if ( htype = = CSS_HEIGHT_SET & & unit ! = CSS_UNIT_PCT ) {
row_height = FIXTOINT ( nscss_len2px ( value , unit ,
row - > style ) ) ;
}
for ( c = row - > children ; c ; c = c - > next ) {
assert ( c - > style ) ;
c - > width = xs [ c - > start_column + c - > columns ] -
xs [ c - > start_column ] -
border_spacing_h -
c - > border [ LEFT ] . width -
c - > padding [ LEFT ] -
c - > padding [ RIGHT ] -
c - > border [ RIGHT ] . width ;
c - > float_children = 0 ;
c - > cached_place_below_level = 0 ;
2004-02-28 20:23:07 +03:00
2016-04-24 01:32:21 +03:00
c - > height = AUTO ;
if ( ! layout_block_context ( c , - 1 , content ) ) {
free ( col ) ;
free ( excess_y ) ;
free ( row_span ) ;
free ( row_span_cell ) ;
free ( xs ) ;
return false ;
}
/* warning: c->descendant_y0 and
* c - > descendant_y1 used as temporary storage
* until after vertical alignment is complete */
c - > descendant_y0 = c - > height ;
c - > descendant_y1 = c - > padding [ BOTTOM ] ;
2005-04-02 22:24:47 +04:00
2016-04-24 01:32:21 +03:00
htype = css_computed_height ( c - > style ,
& value , & unit ) ;
2011-04-04 02:23:14 +04:00
2016-04-24 01:32:21 +03:00
if ( htype = = CSS_HEIGHT_SET & &
unit ! = CSS_UNIT_PCT ) {
/* some sites use height="1" or similar
* to attempt to make cells as small as
* possible , so treat it as a minimum */
int h = FIXTOINT ( nscss_len2px ( value ,
unit , c - > style ) ) ;
if ( c - > height < h )
c - > height = h ;
}
/* specified row height is treated as a minimum
*/
if ( c - > height < row_height )
c - > height = row_height ;
c - > x = xs [ c - > start_column ] +
c - > border [ LEFT ] . width ;
c - > y = c - > border [ TOP ] . width ;
for ( i = 0 ; i ! = c - > columns ; i + + ) {
row_span [ c - > start_column + i ] = c - > rows ;
excess_y [ c - > start_column + i ] =
c - > border [ TOP ] . width +
c - > padding [ TOP ] +
c - > height +
c - > padding [ BOTTOM ] +
c - > border [ BOTTOM ] . width ;
row_span_cell [ c - > start_column + i ] = 0 ;
}
row_span_cell [ c - > start_column ] = c ;
c - > padding [ BOTTOM ] = - border_spacing_v -
c - > border [ TOP ] . width -
c - > padding [ TOP ] -
c - > height -
c - > border [ BOTTOM ] . width ;
}
for ( i = 0 ; i ! = columns ; i + + )
if ( row_span [ i ] ! = 0 )
row_span [ i ] - - ;
else
row_span_cell [ i ] = 0 ;
if ( row - > next | | row_group - > next ) {
/* row height is greatest excess of a cell
* which ends in this row */
for ( i = 0 ; i ! = columns ; i + + )
if ( row_span [ i ] = = 0 & & row_height <
excess_y [ i ] )
row_height = excess_y [ i ] ;
} else {
/* except in the last row */
for ( i = 0 ; i ! = columns ; i + + )
if ( row_height < excess_y [ i ] )
row_height = excess_y [ i ] ;
}
for ( i = 0 ; i ! = columns ; i + + ) {
if ( row_height < excess_y [ i ] )
excess_y [ i ] - = row_height ;
else
excess_y [ i ] = 0 ;
if ( row_span_cell [ i ] ! = 0 )
row_span_cell [ i ] - > padding [ BOTTOM ] + =
row_height +
border_spacing_v ;
}
2011-04-04 02:23:14 +04:00
2016-04-24 01:32:21 +03:00
row - > x = 0 ;
row - > y = row_group_height ;
row - > width = table_width ;
row - > height = row_height ;
row_group_height + = row_height + border_spacing_v ;
}
row_group - > x = 0 ;
row_group - > y = table_height ;
row_group - > width = table_width ;
row_group - > height = row_group_height ;
table_height + = row_group_height ;
}
/* Table height is either the height of the contents, or specified
* height if greater */
table_height = max ( table_height , min_height ) ;
/** \todo distribute spare height over the row groups / rows / cells */
2006-11-04 22:17:11 +03:00
2016-04-24 01:32:21 +03:00
/* perform vertical alignment */
for ( row_group = table - > children ; row_group ;
row_group = row_group - > next ) {
for ( row = row_group - > children ; row ; row = row - > next ) {
for ( c = row - > children ; c ; c = c - > next ) {
enum css_vertical_align_e vertical_align ;
2005-04-09 17:25:54 +04:00
2016-04-24 01:32:21 +03:00
/* unextended bottom padding is in
* c - > descendant_y1 , and unextended
* cell height is in c - > descendant_y0 */
spare_height = ( c - > padding [ BOTTOM ] -
c - > descendant_y1 ) +
( c - > height - c - > descendant_y0 ) ;
2004-02-11 20:15:36 +03:00
2016-04-24 01:32:21 +03:00
vertical_align = css_computed_vertical_align (
c - > style , & value , & unit ) ;
2004-02-11 20:15:36 +03:00
2016-04-24 01:32:21 +03:00
switch ( vertical_align ) {
case CSS_VERTICAL_ALIGN_SUB :
case CSS_VERTICAL_ALIGN_SUPER :
case CSS_VERTICAL_ALIGN_TEXT_TOP :
case CSS_VERTICAL_ALIGN_TEXT_BOTTOM :
case CSS_VERTICAL_ALIGN_SET :
case CSS_VERTICAL_ALIGN_BASELINE :
/* todo: baseline alignment, for now
* just use ALIGN_TOP */
case CSS_VERTICAL_ALIGN_TOP :
break ;
case CSS_VERTICAL_ALIGN_MIDDLE :
c - > padding [ TOP ] + = spare_height / 2 ;
c - > padding [ BOTTOM ] - = spare_height / 2 ;
layout_move_children ( c , 0 ,
spare_height / 2 ) ;
break ;
case CSS_VERTICAL_ALIGN_BOTTOM :
c - > padding [ TOP ] + = spare_height ;
c - > padding [ BOTTOM ] - = spare_height ;
layout_move_children ( c , 0 ,
spare_height ) ;
break ;
case CSS_VERTICAL_ALIGN_INHERIT :
assert ( 0 ) ;
break ;
2009-07-21 14:59:53 +04:00
}
2011-03-01 23:00:41 +03:00
}
2016-04-24 01:32:21 +03:00
}
}
2004-04-18 19:19:53 +04:00
2016-04-24 01:32:21 +03:00
/* Top and bottom margins of 'auto' are set to 0. CSS2.1 10.6.3 */
if ( table - > margin [ TOP ] = = AUTO )
table - > margin [ TOP ] = 0 ;
if ( table - > margin [ BOTTOM ] = = AUTO )
table - > margin [ BOTTOM ] = 0 ;
2011-04-04 02:23:14 +04:00
2016-04-24 01:32:21 +03:00
free ( col ) ;
free ( excess_y ) ;
free ( row_span ) ;
free ( row_span_cell ) ;
free ( xs ) ;
2004-02-11 20:15:36 +03:00
2016-04-24 01:32:21 +03:00
table - > width = table_width ;
table - > height = table_height ;
2011-04-04 02:23:14 +04:00
2016-04-24 01:32:21 +03:00
return true ;
}
2011-04-04 02:23:14 +04:00
2008-03-09 17:10:05 +03:00
2016-04-24 01:32:21 +03:00
/**
* Manimpulate box height according to CSS min - height and max - height properties
*
* \ param box block to modify with any min - height or max - height
* \ param container containing block for absolutely positioned elements , or
* NULL for non absolutely positioned elements .
* \ return whether the height has been changed
*/
static bool layout_apply_minmax_height ( struct box * box , struct box * container )
{
int h ;
struct box * containing_block = NULL ;
bool updated = false ;
2008-04-23 22:49:11 +04:00
2016-04-24 01:32:21 +03:00
/* Find containing block for percentage heights */
if ( box - > style ! = NULL & & css_computed_position ( box - > style ) = =
CSS_POSITION_ABSOLUTE ) {
/* Box is absolutely positioned */
assert ( container ) ;
containing_block = container ;
} else if ( box - > float_container & & box - > style ! = NULL & &
( css_computed_float ( box - > style ) = = CSS_FLOAT_LEFT | |
css_computed_float ( box - > style ) = = CSS_FLOAT_RIGHT ) ) {
/* Box is a float */
assert ( box - > parent & & box - > parent - > parent & &
box - > parent - > parent - > parent ) ;
containing_block = box - > parent - > parent - > parent ;
} else if ( box - > parent & & box - > parent - > type ! = BOX_INLINE_CONTAINER ) {
/* Box is a block level element */
containing_block = box - > parent ;
} else if ( box - > parent & & box - > parent - > type = = BOX_INLINE_CONTAINER ) {
/* Box is an inline block */
assert ( box - > parent - > parent ) ;
containing_block = box - > parent - > parent ;
}
if ( box - > style ) {
enum css_height_e htype = CSS_HEIGHT_AUTO ;
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
2009-02-02 15:56:15 +03:00
2016-04-24 01:32:21 +03:00
if ( containing_block ) {
htype = css_computed_height ( containing_block - > style ,
& value , & unit ) ;
}
/* max-height */
if ( css_computed_max_height ( box - > style , & value , & unit ) = =
CSS_MAX_HEIGHT_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
if ( containing_block & &
containing_block - > height ! = AUTO & &
( css_computed_position ( box - > style ) = =
CSS_POSITION_ABSOLUTE | |
htype = = CSS_HEIGHT_SET ) ) {
/* Box is absolutely positioned or its
* containing block has a valid
* specified height . ( CSS 2.1
* Section 10.5 ) */
h = FPCT_OF_INT_TOINT ( value ,
containing_block - > height ) ;
if ( h < box - > height ) {
box - > height = h ;
updated = true ;
}
}
} else {
h = FIXTOINT ( nscss_len2px ( value , unit ,
box - > style ) ) ;
if ( h < box - > height ) {
box - > height = h ;
updated = true ;
2008-03-09 17:10:05 +03:00
}
2002-06-19 01:24:21 +04:00
}
2016-04-24 01:32:21 +03:00
}
2011-06-15 01:09:38 +04:00
2016-04-24 01:32:21 +03:00
/* min-height */
if ( css_computed_min_height ( box - > style , & value , & unit ) = =
CSS_MIN_HEIGHT_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
if ( containing_block & &
containing_block - > height ! = AUTO & &
( css_computed_position ( box - > style ) = =
CSS_POSITION_ABSOLUTE | |
htype = = CSS_HEIGHT_SET ) ) {
/* Box is absolutely positioned or its
* containing block has a valid
* specified height . ( CSS 2.1
* Section 10.5 ) */
h = FPCT_OF_INT_TOINT ( value ,
containing_block - > height ) ;
if ( h > box - > height ) {
box - > height = h ;
updated = true ;
}
}
} else {
h = FIXTOINT ( nscss_len2px ( value , unit ,
box - > style ) ) ;
if ( h > box - > height ) {
box - > height = h ;
updated = true ;
}
}
2002-06-19 01:24:21 +04:00
}
}
2016-04-24 01:32:21 +03:00
return updated ;
}
2002-06-19 01:24:21 +04:00
2016-04-24 01:32:21 +03:00
/**
* Layout a block which contains an object .
*
* \ param block box of type BLOCK , INLINE_BLOCK , TABLE , or TABLE_CELL
* \ return true on success , false on memory exhaustion
*/
static bool layout_block_object ( struct box * block )
{
assert ( block ) ;
assert ( block - > type = = BOX_BLOCK | |
block - > type = = BOX_INLINE_BLOCK | |
block - > type = = BOX_TABLE | |
block - > type = = BOX_TABLE_CELL ) ;
assert ( block - > object ) ;
2002-12-27 20:28:19 +03:00
2016-04-24 01:32:21 +03:00
# ifdef LAYOUT_DEBUG
LOG ( " block %p, object %s, width %i " , block , hlcache_handle_get_url ( block - > object ) , block - > width ) ;
# endif
2002-12-27 20:28:19 +03:00
2016-04-24 01:32:21 +03:00
if ( content_get_type ( block - > object ) = = CONTENT_HTML ) {
content_reformat ( block - > object , false , block - > width , 1 ) ;
} else {
/* Non-HTML objects */
/* this case handled already in
* layout_block_find_dimensions ( ) */
}
2002-06-21 22:16:24 +04:00
2016-04-24 01:32:21 +03:00
return true ;
}
2013-02-10 20:50:15 +04:00
2016-04-24 01:32:21 +03:00
/**
* Layout a block formatting context .
*
* \ param block BLOCK , INLINE_BLOCK , or TABLE_CELL to layout
* \ param viewport_height Height of viewport in pixels or - ve if unknown
* \ param content Memory pool for any new boxes
* \ return true on success , false on memory exhaustion
*
* This function carries out layout of a block and its children , as described
* in CSS 2.1 9.4 .1 .
*/
static bool
layout_block_context ( struct box * block ,
int viewport_height ,
html_content * content )
{
struct box * box ;
int cx , cy ; /**< current coordinates */
int max_pos_margin = 0 ;
int max_neg_margin = 0 ;
int y = 0 ;
int lm , rm ;
struct box * margin_collapse = NULL ;
bool in_margin = false ;
css_fixed gadget_size ;
css_unit gadget_unit ; /* Checkbox / radio buttons */
2006-04-09 22:59:07 +04:00
2016-04-24 01:32:21 +03:00
assert ( block - > type = = BOX_BLOCK | |
block - > type = = BOX_INLINE_BLOCK | |
block - > type = = BOX_TABLE_CELL ) ;
assert ( block - > width ! = UNKNOWN_WIDTH ) ;
assert ( block - > width ! = AUTO ) ;
2012-11-04 23:55:24 +04:00
2016-04-24 01:32:21 +03:00
block - > float_children = NULL ;
block - > cached_place_below_level = 0 ;
block - > clear_level = 0 ;
/* special case if the block contains an object */
if ( block - > object ) {
int temp_width = block - > width ;
if ( ! layout_block_object ( block ) )
return false ;
layout_get_object_dimensions ( block , & temp_width ,
& block - > height , INT_MIN , INT_MAX ,
INT_MIN , INT_MAX ) ;
return true ;
} else if ( block - > flags & REPLACE_DIM ) {
return true ;
}
/* special case if the block contains an radio button or checkbox */
if ( block - > gadget & & ( block - > gadget - > type = = GADGET_RADIO | |
block - > gadget - > type = = GADGET_CHECKBOX ) ) {
/* form checkbox or radio button
* if width or height is AUTO , set it to 1 em */
gadget_unit = CSS_UNIT_EM ;
gadget_size = INTTOFIX ( 1 ) ;
if ( block - > height = = AUTO )
block - > height = FIXTOINT ( nscss_len2px ( gadget_size ,
gadget_unit , block - > style ) ) ;
}
box = block - > children ;
/* set current coordinates to top-left of the block */
cx = 0 ;
y = cy = block - > padding [ TOP ] ;
if ( box )
box - > y = block - > padding [ TOP ] ;
/* Step through the descendants of the block in depth-first order, but
* not into the children of boxes which aren ' t blocks . For example , if
* the tree passed to this function looks like this ( box - > type shown ) :
*
* block - > BOX_BLOCK
* BOX_BLOCK * ( 1 )
* BOX_INLINE_CONTAINER * ( 2 )
* BOX_INLINE
* BOX_TEXT
* . . .
* BOX_BLOCK * ( 3 )
* BOX_TABLE * ( 4 )
* BOX_TABLE_ROW
* BOX_TABLE_CELL
* . . .
* BOX_TABLE_CELL
* . . .
* BOX_BLOCK * ( 5 )
* BOX_INLINE_CONTAINER * ( 6 )
* BOX_TEXT
* . . .
* then the while loop will visit each box marked with * , setting box
* to each in the order shown . */
while ( box ) {
enum css_overflow_e overflow_x = CSS_OVERFLOW_VISIBLE ;
enum css_overflow_e overflow_y = CSS_OVERFLOW_VISIBLE ;
assert ( box - > type = = BOX_BLOCK | | box - > type = = BOX_TABLE | |
box - > type = = BOX_INLINE_CONTAINER ) ;
/* Tables are laid out before being positioned, because the
* position depends on the width which is calculated in
* table layout . Blocks and inline containers are positioned
* before being laid out , because width is not dependent on
* content , and the position is required during layout for
* correct handling of floats .
*/
2012-11-04 23:55:24 +04:00
2016-04-24 01:32:21 +03:00
if ( box - > style & &
( css_computed_position ( box - > style ) = =
CSS_POSITION_ABSOLUTE | |
css_computed_position ( box - > style ) = =
CSS_POSITION_FIXED ) ) {
box - > x = box - > parent - > padding [ LEFT ] ;
/* absolute positioned; this element will establish
* its own block context when it gets laid out later ,
* so no need to look at its children now . */
goto advance_to_next_box ;
2002-05-04 23:57:18 +04:00
}
2016-04-24 01:32:21 +03:00
/* If we don't know which box the current margin collapses
* through to , find out . Update the pos / neg margin values . */
if ( margin_collapse = = NULL ) {
margin_collapse = layout_next_margin_block ( box , block ,
viewport_height ,
& max_pos_margin , & max_neg_margin ) ;
/* We have a margin that has not yet been applied. */
in_margin = true ;
2009-08-21 21:05:22 +04:00
}
2010-04-27 16:02:12 +04:00
2016-04-24 01:32:21 +03:00
/* Clearance. */
y = 0 ;
if ( box - > style & & css_computed_clear ( box - > style ) ! =
CSS_CLEAR_NONE )
y = layout_clear ( block - > float_children ,
css_computed_clear ( box - > style ) ) ;
2010-04-27 16:02:12 +04:00
2016-04-24 01:32:21 +03:00
/* Find box's overflow properties */
if ( box - > style ) {
overflow_x = css_computed_overflow_x ( box - > style ) ;
overflow_y = css_computed_overflow_y ( box - > style ) ;
2002-06-19 01:24:21 +04:00
}
2009-01-31 16:26:28 +03:00
2016-04-24 01:32:21 +03:00
/* Blocks establishing a block formatting context get minimum
* left and right margins to avoid any floats . */
lm = rm = 0 ;
2002-06-19 19:17:45 +04:00
2016-04-24 01:32:21 +03:00
if ( box - > type = = BOX_BLOCK | | box - > flags & IFRAME ) {
if ( ! box - > object & & ! ( box - > flags & IFRAME ) & &
! ( box - > flags & REPLACE_DIM ) & &
box - > style & &
( overflow_x ! = CSS_OVERFLOW_VISIBLE | |
overflow_y ! = CSS_OVERFLOW_VISIBLE ) ) {
/* box establishes new block formatting context
* so available width may be diminished due to
* floats . */
int x0 , x1 , top ;
struct box * left , * right ;
top = cy + max_pos_margin - max_neg_margin ;
top = ( top > y ) ? top : y ;
x0 = cx ;
x1 = cx + box - > parent - > width -
box - > parent - > padding [ LEFT ] -
box - > parent - > padding [ RIGHT ] ;
find_sides ( block - > float_children , top , top ,
& x0 , & x1 , & left , & right ) ;
/* calculate min required left & right margins
* needed to avoid floats */
lm = x0 - cx ;
rm = cx + box - > parent - > width -
box - > parent - > padding [ LEFT ] -
box - > parent - > padding [ RIGHT ] -
x1 ;
}
layout_block_find_dimensions ( box - > parent - > width ,
viewport_height , lm , rm , box ) ;
if ( box - > type = = BOX_BLOCK & & ! ( box - > flags & IFRAME ) ) {
layout_block_add_scrollbar ( box , RIGHT ) ;
layout_block_add_scrollbar ( box , BOTTOM ) ;
}
} else if ( box - > type = = BOX_TABLE ) {
if ( box - > style ! = NULL ) {
enum css_width_e wtype ;
css_fixed width = 0 ;
css_unit unit = CSS_UNIT_PX ;
2005-08-01 01:57:07 +04:00
2016-04-24 01:32:21 +03:00
wtype = css_computed_width ( box - > style , & width ,
& unit ) ;
if ( wtype = = CSS_WIDTH_AUTO ) {
/* max available width may be
* diminished due to floats . */
int x0 , x1 , top ;
struct box * left , * right ;
top = cy + max_pos_margin -
max_neg_margin ;
top = ( top > y ) ? top : y ;
x0 = cx ;
x1 = cx + box - > parent - > width -
box - > parent - > padding [ LEFT ] -
box - > parent - > padding [ RIGHT ] ;
find_sides ( block - > float_children ,
top , top , & x0 , & x1 ,
& left , & right ) ;
/* calculate min required left & right
* margins needed to avoid floats */
lm = x0 - cx ;
rm = cx + box - > parent - > width -
box - > parent - > padding [ LEFT ] -
box - > parent - > padding [ RIGHT ] -
x1 ;
}
2009-08-07 17:00:28 +04:00
}
2016-04-24 01:32:21 +03:00
if ( ! layout_table ( box , box - > parent - > width - lm - rm ,
content ) )
return false ;
layout_solve_width ( box , box - > parent - > width , box - > width ,
lm , rm , - 1 , - 1 ) ;
2009-07-23 06:29:12 +04:00
}
2016-04-24 01:32:21 +03:00
/* Position box: horizontal. */
box - > x = box - > parent - > padding [ LEFT ] + box - > margin [ LEFT ] +
box - > border [ LEFT ] . width ;
cx + = box - > x ;
2005-08-01 01:57:07 +04:00
2016-04-24 01:32:21 +03:00
/* Position box: vertical. */
if ( box - > border [ TOP ] . width ) {
box - > y + = box - > border [ TOP ] . width ;
cy + = box - > border [ TOP ] . width ;
}
/* Vertical margin */
if ( ( ( box - > type = = BOX_BLOCK & &
( box - > flags & HAS_HEIGHT ) ) | |
box - > type = = BOX_TABLE | |
( box - > type = = BOX_INLINE_CONTAINER & &
box ! = box - > parent - > children ) | |
margin_collapse = = box ) & &
in_margin = = true ) {
/* Margin goes above this box. */
cy + = max_pos_margin - max_neg_margin ;
box - > y + = max_pos_margin - max_neg_margin ;
2002-05-04 23:57:18 +04:00
2016-04-24 01:32:21 +03:00
/* Current margin has been applied. */
in_margin = false ;
max_pos_margin = max_neg_margin = 0 ;
}
2002-06-19 01:24:21 +04:00
2016-04-24 01:32:21 +03:00
/* Handle clearance */
if ( box - > type ! = BOX_INLINE_CONTAINER & &
( y > 0 ) & & ( cy < y ) ) {
/* box clears something*/
box - > y + = y - cy ;
cy = y ;
}
2005-07-02 22:17:51 +04:00
2016-04-24 01:32:21 +03:00
/* Unless the box has an overflow style of visible, the box
* establishes a new block context . */
if ( box - > type = = BOX_BLOCK & & box - > style & &
( overflow_x ! = CSS_OVERFLOW_VISIBLE | |
overflow_y ! = CSS_OVERFLOW_VISIBLE ) ) {
2009-07-21 14:59:53 +04:00
2016-04-24 01:32:21 +03:00
layout_block_context ( box , viewport_height , content ) ;
2011-02-24 16:46:12 +03:00
2016-04-24 01:32:21 +03:00
cy + = box - > padding [ TOP ] ;
2013-03-06 22:39:38 +04:00
2016-04-24 01:32:21 +03:00
if ( box - > height = = AUTO ) {
box - > height = 0 ;
layout_block_add_scrollbar ( box , BOTTOM ) ;
}
2011-03-12 21:44:43 +03:00
2016-04-24 01:32:21 +03:00
cx - = box - > x ;
cy + = box - > height + box - > padding [ BOTTOM ] +
box - > border [ BOTTOM ] . width ;
y = box - > y + box - > padding [ TOP ] + box - > height +
box - > padding [ BOTTOM ] +
box - > border [ BOTTOM ] . width ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
/* Skip children, because they are done in the new
* block context */
goto advance_to_next_box ;
}
2005-07-02 22:17:51 +04:00
2011-04-04 02:23:14 +04:00
# ifdef LAYOUT_DEBUG
2016-04-24 01:32:21 +03:00
LOG ( " box %p, cx %i, cy %i " , box , cx , cy ) ;
2011-04-04 02:23:14 +04:00
# endif
2005-07-03 03:37:41 +04:00
2016-04-24 01:32:21 +03:00
/* Layout (except tables). */
if ( box - > object ) {
if ( ! layout_block_object ( box ) )
return false ;
2005-07-02 22:17:51 +04:00
2016-04-24 01:32:21 +03:00
} else if ( box - > type = = BOX_INLINE_CONTAINER ) {
box - > width = box - > parent - > width ;
if ( ! layout_inline_container ( box , box - > width , block ,
cx , cy , content ) )
return false ;
2005-07-02 22:17:51 +04:00
2016-04-24 01:32:21 +03:00
} else if ( box - > type = = BOX_TABLE ) {
/* Move down to avoid floats if necessary. */
int x0 , x1 ;
struct box * left , * right ;
y = cy ;
while ( 1 ) {
enum css_width_e wtype ;
css_fixed width = 0 ;
css_unit unit = CSS_UNIT_PX ;
2011-03-12 21:44:43 +03:00
2016-04-24 01:32:21 +03:00
wtype = css_computed_width ( box - > style ,
& width , & unit ) ;
2005-07-02 22:17:51 +04:00
2016-04-24 01:32:21 +03:00
x0 = cx ;
x1 = cx + box - > parent - > width ;
find_sides ( block - > float_children , y ,
y + box - > height ,
& x0 , & x1 , & left , & right ) ;
if ( wtype = = CSS_WIDTH_AUTO )
break ;
if ( box - > width < = x1 - x0 )
break ;
if ( ! left & & ! right )
break ;
else if ( ! left )
y = right - > y + right - > height + 1 ;
else if ( ! right )
y = left - > y + left - > height + 1 ;
else if ( left - > y + left - > height <
right - > y + right - > height )
y = left - > y + left - > height + 1 ;
else
y = right - > y + right - > height + 1 ;
}
box - > x + = x0 - cx ;
cx = x0 ;
box - > y + = y - cy ;
cy = y ;
}
2009-07-21 14:59:53 +04:00
2016-04-24 01:32:21 +03:00
/* Advance to next box. */
if ( box - > type = = BOX_BLOCK & & ! box - > object & & ! ( box - > iframe ) & &
box - > children ) {
/* Down into children. */
2013-01-02 16:46:17 +04:00
2016-04-24 01:32:21 +03:00
if ( box = = margin_collapse ) {
/* Current margin collapsed though to this box.
* Unset margin_collapse . */
margin_collapse = NULL ;
2005-07-03 03:37:41 +04:00
}
2013-01-02 16:46:17 +04:00
2016-04-24 01:32:21 +03:00
y = box - > padding [ TOP ] ;
box = box - > children ;
box - > y = y ;
cy + = y ;
2005-07-02 22:17:51 +04:00
continue ;
2016-04-24 01:32:21 +03:00
} else if ( box - > type = = BOX_BLOCK | | box - > object | |
box - > flags & IFRAME )
cy + = box - > padding [ TOP ] ;
if ( box - > type = = BOX_BLOCK & & box - > height = = AUTO ) {
box - > height = 0 ;
layout_block_add_scrollbar ( box , BOTTOM ) ;
2005-07-02 22:17:51 +04:00
}
2016-04-24 01:32:21 +03:00
cy + = box - > height + box - > padding [ BOTTOM ] +
box - > border [ BOTTOM ] . width ;
cx - = box - > x ;
y = box - > y + box - > padding [ TOP ] + box - > height +
box - > padding [ BOTTOM ] +
box - > border [ BOTTOM ] . width ;
2005-07-02 22:17:51 +04:00
2016-04-24 01:32:21 +03:00
advance_to_next_box :
if ( ! box - > next ) {
/* No more siblings:
* up to first ancestor with a sibling . */
2013-02-22 23:00:16 +04:00
2016-04-24 01:32:21 +03:00
do {
if ( box = = margin_collapse ) {
/* Current margin collapsed though to
* this box . Unset margin_collapse . */
margin_collapse = NULL ;
}
2008-02-11 20:53:00 +03:00
2016-04-24 01:32:21 +03:00
/* Apply bottom margin */
if ( max_pos_margin < box - > margin [ BOTTOM ] )
max_pos_margin = box - > margin [ BOTTOM ] ;
else if ( max_neg_margin < - box - > margin [ BOTTOM ] )
max_neg_margin = - box - > margin [ BOTTOM ] ;
2008-02-11 20:53:00 +03:00
2016-04-24 01:32:21 +03:00
box = box - > parent ;
if ( box = = block )
break ;
2008-02-11 20:53:00 +03:00
2016-04-24 01:32:21 +03:00
/* Margin is invalidated if this is a box
* margins can ' t collapse through . */
if ( box - > type = = BOX_BLOCK & &
box - > flags & MAKE_HEIGHT ) {
margin_collapse = NULL ;
in_margin = false ;
max_pos_margin = max_neg_margin = 0 ;
}
if ( box - > height = = AUTO ) {
box - > height = y - box - > padding [ TOP ] ;
2008-02-11 20:53:00 +03:00
2016-04-24 01:32:21 +03:00
if ( box - > type = = BOX_BLOCK )
layout_block_add_scrollbar ( box ,
BOTTOM ) ;
} else
cy + = box - > height -
( y - box - > padding [ TOP ] ) ;
2009-08-31 14:39:32 +04:00
2016-04-24 01:32:21 +03:00
/* Apply any min-height and max-height to
* boxes in normal flow */
if ( box - > style & &
css_computed_position ( box - > style ) ! =
CSS_POSITION_ABSOLUTE & &
layout_apply_minmax_height ( box ,
NULL ) ) {
/* Height altered */
/* Set current cy */
cy + = box - > height -
( y - box - > padding [ TOP ] ) ;
2013-01-02 16:46:17 +04:00
}
2013-02-22 23:00:16 +04:00
2016-04-24 01:32:21 +03:00
cy + = box - > padding [ BOTTOM ] +
box - > border [ BOTTOM ] . width ;
cx - = box - > x ;
y = box - > y + box - > padding [ TOP ] + box - > height +
box - > padding [ BOTTOM ] +
box - > border [ BOTTOM ] . width ;
2013-03-06 22:39:38 +04:00
2016-04-24 01:32:21 +03:00
} while ( box - > next = = NULL ) ;
if ( box = = block )
break ;
}
2005-07-02 22:17:51 +04:00
2016-04-24 01:32:21 +03:00
/* To next sibling. */
2011-03-12 21:44:43 +03:00
2016-04-24 01:32:21 +03:00
if ( box = = margin_collapse ) {
/* Current margin collapsed though to this box.
* Unset margin_collapse . */
margin_collapse = NULL ;
2005-07-02 22:17:51 +04:00
}
2016-04-24 01:32:21 +03:00
if ( max_pos_margin < box - > margin [ BOTTOM ] )
max_pos_margin = box - > margin [ BOTTOM ] ;
else if ( max_neg_margin < - box - > margin [ BOTTOM ] )
max_neg_margin = - box - > margin [ BOTTOM ] ;
2005-07-02 22:17:51 +04:00
2016-04-24 01:32:21 +03:00
box = box - > next ;
box - > y = y ;
}
2009-07-27 14:22:44 +04:00
2016-04-24 01:32:21 +03:00
/* Account for bottom margin of last contained block */
cy + = max_pos_margin - max_neg_margin ;
2005-07-02 22:17:51 +04:00
2016-04-24 01:32:21 +03:00
/* Increase height to contain any floats inside (CSS 2.1 10.6.7). */
for ( box = block - > float_children ; box ; box = box - > next_float ) {
y = box - > y + box - > height + box - > padding [ BOTTOM ] +
box - > border [ BOTTOM ] . width + box - > margin [ BOTTOM ] ;
if ( cy < y )
cy = y ;
}
2005-07-02 22:17:51 +04:00
2016-04-24 01:32:21 +03:00
if ( block - > height = = AUTO ) {
block - > height = cy - block - > padding [ TOP ] ;
if ( block - > type = = BOX_BLOCK )
layout_block_add_scrollbar ( block , BOTTOM ) ;
}
2011-02-14 17:39:42 +03:00
2016-04-24 01:32:21 +03:00
if ( block - > style & & css_computed_position ( block - > style ) ! =
CSS_POSITION_ABSOLUTE ) {
/* Block is in normal flow */
layout_apply_minmax_height ( block , NULL ) ;
}
2011-06-15 00:00:18 +04:00
2016-04-24 01:32:21 +03:00
if ( block - > gadget & &
( block - > gadget - > type = = GADGET_TEXTAREA | |
block - > gadget - > type = = GADGET_PASSWORD | |
block - > gadget - > type = = GADGET_TEXTBOX ) ) {
int ta_width = block - > padding [ LEFT ] + block - > width +
block - > padding [ RIGHT ] ;
int ta_height = block - > padding [ TOP ] + block - > height +
block - > padding [ BOTTOM ] ;
textarea_set_layout ( block - > gadget - > data . text . ta ,
ta_width , ta_height ,
block - > padding [ TOP ] , block - > padding [ RIGHT ] ,
block - > padding [ BOTTOM ] , block - > padding [ LEFT ] ) ;
}
2011-06-28 23:42:31 +04:00
2016-04-24 01:32:21 +03:00
return true ;
}
2009-08-01 04:26:02 +04:00
2005-07-02 22:17:51 +04:00
2016-04-24 01:32:21 +03:00
/**
* Calculate line height from a style .
*/
static int line_height ( const css_computed_style * style )
{
enum css_line_height_e lhtype ;
css_fixed lhvalue = 0 ;
css_unit lhunit = CSS_UNIT_PX ;
css_fixed line_height ;
2011-03-12 21:44:43 +03:00
2016-04-24 01:32:21 +03:00
assert ( style ) ;
lhtype = css_computed_line_height ( style , & lhvalue , & lhunit ) ;
if ( lhtype = = CSS_LINE_HEIGHT_NORMAL ) {
/* Normal => use a constant of 1.3 * font-size */
lhvalue = FLTTOFIX ( 1.3 ) ;
lhtype = CSS_LINE_HEIGHT_NUMBER ;
2005-07-02 22:17:51 +04:00
}
2016-04-24 01:32:21 +03:00
if ( lhtype = = CSS_LINE_HEIGHT_NUMBER | |
lhunit = = CSS_UNIT_PCT ) {
line_height = nscss_len2px ( lhvalue , CSS_UNIT_EM , style ) ;
if ( lhtype ! = CSS_LINE_HEIGHT_NUMBER )
line_height = FDIV ( line_height , F_100 ) ;
} else {
assert ( lhunit ! = CSS_UNIT_PCT ) ;
line_height = nscss_len2px ( lhvalue , lhunit , style ) ;
2011-02-24 16:46:12 +03:00
}
2005-07-02 22:17:51 +04:00
2016-04-24 01:32:21 +03:00
return FIXTOINT ( line_height ) ;
}
2011-04-04 02:23:14 +04:00
2005-07-02 22:17:51 +04:00
2016-04-24 01:32:21 +03:00
/**
* Layout list markers .
*/
static void
layout_lists ( struct box * box ,
const struct gui_layout_table * font_func )
{
struct box * child ;
struct box * marker ;
plot_font_style_t fstyle ;
for ( child = box - > children ; child ; child = child - > next ) {
if ( child - > list_marker ) {
marker = child - > list_marker ;
if ( marker - > object ) {
marker - > width =
content_get_width ( marker - > object ) ;
marker - > x = - marker - > width ;
marker - > height =
content_get_height ( marker - > object ) ;
marker - > y = ( line_height ( marker - > style ) -
marker - > height ) / 2 ;
} else if ( marker - > text ) {
if ( marker - > width = = UNKNOWN_WIDTH ) {
font_plot_style_from_css ( marker - > style ,
& fstyle ) ;
font_func - > width ( & fstyle ,
marker - > text ,
marker - > length ,
& marker - > width ) ;
marker - > flags | = MEASURED ;
}
marker - > x = - marker - > width ;
marker - > y = 0 ;
marker - > height = line_height ( marker - > style ) ;
} else {
marker - > x = 0 ;
marker - > y = 0 ;
marker - > width = 0 ;
marker - > height = 0 ;
}
/* Gap between marker and content */
marker - > x - = 4 ;
}
layout_lists ( child , font_func ) ;
}
2005-07-02 22:17:51 +04:00
}
2004-02-28 20:23:07 +03:00
/**
2016-04-24 01:32:21 +03:00
* Compute box offsets for a relatively or absolutely positioned box with
* respect to a box .
2004-02-28 20:23:07 +03:00
*
2016-04-24 01:32:21 +03:00
* \ param box box to compute offsets for
* \ param containing_block box to compute percentages with respect to
* \ param top updated to top offset , or AUTO
* \ param right updated to right offset , or AUTO
* \ param bottom updated to bottom offset , or AUTO
* \ param left updated to left offset , or AUTO
*
* See CSS 2.1 9.3 .2 . containing_block must have width and height .
2004-02-28 20:23:07 +03:00
*/
2016-04-24 01:32:21 +03:00
static void
layout_compute_offsets ( struct box * box ,
struct box * containing_block ,
int * top ,
int * right ,
int * bottom ,
int * left )
2004-02-28 20:23:07 +03:00
{
2016-04-24 01:32:21 +03:00
uint32_t type ;
2009-07-24 03:05:34 +04:00
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
2016-04-24 01:32:21 +03:00
assert ( containing_block - > width ! = UNKNOWN_WIDTH & &
containing_block - > width ! = AUTO & &
containing_block - > height ! = AUTO ) ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
/* left */
type = css_computed_left ( box - > style , & value , & unit ) ;
if ( type = = CSS_LEFT_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
* left = FPCT_OF_INT_TOINT ( value ,
containing_block - > width ) ;
} else {
* left = FIXTOINT ( nscss_len2px ( value , unit , box - > style ) ) ;
}
2009-07-24 03:05:34 +04:00
} else {
2016-04-24 01:32:21 +03:00
* left = AUTO ;
2004-02-28 20:23:07 +03:00
}
2016-04-24 01:32:21 +03:00
/* right */
type = css_computed_right ( box - > style , & value , & unit ) ;
if ( type = = CSS_RIGHT_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
* right = FPCT_OF_INT_TOINT ( value ,
containing_block - > width ) ;
} else {
* right = FIXTOINT ( nscss_len2px ( value , unit ,
box - > style ) ) ;
}
} else {
* right = AUTO ;
}
2004-02-28 20:23:07 +03:00
2016-04-24 01:32:21 +03:00
/* top */
type = css_computed_top ( box - > style , & value , & unit ) ;
if ( type = = CSS_TOP_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
* top = FPCT_OF_INT_TOINT ( value ,
containing_block - > height ) ;
} else {
* top = FIXTOINT ( nscss_len2px ( value , unit , box - > style ) ) ;
}
} else {
* top = AUTO ;
}
2004-03-26 04:35:35 +03:00
2016-04-24 01:32:21 +03:00
/* bottom */
type = css_computed_bottom ( box - > style , & value , & unit ) ;
if ( type = = CSS_BOTTOM_SET ) {
if ( unit = = CSS_UNIT_PCT ) {
* bottom = FPCT_OF_INT_TOINT ( value ,
containing_block - > height ) ;
} else {
* bottom = FIXTOINT ( nscss_len2px ( value , unit ,
box - > style ) ) ;
}
} else {
* bottom = AUTO ;
}
2004-03-26 04:35:35 +03:00
}
2004-02-11 20:15:36 +03:00
/**
2016-04-24 01:32:21 +03:00
* Layout and position an absolutely positioned box .
2004-02-11 20:15:36 +03:00
*
2016-04-24 01:32:21 +03:00
* \ param box absolute box to layout and position
* \ param containing_block containing block
* \ param cx position of box relative to containing_block
* \ param cy position of box relative to containing_block
* \ param content memory pool for any new boxes
* \ return true on success , false on memory exhaustion
2004-02-11 20:15:36 +03:00
*/
2016-04-24 01:32:21 +03:00
static bool
layout_absolute ( struct box * box ,
struct box * containing_block ,
int cx , int cy ,
html_content * content )
2002-06-19 01:24:21 +04:00
{
2016-04-24 01:32:21 +03:00
int static_left , static_top ; /* static position */
int top , right , bottom , left ;
int width , height , max_width , min_width ;
int * margin = box - > margin ;
int * padding = box - > padding ;
struct box_border * border = box - > border ;
int available_width = containing_block - > width ;
int space ;
2016-01-20 22:24:12 +03:00
2016-04-24 01:32:21 +03:00
assert ( box - > type = = BOX_BLOCK | | box - > type = = BOX_TABLE | |
box - > type = = BOX_INLINE_BLOCK ) ;
2011-04-04 02:23:14 +04:00
2016-04-24 01:32:21 +03:00
/* The static position is where the box would be if it was not
* absolutely positioned . The x and y are filled in by
* layout_block_context ( ) . */
static_left = cx + box - > x ;
static_top = cy + box - > y ;
2002-06-19 19:17:45 +04:00
2016-04-24 01:32:21 +03:00
if ( containing_block - > type = = BOX_BLOCK | |
containing_block - > type = = BOX_INLINE_BLOCK | |
containing_block - > type = = BOX_TABLE_CELL ) {
/* Block level container => temporarily increase containing
* block dimensions to include padding ( we restore this
* again at the end ) */
containing_block - > width + = containing_block - > padding [ LEFT ] +
containing_block - > padding [ RIGHT ] ;
containing_block - > height + = containing_block - > padding [ TOP ] +
containing_block - > padding [ BOTTOM ] ;
2002-06-19 01:24:21 +04:00
} else {
2016-04-24 01:32:21 +03:00
/** \todo inline containers */
2002-06-19 01:24:21 +04:00
}
2016-04-24 01:32:21 +03:00
layout_compute_offsets ( box , containing_block ,
& top , & right , & bottom , & left ) ;
2002-06-19 01:24:21 +04:00
2016-04-24 01:32:21 +03:00
/* Pass containing block into layout_find_dimensions via the float
* containing block box member . This is unused for absolutely positioned
* boxes because a box can ' t be floated and absolutely positioned . */
box - > float_container = containing_block ;
layout_find_dimensions ( available_width , - 1 , box , box - > style ,
& width , & height , & max_width , & min_width ,
0 , 0 , margin , padding , border ) ;
box - > float_container = NULL ;
2002-05-04 23:57:18 +04:00
2016-04-24 01:32:21 +03:00
/* 10.3.7 */
# ifdef LAYOUT_DEBUG
LOG ( " %i + %i + %i + %i + %i + %i + %i + %i + %i = %i " , left , margin [ LEFT ] , border [ LEFT ] . width , padding [ LEFT ] , width , padding [ RIGHT ] , border [ RIGHT ] . width , margin [ RIGHT ] , right , containing_block - > width ) ;
# endif
2002-08-06 00:34:45 +04:00
2016-04-24 01:32:21 +03:00
if ( left = = AUTO & & width = = AUTO & & right = = AUTO ) {
if ( margin [ LEFT ] = = AUTO )
margin [ LEFT ] = 0 ;
if ( margin [ RIGHT ] = = AUTO )
margin [ RIGHT ] = 0 ;
left = static_left ;
2004-06-03 01:21:13 +04:00
2016-04-24 01:32:21 +03:00
width = min ( max ( box - > min_width , available_width ) ,
box - > max_width ) ;
width - = box - > margin [ LEFT ] + box - > border [ LEFT ] . width +
box - > padding [ LEFT ] + box - > padding [ RIGHT ] +
box - > border [ RIGHT ] . width + box - > margin [ RIGHT ] ;
2002-09-18 23:36:28 +04:00
2016-04-24 01:32:21 +03:00
/* Adjust for {min|max}-width */
if ( max_width > = 0 & & width > max_width ) width = max_width ;
if ( min_width > 0 & & width < min_width ) width = min_width ;
2014-06-01 21:36:22 +04:00
2016-04-24 01:32:21 +03:00
right = containing_block - > width -
left -
margin [ LEFT ] - border [ LEFT ] . width - padding [ LEFT ] -
width -
padding [ RIGHT ] - border [ RIGHT ] . width - margin [ RIGHT ] ;
} else if ( left ! = AUTO & & width ! = AUTO & & right ! = AUTO ) {
2014-06-01 21:36:22 +04:00
2016-04-24 01:32:21 +03:00
/* Adjust for {min|max}-width */
if ( max_width > = 0 & & width > max_width ) width = max_width ;
if ( min_width > 0 & & width < min_width ) width = min_width ;
2014-06-01 21:36:22 +04:00
2016-04-24 01:32:21 +03:00
if ( margin [ LEFT ] = = AUTO & & margin [ RIGHT ] = = AUTO ) {
space = containing_block - > width -
left - border [ LEFT ] . width -
padding [ LEFT ] - width - padding [ RIGHT ] -
border [ RIGHT ] . width - right ;
if ( space < 0 ) {
margin [ LEFT ] = 0 ;
margin [ RIGHT ] = space ;
} else {
margin [ LEFT ] = margin [ RIGHT ] = space / 2 ;
2004-12-02 00:48:11 +03:00
}
2016-04-24 01:32:21 +03:00
} else if ( margin [ LEFT ] = = AUTO ) {
margin [ LEFT ] = containing_block - > width -
left - border [ LEFT ] . width -
padding [ LEFT ] - width - padding [ RIGHT ] -
border [ RIGHT ] . width - margin [ RIGHT ] -
right ;
} else if ( margin [ RIGHT ] = = AUTO ) {
margin [ RIGHT ] = containing_block - > width -
left - margin [ LEFT ] -
border [ LEFT ] . width -
padding [ LEFT ] - width - padding [ RIGHT ] -
border [ RIGHT ] . width - right ;
} else {
right = containing_block - > width -
left - margin [ LEFT ] -
border [ LEFT ] . width -
padding [ LEFT ] - width - padding [ RIGHT ] -
border [ RIGHT ] . width - margin [ RIGHT ] ;
2004-12-02 00:48:11 +03:00
}
2016-04-24 01:32:21 +03:00
} else {
if ( margin [ LEFT ] = = AUTO )
margin [ LEFT ] = 0 ;
if ( margin [ RIGHT ] = = AUTO )
margin [ RIGHT ] = 0 ;
2004-12-02 00:48:11 +03:00
2016-04-24 01:32:21 +03:00
if ( left = = AUTO & & width = = AUTO & & right ! = AUTO ) {
available_width - = right ;
2002-05-04 23:57:18 +04:00
2016-04-24 01:32:21 +03:00
width = min ( max ( box - > min_width , available_width ) ,
box - > max_width ) ;
width - = box - > margin [ LEFT ] + box - > border [ LEFT ] . width +
box - > padding [ LEFT ] + box - > padding [ RIGHT ] +
box - > border [ RIGHT ] . width + box - > margin [ RIGHT ] ;
2009-01-26 19:32:19 +03:00
2016-04-24 01:32:21 +03:00
/* Adjust for {min|max}-width */
if ( max_width > = 0 & & width > max_width )
width = max_width ;
if ( min_width > 0 & & width < min_width )
width = min_width ;
2009-01-26 19:32:19 +03:00
2016-04-24 01:32:21 +03:00
left = containing_block - > width -
margin [ LEFT ] - border [ LEFT ] . width -
padding [ LEFT ] - width - padding [ RIGHT ] -
border [ RIGHT ] . width - margin [ RIGHT ] -
right ;
} else if ( left = = AUTO & & width ! = AUTO & & right = = AUTO ) {
2009-01-26 19:32:19 +03:00
2016-04-24 01:32:21 +03:00
/* Adjust for {min|max}-width */
if ( max_width > = 0 & & width > max_width )
width = max_width ;
if ( min_width > 0 & & width < min_width )
width = min_width ;
2009-01-26 19:32:19 +03:00
2016-04-24 01:32:21 +03:00
left = static_left ;
right = containing_block - > width -
left - margin [ LEFT ] -
border [ LEFT ] . width -
padding [ LEFT ] - width - padding [ RIGHT ] -
border [ RIGHT ] . width - margin [ RIGHT ] ;
} else if ( left ! = AUTO & & width = = AUTO & & right = = AUTO ) {
available_width - = left ;
2002-08-06 00:34:45 +04:00
2016-04-24 01:32:21 +03:00
width = min ( max ( box - > min_width , available_width ) ,
box - > max_width ) ;
width - = box - > margin [ LEFT ] + box - > border [ LEFT ] . width +
box - > padding [ LEFT ] + box - > padding [ RIGHT ] +
box - > border [ RIGHT ] . width + box - > margin [ RIGHT ] ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
/* Adjust for {min|max}-width */
if ( max_width > = 0 & & width > max_width )
width = max_width ;
if ( min_width > 0 & & width < min_width )
width = min_width ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
right = containing_block - > width -
left - margin [ LEFT ] -
border [ LEFT ] . width -
padding [ LEFT ] - width - padding [ RIGHT ] -
border [ RIGHT ] . width - margin [ RIGHT ] ;
} else if ( left = = AUTO & & width ! = AUTO & & right ! = AUTO ) {
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
/* Adjust for {min|max}-width */
if ( max_width > = 0 & & width > max_width )
width = max_width ;
if ( min_width > 0 & & width < min_width )
width = min_width ;
2009-05-08 15:43:38 +04:00
2016-04-24 01:32:21 +03:00
left = containing_block - > width -
margin [ LEFT ] - border [ LEFT ] . width -
padding [ LEFT ] - width - padding [ RIGHT ] -
border [ RIGHT ] . width - margin [ RIGHT ] -
right ;
} else if ( left ! = AUTO & & width = = AUTO & & right ! = AUTO ) {
width = containing_block - > width -
left - margin [ LEFT ] -
border [ LEFT ] . width -
padding [ LEFT ] - padding [ RIGHT ] -
border [ RIGHT ] . width - margin [ RIGHT ] -
right ;
2011-04-04 02:23:14 +04:00
2016-04-24 01:32:21 +03:00
/* Adjust for {min|max}-width */
if ( max_width > = 0 & & width > max_width )
width = max_width ;
if ( min_width > 0 & & width < min_width )
width = min_width ;
2011-04-04 02:23:14 +04:00
2016-04-24 01:32:21 +03:00
} else if ( left ! = AUTO & & width ! = AUTO & & right = = AUTO ) {
/* Adjust for {min|max}-width */
if ( max_width > = 0 & & width > max_width )
width = max_width ;
if ( min_width > 0 & & width < min_width )
width = min_width ;
right = containing_block - > width -
left - margin [ LEFT ] -
border [ LEFT ] . width -
padding [ LEFT ] - width - padding [ RIGHT ] -
border [ RIGHT ] . width - margin [ RIGHT ] ;
}
2003-09-12 22:30:44 +04:00
}
2011-04-04 02:23:14 +04:00
# ifdef LAYOUT_DEBUG
2016-04-24 01:32:21 +03:00
LOG ( " %i + %i + %i + %i + %i + %i + %i + %i + %i = %i " , left , margin [ LEFT ] , border [ LEFT ] . width , padding [ LEFT ] , width , padding [ RIGHT ] , border [ RIGHT ] . width , margin [ RIGHT ] , right , containing_block - > width ) ;
2011-04-04 02:23:14 +04:00
# endif
2004-04-12 04:00:47 +04:00
2016-04-24 01:32:21 +03:00
box - > x = left + margin [ LEFT ] + border [ LEFT ] . width - cx ;
if ( containing_block - > type = = BOX_BLOCK | |
containing_block - > type = = BOX_INLINE_BLOCK | |
containing_block - > type = = BOX_TABLE_CELL ) {
/* Block-level ancestor => reset container's width */
containing_block - > width - = containing_block - > padding [ LEFT ] +
containing_block - > padding [ RIGHT ] ;
2003-09-12 22:30:44 +04:00
} else {
2016-04-24 01:32:21 +03:00
/** \todo inline ancestors */
2002-09-19 23:54:43 +04:00
}
2016-04-24 01:32:21 +03:00
box - > width = width ;
box - > height = height ;
2002-09-19 23:54:43 +04:00
2016-04-24 01:32:21 +03:00
if ( box - > type = = BOX_BLOCK | | box - > type = = BOX_INLINE_BLOCK | |
box - > object | | box - > flags & IFRAME ) {
if ( ! layout_block_context ( box , - 1 , content ) )
return false ;
} else if ( box - > type = = BOX_TABLE ) {
/* layout_table also expects the containing block to be
* stored in the float_container field */
box - > float_container = containing_block ;
/* \todo layout_table considers margins etc. again */
if ( ! layout_table ( box , width , content ) )
return false ;
box - > float_container = NULL ;
layout_solve_width ( box , box - > parent - > width , box - > width , 0 , 0 ,
- 1 , - 1 ) ;
2004-05-21 18:26:59 +04:00
}
2016-04-24 01:32:21 +03:00
/* 10.6.4 */
# ifdef LAYOUT_DEBUG
LOG ( " %i + %i + %i + %i + %i + %i + %i + %i + %i = %i " , top , margin [ TOP ] , border [ TOP ] . width , padding [ TOP ] , height , padding [ BOTTOM ] , border [ BOTTOM ] . width , margin [ BOTTOM ] , bottom , containing_block - > height ) ;
# endif
2005-03-22 19:29:16 +03:00
2016-04-24 01:32:21 +03:00
if ( top = = AUTO & & height = = AUTO & & bottom = = AUTO ) {
top = static_top ;
height = box - > height ;
if ( margin [ TOP ] = = AUTO )
margin [ TOP ] = 0 ;
if ( margin [ BOTTOM ] = = AUTO )
margin [ BOTTOM ] = 0 ;
bottom = containing_block - > height -
top - margin [ TOP ] - border [ TOP ] . width -
padding [ TOP ] - height - padding [ BOTTOM ] -
border [ BOTTOM ] . width - margin [ BOTTOM ] ;
} else if ( top ! = AUTO & & height ! = AUTO & & bottom ! = AUTO ) {
if ( margin [ TOP ] = = AUTO & & margin [ BOTTOM ] = = AUTO ) {
space = containing_block - > height -
top - border [ TOP ] . width - padding [ TOP ] -
height - padding [ BOTTOM ] -
border [ BOTTOM ] . width - bottom ;
margin [ TOP ] = margin [ BOTTOM ] = space / 2 ;
} else if ( margin [ TOP ] = = AUTO ) {
margin [ TOP ] = containing_block - > height -
top - border [ TOP ] . width - padding [ TOP ] -
height - padding [ BOTTOM ] -
border [ BOTTOM ] . width - margin [ BOTTOM ] -
bottom ;
} else if ( margin [ BOTTOM ] = = AUTO ) {
margin [ BOTTOM ] = containing_block - > height -
top - margin [ TOP ] - border [ TOP ] . width -
padding [ TOP ] - height -
padding [ BOTTOM ] - border [ BOTTOM ] . width -
bottom ;
} else {
bottom = containing_block - > height -
top - margin [ TOP ] - border [ TOP ] . width -
padding [ TOP ] - height -
padding [ BOTTOM ] - border [ BOTTOM ] . width -
margin [ BOTTOM ] ;
2002-09-18 23:36:28 +04:00
}
2003-01-04 01:19:39 +03:00
} else {
2016-04-24 01:32:21 +03:00
if ( margin [ TOP ] = = AUTO )
margin [ TOP ] = 0 ;
if ( margin [ BOTTOM ] = = AUTO )
margin [ BOTTOM ] = 0 ;
if ( top = = AUTO & & height = = AUTO & & bottom ! = AUTO ) {
height = box - > height ;
top = containing_block - > height -
margin [ TOP ] - border [ TOP ] . width -
padding [ TOP ] - height -
padding [ BOTTOM ] - border [ BOTTOM ] . width -
margin [ BOTTOM ] - bottom ;
} else if ( top = = AUTO & & height ! = AUTO & & bottom = = AUTO ) {
top = static_top ;
bottom = containing_block - > height -
top - margin [ TOP ] - border [ TOP ] . width -
padding [ TOP ] - height -
padding [ BOTTOM ] - border [ BOTTOM ] . width -
margin [ BOTTOM ] ;
} else if ( top ! = AUTO & & height = = AUTO & & bottom = = AUTO ) {
height = box - > height ;
bottom = containing_block - > height -
top - margin [ TOP ] - border [ TOP ] . width -
padding [ TOP ] - height -
padding [ BOTTOM ] - border [ BOTTOM ] . width -
margin [ BOTTOM ] ;
} else if ( top = = AUTO & & height ! = AUTO & & bottom ! = AUTO ) {
top = containing_block - > height -
margin [ TOP ] - border [ TOP ] . width -
padding [ TOP ] - height -
padding [ BOTTOM ] - border [ BOTTOM ] . width -
margin [ BOTTOM ] - bottom ;
} else if ( top ! = AUTO & & height = = AUTO & & bottom ! = AUTO ) {
height = containing_block - > height -
top - margin [ TOP ] - border [ TOP ] . width -
padding [ TOP ] - padding [ BOTTOM ] -
border [ BOTTOM ] . width - margin [ BOTTOM ] -
bottom ;
} else if ( top ! = AUTO & & height ! = AUTO & & bottom = = AUTO ) {
bottom = containing_block - > height -
top - margin [ TOP ] - border [ TOP ] . width -
padding [ TOP ] - height -
padding [ BOTTOM ] - border [ BOTTOM ] . width -
margin [ BOTTOM ] ;
2002-09-18 23:36:28 +04:00
}
2003-01-04 01:19:39 +03:00
}
2002-06-19 19:17:45 +04:00
2016-04-24 01:32:21 +03:00
# ifdef LAYOUT_DEBUG
LOG ( " %i + %i + %i + %i + %i + %i + %i + %i + %i = %i " , top , margin [ TOP ] , border [ TOP ] . width , padding [ TOP ] , height , padding [ BOTTOM ] , border [ BOTTOM ] . width , margin [ BOTTOM ] , bottom , containing_block - > height ) ;
# endif
box - > y = top + margin [ TOP ] + border [ TOP ] . width - cy ;
if ( containing_block - > type = = BOX_BLOCK | |
containing_block - > type = = BOX_INLINE_BLOCK | |
containing_block - > type = = BOX_TABLE_CELL ) {
/* Block-level ancestor => reset container's height */
containing_block - > height - = containing_block - > padding [ TOP ] +
containing_block - > padding [ BOTTOM ] ;
} else {
/** \todo Inline ancestors */
2002-05-04 23:57:18 +04:00
}
2016-04-24 01:32:21 +03:00
box - > height = height ;
layout_apply_minmax_height ( box , containing_block ) ;
2003-07-08 00:30:51 +04:00
2016-04-24 01:32:21 +03:00
return true ;
}
2004-04-12 21:32:45 +04:00
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
/**
* Recursively layout and position absolutely positioned boxes .
*
* \ param box tree of boxes to layout
* \ param containing_block current containing block
* \ param cx position of box relative to containing_block
* \ param cy position of box relative to containing_block
* \ param content memory pool for any new boxes
* \ return true on success , false on memory exhaustion
*/
static bool
layout_position_absolute ( struct box * box ,
struct box * containing_block ,
int cx , int cy ,
html_content * content )
{
struct box * c ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
for ( c = box - > children ; c ; c = c - > next ) {
if ( ( c - > type = = BOX_BLOCK | | c - > type = = BOX_TABLE | |
c - > type = = BOX_INLINE_BLOCK ) & &
( css_computed_position ( c - > style ) = =
CSS_POSITION_ABSOLUTE | |
css_computed_position ( c - > style ) = =
CSS_POSITION_FIXED ) ) {
if ( ! layout_absolute ( c , containing_block ,
cx , cy , content ) )
return false ;
if ( ! layout_position_absolute ( c , c , 0 , 0 , content ) )
return false ;
} else if ( c - > style & & css_computed_position ( c - > style ) = =
CSS_POSITION_RELATIVE ) {
if ( ! layout_position_absolute ( c , c , 0 , 0 , content ) )
return false ;
} else {
int px , py ;
if ( c - > style & & ( css_computed_float ( c - > style ) = =
CSS_FLOAT_LEFT | |
css_computed_float ( c - > style ) = =
CSS_FLOAT_RIGHT ) ) {
/* Float x/y coords are relative to nearest
* ansestor with float_children , rather than
* relative to parent . Need to get x / y relative
* to parent */
struct box * p ;
px = c - > x ;
py = c - > y ;
for ( p = box - > parent ; p & & ! p - > float_children ;
p = p - > parent ) {
px - = p - > x ;
py - = p - > y ;
2003-07-07 01:10:12 +04:00
}
2003-08-30 03:15:54 +04:00
} else {
2016-04-24 01:32:21 +03:00
/* Not a float, so box x/y coords are relative
* to parent */
px = c - > x ;
py = c - > y ;
2002-05-04 23:57:18 +04:00
}
2016-04-24 01:32:21 +03:00
if ( ! layout_position_absolute ( c , containing_block ,
cx + px , cy + py , content ) )
return false ;
2002-05-04 23:57:18 +04:00
}
}
2016-04-24 01:32:21 +03:00
return true ;
}
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
/**
* Compute a box ' s relative offset as per CSS 2.1 9.4 .3
*
* \ param box Box to compute relative offsets for .
* \ param x Receives relative offset in x .
* \ param y Receives relative offset in y .
*/
static void layout_compute_relative_offset ( struct box * box , int * x , int * y )
{
int left , right , top , bottom ;
struct box * containing_block ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
assert ( box & & box - > parent & & box - > style & &
css_computed_position ( box - > style ) = =
CSS_POSITION_RELATIVE ) ;
if ( box - > float_container & &
( css_computed_float ( box - > style ) = = CSS_FLOAT_LEFT | |
css_computed_float ( box - > style ) = = CSS_FLOAT_RIGHT ) ) {
containing_block = box - > float_container ;
} else {
containing_block = box - > parent ;
}
layout_compute_offsets ( box , containing_block ,
& top , & right , & bottom , & left ) ;
if ( left = = AUTO & & right = = AUTO )
left = right = 0 ;
else if ( left = = AUTO )
/* left is auto => computed = -right */
left = - right ;
else if ( right = = AUTO )
/* right is auto => computed = -left */
right = - left ;
else {
/* over constrained => examine direction property
* of containing block */
if ( containing_block - > style & &
css_computed_direction (
containing_block - > style ) = =
CSS_DIRECTION_RTL ) {
/* right wins */
left = - right ;
} else {
/* assume LTR in all other cases */
right = - left ;
2005-01-11 00:35:34 +03:00
}
}
2016-04-24 01:32:21 +03:00
assert ( left = = - right ) ;
2011-01-08 20:34:45 +03:00
2016-04-24 01:32:21 +03:00
if ( top = = AUTO & & bottom = = AUTO ) {
top = bottom = 0 ;
} else if ( top = = AUTO ) {
top = - bottom ;
} else {
/* bottom is AUTO, or neither are AUTO */
bottom = - top ;
}
2002-06-19 19:17:45 +04:00
2016-04-24 01:32:21 +03:00
# ifdef LAYOUT_DEBUG
LOG ( " left %i, right %i, top %i, bottom %i " , left , right , top , bottom ) ;
# endif
2004-06-03 01:21:13 +04:00
2016-04-24 01:32:21 +03:00
* x = left ;
* y = top ;
2002-05-04 23:57:18 +04:00
}
2002-09-18 23:36:28 +04:00
2005-01-11 00:35:34 +03:00
/**
2016-04-24 01:32:21 +03:00
* Adjust positions of relatively positioned boxes .
2004-02-23 01:22:50 +03:00
*
2016-04-24 01:32:21 +03:00
* \ param root box to adjust the position of
* \ param fp box which forms the block formatting context for children of
* " root " which are floats
* \ param fx x offset due to intervening relatively positioned boxes
* between current box , " root " , and the block formatting context
* box , " fp " , for float children of " root "
* \ param fy y offset due to intervening relatively positioned boxes
* between current box , " root " , and the block formatting context
* box , " fp " , for float children of " root "
2002-09-18 23:36:28 +04:00
*/
2016-04-24 01:32:21 +03:00
static void
layout_position_relative ( struct box * root , struct box * fp , int fx , int fy )
2002-09-18 23:36:28 +04:00
{
2016-04-24 01:32:21 +03:00
struct box * box ; /* for children of "root" */
struct box * fn ; /* for block formatting context box for children of
* " box " */
struct box * fc ; /* for float children of the block formatting context,
* " fp " */
int x , y ; /* for the offsets resulting from any relative
* positioning on the current block */
int fnx , fny ; /* for affsets which apply to flat children of "box" */
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
/**\todo ensure containing box is large enough after moving boxes */
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
assert ( root ) ;
2005-04-14 23:54:24 +04:00
2016-04-24 01:32:21 +03:00
/* Normal children */
for ( box = root - > children ; box ; box = box - > next ) {
2002-12-27 21:58:03 +03:00
2016-04-24 01:32:21 +03:00
if ( box - > type = = BOX_TEXT )
2005-07-02 22:17:51 +04:00
continue ;
2003-09-12 02:02:06 +04:00
2016-04-24 01:32:21 +03:00
/* If relatively positioned, get offsets */
if ( box - > style & & css_computed_position ( box - > style ) = =
CSS_POSITION_RELATIVE )
layout_compute_relative_offset ( box , & x , & y ) ;
else
x = y = 0 ;
2004-05-28 02:13:20 +04:00
2016-04-24 01:32:21 +03:00
/* Adjust float coordinates.
* ( note float x and y are relative to their block formatting
* context box and not their parent ) */
if ( box - > style & & ( css_computed_float ( box - > style ) = =
CSS_FLOAT_LEFT | |
css_computed_float ( box - > style ) = =
CSS_FLOAT_RIGHT ) & &
( fx ! = 0 | | fy ! = 0 ) ) {
/* box is a float and there is a float offset to
* apply */
for ( fc = fp - > float_children ; fc ; fc = fc - > next_float ) {
if ( box = = fc - > children ) {
/* Box is floated in the block
* formatting context block , fp .
* Apply float offsets . */
box - > x + = fx ;
box - > y + = fy ;
fx = fy = 0 ;
}
}
}
2008-04-20 19:49:25 +04:00
2016-04-24 01:32:21 +03:00
if ( box - > float_children ) {
fn = box ;
fnx = fny = 0 ;
} else {
fn = fp ;
fnx = fx + x ;
fny = fy + y ;
}
2003-04-10 01:57:09 +04:00
2016-04-24 01:32:21 +03:00
/* recurse first */
layout_position_relative ( box , fn , fnx , fny ) ;
2003-09-12 02:02:06 +04:00
2016-04-24 01:32:21 +03:00
/* Ignore things we're not interested in. */
if ( ! box - > style | | ( box - > style & &
css_computed_position ( box - > style ) ! =
CSS_POSITION_RELATIVE ) )
2005-07-02 22:17:51 +04:00
continue ;
2003-09-12 02:02:06 +04:00
2016-04-24 01:32:21 +03:00
box - > x + = x ;
box - > y + = y ;
2003-04-10 01:57:09 +04:00
2016-04-24 01:32:21 +03:00
/* Handle INLINEs - their "children" are in fact
* the sibling boxes between the INLINE and
* INLINE_END boxes */
if ( box - > type = = BOX_INLINE & & box - > inline_end ) {
struct box * b ;
for ( b = box - > next ; b & & b ! = box - > inline_end ;
b = b - > next ) {
b - > x + = x ;
b - > y + = y ;
2002-09-18 23:36:28 +04:00
}
}
2016-04-24 01:32:21 +03:00
}
}
2002-09-18 23:36:28 +04:00
2005-07-02 22:17:51 +04:00
2016-04-24 01:32:21 +03:00
/* exported function documented in render/layout.h */
bool layout_document ( html_content * content , int width , int height )
{
bool ret ;
struct box * doc = content - > layout ;
const struct gui_layout_table * font_func = content - > font_func ;
layout_minmax_block ( doc , font_func ) ;
layout_block_find_dimensions ( width , height , 0 , 0 , doc ) ;
doc - > x = doc - > margin [ LEFT ] + doc - > border [ LEFT ] . width ;
doc - > y = doc - > margin [ TOP ] + doc - > border [ TOP ] . width ;
width - = doc - > margin [ LEFT ] + doc - > border [ LEFT ] . width +
doc - > padding [ LEFT ] + doc - > padding [ RIGHT ] +
doc - > border [ RIGHT ] . width + doc - > margin [ RIGHT ] ;
if ( width < 0 ) {
width = 0 ;
2002-09-18 23:36:28 +04:00
}
2016-04-24 01:32:21 +03:00
doc - > width = width ;
2003-01-04 01:19:39 +03:00
2016-04-24 01:32:21 +03:00
ret = layout_block_context ( doc , height , content ) ;
/* make <html> and <body> fill available height */
if ( doc - > y + doc - > padding [ TOP ] + doc - > height + doc - > padding [ BOTTOM ] +
doc - > border [ BOTTOM ] . width + doc - > margin [ BOTTOM ] <
height ) {
doc - > height = height - ( doc - > y + doc - > padding [ TOP ] +
doc - > padding [ BOTTOM ] +
doc - > border [ BOTTOM ] . width +
doc - > margin [ BOTTOM ] ) ;
if ( doc - > children )
doc - > children - > height = doc - > height -
( doc - > children - > margin [ TOP ] +
doc - > children - > border [ TOP ] . width +
doc - > children - > padding [ TOP ] +
doc - > children - > padding [ BOTTOM ] +
doc - > children - > border [ BOTTOM ] . width +
doc - > children - > margin [ BOTTOM ] ) ;
2005-07-02 22:17:51 +04:00
}
2004-06-03 01:21:13 +04:00
2016-04-24 01:32:21 +03:00
layout_lists ( doc , font_func ) ;
layout_position_absolute ( doc , doc , 0 , 0 , content ) ;
layout_position_relative ( doc , doc , 0 , 0 ) ;
2005-07-21 02:25:56 +04:00
2016-04-24 01:32:21 +03:00
layout_calculate_descendant_bboxes ( doc ) ;
2005-07-22 01:48:41 +04:00
2016-04-24 01:32:21 +03:00
return ret ;
2002-09-18 23:36:28 +04:00
}
2004-08-01 17:08:19 +04:00
2005-04-14 23:54:24 +04:00
/**
2016-04-24 01:32:21 +03:00
* Insert a float into a container .
2005-07-02 22:17:51 +04:00
*
2016-04-24 01:32:21 +03:00
* \ param cont block formatting context block , used to contain float
* \ param b box to add to float
*
* This sorts floats in order of descending bottom edges .
2005-04-14 23:54:24 +04:00
*/
2016-04-24 01:32:21 +03:00
static void add_float_to_container ( struct box * cont , struct box * b )
2005-04-14 23:54:24 +04:00
{
2016-04-24 01:32:21 +03:00
struct box * box = cont - > float_children ;
int b_bottom = b - > y + b - > height ;
2005-04-14 23:54:24 +04:00
2016-04-24 01:32:21 +03:00
assert ( b - > type = = BOX_FLOAT_LEFT | | b - > type = = BOX_FLOAT_RIGHT ) ;
if ( box = = NULL ) {
/* No other float children */
b - > next_float = NULL ;
cont - > float_children = b ;
return ;
} else if ( b_bottom > = box - > y + box - > height ) {
/* Goes at start of list */
b - > next_float = cont - > float_children ;
cont - > float_children = b ;
} else {
struct box * prev = NULL ;
while ( box ! = NULL & & b_bottom < box - > y + box - > height ) {
prev = box ;
box = box - > next_float ;
}
if ( prev ! = NULL ) {
b - > next_float = prev - > next_float ;
prev - > next_float = b ;
}
2005-04-14 23:54:24 +04:00
}
}
/**
2016-04-24 01:32:21 +03:00
* Split a text box .
2005-07-02 22:17:51 +04:00
*
2016-04-24 01:32:21 +03:00
* \ param content memory pool for any new boxes
* \ param fstyle style for text in text box
* \ param split_box box with text to split
* \ param new_length new length for text in split_box , after splitting
* \ param new_width new width for text in split_box , after splitting
* \ return true on success , false on memory exhaustion
*
* A new box is created and inserted into the box tree after split_box ,
* containing the text after new_length excluding the initial space character .
2005-04-14 23:54:24 +04:00
*/
2016-04-24 01:32:21 +03:00
static bool
layout_text_box_split ( html_content * content ,
plot_font_style_t * fstyle ,
struct box * split_box ,
size_t new_length ,
int new_width )
{
int space_width = split_box - > space ;
struct box * c2 ;
const struct gui_layout_table * font_func = content - > font_func ;
bool space = ( split_box - > text [ new_length ] = = ' ' ) ;
int used_length = new_length + ( space ? 1 : 0 ) ;
if ( ( space & & space_width = = 0 ) | | space_width = = UNKNOWN_WIDTH ) {
/* We're need to add a space, and we don't know how big
* it ' s to be , OR we have a space of unknown width anyway ;
* Calculate space width */
font_func - > width ( fstyle , " " , 1 , & space_width ) ;
}
if ( split_box - > space = = UNKNOWN_WIDTH )
split_box - > space = space_width ;
if ( ! space )
space_width = 0 ;
/* Create clone of split_box, c2 */
c2 = talloc_memdup ( content - > bctx , split_box , sizeof * c2 ) ;
if ( ! c2 )
return false ;
c2 - > flags | = CLONE ;
/* Set remaining text in c2 */
c2 - > text + = used_length ;
/* Set c2 according to the remaining text */
c2 - > width - = new_width + space_width ;
c2 - > flags & = ~ MEASURED ; /* width has been estimated */
c2 - > length = split_box - > length - used_length ;
/* Update split_box for its reduced text */
split_box - > width = new_width ;
split_box - > flags | = MEASURED ;
split_box - > length = new_length ;
split_box - > space = space_width ;
/* Insert c2 into box list */
c2 - > next = split_box - > next ;
split_box - > next = c2 ;
c2 - > prev = split_box ;
if ( c2 - > next )
c2 - > next - > prev = c2 ;
else
c2 - > parent - > last = c2 ;
# ifdef LAYOUT_DEBUG
LOG ( " split_box %p len: %u \" %.*s \" " , split_box , split_box - > length , split_box - > length , split_box - > text ) ;
LOG ( " new_box %p len: %u \" %.*s \" " , c2 , c2 - > length , c2 - > length , c2 - > text ) ;
# endif
return true ;
}
2005-04-14 23:54:24 +04:00
2016-04-24 01:32:21 +03:00
/**
* Compute dimensions of box , margins , paddings , and borders for a floating
* element using shrink - to - fit . Also used for inline - blocks .
*
* \ param available_width Max width available in pixels
* \ param style Box ' s style
* \ param box Box for which to find dimensions
* Box margins , borders , paddings , width and
* height are updated .
*/
static void
layout_float_find_dimensions ( int available_width ,
const css_computed_style * style ,
struct box * box )
2005-04-14 23:54:24 +04:00
{
2016-04-24 01:32:21 +03:00
int width , height , max_width , min_width , max_height , min_height ;
int * margin = box - > margin ;
int * padding = box - > padding ;
struct box_border * border = box - > border ;
enum css_overflow_e overflow_x = css_computed_overflow_x ( style ) ;
enum css_overflow_e overflow_y = css_computed_overflow_y ( style ) ;
int scrollbar_width_x =
( overflow_x = = CSS_OVERFLOW_SCROLL | |
overflow_x = = CSS_OVERFLOW_AUTO ) ?
SCROLLBAR_WIDTH : 0 ;
int scrollbar_width_y =
( overflow_y = = CSS_OVERFLOW_SCROLL | |
overflow_y = = CSS_OVERFLOW_AUTO ) ?
SCROLLBAR_WIDTH : 0 ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
layout_find_dimensions ( available_width , - 1 , box , style , & width , & height ,
& max_width , & min_width , & max_height , & min_height ,
margin , padding , border ) ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
if ( margin [ LEFT ] = = AUTO )
margin [ LEFT ] = 0 ;
if ( margin [ RIGHT ] = = AUTO )
margin [ RIGHT ] = 0 ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
if ( box - > gadget = = NULL ) {
padding [ RIGHT ] + = scrollbar_width_y ;
padding [ BOTTOM ] + = scrollbar_width_x ;
}
2005-04-14 23:54:24 +04:00
2016-04-24 01:32:21 +03:00
if ( box - > object & & ! ( box - > flags & REPLACE_DIM ) & &
content_get_type ( box - > object ) ! = CONTENT_HTML ) {
/* Floating replaced element, with intrinsic width or height.
* See 10.3 .6 and 10.6 .2 */
layout_get_object_dimensions ( box , & width , & height ,
min_width , max_width , min_height , max_height ) ;
} else if ( box - > gadget & & ( box - > gadget - > type = = GADGET_TEXTBOX | |
box - > gadget - > type = = GADGET_PASSWORD | |
box - > gadget - > type = = GADGET_FILE | |
box - > gadget - > type = = GADGET_TEXTAREA ) ) {
css_fixed size = 0 ;
css_unit unit = CSS_UNIT_EM ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
/* Give sensible dimensions to gadgets, with auto width/height,
* that don ' t shrink to fit contained text . */
assert ( box - > style ) ;
if ( box - > gadget - > type = = GADGET_TEXTBOX | |
box - > gadget - > type = = GADGET_PASSWORD | |
box - > gadget - > type = = GADGET_FILE ) {
if ( width = = AUTO ) {
size = INTTOFIX ( 10 ) ;
width = FIXTOINT ( nscss_len2px ( size , unit ,
box - > style ) ) ;
}
if ( box - > gadget - > type = = GADGET_FILE & &
height = = AUTO ) {
size = FLTTOFIX ( 1.5 ) ;
height = FIXTOINT ( nscss_len2px ( size , unit ,
box - > style ) ) ;
}
}
if ( box - > gadget - > type = = GADGET_TEXTAREA ) {
if ( width = = AUTO ) {
size = INTTOFIX ( 10 ) ;
width = FIXTOINT ( nscss_len2px ( size , unit ,
box - > style ) ) ;
}
if ( height = = AUTO ) {
size = INTTOFIX ( 4 ) ;
height = FIXTOINT ( nscss_len2px ( size , unit ,
box - > style ) ) ;
2009-07-24 03:05:34 +04:00
}
}
2016-04-24 01:32:21 +03:00
} else if ( width = = AUTO ) {
/* CSS 2.1 section 10.3.5 */
width = min ( max ( box - > min_width , available_width ) ,
box - > max_width ) ;
2005-07-03 03:37:41 +04:00
2016-04-24 01:32:21 +03:00
/* width includes margin, borders and padding */
if ( width = = available_width ) {
width - = box - > margin [ LEFT ] + box - > border [ LEFT ] . width +
box - > padding [ LEFT ] +
box - > padding [ RIGHT ] +
box - > border [ RIGHT ] . width +
box - > margin [ RIGHT ] ;
} else {
/* width was obtained from a min_width or max_width
* value , so need to use the same method for calculating
* mbp as was used in layout_minmax_block ( ) */
int fixed = 0 ;
float frac = 0 ;
calculate_mbp_width ( box - > style , LEFT , true , true , true ,
& fixed , & frac ) ;
calculate_mbp_width ( box - > style , RIGHT , true , true , true ,
& fixed , & frac ) ;
if ( fixed < 0 )
fixed = 0 ;
2009-07-24 03:05:34 +04:00
2016-04-24 01:32:21 +03:00
width - = fixed ;
2009-07-24 03:05:34 +04:00
}
2005-07-03 03:37:41 +04:00
2016-04-24 01:32:21 +03:00
if ( max_width > = 0 & & width > max_width ) width = max_width ;
if ( min_width > 0 & & width < min_width ) width = min_width ;
} else {
if ( max_width > = 0 & & width > max_width ) width = max_width ;
if ( min_width > 0 & & width < min_width ) width = min_width ;
width - = scrollbar_width_y ;
2009-05-01 22:00:01 +04:00
}
2016-04-24 01:32:21 +03:00
box - > width = width ;
box - > height = height ;
if ( margin [ TOP ] = = AUTO )
margin [ TOP ] = 0 ;
if ( margin [ BOTTOM ] = = AUTO )
margin [ BOTTOM ] = 0 ;
2005-04-14 23:54:24 +04:00
}
2006-11-05 15:58:24 +03:00
/**
2016-04-24 01:32:21 +03:00
* Layout the contents of a float or inline block .
*
* \ param b float or inline block box
* \ param width available width
* \ param content memory pool for any new boxes
* \ return true on success , false on memory exhaustion
2006-11-05 15:58:24 +03:00
*/
2016-04-24 01:32:21 +03:00
static bool layout_float ( struct box * b , int width , html_content * content )
{
assert ( b - > type = = BOX_TABLE | | b - > type = = BOX_BLOCK | |
b - > type = = BOX_INLINE_BLOCK ) ;
layout_float_find_dimensions ( width , b - > style , b ) ;
if ( b - > type = = BOX_TABLE ) {
if ( ! layout_table ( b , width , content ) )
return false ;
if ( b - > margin [ LEFT ] = = AUTO )
b - > margin [ LEFT ] = 0 ;
if ( b - > margin [ RIGHT ] = = AUTO )
b - > margin [ RIGHT ] = 0 ;
if ( b - > margin [ TOP ] = = AUTO )
b - > margin [ TOP ] = 0 ;
if ( b - > margin [ BOTTOM ] = = AUTO )
b - > margin [ BOTTOM ] = 0 ;
} else
return layout_block_context ( b , - 1 , content ) ;
return true ;
}
2006-11-05 15:58:24 +03:00
2016-04-24 01:32:21 +03:00
/**
* Position a float in the first available space .
*
* \ param c float box to position
* \ param width available width
* \ param cx x coordinate relative to cont to place float right of
* \ param y y coordinate relative to cont to place float below
* \ param cont ancestor box which defines horizontal space , for floats
*/
static void
place_float_below ( struct box * c , int width , int cx , int y , struct box * cont )
2006-11-05 15:58:24 +03:00
{
2016-04-24 01:32:21 +03:00
int x0 , x1 , yy ;
struct box * left ;
struct box * right ;
2006-11-05 15:58:24 +03:00
2016-04-24 01:32:21 +03:00
yy = y > cont - > cached_place_below_level ?
y : cont - > cached_place_below_level ;
# ifdef LAYOUT_DEBUG
LOG ( " c %p, width %i, cx %i, y %i, cont %p " , c , width , cx , y , cont ) ;
# endif
do {
y = yy ;
x0 = cx ;
x1 = cx + width ;
find_sides ( cont - > float_children , y , y + c - > height , & x0 , & x1 ,
& left , & right ) ;
if ( left ! = 0 & & right ! = 0 ) {
yy = ( left - > y + left - > height <
right - > y + right - > height ?
left - > y + left - > height :
right - > y + right - > height ) ;
} else if ( left = = 0 & & right ! = 0 ) {
yy = right - > y + right - > height ;
} else if ( left ! = 0 & & right = = 0 ) {
yy = left - > y + left - > height ;
2006-11-05 15:58:24 +03:00
}
2016-04-24 01:32:21 +03:00
} while ( ( left ! = 0 | | right ! = 0 ) & & ( c - > width > x1 - x0 ) ) ;
if ( c - > type = = BOX_FLOAT_LEFT ) {
c - > x = x0 ;
} else {
c - > x = x1 - c - > width ;
2006-11-05 15:58:24 +03:00
}
2016-04-24 01:32:21 +03:00
c - > y = y ;
cont - > cached_place_below_level = y ;
2006-11-05 15:58:24 +03:00
}
2006-06-26 08:52:34 +04:00
/**
2016-04-24 01:32:21 +03:00
* Position a line of boxes in inline formatting context .
2008-09-21 23:18:27 +04:00
*
2016-04-24 01:32:21 +03:00
* \ param first box at start of line
* \ param width available width on input , updated with actual width on output
* ( may be incorrect if the line gets split ? )
* \ param y coordinate of top of line , updated on exit to bottom
* \ param cx coordinate of left of line relative to cont
* \ param cy coordinate of top of line relative to cont
* \ param cont ancestor box which defines horizontal space , for floats
* \ param indent apply any first - line indent
* \ param has_text_children at least one TEXT in the inline_container
* \ param next_box updated to first box for next line , or 0 at end
* \ param content memory pool for any new boxes
* \ return true on success , false on memory exhaustion
2006-06-26 08:52:34 +04:00
*/
2016-04-24 01:32:21 +03:00
static bool
layout_line ( struct box * first ,
int * width ,
int * y ,
int cx ,
int cy ,
struct box * cont ,
bool indent ,
bool has_text_children ,
html_content * content ,
struct box * * next_box )
2006-06-26 08:52:34 +04:00
{
2016-04-24 01:32:21 +03:00
int height , used_height ;
int x0 = 0 ;
int x1 = * width ;
int x , h , x_previous ;
int fy = cy ;
struct box * left ;
struct box * right ;
struct box * b ;
struct box * split_box = 0 ;
struct box * d ;
struct box * br_box = 0 ;
bool move_y = false ;
bool place_below = false ;
int space_before = 0 , space_after = 0 ;
unsigned int inline_count = 0 ;
unsigned int i ;
const struct gui_layout_table * font_func = content - > font_func ;
plot_font_style_t fstyle ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
# ifdef LAYOUT_DEBUG
LOG ( " first %p, first->text '%.*s', width %i, y %i, cx %i, cy %i " , first , ( int ) first - > length , first - > text , * width , * y , cx , cy ) ;
# endif
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
/* find sides at top of line */
x0 + = cx ;
x1 + = cx ;
find_sides ( cont - > float_children , cy , cy , & x0 , & x1 , & left , & right ) ;
x0 - = cx ;
x1 - = cx ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
if ( indent )
x0 + = layout_text_indent ( first - > parent - > parent - > style , * width ) ;
if ( x1 < x0 )
x1 = x0 ;
/* get minimum line height from containing block.
* this is the line - height if there are text children and also in the
* case of an initially empty text input */
if ( has_text_children | | first - > parent - > parent - > gadget )
used_height = height =
line_height ( first - > parent - > parent - > style ) ;
else
/* inline containers with no text are usually for layout and
* look better with no minimum line - height */
used_height = height = 0 ;
/* pass 1: find height of line assuming sides at top of line: loop
* body executed at least once
* keep in sync with the loop in layout_minmax_line ( ) */
# ifdef LAYOUT_DEBUG
LOG ( " x0 %i, x1 %i, x1 - x0 %i " , x0 , x1 , x1 - x0 ) ;
# endif
for ( x = 0 , b = first ; x < = x1 - x0 & & b ! = 0 ; b = b - > next ) {
int min_width , max_width , min_height , max_height ;
assert ( b - > type = = BOX_INLINE | | b - > type = = BOX_INLINE_BLOCK | |
b - > type = = BOX_FLOAT_LEFT | |
b - > type = = BOX_FLOAT_RIGHT | |
b - > type = = BOX_BR | | b - > type = = BOX_TEXT | |
b - > type = = BOX_INLINE_END ) ;
# ifdef LAYOUT_DEBUG
LOG ( " pass 1: b %p, x %i " , b , x ) ;
# endif
if ( b - > type = = BOX_BR )
break ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
if ( b - > type = = BOX_FLOAT_LEFT | | b - > type = = BOX_FLOAT_RIGHT )
continue ;
if ( b - > type = = BOX_INLINE_BLOCK & &
( css_computed_position ( b - > style ) = =
CSS_POSITION_ABSOLUTE | |
css_computed_position ( b - > style ) = =
CSS_POSITION_FIXED ) )
2006-06-26 08:52:34 +04:00
continue ;
2016-04-24 01:32:21 +03:00
assert ( b - > style ! = NULL ) ;
font_plot_style_from_css ( b - > style , & fstyle ) ;
2008-09-21 23:18:27 +04:00
2016-04-24 01:32:21 +03:00
x + = space_after ;
2008-09-21 23:18:27 +04:00
2016-04-24 01:32:21 +03:00
if ( b - > type = = BOX_INLINE_BLOCK ) {
if ( b - > max_width ! = UNKNOWN_WIDTH )
if ( ! layout_float ( b , * width , content ) )
return false ;
h = b - > border [ TOP ] . width + b - > padding [ TOP ] + b - > height +
b - > padding [ BOTTOM ] +
b - > border [ BOTTOM ] . width ;
if ( height < h )
height = h ;
x + = b - > margin [ LEFT ] + b - > border [ LEFT ] . width +
b - > padding [ LEFT ] + b - > width +
b - > padding [ RIGHT ] +
b - > border [ RIGHT ] . width +
b - > margin [ RIGHT ] ;
space_after = 0 ;
continue ;
2008-09-21 23:18:27 +04:00
}
2016-04-24 01:32:21 +03:00
if ( b - > type = = BOX_INLINE ) {
/* calculate borders, margins, and padding */
layout_find_dimensions ( * width , - 1 , b , b - > style , 0 , 0 ,
0 , 0 , 0 , 0 , b - > margin , b - > padding ,
b - > border ) ;
for ( i = 0 ; i ! = 4 ; i + + )
if ( b - > margin [ i ] = = AUTO )
b - > margin [ i ] = 0 ;
x + = b - > margin [ LEFT ] + b - > border [ LEFT ] . width +
b - > padding [ LEFT ] ;
if ( b - > inline_end ) {
b - > inline_end - > margin [ RIGHT ] = b - > margin [ RIGHT ] ;
b - > inline_end - > padding [ RIGHT ] =
b - > padding [ RIGHT ] ;
b - > inline_end - > border [ RIGHT ] =
b - > border [ RIGHT ] ;
} else {
x + = b - > padding [ RIGHT ] +
b - > border [ RIGHT ] . width +
b - > margin [ RIGHT ] ;
}
} else if ( b - > type = = BOX_INLINE_END ) {
b - > width = 0 ;
if ( b - > space = = UNKNOWN_WIDTH ) {
font_func - > width ( & fstyle , " " , 1 , & b - > space ) ;
/** \todo handle errors */
}
space_after = b - > space ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
x + = b - > padding [ RIGHT ] + b - > border [ RIGHT ] . width +
b - > margin [ RIGHT ] ;
2006-06-27 02:24:42 +04:00
continue ;
2016-04-24 01:32:21 +03:00
}
2006-06-27 02:24:42 +04:00
2016-04-24 01:32:21 +03:00
if ( ! b - > object & & ! ( b - > flags & IFRAME ) & & ! b - > gadget & &
! ( b - > flags & REPLACE_DIM ) ) {
/* inline non-replaced, 10.3.1 and 10.6.1 */
b - > height = line_height ( b - > style ? b - > style :
b - > parent - > parent - > style ) ;
if ( height < b - > height )
height = b - > height ;
2006-06-27 02:24:42 +04:00
2016-04-24 01:32:21 +03:00
if ( ! b - > text ) {
b - > width = 0 ;
space_after = 0 ;
continue ;
2006-06-27 02:24:42 +04:00
}
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
if ( b - > width = = UNKNOWN_WIDTH ) {
/** \todo handle errors */
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
/* If it's a select element, we must use the
* width of the widest option text */
if ( b - > parent - > parent - > gadget & &
b - > parent - > parent - > gadget - > type
= = GADGET_SELECT ) {
int opt_maxwidth = 0 ;
struct form_option * o ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
for ( o = b - > parent - > parent - > gadget - >
data . select . items ; o ;
o = o - > next ) {
int opt_width ;
font_func - > width ( & fstyle ,
o - > text ,
strlen ( o - > text ) ,
& opt_width ) ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
if ( opt_maxwidth < opt_width )
opt_maxwidth = opt_width ;
}
b - > width = opt_maxwidth ;
if ( nsoption_bool ( core_select_menu ) )
b - > width + = SCROLLBAR_WIDTH ;
} else {
font_func - > width ( & fstyle , b - > text ,
b - > length , & b - > width ) ;
b - > flags | = MEASURED ;
}
}
2009-05-28 22:06:49 +04:00
2016-04-24 01:32:21 +03:00
/* If the current text has not been measured (i.e. its
* width was estimated after splitting ) , and it fits on
* the line , measure it properly , so next box is placed
* correctly . */
if ( b - > text & & ( x + b - > width < x1 - x0 ) & &
! ( b - > flags & MEASURED ) & &
b - > next ) {
font_func - > width ( & fstyle , b - > text ,
b - > length , & b - > width ) ;
b - > flags | = MEASURED ;
}
2006-06-26 17:22:43 +04:00
2016-04-24 01:32:21 +03:00
x + = b - > width ;
if ( b - > space = = UNKNOWN_WIDTH ) {
font_func - > width ( & fstyle , " " , 1 , & b - > space ) ;
/** \todo handle errors */
}
space_after = b - > space ;
continue ;
2006-06-26 08:52:34 +04:00
}
2016-04-24 01:32:21 +03:00
space_after = 0 ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
/* inline replaced, 10.3.2 and 10.6.2 */
assert ( b - > style ) ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
layout_find_dimensions ( * width , - 1 , b , b - > style ,
& b - > width , & b - > height , & max_width , & min_width ,
& max_height , & min_height , NULL , NULL , NULL ) ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
if ( b - > object & & ! ( b - > flags & REPLACE_DIM ) ) {
layout_get_object_dimensions ( b , & b - > width , & b - > height ,
min_width , max_width ,
min_height , max_height ) ;
} else if ( b - > flags & IFRAME ) {
/* TODO: should we look at the content dimensions? */
if ( b - > width = = AUTO )
b - > width = 400 ;
if ( b - > height = = AUTO )
b - > height = 300 ;
/* We reformat the iframe browser window to new
* dimensions in pass 2 */
} else {
/* form control with no object */
if ( b - > width = = AUTO )
b - > width = FIXTOINT ( nscss_len2px ( INTTOFIX ( 1 ) ,
CSS_UNIT_EM , b - > style ) ) ;
if ( b - > height = = AUTO )
b - > height = FIXTOINT ( nscss_len2px ( INTTOFIX ( 1 ) ,
CSS_UNIT_EM , b - > style ) ) ;
}
/* Reformat object to new box size */
if ( b - > object & & content_get_type ( b - > object ) = = CONTENT_HTML & &
b - > width ! =
content_get_available_width ( b - > object ) ) {
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
enum css_height_e htype = css_computed_height ( b - > style ,
& value , & unit ) ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
content_reformat ( b - > object , false , b - > width , b - > height ) ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
if ( htype = = CSS_HEIGHT_AUTO )
b - > height = content_get_height ( b - > object ) ;
}
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
if ( height < b - > height )
height = b - > height ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
x + = b - > width ;
2006-10-09 02:46:25 +04:00
}
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
/* find new sides using this height */
x0 = cx ;
x1 = cx + * width ;
find_sides ( cont - > float_children , cy , cy + height , & x0 , & x1 ,
& left , & right ) ;
x0 - = cx ;
x1 - = cx ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
if ( indent )
x0 + = layout_text_indent ( first - > parent - > parent - > style , * width ) ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
if ( x1 < x0 )
x1 = x0 ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
space_after = space_before = 0 ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
/* pass 2: place boxes in line: loop body executed at least once */
# ifdef LAYOUT_DEBUG
LOG ( " x0 %i, x1 %i, x1 - x0 %i " , x0 , x1 , x1 - x0 ) ;
# endif
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
for ( x = x_previous = 0 , b = first ; x < = x1 - x0 & & b ; b = b - > next ) {
# ifdef LAYOUT_DEBUG
LOG ( " pass 2: b %p, x %i " , b , x ) ;
# endif
2006-10-09 02:46:25 +04:00
2016-04-24 01:32:21 +03:00
if ( b - > type = = BOX_INLINE_BLOCK & &
( css_computed_position ( b - > style ) = =
CSS_POSITION_ABSOLUTE | |
css_computed_position ( b - > style ) = =
CSS_POSITION_FIXED ) ) {
b - > x = x + space_after ;
2006-06-29 19:53:17 +04:00
2016-04-24 01:32:21 +03:00
} else if ( b - > type = = BOX_INLINE | |
b - > type = = BOX_INLINE_BLOCK | |
b - > type = = BOX_TEXT | |
b - > type = = BOX_INLINE_END ) {
assert ( b - > width ! = UNKNOWN_WIDTH ) ;
2006-06-29 19:53:17 +04:00
2016-04-24 01:32:21 +03:00
x_previous = x ;
x + = space_after ;
b - > x = x ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
if ( ( b - > type = = BOX_INLINE & & ! b - > inline_end ) | |
b - > type = = BOX_INLINE_BLOCK ) {
b - > x + = b - > margin [ LEFT ] + b - > border [ LEFT ] . width ;
x = b - > x + b - > padding [ LEFT ] + b - > width +
b - > padding [ RIGHT ] +
b - > border [ RIGHT ] . width +
b - > margin [ RIGHT ] ;
} else if ( b - > type = = BOX_INLINE ) {
b - > x + = b - > margin [ LEFT ] + b - > border [ LEFT ] . width ;
x = b - > x + b - > padding [ LEFT ] + b - > width ;
} else if ( b - > type = = BOX_INLINE_END ) {
b - > height = b - > inline_end - > height ;
x + = b - > padding [ RIGHT ] +
b - > border [ RIGHT ] . width +
b - > margin [ RIGHT ] ;
} else {
x + = b - > width ;
}
space_before = space_after ;
if ( b - > object | | b - > flags & REPLACE_DIM | |
b - > flags & IFRAME )
space_after = 0 ;
else if ( b - > text | | b - > type = = BOX_INLINE_END ) {
if ( b - > space = = UNKNOWN_WIDTH ) {
font_plot_style_from_css ( b - > style ,
& fstyle ) ;
/** \todo handle errors */
font_func - > width ( & fstyle , " " , 1 ,
& b - > space ) ;
}
space_after = b - > space ;
} else {
space_after = 0 ;
}
split_box = b ;
move_y = true ;
inline_count + + ;
} else if ( b - > type = = BOX_BR ) {
b - > x = x ;
b - > width = 0 ;
br_box = b ;
b = b - > next ;
split_box = 0 ;
move_y = true ;
break ;
} else {
/* float */
2011-04-04 02:23:14 +04:00
# ifdef LAYOUT_DEBUG
2016-04-24 01:32:21 +03:00
LOG ( " float %p " , b ) ;
2011-04-04 02:23:14 +04:00
# endif
2016-04-24 01:32:21 +03:00
d = b - > children ;
d - > float_children = 0 ;
d - > cached_place_below_level = 0 ;
b - > float_container = d - > float_container = cont ;
2006-06-29 13:55:31 +04:00
2016-04-24 01:32:21 +03:00
if ( ! layout_float ( d , * width , content ) )
return false ;
2006-06-29 13:37:18 +04:00
2016-04-24 01:32:21 +03:00
# ifdef LAYOUT_DEBUG
LOG ( " %p : %d %d " , d , d - > margin [ TOP ] , d - > border [ TOP ] . width ) ;
# endif
2008-09-28 00:19:46 +04:00
2016-04-24 01:32:21 +03:00
d - > x = d - > margin [ LEFT ] + d - > border [ LEFT ] . width ;
d - > y = d - > margin [ TOP ] + d - > border [ TOP ] . width ;
b - > width = d - > margin [ LEFT ] + d - > border [ LEFT ] . width +
d - > padding [ LEFT ] + d - > width +
d - > padding [ RIGHT ] +
d - > border [ RIGHT ] . width +
d - > margin [ RIGHT ] ;
b - > height = d - > margin [ TOP ] + d - > border [ TOP ] . width +
d - > padding [ TOP ] + d - > height +
d - > padding [ BOTTOM ] +
d - > border [ BOTTOM ] . width +
d - > margin [ BOTTOM ] ;
if ( b - > width > ( x1 - x0 ) - x )
place_below = true ;
if ( d - > style & & ( css_computed_clear ( d - > style ) = =
CSS_CLEAR_NONE | |
( css_computed_clear ( d - > style ) = =
CSS_CLEAR_LEFT & & left = = 0 ) | |
( css_computed_clear ( d - > style ) = =
CSS_CLEAR_RIGHT & &
right = = 0 ) | |
( css_computed_clear ( d - > style ) = =
CSS_CLEAR_BOTH & &
left = = 0 & & right = = 0 ) ) & &
( ! place_below | |
( left = = 0 & & right = = 0 & & x = = 0 ) ) & &
cy > = cont - > clear_level & &
cy > = cont - > cached_place_below_level ) {
/* + not cleared or,
* cleared and there are no floats to clear
* + fits without needing to be placed below or ,
* this line is empty with no floats
* + current y , cy , is below the clear level
*
* Float affects current line */
if ( b - > type = = BOX_FLOAT_LEFT ) {
b - > x = cx + x0 ;
if ( b - > width > 0 )
x0 + = b - > width ;
left = b ;
} else {
b - > x = cx + x1 - b - > width ;
if ( b - > width > 0 )
x1 - = b - > width ;
right = b ;
}
b - > y = cy ;
} else {
/* cleared or doesn't fit on line */
/* place below into next available space */
int fcy = ( cy > cont - > clear_level ) ? cy :
cont - > clear_level ;
fcy = ( fcy > cont - > cached_place_below_level ) ?
fcy :
cont - > cached_place_below_level ;
fy = ( fy > fcy ) ? fy : fcy ;
fy = ( fy = = cy ) ? fy + height : fy ;
2008-09-28 00:19:46 +04:00
2016-04-24 01:32:21 +03:00
place_float_below ( b , * width , cx , fy , cont ) ;
fy = b - > y ;
if ( d - > style & & (
( css_computed_clear ( d - > style ) = =
CSS_CLEAR_LEFT & & left ! = 0 ) | |
( css_computed_clear ( d - > style ) = =
CSS_CLEAR_RIGHT & &
right ! = 0 ) | |
( css_computed_clear ( d - > style ) = =
CSS_CLEAR_BOTH & &
( left ! = 0 | | right ! = 0 ) ) ) ) {
/* to be cleared below existing
* floats */
if ( b - > type = = BOX_FLOAT_LEFT )
b - > x = cx ;
else
b - > x = cx + * width - b - > width ;
2008-09-28 00:19:46 +04:00
2016-04-24 01:32:21 +03:00
fcy = layout_clear ( cont - > float_children ,
css_computed_clear ( d - > style ) ) ;
if ( fcy > cont - > clear_level )
cont - > clear_level = fcy ;
if ( b - > y < fcy )
b - > y = fcy ;
}
if ( b - > type = = BOX_FLOAT_LEFT )
left = b ;
else
right = b ;
2006-06-26 08:52:34 +04:00
}
2016-04-24 01:32:21 +03:00
add_float_to_container ( cont , b ) ;
2006-06-26 17:22:43 +04:00
2016-04-24 01:32:21 +03:00
split_box = 0 ;
}
}
2006-06-26 17:22:43 +04:00
2016-04-24 01:32:21 +03:00
if ( x1 - x0 < x & & split_box ) {
/* the last box went over the end */
size_t split = 0 ;
int w ;
bool no_wrap = css_computed_white_space (
split_box - > style ) = = CSS_WHITE_SPACE_NOWRAP | |
css_computed_white_space (
split_box - > style ) = = CSS_WHITE_SPACE_PRE ;
2006-06-29 13:37:18 +04:00
2016-04-24 01:32:21 +03:00
x = x_previous ;
2008-09-28 00:19:46 +04:00
2016-04-24 01:32:21 +03:00
if ( ! no_wrap & &
( split_box - > type = = BOX_INLINE | |
split_box - > type = = BOX_TEXT ) & &
! split_box - > object & &
! ( split_box - > flags & REPLACE_DIM ) & &
! ( split_box - > flags & IFRAME ) & &
! split_box - > gadget & & split_box - > text ) {
2008-09-28 00:19:46 +04:00
2016-04-24 01:32:21 +03:00
font_plot_style_from_css ( split_box - > style , & fstyle ) ;
/** \todo handle errors */
font_func - > split ( & fstyle ,
split_box - > text ,
split_box - > length ,
x1 - x0 - x - space_before ,
& split ,
& w ) ;
}
2008-09-28 00:19:46 +04:00
2016-04-24 01:32:21 +03:00
/* split == 0 implies that text can't be split */
2006-06-26 17:22:43 +04:00
2016-04-24 01:32:21 +03:00
if ( split = = 0 )
w = split_box - > width ;
2006-06-29 13:37:18 +04:00
2016-04-24 01:32:21 +03:00
# ifdef LAYOUT_DEBUG
LOG ( " splitting: split_box %p \" %.*s \" , spilt %zu, w %i, " " left %p, right %p, inline_count %u " , split_box , ( int ) split_box - > length , split_box - > text , split , w , left , right , inline_count ) ;
# endif
2008-09-28 00:19:46 +04:00
2016-04-24 01:32:21 +03:00
if ( ( split = = 0 | | x1 - x0 < = x + space_before + w ) & &
! left & & ! right & & inline_count = = 1 ) {
/* first word of box doesn't fit, but no floats and
* first box on line so force in */
if ( split = = 0 | | split = = split_box - > length ) {
/* only one word in this box, or not text
* or white - space : nowrap */
b = split_box - > next ;
} else {
/* cut off first word for this line */
if ( ! layout_text_box_split ( content , & fstyle ,
split_box , split , w ) )
return false ;
b = split_box - > next ;
}
x + = space_before + w ;
# ifdef LAYOUT_DEBUG
LOG ( " forcing " ) ;
# endif
} else if ( ( split = = 0 | | x1 - x0 < = x + space_before + w ) & &
inline_count = = 1 ) {
/* first word of first box doesn't fit, but a float is
* taking some of the width so move below it */
assert ( left | | right ) ;
used_height = 0 ;
if ( left ) {
# ifdef LAYOUT_DEBUG
LOG ( " cy %i, left->y %i, left->height %i " , cy , left - > y , left - > height ) ;
# endif
used_height = left - > y + left - > height - cy + 1 ;
# ifdef LAYOUT_DEBUG
LOG ( " used_height %i " , used_height ) ;
# endif
}
if ( right & & used_height <
right - > y + right - > height - cy + 1 )
used_height = right - > y + right - > height - cy + 1 ;
2008-09-28 00:19:46 +04:00
2016-04-24 01:32:21 +03:00
if ( used_height < 0 )
used_height = 0 ;
2008-09-28 00:19:46 +04:00
2016-04-24 01:32:21 +03:00
b = split_box ;
# ifdef LAYOUT_DEBUG
LOG ( " moving below float " ) ;
# endif
} else if ( split = = 0 | | x1 - x0 < = x + space_before + w ) {
/* first word of box doesn't fit so leave box for next
* line */
b = split_box ;
# ifdef LAYOUT_DEBUG
LOG ( " leaving for next line " ) ;
# endif
} else {
/* fit as many words as possible */
assert ( split ! = 0 ) ;
# ifdef LAYOUT_DEBUG
LOG ( " '%.*s' %i %zu %i " , ( int ) split_box - > length , split_box - > text , x1 - x0 , split , w ) ;
# endif
if ( split ! = split_box - > length ) {
if ( ! layout_text_box_split ( content , & fstyle ,
split_box , split , w ) )
return false ;
b = split_box - > next ;
}
x + = space_before + w ;
# ifdef LAYOUT_DEBUG
LOG ( " fitting words " ) ;
# endif
}
move_y = true ;
}
2008-09-28 00:19:46 +04:00
2016-04-24 01:32:21 +03:00
/* set positions */
switch ( css_computed_text_align ( first - > parent - > parent - > style ) ) {
case CSS_TEXT_ALIGN_RIGHT :
case CSS_TEXT_ALIGN_LIBCSS_RIGHT :
x0 = x1 - x ;
break ;
case CSS_TEXT_ALIGN_CENTER :
case CSS_TEXT_ALIGN_LIBCSS_CENTER :
x0 = ( x0 + ( x1 - x ) ) / 2 ;
break ;
case CSS_TEXT_ALIGN_LEFT :
case CSS_TEXT_ALIGN_LIBCSS_LEFT :
case CSS_TEXT_ALIGN_JUSTIFY :
/* leave on left */
break ;
case CSS_TEXT_ALIGN_DEFAULT :
/* None; consider text direction */
switch ( css_computed_direction ( first - > parent - > parent - > style ) ) {
case CSS_DIRECTION_LTR :
/* leave on left */
break ;
case CSS_DIRECTION_RTL :
x0 = x1 - x ;
break ;
}
break ;
}
2008-09-28 00:19:46 +04:00
2016-04-24 01:32:21 +03:00
for ( d = first ; d ! = b ; d = d - > next ) {
d - > flags & = ~ NEW_LINE ;
2008-09-28 00:19:46 +04:00
2016-04-24 01:32:21 +03:00
if ( d - > type = = BOX_INLINE_BLOCK & &
( css_computed_position ( d - > style ) = =
CSS_POSITION_ABSOLUTE | |
css_computed_position ( d - > style ) = =
CSS_POSITION_FIXED ) ) {
/* positioned inline-blocks:
* set static position ( x , y ) only , rest of positioning
* is handled later */
d - > x + = x0 ;
d - > y = * y ;
continue ;
} else if ( ( d - > type = = BOX_INLINE & &
( ( d - > object | | d - > gadget ) = = false ) & &
! ( d - > flags & IFRAME ) & &
! ( d - > flags & REPLACE_DIM ) ) | |
d - > type = = BOX_BR | |
d - > type = = BOX_TEXT | |
d - > type = = BOX_INLINE_END ) {
/* regular (non-replaced) inlines */
d - > x + = x0 ;
d - > y = * y - d - > padding [ TOP ] ;
2008-09-28 00:19:46 +04:00
2016-04-24 01:32:21 +03:00
if ( d - > type = = BOX_TEXT & & d - > height > used_height ) {
/* text */
used_height = d - > height ;
}
} else if ( ( d - > type = = BOX_INLINE ) | |
d - > type = = BOX_INLINE_BLOCK ) {
/* replaced inlines and inline-blocks */
d - > x + = x0 ;
d - > y = * y + d - > border [ TOP ] . width + d - > margin [ TOP ] ;
h = d - > margin [ TOP ] + d - > border [ TOP ] . width +
d - > padding [ TOP ] + d - > height +
d - > padding [ BOTTOM ] +
d - > border [ BOTTOM ] . width +
d - > margin [ BOTTOM ] ;
if ( used_height < h )
used_height = h ;
2006-06-26 08:52:34 +04:00
}
}
2011-04-04 02:23:14 +04:00
2016-04-24 01:32:21 +03:00
first - > flags | = NEW_LINE ;
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
assert ( b ! = first | | ( move_y & & 0 < used_height & & ( left | | right ) ) ) ;
/* handle vertical-align by adjusting box y values */
/** \todo proper vertical alignment handling */
for ( d = first ; d ! = b ; d = d - > next ) {
if ( ( d - > type = = BOX_INLINE & & d - > inline_end ) | |
d - > type = = BOX_BR | |
d - > type = = BOX_TEXT | |
d - > type = = BOX_INLINE_END ) {
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
switch ( css_computed_vertical_align ( d - > style , & value ,
& unit ) ) {
case CSS_VERTICAL_ALIGN_SUPER :
case CSS_VERTICAL_ALIGN_TOP :
case CSS_VERTICAL_ALIGN_TEXT_TOP :
/* already at top */
break ;
case CSS_VERTICAL_ALIGN_SUB :
case CSS_VERTICAL_ALIGN_BOTTOM :
case CSS_VERTICAL_ALIGN_TEXT_BOTTOM :
d - > y + = used_height - d - > height ;
break ;
default :
case CSS_VERTICAL_ALIGN_BASELINE :
d - > y + = 0.75 * ( used_height - d - > height ) ;
break ;
}
}
2006-06-29 15:55:21 +04:00
}
2006-06-26 17:22:43 +04:00
2016-04-24 01:32:21 +03:00
/* handle clearance for br */
if ( br_box & & css_computed_clear ( br_box - > style ) ! = CSS_CLEAR_NONE ) {
int clear_y = layout_clear ( cont - > float_children ,
css_computed_clear ( br_box - > style ) ) ;
if ( used_height < clear_y - cy )
used_height = clear_y - cy ;
2006-06-26 08:52:34 +04:00
}
2016-04-24 01:32:21 +03:00
if ( move_y )
* y + = used_height ;
* next_box = b ;
* width = x ; /* return actual width */
return true ;
}
/* exported function documented in render/layout.h */
bool layout_inline_container ( struct box * inline_container , int width ,
struct box * cont , int cx , int cy , html_content * content )
{
bool first_line = true ;
bool has_text_children ;
struct box * c , * next ;
int y = 0 ;
int curwidth , maxwidth = width ;
assert ( inline_container - > type = = BOX_INLINE_CONTAINER ) ;
2011-04-04 02:23:14 +04:00
# ifdef LAYOUT_DEBUG
2016-04-24 01:32:21 +03:00
LOG ( " inline_container %p, width %i, cont %p, cx %i, cy %i " , inline_container , width , cont , cx , cy ) ;
2011-04-04 02:23:14 +04:00
# endif
2016-04-24 01:32:21 +03:00
has_text_children = false ;
for ( c = inline_container - > children ; c ; c = c - > next ) {
bool is_pre = false ;
if ( c - > style ) {
enum css_white_space_e whitespace ;
whitespace = css_computed_white_space ( c - > style ) ;
is_pre = ( whitespace = = CSS_WHITE_SPACE_PRE | |
whitespace = = CSS_WHITE_SPACE_PRE_LINE | |
whitespace = = CSS_WHITE_SPACE_PRE_WRAP ) ;
2006-06-26 08:52:34 +04:00
}
2016-04-24 01:32:21 +03:00
if ( ( ! c - > object & & ! ( c - > flags & REPLACE_DIM ) & &
! ( c - > flags & IFRAME ) & &
c - > text & & ( c - > length | | is_pre ) ) | |
c - > type = = BOX_BR )
has_text_children = true ;
2006-06-26 08:52:34 +04:00
}
2011-04-04 02:23:14 +04:00
2016-04-24 01:32:21 +03:00
/** \todo fix wrapping so that a box with horizontal scrollbar will
* shrink back to ' width ' if no word is wider than ' width ' ( Or just set
* curwidth = width and have the multiword lines wrap to the min width )
*/
for ( c = inline_container - > children ; c ; ) {
2011-04-04 02:23:14 +04:00
# ifdef LAYOUT_DEBUG
2016-04-24 01:32:21 +03:00
LOG ( " c %p " , c ) ;
2011-04-04 02:23:14 +04:00
# endif
2016-04-24 01:32:21 +03:00
curwidth = inline_container - > width ;
if ( ! layout_line ( c , & curwidth , & y , cx , cy + y , cont , first_line ,
has_text_children , content , & next ) )
return false ;
maxwidth = max ( maxwidth , curwidth ) ;
c = next ;
first_line = false ;
2006-06-29 15:55:21 +04:00
}
2016-04-24 01:32:21 +03:00
inline_container - > width = maxwidth ;
inline_container - > height = y ;
2006-06-26 08:52:34 +04:00
return true ;
}
2016-04-24 01:32:21 +03:00
/* exported function documented in render/layout.h */
void
layout_minmax_table ( struct box * table , const struct gui_layout_table * font_func )
2006-06-26 08:52:34 +04:00
{
2016-04-24 01:32:21 +03:00
unsigned int i , j ;
int border_spacing_h = 0 ;
int table_min = 0 , table_max = 0 ;
int extra_fixed = 0 ;
float extra_frac = 0 ;
struct column * col = table - > col ;
struct box * row_group , * row , * cell ;
enum css_width_e wtype ;
2009-07-24 03:05:34 +04:00
css_fixed value = 0 ;
css_unit unit = CSS_UNIT_PX ;
2016-04-24 01:32:21 +03:00
/* check if the widths have already been calculated */
if ( table - > max_width ! = UNKNOWN_MAX_WIDTH )
return ;
2006-06-30 03:30:06 +04:00
2016-04-24 01:32:21 +03:00
/* start with 0 except for fixed-width columns */
for ( i = 0 ; i ! = table - > columns ; i + + ) {
if ( col [ i ] . type = = COLUMN_WIDTH_FIXED )
col [ i ] . min = col [ i ] . max = col [ i ] . width ;
else
col [ i ] . min = col [ i ] . max = 0 ;
2009-07-24 03:05:34 +04:00
}
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
/* border-spacing is used in the separated borders model */
if ( css_computed_border_collapse ( table - > style ) = =
CSS_BORDER_COLLAPSE_SEPARATE ) {
css_fixed h = 0 , v = 0 ;
css_unit hu = CSS_UNIT_PX , vu = CSS_UNIT_PX ;
css_computed_border_spacing ( table - > style , & h , & hu , & v , & vu ) ;
border_spacing_h = FIXTOINT ( nscss_len2px ( h , hu , table - > style ) ) ;
2009-07-24 03:05:34 +04:00
}
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
/* 1st pass: consider cells with colspan 1 only */
for ( row_group = table - > children ; row_group ; row_group = row_group - > next )
for ( row = row_group - > children ; row ; row = row - > next )
for ( cell = row - > children ; cell ; cell = cell - > next ) {
assert ( cell - > type = = BOX_TABLE_CELL ) ;
assert ( cell - > style ) ;
/** TODO: Handle colspan="0" correctly.
* It ' s currently converted to 1 in box normaisation */
assert ( cell - > columns ! = 0 ) ;
if ( cell - > columns ! = 1 )
continue ;
layout_minmax_block ( cell , font_func ) ;
i = cell - > start_column ;
if ( col [ i ] . positioned )
continue ;
/* update column min, max widths using cell widths */
if ( col [ i ] . min < cell - > min_width )
col [ i ] . min = cell - > min_width ;
if ( col [ i ] . max < cell - > max_width )
col [ i ] . max = cell - > max_width ;
}
/* 2nd pass: cells which span multiple columns */
for ( row_group = table - > children ; row_group ; row_group = row_group - > next )
for ( row = row_group - > children ; row ; row = row - > next )
for ( cell = row - > children ; cell ; cell = cell - > next ) {
unsigned int flexible_columns = 0 ;
int min = 0 , max = 0 , fixed_width = 0 , extra ;
if ( cell - > columns = = 1 )
continue ;
layout_minmax_block ( cell , font_func ) ;
i = cell - > start_column ;
/* find min width so far of spanned columns, and count
* number of non - fixed spanned columns and total fixed width */
for ( j = 0 ; j ! = cell - > columns ; j + + ) {
min + = col [ i + j ] . min ;
if ( col [ i + j ] . type = = COLUMN_WIDTH_FIXED )
fixed_width + = col [ i + j ] . width ;
else
flexible_columns + + ;
}
min + = ( cell - > columns - 1 ) * border_spacing_h ;
/* distribute extra min to spanned columns */
if ( min < cell - > min_width ) {
if ( flexible_columns = = 0 ) {
extra = 1 + ( cell - > min_width - min ) /
cell - > columns ;
for ( j = 0 ; j ! = cell - > columns ; j + + ) {
col [ i + j ] . min + = extra ;
if ( col [ i + j ] . max < col [ i + j ] . min )
col [ i + j ] . max = col [ i + j ] . min ;
}
} else {
extra = 1 + ( cell - > min_width - min ) /
flexible_columns ;
for ( j = 0 ; j ! = cell - > columns ; j + + ) {
if ( col [ i + j ] . type ! =
COLUMN_WIDTH_FIXED ) {
col [ i + j ] . min + = extra ;
if ( col [ i + j ] . max <
col [ i + j ] . min )
col [ i + j ] . max =
col [ i + j ] . min ;
}
}
}
}
/* find max width so far of spanned columns */
for ( j = 0 ; j ! = cell - > columns ; j + + )
max + = col [ i + j ] . max ;
max + = ( cell - > columns - 1 ) * border_spacing_h ;
/* distribute extra max to spanned columns */
if ( max < cell - > max_width & & flexible_columns ) {
extra = 1 + ( cell - > max_width - max ) / flexible_columns ;
for ( j = 0 ; j ! = cell - > columns ; j + + )
if ( col [ i + j ] . type ! = COLUMN_WIDTH_FIXED )
col [ i + j ] . max + = extra ;
2009-07-24 03:05:34 +04:00
}
}
2006-06-26 08:52:34 +04:00
2016-04-24 01:32:21 +03:00
for ( i = 0 ; i ! = table - > columns ; i + + ) {
if ( col [ i ] . max < col [ i ] . min ) {
box_dump ( stderr , table , 0 , true ) ;
assert ( 0 ) ;
2009-07-24 03:05:34 +04:00
}
2016-04-24 01:32:21 +03:00
table_min + = col [ i ] . min ;
table_max + = col [ i ] . max ;
}
/* fixed width takes priority, unless it is too narrow */
wtype = css_computed_width ( table - > style , & value , & unit ) ;
if ( wtype = = CSS_WIDTH_SET & & unit ! = CSS_UNIT_PCT ) {
int width = FIXTOINT ( nscss_len2px ( value , unit , table - > style ) ) ;
if ( table_min < width )
table_min = width ;
if ( table_max < width )
table_max = width ;
2009-07-24 03:05:34 +04:00
}
2016-04-24 01:32:21 +03:00
/* add margins, border, padding to min, max widths */
calculate_mbp_width ( table - > style , LEFT , true , true , true ,
& extra_fixed , & extra_frac ) ;
calculate_mbp_width ( table - > style , RIGHT , true , true , true ,
& extra_fixed , & extra_frac ) ;
if ( extra_fixed < 0 )
extra_fixed = 0 ;
if ( extra_frac < 0 )
extra_frac = 0 ;
if ( 1.0 < = extra_frac )
extra_frac = 0.9 ;
table - > min_width = ( table_min + extra_fixed ) / ( 1.0 - extra_frac ) ;
table - > max_width = ( table_max + extra_fixed ) / ( 1.0 - extra_frac ) ;
table - > min_width + = ( table - > columns + 1 ) * border_spacing_h ;
table - > max_width + = ( table - > columns + 1 ) * border_spacing_h ;
assert ( 0 < = table - > min_width & & table - > min_width < = table - > max_width ) ;
2006-06-26 08:52:34 +04:00
}
2011-02-22 17:57:04 +03:00
/**
* Find a box ' s bounding box relative to itself , i . e . the box ' s border edge box
*
* \ param box box find bounding box of
* \ param desc_x0 updated to left of box ' s bbox
* \ param desc_y0 updated to top of box ' s bbox
* \ param desc_x1 updated to right of box ' s bbox
* \ param desc_y1 updated to bottom of box ' s bbox
*/
2016-04-24 01:32:21 +03:00
static void
layout_get_box_bbox ( struct box * box ,
int * desc_x0 , int * desc_y0 ,
int * desc_x1 , int * desc_y1 )
2011-02-22 17:57:04 +03:00
{
* desc_x0 = - box - > border [ LEFT ] . width ;
* desc_y0 = - box - > border [ TOP ] . width ;
* desc_x1 = box - > padding [ LEFT ] + box - > width + box - > padding [ RIGHT ] +
box - > border [ RIGHT ] . width ;
* desc_y1 = box - > padding [ TOP ] + box - > height + box - > padding [ BOTTOM ] +
box - > border [ BOTTOM ] . width ;
2013-04-17 15:12:27 +04:00
/* To stop the top of text getting clipped when css line-height is
* reduced , we increase the top of the descendant bbox . */
if ( box - > type = = BOX_BLOCK & & box - > style ! = NULL & &
2014-06-01 21:36:22 +04:00
css_computed_overflow_y ( box - > style ) = =
2013-04-17 15:12:27 +04:00
CSS_OVERFLOW_VISIBLE & &
box - > object = = NULL ) {
css_fixed font_size = 0 ;
css_unit font_unit = CSS_UNIT_PT ;
int text_height ;
css_computed_font_size ( box - > style , & font_size , & font_unit ) ;
text_height = nscss_len2px ( font_size , font_unit , box - > style ) ;
2014-08-20 14:08:35 +04:00
text_height = FIXTOINT ( text_height * 3 / 4 ) ;
2013-04-17 15:12:27 +04:00
* desc_y0 = ( * desc_y0 < - text_height ) ? * desc_y0 : - text_height ;
}
2011-02-22 17:57:04 +03:00
}
2011-02-22 14:38:19 +03:00
/**
* Apply changes to box descendant_ [ xy ] [ 01 ] values due to given child .
*
* \ param box box to update
* \ param child a box , which may affect box ' s descendant bbox
* \ param off_x offset to apply to child - > x coord to treat as child of box
* \ param off_y offset to apply to child - > y coord to treat as child of box
*/
2016-04-24 01:32:21 +03:00
static void
layout_update_descendant_bbox ( struct box * box ,
struct box * child ,
int off_x ,
int off_y )
2011-02-22 14:38:19 +03:00
{
2011-02-22 18:12:18 +03:00
int child_desc_x0 , child_desc_y0 , child_desc_x1 , child_desc_y1 ;
2011-02-22 14:38:19 +03:00
/* get coordinates of child relative to box */
int child_x = child - > x - off_x ;
int child_y = child - > y - off_y ;
2011-05-10 15:11:54 +04:00
bool html_object = ( child - > object & &
content_get_type ( child - > object ) = = CONTENT_HTML ) ;
2014-06-01 21:36:22 +04:00
enum css_overflow_e overflow_x = CSS_OVERFLOW_VISIBLE ;
enum css_overflow_e overflow_y = CSS_OVERFLOW_VISIBLE ;
if ( child - > style ! = NULL ) {
overflow_x = css_computed_overflow_x ( child - > style ) ;
overflow_y = css_computed_overflow_y ( child - > style ) ;
}
2015-11-01 17:05:27 +03:00
/* Get child's border edge */
2015-10-31 22:08:48 +03:00
layout_get_box_bbox ( child , & child_desc_x0 , & child_desc_y0 ,
& child_desc_x1 , & child_desc_y1 ) ;
if ( overflow_x = = CSS_OVERFLOW_VISIBLE & &
html_object = = false ) {
2014-06-01 21:36:22 +04:00
/* get child's descendant bbox relative to box */
2015-10-31 22:08:48 +03:00
child_desc_x0 = child - > descendant_x0 ;
child_desc_x1 = child - > descendant_x1 ;
2015-11-01 17:05:27 +03:00
}
if ( overflow_y = = CSS_OVERFLOW_VISIBLE & &
2015-10-31 22:08:48 +03:00
html_object = = false ) {
2015-11-01 17:05:27 +03:00
/* get child's descendant bbox relative to box */
2015-10-31 22:08:48 +03:00
child_desc_y0 = child - > descendant_y0 ;
child_desc_y1 = child - > descendant_y1 ;
2011-02-22 18:12:18 +03:00
}
2011-02-22 14:38:19 +03:00
2015-10-31 22:08:48 +03:00
child_desc_x0 + = child_x ;
child_desc_y0 + = child_y ;
child_desc_x1 + = child_x ;
child_desc_y1 + = child_y ;
2011-02-22 14:38:19 +03:00
/* increase box's descendant bbox to contain descendants */
if ( child_desc_x0 < box - > descendant_x0 )
box - > descendant_x0 = child_desc_x0 ;
if ( child_desc_y0 < box - > descendant_y0 )
box - > descendant_y0 = child_desc_y0 ;
if ( box - > descendant_x1 < child_desc_x1 )
box - > descendant_x1 = child_desc_x1 ;
if ( box - > descendant_y1 < child_desc_y1 )
box - > descendant_y1 = child_desc_y1 ;
}
2016-04-24 01:32:21 +03:00
/* exported function documented in render/layout.h */
2004-08-01 17:08:19 +04:00
void layout_calculate_descendant_bboxes ( struct box * box )
{
struct box * child ;
2015-11-12 01:22:19 +03:00
assert ( box - > width ! = UNKNOWN_WIDTH ) ;
assert ( box - > height ! = AUTO ) ;
2011-03-02 00:48:38 +03:00
/* assert((box->width >= 0) && (box->height >= 0)); */
2005-04-02 15:13:27 +04:00
2011-02-22 17:57:04 +03:00
/* Initialise box's descendant box to border edge box */
layout_get_box_bbox ( box , & box - > descendant_x0 , & box - > descendant_y0 ,
& box - > descendant_x1 , & box - > descendant_y1 ) ;
2004-08-01 17:08:19 +04:00
2011-02-22 17:57:04 +03:00
/* Extend it to contain HTML contents if box is replaced */
2010-08-31 02:30:43 +04:00
if ( box - > object & & content_get_type ( box - > object ) = = CONTENT_HTML ) {
if ( box - > descendant_x1 < content_get_width ( box - > object ) )
box - > descendant_x1 = content_get_width ( box - > object ) ;
if ( box - > descendant_y1 < content_get_height ( box - > object ) )
box - > descendant_y1 = content_get_height ( box - > object ) ;
}
2011-06-24 13:30:33 +04:00
if ( box - > iframe ! = NULL ) {
int x , y ;
box_coords ( box , & x , & y ) ;
browser_window_set_position ( box - > iframe , x , y ) ;
browser_window_set_dimensions ( box - > iframe ,
box - > width , box - > height ) ;
browser_window_reformat ( box - > iframe , true ,
box - > width , box - > height ) ;
}
2005-08-08 23:19:20 +04:00
if ( box - > type = = BOX_INLINE | | box - > type = = BOX_TEXT )
return ;
if ( box - > type = = BOX_INLINE_END ) {
box = box - > inline_end ;
2008-12-21 18:51:23 +03:00
for ( child = box - > next ; child ;
2005-08-08 23:19:20 +04:00
child = child - > next ) {
if ( child - > type = = BOX_FLOAT_LEFT | |
child - > type = = BOX_FLOAT_RIGHT )
continue ;
2011-02-22 14:38:19 +03:00
layout_update_descendant_bbox ( box , child ,
box - > x , box - > y ) ;
2008-12-21 18:51:23 +03:00
if ( child = = box - > inline_end )
break ;
2005-08-08 23:19:20 +04:00
}
return ;
}
2011-08-23 14:42:03 +04:00
if ( box - > flags & REPLACE_DIM )
/* Box's children aren't displayed if the box is replaced */
return ;
2004-08-01 17:08:19 +04:00
for ( child = box - > children ; child ; child = child - > next ) {
if ( child - > type = = BOX_FLOAT_LEFT | |
child - > type = = BOX_FLOAT_RIGHT )
continue ;
layout_calculate_descendant_bboxes ( child ) ;
2014-06-01 21:36:22 +04:00
if ( box - > style & & css_computed_overflow_x ( box - > style ) = =
CSS_OVERFLOW_HIDDEN & &
css_computed_overflow_y ( box - > style ) = =
2009-07-24 03:05:34 +04:00
CSS_OVERFLOW_HIDDEN )
2005-08-08 01:28:48 +04:00
continue ;
2011-02-22 14:38:19 +03:00
layout_update_descendant_bbox ( box , child , 0 , 0 ) ;
2004-08-01 17:08:19 +04:00
}
for ( child = box - > float_children ; child ; child = child - > next_float ) {
2006-06-26 08:52:34 +04:00
assert ( child - > type = = BOX_FLOAT_LEFT | |
child - > type = = BOX_FLOAT_RIGHT ) ;
layout_calculate_descendant_bboxes ( child ) ;
2011-02-22 14:38:19 +03:00
layout_update_descendant_bbox ( box , child , 0 , 0 ) ;
2006-06-26 08:52:34 +04:00
}
2006-11-05 15:58:24 +03:00
if ( box - > list_marker ) {
child = box - > list_marker ;
layout_calculate_descendant_bboxes ( child ) ;
2011-02-22 14:38:19 +03:00
layout_update_descendant_bbox ( box , child , 0 , 0 ) ;
2006-11-05 15:58:24 +03:00
}
2004-08-01 17:08:19 +04:00
}