1 /** 2 * Copyright 2011 JogAmp Community. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without modification, are 5 * permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, this list of 8 * conditions and the following disclaimer. 9 * 10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 * of conditions and the following disclaimer in the documentation and/or other materials 12 * provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED 15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * 24 * The views and conclusions contained in the software and documentation are those of the 25 * authors and should not be interpreted as representing official policies, either expressed 26 * or implied, of JogAmp Community. 27 */ 28 package jogamp.graph.font.typecast; 29 30 import com.jogamp.common.util.IntIntHashMap; 31 import com.jogamp.graph.curve.OutlineShape; 32 import com.jogamp.graph.font.Font; 33 import com.jogamp.opengl.math.geom.AABBox; 34 35 public final class TypecastGlyph implements Font.Glyph { 36 public static final class Advance 37 { 38 private final Font font; 39 private final float advance; 40 private final IntIntHashMap size2advanceI = new IntIntHashMap(); 41 Advance(final Font font, final float advance)42 public Advance(final Font font, final float advance) 43 { 44 this.font = font; 45 this.advance = advance; 46 size2advanceI.setKeyNotFoundValue(0); 47 } 48 reset()49 public final void reset() { 50 size2advanceI.clear(); 51 } 52 getFont()53 public final Font getFont() { return font; } 54 getScale(final float pixelSize)55 public final float getScale(final float pixelSize) 56 { 57 return this.font.getMetrics().getScale(pixelSize); 58 } 59 add(final float advance, final float size)60 public final void add(final float advance, final float size) 61 { 62 size2advanceI.put(Float.floatToIntBits(size), Float.floatToIntBits(advance)); 63 } 64 get(final float pixelSize, final boolean useFrationalMetrics)65 public final float get(final float pixelSize, final boolean useFrationalMetrics) 66 { 67 final int sI = Float.floatToIntBits(pixelSize); 68 final int aI = size2advanceI.get(sI); 69 if( 0 != aI ) { 70 return Float.intBitsToFloat(aI); 71 } 72 final float a; 73 if ( useFrationalMetrics ) { 74 a = this.advance * getScale(pixelSize); 75 } else { 76 // a = Math.ceil(this.advance * getScale(pixelSize)); 77 a = Math.round(this.advance * getScale(pixelSize)); // TODO: check whether ceil should be used instead? 78 } 79 size2advanceI.put(sI, Float.floatToIntBits(a)); 80 return a; 81 } 82 83 @Override toString()84 public final String toString() 85 { 86 return "\nAdvance:"+ 87 "\n advance: "+this.advance+ 88 "\n advances: \n"+size2advanceI; 89 } 90 } 91 92 public static final class Metrics 93 { 94 private final AABBox bbox; 95 private final Advance advance; 96 Metrics(final Font font, final AABBox bbox, final float advance)97 public Metrics(final Font font, final AABBox bbox, final float advance) 98 { 99 this.bbox = bbox; 100 this.advance = new Advance(font, advance); 101 } 102 reset()103 public final void reset() { 104 advance.reset(); 105 } 106 getFont()107 public final Font getFont() { return advance.getFont(); } 108 getScale(final float pixelSize)109 public final float getScale(final float pixelSize) 110 { 111 return this.advance.getScale(pixelSize); 112 } 113 getBBox()114 public final AABBox getBBox() 115 { 116 return this.bbox; 117 } 118 addAdvance(final float advance, final float size)119 public final void addAdvance(final float advance, final float size) 120 { 121 this.advance.add(advance, size); 122 } 123 getAdvance(final float pixelSize, final boolean useFrationalMetrics)124 public final float getAdvance(final float pixelSize, final boolean useFrationalMetrics) 125 { 126 return this.advance.get(pixelSize, useFrationalMetrics); 127 } 128 129 @Override toString()130 public final String toString() 131 { 132 return "\nMetrics:"+ 133 "\n bbox: "+this.bbox+ 134 this.advance; 135 } 136 } 137 138 public static final short INVALID_ID = (short)((1 << 16) - 1); 139 public static final short MAX_ID = (short)((1 << 16) - 2); 140 141 private final char symbol; 142 private final OutlineShape shape; // in EM units 143 private final short id; 144 private final Metrics metrics; 145 TypecastGlyph(final Font font, final char symbol, final short id, final AABBox bbox, final int advance, final OutlineShape shape)146 protected TypecastGlyph(final Font font, final char symbol, final short id, final AABBox bbox, final int advance, final OutlineShape shape) { 147 this.symbol = symbol; 148 this.shape = shape; 149 this.id = id; 150 this.metrics = new Metrics(font, bbox, advance); 151 } 152 153 @Override getFont()154 public final Font getFont() { 155 return this.metrics.getFont(); 156 } 157 158 @Override getSymbol()159 public final char getSymbol() { 160 return this.symbol; 161 } 162 getBBoxUnsized()163 final AABBox getBBoxUnsized() { 164 return this.metrics.getBBox(); 165 } 166 167 @Override getBBox()168 public final AABBox getBBox() { 169 return this.metrics.getBBox(); 170 } 171 getMetrics()172 public final Metrics getMetrics() { 173 return this.metrics; 174 } 175 176 @Override getID()177 public final short getID() { 178 return this.id; 179 } 180 181 @Override getScale(final float pixelSize)182 public final float getScale(final float pixelSize) { 183 return this.metrics.getScale(pixelSize); 184 } 185 186 @Override getBBox(final AABBox dest, final float pixelSize, final float[] tmpV3)187 public final AABBox getBBox(final AABBox dest, final float pixelSize, final float[] tmpV3) { 188 return dest.copy(getBBox()).scale(getScale(pixelSize), tmpV3); 189 } 190 addAdvance(final float advance, final float size)191 protected final void addAdvance(final float advance, final float size) { 192 this.metrics.addAdvance(advance, size); 193 } 194 195 @Override getAdvance(final float pixelSize, final boolean useFrationalMetrics)196 public final float getAdvance(final float pixelSize, final boolean useFrationalMetrics) { 197 return this.metrics.getAdvance(pixelSize, useFrationalMetrics); 198 } 199 200 @Override getShape()201 public final OutlineShape getShape() { 202 return this.shape; 203 } 204 205 @Override hashCode()206 public final int hashCode() { 207 // 31 * x == (x << 5) - x 208 final int hash = 31 + getFont().getName(Font.NAME_UNIQUNAME).hashCode(); 209 return ((hash << 5) - hash) + id; 210 } 211 } 212