Add teardown phase to the start of each layout operation that manually breaks cycles between flows, boxes, fonts, shapers, and textruns on stale layout data.

This commit is contained in:
Josh Matthews 2013-05-22 14:19:18 -04:00
parent 982dd0c0f0
commit ec4f16fa68
8 changed files with 93 additions and 0 deletions

View file

@ -177,6 +177,10 @@ pub impl FontGroup {
}
}
fn teardown(&mut self) {
self.fonts = ~[];
}
fn create_textrun(&self, text: ~str) -> TextRun {
assert!(self.fonts.len() > 0);
@ -283,6 +287,11 @@ pub impl Font {
return result;
}
fn teardown(&mut self) {
self.shaper = None;
self.azure_font = None;
}
// TODO: this should return a borrowed pointer, but I can't figure
// out why borrowck doesn't like my implementation.

View file

@ -51,6 +51,10 @@ pub impl<'self> TextRun {
return run;
}
fn teardown(&self) {
self.font.teardown();
}
fn compute_potential_breaks(text: &str, glyphs: &mut GlyphStore) {
// TODO(Issue #230): do a better job. See Gecko's LineBreaker.

View file

@ -18,6 +18,14 @@ impl LayoutAuxMethods for AbstractNode {
/// box in the COW model) and populates it with an empty style object.
fn initialize_layout_data(self) -> Option<@mut LayoutData> {
if self.has_layout_data() {
{
let layout_data = &mut self.layout_data().flow;
match *layout_data {
Some(ref flow) => flow.teardown(),
None => ()
}
}
self.layout_data().flow = None;
None
} else {
let data = @mut LayoutData::new();

View file

@ -45,6 +45,14 @@ impl BlockFlowData {
is_root: true
}
}
pub fn teardown(&mut self) {
self.common.teardown();
for self.box.each |box| {
box.teardown();
}
self.box = None;
}
}
pub trait BlockLayout {

View file

@ -59,6 +59,15 @@ pub enum RenderBox {
UnscannedTextRenderBoxClass(@mut UnscannedTextRenderBox),
}
impl RenderBox {
pub fn teardown(&self) {
match *self {
TextRenderBoxClass(box) => box.teardown(),
_ => ()
}
}
}
/// A box that represents a (replaced content) image and its accompanying borders, shadows, etc.
pub struct ImageRenderBox {
base: RenderBoxBase,
@ -88,6 +97,12 @@ pub struct TextRenderBox {
text_data: TextBoxData,
}
impl TextRenderBox {
fn teardown(&self) {
self.text_data.teardown();
}
}
/// The data for an unscanned text box.
pub struct UnscannedTextRenderBox {
base: RenderBoxBase,

View file

@ -67,6 +67,43 @@ impl Clone for FlowContext {
}
}
impl FlowContext {
pub fn teardown(&self) {
match *self {
AbsoluteFlow(data) |
FloatFlow(data) |
InlineBlockFlow(data) |
TableFlow(data) => data.teardown(),
BlockFlow(data) => data.teardown(),
InlineFlow(data) => data.teardown()
}
}
}
impl FlowData {
pub fn teardown(&mut self) {
// Under the assumption that all flows exist in a tree,
// we must restrict ourselves to finalizing flows that
// are descendents and subsequent siblings to ourselves,
// or we risk dynamic borrow failures.
self.parent = None;
for self.first_child.each |flow| {
flow.teardown();
}
self.first_child = None;
self.last_child = None;
for self.next_sibling.each |flow| {
flow.teardown();
}
self.next_sibling = None;
self.prev_sibling = None;
}
}
impl TreeNodeRef<FlowData> for FlowContext {
fn with_base<R>(&self, callback: &fn(&FlowData) -> R) -> R {
match *self {

View file

@ -638,6 +638,14 @@ impl InlineFlowData {
elems: ElementMapping::new(),
}
}
pub fn teardown(&mut self) {
self.common.teardown();
for self.boxes.each |box| {
box.teardown();
}
self.boxes = ~[];
}
}
pub trait InlineLayout {

View file

@ -21,6 +21,10 @@ impl TextBoxData {
range: range,
}
}
pub fn teardown(&self) {
self.run.teardown();
}
}
pub fn adapt_textbox_with_range(mut base: RenderBoxBase, run: @TextRun, range: Range)