package com.gebauz.bauzoid.graphics;
import java.util.Hashtable;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.gebauz.bauzoid.graphics.sprite.Sprite;
import com.gebauz.bauzoid.graphics.sprite.SpriteInstance;
import com.gebauz.bauzoid.graphics.sprite.TileBatch;
import com.gebauz.bauzoid.math.Vector4;
public class Font extends GraphicsObject
{
public static final Vector4 DEFAULT_COLOR =
new Vector4
(1,
1,
1,
1);
public static class KerningPair
{
public char first
;
public char second
;
public KerningPair
(char a,
char b
)
{
first = a
;
second = b
;
}
@
Override
public boolean equals
(Object other
)
{
// Not strictly necessary, but often a good optimization
if (this == other
)
return true;
if (!(other
instanceof KerningPair
))
return false;
KerningPair p =
(KerningPair
)other
;
return ((first == p.
first) && (second == p.
second));
}
@
Override
public int hashCode
()
{
return (first
* 256) + second
;
}
}
public static class CharacterInfo
{
private char mCharacter
;
private SpriteInstance mSpriteInstance =
null;
public float offsetX =
0;
public float offsetY =
0;
public float width
;
public CharacterInfo
(char c
)
{
mCharacter = c
;
}
public final char getCharacter
()
{
return mCharacter
;
}
public void setSpriteInstance
(SpriteInstance instance
)
{
mSpriteInstance = instance
;
}
public final SpriteInstance getSpriteInstance
()
{
return mSpriteInstance
;
}
public void render
()
{
if (mSpriteInstance ==
null)
return;
mSpriteInstance.
render();
}
}
private CharacterInfo
[] mCharacters =
null;
private float mAscent = 0.0f
;
private float mGlobalMultiplier = 2.0f
;
private Sprite mSprite =
null;
private Hashtable<KerningPair,
Integer> mKernings =
new Hashtable<KerningPair,
Integer>();
/** The y difference of a line break in multiples of line height. */
private float mLineBreakFactor = 1.0f
;
public Font(Graphics graphics
)
{
super(graphics
);
}
public void dispose
()
{
mCharacters =
null;
}
public void setAscent
(float ascent
)
{
mAscent = ascent
;
}
public void setCharacters
(CharacterInfo
[] characters
)
{
mCharacters = characters
;
}
public void setSprite
(Sprite sprite
)
{
mSprite = sprite
;
}
public void setGlobalMultiplier
(float multiplier
)
{
mGlobalMultiplier = multiplier
;
}
public void drawText
(String text,
float x,
float y,
float scale
)
{
drawText
(text, x, y, DEFAULT_COLOR, scale
);
}
public void drawText
(String text,
float x,
float y
)
{
drawText
(text, x, y, DEFAULT_COLOR
);
}
public void drawText
(String text,
float x,
float y, Vector4 color
)
{
drawText
(text, x, y, color, 1.0f
);
}
public void drawTextDirect
(String text,
float x,
float y, Vector4 color,
float scale
)
{
float posX = x
;
float posY = y
;
for (int i =
0; i
< text.
length(); i++
)
{
if (text.
charAt(i
) ==
'\n')
{
posY += mAscent
* mLineBreakFactor
* scale
;
posX = x
;
continue;
}
int n = getCharacterIndexNoCase
(text.
charAt(i
));
if (n == -
1)
{
continue;
}
CharacterInfo c = mCharacters
[n
];
int kerning =
0;
if (i
< (text.
length()-
1))
{
// apply kerning if any
char first = c.
getCharacter();
char second = text.
charAt(i+
1);
kerning = getKerning
(first, second
);
}
if (c.
mSpriteInstance !=
null)
{
float texW = c.
mSpriteInstance.
getSprite().
getTextureWidth();
float texH = c.
mSpriteInstance.
getSprite().
getTextureHeight();
c.
mSpriteInstance.
transform.
x = posX
;
c.
mSpriteInstance.
transform.
y = posY
;
c.
mSpriteInstance.
color = color
;
c.
mSpriteInstance.
transform.
w = c.
mSpriteInstance.
getSpriteRegion().
getWidth() * texW
* scale
* mGlobalMultiplier
;
c.
mSpriteInstance.
transform.
h = c.
mSpriteInstance.
getSpriteRegion().
getHeight() * texH
* scale
* mGlobalMultiplier
;
//c.mSpriteInstance.param.w = mSprite.getRegionWidth(c.mSpriteInstance.getRegionIndex()) * scale * mGlobalMultiplier;
//c.mSpriteInstance.param.h = mSprite.getRegionHeight(c.mSpriteInstance.getRegionIndex()) * scale * mGlobalMultiplier;
c.
mSpriteInstance.
transform.
pivotX =
0;
c.
mSpriteInstance.
transform.
pivotY =
0;
c.
mSpriteInstance.
render();
}
posX += c.
width * scale + kerning - c.
offsetX;
}
}
public void drawText
(String text,
float x,
float y, Vector4 color,
float scale
)
{
float posX = x
;
float posY = y
;
TileBatch batch = getGraphics
().
getBatch();
batch.
begin();
for (int i =
0; i
< text.
length(); i++
)
{
if (text.
charAt(i
) ==
'\n')
{
posY += mAscent
* mLineBreakFactor
* scale
;
posX = x
;
continue;
}
int n = getCharacterIndexNoCase
(text.
charAt(i
));
if (n == -
1)
{
continue;
}
CharacterInfo c = mCharacters
[n
];
int kerning =
0;
if (i
< (text.
length()-
1))
{
// apply kerning if any
char first = c.
getCharacter();
char second = text.
charAt(i+
1);
kerning = getKerning
(first, second
);
}
if (c.
mSpriteInstance !=
null)
{
float texW = c.
mSpriteInstance.
getSprite().
getTextureWidth();
float texH = c.
mSpriteInstance.
getSprite().
getTextureHeight();
c.
mSpriteInstance.
transform.
x = posX
;
c.
mSpriteInstance.
transform.
y = posY
;
c.
mSpriteInstance.
color = color
;
c.
mSpriteInstance.
transform.
w = c.
mSpriteInstance.
getSpriteRegion().
getWidth() * texW
* scale
* mGlobalMultiplier
;
c.
mSpriteInstance.
transform.
h = c.
mSpriteInstance.
getSpriteRegion().
getHeight() * texH
* scale
* mGlobalMultiplier
;
//c.mSpriteInstance.param.w = mSprite.getRegionWidth(c.mSpriteInstance.getRegionIndex()) * scale * mGlobalMultiplier;
//c.mSpriteInstance.param.h = mSprite.getRegionHeight(c.mSpriteInstance.getRegionIndex()) * scale * mGlobalMultiplier;
c.
mSpriteInstance.
transform.
pivotX =
0;
c.
mSpriteInstance.
transform.
pivotY =
0;
batch.
drawSprite(c.
mSpriteInstance);
}
posX += c.
width * scale + kerning - c.
offsetX;
}
batch.
end();
}
public float getTextWidth
(String text,
float scale
)
{
float maxWidth =
0;
float width =
0;
float posX =
0;
for (int i =
0; i
< text.
length(); i++
)
{
if (text.
charAt(i
) ==
'\n')
{
posX =
0;
continue;
}
int n = getCharacterIndexNoCase
(text.
charAt(i
));
if (n == -
1)
{
continue;
}
CharacterInfo c = mCharacters
[n
];
int kerning =
0;
if (i
< (text.
length()-
1))
{
// apply kerning if any
char first = c.
getCharacter();
char second = text.
charAt(i+
1);
kerning = getKerning
(first, second
);
}
width = posX + c.
width * scale
;
if (maxWidth
< width
)
{
maxWidth = width
;
}
posX += c.
width * scale + kerning - c.
offsetX;
}
return maxWidth
;
}
public float getTextHeight
(String text,
float scale
)
{
float maxHeight =
0;
float posY =
0;
for (int i =
0; i
< text.
length(); i++
)
{
if (text.
charAt(i
) ==
'\n')
{
posY += mAscent
* mLineBreakFactor
* scale
;
continue;
}
int n = getCharacterIndexNoCase
(text.
charAt(i
));
if (n == -
1)
{
continue;
}
float charHeight =
this.
mAscent * scale
;
if ((posY + charHeight
) > maxHeight
)
{
maxHeight = posY + charHeight
;
}
}
return maxHeight
;
}
public int getCharacterIndex
(char c
)
{
for (int i =
0; i
< mCharacters.
length; i++
)
{
if (mCharacters
[i
].
getCharacter() == c
)
return i
;
}
return -
1;
}
public int getCharacterIndexNoCase
(char c
)
{
int n = getCharacterIndex
(c
);
if (n == -
1)
{
n = getCharacterIndex
(Character.
toLowerCase(c
));
if (n == -
1)
{
n = getCharacterIndex
(Character.
toUpperCase(c
));
}
}
return n
;
}
public CharacterInfo getCharacter
(char c
)
{
int i = getCharacterIndex
(c
);
if (i
!= -
1)
return mCharacters
[i
];
return null;
}
public void setKerning
(char first,
char second,
int value
)
{
mKernings.
put(new KerningPair
(first, second
), value
);
}
public int getKerning
(char first,
char second
)
{
Integer value = mKernings.
get(new KerningPair
(first, second
));
if (value ==
null)
return 0;
return value
;
}
public void setFiltering
(boolean filter
)
{
/*
// HACK: should use own texture class
if (filter)
getGraphics().renderStates.getTextureStage(0).setTextureFilter(mSprite.getTexture(), TextureFilter.Linear, TextureFilter.Linear);
else
getGraphics().renderStates.getTextureStage(0).setTextureFilter(mSprite.getTexture(), TextureFilter.Nearest, TextureFilter.Nearest);*/
if (filter
)
mSprite.
getTexture().
setFilter(TextureFilter.
Linear, TextureFilter.
Linear);
else
mSprite.
getTexture().
setFilter(TextureFilter.
Nearest, TextureFilter.
Nearest);
}
public final void setLineBreak
(float multiple
) { mLineBreakFactor = multiple
; }
public final float getLineBreak
() { return mLineBreakFactor
; }
}