/* * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package javax.swing.plaf.basic;import java.awt.*;import java.awt.event.*;import java.beans.*;import java.net.URL;import java.net.MalformedURLException;import javax.swing.*;import javax.swing.text.*;import javax.swing.text.html.*;import javax.swing.plaf.*;import javax.swing.border.*;/** * Provides the look and feel for a JEditorPane. * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @author Timothy Prinzing */public class BasicEditorPaneUI extends BasicTextUI { /** * Creates a UI for the JTextPane. * * @param c the JTextPane component * @return the UI */ public static ComponentUI createUI(JComponent c) { return new BasicEditorPaneUI(); } /** * Creates a new BasicEditorPaneUI. */ public BasicEditorPaneUI() { super(); } /** * Fetches the name used as a key to lookup properties through the * UIManager. This is used as a prefix to all the standard * text properties. * * @return the name ("EditorPane") */ protected String getPropertyPrefix() { return "EditorPane"; } /** *{@inheritDoc} * * @since 1.5 */ public void installUI(JComponent c) { super.installUI(c); updateDisplayProperties(c.getFont(), c.getForeground()); } /** *{@inheritDoc} * * @since 1.5 */ public void uninstallUI(JComponent c) { cleanDisplayProperties(); super.uninstallUI(c); } /** * Fetches the EditorKit for the UI. This is whatever is * currently set in the associated JEditorPane. * * @return the editor capabilities * @see TextUI#getEditorKit */ public EditorKit getEditorKit(JTextComponent tc) { JEditorPane pane = (JEditorPane) getComponent(); return pane.getEditorKit(); } /** * Fetch an action map to use. The map for a JEditorPane * is not shared because it changes with the EditorKit. */ ActionMap getActionMap() { ActionMap am = new ActionMapUIResource(); am.put("requestFocus", new FocusAction()); EditorKit editorKit = getEditorKit(getComponent()); if (editorKit != null) { Action[] actions = editorKit.getActions(); if (actions != null) { addActions(am, actions); } } am.put(TransferHandler.getCutAction().getValue(Action.NAME), TransferHandler.getCutAction()); am.put(TransferHandler.getCopyAction().getValue(Action.NAME), TransferHandler.getCopyAction()); am.put(TransferHandler.getPasteAction().getValue(Action.NAME), TransferHandler.getPasteAction()); return am; } /** * This method gets called when a bound property is changed * on the associated JTextComponent. This is a hook * which UI implementations may change to reflect how the * UI displays bound properties of JTextComponent subclasses. * This is implemented to rebuild the ActionMap based upon an * EditorKit change. * * @param evt the property change event */ protected void propertyChange(PropertyChangeEvent evt) { super.propertyChange(evt); String name = evt.getPropertyName(); if ("editorKit".equals(name)) { ActionMap map = SwingUtilities.getUIActionMap(getComponent()); if (map != null) { Object oldValue = evt.getOldValue(); if (oldValue instanceof EditorKit) { Action[] actions = ((EditorKit)oldValue).getActions(); if (actions != null) { removeActions(map, actions); } } Object newValue = evt.getNewValue(); if (newValue instanceof EditorKit) { Action[] actions = ((EditorKit)newValue).getActions(); if (actions != null) { addActions(map, actions); } } } updateFocusTraversalKeys(); } else if ("editable".equals(name)) { updateFocusTraversalKeys(); } else if ("foreground".equals(name) || "font".equals(name) || "document".equals(name) || JEditorPane.W3C_LENGTH_UNITS.equals(name) || JEditorPane.HONOR_DISPLAY_PROPERTIES.equals(name) ) { JComponent c = getComponent(); updateDisplayProperties(c.getFont(), c.getForeground()); if ( JEditorPane.W3C_LENGTH_UNITS.equals(name) || JEditorPane.HONOR_DISPLAY_PROPERTIES.equals(name) ) { modelChanged(); } if ("foreground".equals(name)) { Object honorDisplayPropertiesObject = c. getClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES); boolean honorDisplayProperties = false; if (honorDisplayPropertiesObject instanceof Boolean) { honorDisplayProperties = ((Boolean)honorDisplayPropertiesObject).booleanValue(); } if (honorDisplayProperties) { modelChanged(); } } } } void removeActions(ActionMap map, Action[] actions) { int n = actions.length; for (int i = 0; i < n; i++) { Action a = actions[i]; map.remove(a.getValue(Action.NAME)); } } void addActions(ActionMap map, Action[] actions) { int n = actions.length; for (int i = 0; i < n; i++) { Action a = actions[i]; map.put(a.getValue(Action.NAME), a); } } void updateDisplayProperties(Font font, Color fg) { JComponent c = getComponent(); Object honorDisplayPropertiesObject = c. getClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES); boolean honorDisplayProperties = false; Object w3cLengthUnitsObject = c.getClientProperty(JEditorPane. W3C_LENGTH_UNITS); boolean w3cLengthUnits = false; if (honorDisplayPropertiesObject instanceof Boolean) { honorDisplayProperties = ((Boolean)honorDisplayPropertiesObject).booleanValue(); } if (w3cLengthUnitsObject instanceof Boolean) { w3cLengthUnits = ((Boolean)w3cLengthUnitsObject).booleanValue(); } if (this instanceof BasicTextPaneUI || honorDisplayProperties) { //using equals because can not use UIResource for Boolean Document doc = getComponent().getDocument(); if (doc instanceof StyledDocument) { if (doc instanceof HTMLDocument && honorDisplayProperties) { updateCSS(font, fg); } else { updateStyle(font, fg); } } } else { cleanDisplayProperties(); } if ( w3cLengthUnits ) { Document doc = getComponent().getDocument(); if (doc instanceof HTMLDocument) { StyleSheet documentStyleSheet = ((HTMLDocument)doc).getStyleSheet(); documentStyleSheet.addRule("W3C_LENGTH_UNITS_ENABLE"); } } else { Document doc = getComponent().getDocument(); if (doc instanceof HTMLDocument) { StyleSheet documentStyleSheet = ((HTMLDocument)doc).getStyleSheet(); documentStyleSheet.addRule("W3C_LENGTH_UNITS_DISABLE"); } } } /** * Attribute key to reference the default font. * used in javax.swing.text.StyleContext.getFont * to resolve the default font. */ private static final String FONT_ATTRIBUTE_KEY = "FONT_ATTRIBUTE_KEY"; void cleanDisplayProperties() { Document document = getComponent().getDocument(); if (document instanceof HTMLDocument) { StyleSheet documentStyleSheet = ((HTMLDocument)document).getStyleSheet(); StyleSheet[] styleSheets = documentStyleSheet.getStyleSheets(); if (styleSheets != null) { for (StyleSheet s : styleSheets) { if (s instanceof StyleSheetUIResource) { documentStyleSheet.removeStyleSheet(s); documentStyleSheet.addRule("BASE_SIZE_DISABLE"); break; } } } Style style = ((StyledDocument) document).getStyle(StyleContext.DEFAULT_STYLE); if (style.getAttribute(FONT_ATTRIBUTE_KEY) != null) { style.removeAttribute(FONT_ATTRIBUTE_KEY); } } } static class StyleSheetUIResource extends StyleSheet implements UIResource { } private void updateCSS(Font font, Color fg) { JTextComponent component = getComponent(); Document document = component.getDocument(); if (document instanceof HTMLDocument) { StyleSheet styleSheet = new StyleSheetUIResource(); StyleSheet documentStyleSheet = ((HTMLDocument)document).getStyleSheet(); StyleSheet[] styleSheets = documentStyleSheet.getStyleSheets(); if (styleSheets != null) { for (StyleSheet s : styleSheets) { if (s instanceof StyleSheetUIResource) { documentStyleSheet.removeStyleSheet(s); } } } String cssRule = sun.swing. SwingUtilities2.displayPropertiesToCSS(font, fg); styleSheet.addRule(cssRule); documentStyleSheet.addStyleSheet(styleSheet); documentStyleSheet.addRule("BASE_SIZE " + component.getFont().getSize()); Style style = ((StyledDocument) document).getStyle(StyleContext.DEFAULT_STYLE); if (! font.equals(style.getAttribute(FONT_ATTRIBUTE_KEY))) { style.addAttribute(FONT_ATTRIBUTE_KEY, font); } } } private void updateStyle(Font font, Color fg) { updateFont(font); updateForeground(fg); } /** * Update the color in the default style of the document. * * @param color the new color to use or null to remove the color attribute * from the document's style */ private void updateForeground(Color color) { StyledDocument doc = (StyledDocument)getComponent().getDocument(); Style style = doc.getStyle(StyleContext.DEFAULT_STYLE); if (style == null) { return; } if (color == null) { if (style.getAttribute(StyleConstants.Foreground) != null) { style.removeAttribute(StyleConstants.Foreground); } } else { if (! color.equals(StyleConstants.getForeground(style))) { StyleConstants.setForeground(style, color); } } } /** * Update the font in the default style of the document. * * @param font the new font to use or null to remove the font attribute * from the document's style */ private void updateFont(Font font) { StyledDocument doc = (StyledDocument)getComponent().getDocument(); Style style = doc.getStyle(StyleContext.DEFAULT_STYLE); if (style == null) { return; } String fontFamily = (String) style.getAttribute(StyleConstants.FontFamily); Integer fontSize = (Integer) style.getAttribute(StyleConstants.FontSize); Boolean isBold = (Boolean) style.getAttribute(StyleConstants.Bold); Boolean isItalic = (Boolean) style.getAttribute(StyleConstants.Italic); Font fontAttribute = (Font) style.getAttribute(FONT_ATTRIBUTE_KEY); if (font == null) { if (fontFamily != null) { style.removeAttribute(StyleConstants.FontFamily); } if (fontSize != null) { style.removeAttribute(StyleConstants.FontSize); } if (isBold != null) { style.removeAttribute(StyleConstants.Bold); } if (isItalic != null) { style.removeAttribute(StyleConstants.Italic); } if (fontAttribute != null) { style.removeAttribute(FONT_ATTRIBUTE_KEY); } } else { if (! font.getName().equals(fontFamily)) { StyleConstants.setFontFamily(style, font.getName()); } if (fontSize == null || fontSize.intValue() != font.getSize()) { StyleConstants.setFontSize(style, font.getSize()); } if (isBold == null || isBold.booleanValue() != font.isBold()) { StyleConstants.setBold(style, font.isBold()); } if (isItalic == null || isItalic.booleanValue() != font.isItalic()) { StyleConstants.setItalic(style, font.isItalic()); } if (! font.equals(fontAttribute)) { style.addAttribute(FONT_ATTRIBUTE_KEY, font); } } }}
/*
* Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.swing.plaf.basic;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.net.URL;
import java.net.MalformedURLException;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import javax.swing.plaf.*;
import javax.swing.border.*;
/**
* Provides the look and feel for a JEditorPane.
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is
* appropriate for short term storage or RMI between applications running
* the same version of Swing. As of 1.4, support for long term storage
* of all JavaBeans<sup><font size="-2">TM</font></sup>
* has been added to the <code>java.beans</code> package.
* Please see {@link java.beans.XMLEncoder}.
*
* @author Timothy Prinzing
*/
public class BasicEditorPaneUI extends BasicTextUI {
/**
* Creates a UI for the JTextPane.
*
* @param c the JTextPane component
* @return the UI
*/
public static ComponentUI createUI(JComponent c) {
return new BasicEditorPaneUI();
}
/**
* Creates a new BasicEditorPaneUI.
*/
public BasicEditorPaneUI() {
super();
}
/**
* Fetches the name used as a key to lookup properties through the
* UIManager. This is used as a prefix to all the standard
* text properties.
*
* @return the name ("EditorPane")
*/
protected String getPropertyPrefix() {
return "EditorPane";
}
/**
*{@inheritDoc}
*
* @since 1.5
*/
public void installUI(JComponent c) {
super.installUI(c);
updateDisplayProperties(c.getFont(),
c.getForeground());
}
/**
*{@inheritDoc}
*
* @since 1.5
*/
public void uninstallUI(JComponent c) {
cleanDisplayProperties();
super.uninstallUI(c);
}
/**
* Fetches the EditorKit for the UI. This is whatever is
* currently set in the associated JEditorPane.
*
* @return the editor capabilities
* @see TextUI#getEditorKit
*/
public EditorKit getEditorKit(JTextComponent tc) {
JEditorPane pane = (JEditorPane) getComponent();
return pane.getEditorKit();
}
/**
* Fetch an action map to use. The map for a JEditorPane
* is not shared because it changes with the EditorKit.
*/
ActionMap getActionMap() {
ActionMap am = new ActionMapUIResource();
am.put("requestFocus", new FocusAction());
EditorKit editorKit = getEditorKit(getComponent());
if (editorKit != null) {
Action[] actions = editorKit.getActions();
if (actions != null) {
addActions(am, actions);
}
}
am.put(TransferHandler.getCutAction().getValue(Action.NAME),
TransferHandler.getCutAction());
am.put(TransferHandler.getCopyAction().getValue(Action.NAME),
TransferHandler.getCopyAction());
am.put(TransferHandler.getPasteAction().getValue(Action.NAME),
TransferHandler.getPasteAction());
return am;
}
/**
* This method gets called when a bound property is changed
* on the associated JTextComponent. This is a hook
* which UI implementations may change to reflect how the
* UI displays bound properties of JTextComponent subclasses.
* This is implemented to rebuild the ActionMap based upon an
* EditorKit change.
*
* @param evt the property change event
*/
protected void propertyChange(PropertyChangeEvent evt) {
super.propertyChange(evt);
String name = evt.getPropertyName();
if ("editorKit".equals(name)) {
ActionMap map = SwingUtilities.getUIActionMap(getComponent());
if (map != null) {
Object oldValue = evt.getOldValue();
if (oldValue instanceof EditorKit) {
Action[] actions = ((EditorKit)oldValue).getActions();
if (actions != null) {
removeActions(map, actions);
}
}
Object newValue = evt.getNewValue();
if (newValue instanceof EditorKit) {
Action[] actions = ((EditorKit)newValue).getActions();
if (actions != null) {
addActions(map, actions);
}
}
}
updateFocusTraversalKeys();
} else if ("editable".equals(name)) {
updateFocusTraversalKeys();
} else if ("foreground".equals(name)
|| "font".equals(name)
|| "document".equals(name)
|| JEditorPane.W3C_LENGTH_UNITS.equals(name)
|| JEditorPane.HONOR_DISPLAY_PROPERTIES.equals(name)
) {
JComponent c = getComponent();
updateDisplayProperties(c.getFont(), c.getForeground());
if ( JEditorPane.W3C_LENGTH_UNITS.equals(name)
|| JEditorPane.HONOR_DISPLAY_PROPERTIES.equals(name) ) {
modelChanged();
}
if ("foreground".equals(name)) {
Object honorDisplayPropertiesObject = c.
getClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES);
boolean honorDisplayProperties = false;
if (honorDisplayPropertiesObject instanceof Boolean) {
honorDisplayProperties =
((Boolean)honorDisplayPropertiesObject).booleanValue();
}
if (honorDisplayProperties) {
modelChanged();
}
}
}
}
void removeActions(ActionMap map, Action[] actions) {
int n = actions.length;
for (int i = 0; i < n; i++) {
Action a = actions[i];
map.remove(a.getValue(Action.NAME));
}
}
void addActions(ActionMap map, Action[] actions) {
int n = actions.length;
for (int i = 0; i < n; i++) {
Action a = actions[i];
map.put(a.getValue(Action.NAME), a);
}
}
void updateDisplayProperties(Font font, Color fg) {
JComponent c = getComponent();
Object honorDisplayPropertiesObject = c.
getClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES);
boolean honorDisplayProperties = false;
Object w3cLengthUnitsObject = c.getClientProperty(JEditorPane.
W3C_LENGTH_UNITS);
boolean w3cLengthUnits = false;
if (honorDisplayPropertiesObject instanceof Boolean) {
honorDisplayProperties =
((Boolean)honorDisplayPropertiesObject).booleanValue();
}
if (w3cLengthUnitsObject instanceof Boolean) {
w3cLengthUnits = ((Boolean)w3cLengthUnitsObject).booleanValue();
}
if (this instanceof BasicTextPaneUI
|| honorDisplayProperties) {
//using equals because can not use UIResource for Boolean
Document doc = getComponent().getDocument();
if (doc instanceof StyledDocument) {
if (doc instanceof HTMLDocument
&& honorDisplayProperties) {
updateCSS(font, fg);
} else {
updateStyle(font, fg);
}
}
} else {
cleanDisplayProperties();
}
if ( w3cLengthUnits ) {
Document doc = getComponent().getDocument();
if (doc instanceof HTMLDocument) {
StyleSheet documentStyleSheet =
((HTMLDocument)doc).getStyleSheet();
documentStyleSheet.addRule("W3C_LENGTH_UNITS_ENABLE");
}
} else {
Document doc = getComponent().getDocument();
if (doc instanceof HTMLDocument) {
StyleSheet documentStyleSheet =
((HTMLDocument)doc).getStyleSheet();
documentStyleSheet.addRule("W3C_LENGTH_UNITS_DISABLE");
}
}
}
/**
* Attribute key to reference the default font.
* used in javax.swing.text.StyleContext.getFont
* to resolve the default font.
*/
private static final String FONT_ATTRIBUTE_KEY = "FONT_ATTRIBUTE_KEY";
void cleanDisplayProperties() {
Document document = getComponent().getDocument();
if (document instanceof HTMLDocument) {
StyleSheet documentStyleSheet =
((HTMLDocument)document).getStyleSheet();
StyleSheet[] styleSheets = documentStyleSheet.getStyleSheets();
if (styleSheets != null) {
for (StyleSheet s : styleSheets) {
if (s instanceof StyleSheetUIResource) {
documentStyleSheet.removeStyleSheet(s);
documentStyleSheet.addRule("BASE_SIZE_DISABLE");
break;
}
}
}
Style style = ((StyledDocument) document).getStyle(StyleContext.DEFAULT_STYLE);
if (style.getAttribute(FONT_ATTRIBUTE_KEY) != null) {
style.removeAttribute(FONT_ATTRIBUTE_KEY);
}
}
}
static class StyleSheetUIResource extends StyleSheet implements UIResource {
}
private void updateCSS(Font font, Color fg) {
JTextComponent component = getComponent();
Document document = component.getDocument();
if (document instanceof HTMLDocument) {
StyleSheet styleSheet = new StyleSheetUIResource();
StyleSheet documentStyleSheet =
((HTMLDocument)document).getStyleSheet();
StyleSheet[] styleSheets = documentStyleSheet.getStyleSheets();
if (styleSheets != null) {
for (StyleSheet s : styleSheets) {
if (s instanceof StyleSheetUIResource) {
documentStyleSheet.removeStyleSheet(s);
}
}
}
String cssRule = sun.swing.
SwingUtilities2.displayPropertiesToCSS(font,
fg);
styleSheet.addRule(cssRule);
documentStyleSheet.addStyleSheet(styleSheet);
documentStyleSheet.addRule("BASE_SIZE " +
component.getFont().getSize());
Style style = ((StyledDocument) document).getStyle(StyleContext.DEFAULT_STYLE);
if (! font.equals(style.getAttribute(FONT_ATTRIBUTE_KEY))) {
style.addAttribute(FONT_ATTRIBUTE_KEY, font);
}
}
}
private void updateStyle(Font font, Color fg) {
updateFont(font);
updateForeground(fg);
}
/**
* Update the color in the default style of the document.
*
* @param color the new color to use or null to remove the color attribute
* from the document's style
*/
private void updateForeground(Color color) {
StyledDocument doc = (StyledDocument)getComponent().getDocument();
Style style = doc.getStyle(StyleContext.DEFAULT_STYLE);
if (style == null) {
return;
}
if (color == null) {
if (style.getAttribute(StyleConstants.Foreground) != null) {
style.removeAttribute(StyleConstants.Foreground);
}
} else {
if (! color.equals(StyleConstants.getForeground(style))) {
StyleConstants.setForeground(style, color);
}
}
}
/**
* Update the font in the default style of the document.
*
* @param font the new font to use or null to remove the font attribute
* from the document's style
*/
private void updateFont(Font font) {
StyledDocument doc = (StyledDocument)getComponent().getDocument();
Style style = doc.getStyle(StyleContext.DEFAULT_STYLE);
if (style == null) {
return;
}
String fontFamily = (String) style.getAttribute(StyleConstants.FontFamily);
Integer fontSize = (Integer) style.getAttribute(StyleConstants.FontSize);
Boolean isBold = (Boolean) style.getAttribute(StyleConstants.Bold);
Boolean isItalic = (Boolean) style.getAttribute(StyleConstants.Italic);
Font fontAttribute = (Font) style.getAttribute(FONT_ATTRIBUTE_KEY);
if (font == null) {
if (fontFamily != null) {
style.removeAttribute(StyleConstants.FontFamily);
}
if (fontSize != null) {
style.removeAttribute(StyleConstants.FontSize);
}
if (isBold != null) {
style.removeAttribute(StyleConstants.Bold);
}
if (isItalic != null) {
style.removeAttribute(StyleConstants.Italic);
}
if (fontAttribute != null) {
style.removeAttribute(FONT_ATTRIBUTE_KEY);
}
} else {
if (! font.getName().equals(fontFamily)) {
StyleConstants.setFontFamily(style, font.getName());
}
if (fontSize == null
|| fontSize.intValue() != font.getSize()) {
StyleConstants.setFontSize(style, font.getSize());
}
if (isBold == null
|| isBold.booleanValue() != font.isBold()) {
StyleConstants.setBold(style, font.isBold());
}
if (isItalic == null
|| isItalic.booleanValue() != font.isItalic()) {
StyleConstants.setItalic(style, font.isItalic());
}
if (! font.equals(fontAttribute)) {
style.addAttribute(FONT_ATTRIBUTE_KEY, font);
}
}
}
}