@Override public void write(Text text, Writer writer) throws IOException { AttributedCharacterIterator iterator = text.getIterator(); Entry<Attribute, Object> lastAttribute = null; while (true) { if (iterator.getIndex() == iterator.getEndIndex()) { break; } Entry<Attribute, Object> entry = getAttribute(iterator); if (!Objects.equals(entry, lastAttribute)) { endEntity(lastAttribute, writer); beginEntity(entry, writer); } writer.write(iterator.current()); lastAttribute = entry; iterator.next(); } endEntity(lastAttribute, writer); }
/** * Tell the component to commit all of the characters in the string to the current * text view. This effectively wipes out any text in progress. */ private synchronized void insertText(String aString) { AttributedString attribString = new AttributedString(aString); // Set locale information on the new string. attribString.addAttribute(Attribute.LANGUAGE, getLocale(), 0, aString.length()); TextHitInfo theCaret = TextHitInfo.afterOffset(aString.length() - 1); InputMethodEvent event = new InputMethodEvent(fAwtFocussedComponent, InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, attribString.getIterator(), aString.length(), theCaret, theCaret); LWCToolkit.postEvent(LWCToolkit.targetToAppContext(fAwtFocussedComponent), event); fCurrentText = null; fCurrentTextAsString = null; fCurrentTextLength = 0; }
/** * Tell the component to commit all of the characters in the string to the current * text view. This effectively wipes out any text in progress. */ synchronized private void insertText(String aString) { AttributedString attribString = new AttributedString(aString); // Set locale information on the new string. attribString.addAttribute(Attribute.LANGUAGE, getLocale(), 0, aString.length()); TextHitInfo theCaret = TextHitInfo.afterOffset(aString.length() - 1); InputMethodEvent event = new InputMethodEvent(fAwtFocussedComponent, InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, attribString.getIterator(), aString.length(), theCaret, theCaret); LWCToolkit.postEvent(LWCToolkit.targetToAppContext(fAwtFocussedComponent), event); fCurrentText = null; fCurrentTextAsString = null; fCurrentTextLength = 0; }
public static AttributeValues fromSerializableHashtable(Hashtable<Object, Object> ht) { AttributeValues result = new AttributeValues(); if (ht != null && !ht.isEmpty()) { for (Map.Entry<Object, Object> e: ht.entrySet()) { Object key = e.getKey(); Object val = e.getValue(); if (key.equals(DEFINED_KEY)) { result.defineAll(((Integer)val).intValue()); } else { try { EAttribute ea = EAttribute.forAttribute((Attribute)key); if (ea != null) { result.set(ea, val); } } catch (ClassCastException ex) { } } } } return result; }
private void beginEntity(Entry<Attribute, Object> entry, Writer writer) throws IOException { if (entry == null) { return; } Attribute entity = entry.getKey(); if (entity == TextEntity.BOLD) { writer.write("<b>"); } else if (entity == TextEntity.ITALIC) { writer.write("<i>"); } else if (entity == TextEntity.CODE) { writer.write("<code>"); } else if (entity == TextEntity.CODE_BLOCK) { writer.write("<pre>"); } else if (entity == TextEntity.LINK) { writer.write("<a href=\"" + escape(entry.getValue().toString()) + "\">"); } else if (entity == TextEntity.TEXT_MENTION) { User user = (User) entry.getValue(); writer.write("<a href=\"" + escape(TextEntity.TEXT_MENTION_LINK) + user.getId() + "\">"); } }
private static final void checkIteratorAttribute(AttributedCharacterIterator iterator, int index, Attribute key, Object expectedValue) throws Exception { iterator.setIndex(index); Object value = iterator.getAttribute(key); if (!((expectedValue == null && value == null) || (expectedValue != null && expectedValue.equals(value)))) { throwException(iterator, "iterator returns wrong attribute value - " + value + " instead of " + expectedValue); } value = iterator.getAttributes().get(key); if (!((expectedValue == null && value == null) || (expectedValue != null && expectedValue.equals(value)))) { throwException(iterator, "iterator's map returns wrong attribute value - " + value + " instead of " + expectedValue); } }
private void beginEntity(Entry<Attribute, Object> entry, Writer writer) throws IOException { if (entry == null) { return; } Attribute entity = entry.getKey(); if (entity == TextEntity.BOLD) { writer.write('*'); } else if (entity == TextEntity.ITALIC) { writer.write('_'); } else if (entity == TextEntity.CODE) { writer.write('`'); } else if (entity == TextEntity.CODE_BLOCK) { writer.write("```"); } else if (entity == TextEntity.LINK || entity == TextEntity.TEXT_MENTION) { writer.write("["); } }
public int getRunStart(Attribute attribute) { if (currentRunStart == beginIndex || currentRunIndex == -1) { return currentRunStart; } else { Object value = getAttribute(attribute); int runStart = currentRunStart; int runIndex = currentRunIndex; while (runStart > beginIndex && valuesMatch(value, AttributedString.this.getAttribute(attribute, runIndex - 1))) { runIndex--; runStart = runStarts[runIndex]; } if (runStart < beginIndex) { runStart = beginIndex; } return runStart; } }
/** * Selects the passed in field, returning true if it is found, * false otherwise. */ private boolean select(final JFormattedTextField ftf, final AttributedCharacterIterator iterator, final DateFormat.Field field) { final int max = ftf.getDocument().getLength(); iterator.first(); do { final Map<Attribute,Object> attrs = iterator.getAttributes(); if (attrs == null || !attrs.containsKey(field)) continue; final int start = iterator.getRunStart(field); final int end = iterator.getRunLimit(field); if (start != -1 && end != -1 && start <= max && end <= max) { ftf.select(start, end); } return true; } while (iterator.next() != CharacterIterator.DONE); return false; }
/** * Constructs a {@code TextLayout} from an iterator over styled text. * <p> * The iterator must specify a single paragraph of text because an * entire paragraph is required for the bidirectional * algorithm. * @param text the styled text to display * @param frc contains information about a graphics device which is needed * to measure the text correctly. * Text measurements can vary slightly depending on the * device resolution, and attributes such as antialiasing. This * parameter does not specify a translation between the * {@code TextLayout} and user space. */ public TextLayout(AttributedCharacterIterator text, FontRenderContext frc) { if (text == null) { throw new IllegalArgumentException("Null iterator passed to TextLayout constructor."); } int start = text.getBeginIndex(); int limit = text.getEndIndex(); if (start == limit) { throw new IllegalArgumentException("Zero length iterator passed to TextLayout constructor."); } int len = limit - start; text.first(); char[] chars = new char[len]; int n = 0; for (char c = text.first(); c != CharacterIterator.DONE; c = text.next()) { chars[n++] = c; } text.first(); if (text.getRunLimit() == limit) { Map<? extends Attribute, ?> attributes = text.getAttributes(); Font font = singleFont(chars, 0, len, attributes); if (font != null) { fastInit(chars, font, attributes, frc); return; } } standardInit(text, chars, frc); }
/** * Initialize the paragraph-specific data. */ private void paragraphInit(byte aBaseline, CoreMetrics lm, Map<? extends Attribute, ?> paragraphAttrs, char[] text) { baseline = aBaseline; // normalize to current baseline baselineOffsets = TextLine.getNormalizedOffsets(lm.baselineOffsets, baseline); justifyRatio = AttributeValues.getJustification(paragraphAttrs); NumericShaper shaper = AttributeValues.getNumericShaping(paragraphAttrs); if (shaper != null) { shaper.shape(text, 0, text.length); } }
/** * Constructs a <code>TextLayout</code> from an iterator over styled text. * <p> * The iterator must specify a single paragraph of text because an * entire paragraph is required for the bidirectional * algorithm. * @param text the styled text to display * @param frc contains information about a graphics device which is needed * to measure the text correctly. * Text measurements can vary slightly depending on the * device resolution, and attributes such as antialiasing. This * parameter does not specify a translation between the * <code>TextLayout</code> and user space. */ public TextLayout(AttributedCharacterIterator text, FontRenderContext frc) { if (text == null) { throw new IllegalArgumentException("Null iterator passed to TextLayout constructor."); } int start = text.getBeginIndex(); int limit = text.getEndIndex(); if (start == limit) { throw new IllegalArgumentException("Zero length iterator passed to TextLayout constructor."); } int len = limit - start; text.first(); char[] chars = new char[len]; int n = 0; for (char c = text.first(); c != CharacterIterator.DONE; c = text.next()) { chars[n++] = c; } text.first(); if (text.getRunLimit() == limit) { Map<? extends Attribute, ?> attributes = text.getAttributes(); Font font = singleFont(chars, 0, len, attributes); if (font != null) { fastInit(chars, font, attributes, frc); return; } } standardInit(text, chars, frc); }
private void fastInit(char[] chars, Font font, Map<? extends Attribute, ?> attrs, FontRenderContext frc) { // Object vf = attrs.get(TextAttribute.ORIENTATION); // isVerticalLine = TextAttribute.ORIENTATION_VERTICAL.equals(vf); isVerticalLine = false; LineMetrics lm = font.getLineMetrics(chars, 0, chars.length, frc); CoreMetrics cm = CoreMetrics.get(lm); byte glyphBaseline = (byte) cm.baselineIndex; if (attrs == null) { baseline = glyphBaseline; baselineOffsets = cm.baselineOffsets; justifyRatio = 1.0f; } else { paragraphInit(glyphBaseline, cm, attrs, chars); } characterCount = chars.length; textLine = TextLine.fastCreateTextLine(frc, chars, font, cm, attrs); }
/** * 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. */ private static Object getGraphicOrFont( Map<? extends Attribute, ?> attributes) { 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; } }
private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, Attribute key, int[] expectedLimits) throws Exception { int previous = 0; char c = iterator.first(); for (int i = 0; i < expectedLimits.length; i++) { if (iterator.getRunStart(key) != previous || iterator.getRunLimit(key) != expectedLimits[i]) { throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart(key) + ", " + iterator.getRunLimit(key) + " for key " + key); } previous = expectedLimits[i]; c = iterator.setIndex(previous); } if (c != CharacterIterator.DONE) { throwException(iterator, "iterator's run sequence doesn't end with DONE"); } }
public int getRunStart(Set<? extends Attribute> attributes) { if (currentRunStart == beginIndex || currentRunIndex == -1) { return currentRunStart; } else { int runStart = currentRunStart; int runIndex = currentRunIndex; while (runStart > beginIndex && AttributedString.this.attributeValuesMatch(attributes, currentRunIndex, runIndex - 1)) { runIndex--; runStart = runStarts[runIndex]; } if (runStart < beginIndex) { runStart = beginIndex; } return runStart; } }
public int getRunLimit(Set<? extends Attribute> attributes) { if (currentRunLimit == endIndex || currentRunIndex == -1) { return currentRunLimit; } else { int runLimit = currentRunLimit; int runIndex = currentRunIndex; while (runLimit < endIndex && AttributedString.this.attributeValuesMatch(attributes, currentRunIndex, runIndex + 1)) { runIndex++; runLimit = runIndex < runCount - 1 ? runStarts[runIndex + 1] : endIndex; } if (runLimit > endIndex) { runLimit = endIndex; } return runLimit; } }
public AttributeValues merge(Map<? extends Attribute, ?>map, int mask) { if (map instanceof AttributeMap && ((AttributeMap) map).getValues() != null) { merge(((AttributeMap)map).getValues(), mask); } else if (map != null && !map.isEmpty()) { for (Map.Entry<? extends Attribute, ?> e: map.entrySet()) { try { EAttribute ea = EAttribute.forAttribute(e.getKey()); if (ea!= null && (mask & ea.mask) != 0) { set(ea, e.getValue()); } } catch (ClassCastException cce) { // IGNORED } } } return this; }
public Set<Map.Entry<Attribute, Object>> entrySet() { HashSet<Map.Entry<Attribute, Object>> set = new HashSet<>(); synchronized (AttributedString.this) { int size = runAttributes[runIndex].size(); for (int i = 0; i < size; i++) { Attribute key = runAttributes[runIndex].get(i); Object value = runAttributeValues[runIndex].get(i); if (value instanceof Annotation) { value = AttributedString.this.getAttributeCheckRange(key, runIndex, beginIndex, endIndex); if (value == null) { continue; } } Map.Entry<Attribute, Object> entry = new AttributeEntry(key, value); set.add(entry); } } return set; }
/** * Constructs a <code>TextLayout</code> from a <code>String</code> * and an attribute set. * <p> * All the text is styled using the provided attributes. * <p> * <code>string</code> must specify a single paragraph of text because an * entire paragraph is required for the bidirectional algorithm. * @param string the text to display * @param attributes the attributes used to style the text * @param frc contains information about a graphics device which is needed * to measure the text correctly. * Text measurements can vary slightly depending on the * device resolution, and attributes such as antialiasing. This * parameter does not specify a translation between the * <code>TextLayout</code> and user space. */ public TextLayout(String string, Map<? extends Attribute,?> attributes, FontRenderContext frc) { if (string == null) { throw new IllegalArgumentException("Null string passed to TextLayout constructor."); } if (attributes == null) { throw new IllegalArgumentException("Null map passed to TextLayout constructor."); } if (string.length() == 0) { throw new IllegalArgumentException("Zero length string passed to TextLayout constructor."); } char[] text = string.toCharArray(); Font font = singleFont(text, 0, text.length, attributes); if (font != null) { fastInit(text, font, attributes, frc); } else { AttributedString as = new AttributedString(string, attributes); standardInit(as.getIterator(), text, frc); } }
public int getRunLimit(Attribute attribute) { if (currentRunLimit == endIndex || currentRunIndex == -1) { return currentRunLimit; } else { Object value = getAttribute(attribute); int runLimit = currentRunLimit; int runIndex = currentRunIndex; while (runLimit < endIndex && valuesMatch(value, AttributedString.this.getAttribute(attribute, runIndex + 1))) { runIndex++; runLimit = runIndex < runCount - 1 ? runStarts[runIndex + 1] : endIndex; } if (runLimit > endIndex) { runLimit = endIndex; } return runLimit; } }
public AttributedCharacterIterator cancelLatestCommittedText( Attribute[] attributes) { Document doc = getDocument(); if ((doc != null) && (latestCommittedTextStart != null) && (!latestCommittedTextStart.equals(latestCommittedTextEnd))) { try { int startIndex = latestCommittedTextStart.getOffset(); int endIndex = latestCommittedTextEnd.getOffset(); String latestCommittedText = doc.getText(startIndex, endIndex - startIndex); doc.remove(startIndex, endIndex - startIndex); return new AttributedString(latestCommittedText).getIterator(); } catch (BadLocationException ble) {} } return null; }
private static final void dumpIterator(AttributedCharacterIterator iterator) { Set attributeKeys = iterator.getAllAttributeKeys(); System.out.print("All attributes: "); Iterator keyIterator = attributeKeys.iterator(); while (keyIterator.hasNext()) { Attribute key = (Attribute) keyIterator.next(); System.out.print(key); } for(char c = iterator.first(); c != CharacterIterator.DONE; c = iterator.next()) { if (iterator.getIndex() == iterator.getBeginIndex() || iterator.getIndex() == iterator.getRunStart()) { System.out.println(); Map attributes = iterator.getAttributes(); Set entries = attributes.entrySet(); Iterator attributeIterator = entries.iterator(); while (attributeIterator.hasNext()) { Map.Entry entry = (Map.Entry) attributeIterator.next(); System.out.print("<" + entry.getKey() + ": " + entry.getValue() + ">"); } } System.out.print(" "); System.out.print(c); } System.out.println(); System.out.println("done"); System.out.println(); }
/** * Returns the <code>Format.Field</code> constants associated with * the text at <code>offset</code>. If <code>offset</code> is not * a valid location into the current text, this will return an * empty array. * * @param offset offset into text to be examined * @return Format.Field constants associated with the text at the * given position. */ public Format.Field[] getFields(int offset) { if (getAllowsInvalid()) { // This will work if the currently edited value is valid. updateMask(); } Map<Attribute, Object> attrs = getAttributes(offset); if (attrs != null && attrs.size() > 0) { ArrayList<Attribute> al = new ArrayList<Attribute>(); al.addAll(attrs.keySet()); return al.toArray(EMPTY_FIELD_ARRAY); } return EMPTY_FIELD_ARRAY; }
private static Map<Attribute,Object> translate(AttributeSet attrs, Map<AttributeSet,Map<Attribute,Object>> cache) { Map<Attribute,Object> textAttrs = cache.get(attrs); if (textAttrs == null) { textAttrs = AttributedCharSequence.translate(attrs); cache.put(attrs, textAttrs); } return textAttrs; }
/** * Create a new StyledParagraph over the given styled text. * @param aci an iterator over the text * @param chars the characters extracted from aci */ public StyledParagraph(AttributedCharacterIterator aci, char[] chars) { 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<? extends Attribute, ?> 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); } }
/** * Updates the interal bitset from <code>iterator</code>. This will * set <code>validMask</code> to true if <code>iterator</code> is * non-null. */ private void updateMask(AttributedCharacterIterator iterator) { if (iterator != null) { validMask = true; this.iterator = iterator; // Update the literal mask if (literalMask == null) { literalMask = new BitSet(); } else { for (int counter = literalMask.length() - 1; counter >= 0; counter--) { literalMask.clear(counter); } } iterator.first(); while (iterator.current() != CharacterIterator.DONE) { Map<Attribute,Object> attributes = iterator.getAttributes(); boolean set = isLiteral(attributes); int start = iterator.getIndex(); int end = iterator.getRunLimit(); while (start < end) { if (set) { literalMask.set(start); } else { literalMask.clear(start); } start++; } iterator.setIndex(start); } } }
void setText(CharSequence text, Map<Attribute,Object> defaultTextAttrs) { this.text = text; int endIndex = endIndex(); int textLen = text.length(); if (endIndex > textLen) { throw new IllegalStateException("endIndex=" + endIndex + " > text.length()=" + textLen); // NOI18N } if (endIndex < textLen) { addTextRun(textLen, defaultTextAttrs); } ((ArrayList)textRuns).trimToSize(); }
@Override public Map<Attribute, Object> getAttributes() { if (textRunIndex >= textRuns.size()) { return Collections.emptyMap(); } return textRuns.get(textRunIndex).attrs; }
public static AffineTransform getCharTransform(Map<?, ?> map) { if (map != null) { AttributeValues av = null; if (map instanceof AttributeMap && ((AttributeMap) map).getValues() != null) { av = ((AttributeMap)map).getValues(); } else if (map.get(TextAttribute.TRANSFORM) != null) { av = AttributeValues.fromMap((Map<Attribute, ?>)map); // yuck } if (av != null) { return av.charTransform; } } return null; }
public static void main(String[] args) throws Exception { testSerializationCycle(Attribute.LANGUAGE); testSerializationCycle(TextAttribute.INPUT_METHOD_HIGHLIGHT); boolean gotException = false; Attribute result = null; try { result = doSerializationCycle(FakeAttribute.LANGUAGE); } catch (Throwable e) { gotException = true; } if (!gotException) { throw new RuntimeException("Attribute should throw an exception when given a fake \"language\" attribute. Deserialized object: " + result); } }
public void formatAndAppend(Format formatter, Object arg) { if (attributes == null) { append(formatter.format(arg)); } else { AttributedCharacterIterator formattedArg = formatter.formatToCharacterIterator(arg); int prevLength = length; append(formattedArg); // Copy all of the attributes from formattedArg to our attributes list. formattedArg.first(); int start = formattedArg.getIndex(); // Should be 0 but might not be. int limit = formattedArg.getEndIndex(); // == start + length - prevLength int offset = prevLength - start; // Adjust attribute indexes for the result string. while (start < limit) { Map<Attribute, Object> map = formattedArg.getAttributes(); int runLimit = formattedArg.getRunLimit(); if (map.size() != 0) { for (Map.Entry<Attribute, Object> entry : map.entrySet()) { attributes.add( new AttributeAndPosition( entry.getKey(), entry.getValue(), offset + start, offset + runLimit)); } } start = runLimit; formattedArg.setIndex(start); } } }
static Attribute doSerializationCycle(Attribute attribute) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(attribute); oos.flush(); byte[] data = baos.toByteArray(); ByteArrayInputStream bais = new ByteArrayInputStream(data); ObjectInputStream ois = new ObjectInputStream(bais); Attribute result = (Attribute) ois.readObject(); return result; }
private void verifyLimit(AttributedCharacterIterator iterator, Map<String,Object> table) { int begin = Integer.parseInt((String)table.get("begin")); int end = Integer.parseInt((String)table.get("end")); @SuppressWarnings("unchecked") Set<Attribute> attrs = makeAttributes((List)table.get("attributes")); String begin2S = (String)table.get("begin2"); int begin2 = (begin2S != null) ? Integer.parseInt(begin2S) : begin; String end2S = (String)table.get("end2"); int end2 = (end2S != null) ? Integer.parseInt(end2S) : end; for (int counter = begin; counter < end; counter++) { iterator.setIndex(counter); if (iterator.getRunStart() != begin) { errln("Begin doesn't match want " + begin + " got " + iterator.getRunStart() + " at " + counter + " attrs " + attrs); } if (iterator.getRunStart(attrs) != begin2) { errln("Begin2 doesn't match want " + begin2 + " got " + iterator.getRunStart(attrs) + " at " + counter + " attrs " + attrs); } if (iterator.getRunLimit() != end) { errln("End doesn't match want " + end + " got " + iterator.getRunLimit() + " at " + counter + " attrs " + attrs); } if (iterator.getRunLimit(attrs) != end2) { errln("End2 doesn't match want " + end2 + " got " + iterator.getRunLimit(attrs) + " at " + counter + " attrs " + attrs); } } }