001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.image.typography; 031 032import java.text.AttributedCharacterIterator.Attribute; 033import java.text.AttributedString; 034import java.util.Map; 035 036import org.openimaj.image.renderer.ImageRenderer; 037import org.openimaj.image.typography.hershey.HersheyFont; 038 039/** 040 * Base class for the representation of font styles. 041 * 042 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 043 * 044 * @param <T> the pixel type 045 */ 046public class FontStyle<T> { 047 /** 048 * Attributes for styling {@link AttributedString}s. 049 * 050 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 051 */ 052 public static class FontStyleAttribute extends Attribute { 053 private static final long serialVersionUID = 1L; 054 055 /** 056 * Default constructor 057 * @param name the name of the attribute 058 */ 059 public FontStyleAttribute(final String name) { 060 super(name); 061 } 062 } 063 064 /** 065 * Horizontal alignment options 066 * 067 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 068 * 069 */ 070 public static enum HorizontalAlignment { 071 /** 072 * Centered text from the starting point 073 */ 074 HORIZONTAL_CENTER, 075 /** 076 * Left-aligned text from the starting point 077 */ 078 HORIZONTAL_LEFT, 079 /** 080 * Right-aligned text from the starting point 081 */ 082 HORIZONTAL_RIGHT, 083 } 084 085 /** 086 * Vertical alignment options 087 * 088 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 089 * 090 */ 091 public static enum VerticalAlignment { 092 /** 093 * 094 */ 095 VERTICAL_TOP, 096 /** 097 * 098 */ 099 VERTICAL_HALF, 100 /** 101 * 102 */ 103 VERTICAL_CAP, 104 /** 105 * Bottom of characters aligned 106 */ 107 VERTICAL_BOTTOM, 108 } 109 110 /** 111 * Attribute for the font. Value should be a {@link Font}. 112 */ 113 public static final Attribute FONT = new FontStyleAttribute("font"); 114 115 /** 116 * Attribute for italic text. Value should be Boolean. 117 */ 118 public static final Attribute ITALIC = new FontStyleAttribute("italic"); 119 120 /** 121 * Attribute for rotating the text. Value should be a Number in radians. 122 */ 123 public static final Attribute ANGLE = new FontStyleAttribute("angle"); 124 125 /** 126 * Attribute for stroke colour. Value should be of type <T>. 127 */ 128 public static final Attribute COLOUR = new FontStyleAttribute("colour"); 129 130 /** 131 * Attribute for horizontal alignment. Must be an instance of {@link HorizontalAlignment} 132 */ 133 public static final Attribute HORIZONTAL_ALIGNMENT = new FontStyleAttribute("horizontalAlignment"); 134 135 /** 136 * Attribute for vertical alignment. Must be an instance of {@link VerticalAlignment} 137 */ 138 public static final Attribute VERTICAL_ALIGNMENT = new FontStyleAttribute("verticalAlignment"); 139 140 /** 141 * Attribute for font size. Must be a Number in pixels. 142 */ 143 public static final Attribute FONT_SIZE = new FontStyleAttribute("fontSize"); 144 145 private static final Font<?> DEFAULT_FONT = HersheyFont.ROMAN_SIMPLEX; 146 147 /** 148 * The font 149 */ 150 protected Font<?> font; 151 152 /** 153 * should the associated text be rendered in italic? 154 */ 155 protected boolean italic; 156 157 /** 158 * Angle in radians for drawing the associated text 159 */ 160 protected float angle; 161 162 /** 163 * Stroke colour for drawing the associated text 164 */ 165 protected T colour; 166 167 /** 168 * horizontal alignment of the text 169 */ 170 protected HorizontalAlignment horizontalAlignment = HorizontalAlignment.HORIZONTAL_LEFT; 171 172 /** 173 * vertical alignment of the text 174 */ 175 protected VerticalAlignment verticalAlignment = VerticalAlignment.VERTICAL_BOTTOM; 176 177 /** 178 * Font size in pixels 179 */ 180 protected int fontSize = 24; 181 182 protected FontStyle(final Font<?> font, final ImageRenderer<T, ?> renderer) { 183 this.colour = renderer.defaultForegroundColour(); 184 this.font = font; 185 } 186 187 /** 188 * @param font 189 * @param col 190 */ 191 public FontStyle(final Font<?> font, final T col) { 192 this.colour= col; 193 this.font = font; 194 } 195 196 /** 197 * Parse the attributes map and set this FontStyle accordingly. 198 * Subclasses should override this method to add extra attributes. 199 * 200 * @param attrs the attribute map 201 */ 202 @SuppressWarnings("unchecked") 203 public void parseAttributes(final Map<? extends Attribute,Object> attrs) { 204 if (attrs.containsKey(FontStyle.FONT)) this.font = (Font<?>) attrs.get(FontStyle.FONT); 205 if (attrs.containsKey(FontStyle.ITALIC)) this.italic = (Boolean) attrs.get(FontStyle.ITALIC); 206 if (attrs.containsKey(FontStyle.ANGLE)) this.angle = ((Number) attrs.get(FontStyle.ANGLE)).floatValue(); 207 if (attrs.containsKey(FontStyle.COLOUR)) this.colour = (T) attrs.get(FontStyle.COLOUR); 208 if (attrs.containsKey(FontStyle.HORIZONTAL_ALIGNMENT)) this.horizontalAlignment = (HorizontalAlignment) attrs.get(FontStyle.HORIZONTAL_ALIGNMENT); 209 if (attrs.containsKey(FontStyle.VERTICAL_ALIGNMENT)) this.verticalAlignment = (VerticalAlignment) attrs.get(FontStyle.VERTICAL_ALIGNMENT); 210 if (attrs.containsKey(FontStyle.FONT_SIZE)) this.fontSize = ((Number) attrs.get(FontStyle.FONT_SIZE)).intValue(); 211 } 212 213 /** 214 * Get the renderer suitable for rendering text with this style 215 * into the given image. 216 * @param renderer the image renderer 217 * @return the renderer 218 */ 219 public FontRenderer<T, FontStyle<T>> getRenderer(final ImageRenderer<T, ?> renderer) { 220 return this.font.getRenderer(renderer); 221 } 222 223 /** 224 * Construct a new FontStyle from the given attribute map, suitable for 225 * rendering into the given image. 226 * @param <T> the pixel type. 227 * @param attrs the attribute map 228 * @param renderer the image renderer 229 * @return the FontStyle 230 */ 231 public static <T> FontStyle<T> parseAttributes(final Map<? extends Attribute,Object> attrs, final ImageRenderer<T,?> renderer) { 232 Font<?> fnt = (Font<?>) attrs.get(FontStyle.FONT); 233 234 if (fnt == null) 235 fnt = FontStyle.DEFAULT_FONT; 236 237 final FontStyle<T> sty = fnt.createStyle(renderer); 238 sty.parseAttributes(attrs); 239 return sty; 240 } 241 242 /** 243 * @return the font 244 */ 245 public Font<?> getFont() { 246 return this.font; 247 } 248 249 /** 250 * @param font the font to set 251 */ 252 public void setFont(final Font<?> font) { 253 this.font = font; 254 } 255 256 /** 257 * @return the italic 258 */ 259 public boolean isItalic() { 260 return this.italic; 261 } 262 263 /** 264 * @param italic the italic to set 265 */ 266 public void setItalic(final boolean italic) { 267 this.italic = italic; 268 } 269 270 /** 271 * @return the angle 272 */ 273 public float getAngle() { 274 return this.angle; 275 } 276 277 /** 278 * @param angle the angle to set 279 */ 280 public void setAngle(final float angle) { 281 this.angle = angle; 282 } 283 284 /** 285 * @return the colour 286 */ 287 public T getColour() { 288 return this.colour; 289 } 290 291 /** 292 * @param colour the colour to set 293 */ 294 public void setColour(final T colour) { 295 this.colour = colour; 296 } 297 298 /** 299 * @return the horizontalAlignment 300 */ 301 public HorizontalAlignment getHorizontalAlignment() { 302 return this.horizontalAlignment; 303 } 304 305 /** 306 * @param horizontalAlignment the horizontalAlignment to set 307 */ 308 public void setHorizontalAlignment(final HorizontalAlignment horizontalAlignment) { 309 this.horizontalAlignment = horizontalAlignment; 310 } 311 312 /** 313 * @return the verticalAlignment 314 */ 315 public VerticalAlignment getVerticalAlignment() { 316 return this.verticalAlignment; 317 } 318 319 /** 320 * @param verticalAlignment the verticalAlignment to set 321 */ 322 public void setVerticalAlignment(final VerticalAlignment verticalAlignment) { 323 this.verticalAlignment = verticalAlignment; 324 } 325 326 /** 327 * @return the fontSize 328 */ 329 public int getFontSize() { 330 return this.fontSize; 331 } 332 333 /** 334 * @param fontSize the fontSize to set 335 */ 336 public void setFontSize(final int fontSize) { 337 this.fontSize = fontSize; 338 } 339}