1 /******************************************************************************* 2 * Copyright 2011 See AUTHORS file. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 17 package com.badlogic.gdx.tools.hiero.unicodefont; 18 19 import java.awt.Font; 20 import java.awt.Rectangle; 21 import java.awt.Shape; 22 import java.awt.font.GlyphMetrics; 23 import java.awt.font.GlyphVector; 24 25 import com.badlogic.gdx.graphics.Texture; 26 import com.badlogic.gdx.graphics.g2d.BitmapFont; 27 import com.badlogic.gdx.tools.hiero.unicodefont.UnicodeFont.RenderType; 28 29 /** Represents the glyph in a font for a unicode codepoint. 30 * @author Nathan Sweet */ 31 public class Glyph { 32 private int codePoint; 33 private short width, height; 34 private short yOffset; 35 private boolean isMissing; 36 private Shape shape; 37 float u, v, u2, v2; 38 private int xOffset, xAdvance; 39 Texture texture; 40 Glyph(int codePoint, Rectangle bounds, GlyphVector vector, int index, UnicodeFont unicodeFont)41 Glyph (int codePoint, Rectangle bounds, GlyphVector vector, int index, UnicodeFont unicodeFont) { 42 this.codePoint = codePoint; 43 44 int padTop = unicodeFont.getPaddingTop(), padBottom = unicodeFont.getPaddingBottom(); 45 int padLeft = unicodeFont.getPaddingLeft(), padRight = unicodeFont.getPaddingRight(); 46 47 if (unicodeFont.renderType == RenderType.FreeType && unicodeFont.bitmapFont != null) { 48 BitmapFont.Glyph g = unicodeFont.bitmapFont.getData().getGlyph((char)codePoint); 49 if (g == null) 50 isMissing = true; 51 else { 52 boolean empty = g.width == 0 || g.height == 0; 53 width = empty ? 0 : (short)(g.width + padLeft + padRight); 54 height = empty ? 0 : (short)(g.height + padTop + padBottom); 55 yOffset = (short)(g.yoffset - padTop); 56 xOffset = g.xoffset - unicodeFont.getPaddingLeft(); 57 xAdvance = g.xadvance + unicodeFont.getPaddingAdvanceX() + unicodeFont.getPaddingLeft() 58 + unicodeFont.getPaddingRight(); 59 isMissing = codePoint == 0; 60 } 61 62 } else { 63 GlyphMetrics metrics = vector.getGlyphMetrics(index); 64 int lsb = (int)metrics.getLSB(); 65 if (lsb > 0) lsb = 0; 66 int rsb = (int)metrics.getRSB(); 67 if (rsb > 0) rsb = 0; 68 69 int glyphWidth = bounds.width - lsb - rsb; 70 int glyphHeight = bounds.height; 71 if (glyphWidth > 0 && glyphHeight > 0) { 72 width = (short)(glyphWidth + padLeft + padRight); 73 height = (short)(glyphHeight + padTop + padBottom); 74 yOffset = (short)(unicodeFont.getAscent() + bounds.y - padTop); 75 } 76 77 // xOffset and xAdvance will be incorrect for unicode characters such as combining marks or non-spacing characters 78 // (eg Pnujabi's "\u0A1C\u0A47") that require the context of surrounding glyphs to determine spacing, but this is the 79 // best we can do with the BMFont format. 80 char[] chars = Character.toChars(codePoint); 81 GlyphVector charVector = unicodeFont.getFont().layoutGlyphVector(GlyphPage.renderContext, chars, 0, chars.length, 82 Font.LAYOUT_LEFT_TO_RIGHT); 83 GlyphMetrics charMetrics = vector.getGlyphMetrics(0); 84 xOffset = vector.getGlyphPixelBounds(0, GlyphPage.renderContext, 0, 0).x - unicodeFont.getPaddingLeft(); 85 xAdvance = (int)(metrics.getAdvanceX() + unicodeFont.getPaddingAdvanceX() + unicodeFont.getPaddingLeft() 86 + unicodeFont.getPaddingRight()); 87 88 shape = vector.getGlyphOutline(index, -bounds.x + unicodeFont.getPaddingLeft(), -bounds.y + unicodeFont.getPaddingTop()); 89 90 isMissing = !unicodeFont.getFont().canDisplay((char)codePoint); 91 } 92 } 93 94 /** The unicode codepoint the glyph represents. */ getCodePoint()95 public int getCodePoint () { 96 return codePoint; 97 } 98 99 /** Returns true if the font does not have a glyph for this codepoint. */ isMissing()100 public boolean isMissing () { 101 return isMissing; 102 } 103 104 /** The width of the glyph's image. */ getWidth()105 public int getWidth () { 106 return width; 107 } 108 109 /** The height of the glyph's image. */ getHeight()110 public int getHeight () { 111 return height; 112 } 113 114 /** The shape to use to draw this glyph. This is set to null after the glyph is stored in a GlyphPage. */ getShape()115 public Shape getShape () { 116 return shape; 117 } 118 setShape(Shape shape)119 public void setShape (Shape shape) { 120 this.shape = shape; 121 } 122 setTexture(Texture texture, float u, float v, float u2, float v2)123 public void setTexture (Texture texture, float u, float v, float u2, float v2) { 124 this.texture = texture; 125 this.u = u; 126 this.v = v; 127 this.u2 = u2; 128 this.v2 = v2; 129 } 130 getTexture()131 public Texture getTexture () { 132 return texture; 133 } 134 getU()135 public float getU () { 136 return u; 137 } 138 getV()139 public float getV () { 140 return v; 141 } 142 getU2()143 public float getU2 () { 144 return u2; 145 } 146 getV2()147 public float getV2 () { 148 return v2; 149 } 150 151 /** The distance from drawing y location to top of this glyph, causing the glyph to sit on the baseline. */ getYOffset()152 public int getYOffset () { 153 return yOffset; 154 } 155 getXOffset()156 public int getXOffset () { 157 return xOffset; 158 } 159 getXAdvance()160 public int getXAdvance () { 161 return xAdvance; 162 } 163 } 164