JDK-4372591 : add TextAttribute state to Graphics2D, getters/setters
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2000-09-20
  • Updated: 2005-08-25
  • Resolved: 2005-08-25
Related Reports
Duplicate :  
Description
Clients typically use drawString to render small, complete segments of text.  This call does not fully support all the text and layout attributes.  In particular it does not support the layout attributes, RUN_DIRECTION and NUMERIC_SHAPING (used in right-to-left languages), nor does it support some more familiar text attributes, e.g., underline or strikethrough.  Client control of rendering using these attributes is currently available only through the TextLayout API.

It is desireable to let one framework (such as swing, or a parent component) compute and set some text attributes for a client (a child component, or a user of a swing component).  It is also desireable that clients not have to change their code in order to access this functionality.

It is proposed that new state be added to Graphics2D to hold the full complement of TextAttributes.  Methods will be added to let clients modify and query the attributes used for rendering.  The semantics of setFont and the relationship of the font and its attributes to the graphic's attributes will be clarified.

This will allow frameworks, like swing, to calculate desired values for RUN_DIRECTION and NUMERIC_SHAPING based on locale or user preferences, and allow clients' text rendering to reflect these values, without clients having to change their code.

Comments
EVALUATION This seems to me to be the same request as 4828102: Need API to get/set TextAttribute on Graphics2D which as noted there was implemented with Font support under bug ID 4296952. So I am closing this as a dup of 4828102 but the issue IS resolved - just differently.
25-08-2005

WORK AROUND Require clients to maintain attribute state themselves, and to use TextLayout.draw. There is no existing API in Graphics or Component that can be used to communicate this state through the view hierarchy, so this workaround is limited.
11-06-2004

PUBLIC COMMENTS Add state and getters/setters on Graphics2D to hold a collection of TextAttributes, which are used when rendering 'plain text' via drawString, drawChars, and drawBytes.
10-06-2004

SUGGESTED FIX The proposed API changes are as follows: /** * Modify the text attributes used by <code>drawString</code>. This is * a generalization of <code>setFont</code> that allows control over * layout-related attributes in addition to font-related ones. * <code>setFont</code> affects only those attributes that can be * applied to a <code>Font</code>, while <code>addTextAttributes</code> * offers complete control. Setting layout-related attributes can * adversely impact rendering performance. * <p> * Using an attribute whose value is null removes it from the * collection of defined attributes, effectively restoring * that attribute to its default value. Attributes not present in * the argument to the call are not affected, with the following * exceptions: * <p> * Setting a value for <code>TextAttribute.FONT</code> is equivalent to * calling <code>setFont</code> with that font. This causes the other * font-specific attribute values (family, size, weight, and posture) * to match those in the font. For example, if the value of * <code>TextAttribute.FONT</code> is a font with the family name * <code>"Helvetica"</code> then the value of <code>TextAttribute.FAMILY</code> * will be set to <code>"Helvetica"</code>. * <p> * If other font attributes are defined in the same call, they are * applied after the those from <code>TextAttribute.FONT</code> if present. * <p> * Subsequent to this call, the value of <code>TextAttribute.FONT</code> * will be defined and be equal to the font returned by <code>getFont()</code>. * This font will reflect any changes to font attribute values made in * this call. * <p> * Illegal values or types will not be detected at this time, but * might cause exceptions to be thrown when drawString is called. * <p> * For example: * <blockquote><code> * Map attributes = new HashMap(); * attributes.put(TextAttribute.FAMILY, "Lucida Sans"); * attributes.put(TextAttribute.SIZE, null); * graphics.addTextAttributes(attributes); * * // Future calls to drawString will now use Lucida Sans, at the * // default point size, in whatever style (bold, italic) was * // previously in effect. * * graphics.setFont(new Font("sanserif", Font.PLAIN, 14)); * Map attributes = graphics.getTextAttributes(); * * // Future calls to drawString will use the provided font. * // The map returned from getTextAttributes contains (at least) values * // for TextAttribute.FONT, TextAttribute.FAMILY, TextAttribute.POSTURE, * // TextAttribute.WEIGHT, and TextAttribute.SIZE equal to those in the * // font that was used above. * * graphics.addTextAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_ITALIC); * Font newFont = graphics.getFont(); * Map newAttributes = graphics.getTextAttributes(); * * // newFont differs from the font previously passed to setFont, it is now * // an italic font (if available). newAttributes defines an equal value * // for TextAttribute.FONT. TextAttribute.POSTURE reflects the new value, * // other attributes, if already defined, are unchanged. * </code></blockquote> * * @param attributes a Map containing the attributes to modify and their new values * @see java.awt.Graphics#setFont * @see #getTextAttributes * @see #addTextAttribute * @see #setTextAttributes * @since JDK1.4 */ public abstract void addTextAttributes(Map attributes); /** * Set a new value for the text attribute. This is a convenience method * with the same behavior as addTextAttributes except it defines a single * attribute and value. Using an attribute whose value is null removes it * from the collection of defined attributes, effectively restoring * that attribute to its default value. If the attribute is a * font-related attribute, the font returned by <code>getFont()</code> * might change. * * @param key the attribute whose value is to be changed * @param value the new value of the attribute, or null to restore the default * @see #getTextAttributes * @see #addTextAttributes * @see #setTextAttributes */ public abstract void addTextAttribute(TextAttribute key, Object value); /** * Set the text attributes to the provided set. This has the effect of * removing all existing layout-related attributes, then adding * the new ones. The attributes parameter can be null. Font-related * attributes are not removed, though the new attributes can replace * them. The font can be changed if font-related attributes are replaced. * * @param attributes the new attributes * @see #addTextAttribute * @see #addTextAttribute * @see #getTextAttributes */ public abstract void setTextAttributes(Map attributes); /** * Return a Map containing the current set of text attributes. * Attributes with default values are not necessarily present in the * result. * * @returns the current text attributes * @see #addTextAttribute * @see #addTextAttributes * @see #setTextAttributes */ public abstract Map getTextAttributes(); ---- change addTextAttribute to setTextAttribute to match the renderingHints API naming. doug.felt@eng 2000-09-20 Meeting with members of the swing team resulted in a decision to change this API. Swing components each hold copies of font and set them before rendering. Since Font is immutable, it can be shared, and when multiple calls to set the same font on a graphics are made, the redundant calls can be easily ignored. Map doesn't offer this security. For this reason, it was determined that adding a separate, immutable class specifically to hold a collection of TextAttributes would be required. This new class would be TextAttributeState and have the desired immutability and uniqueness properties. doug.felt@eng 2000-11-27
27-11-2000

EVALUATION Swing requires some means to propagate attributes, this would provide the foundation for that. doug.felt@eng 2000-09-20
20-09-2000