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> 045 * the pixel type 046 */ 047public class FontStyle<T> { 048 /** 049 * Attributes for styling {@link AttributedString}s. 050 * 051 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 052 */ 053 public static class FontStyleAttribute extends Attribute { 054 private static final long serialVersionUID = 1L; 055 056 /** 057 * Default constructor 058 * 059 * @param name 060 * the name of the attribute 061 */ 062 public FontStyleAttribute(final String name) { 063 super(name); 064 } 065 } 066 067 /** 068 * Horizontal alignment options 069 * 070 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 071 * 072 */ 073 public static enum HorizontalAlignment { 074 /** 075 * Centered text from the starting point 076 */ 077 HORIZONTAL_CENTER, 078 /** 079 * Left-aligned text from the starting point 080 */ 081 HORIZONTAL_LEFT, 082 /** 083 * Right-aligned text from the starting point 084 */ 085 HORIZONTAL_RIGHT, 086 } 087 088 /** 089 * Vertical alignment options 090 * 091 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 092 * 093 */ 094 public static enum VerticalAlignment { 095 /** 096 * 097 */ 098 VERTICAL_TOP, 099 /** 100 * 101 */ 102 VERTICAL_HALF, 103 /** 104 * 105 */ 106 VERTICAL_CAP, 107 /** 108 * Bottom of characters aligned 109 */ 110 VERTICAL_BOTTOM, 111 } 112 113 /** 114 * Attribute for the font. Value should be a {@link Font}. 115 */ 116 public static final Attribute FONT = new FontStyleAttribute("font"); 117 118 /** 119 * Attribute for italic text. Value should be Boolean. 120 */ 121 public static final Attribute ITALIC = new FontStyleAttribute("italic"); 122 123 /** 124 * Attribute for rotating the text. Value should be a Number in radians. 125 */ 126 public static final Attribute ANGLE = new FontStyleAttribute("angle"); 127 128 /** 129 * Attribute for stroke colour. 130 */ 131 public static final Attribute COLOUR = new FontStyleAttribute("colour"); 132 133 /** 134 * Attribute for horizontal alignment. Must be an instance of 135 * {@link HorizontalAlignment} 136 */ 137 public static final Attribute HORIZONTAL_ALIGNMENT = new FontStyleAttribute("horizontalAlignment"); 138 139 /** 140 * Attribute for vertical alignment. Must be an instance of 141 * {@link VerticalAlignment} 142 */ 143 public static final Attribute VERTICAL_ALIGNMENT = new FontStyleAttribute("verticalAlignment"); 144 145 /** 146 * Attribute for font size. Must be a Number in pixels. 147 */ 148 public static final Attribute FONT_SIZE = new FontStyleAttribute("fontSize"); 149 150 private static final Font<?> DEFAULT_FONT = HersheyFont.ROMAN_SIMPLEX; 151 152 /** 153 * The font 154 */ 155 protected Font<?> font; 156 157 /** 158 * should the associated text be rendered in italic? 159 */ 160 protected boolean italic; 161 162 /** 163 * Angle in radians for drawing the associated text 164 */ 165 protected float angle; 166 167 /** 168 * Stroke colour for drawing the associated text 169 */ 170 protected T colour; 171 172 /** 173 * horizontal alignment of the text 174 */ 175 protected HorizontalAlignment horizontalAlignment = HorizontalAlignment.HORIZONTAL_LEFT; 176 177 /** 178 * vertical alignment of the text 179 */ 180 protected VerticalAlignment verticalAlignment = VerticalAlignment.VERTICAL_BOTTOM; 181 182 /** 183 * Font size in pixels 184 */ 185 protected int fontSize = 24; 186 187 protected FontStyle(final Font<?> font, final ImageRenderer<T, ?> renderer) { 188 this.colour = renderer.defaultForegroundColour(); 189 this.font = font; 190 } 191 192 /** 193 * @param font 194 * @param col 195 */ 196 public FontStyle(final Font<?> font, final T col) { 197 this.colour = col; 198 this.font = font; 199 } 200 201 /** 202 * Parse the attributes map and set this FontStyle accordingly. Subclasses 203 * should override this method to add extra attributes. 204 * 205 * @param attrs 206 * the attribute map 207 */ 208 @SuppressWarnings("unchecked") 209 public void parseAttributes(final Map<? extends Attribute, Object> attrs) { 210 if (attrs.containsKey(FontStyle.FONT)) 211 this.font = (Font<?>) attrs.get(FontStyle.FONT); 212 if (attrs.containsKey(FontStyle.ITALIC)) 213 this.italic = (Boolean) attrs.get(FontStyle.ITALIC); 214 if (attrs.containsKey(FontStyle.ANGLE)) 215 this.angle = ((Number) attrs.get(FontStyle.ANGLE)).floatValue(); 216 if (attrs.containsKey(FontStyle.COLOUR)) 217 this.colour = (T) attrs.get(FontStyle.COLOUR); 218 if (attrs.containsKey(FontStyle.HORIZONTAL_ALIGNMENT)) 219 this.horizontalAlignment = (HorizontalAlignment) attrs.get(FontStyle.HORIZONTAL_ALIGNMENT); 220 if (attrs.containsKey(FontStyle.VERTICAL_ALIGNMENT)) 221 this.verticalAlignment = (VerticalAlignment) attrs.get(FontStyle.VERTICAL_ALIGNMENT); 222 if (attrs.containsKey(FontStyle.FONT_SIZE)) 223 this.fontSize = ((Number) attrs.get(FontStyle.FONT_SIZE)).intValue(); 224 } 225 226 /** 227 * Get the renderer suitable for rendering text with this style into the 228 * given image. 229 * 230 * @param renderer 231 * the image renderer 232 * @return the renderer 233 */ 234 public FontRenderer<T, FontStyle<T>> getRenderer(final ImageRenderer<T, ?> renderer) { 235 return this.font.getRenderer(renderer); 236 } 237 238 /** 239 * Construct a new FontStyle from the given attribute map, suitable for 240 * rendering into the given image. 241 * 242 * @param <T> 243 * the pixel type. 244 * @param attrs 245 * the attribute map 246 * @param renderer 247 * the image renderer 248 * @return the FontStyle 249 */ 250 public static <T> FontStyle<T> parseAttributes(final Map<? extends Attribute, Object> attrs, 251 final ImageRenderer<T, ?> renderer) 252 { 253 Font<?> fnt = (Font<?>) attrs.get(FontStyle.FONT); 254 255 if (fnt == null) 256 fnt = FontStyle.DEFAULT_FONT; 257 258 final FontStyle<T> sty = fnt.createStyle(renderer); 259 sty.parseAttributes(attrs); 260 return sty; 261 } 262 263 /** 264 * @return the font 265 */ 266 public Font<?> getFont() { 267 return this.font; 268 } 269 270 /** 271 * @param font 272 * the font to set 273 */ 274 public void setFont(final Font<?> font) { 275 this.font = font; 276 } 277 278 /** 279 * @return the italic 280 */ 281 public boolean isItalic() { 282 return this.italic; 283 } 284 285 /** 286 * @param italic 287 * the italic to set 288 */ 289 public void setItalic(final boolean italic) { 290 this.italic = italic; 291 } 292 293 /** 294 * @return the angle 295 */ 296 public float getAngle() { 297 return this.angle; 298 } 299 300 /** 301 * @param angle 302 * the angle to set 303 */ 304 public void setAngle(final float angle) { 305 this.angle = angle; 306 } 307 308 /** 309 * @return the colour 310 */ 311 public T getColour() { 312 return this.colour; 313 } 314 315 /** 316 * @param colour 317 * the colour to set 318 */ 319 public void setColour(final T colour) { 320 this.colour = colour; 321 } 322 323 /** 324 * @return the horizontalAlignment 325 */ 326 public HorizontalAlignment getHorizontalAlignment() { 327 return this.horizontalAlignment; 328 } 329 330 /** 331 * @param horizontalAlignment 332 * the horizontalAlignment to set 333 */ 334 public void setHorizontalAlignment(final HorizontalAlignment horizontalAlignment) { 335 this.horizontalAlignment = horizontalAlignment; 336 } 337 338 /** 339 * @return the verticalAlignment 340 */ 341 public VerticalAlignment getVerticalAlignment() { 342 return this.verticalAlignment; 343 } 344 345 /** 346 * @param verticalAlignment 347 * the verticalAlignment to set 348 */ 349 public void setVerticalAlignment(final VerticalAlignment verticalAlignment) { 350 this.verticalAlignment = verticalAlignment; 351 } 352 353 /** 354 * @return the fontSize 355 */ 356 public int getFontSize() { 357 return this.fontSize; 358 } 359 360 /** 361 * @param fontSize 362 * the fontSize to set 363 */ 364 public void setFontSize(final int fontSize) { 365 this.fontSize = fontSize; 366 } 367}