Widening.

git-svn-id: https://samskivert.googlecode.com/svn/trunk@2511 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
samskivert
2008-12-18 01:45:43 +00:00
parent edb6f304e4
commit 0f359f3f21
+130 -183
View File
@@ -38,6 +38,7 @@ import java.text.AttributedCharacterIterator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -51,21 +52,16 @@ import com.samskivert.util.Tuple;
import static com.samskivert.Log.log; import static com.samskivert.Log.log;
/** /**
* The label is a multipurpose text display mechanism that can display * The label is a multipurpose text display mechanism that can display small amounts of text
* small amounts of text wrapped to fit into a variety of constrained * wrapped to fit into a variety of constrained spaces. It can be requested to conform to a
* spaces. It can be requested to conform to a particular width or height * particular width or height and will expand into the other dimension in order to accomodate the
* and will expand into the other dimension in order to accomodate the * text at hand. It is not a component, but is intended for use by components and other more
* text at hand. It is not a component, but is intended for use by * heavyweight entities.
* components and other more heavyweight entities.
*/ */
public class Label implements SwingConstants, LabelStyleConstants public class Label implements SwingConstants, LabelStyleConstants
{ {
/** The pattern used to mark the start/end of color blocks. */ /** The pattern used to mark the start/end of color blocks. */
public static final Pattern COLOR_PATTERN = public static final Pattern COLOR_PATTERN = Pattern.compile("#([Xx]|[0-9A-Fa-f]{6}+)");
Pattern.compile("#([Xx]|[0-9A-Fa-f]{6}+)");
private static final Pattern ESCAPED_PATTERN =
Pattern.compile("#''([Xx]|[0-9A-Fa-f]{6}+)");
/** /**
* Filter out any color tags from the specified text. * Filter out any color tags from the specified text.
@@ -77,8 +73,7 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Escape any special tags so that they won't be interpreted by the * Escape any special tags so that they won't be interpreted by the label.
* label.
*/ */
public static String escapeColors (String txt) public static String escapeColors (String txt)
{ {
@@ -87,9 +82,8 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Un-escape special tags so that they again look correct. Called by * Un-escape special tags so that they again look correct. Called by rendering components that
* rendering components that do not understand the color tags * do not understand the color tags to filter colors and unescape any escaped colors.
* to filter colors and unescape any escaped colors.
*/ */
public static String unescapeColors (String txt) public static String unescapeColors (String txt)
{ {
@@ -123,8 +117,7 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Constructs a label with the supplied text and configuration * Constructs a label with the supplied text and configuration parameters.
* parameters.
*/ */
public Label (String text, Color textColor, Font font) public Label (String text, Color textColor, Font font)
{ {
@@ -132,11 +125,9 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Constructs a label with the supplied text and configuration * Constructs a label with the supplied text and configuration parameters.
* parameters.
*/ */
public Label ( public Label (String text, int style, Color textColor, Color altColor, Font font)
String text, int style, Color textColor, Color altColor, Font font)
{ {
setText(text); setText(text);
setStyle(style); setStyle(style);
@@ -156,18 +147,16 @@ public class Label implements SwingConstants, LabelStyleConstants
/** /**
* Sets the text to be displayed by this label. * Sets the text to be displayed by this label.
* *
* <p> This should be followed by a call to {@link #layout} before a * <p> This should be followed by a call to {@link #layout} before a call is made to {@link
* call is made to {@link #render} as this method invalidates the * #render} as this method invalidates the layout information.
* layout information.
* *
* @return true if the text changed as a result of being set, false if * @return true if the text changed as a result of being set, false if the label was already
* the label was already displaying the requested text. * displaying the requested text.
*/ */
public boolean setText (String text) public boolean setText (String text)
{ {
// the Java text stuff freaks out in a variety of ways if it is // the Java text stuff freaks out in a variety of ways if it is asked to deal with the
// asked to deal with the empty string, so we fake blank labels by // empty string, so we fake blank labels by just using a space
// just using a space
if (StringUtil.isBlank(text)) { if (StringUtil.isBlank(text)) {
text = " "; text = " ";
} }
@@ -178,8 +167,8 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
// _text should contain the text without any tags // _text should contain the text without any tags
// _rawText will be null if there are no tags
_text = filterColors(text); _text = filterColors(text);
// _rawText will be null if there are no tags
_rawText = text.equals(_text) ? null : text; _rawText = text.equals(_text) ? null : text;
// if what we were passed contains escaped color tags, unescape them // if what we were passed contains escaped color tags, unescape them
@@ -193,12 +182,11 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Sets the font to be used by this label. If the font is not set, the * Sets the font to be used by this label. If the font is not set, the current font of the
* current font of the graphics context will be used. * graphics context will be used.
* *
* <p> This should be followed by a call to {@link #layout} before a * <p> This should be followed by a call to {@link #layout} before a call is made to {@link
* call is made to {@link #render} as this method invalidates the * #render} as this method invalidates the layout information.
* layout information.
*/ */
public void setFont (Font font) public void setFont (Font font)
{ {
@@ -215,9 +203,8 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Sets the color used to render the text. Setting the text color to * Sets the color used to render the text. Setting the text color to <code>null</code> will
* <code>null</code> will render the label in the graphics context * render the label in the graphics context color (which is the default).
* color (which is the default).
*/ */
public void setTextColor (Color color) public void setTextColor (Color color)
{ {
@@ -225,8 +212,7 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Returns the alternate color used to render the text's outline or * Returns the alternate color used to render the text's outline or shadow, if any.
* shadow, if any.
*/ */
public Color getAlternateColor () public Color getAlternateColor ()
{ {
@@ -234,10 +220,9 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Instructs the label to render the text with the specified alternate * Instructs the label to render the text with the specified alternate color when
* color when rendering. The text itself will be rendered in whatever * rendering. The text itself will be rendered in whatever color is currently set in the
* color is currently set in the graphics context, but the outline or * graphics context, but the outline or shadow (if any) will always be in the specified color.
* shadow (if any) will always be in the specified color.
*/ */
public void setAlternateColor (Color color) public void setAlternateColor (Color color)
{ {
@@ -253,14 +238,12 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Sets the alignment of the text within the label to either {@link * Sets the alignment of the text within the label to either {@link SwingConstants#LEFT},
* SwingConstants#LEFT}, {@link SwingConstants#RIGHT}, or {@link * {@link SwingConstants#RIGHT}, or {@link SwingConstants#CENTER}. The default alignment is
* SwingConstants#CENTER}. The default alignment is selected to be * selected to be appropriate for the locale of the text being rendered.
* appropriate for the locale of the text being rendered.
* *
* <p> This should be followed by a call to {@link #layout} before a * <p> This should be followed by a call to {@link #layout} before a call is made to {@link
* call is made to {@link #render} as this method invalidates the * #render} as this method invalidates the layout information.
* layout information.
*/ */
public void setAlignment (int align) public void setAlignment (int align)
{ {
@@ -268,13 +251,12 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Sets the style of the text within the label to one of the styles * Sets the style of the text within the label to one of the styles defined in {@link
* defined in {@link LabelStyleConstants}. Some styles can be combined * LabelStyleConstants}. Some styles can be combined together into a mask,
* together into a mask, ie. <code>BOLD|UNDERLINE</code>. * ie. <code>BOLD|UNDERLINE</code>.
* *
* <p> This should be followed by a call to {@link #layout} before a * <p> This should be followed by a call to {@link #layout} before a call is made to {@link
* call is made to {@link #render} as this method invalidates the * #render} as this method invalidates the layout information.
* layout information.
*/ */
public void setStyle (int style) public void setStyle (int style)
{ {
@@ -283,13 +265,11 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Instructs the label to attempt to achieve a balance between width * Instructs the label to attempt to achieve a balance between width and height that
* and height that approximates the golden ratio (width ~1.618 times * approximates the golden ratio (width ~1.618 times height).
* height).
* *
* <p> This should be followed by a call to {@link #layout} before a * <p> This should be followed by a call to {@link #layout} before a call is made to {@link
* call is made to {@link #render} as this method invalidates the * #render} as this method invalidates the layout information.
* layout information.
*/ */
public void setGoldenLayout () public void setGoldenLayout ()
{ {
@@ -300,15 +280,13 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Sets the target width for this label. Text will be wrapped to fit * Sets the target width for this label. Text will be wrapped to fit into this width, forcibly
* into this width, forcibly breaking words on character boundaries if * breaking words on character boundaries if a single word is too long to fit into the target
* a single word is too long to fit into the target width. Calling * width. Calling this method will annul any previously established target height as we must
* this method will annul any previously established target height as * have one degree of freedom in which to maneuver.
* we must have one degree of freedom in which to maneuver.
* *
* <p> This should be followed by a call to {@link #layout} before a * <p> This should be followed by a call to {@link #layout} before a call is made to {@link
* call is made to {@link #render} as this method invalidates the * #render} as this method invalidates the layout information.
* layout information.
*/ */
public void setTargetWidth (int targetWidth) public void setTargetWidth (int targetWidth)
{ {
@@ -322,17 +300,15 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Sets the target height for this label. A simple algorithm will be * Sets the target height for this label. A simple algorithm will be used to balance the width
* used to balance the width of the text in order that there are only * of the text in order that there are only as many lines of text as fit into the target
* as many lines of text as fit into the target height. If rendering * height. If rendering the label as a single line of text causes it to be taller than the
* the label as a single line of text causes it to be taller than the * target height, we simply render ourselves anyway. Calling this method will annul any
* target height, we simply render ourselves anyway. Calling this * previously established target width as we must have one degree of freedom in which to
* method will annul any previously established target width as we * maneuver.
* must have one degree of freedom in which to maneuver.
* *
* <p> This should be followed by a call to {@link #layout} before a * <p> This should be followed by a call to {@link #layout} before a call is made to {@link
* call is made to {@link #render} as this method invalidates the * #render} as this method invalidates the layout information.
* layout information.
*/ */
public void setTargetHeight (int targetHeight) public void setTargetHeight (int targetHeight)
{ {
@@ -363,8 +339,7 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Returns our computed dimensions. Only valid after a call to {@link * Returns our computed dimensions. Only valid after a call to {@link #layout}.
* #layout}.
*/ */
public Dimension getSize () public Dimension getSize ()
{ {
@@ -380,8 +355,7 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Calls {@link #layout(Graphics2D)} with the graphics context for the * Calls {@link #layout(Graphics2D)} with the graphics context for the given component.
* given component.
*/ */
public void layout (Component comp) public void layout (Component comp)
{ {
@@ -393,27 +367,24 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Requests that this label lay out its text, obtaining information * Requests that this label lay out its text, obtaining information from the supplied graphics
* from the supplied graphics context to do so. It is expected that * context to do so. It is expected that the label will be subsequently rendered in the same
* the label will be subsequently rendered in the same graphics * graphics context or at least one that is configured very similarly. If not, wackiness may
* context or at least one that is configured very similarly. If not, * ensue.
* wackiness may ensue.
*/ */
public void layout (Graphics2D gfx) public void layout (Graphics2D gfx)
{ {
FontRenderContext frc = gfx.getFontRenderContext(); FontRenderContext frc = gfx.getFontRenderContext();
ArrayList<Tuple<TextLayout,Rectangle2D>> layouts = null; List<Tuple<TextLayout,Rectangle2D>> layouts = null;
// if we have a target height, do some processing and convert that // if we have a target height, do some processing and convert that into a target width
// into a target width
if (_constraints.height > 0 || _constraints.width == -1) { if (_constraints.height > 0 || _constraints.width == -1) {
int targetHeight = _constraints.height; int targetHeight = _constraints.height;
// if we're approximating the golden ratio, target a height // if we're approximating the golden ratio, target a height that gets us near that
// that gets us near that ratio, then we can err on the side // ratio, then we can err on the side of being a bit wider which is generally nicer
// of being a bit wider which is generally nicer than being // than being taller (for those of us that don't speak verticall written languages,
// taller (for those of us that don't speak verticall written // anyway)
// languages, anyway)
if (_constraints.width == -1) { if (_constraints.width == -1) {
TextLayout layout = new TextLayout(textIterator(gfx), frc); TextLayout layout = new TextLayout(textIterator(gfx), frc);
Rectangle2D bounds = getBounds(layout); Rectangle2D bounds = getBounds(layout);
@@ -443,12 +414,11 @@ public class Label implements SwingConstants, LabelStyleConstants
if (lines > 1) { if (lines > 1) {
int targetWidth = (int)Math.round(getWidth(bounds) / lines); int targetWidth = (int)Math.round(getWidth(bounds) / lines);
// attempt to lay the text out in the specified width, // attempt to lay the text out in the specified width, incrementing by 10% each
// incrementing by 10% each time; limit our attempts to 10 // time; limit our attempts to 10 expansions to avoid infinite loops if something
// expansions to avoid infinite loops if something is fucked // is fucked
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
LineBreakMeasurer measurer = LineBreakMeasurer measurer = new LineBreakMeasurer(textIterator(gfx), frc);
new LineBreakMeasurer(textIterator(gfx), frc);
layouts = computeLines(measurer, targetWidth, _size, true); layouts = computeLines(measurer, targetWidth, _size, true);
if ((layouts != null) && (layouts.size() <= lines)) { if ((layouts != null) && (layouts.size() <= lines)) {
break; break;
@@ -463,14 +433,13 @@ public class Label implements SwingConstants, LabelStyleConstants
layouts = computeLines(measurer, _constraints.width, _size, false); layouts = computeLines(measurer, _constraints.width, _size, false);
} }
// if no constraint, or our constraining height puts us on one line // if no constraint, or our constraining height puts us on one line then layout on one line
// then layout on one line and call it good // and call it good
if (layouts == null) { if (layouts == null) {
TextLayout layout = new TextLayout(textIterator(gfx), frc); TextLayout layout = new TextLayout(textIterator(gfx), frc);
Rectangle2D bounds = getBounds(layout); Rectangle2D bounds = getBounds(layout);
// for some reason JDK1.3 on Linux chokes on setSize(double,double) // for some reason JDK1.3 on Linux chokes on setSize(double,double)
_size.setSize(Math.ceil(getWidth(bounds)), _size.setSize(Math.ceil(getWidth(bounds)), Math.ceil(getHeight(layout)));
Math.ceil(getHeight(layout)));
layouts = new ArrayList<Tuple<TextLayout,Rectangle2D>>(); layouts = new ArrayList<Tuple<TextLayout,Rectangle2D>>();
layouts.add(new Tuple<TextLayout,Rectangle2D>(layout, bounds)); layouts.add(new Tuple<TextLayout,Rectangle2D>(layout, bounds));
} }
@@ -492,25 +461,22 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Computes the lines of text for this label given the specified * Computes the lines of text for this label given the specified target width. The overall size
* target width. The overall size of the computed lines is stored into * of the computed lines is stored into the <code>size</code> parameter.
* the <code>size</code> parameter.
* *
* @return an {@link ArrayList} or null if <code>keepWordsWhole</code> * @return an {@link List} or null if <code>keepWordsWhole</code> was true and the lines could
* was true and the lines could not be layed out in the target width. * not be layed out in the target width.
*/ */
protected ArrayList<Tuple<TextLayout,Rectangle2D>> computeLines ( protected List<Tuple<TextLayout,Rectangle2D>> computeLines (
LineBreakMeasurer measurer, int targetWidth, Dimension size, LineBreakMeasurer measurer, int targetWidth, Dimension size, boolean keepWordsWhole)
boolean keepWordsWhole)
{ {
// start with a size of zero // start with a size of zero
double width = 0, height = 0; double width = 0, height = 0;
ArrayList<Tuple<TextLayout,Rectangle2D>> layouts = List<Tuple<TextLayout,Rectangle2D>> layouts = new ArrayList<Tuple<TextLayout,Rectangle2D>>();
new ArrayList<Tuple<TextLayout,Rectangle2D>>();
try { try {
// obtain our new dimensions by using a line break iterator to // obtain our new dimensions by using a line break iterator to lay out our text one
// lay out our text one line at a time // line at a time
TextLayout layout; TextLayout layout;
int lastposition = _text.length(); int lastposition = _text.length();
while (true) { while (true) {
@@ -518,8 +484,7 @@ public class Label implements SwingConstants, LabelStyleConstants
if (nextret == -1) { if (nextret == -1) {
nextret = lastposition; nextret = lastposition;
} }
layout = measurer.nextLayout( layout = measurer.nextLayout(targetWidth, nextret, keepWordsWhole);
targetWidth, nextret, keepWordsWhole);
if (layout == null) { if (layout == null) {
break; break;
} }
@@ -529,8 +494,8 @@ public class Label implements SwingConstants, LabelStyleConstants
layouts.add(new Tuple<TextLayout,Rectangle2D>(layout, bounds)); layouts.add(new Tuple<TextLayout,Rectangle2D>(layout, bounds));
} }
// fill in the computed size; for some reason JDK1.3 on Linux // fill in the computed size; for some reason JDK1.3 on Linux chokes on
// chokes on setSize(double,double) // setSize(double,double)
size.setSize(Math.ceil(width), Math.ceil(height)); size.setSize(Math.ceil(width), Math.ceil(height));
// this can only happen if keepWordsWhole is true // this can only happen if keepWordsWhole is true
@@ -546,17 +511,14 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Renders the layout at the specified position in the supplied * Renders the layout at the specified position in the supplied graphics context.
* graphics context.
*/ */
public void render (Graphics2D gfx, float x, float y) public void render (Graphics2D gfx, float x, float y)
{ {
// nothing to do if we haven't been laid out // nothing to do if we haven't been laid out
if (_layouts == null) { if (_layouts == null) {
log.warning(hashCode() + " Unlaid-out label asked to render " + log.warning(hashCode() + " Unlaid-out label asked to render [text=" + _text +
"[text=" + _text + /* ", last=" + _invalidator + */ "].");
// ", last=" + _invalidator +
"].");
return; return;
} }
@@ -581,21 +543,18 @@ public class Label implements SwingConstants, LabelStyleConstants
case CENTER: rx = x + extra/2; break; case CENTER: rx = x + extra/2; break;
} }
// shift over any lines that start with a font that extends // shift over any lines that start with a font that extends into negative x-land
// into negative x-land
rx += _leaders[i]; rx += _leaders[i];
// System.out.println(i + " x: " + x + " y: " + y + " rx: " + rx + // System.out.println(i + " x: " + x + " y: " + y + " rx: " + rx + " a: " + _align +
// " a: " + _align + " width: " + _size.width + // " width: " + _size.width + " lx: " + lbounds.getX() +
// " lx: " + lbounds.getX() + // " lwidth: " + getWidth(lbounds) + " extra: " + extra);
// " lwidth: " + getWidth(lbounds) +
// " extra: " + extra);
Color textColor; Color textColor;
if ((_style & OUTLINE) != 0) { if ((_style & OUTLINE) != 0) {
// render the outline using the hacky, but much nicer than // render the outline using the hacky, but much nicer than using "real" outlines
// using "real" outlines (via TextLayout.getOutline), method // (via TextLayout.getOutline), method
textColor = gfx.getColor(); textColor = gfx.getColor();
gfx.setColor(_alternateColor); gfx.setColor(_alternateColor);
_mainDraw = false; _mainDraw = false;
@@ -637,8 +596,7 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Constructs an attributed character iterator with our text and the * Constructs an attributed character iterator with our text and the appropriate font.
* appropriate font.
*/ */
protected AttributedCharacterIterator textIterator (Graphics2D gfx) protected AttributedCharacterIterator textIterator (Graphics2D gfx)
{ {
@@ -647,8 +605,7 @@ public class Label implements SwingConstants, LabelStyleConstants
HashMap<TextAttribute,Object> map = new HashMap<TextAttribute,Object>(); HashMap<TextAttribute,Object> map = new HashMap<TextAttribute,Object>();
map.put(TextAttribute.FONT, font); map.put(TextAttribute.FONT, font);
if ((_style & UNDERLINE) != 0) { if ((_style & UNDERLINE) != 0) {
map.put(TextAttribute.UNDERLINE, map.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_ONE_PIXEL);
TextAttribute.UNDERLINE_LOW_ONE_PIXEL);
} }
AttributedString text = new AttributedString(_text, map); AttributedString text = new AttributedString(_text, map);
@@ -670,8 +627,7 @@ public class Label implements SwingConstants, LabelStyleConstants
// color the segment just passed // color the segment just passed
endSeg += m.start(); endSeg += m.start();
if (lastColor != null) { if (lastColor != null) {
text.addAttribute(TextAttribute.FOREGROUND, lastColor, text.addAttribute(TextAttribute.FOREGROUND, lastColor, startSeg, endSeg);
startSeg, endSeg);
} }
// parse the tag: start or end a color // parse the tag: start or end a color
@@ -679,32 +635,25 @@ public class Label implements SwingConstants, LabelStyleConstants
if ("x".equalsIgnoreCase(group)) { if ("x".equalsIgnoreCase(group)) {
lastColor = null; lastColor = null;
} else { } else {
try { lastColor = new Color(Integer.parseInt(group, 16));
lastColor = new Color(Integer.parseInt(group, 16));
} catch (NumberFormatException nfe) {
log.warning("This shouldn't be possible, the regex " +
"is precise [badcolor=" + group + "].");
}
} }
// prepare for the next segment // prepare for the next segment
startSeg = endSeg; startSeg = endSeg;
// Subtract the end of the segment from endSeg // Subtract the end of the segment from endSeg so that when we add the start of the
// so that when we add the start of the next match we have // next match we have actually added the length of the characters in between.
// actually added the length of the characters in between.
endSeg -= m.end(); endSeg -= m.end();
} }
// apply any final color to the tail segment // apply any final color to the tail segment
if (lastColor != null) { if (lastColor != null) {
text.addAttribute(TextAttribute.FOREGROUND, lastColor, text.addAttribute(TextAttribute.FOREGROUND, lastColor, startSeg, _text.length());
startSeg, _text.length());
} }
} }
} }
/** /**
* Computes the total width of a {@link TextLayout} given bounds * Computes the total width of a {@link TextLayout} given bounds returned from a call to {@link
* returned from a call to {@link TextLayout#getBounds}. * TextLayout#getBounds}.
*/ */
protected double getWidth (Rectangle2D laybounds) protected double getWidth (Rectangle2D laybounds)
{ {
@@ -720,8 +669,8 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Gets the bounds of the supplied text layout in a way that works * Gets the bounds of the supplied text layout in a way that works around the various
* around the various befuckeries that currently happen on the Mac. * befuckeries that currently happen on the Mac.
*/ */
protected Rectangle2D getBounds (TextLayout layout) protected Rectangle2D getBounds (TextLayout layout)
{ {
@@ -733,14 +682,12 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Computes the height based on the leading, ascent and descent rather * Computes the height based on the leading, ascent and descent rather than what the layout
* than what the layout reports via <code>getBounds()</code> which * reports via <code>getBounds()</code> which rarely seems to have any bearing on reality.
* rarely seems to have any bearing on reality.
*/ */
protected float getHeight (TextLayout layout) protected float getHeight (TextLayout layout)
{ {
float height = layout.getLeading() + layout.getAscent() + float height = layout.getLeading() + layout.getAscent() + layout.getDescent();
layout.getDescent();
if ((_style & OUTLINE) != 0) { if ((_style & OUTLINE) != 0) {
height += 2; height += 2;
} else if ((_style & SHADOW) != 0) { } else if ((_style & SHADOW) != 0) {
@@ -750,8 +697,8 @@ public class Label implements SwingConstants, LabelStyleConstants
} }
/** /**
* Called when the label is changed in such a way that it must be * Called when the label is changed in such a way that it must be relaid out before again being
* relaid out before again being rendered. * rendered.
*/ */
protected void invalidate (String where) protected void invalidate (String where)
{ {
@@ -777,17 +724,15 @@ public class Label implements SwingConstants, LabelStyleConstants
/** Our calculated size. */ /** Our calculated size. */
protected Dimension _size = new Dimension(); protected Dimension _size = new Dimension();
/** Some fonts (God bless 'em) extend to the left of the position at /** Some fonts (God bless 'em) extend to the left of the position at which you request that
* which you request that they be rendered. We opt to push such lines * they be rendered. We opt to push such lines to the right sufficiently that they line up with
* to the right sufficiently that they line up with the rest of the * the rest of the lines (perhaps not the typographically ideal thing to do, but we're in
* lines (perhaps not the typographically ideal thing to do, but we're * computer land and when we say our bounds are (0, 0, width, height) we damned well better not
* in computer land and when we say our bounds are (0, 0, width, * render outside those bounds, which these wonderful fonts are choosing to do). */
* height) we damned well better not render outside those bounds,
* which these wonderful fonts are choosing to do). */
protected float[] _leaders; protected float[] _leaders;
/** The font we use when laying out and rendering out text, or null if /** The font we use when laying out and rendering out text, or null if we're to use the default
* we're to use the default font. */ * font. */
protected Font _font; protected Font _font;
/** Formatted text layout instances that contain each line of text. */ /** Formatted text layout instances that contain each line of text. */
@@ -796,17 +741,16 @@ public class Label implements SwingConstants, LabelStyleConstants
/** Formatted text layout instances that contain each line of text. */ /** Formatted text layout instances that contain each line of text. */
protected Rectangle2D[] _lbounds; protected Rectangle2D[] _lbounds;
/** The color in which to render the text outline or shadow if we're /** The color in which to render the text outline or shadow if we're rendering in outline or
* rendering in outline or shadow mode. */ * shadow mode. */
protected Color _alternateColor = null; protected Color _alternateColor = null;
/** The color in which to render the text or null if the text should /** The color in which to render the text or null if the text should be rendered with the
* be rendered with the graphics context color. */ * graphics context color. */
protected Color _textColor = null; protected Color _textColor = null;
/** Will be true only when we're drawing a textlayout for the "main" /** Will be true only when we're drawing a textlayout for the "main" portion of the label. If
* portion of the label. If we are in OUTLINE mode, we draw each layout * we are in OUTLINE mode, we draw each layout 9 times: the last one is the only main one. */
* 9 times: the last one is the only main one. */
protected boolean _mainDraw = true; protected boolean _mainDraw = true;
// /** Used for debugging. */ // /** Used for debugging. */
@@ -814,4 +758,7 @@ public class Label implements SwingConstants, LabelStyleConstants
/** An approximation of the golden ratio. */ /** An approximation of the golden ratio. */
protected static final double GOLDEN_RATIO = 1.618034; protected static final double GOLDEN_RATIO = 1.618034;
/** Used by {@link #unescapeColors}. */
protected static final Pattern ESCAPED_PATTERN = Pattern.compile("#''([Xx]|[0-9A-Fa-f]{6}+)");
} }