From d10ee5a9fc218b04df8fa6081d422bdb7d4eceff Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 4 Dec 2006 22:09:44 +0000 Subject: 2006-12-04 Roman Kennke * javax/swing/text/BoxView.java (paint): Replaced painting algorithm with more simple and more reliable painting of the box. * javax/swing/text/html/BlockView.java (PositionInfo): New inner class. Stores additional CSS positioning information. (positionInfo): New field. (BlockView): Initialize positionInfo field. (fetchLayoutInfo): New helper method. Fetches additional CSS positioning information. (layoutMajorAxis): Perform additional CSS layout. (layoutMinorAxis): Perform additional CSS layout. (positionView): New helper method. (replace): Overridden to fetch additional layout information. * javax/swing/text/html/CSS.java (Attribute.POSITION): New field. (Attribute.LEFT): New field. (Attribute.RIGHT): New field. (Attribute.TOP): New field. (Attribute.BOTTOM): New field. (getValue): Create Length for left, right, top and bottom attributes. 2006-12-04 Roman Kennke * gnu/javax/swing/text/html/parser/support/Parser.java (Sgml): Consume any whitespace that immediately follows and sgml insertion. (parseDocument): Consume any initial whitespace. --- ChangeLog | 32 +++ .../swing/text/html/parser/support/Parser.java | 4 + javax/swing/text/BoxView.java | 89 +------- javax/swing/text/html/BlockView.java | 250 ++++++++++++++++++++- javax/swing/text/html/CSS.java | 16 +- 5 files changed, 306 insertions(+), 85 deletions(-) diff --git a/ChangeLog b/ChangeLog index 391f0c0eb..61edef61d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2006-12-04 Roman Kennke + + * javax/swing/text/BoxView.java + (paint): Replaced painting algorithm with more simple and more + reliable painting of the box. + * javax/swing/text/html/BlockView.java + (PositionInfo): New inner class. Stores additional CSS + positioning information. + (positionInfo): New field. + (BlockView): Initialize positionInfo field. + (fetchLayoutInfo): New helper method. Fetches additional + CSS positioning information. + (layoutMajorAxis): Perform additional CSS layout. + (layoutMinorAxis): Perform additional CSS layout. + (positionView): New helper method. + (replace): Overridden to fetch additional layout information. + * javax/swing/text/html/CSS.java + (Attribute.POSITION): New field. + (Attribute.LEFT): New field. + (Attribute.RIGHT): New field. + (Attribute.TOP): New field. + (Attribute.BOTTOM): New field. + (getValue): Create Length for left, right, top and bottom + attributes. + +2006-12-04 Roman Kennke + + * gnu/javax/swing/text/html/parser/support/Parser.java + (Sgml): Consume any whitespace that immediately follows + and sgml insertion. + (parseDocument): Consume any initial whitespace. + 2006-12-03 Mark Wielaard * gnu/javax/management/Server.java (beans): Initialize. diff --git a/gnu/javax/swing/text/html/parser/support/Parser.java b/gnu/javax/swing/text/html/parser/support/Parser.java index f04c58138..3a407310e 100644 --- a/gnu/javax/swing/text/html/parser/support/Parser.java +++ b/gnu/javax/swing/text/html/parser/support/Parser.java @@ -583,6 +583,8 @@ public class Parser ); } } + // Consume any whitespace that follows the Sgml insertion. + optional(WS); } /** @@ -896,6 +898,8 @@ public class Parser protected void parseDocument() throws ParseException { + // Read up any initial whitespace. + optional(WS); while (getTokenAhead().kind != EOF) { advanced = false; diff --git a/javax/swing/text/BoxView.java b/javax/swing/text/BoxView.java index 72bc07e75..0754d9b9b 100644 --- a/javax/swing/text/BoxView.java +++ b/javax/swing/text/BoxView.java @@ -285,89 +285,14 @@ public class BoxView // This returns a cached instance. alloc = getInsideAllocation(alloc); - // The following algorithm optimizes painting of a BoxView by taking - // advantage of the layout order of the box children. - // - // 1. It first searches a child that which's allocation is inside the clip. - // This is accomplished by an efficient binary search. This assumes - // that the children of the BoxView are laid out in the same order - // as their index within the view. This is true for the BoxView, but - // might not be the case for all subclasses. - // 2. Starting from the found view, it paints the children in both - // directions until the first view is hit that is outside the clip. - - // First we search a child view that is inside the clip. - - // Fetch the clip rect and calculate the center point of it. - clipRect = g.getClipBounds(clipRect); - int cX = clipRect.x + clipRect.width / 2; - int cY = clipRect.y + clipRect.height / 2; - - int viewCount = getViewCount(); - int up = viewCount; - int low = 0; - int mid = (up - low) / 2; - View start = getView(mid); - - int newMid; - // Use another cached instance here to avoid allocations during - // painting. - tmpRect.setBounds(alloc); - // This modifies tmpRect. - childAllocation(mid, tmpRect); - while (! clipRect.intersects(tmpRect)) - { - if (isBefore(cX, cY, tmpRect)) - { - up = mid; - newMid = (up - low) / 2 + low; - mid = (newMid == mid) ? newMid - 1 : newMid; - } - else if (isAfter(cX, cY, tmpRect)) - { - low = mid; - newMid = (up - low) / 2 + low; - mid = (newMid == mid) ? newMid + 1 : newMid; - } - else - break; - if (mid >= 0 && mid < viewCount) - { - start = getView(mid); - tmpRect.setBounds(alloc); - childAllocation(mid, tmpRect); - } - else - break; - } - - if (mid >= 0 && mid < viewCount) + int count = getViewCount(); + for (int i = 0; i < count; i++) { - // Ok, we found one view that is inside the clip rect. Now paint the - // children before it that are inside the clip. - boolean inClip = true; - for (int i = mid - 1; i >= 0 && inClip; i--) - { - start = getView(i); - tmpRect.setBounds(alloc); - childAllocation(i, tmpRect); - inClip = clipRect.intersects(tmpRect); - if (inClip) - paintChild(g, tmpRect, i); - } - - // Now paint the found view and all views after it that lie inside the - // clip. - inClip = true; - for (int i = mid; i < viewCount && inClip; i++) - { - start = getView(i); - tmpRect.setBounds(alloc); - childAllocation(i, tmpRect); - inClip = clipRect.intersects(tmpRect); - if (inClip) - paintChild(g, tmpRect, i); - } + View child = getView(i); + tmpRect.setBounds(alloc); + childAllocation(i, tmpRect); + if (g.hitClip(tmpRect.x, tmpRect.y, tmpRect.width, tmpRect.height)) + paintChild(g, tmpRect, i); } } diff --git a/javax/swing/text/html/BlockView.java b/javax/swing/text/html/BlockView.java index 82bd8604e..9e4d9310d 100644 --- a/javax/swing/text/html/BlockView.java +++ b/javax/swing/text/html/BlockView.java @@ -44,6 +44,7 @@ import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.Shape; +import java.util.HashMap; import javax.swing.SizeRequirements; import javax.swing.event.DocumentEvent; @@ -59,6 +60,81 @@ import javax.swing.text.ViewFactory; public class BlockView extends BoxView { + /** + * Stores information about child positioning according to the + * CSS attributes position, left, right, top and bottom. + */ + private static class PositionInfo + { + // TODO: Use enums when available. + + /** + * Static positioning. This is the default and is thus rarely really + * used. + */ + static final int STATIC = 0; + + /** + * Relative positioning. The box is teaked relative to its static + * computed bounds. + */ + static final int RELATIVE = 1; + + /** + * Absolute positioning. The box is moved relative to the parent's box. + */ + static final int ABSOLUTE = 2; + + /** + * Like ABSOLUTE, with some fixation against the viewport (not yet + * implemented). + */ + static final int FIXED = 3; + + /** + * The type according to the constants of this class. + */ + int type; + + /** + * The left constraint, null if not set. + */ + Length left; + + /** + * The right constraint, null if not set. + */ + Length right; + + /** + * The top constraint, null if not set. + */ + Length top; + + /** + * The bottom constraint, null if not set. + */ + Length bottom; + + /** + * Creates a new PositionInfo object. + * + * @param typ the type to set + * @param l the left constraint + * @param r the right constraint + * @param t the top constraint + * @param b the bottom constraint + */ + PositionInfo(int typ, Length l, Length r, Length t, Length b) + { + type = typ; + left = l; + right = r; + top = t; + bottom = b; + } + } + /** * The attributes for this view. */ @@ -76,6 +152,11 @@ public class BlockView extends BoxView */ private Length[] cssSpans; + /** + * Stores additional CSS layout information. + */ + private HashMap positionInfo; + /** * Creates a new view that represents an html box. * This can be used for a number of elements. @@ -87,6 +168,7 @@ public class BlockView extends BoxView { super(elem, axis); cssSpans = new Length[2]; + positionInfo = new HashMap(); } /** @@ -283,6 +365,102 @@ public class BlockView extends BoxView offsets[i] = 0; spans[i] = Math.max(min, targetSpan); } + + // Adjust according to CSS position info. + positionView(targetSpan, axis, i, offsets, spans); + } + } + + /** + * Overridden to perform additional CSS layout (absolute/relative + * positioning). + */ + protected void layoutMajorAxis(int targetSpan, int axis, + int[] offsets, int[] spans) + { + super.layoutMajorAxis(targetSpan, axis, offsets, spans); + + // Adjust according to CSS position info. + int viewCount = getViewCount(); + for (int i = 0; i < viewCount; i++) + { + positionView(targetSpan, axis, i, offsets, spans); + } + } + + /** + * Positions a view according to any additional CSS constraints. + * + * @param targetSpan the target span + * @param axis the axis + * @param i the index of the view + * @param offsets the offsets get placed here + * @param spans the spans get placed here + */ + private void positionView(int targetSpan, int axis, int i, int[] offsets, + int[] spans) + { + View view = getView(i); + PositionInfo pos = (PositionInfo) positionInfo.get(view); + if (pos != null) + { + int p0 = -1; + int p1 = -1; + if (axis == X_AXIS) + { + Length l = pos.left; + if (l != null) + p0 = (int) l.getValue(targetSpan); + l = pos.right; + if (l != null) + p1 = (int) l.getValue(targetSpan); + } + else + { + Length l = pos.top; + if (l != null) + p0 = (int) l.getValue(targetSpan); + l = pos.bottom; + if (l != null) + p1 = (int) l.getValue(targetSpan); + } + if (pos.type == PositionInfo.ABSOLUTE + || pos.type == PositionInfo.FIXED) + { + if (p0 != -1) + { + offsets[i] = p0; + if (p1 != -1) + { + // Overrides computed width. (Possibly overconstrained + // when the width attribute was set too.) + spans[i] = targetSpan - p1 - offsets[i]; + } + } + else if (p1 != -1) + { + // Preserve any computed width. + offsets[i] = targetSpan - p1 - spans[i]; + } + } + else if (pos.type == PositionInfo.RELATIVE) + { + if (p0 != -1) + { + offsets[i] += p0; + if (p1 != -1) + { + // Overrides computed width. (Possibly overconstrained + // when the width attribute was set too.) + spans[i] = spans[i] - p0 - p1 - offsets[i]; + } + } + else if (p1 != -1) + { + // Preserve any computed width. + offsets[i] -= p1; + } + } } } @@ -305,7 +483,7 @@ public class BlockView extends BoxView painter.paint(g, rect.x, rect.y, rect.width, rect.height, this); super.paint(g, a); } - + /** * Fetches the attributes to use when painting. * @@ -469,4 +647,74 @@ public class BlockView extends BoxView HTMLDocument doc = (HTMLDocument) getDocument(); return doc.getStyleSheet(); } + + /** + * Overridden to fetch additional CSS layout information. + */ + public void replace(int offset, int length, View[] views) + { + // First remove unneeded stuff. + for (int i = 0; i < length; i++) + { + View child = getView(i + offset); + positionInfo.remove(child); + } + + // Call super to actually replace the views. + super.replace(offset, length, views); + + // Now fetch the position infos for the new views. + for (int i = 0; i < views.length; i++) + { + fetchLayoutInfo(views[i]); + } + } + + /** + * Fetches and stores the layout info for the specified view. + * + * @param view the view for which the layout info is stored + */ + private void fetchLayoutInfo(View view) + { + AttributeSet atts = view.getAttributes(); + Object o = atts.getAttribute(CSS.Attribute.POSITION); + if (o != null && o instanceof String && ! o.equals("static")) + { + int type; + if (o.equals("relative")) + type = PositionInfo.RELATIVE; + else if (o.equals("absolute")) + type = PositionInfo.ABSOLUTE; + else if (o.equals("fixed")) + type = PositionInfo.FIXED; + else + type = PositionInfo.STATIC; + + if (type != PositionInfo.STATIC) + { + StyleSheet ss = getStyleSheet(); + float emBase = ss.getEMBase(atts); + float exBase = ss.getEXBase(atts); + Length left = (Length) atts.getAttribute(CSS.Attribute.LEFT); + if (left != null) + left.setFontBases(emBase, exBase); + Length right = (Length) atts.getAttribute(CSS.Attribute.RIGHT); + if (right != null) + right.setFontBases(emBase, exBase); + Length top = (Length) atts.getAttribute(CSS.Attribute.TOP); + if (top != null) + top.setFontBases(emBase, exBase); + Length bottom = (Length) atts.getAttribute(CSS.Attribute.BOTTOM); + if (bottom != null) + bottom.setFontBases(emBase, exBase); + if (left != null || right != null || top != null || bottom != null) + { + PositionInfo pos = new PositionInfo(type, left, right, top, + bottom); + positionInfo.put(view, pos); + } + } + } + } } diff --git a/javax/swing/text/html/CSS.java b/javax/swing/text/html/CSS.java index 0d1eeb762..294d47fb2 100644 --- a/javax/swing/text/html/CSS.java +++ b/javax/swing/text/html/CSS.java @@ -418,7 +418,17 @@ public class CSS implements Serializable new Attribute("border-right-color", false, null); static final Attribute BORDER_SPACING = new Attribute("border-spacing", false, null); - + static final Attribute POSITION = + new Attribute("position", false, null); + static final Attribute LEFT = + new Attribute("left", false, null); + static final Attribute RIGHT = + new Attribute("right", false, null); + static final Attribute TOP = + new Attribute("top", false, null); + static final Attribute BOTTOM = + new Attribute("bottom", false, null); + /** * The attribute string. */ @@ -522,7 +532,9 @@ public class CSS implements Serializable || att == Attribute.HEIGHT || att == Attribute.PADDING || att == Attribute.PADDING_BOTTOM || att == Attribute.PADDING_LEFT || att == Attribute.PADDING_RIGHT - || att == Attribute.PADDING_TOP) + || att == Attribute.PADDING_TOP + || att == Attribute.LEFT || att == Attribute.RIGHT + || att == Attribute.TOP || att == Attribute.BOTTOM) o = new Length(v); else if (att == Attribute.BORDER_WIDTH || att == Attribute.BORDER_TOP_WIDTH || att == Attribute.BORDER_LEFT_WIDTH -- cgit v1.2.1