This improves HTML rendering by:
- Making ParagraphView and BlockView recognize the CSS width and height
attribute, including relative (%) values.
- Adjusting the InlineView so that it never gets smaller than the
longest word.

plus some smaller fixes.

2006-11-03  Roman Kennke  <[EMAIL PROTECTED]>

        * javax/swing/text/html/BlockView.java
        (attributes): New field.
        (cssHeight): New field.
        (cssWidth): New field.
        (painter): New field.
        (calculateMajorAxisRequirements): Overridden to account for
        CSS settings.
        (calculateMinorAxisRequirements): Overridden to account for
        CSS settings.
        (layoutMinorAxis): Overridden to account for CSS settings.
        (changedUpdate): Formatting fixlet.
        (constrainSize): New helper method.
        (getAlignment): Fix alignment.
        (getAttributes): Cache attributes for better performance.
        (getStyleSheet): Fetch stylesheet from document rather than creating
        a new one.
        (paint): Remove comment.
        (setCSSSpan): New helper method.
        (setPropertiesFromAttributes): Implemented to fetch the
        recognized properties.
        * javax/swing/text/html/CSS.java
        (getValue): Added mapping for width and height attributes.
        * javax/swing/text/html/InlineView.java
        (longestWord): New field.
        (getLongestWord): New helper method.
        (calculateLongestWord): New helper method.
        (getMinimumSpan): Overridden to constrain the minimum span by the
        longest word.
        * javax/swing/text/html/ParagraphView.java
        (cssHeight): New field.
        (cssWidth): New field.
        (calculateMinorAxisRequirements): Overridden to account for
        CSS settings.
        (setCSSSpan): New helper method.
        (setPropertiesFromAttributes): Fetch CSS width and height. Added
        null check.
        * gnu/javax/swing/text/html/css/Length.java
        (percentage): New field.
        (Length): Determine percentage values.
        (getValue(float)): New method for handling percentage values.
        (isPercentage): New method.

/Roman

Index: javax/swing/text/html/BlockView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/BlockView.java,v
retrieving revision 1.3
diff -u -1 -5 -r1.3 BlockView.java
--- javax/swing/text/html/BlockView.java	20 Dec 2005 15:59:45 -0000	1.3
+++ javax/swing/text/html/BlockView.java	5 Nov 2006 20:22:16 -0000
@@ -26,60 +26,82 @@
 As a special exception, the copyright holders of this library give you
 permission to link this library with independent modules to produce an
 executable, regardless of the license terms of these independent
 modules, and to copy and distribute the resulting executable under
 terms of your choice, provided that you also meet, for each linked
 independent module, the terms and conditions of the license of that
 module.  An independent module is a module which is not derived from
 or based on this library.  If you modify this library, you may extend
 this exception to your version of the library, but you are not
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
 
 package javax.swing.text.html;
 
+import gnu.javax.swing.text.html.css.Length;
+
 import java.awt.Graphics;
 import java.awt.Rectangle;
 import java.awt.Shape;
 
 import javax.swing.SizeRequirements;
 import javax.swing.event.DocumentEvent;
 import javax.swing.text.AttributeSet;
 import javax.swing.text.BoxView;
 import javax.swing.text.Element;
 import javax.swing.text.View;
 import javax.swing.text.ViewFactory;
 
 /**
  * @author Lillian Angel <[EMAIL PROTECTED]>
  */
 public class BlockView extends BoxView
 {
-  
+
+  /**
+   * The attributes for this view.
+   */
+  private AttributeSet attributes;
+
+  /**
+   * The box painter for this view.
+   */
+  private StyleSheet.BoxPainter painter;
+
+  /**
+   * The width as specified in the stylesheet, null if not specified.
+   */
+  private Length cssWidth;
+
+  /**
+   * The height as specified in the stylesheet, null if not specified.
+   */
+  private Length cssHeight;
+
   /**
    * Creates a new view that represents an html box. 
    * This can be used for a number of elements.
    * 
    * @param elem - the element to create a view for
    * @param axis - either View.X_AXIS or View.Y_AXIS
    */
   public BlockView(Element elem, int axis)
   {
     super(elem, axis);
   }
-  
+
   /**
    * Creates the parent view for this. It is called before
    * any other methods, if the parent view is working properly.
    * Implemented to forward to the superclass and call
    * setPropertiesFromAttributes to set the paragraph 
    * properties.
    * 
    * @param parent - the new parent, or null if the view
    * is being removed from a parent it was added to. 
    */
   public void setParent(View parent)
   {
     super.setParent(parent);
     
     if (parent != null)
@@ -87,103 +109,214 @@
   }
   
   /**
    * Calculates the requirements along the major axis.
    * This is implemented to call the superclass and then
    * adjust it if the CSS width or height attribute is specified
    * and applicable.
    * 
    * @param axis - the axis to check the requirements for.
    * @param r - the SizeRequirements. If null, one is created.
    * @return the new SizeRequirements object.
    */
   protected SizeRequirements calculateMajorAxisRequirements(int axis,
                                                             SizeRequirements r)
   {
-    SizeRequirements sr = super.calculateMajorAxisRequirements(axis, r);
-    // FIXME: adjust it if the CSS width or height attribute is specified
-    // and applicable
-    return sr;
+    if (r == null)
+      r = new SizeRequirements();
+    
+    if (setCSSSpan(r, axis))
+      {
+        // If we have set the span from CSS, then we need to adjust
+        // the margins.
+        SizeRequirements parent = super.calculateMajorAxisRequirements(axis,
+                                                                       null);
+        int margin = axis == X_AXIS ? getLeftInset() + getRightInset()
+                                    : getTopInset() + getBottomInset();
+        r.minimum -= margin;
+        r.preferred -= margin;
+        r.maximum -= margin;
+        constrainSize(axis, r, parent);
+      }
+    else
+      r = super.calculateMajorAxisRequirements(axis, r);
+    return r;
   }
   
   /**
    * Calculates the requirements along the minor axis.
    * This is implemented to call the superclass and then
    * adjust it if the CSS width or height attribute is specified
    * and applicable.
    * 
    * @param axis - the axis to check the requirements for.
    * @param r - the SizeRequirements. If null, one is created.
    * @return the new SizeRequirements object.
    */
   protected SizeRequirements calculateMinorAxisRequirements(int axis,
                                                             SizeRequirements r)
   {
-    SizeRequirements sr = super.calculateMinorAxisRequirements(axis, r);
-    // FIXME: adjust it if the CSS width or height attribute is specified
-    // and applicable.
-    return sr;
+    if (r == null)
+      r = new SizeRequirements();
+    
+    if (setCSSSpan(r, axis))
+      {
+        // If we have set the span from CSS, then we need to adjust
+        // the margins.
+        SizeRequirements parent = super.calculateMinorAxisRequirements(axis,
+                                                                       null);
+        int margin = axis == X_AXIS ? getLeftInset() + getRightInset()
+                                    : getTopInset() + getBottomInset();
+        r.minimum -= margin;
+        r.preferred -= margin;
+        r.maximum -= margin;
+        constrainSize(axis, r, parent);
+      }
+    else
+      r = super.calculateMinorAxisRequirements(axis, r);
+    return r;
   }
-  
+
+  /**
+   * Sets the span on the SizeRequirements object according to the
+   * according CSS span value, when it is set.
+   * 
+   * @param r the size requirements
+   * @param axis the axis
+   *
+   * @return <code>true</code> when the CSS span has been set,
+   *         <code>false</code> otherwise
+   */
+  private boolean setCSSSpan(SizeRequirements r, int axis)
+  {
+    boolean ret = false;
+    if (axis == X_AXIS)
+      {
+        if (cssWidth != null && ! cssWidth.isPercentage())
+          {
+            r.minimum = (int) cssWidth.getValue();
+            r.preferred = (int) cssWidth.getValue();
+            r.maximum = (int) cssWidth.getValue();
+            ret = true;
+          }
+      }
+    else
+      {
+        if (cssHeight != null && ! cssWidth.isPercentage())
+          {
+            r.minimum = (int) cssHeight.getValue();
+            r.preferred = (int) cssHeight.getValue();
+            r.maximum = (int) cssHeight.getValue();
+            ret = true;
+          }
+      }
+    return ret;
+  }
+
+  /**
+   * Constrains the <code>r</code> requirements according to
+   * <code>min</code>.
+   *
+   * @param axis the axis
+   * @param r the requirements to constrain
+   * @param min the constraining requirements
+   */
+  private void constrainSize(int axis, SizeRequirements r,
+                             SizeRequirements min)
+  {
+    if (min.minimum > r.minimum)
+      {
+        r.minimum = min.minimum;
+        r.preferred = min.minimum;
+        r.maximum = Math.max(r.maximum, min.maximum);
+      }
+  }
+
   /**
    * Lays out the box along the minor axis (the axis that is
    * perpendicular to the axis that it represents). The results
    * of the layout are placed in the given arrays which are
    * the allocations to the children along the minor axis.
    * 
    * @param targetSpan - the total span given to the view, also 
    * used to layout the children.
    * @param axis - the minor axis
    * @param offsets - the offsets from the origin of the view for
    * all the child views. This is a return value and is filled in by this
    * function.
    * @param spans - the span of each child view. This is a return value and is 
    * filled in by this function.
    */
   protected void layoutMinorAxis(int targetSpan, int axis,
                                  int[] offsets, int[] spans)
   {
-    // FIXME: Not implemented.
-    super.layoutMinorAxis(targetSpan, axis, offsets, spans);
+    int viewCount = getViewCount();
+    Length length = axis == X_AXIS ? cssWidth : cssHeight;
+    for (int i = 0; i < viewCount; i++)
+      {
+        View view = getView(i);
+        int min = (int) view.getMinimumSpan(axis);
+        int max;
+        // Handle percentage span value.
+        if (length != null && length.isPercentage())
+          {
+            min = Math.max((int) length.getValue(targetSpan), min);
+            max = min;
+          }
+        else
+          max = (int) view.getMaximumSpan(axis);
+
+        if (max < targetSpan)
+          {
+            // Align child.
+            float align = view.getAlignment(axis);
+            offsets[i] = (int) ((targetSpan - max) * align);
+            spans[i] = max;
+          }
+        else
+          {
+            offsets[i] = 0;
+            spans[i] = Math.max(min, targetSpan);
+          }
+      }
   }
   
   /**
    * Paints using the given graphics configuration and shape.
    * This delegates to the css box painter to paint the
    * border and background prior to the interior.
    * 
    * @param g - Graphics configuration
    * @param a - the Shape to render into.
    */
   public void paint(Graphics g, Shape a)
   {
-    Rectangle rect = (Rectangle) a;
-    // FIXME: not fully implemented
-    getStyleSheet().getBoxPainter(getAttributes()).paint(g, rect.x, rect.y,
-                                                         rect.width,
-                                                         rect.height, this);
+    Rectangle rect = a instanceof Rectangle ? (Rectangle) a : a.getBounds();
+    painter.paint(g, rect.x, rect.y, rect.width, rect.height, this);
     super.paint(g, a);
   }
   
   /**
    * Fetches the attributes to use when painting.
    * 
    * @return the attributes of this model.
    */
   public AttributeSet getAttributes()
   {
-    return getStyleSheet().getViewAttributes(this);
+    if (attributes == null)
+      attributes = getStyleSheet().getViewAttributes(this);
+    return attributes;
   }
   
   /**
    * Gets the resize weight.
    * 
    * @param axis - the axis to get the resize weight for.
    * @return the resize weight.
    * @throws IllegalArgumentException - for an invalid axis
    */
   public int getResizeWeight(int axis) throws IllegalArgumentException
   {
     // Can't resize the Y_AXIS
     if (axis == Y_AXIS)
       return 0;
     if (axis == X_AXIS)
@@ -194,52 +327,56 @@
   /**
    * Gets the alignment.
    * 
    * @param axis - the axis to get the alignment for.
    * @return the alignment.
    */
   public float getAlignment(int axis)
   {
     if (axis == X_AXIS)
       return 0.0F;
     if (axis == Y_AXIS)
       {
         if (getViewCount() == 0)
           return 0.0F;
         float prefHeight = getPreferredSpan(Y_AXIS);
-        float firstRowHeight = getView(0).getPreferredSpan(Y_AXIS);
-        return (firstRowHeight / 2.F) / prefHeight;
+        View first = getView(0);
+        float firstRowHeight = first.getPreferredSpan(Y_AXIS);
+        return prefHeight != 0 ? (firstRowHeight * first.getAlignment(Y_AXIS))
+                                 / prefHeight
+                               : 0;
       }
     throw new IllegalArgumentException("Invalid Axis");
   }
   
   /**
    * Gives notification from the document that attributes were
    * changed in a location that this view is responsible for.
    * 
    * @param ev - the change information
    * @param a - the current shape of the view
    * @param f - the factory to use to rebuild if the view has children.
    */
   public void changedUpdate(DocumentEvent ev,
                             Shape a, ViewFactory f)
   {
     super.changedUpdate(ev, a, f);
     
     // If more elements were added, then need to set the properties for them
     int currPos = ev.getOffset();
-    if (currPos <= getStartOffset() && (currPos + ev.getLength()) >= getEndOffset())
+    if (currPos <= getStartOffset()
+        && (currPos + ev.getLength()) >= getEndOffset())
         setPropertiesFromAttributes();
   }
 
   /**
    * Determines the preferred span along the axis.
    * 
    * @param axis - the view to get the preferred span for.
    * @return the span the view would like to be painted into >=0/
    * The view is usually told to paint into the span that is returned, 
    * although the parent may choose to resize or break the view.
    * @throws IllegalArgumentException - for an invalid axis
    */
   public float getPreferredSpan(int axis) throws IllegalArgumentException
   {
     if (axis == X_AXIS || axis == Y_AXIS)
@@ -272,30 +409,47 @@
    * although the parent may choose to resize or break the view.
    * @throws IllegalArgumentException - for an invalid axis
    */
   public float getMaximumSpan(int axis) throws IllegalArgumentException
   {
     if (axis == X_AXIS || axis == Y_AXIS)
       return super.getMaximumSpan(axis);
     throw new IllegalArgumentException("Invalid Axis");
   }
   
   /**
    * Updates any cached values that come from attributes.
    */
   protected void setPropertiesFromAttributes()
   {
-    // FIXME: Not implemented (need to use StyleSheet).
+    // Fetch attributes.
+    StyleSheet ss = getStyleSheet();
+    attributes = ss.getViewAttributes(this);
+
+    // Fetch painter.
+    painter = ss.getBoxPainter(attributes);
+
+    // Update insets.
+    if (attributes != null)
+      {
+        setInsets((short) painter.getInset(TOP, this),
+                  (short) painter.getInset(LEFT, this),
+                  (short) painter.getInset(BOTTOM, this),
+                  (short) painter.getInset(RIGHT, this));
+      }
+
+    // Fetch width and height.
+    cssWidth = (Length) attributes.getAttribute(CSS.Attribute.WIDTH);
+    cssHeight = (Length) attributes.getAttribute(CSS.Attribute.HEIGHT);
   }
   
   /**
    * Gets the default style sheet.
    * 
    * @return the style sheet
    */
   protected StyleSheet getStyleSheet()
   {
-    StyleSheet styleSheet = new StyleSheet();
-    styleSheet.importStyleSheet(getClass().getResource(HTMLEditorKit.DEFAULT_CSS));
-    return styleSheet;
+    HTMLDocument doc = (HTMLDocument) getDocument();
+    return doc.getStyleSheet();
   }
 }
Index: javax/swing/text/html/CSS.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/CSS.java,v
retrieving revision 1.6
diff -u -1 -5 -r1.6 CSS.java
--- javax/swing/text/html/CSS.java	31 Aug 2006 21:07:05 -0000	1.6
+++ javax/swing/text/html/CSS.java	5 Nov 2006 20:22:16 -0000
@@ -476,22 +476,23 @@
    * @return the wrapped value
    */
   static Object getValue(Attribute att, String v)
   {
     Object o;
     if (att == Attribute.FONT_SIZE)
       o = new FontSize(v);
     else if (att == Attribute.FONT_WEIGHT)
       o = new FontWeight(v);
     else if (att == Attribute.FONT_STYLE)
       o = new FontStyle(v);
     else if (att == Attribute.COLOR || att == Attribute.BACKGROUND_COLOR)
       o = new CSSColor(v);
     else if (att == Attribute.MARGIN || att == Attribute.MARGIN_BOTTOM
              || att == Attribute.MARGIN_LEFT || att == Attribute.MARGIN_RIGHT
-             || att == Attribute.MARGIN_TOP)
+             || att == Attribute.MARGIN_TOP || att == Attribute.WIDTH
+             || att == Attribute.HEIGHT)
       o = new Length(v);
     else
       o = v;
     return o;
   }
 }
Index: javax/swing/text/html/InlineView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/InlineView.java,v
retrieving revision 1.4
diff -u -1 -5 -r1.4 InlineView.java
--- javax/swing/text/html/InlineView.java	25 Aug 2006 11:40:44 -0000	1.4
+++ javax/swing/text/html/InlineView.java	5 Nov 2006 20:22:16 -0000
@@ -26,57 +26,68 @@
 As a special exception, the copyright holders of this library give you
 permission to link this library with independent modules to produce an
 executable, regardless of the license terms of these independent
 modules, and to copy and distribute the resulting executable under
 terms of your choice, provided that you also meet, for each linked
 independent module, the terms and conditions of the license of that
 module.  An independent module is a module which is not derived from
 or based on this library.  If you modify this library, you may extend
 this exception to your version of the library, but you are not
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
 
 package javax.swing.text.html;
 
+import java.awt.FontMetrics;
 import java.awt.Shape;
+import java.text.BreakIterator;
 
 import javax.swing.event.DocumentEvent;
 import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
 import javax.swing.text.Document;
 import javax.swing.text.Element;
 import javax.swing.text.LabelView;
+import javax.swing.text.Segment;
 import javax.swing.text.View;
 import javax.swing.text.ViewFactory;
 
 /**
  * Renders HTML content (identified by [EMAIL PROTECTED] HTML.Tag#CONTENT}). This is
  * basically a [EMAIL PROTECTED] LabelView} that is adjusted to understand styles defined
  * by stylesheets.
  *
  * @author Roman Kennke ([EMAIL PROTECTED])
  */
 public class InlineView
   extends LabelView
 {
 
   /**
    * The attributes used by this view.
    */
   private AttributeSet attributes;
 
   /**
+   * The span of the longest word in this view.
+   *
+   * @see #getLongestWord()
+   */
+  private float longestWord;
+
+  /**
    * Creates a new <code>InlineView</code> that renders the specified element.
    *
    * @param element the element for this view
    */
   public InlineView(Element element)
   {
     super(element);
   }
 
   /**
    * Receives notification that something was inserted into the document in
    * a location that this view is responsible for.
    *
    * @param e the document event
    * @param a the current allocation of this view
@@ -195,16 +206,86 @@
 
   /**
    * Returns the stylesheet used by this view. This returns the stylesheet
    * of the <code>HTMLDocument</code> that is rendered by this view.
    *
    * @return the stylesheet used by this view
    */
   protected StyleSheet getStyleSheet()
   {
     Document doc = getDocument();
     StyleSheet styleSheet = null;
     if (doc instanceof HTMLDocument)
       styleSheet = ((HTMLDocument) doc).getStyleSheet();
     return styleSheet;
   }
+
+  /**
+   * Returns the minimum span for the specified axis. This returns the
+   * width of the longest word for the X axis and the super behaviour for
+   * the Y axis. This is a slight deviation from the reference implementation.
+   * IMO this should improve rendering behaviour so that an InlineView never
+   * gets smaller than the longest word in it.
+   */
+  public float getMinimumSpan(int axis)
+  {
+    float min = super.getMinimumSpan(axis);
+    if (axis == X_AXIS)
+      min = Math.max(getLongestWord(), min);
+    return min;
+  }
+
+  /**
+   * Returns the span of the longest word in this view.
+   *
+   * @return the span of the longest word in this view
+   */
+  private float getLongestWord()
+  {
+    if (longestWord == -1)
+      longestWord = calculateLongestWord();
+    return longestWord;
+  }
+
+  /**
+   * Calculates the span of the longest word in this view.
+   *
+   * @return the span of the longest word in this view
+   */
+  private float calculateLongestWord()
+  {
+    float span = 0;
+    try
+      {
+        Document doc = getDocument();
+        int p0 = getStartOffset();
+        int p1 = getEndOffset();
+        Segment s = new Segment();
+        doc.getText(p0, p1 - p0, s);
+        BreakIterator iter = BreakIterator.getWordInstance();
+        iter.setText(s);
+        int wordStart = p0;
+        int wordEnd = p0;
+        int start = iter.first();
+        for (int end = iter.next(); end != BreakIterator.DONE;
+             start = end, end = iter.next())
+          {
+            if ((end - start) > (wordEnd - wordStart))
+              {
+                wordStart = start;
+                wordEnd = end;
+              }
+          }
+        if (wordEnd - wordStart > 0)
+          {
+            FontMetrics fm = getFontMetrics();
+            int offset = s.offset + wordStart - s.getBeginIndex();
+            span = fm.charsWidth(s.array, offset, wordEnd - wordStart);
+          }
+      }
+    catch (BadLocationException ex)
+      {
+        // Return 0.
+      }
+    return span;
+  }
 }
Index: javax/swing/text/html/ParagraphView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/ParagraphView.java,v
retrieving revision 1.3
diff -u -1 -5 -r1.3 ParagraphView.java
--- javax/swing/text/html/ParagraphView.java	31 Aug 2006 21:07:05 -0000	1.3
+++ javax/swing/text/html/ParagraphView.java	5 Nov 2006 20:22:16 -0000
@@ -26,30 +26,32 @@
 As a special exception, the copyright holders of this library give you
 permission to link this library with independent modules to produce an
 executable, regardless of the license terms of these independent
 modules, and to copy and distribute the resulting executable under
 terms of your choice, provided that you also meet, for each linked
 independent module, the terms and conditions of the license of that
 module.  An independent module is a module which is not derived from
 or based on this library.  If you modify this library, you may extend
 this exception to your version of the library, but you are not
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
 
 package javax.swing.text.html;
 
+import gnu.javax.swing.text.html.css.Length;
+
 import java.awt.Graphics;
 import java.awt.Rectangle;
 import java.awt.Shape;
 
 import javax.swing.SizeRequirements;
 import javax.swing.text.AttributeSet;
 import javax.swing.text.Document;
 import javax.swing.text.Element;
 import javax.swing.text.StyleConstants;
 import javax.swing.text.View;
 
 /**
  * Renders a paragraph in HTML. This is a subclass of
  * [EMAIL PROTECTED] javax.swing.text.ParagraphView} with some adjustments for
  * understanding stylesheets.
@@ -59,30 +61,40 @@
 public class ParagraphView
   extends javax.swing.text.ParagraphView
 {
 
   /**
    * The attributes used by this view.
    */
   private AttributeSet attributes;
 
   /**
    * The stylesheet's box painter.
    */
   private StyleSheet.BoxPainter painter;
 
   /**
+   * The width as specified in the stylesheet or null if not specified.
+   */
+  private Length cssWidth;
+
+  /**
+   * The height as specified in the stylesheet or null if not specified.
+   */
+  private Length cssHeight;
+
+  /**
    * Creates a new ParagraphView for the specified element.
    *
    * @param element the element
    */
   public ParagraphView(Element element)
   {
     super(element);
   }
 
   /**
    * Sets the parent of this view. This is implemented to call the parent
    * functionality and then trigger [EMAIL PROTECTED] #setPropertiesFromAttributes} in
    * order to load the stylesheet attributes.
    *
    * @param parent the parent view to set
@@ -104,85 +116,148 @@
       {
         attributes = getStyleSheet().getViewAttributes(this);
       }
     return attributes;
   }
 
   /**
    * Loads the visual properties of the ParagraphView from the element's
    * attributes and the stylesheet of the HTML document.
    */
   protected void setPropertiesFromAttributes()
   {
     super.setPropertiesFromAttributes();
 
     // Fetch CSS attributes.
-    AttributeSet atts = getAttributes();
-    Object o = atts.getAttribute(CSS.Attribute.TEXT_ALIGN);
-    if (o != null)
-      {
-        String align = o.toString();
-        if (align.equals("left"))
-          setJustification(StyleConstants.ALIGN_LEFT);
-        else if (align.equals("right"))
-          setJustification(StyleConstants.ALIGN_RIGHT);
-        else if (align.equals("center"))
-          setJustification(StyleConstants.ALIGN_CENTER);
-        else if (align.equals("justify"))
-          setJustification(StyleConstants.ALIGN_JUSTIFIED);
-      }
-
-    // Fetch StyleSheet's box painter.
-    painter = getStyleSheet().getBoxPainter(atts);
-    setInsets((short) painter.getInset(TOP, this),
-              (short) painter.getInset(LEFT, this),
-              (short) painter.getInset(BOTTOM, this),
-              (short) painter.getInset(RIGHT, this));
+    attributes = getAttributes();
+    if (attributes != null)
+      {
+        super.setPropertiesFromAttributes();
+        Object o = attributes.getAttribute(CSS.Attribute.TEXT_ALIGN);
+        if (o != null)
+          {
+            String align = o.toString();
+            if (align.equals("left"))
+              setJustification(StyleConstants.ALIGN_LEFT);
+            else if (align.equals("right"))
+              setJustification(StyleConstants.ALIGN_RIGHT);
+            else if (align.equals("center"))
+              setJustification(StyleConstants.ALIGN_CENTER);
+            else if (align.equals("justify"))
+              setJustification(StyleConstants.ALIGN_JUSTIFIED);
+          }
+
+        // Fetch StyleSheet's box painter.
+        painter = getStyleSheet().getBoxPainter(attributes);
+        setInsets((short) painter.getInset(TOP, this),
+                  (short) painter.getInset(LEFT, this),
+                  (short) painter.getInset(BOTTOM, this),
+                  (short) painter.getInset(RIGHT, this));
 
-    // TODO: Handle CSS width and height attributes somehow.
+        cssWidth = (Length) attributes.getAttribute(CSS.Attribute.WIDTH);
+        cssHeight = (Length) attributes.getAttribute(CSS.Attribute.WIDTH);
+      }
   }
 
   /**
    * Returns the stylesheet used by this view.
    *
    * @return the stylesheet used by this view
    */
   protected StyleSheet getStyleSheet()
   {
     Document doc = getDocument();
     StyleSheet styleSheet = null;
     if (doc instanceof HTMLDocument)
       styleSheet = ((HTMLDocument) doc).getStyleSheet();
     return styleSheet;
   }
 
   /**
    * Calculates the minor axis requirements of this view. This is implemented
    * to return the super class'es requirements and modifies the minimumSpan
    * slightly so that it is not smaller than the length of the longest word.
    *
    * @param axis the axis
    * @param r the SizeRequirements object to be used as return parameter;
    *        if <code>null</code> a new one will be created
    *
    * @return the requirements along the minor layout axis
    */
   protected SizeRequirements calculateMinorAxisRequirements(int axis,
                                                             SizeRequirements r)
   {
-    // FIXME: Implement the above specified behaviour.
-    return super.calculateMinorAxisRequirements(axis, r);
+    r = super.calculateMinorAxisRequirements(axis, r);
+    if (setCSSSpan(r, axis))
+      {
+        // If we have set the span from CSS, then we need to adjust
+        // the margins.
+        SizeRequirements parent = super.calculateMinorAxisRequirements(axis,
+                                                                       null);
+        int margin = axis == X_AXIS ? getLeftInset() + getRightInset()
+                                    : getTopInset() + getBottomInset();
+        r.minimum -= margin;
+        r.preferred -= margin;
+        r.maximum -= margin;
+      }
+    else
+      {
+        float min = 0;
+        int n = getLayoutViewCount();
+        for (int i = 0; i < n; i++)
+          min = Math.max(getLayoutView(i).getMinimumSpan(axis), min);
+        r.minimum = (int) min;
+        r.preferred = Math.max(r.preferred, r.minimum);
+        r.maximum = Math.max(r.maximum, r.preferred);
+      }
+    return r;
+  }
+
+  /**
+   * Sets the span on the SizeRequirements object according to the
+   * according CSS span value, when it is set.
+   * 
+   * @param r the size requirements
+   * @param axis the axis
+   *
+   * @return <code>true</code> when the CSS span has been set,
+   *         <code>false</code> otherwise
+   */
+  private boolean setCSSSpan(SizeRequirements r, int axis)
+  {
+    boolean ret = false;
+    if (axis == X_AXIS)
+      {
+        if (cssWidth != null && ! cssWidth.isPercentage())
+          {
+            r.minimum = (int) cssWidth.getValue();
+            r.preferred = (int) cssWidth.getValue();
+            r.maximum = (int) cssWidth.getValue();
+            ret = true;
+          }
+      }
+    else
+      {
+        if (cssHeight != null && ! cssWidth.isPercentage())
+          {
+            r.minimum = (int) cssHeight.getValue();
+            r.preferred = (int) cssHeight.getValue();
+            r.maximum = (int) cssHeight.getValue();
+            ret = true;
+          }
+      }
+    return ret;
   }
 
   /**
    * Determines if this view is visible or not. If none of the children is
    * visible and the only visible child is the break that ends the paragraph,
    * this paragraph is not considered to be visible.
    *
    * @return the visibility of this paragraph
    */
   public boolean isVisible()
   {
     // FIXME: Implement the above specified behaviour.
     return super.isVisible();
   }
 
Index: gnu/javax/swing/text/html/css/Length.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/javax/swing/text/html/css/Length.java,v
retrieving revision 1.1
diff -u -1 -5 -r1.1 Length.java
--- gnu/javax/swing/text/html/css/Length.java	31 Aug 2006 21:07:05 -0000	1.1
+++ gnu/javax/swing/text/html/css/Length.java	5 Nov 2006 20:22:16 -0000
@@ -45,46 +45,83 @@
  */
 public class Length
 {
 
   /**
    * The original value.
    */
   private String value;
 
   /**
    * The converted value.
    */
   private float floatValue;
 
   /**
+   * Indicates when the value is a percentage value.
+   */
+  private boolean isPercentage;
+
+  /**
    * Creates a new length converter instance.
    *
    * @param val the CSS value
    */
   public Length(String val)
   {
     value = val;
     int i = value.indexOf("px");
+    int percent = value.indexOf("%");
     floatValue = 0.0F;
     if (i != -1)
       {
         String sub = value.substring(0, i);
         floatValue = Float.parseFloat(sub);
       }
+    else if (percent != -1)
+      {
+        isPercentage = true;
+        String sub = value.substring(0, percent);
+        floatValue = Float.parseFloat(sub) / 100;
+      }
     else
       {
         // TODO: Implement other length options.
         floatValue = Float.parseFloat(value);
       }
   }
 
   /**
    * Returns the value converted to pixels.
    *
    * @return the value converted to pixels
    */
   public float getValue()
   {
     return floatValue;
   }
+
+  /**
+   * Returns the absolute span for the case when this length value is
+   * a relative value.
+   *
+   * @param span the target span
+   *
+   * @return the absolute span
+   */
+  public float getValue(float span)
+  {
+    return span * floatValue;
+  }
+
+  /**
+   * Returns <code>true</code> when the length value is a percentage
+   * value, <code>false</code> otherwise.
+   *
+   * @return <code>true</code> when the length value is a percentage
+   *         value, <code>false</code> otherwise
+   */
+  public boolean isPercentage()
+  {
+    return isPercentage;
+  }
 }

Reply via email to