StyledParagraphpublic final class StyledParagraph extends Object This class stores Font, GraphicAttribute, and Decoration intervals
on a paragraph of styled text.
Currently, this class is optimized for a small number of intervals
(preferrably 1). |
Fields Summary |
---|
private int | length | private Decoration | decoration | private Object | font | private Vector | decorations | int[] | decorationStarts | private Vector | fonts | int[] | fontStarts | private static int | INITIAL_SIZE |
Constructors Summary |
---|
public StyledParagraph(AttributedCharacterIterator aci, char[] chars)Create a new StyledParagraph over the given styled text.
int start = aci.getBeginIndex();
int end = aci.getEndIndex();
length = end - start;
int index = start;
aci.first();
do {
final int nextRunStart = aci.getRunLimit();
final int localIndex = index-start;
Map attributes = aci.getAttributes();
attributes = addInputMethodAttrs(attributes);
Decoration d = Decoration.getDecoration(attributes);
addDecoration(d, localIndex);
Object f = getGraphicOrFont(attributes);
if (f == null) {
addFonts(chars, attributes, localIndex, nextRunStart-start);
}
else {
addFont(f, localIndex);
}
aci.setIndex(nextRunStart);
index = nextRunStart;
} while (index < end);
// Add extra entries to starts arrays with the length
// of the paragraph. 'this' is used as a dummy value
// in the Vector.
if (decorations != null) {
decorationStarts = addToVector(this, length, decorations, decorationStarts);
}
if (fonts != null) {
fontStarts = addToVector(this, length, fonts, fontStarts);
}
|
Methods Summary |
---|
private void | addDecoration(sun.font.Decoration d, int index)Add a new Decoration run with the given Decoration at the
given index.
if (decorations != null) {
decorationStarts = addToVector(d,
index,
decorations,
decorationStarts);
}
else if (decoration == null) {
decoration = d;
}
else {
if (!decoration.equals(d)) {
decorations = new Vector(INITIAL_SIZE);
decorations.addElement(decoration);
decorations.addElement(d);
decorationStarts = new int[INITIAL_SIZE];
decorationStarts[0] = 0;
decorationStarts[1] = index;
}
}
| private void | addFont(java.lang.Object f, int index)Add a new Font/GraphicAttribute run with the given object at the
given index.
if (fonts != null) {
fontStarts = addToVector(f, index, fonts, fontStarts);
}
else if (font == null) {
font = f;
}
else {
if (!font.equals(f)) {
fonts = new Vector(INITIAL_SIZE);
fonts.addElement(font);
fonts.addElement(f);
fontStarts = new int[INITIAL_SIZE];
fontStarts[0] = 0;
fontStarts[1] = index;
}
}
| private void | addFonts(char[] chars, java.util.Map attributes, int start, int limit)Resolve the given chars into Fonts using FontResolver, then add
font runs for each.
FontResolver resolver = FontResolver.getInstance();
CodePointIterator iter = CodePointIterator.create(chars, start, limit);
for (int runStart = iter.charIndex(); runStart < limit; runStart = iter.charIndex()) {
int fontIndex = resolver.nextFontRunIndex(iter);
addFont(resolver.getFont(fontIndex, attributes), runStart);
}
| static java.util.Map | addInputMethodAttrs(java.util.Map oldStyles)Return a Map with entries from oldStyles, as well as input
method entries, if any.
Object value = oldStyles.get(TextAttribute.INPUT_METHOD_HIGHLIGHT);
try {
if (value != null) {
if (value instanceof Annotation) {
value = ((Annotation)value).getValue();
}
InputMethodHighlight hl;
hl = (InputMethodHighlight) value;
Map imStyles = null;
try {
imStyles = hl.getStyle();
} catch (NoSuchMethodError e) {
}
if (imStyles == null) {
Toolkit tk = Toolkit.getDefaultToolkit();
imStyles = tk.mapInputMethodHighlight(hl);
}
if (imStyles != null) {
HashMap newStyles = new HashMap(5, (float)0.9);
newStyles.putAll(oldStyles);
newStyles.putAll(imStyles);
return newStyles;
}
}
}
catch(ClassCastException e) {
}
return oldStyles;
| private static int[] | addToVector(java.lang.Object obj, int index, java.util.Vector v, int[] starts)Append the given Object to the given Vector. Add
the given index to the given starts array. If the
starts array does not have room for the index, a
new array is created and returned.
if (!v.lastElement().equals(obj)) {
v.addElement(obj);
int count = v.size();
if (starts.length == count) {
int[] temp = new int[starts.length*2];
System.arraycopy(starts, 0, temp, 0, starts.length);
starts = temp;
}
starts[count-1] = index;
}
return starts;
| public static java.awt.font.StyledParagraph | deleteChar(java.text.AttributedCharacterIterator aci, char[] chars, int deletePos, java.awt.font.StyledParagraph oldParagraph)Return a StyledParagraph reflecting the insertion of a single character
into the text. This method will attempt to reuse the given paragraph,
but may create a new paragraph.
// We will reuse oldParagraph unless there was a length-1 run
// at deletePos. We could do more work and check the individual
// Font and Decoration runs, but we don't right now...
deletePos -= aci.getBeginIndex();
if (oldParagraph.decorations == null && oldParagraph.fonts == null) {
oldParagraph.length -= 1;
return oldParagraph;
}
if (oldParagraph.getRunLimit(deletePos) == deletePos+1) {
if (deletePos == 0 || oldParagraph.getRunLimit(deletePos-1) == deletePos) {
return new StyledParagraph(aci, chars);
}
}
oldParagraph.length -= 1;
if (oldParagraph.decorations != null) {
deleteFrom(deletePos,
oldParagraph.decorationStarts,
oldParagraph.decorations.size());
}
if (oldParagraph.fonts != null) {
deleteFrom(deletePos,
oldParagraph.fontStarts,
oldParagraph.fonts.size());
}
return oldParagraph;
| private static void | deleteFrom(int deleteAt, int[] starts, int numStarts)Adjust indices in starts to reflect a deletion after deleteAt.
Any index in starts greater than deleteAt will be increased by 1.
It is the caller's responsibility to make sure that no 0-length
runs result.
while (starts[--numStarts] > deleteAt) {
starts[numStarts] -= 1;
}
| private static int | findRunContaining(int index, int[] starts)Return i such that starts[i] <= index < starts[i+1]. starts
must be in increasing order, with at least one element greater
than index.
for (int i=1; true; i++) {
if (starts[i] > index) {
return i-1;
}
}
| public sun.font.Decoration | getDecorationAt(int index)Return the Decoration in effect at the given index.
if (index < 0 || index >= length) {
throw new IllegalArgumentException("index out of range");
}
if (decorations == null) {
return decoration;
}
int run = findRunContaining(index, decorationStarts);
return (Decoration) decorations.elementAt(run);
| public java.lang.Object | getFontOrGraphicAt(int index)Return the Font or GraphicAttribute in effect at the given index.
The client must test the type of the return value to determine what
it is.
if (index < 0 || index >= length) {
throw new IllegalArgumentException("index out of range");
}
if (fonts == null) {
return font;
}
int run = findRunContaining(index, fontStarts);
return fonts.elementAt(run);
| private static java.lang.Object | getGraphicOrFont(java.util.Map attributes)Extract a GraphicAttribute or Font from the given attributes.
If attributes does not contain a GraphicAttribute, Font, or
Font family entry this method returns null.
Object value = attributes.get(TextAttribute.CHAR_REPLACEMENT);
if (value != null) {
return value;
}
value = attributes.get(TextAttribute.FONT);
if (value != null) {
return value;
}
if (attributes.get(TextAttribute.FAMILY) != null) {
return Font.getFont(attributes);
}
else {
return null;
}
| public int | getRunLimit(int index)Return the index at which there is a different Font, GraphicAttribute, or
Dcoration than at the given index.
if (index < 0 || index >= length) {
throw new IllegalArgumentException("index out of range");
}
int limit1 = length;
if (decorations != null) {
int run = findRunContaining(index, decorationStarts);
limit1 = decorationStarts[run+1];
}
int limit2 = length;
if (fonts != null) {
int run = findRunContaining(index, fontStarts);
limit2 = fontStarts[run+1];
}
return Math.min(limit1, limit2);
| public static java.awt.font.StyledParagraph | insertChar(java.text.AttributedCharacterIterator aci, char[] chars, int insertPos, java.awt.font.StyledParagraph oldParagraph)Return a StyledParagraph reflecting the insertion of a single character
into the text. This method will attempt to reuse the given paragraph,
but may create a new paragraph.
// If the styles at insertPos match those at insertPos-1,
// oldParagraph will be reused. Otherwise we create a new
// paragraph.
char ch = aci.setIndex(insertPos);
int relativePos = Math.max(insertPos - aci.getBeginIndex() - 1, 0);
Map attributes = addInputMethodAttrs(aci.getAttributes());
Decoration d = Decoration.getDecoration(attributes);
if (!oldParagraph.getDecorationAt(relativePos).equals(d)) {
return new StyledParagraph(aci, chars);
}
Object f = getGraphicOrFont(attributes);
if (f == null) {
FontResolver resolver = FontResolver.getInstance();
int fontIndex = resolver.getFontIndex(ch);
f = resolver.getFont(fontIndex, attributes);
}
if (!oldParagraph.getFontOrGraphicAt(relativePos).equals(f)) {
return new StyledParagraph(aci, chars);
}
// insert into existing paragraph
oldParagraph.length += 1;
if (oldParagraph.decorations != null) {
insertInto(relativePos,
oldParagraph.decorationStarts,
oldParagraph.decorations.size());
}
if (oldParagraph.fonts != null) {
insertInto(relativePos,
oldParagraph.fontStarts,
oldParagraph.fonts.size());
}
return oldParagraph;
| private static void | insertInto(int pos, int[] starts, int numStarts)Adjust indices in starts to reflect an insertion after pos.
Any index in starts greater than pos will be increased by 1.
while (starts[--numStarts] > pos) {
starts[numStarts] += 1;
}
|
|