Changes to make Layer/Ilayer reflow work. This should fix sites like

altavista and slashdot.org.
This commit is contained in:
nisheeth%netscape.com 1998-10-13 04:48:49 +00:00
parent a867742b43
commit ce478388e4
9 changed files with 565 additions and 530 deletions

View File

@ -247,6 +247,8 @@ typedef struct LO_BlockInitializeStruct_struct {
int32 width;
XP_Bool has_height;
int32 height;
uint8 percent_width;
uint8 percent_height;
char *name;
char *id;
char *above;
@ -1258,8 +1260,8 @@ typedef struct LO_BlockQuote_struct {
typedef struct LO_Layer_struct {
LO_Any lo_any;
Bool is_end;
Bool is_end;
void /* lo_LayerDocState */ *layerDoc;
LO_BlockInitializeStruct *initParams;
} LO_LayerStruct;

View File

@ -70,7 +70,17 @@ struct lo_Block {
char *source_url;
};
static int lo_AppendLayerElement(MWContext *context, lo_DocState *state, int32 is_end);
static int lo_AppendLayerElement(MWContext *context, lo_DocState *state,
LO_BlockInitializeStruct *param,
lo_LayerDocState *layerDoc, Bool is_end);
static PRBool
lo_SetupDocStateForLayer(lo_DocState *state,
lo_LayerDocState *layer_state,
int32 width,
int32 height,
PRBool is_inflow,
PRBool reflow);
#ifdef XP_MAC
PRIVATE
@ -614,9 +624,7 @@ lo_BeginLayer(MWContext *context,
LO_BlockInitializeStruct *param,
XP_Bool is_inflow);
#ifdef XP_MAC
PRIVATE
#endif
void
lo_FreeBlockInitializeStruct(LO_BlockInitializeStruct *param)
{
@ -740,6 +748,13 @@ lo_BeginLayerTag(MWContext *context, lo_DocState *state, PA_Tag *tag)
val = (char*)lo_FetchParamValue(context, tag, PARAM_WIDTH);
if(val)
{
Bool is_percent;
int32 ival;
ival = lo_ValueOrPercent(val, &is_percent);
if (is_percent)
param->percent_width = (uint8) ival;
param->has_width = TRUE;
param->width = lo_parse_horizontal_param(val, state, context);
XP_FREE(val);
@ -752,6 +767,13 @@ lo_BeginLayerTag(MWContext *context, lo_DocState *state, PA_Tag *tag)
val = (char*)lo_FetchParamValue(context, tag, PARAM_HEIGHT);
if(val)
{
Bool is_percent;
int32 ival;
ival = lo_ValueOrPercent(val, &is_percent);
if (is_percent)
param->percent_height = (uint8) ival;
param->has_height = TRUE;
param->height = lo_parse_vertical_param(val, state, context);
XP_FREE(val);
@ -818,11 +840,14 @@ lo_BeginLayerTag(MWContext *context, lo_DocState *state, PA_Tag *tag)
param->tag = tag;
param->ss_tag = NULL;
if (lo_BeginLayer(context, state, param, tag->type == P_ILAYER))
lo_FreeBlockInitializeStruct(param);
lo_BeginLayer(context, state, param, tag->type == P_ILAYER);
/* lo_FreeBlockInitializeStruct(param); */
}
static int lo_AppendLayerElement(MWContext *context, lo_DocState *state, int32 is_end)
static int lo_AppendLayerElement(MWContext *context, lo_DocState *state,
LO_BlockInitializeStruct *param,
lo_LayerDocState *layerDoc, Bool is_end)
{
LO_LayerStruct *layer;
layer = (LO_LayerStruct*)lo_NewElement(context, state, LO_LAYER, NULL, 0);
@ -842,7 +867,8 @@ static int lo_AppendLayerElement(MWContext *context, lo_DocState *state, int32 i
layer->lo_any.ele_id = NEXT_ELEMENT;
layer->is_end = is_end;
layer->initParams = NULL; /* Not keeping params for now. Just trying to fix ILAYER crash. */
layer->initParams = param;
layer->layerDoc = layerDoc;
lo_AppendToLineList(context, state, (LO_Element*)layer, 0);
@ -1218,6 +1244,8 @@ lo_SetStyleSheetLayerProperties(MWContext *context,
ss_num = STYLESTRUCT_GetNumber(style_struct, HEIGHT_STYLE);
if(ss_num)
{
if(!XP_STRCMP(ss_num->units, "%"))
param->percent_height = (uint8) ss_num->value;
LO_AdjustSSUnits(ss_num, HEIGHT_STYLE, context, state);
param->height = FEUNITS_Y((int32)ss_num->value, context);
param->has_height = TRUE;
@ -1225,9 +1253,19 @@ lo_SetStyleSheetLayerProperties(MWContext *context,
}
/* don't set width. normal style sheets will handle it */
/* NRA: I think we do need to set the width. But, need to check with Scott. */
ss_num = STYLESTRUCT_GetNumber(style_struct, WIDTH_STYLE);
if(ss_num)
{
if(!XP_STRCMP(ss_num->units, "%"))
param->percent_width = (uint8) ss_num->value;
LO_AdjustSSUnits(ss_num, WIDTH_STYLE, context, state);
param->width = FEUNITS_X((int32)ss_num->value, context);
param->has_width = TRUE;
STYLESTRUCT_FreeSSNumber(style_struct, ss_num);
}
prop = STYLESTRUCT_GetString(style_struct, CLIP_STYLE);
if(prop) {
param->clip = lo_ParseStyleCoords(context, state, style_struct, prop);
param->clip_expansion_policy = LO_AUTO_EXPAND_NONE;
@ -1281,8 +1319,7 @@ lo_SetStyleSheetLayerProperties(MWContext *context,
param->tag = NULL;
param->ss_tag = tag;
if (lo_BeginLayer(context, state, param, is_inflow))
lo_FreeBlockInitializeStruct(param);
lo_BeginLayer(context, state, param, is_inflow);
}
#endif /* DOM */
@ -1315,7 +1352,7 @@ lo_SaveDocState(lo_Block *block, lo_DocState *state)
}
static void
lo_RestoreDocState(lo_Block *block, lo_DocState *state)
lo_RestoreDocState(lo_Block *block, lo_DocState *state, Bool reflow)
{
lo_DocState *saved = block->saved_state;
lo_FontStack *font_stack;
@ -1334,7 +1371,8 @@ lo_RestoreDocState(lo_Block *block, lo_DocState *state)
}
state->top_state->body_attr = block->old_body_attr;
lo_SetBaseUrl(state->top_state, block->old_base_url, FALSE);
if (!reflow)
lo_SetBaseUrl(state->top_state, block->old_base_url, FALSE);
if (block->is_inflow) {
state->line_num = saved->line_num;
@ -1411,7 +1449,8 @@ lo_SetupDocStateForLayer(lo_DocState *state,
lo_LayerDocState *layer_state,
int32 width,
int32 height,
PRBool is_inflow)
PRBool is_inflow,
PRBool reflow)
{
lo_Block *block = layer_state->temp_block;
MWContext *context = block->context;
@ -1427,7 +1466,7 @@ lo_SetupDocStateForLayer(lo_DocState *state,
state->float_list = NULL;
state->line_list = NULL;
if (state->top_state->base_url)
if (state->top_state->base_url && !reflow)
block->old_base_url = XP_STRDUP(state->top_state->base_url);
if (is_inflow)
@ -1832,19 +1871,16 @@ lo_begin_layer_internal(MWContext *context,
inherit_visibility = (PRBool)!XP_STRCASECMP(param->visibility, "inherit");
}
if (is_inflow)
{
/* Add a new LO_LAYER dummy layout element to the line list. Relayout will step through
the line list and reflow the layer when the LO_LAYER element is encountered. */
if (!lo_AppendLayerElement(context, state, FALSE))
return;
}
/* Add a new LO_LAYER dummy layout element to the line list. Relayout will step through
the line list and reflow the layer when the LO_LAYER element is encountered. */
if (!lo_AppendLayerElement(context, state, param, layer_state, FALSE))
return;
/* Reset document layout state, saving old state to be restored
after we lay out this layer. */
if (!lo_SetupDocStateForLayer(state, layer_state,
block_wrap_width, layer_state->height,
(PRBool)is_inflow)) {
(PRBool)is_inflow, PR_FALSE)) {
state->top_state->out_of_memory = TRUE;
lo_DeleteLayerState(context, state, layer_state);
return;
@ -2128,6 +2164,12 @@ lo_BeginLayer(MWContext *context,
if (!context->compositor || !param)
return TRUE;
lo_begin_layer_internal(context, state, param, is_inflow);
return TRUE;
/* We no longer recreate layers on resizes, so the following code that rehooks up
layout's layer data structures with the JS layer objects can go away. */
#if 0
if (state->top_state->resize_reload && !state->in_relayout &&
!lo_IsAnyCurrentAncestorDynamic(state) && LM_CanDoJS(context)) {
lo_RestoreLayerClosure *closure;
@ -2177,6 +2219,7 @@ lo_BeginLayer(MWContext *context,
lo_begin_layer_internal(context, state, param, is_inflow);
return TRUE;
}
#endif
}
void
@ -2486,14 +2529,11 @@ lo_EndLayer(MWContext *context,
}
/* Restore document layout state, if necessary */
lo_RestoreDocState(block, state);
lo_RestoreDocState(block, state, FALSE);
if (block->is_inflow)
{
/* Mark the </LAYER> tag by appending a LO_LAYER element to the line list. */
if (!lo_AppendLayerElement(context, state, TRUE))
return;
}
/* Mark the </(I)LAYER> tag by appending a LO_LAYER element to the line list. */
if (!lo_AppendLayerElement(context, state, NULL, NULL, TRUE))
return;
if (cell != NULL && !block->is_inflow)
{
@ -2558,8 +2598,6 @@ lo_EndLayer(MWContext *context,
ET_SendLoadEvent(context, EVENT_LOAD, NULL, NULL, layer_state->id,
state->top_state->resize_reload);
lo_DeleteBlock(block);
layer_state->temp_block = NULL;
}
void
@ -2766,7 +2804,7 @@ lo_init_block(MWContext *context, lo_DocState *state,
layer_state->temp_block = block;
if (!lo_SetupDocStateForLayer(state, layer_state,
width, layer_state->height, PR_FALSE)) {
width, layer_state->height, PR_FALSE, PR_FALSE)) {
lo_DeleteBlock(block);
layer_state->temp_block = NULL;
return NULL;
@ -3039,3 +3077,271 @@ LO_CreateNewLayer(MWContext *context, int32 wrap_width, int32 parent_layer_id)
return layer_id;
}
/* Called when you see a start LO_LAYER element. Reflow version of lo_begin_layer_internal */
void
lo_BeginLayerReflow(MWContext *context, lo_DocState *state,
LO_BlockInitializeStruct *param,
lo_LayerDocState *layer_state)
{
lo_Block *block;
lo_LayerDocState *parent_layer_state;
int32 block_wrap_width, x_parent_offset, y_parent_offset;
CL_Layer *layer, *parent_layer;
int32 block_x, block_y;
Bool is_inflow;
XP_Rect bbox;
LO_CellStruct *cell;
lo_GroupLayerClosure *closure;
lo_HTMLBlockClosure *content_closure;
if (!context->compositor || !param || !layer_state)
return;
block = layer_state->temp_block;
is_inflow = block->is_inflow;
cell = layer_state->cell;
layer = layer_state->layer;
/*
* If this is a nested inflow layer, then flush the line list into our parent
* (without introducing a line break). This ensures that whatever line changes
* (specifically shifting of cell origin) that occur while laying out this ilayer
* are reflected in our parent.
*/
if (lo_InsideInflowLayer(state) && is_inflow)
{
lo_rl_AddBreakAndFlushLine(context, state, LO_LINEFEED_BREAK_SOFT, LO_CLEAR_NONE, FALSE);
}
/* In-flow layers use coordinates that are relative to their
"natural", in-flow position. */
if (block->is_inflow) {
block->x_offset = state->x;
block->y_offset = state->y;
} else {
block->x_offset = 0;
block->y_offset = 0;
}
x_parent_offset = y_parent_offset = 0;
parent_layer_state = lo_CurrentLayerState(state);
parent_layer = parent_layer_state->layer;
if (parent_layer) /* Paranoia */
lo_GetLayerXYShift(parent_layer, &x_parent_offset, &y_parent_offset);
/*
* Get the X position of the block
*/
if (param->has_left)
{
block_x = param->left;
} else {
if (block->is_inflow) {
block_x = 0;
} else {
block_x = state->x - x_parent_offset;
}
}
/*
* Get the Y position of the block
*/
if (param->has_top)
{
block_y = param->top;
} else {
if (block->is_inflow) {
block_y = 0;
} else {
block_y = state->y - y_parent_offset;
}
}
XP_BZERO(&bbox, sizeof(bbox));
/*
* Get the width parameter, in absolute or percentage.
* If percentage, make it absolute.
*/
if (param->has_width)
block_wrap_width = param->width;
else if (param->has_left)
block_wrap_width = state->right_margin - param->left;
else
block_wrap_width = state->right_margin - state->x;
/*
* Parse the comma separated coordinate list into an
* array of integers.
*/
if (param->clip)
{
bbox = *param->clip;
/* Don't allow the layer's clip to expand */
block->clip_expansion_policy = param->clip_expansion_policy;
} else {
/* Allow the clip to expand to include the layer's contents. */
block->clip_expansion_policy = LO_AUTO_EXPAND_CLIP;
if (param->has_width)
bbox.right = block_wrap_width;
}
if (param->has_height) {
layer_state->height = param->height;
/* If no CLIP set, set initial bottom edge of layer clip to be
the same as HEIGHT. */
if (block->clip_expansion_policy & LO_AUTO_EXPAND_CLIP_BOTTOM)
bbox.bottom = param->height;
}
/* Treat any value of OVERFLOW, except "hidden" to be the same as
"visible". For compatibility with the older CSS positioning
spec, we also treat "none" specially. Can't set OVERFLOW
unless HEIGHT is provided. */
if (param->has_height &&
param->overflow &&
XP_STRCASECMP(param->overflow, "none") &&
XP_STRCASECMP(param->overflow, "visible")) {
/* Constrain all drawing to {0, 0, width, height} box */
XP_Rect *viewRect = &layer_state->viewRect;
viewRect->left = 0;
viewRect->top = 0;
viewRect->right = block_wrap_width;
viewRect->bottom = param->height;
}
/* Reset document layout state, saving old state to be restored
after we lay out this layer. */
if (!lo_SetupDocStateForLayer(state, layer_state,
block_wrap_width, layer_state->height,
(PRBool)is_inflow, PR_TRUE)) {
state->top_state->out_of_memory = TRUE;
lo_DeleteLayerState(context, state, layer_state);
return;
}
/* Reset cell struct variables that depend on the doc state */
cell->ele_id = NEXT_ELEMENT;
cell->x = state->x;
cell->y = state->y;
cell->width = 0;
cell->height = 0;
cell->x_offset = 0;
cell->y_offset = 0;
closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer);
if (closure)
{
/* Reset group layer closure's properties */
XP_ASSERT(closure->type == LO_GROUP_LAYER);
closure->x_offset = block->x_offset;
closure->y_offset = block->y_offset;
closure->wrap_width = block_wrap_width;
}
/* Move layer into position. Set clip dimensions and initial visibility. */
LO_MoveLayer(layer, block_x, block_y);
LO_SetLayerBbox(layer, &bbox);
lo_expand_parent_bbox(layer);
CL_ChangeLayerFlag(layer, CL_HIDDEN, hidden);
/* Resize the layer */
CL_ResizeLayer(layer, block_wrap_width, layer_state->height);
/* Push this layer on the layer stack */
lo_PushLayerState(state->top_state, layer_state);
state->layer_nest_level++;
}
/* Called when the end LO_LAYER element is seen by the reflow code */
void
lo_EndLayerReflow(MWContext *context, lo_DocState *state)
{
lo_LayerDocState *layer_state = lo_CurrentLayerState(state);
lo_Block *block = layer_state->temp_block;
LO_CellStruct *cell = NULL;
int32 right_edge;
/* During destruction, the compositor can disappear out from underneath us. */
if (!context->compositor || !block)
return;
if (! block->is_inflow) {
lo_EndLayoutDuringReflow(context, state);
}
else {
lo_rl_FlushLineList(context, state, LO_LINEFEED_BREAK_SOFT, LO_CLEAR_NONE, FALSE);
}
cell = lo_compose_block(context, state, block);
/* For an in-flow layer, expand the enclosing cell's size on the
right and bottom edges to contain any descendant
layers. However, we only do this for ILAYER tags, not for
layers created as a result of 'position:relative' applied to
style-sheet elements. */
if (block->is_inflow && !block->uses_ss_positioning) {
int32 grow_width, grow_height;
XP_Rect bbox;
CL_GetLayerBbox(block->layer, &bbox);
grow_width = (bbox.right - cell->width);
grow_height = (bbox.bottom - cell->height);
/* Position of right-edge of cell containing layer */
right_edge = state->x;
/* If the inflow layer is caused to grow vertically, force a
line break. */
if (grow_height > 0) {
lo_SetLineBreakState ( context, state, FALSE, LO_LINEFEED_BREAK_HARD, 1, TRUE);
cell->height = bbox.bottom;
state->y += grow_height;
}
/* Compute new position of cell's right edge. */
if (grow_width > 0) {
right_edge += grow_width;
cell->width = bbox.right;
}
/* Set minimum and maximum possible layout widths so that any
enclosing table cells will be dimensioned properly. */
if (right_edge + state->win_right > state->max_width)
state->max_width = right_edge + state->win_right;
if (right_edge + state->win_right > state->min_width)
state->min_width = right_edge + state->win_right;
}
/* Restore document layout state, if necessary */
lo_RestoreDocState(block, state, TRUE);
if (cell != NULL && !block->is_inflow)
{
int32 max_y;
cell->next = NULL;
cell->ele_id = NEXT_ELEMENT;
lo_RenumberCell(state, cell);
/* XXX - Do we really want to expand the document size to
include the layer ? */
max_y = cell->y + cell->y_offset + cell->height;
if (max_y > state->max_height)
{
state->max_height = max_y;
}
}
state->layer_nest_level--;
lo_PopLayerState(state);
ET_SendLoadEvent(context, EVENT_LOAD, NULL, NULL, layer_state->id,
TRUE);
}

View File

@ -26,6 +26,7 @@
#endif
#include "layers.h"
#include "pa_parse.h"
#include "laylayer.h"
#define IL_CLIENT /* XXXM12N Defined by Image Library clients */
#include "libimg.h" /* Image Library public API. */
@ -764,6 +765,20 @@ lo_ScrapeElement(MWContext *context, LO_Element *element, Bool freeTableOrCellSt
element->lo_textBlock.break_table = NULL;
}
break;
case LO_LAYER:
if ( element->lo_layer.initParams )
{
lo_FreeBlockInitializeStruct( element->lo_layer.initParams );
element->lo_layer.initParams = NULL;
}
if ( element->lo_layer.layerDoc )
{
/* We are going to let the layer cleanup function,
lo_DeleteLayerState() clean the lo_Block structure
on the layer doc state (lo_LayerDocState) */
element->lo_layer.layerDoc = NULL;
}
break;
}
}

View File

@ -2837,7 +2837,7 @@ lo_ActivateImageLayer(MWContext *context, LO_ImageStruct *image)
/* Move layer to new position and unhide it. */
CL_MoveLayer(layer, x, y);
CL_SetLayerHidden(layer, PR_FALSE);
image->ele_attrmask |= LO_ELE_DRAWN;
/* image->ele_attrmask |= LO_ELE_DRAWN; */
/* In order to increase the perceived speed of image loading,
non-backdrop, non-icon images have the delayed icon, ALT text

View File

@ -51,7 +51,7 @@ struct lo_LayerDocState
CL_Layer *layer;
void *mocha_object;
lo_DocLists *doc_lists; /* Layout element lists, e.g. embeds, forms */
lo_Block *temp_block; /* Data used only during HTML layer layout */
lo_Block *temp_block; /* Data used during HTML layer layout and reflow */
};
struct lo_LayerStack {

View File

@ -1092,165 +1092,9 @@ lo_FlushLineList(MWContext *context, lo_DocState *state, uint32 break_type, uint
{
LO_LinefeedStruct *linefeed;
/*
LO_Element **line_array;
*/
/* int32 justification_remainder=0;*/
/*
#ifdef XP_WIN16
int32 a_size;
int32 a_indx;
int32 a_line;
XP_Block *larray_array;
#endif
*/
/* XP_WIN16 */
lo_UpdateStateWhileFlushingLine( context, state );
/*
if (state->top_state->nothing_displayed != FALSE) {
*/
/*
* If we are displaying elements we are
* no longer in the HEAD section of the HTML
* we are in the BODY section.
*/
/*
state->top_state->in_head = FALSE;
state->top_state->in_body = TRUE;
lo_use_default_doc_background(context, state);
state->top_state->nothing_displayed = FALSE;
}
*/
/*
* There is a break at the end of this line.
* this may change min_width.
*/
/*
{
int32 new_break_holder;
int32 min_width;
int32 indent;
new_break_holder = state->x;
min_width = new_break_holder - state->break_holder;
indent = state->list_stack->old_left_margin - state->win_left;
min_width += indent;
if (min_width > state->min_width)
{
state->min_width = min_width;
}
*/
/* If we are not within <NOBR> content, allow break_holder
* to be set to the new position where a line break can occur.
* This fixes BUG #70782
*/
/*
if (state->breakable != FALSE) {
state->break_holder = new_break_holder;
}
}
*/
/*
* If in a division centering or right aligning this line
*/
/*
if ((state->align_stack != NULL)&&(state->delay_align == FALSE))
{
int32 push_right;
LO_Element *tptr;
if (state->align_stack->alignment == LO_ALIGN_CENTER)
{
push_right = (state->right_margin - state->x) / 2;
}
else if (state->align_stack->alignment == LO_ALIGN_RIGHT)
{
push_right = state->right_margin - state->x;
}
else if(state->align_stack->alignment == LO_ALIGN_JUSTIFY)
{
push_right = lo_calc_push_right_for_justify(state, &justification_remainder);
}
else
{
push_right = 0;
}
if ((push_right > 0 || justification_remainder)
&&(state->line_list != NULL))
{
int32 count = 0;
int32 move_delta;
tptr = state->line_list;
if(state->align_stack->alignment == LO_ALIGN_JUSTIFY)
move_delta = 0;
else
move_delta = push_right;
while (tptr != NULL)
{
*/
/*
* We don't shift over inflow layers, since their contents
* have already been shifted over.
*/
/*
* We also don't shift bullets of type BULLET_MQUOTE.
*/
/*
if (((tptr->type != LO_CELL)||
(!tptr->lo_cell.cell_inflow_layer))&&
((tptr->type != LO_BULLET)||
((tptr->type == LO_BULLET)&&
(tptr->lo_bullet.bullet_type != BULLET_MQUOTE))))
{
tptr->lo_any.x += move_delta;
}
*/
/* justification push_rights are additive */
/*
if(state->align_stack->alignment == LO_ALIGN_JUSTIFY)
{
move_delta += push_right;
*/
/* if there is a justification remainder, add a pixel
* to the first n word breaks
*/
/*
if(count < justification_remainder)
move_delta++;
}
*/
/*
* Note that if this is an inflow layer, we don't want
* to shift it since the alignment has already propogated
* to its contents.
*/
/*
if ((tptr->type == LO_CELL) &&
!tptr->lo_cell.cell_inflow_layer)
{
lo_ShiftCell((LO_CellStruct *)tptr, move_delta, 0);
}
tptr = tptr->lo_any.next;
count++;
}
if(state->align_stack->alignment == LO_ALIGN_JUSTIFY)
state->x = state->right_margin;
else
state->x += push_right;
}
}
*/
#if 0
/* apply line-height stack mods (if exists) */
if(state->line_height_stack && state->end_last_line)
@ -1318,122 +1162,6 @@ lo_FlushLineList(MWContext *context, lo_DocState *state, uint32 break_type, uint
if (linefeed != NULL)
{
lo_AppendLineFeed( context, state, linefeed, breaking, TRUE );
/*
LO_Element *tptr;
if (breaking != FALSE)
{
linefeed->ele_attrmask |= LO_ELE_BREAKING;
}
*/
/*
* Horrible bitflag overuse!!! For multicolumn text
* we need to know if a line of text can be used for
* a column break, or if it cannot because it is wrapped
* around some object in the margin. For lines that can be
* used for column breaks, we will set the BREAKABLE
* flag in their element mask.
*/
/*
if ((state->left_margin_stack == NULL)&&
(state->right_margin_stack == NULL))
{
linefeed->ele_attrmask |= LO_ELE_BREAKABLE;
}
if ((state->align_stack != NULL)&&
(state->delay_align != FALSE)&&
(state->align_stack->alignment != LO_ALIGN_LEFT))
{
if (state->align_stack->alignment == LO_ALIGN_CENTER)
{
linefeed->ele_attrmask |= LO_ELE_DELAY_CENTER;
}
else if (state->align_stack->alignment == LO_ALIGN_RIGHT)
{
linefeed->ele_attrmask |= LO_ELE_DELAY_RIGHT;
}
}
tptr = state->line_list;
if (tptr == NULL)
{
state->line_list = (LO_Element *)linefeed;
linefeed->prev = NULL;
}
else
{
while (tptr != NULL)
{
*/
/*
* If the display is blocked for an element
* we havn't reached yet, check to see if
* it is in this line, and if so, save its
* y position.
*/
/*
if ((state->display_blocked != FALSE)&&
#ifdef EDITOR
(!state->edit_relayout_display_blocked)&&
#endif
(state->is_a_subdoc == SUBDOC_NOT)&&
(state->display_blocking_element_y == 0)&&
(state->display_blocking_element_id != -1)&&
(tptr->lo_any.ele_id >=
state->display_blocking_element_id))
{
state->display_blocking_element_y =
state->y;
*/
/*
* Special case, if the blocking element
* is on the first line, no blocking
* at all needs to happen.
*/
/*
if (state->y == state->win_top)
{
state->display_blocked = FALSE;
FE_SetDocPosition(context,
FE_VIEW, 0, state->base_y);
if (context->compositor)
{
XP_Rect rect;
rect.left = 0;
rect.top = 0;
rect.right = state->win_width;
rect.bottom = state->win_height;
CL_UpdateDocumentRect(context->compositor,
&rect, (PRBool)FALSE);
}
}
}
tptr->lo_any.line_height = state->line_height;
*/
/*
* Special for bullets of type BULLET_MQUOTE
* They should always be as tall as the line.
*/
/*
if ((tptr->type == LO_BULLET)&&
(tptr->lo_bullet.bullet_type ==
BULLET_MQUOTE))
{
tptr->lo_any.y_offset = 0;
tptr->lo_any.height =
tptr->lo_any.line_height;
}
tptr = tptr->lo_any.next;
}
linefeed->prev = tptr;
}
state->x += linefeed->width;
*/
}
else
{
@ -1448,180 +1176,7 @@ lo_FlushLineList(MWContext *context, lo_DocState *state, uint32 break_type, uint
return;
}
/*
* We are in a layer within this (sub)doc, stuff the line there instead.
*/
if (state->layer_nest_level > 0)
{
lo_AddLineListToLayer(context, state, (LO_Element *)linefeed);
state->line_list = NULL;
state->old_break = NULL;
state->old_break_block = NULL;
state->old_break_pos = -1;
state->old_break_width = 0;
state->baseline = 0;
return;
}
/*
* If necessary, grow the line array to hold more lines.
*/
/*
#ifdef XP_WIN16
a_size = SIZE_LIMIT / sizeof(LO_Element *);
a_indx = (state->line_num - 1) / a_size;
a_line = state->line_num - (a_indx * a_size);
XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array);
state->line_array = larray_array[a_indx];
if (a_line == a_size)
{
state->line_array = XP_ALLOC_BLOCK(LINE_INC *
sizeof(LO_Element *));
if (state->line_array == NULL)
{
XP_UNLOCK_BLOCK(state->larray_array);
state->top_state->out_of_memory = TRUE;
return;
}
XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array);
line_array[0] = NULL;
XP_UNLOCK_BLOCK(state->line_array);
state->line_array_size = LINE_INC;
state->larray_array_size++;
XP_UNLOCK_BLOCK(state->larray_array);
state->larray_array = XP_REALLOC_BLOCK(
state->larray_array, (state->larray_array_size
* sizeof(XP_Block)));
if (state->larray_array == NULL)
{
state->top_state->out_of_memory = TRUE;
return;
}
XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array);
larray_array[state->larray_array_size - 1] = state->line_array;
state->line_array = larray_array[a_indx];
}
else if (a_line >= state->line_array_size)
{
state->line_array_size += LINE_INC;
if (state->line_array_size > a_size)
{
state->line_array_size = (intn)a_size;
}
state->line_array = XP_REALLOC_BLOCK(state->line_array,
(state->line_array_size * sizeof(LO_Element *)));
if (state->line_array == NULL)
{
XP_UNLOCK_BLOCK(state->larray_array);
state->top_state->out_of_memory = TRUE;
return;
}
larray_array[a_indx] = state->line_array;
}
*/
/*
* Place this line of elements into the line array.
*/
/*
XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array);
line_array[a_line - 1] = state->line_list;
XP_UNLOCK_BLOCK(state->line_array);
XP_UNLOCK_BLOCK(state->larray_array);
#else
if (state->line_num > state->line_array_size)
{
int32 line_inc;
if (state->line_array_size > (LINE_INC * 10))
{
line_inc = state->line_array_size / 10;
}
else
{
line_inc = LINE_INC;
}
state->line_array = XP_REALLOC_BLOCK(state->line_array,
((state->line_array_size + line_inc) *
sizeof(LO_Element *)));
if (state->line_array == NULL)
{
state->top_state->out_of_memory = TRUE;
return;
}
state->line_array_size += line_inc;
}
*/
/*
* Place this line of elements into the line array.
*/
/*
XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array);
line_array[state->line_num - 1] = state->line_list;
XP_UNLOCK_BLOCK(state->line_array);
#endif */
/* XP_WIN16 */
/*
* connect the complete doubly linked list between this line
* and the last one.
*/
/*
if (state->end_last_line != NULL)
{
state->end_last_line->lo_any.next = state->line_list;
state->line_list->lo_any.prev = state->end_last_line;
}
state->end_last_line = (LO_Element *)linefeed;
state->line_list = NULL;
state->line_num++;
*/
/*
*Don't draw if we're doing layers...we'll just refresh when the
* the layer size increases.
*/
/*
#ifdef LAYERS
*/
/*
* Have the front end display this line.
*/
/* For layers, only draw if a compositor doesn't exist */
/*
if (!context->compositor)
*/
/* We need to supply a display rectangle that is guaranteed to
encompass all elements on the line. The special 0x3fffffff
value is approximately half the range of a 32-bit int, so
it leaves room for overflow if arithmetic is done on these
values. */
/*
lo_DisplayLine(context, state, (state->line_num - 2),
0, 0, 0x3fffffffL, 0x3fffffffL);
#else
lo_DisplayLine(context, state, (state->line_num - 2),
0, 0, 0x3fffffffL, 0x3fffffffL);
#endif */ /* LAYERS */
lo_UpdateStateAfterFlushingLine( context, state, linefeed, FALSE );
/*
* We are starting a new line. Clear any old break
* positions left over, clear the line_list, and increase
* the line number.
*/
/*
state->old_break = NULL;
state->old_break_block = NULL;
state->old_break_pos = -1;
state->old_break_width = 0;
state->baseline = 0;
*/
}
@ -4081,6 +3636,72 @@ static void *hooked_data_object = NULL;
static intn hooked_status = 0;
static PA_Tag *hooked_tag = NULL;
#ifdef DOM
char *element_names[] = {
"NONE",
"TEXT",
"LINEFEED",
"HRULE",
"IMAGE",
"BULLET",
"FORM_ELE",
"SUBDOC",
"TABLE",
"CELL",
"EMBED",
"EDGE",
"JAVA",
"SCRIPT",
"OBJECT",
"PARAGRAPH",
"CENTER",
"MULTICOL",
"FLOAT",
"TEXTBLOCK",
"LIST",
"DESCTITLE",
"DESCTEXT",
"BLOCKQUOTE",
"LAYER",
"HEADING",
"SPAN",
"BUILTIN",
"SPACER",
"SUPER",
"SUB"
};
static void
DumpNodeElements(DOM_Node *node)
{
#ifdef DEBUG_shaver
LO_Element *eptr;
if (node->type != NODE_TYPE_ELEMENT &&
node->type != NODE_TYPE_TEXT)
return;
fprintf(stderr, "%s %s elements:",
PA_TagString(ELEMENT_PRIV(node)->tagtype),
node->name ? node->name : "");
if (ELEMENT_PRIV(node)->tagtype == P_TABLE_ROW ||
ELEMENT_PRIV(node)->tagtype == P_TABLE_DATA) {
fprintf(stderr, " <NOT REALLY AN ELEMENT>\n");
return;
}
eptr = ELEMENT_PRIV(node)->ele_start;
if (!eptr) {
fprintf(stderr, " <none> (SHOULD REMOVE FROM TREE!)\n");
return;
}
while (eptr && eptr != ELEMENT_PRIV(node)->ele_end) {
fprintf(stderr, " %s", element_names[eptr->type]);
eptr = eptr->lo_any.next;
}
if (eptr)
fprintf(stderr, " %s", element_names[eptr->type]);
fprintf(stderr, "\n");
#endif
}
#endif
/*************************************
* Function: LO_ProcessTag
@ -8145,7 +7766,22 @@ void lo_AppendLineListToLineArray( MWContext *context, lo_DocState *state, LO_El
void lo_UpdateStateAfterFlushingLine( MWContext *context, lo_DocState *state, LO_LinefeedStruct *linefeed, Bool inRelayout )
{
/* LO_LinefeedStruct *linefeed; */
/*
* We are in a layer within this (sub)doc, stuff the line there instead.
*/
if (state->layer_nest_level > 0)
{
lo_AddLineListToLayer(context, state, (LO_Element *)linefeed);
state->line_list = NULL;
state->old_break = NULL;
state->old_break_block = NULL;
state->old_break_pos = -1;
state->old_break_width = 0;
state->baseline = 0;
return;
}
lo_AppendLineListToLineArray( context, state, (LO_Element *) linefeed );
/*

View File

@ -1202,7 +1202,6 @@ extern LO_AnchorData *lo_GetElementAnchor(LO_Element *element);
extern void lo_GetElementFGColor(LO_Element *element, LO_Color *color);
extern void lo_SetElementFGColor(LO_Element *element, LO_Color *color);
extern void lo_ShiftElementList(LO_Element *, int32, int32);
extern void lo_RenumberCell(lo_DocState *, LO_CellStruct *);
extern void lo_ShiftCell(LO_CellStruct *, int32, int32);
extern int32 lo_CleanTextWhitespace(char *, int32);
@ -1468,6 +1467,14 @@ extern void lo_SetupStateForBeginMulticol( lo_DocState *state, lo_MultiCol *mult
/* Common code for layout and relayout of spacers */
extern void lo_LayoutSpacerElement(MWContext *context, lo_DocState *state, LO_SpacerStruct *spacer, Bool relayout);
/* Reflow of layers */
extern void lo_BeginLayerReflow(MWContext *context, lo_DocState *state,
LO_BlockInitializeStruct *param,
lo_LayerDocState *layer_state);
extern void lo_EndLayerReflow(MWContext *context, lo_DocState *state);
extern void lo_FreeBlockInitializeStruct(LO_BlockInitializeStruct *param);
/*
* Adds a soft line break to the end of the line list and adds the line list to the line array.
* Resets line list to NULL. Should be used during relayout only.
@ -1486,6 +1493,10 @@ extern void lo_PrepareElementForReuse( MWContext *context, lo_DocState *state, L
extern void LO_Reflow(MWContext *context, lo_DocState * state, LO_Element *startElement,
LO_Element *endElement);
/* Reflow version of lo_FlushLineList() */
extern void lo_rl_FlushLineList( MWContext *context, lo_DocState *state,
uint32 break_type, uint32 clear_type, Bool breaking );
extern Bool lo_IsDummyLayoutElement(LO_Element *ele);
/* Useful Macros */

View File

@ -143,7 +143,8 @@ void lo_FillInBuiltinGeometry(lo_DocState *state, LO_BuiltinStruct *builtin,
Bool relayout);
void lo_UpdateStateAfterBuiltinLayout (lo_DocState *state, LO_BuiltinStruct *builtin,
int32 line_inc, int32 baseline_inc);
static void
lo_rl_SetLayerDimensions( lo_RelayoutState *relay_state, LO_BlockInitializeStruct *layerParams );
/* NRA - 10/3/97: Main Relayout Entry Point
* This function walks through the layout element list and re-lays out
@ -1530,25 +1531,104 @@ lo_rl_FitTextBlock( lo_RelayoutState *relay_state, LO_Element *lo_ele )
return next;
}
static void
lo_rl_SetLayerDimensions( lo_RelayoutState *relay_state, LO_BlockInitializeStruct *layerParams )
{
XP_ASSERT(layerParams != NULL);
if (layerParams)
{
if (layerParams->percent_width > 0)
{
int32 parent_width = lo_GetEnclosingLayerWidth(relay_state->doc_state);
layerParams->width = (parent_width * layerParams->percent_width) / 100;
}
if (layerParams->percent_height > 0)
{
int32 parent_height = lo_GetEnclosingLayerHeight(relay_state->doc_state);
layerParams->height = (parent_height * layerParams->percent_height) / 100;
}
}
}
static LO_Element *
lo_rl_FitLayer( lo_RelayoutState *relay_state, LO_Element *lo_ele )
{
LO_Element *next;
LO_LayerStruct *layerEle = (LO_LayerStruct *)lo_ele;
LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE );
XP_ASSERT(lo_ele->lo_layer.is_end == FALSE);
/* Skip all elements between the start and end LO_LAYER elements */
next = lo_ele;
do
if(layerEle && layerEle->is_end == FALSE)
{
next = lo_tv_GetNextLayoutElement( relay_state->doc_state, next, TRUE);
} while (next != NULL && next->lo_any.type != LO_LAYER);
LO_LayerStruct *endLayer = NULL;
LO_Element *lastFloat = NULL;
LO_CellStruct *cell = NULL;
if (next->lo_any.type == LO_LAYER) {
XP_ASSERT(next->lo_layer.is_end == TRUE);
next = lo_tv_GetNextLayoutElement( relay_state->doc_state, next, TRUE);
lo_AppendToLineList( relay_state->context, relay_state->doc_state, lo_ele, 0 );
lo_rl_SetLayerDimensions( relay_state, layerEle->initParams );
lo_BeginLayerReflow( relay_state->context, relay_state->doc_state, layerEle->initParams,
layerEle->layerDoc );
if (next->lo_any.type == LO_CELL)
{
/* We are reflowing an ILAYER */
cell = (LO_CellStruct *) next;
/* Set "next" to the layout element following the LO_CELL */
next = lo_tv_GetNextLayoutElement( relay_state->doc_state, next, TRUE);
/* Set the cell's next pointer to null. We've got to fool the end layer
code into thinking that this cell is the last element on the line list. */
cell->next = NULL;
}
else
{
/* We are reflowing a LAYER. So, we get the cell from the lo_LayerDocState structure */
lo_LayerDocState *layerDoc = (lo_LayerDocState *) layerEle->layerDoc;
cell = layerDoc->cell;
}
/* Assert that next is a dummy layout element marking the end of the layer */
XP_ASSERT(next->lo_any.type == LO_LAYER && next->lo_layer.is_end == TRUE);
endLayer = (LO_LayerStruct *) next;
next = cell->cell_list;
if (next)
{
/* The next layout element to be fitted is the first element on the cell list.
Once the cell list has been fitted we want to end the layer, so we append
the end layer element to the cell list. */
XP_ASSERT(cell->cell_list_end && cell->cell_list_end->lo_any.next == NULL);
cell->cell_list_end->lo_any.next = (LO_Element*) endLayer;
/* We also need to append the cell's float list to the state's float list */
lastFloat = lo_GetLastElementInList(relay_state->doc_state->float_list);
if (lastFloat)
lastFloat->lo_any.next = cell->cell_float_list;
}
else
{
/* There is nothing on the cell's line list to reflow. So, the float list should
also be null. The next element to be fitted is set to the end layer element. */
XP_ASSERT(cell->cell_float_list == NULL);
next = endLayer;
}
/* Since the elements inside the layer are going to be reflowed while state->layer_nest_level
is greater than zero, lo_FlushLineList() will append the layout elements onto the cell's
line list. So, the cell's line list and float lists need to be initialized to null. */
if (cell)
{
cell->cell_list = NULL;
cell->cell_float_list = NULL;
cell->cell_list_end = NULL;
}
}
else
{
lo_EndLayerReflow( relay_state->context, relay_state->doc_state );
lo_AppendToLineList( relay_state->context, relay_state->doc_state, lo_ele, 0 );
}
return next;
}
@ -1703,6 +1783,21 @@ void lo_rl_AppendLinefeedAndFlushLine( MWContext *context, lo_DocState *state, L
lo_UpdateFEProgressBar(context, state);
}
/* Reflow version of lo_FlushLineList() */
void lo_rl_FlushLineList( MWContext *context, lo_DocState *state,
uint32 break_type, uint32 clear_type, Bool breaking )
{
LO_LinefeedStruct *linefeed = NULL;
lo_UpdateStateWhileFlushingLine( context, state );
linefeed = lo_NewLinefeed( state, context, break_type, clear_type );
if (linefeed != NULL)
{
lo_AppendLineFeed( context, state, linefeed, breaking, FALSE );
}
lo_UpdateStateAfterFlushingLine( context, state, linefeed, TRUE );
}
/*
* Append a dummy layout element in the line list. When the relayout engine
* will see this dummy element, it will call lo_LayoutFloat{Image,JavaApp,Embed}()
@ -1738,8 +1833,6 @@ void lo_rl_ReflowCell( MWContext *context, lo_DocState *state, LO_CellStruct *ce
lo_RelayoutState *relay_state;
LO_Element *first;
LO_LockLayout();
/* Copy over cell line lists, float lists to state */
lo_rl_CopyCellToState( cell, state );
@ -1759,8 +1852,6 @@ void lo_rl_ReflowCell( MWContext *context, lo_DocState *state, LO_CellStruct *ce
/* Done with relayout. Destroy relayout state. */
lo_rl_DestroyRelayoutState( relay_state );
LO_UnlockLayout();
}
void lo_rl_ReflowDocState( MWContext *context, lo_DocState *state )
@ -1768,8 +1859,6 @@ void lo_rl_ReflowDocState( MWContext *context, lo_DocState *state )
lo_RelayoutState *relay_state;
LO_Element *first;
LO_LockLayout();
/* Create relayout state */
relay_state = lo_rl_CreateRelayoutState();
relay_state->doc_state = state;
@ -1783,14 +1872,14 @@ void lo_rl_ReflowDocState( MWContext *context, lo_DocState *state )
/* Dummy Floating elements on a new line at the end of a document were not getting put into
the line_array. This code should ensure that anything left on the line_list gets flushed
to the line_array. */
to the line_array. */
/*
if (state->line_list != NULL)
lo_AppendLineListToLineArray( context, state, lo_GetLastElementInList(state->line_list) );
*/
/* Done with relayout. Destroy relayout state. */
lo_rl_DestroyRelayoutState( relay_state );
LO_UnlockLayout();
}
void lo_PrepareElementForReuse( MWContext *context, lo_DocState *state, LO_Element * eptr,

View File

@ -229,30 +229,6 @@ lo_SetElementFGColor(LO_Element *element, LO_Color *color)
}
}
void
lo_ShiftElementList(LO_Element *e_list, int32 dx, int32 dy)
{
LO_Element *eptr;
if (e_list == NULL)
{
return;
}
eptr = e_list;
while (eptr != NULL)
{
eptr->lo_any.x += dx;
eptr->lo_any.y += dy;
if (eptr->type == LO_CELL)
{
lo_ShiftCell((LO_CellStruct *)eptr, dx, dy);
}
eptr = eptr->lo_any.next;
}
}
NET_ReloadMethod
LO_GetReloadMethod(MWContext *context)
{