From b9be4b3dd020f2fc4424367e773ec3c63406a225 Mon Sep 17 00:00:00 2001 From: "nisheeth%netscape.com" Date: Tue, 13 Oct 1998 04:48:49 +0000 Subject: [PATCH] Changes to make Layer/Ilayer reflow work. This should fix sites like altavista and slashdot.org. git-svn-id: svn://10.0.0.236/trunk@12665 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/include/lo_ele.h | 6 +- mozilla/lib/layout/layblock.c | 372 +++++++++++++++++++++--- mozilla/lib/layout/layfree.c | 15 + mozilla/lib/layout/laylayer.c | 2 +- mozilla/lib/layout/laylayer.h | 2 +- mozilla/lib/layout/layout.c | 528 ++++++---------------------------- mozilla/lib/layout/layout.h | 13 +- mozilla/lib/layout/layrelay.c | 133 +++++++-- mozilla/lib/layout/layutil.c | 24 -- 9 files changed, 565 insertions(+), 530 deletions(-) diff --git a/mozilla/include/lo_ele.h b/mozilla/include/lo_ele.h index 0083719788c..0bb21b63221 100644 --- a/mozilla/include/lo_ele.h +++ b/mozilla/include/lo_ele.h @@ -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; diff --git a/mozilla/lib/layout/layblock.c b/mozilla/lib/layout/layblock.c index 40d38fc24f6..37328a1674f 100644 --- a/mozilla/lib/layout/layblock.c +++ b/mozilla/lib/layout/layblock.c @@ -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 tag by appending a LO_LAYER element to the line list. */ - if (!lo_AppendLayerElement(context, state, TRUE)) - return; - } + /* Mark the 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); + +} \ No newline at end of file diff --git a/mozilla/lib/layout/layfree.c b/mozilla/lib/layout/layfree.c index 6b2cdbd6e49..35c2c1e4e3d 100644 --- a/mozilla/lib/layout/layfree.c +++ b/mozilla/lib/layout/layfree.c @@ -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; } } diff --git a/mozilla/lib/layout/laylayer.c b/mozilla/lib/layout/laylayer.c index a69bc1f0f4b..80e52691068 100644 --- a/mozilla/lib/layout/laylayer.c +++ b/mozilla/lib/layout/laylayer.c @@ -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 diff --git a/mozilla/lib/layout/laylayer.h b/mozilla/lib/layout/laylayer.h index 367f29decff..5529b296d2a 100644 --- a/mozilla/lib/layout/laylayer.h +++ b/mozilla/lib/layout/laylayer.h @@ -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 { diff --git a/mozilla/lib/layout/layout.c b/mozilla/lib/layout/layout.c index 490067e6653..64335f3a40d 100644 --- a/mozilla/lib/layout/layout.c +++ b/mozilla/lib/layout/layout.c @@ -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 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, " \n"); + return; + } + eptr = ELEMENT_PRIV(node)->ele_start; + if (!eptr) { + fprintf(stderr, " (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 ); /* diff --git a/mozilla/lib/layout/layout.h b/mozilla/lib/layout/layout.h index 75dbf19de2c..d695b3d52a7 100644 --- a/mozilla/lib/layout/layout.h +++ b/mozilla/lib/layout/layout.h @@ -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 */ diff --git a/mozilla/lib/layout/layrelay.c b/mozilla/lib/layout/layrelay.c index 0482d276559..239e94296a1 100644 --- a/mozilla/lib/layout/layrelay.c +++ b/mozilla/lib/layout/layrelay.c @@ -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, diff --git a/mozilla/lib/layout/layutil.c b/mozilla/lib/layout/layutil.c index caf50f6bab9..dd84d2c1085 100644 --- a/mozilla/lib/layout/layutil.c +++ b/mozilla/lib/layout/layutil.c @@ -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) {