// *************************************************************
// * TextSplat -- Version 1.3.2
// * by Deaod
// *************************************************************
// *
// * CREDITS:
// * - MasterofSickness (reported bugs and gave a cool optimization idea)
// * - Vexorian (JassHelper, ARGB, Table)
// * - PitzerMike (JassNewGenPack, original TextSplat system)
// * - MindWorX (JassNewGenPack)
// * - Pipedream (Grimoire)
// * - SFilip (TESH)
// *
// * HOW TO IMPORT:
// * * C'n'P the code into your map
// * * If you haven't done that already, import ARGB and Table into your map
// * * Set up a Font (a HOW-TO can be found inside the Font library)
// *
// * HOW TO USE:
// *
// * * Theres a procedural API and an object oriented API
// * The procedural resembles the API of texttags with one exception: You have to pass a font to the CreateTextSplat function.
// * Other than that, simply replace TextTag in the function names with TextSplat to switch over to TextSplats.
// * Note that there might be discrepancies between texttags and textsplats concerning the more obscure features of texttags,
// * such as the "suspended" attribute.
// *
// * The object oriented API, however, has more options, for example you can read the width of the textsplat in WC3 units of length.
// *
// * * declare a variable of type textsplat
// *
// * * use textsplat.create(font Font) to create a new image
// * - Refer to the documentation of the Font library for detailed information on Fonts
// *
// * * you can change the text of the textsplat by calling the method yourtsplat.setText(string text, real height, integer aligntype).
// * - text is the new text the textsplat should read
// * - height is the fontsize of the text
// * - aligntype is where the text should be aligned. Possible aligntypes:
// * TEXTSPLAT_TEXT_ALIGN_LEFT, TEXTSPLAT_TEXT_ALIGN_CENTER, TEXTSPLAT_TEXT_ALIGN_RIGHT
// * you can embed images into text (as long as the Font supports the embedded images) by surrounding the images identifier by "|i"
// * Example: "|igold|i" would be converted into the gold coin image (if the font supports it).
// * Note that image idenitifiers are case- and slash-insensitive (the latter meaning that / == \). "|ilumber|i" displays the same image as
// * "|iLuMBeR|i" does.
// *
// * * you can change the velocity of a textsplat by calling the method yourtsplat.setVelocity(real xvel, real yvel, real zvel)
// * Velocities are in (WC3 units of length)/second
// *
// * * you can change the color of the textsplat by calling the method yourtsplat.setColor(integer red, integer green, integer blue, integer alpha)
// * All parameters can take values from 0 to 255 (including 0 and 255).
// * This changes the color of all chars outside |cAARRGGBB - |r tags.
// * Changes in the value of the alpha channel are prohibited if the textsplat is currently fading.
// * Note that textsplats, unlike texttags, have a working alpha channel.
// *
// * * you can change the position of a textsplat by calling the method yourtsplat.setPosition(real x, real y, real z)
// * the point specified is the lower left corner of the textsplat.
// * Theres also a variant of this function (yourtsplat.setPosUnit(unit u, real z)) that aligns the textsplats lower left corner
// * to the units origin and with the specified z offset (from 0., not the units locations z).
// *
// * * you can access the standard attributes (lifespan, fadepoint, age, permanent, visible) of texttags as variable members of the struct.
// * Example: set yourtsplat.fadepoint=2.
// * Note that some things may not work exactly like they did with texttags. If you notice such a discrepancy, tell me about it.
// *
// * * you can access the width of the textsplat by reading the width member of the struct (yourtsplat.width).
// * Note that this member is read only.
// * It returns the width of the textsplat in standard WC3 units of length.
// *
// * * you can access the height of the textsplat by read the height member of the structs (yourtsplat.height).
// * This returns the Y size of the textsplat, much like the width member returns the X size.
// * The returned values are in standard WC3 units of length.
// *
// * * you can access and change the font of a textsplat on the fly by reading/writing the .font member
// * Note that any changes to the font only take place after the next call to .setText()
// *
// * * to destroy a textsplat use yourtsplat.destroy()
// *
// *************************************************************
library TextSplat initializer Init uses ARGB, ImageUtils, Table, Font
globals
private constant real TICK = 1./40
private constant integer DEFAULT_COLOR = 0xFFFFFFFF // white
private constant integer DEFAULT_IMAGE_TYPE = IMAGE_TYPE_SELECTION
constant integer DEFAULT_IMAGE_SIZE = 32 // If you dont know what this is used for, you might want to leave it alone to not fuck things up
constant integer TEXTSPLAT_TEXT_ALIGN_LEFT = 1
constant integer TEXTSPLAT_TEXT_ALIGN_CENTER = 2
constant integer TEXTSPLAT_TEXT_ALIGN_RIGHT = 3
constant real TEXT_SIZE_TO_IMAGE_SIZE = 4.146479
private constant integer TOKENS_PER_CHUNK = 40 // lower this if you make heavy use of |cAARRGGBB strings in textsplats. Maximum working value is about 65.
endglobals
globals
private real array TextAlignBonus
private StringTable Hex2Dec
private StringTable IsHex
endglobals
private struct char
image Img
string Path
real SizeX
real SizeY
real X
real Y
real Z
integer Type
boolean Show
boolean DefaultColor
integer ColorAlpha
integer ColorRed
integer ColorBlue
integer ColorGreen
private method Recreate takes nothing returns nothing
if .Img!=null then
call ReleaseImage(.Img)
endif
set .Img=NewImage(.Path, .SizeX, .SizeY, 0, .X, .Y, 0, 0, 0, 0, .Type)
call SetImageConstantHeight(.Img, true, .Z)
call SetImageColor(.Img, .ColorRed, .ColorGreen, .ColorBlue, .ColorAlpha)
call SetImageRenderAlways(.Img, .Show)
endmethod
method operator color= takes ARGB col returns nothing
set .ColorAlpha=col.alpha
set .ColorRed=col.red
set .ColorGreen=col.green
set .ColorBlue=col.blue
call SetImageColor(.Img, .ColorRed, .ColorGreen, .ColorBlue, .ColorAlpha)
endmethod
private static method create takes string path, real sizex, real sizey, real x, real y, real z returns thistype
local thistype s=.allocate()
set s.Path=path
set s.SizeX=sizex
set s.SizeY=sizey
set s.X=x
set s.Y=y
set s.Z=z
set s.Show=true
set s.Type=DEFAULT_IMAGE_TYPE
set s.color=DEFAULT_COLOR
call s.Recreate()
return s
endmethod
static method createChar takes font f, string ch, real x, real y, real z, real size returns thistype
return .create(f[ch].path, size*TEXT_SIZE_TO_IMAGE_SIZE, size*TEXT_SIZE_TO_IMAGE_SIZE, x, y, z)
endmethod
static method createImage takes font f, string img, real x, real y, real z, real size returns thistype
return .create(f.getImage(img).path, size*TEXT_SIZE_TO_IMAGE_SIZE, size*TEXT_SIZE_TO_IMAGE_SIZE, x, y, z)
endmethod
method onDestroy takes nothing returns nothing
if .Img!=null then
call ReleaseImage(.Img)
endif
set .Img=null
endmethod
endstruct
private struct TextToken extends array
integer tokenType
string value
ARGB valueColor
boolean isDefaultColor
integer line
real posX
real posY
static constant integer TOKEN_TYPE_INVALID = 0
static constant integer TOKEN_TYPE_NORMAL = 1
static constant integer TOKEN_TYPE_NEWLINE = 2
static constant integer TOKEN_TYPE_COLOR = 3
static constant integer TOKEN_TYPE_COLOREND = 4
static constant integer TOKEN_TYPE_IMAGE = 5
endstruct
globals
private real array LineWidth
private string array TextChars
private real MaxLineWidth
private integer TSPCount
private integer TSPSourceStringLength
private integer CurrentLine
private ARGB CurrentColor
private boolean IsDefaultColor
private char TSPChar
private real SourceX
private real SourceY
private integer TokenAmount
private TextToken CurrentToken
private location LocZ=Location(0,0)
endglobals
private function IsHexadecimal takes integer offset returns boolean
local integer i = offset
local integer l = i + 8
loop
exitwhen i >= l
if IsHex[TextChars[i]] == 0 then
// one illegal char aborts
return false
endif
set i=i+1
endloop
return true
endfunction
private function prepareText takes string text returns nothing
local integer i = 0
loop
exitwhen i >= TSPSourceStringLength
set TextChars[i] = SubString(text, i, i+1)
set i = i + 1
endloop
// zero termination
set TextChars[i] = null
endfunction
// this is a bit hacky... but necessary to avoid hitting the op limit.
private function tokenizeText takes TextToken base returns nothing
local integer i = TSPCount
local string curChar
local TextToken token = CurrentToken
loop
exitwhen (integer(token) - integer(base) >= TOKENS_PER_CHUNK) or (i >= TSPSourceStringLength)
set curChar = TextChars[i]
// check for \n or \r\n or |n
if curChar=="\n" or (curChar=="\r" and TextChars[i + 1] == "\n") or (curChar=="|" and TextChars[i + 1]=="n") then
set token.tokenType = TextToken.TOKEN_TYPE_NEWLINE
set token = TextToken(integer(token) + 1)
if curChar != "\n" then
set i = i + 1
endif
elseif curChar=="|" and TextChars[i + 1] == "c" and TSPSourceStringLength - i >= 10 and IsHexadecimal(i + 2) then
set token.tokenType = TextToken.TOKEN_TYPE_COLOR
set token.valueColor = ARGB.create(Hex2Dec[TextChars[i + 2] + TextChars[i + 3]], Hex2Dec[TextChars[i + 4] + TextChars[i + 5]], Hex2Dec[TextChars[i + 6] + TextChars[i + 7]], Hex2Dec[TextChars[i + 8] + TextChars[i + 9]])
set token = TextToken(integer(token) + 1)
set i = i + 9
elseif curChar=="|" and TextChars[i + 1] == "r" then
set token.tokenType = TextToken.TOKEN_TYPE_COLOREND
set token = TextToken(integer(token) + 1)
set i = i + 1
elseif curChar == "|" and TextChars[i + 1] == "i" then
set i = i + 2
set token.tokenType = TextToken.TOKEN_TYPE_IMAGE
set token.value = ""
loop
exitwhen (TextChars[i] == "|" and TextChars[i + 1] == "i") or (i >= TSPSourceStringLength)
set token.value = token.value + TextChars[i]
set i = i + 1
endloop
set token = TextToken(integer(token) + 1)
set i = i + 1
else // normal char
set token.tokenType = TextToken.TOKEN_TYPE_NORMAL
set token.value = curChar
set token = TextToken(integer(token) + 1)
endif
set i = i + 1
endloop
set CurrentToken = token
set TSPCount = i
endfunction
private function layoutText takes TextToken base, ARGB backgroundColor, font textFont, real lineHeight returns nothing
local TextToken token = CurrentToken
local real width
loop
exitwhen (integer(token) - integer(base) >= TOKENS_PER_CHUNK) or (integer(token) >= TokenAmount)
if token.tokenType == TextToken.TOKEN_TYPE_NEWLINE then
if LineWidth[CurrentLine] > MaxLineWidth or CurrentLine == 0 then
set MaxLineWidth = LineWidth[CurrentLine]
endif
set CurrentLine = CurrentLine + 1
set LineWidth[CurrentLine] = 0
elseif token.tokenType == TextToken.TOKEN_TYPE_COLOR then
set CurrentColor = token.valueColor
set IsDefaultColor = false
elseif token.tokenType == TextToken.TOKEN_TYPE_COLOREND then
set CurrentColor = backgroundColor
set IsDefaultColor = true
elseif token.tokenType == TextToken.TOKEN_TYPE_IMAGE or token.tokenType == TextToken.TOKEN_TYPE_NORMAL then
set token.valueColor = CurrentColor
set token.isDefaultColor = IsDefaultColor
set token.line = CurrentLine
if token.tokenType == TextToken.TOKEN_TYPE_IMAGE then
set width = (textFont.getImage(token.value).width * TEXT_SIZE_TO_IMAGE_SIZE * lineHeight / DEFAULT_IMAGE_SIZE)
else
set width = (textFont[token.value].width * TEXT_SIZE_TO_IMAGE_SIZE * lineHeight / DEFAULT_IMAGE_SIZE)
endif
set token.posY = CurrentLine * lineHeight * TEXT_SIZE_TO_IMAGE_SIZE
set token.posX = LineWidth[CurrentLine]
set LineWidth[CurrentLine] = LineWidth[CurrentLine] + width
endif
set token = TextToken(integer(token) + 1)
endloop
set CurrentToken = token
endfunction
private function displayText takes TextToken base, real lineHeight, integer alignType, real z, boolean visible, font textFont, Table t returns nothing
local integer i
local boolean b
local TextToken token = CurrentToken
local real x
local real y
loop
exitwhen (integer(token) - integer(base) >= TOKENS_PER_CHUNK) or (integer(token) >= TokenAmount)
if token.tokenType == TextToken.TOKEN_TYPE_IMAGE or token.tokenType == TextToken.TOKEN_TYPE_NORMAL then
set x = SourceX + token.posX + ( TextAlignBonus[alignType] * (MaxLineWidth - LineWidth[token.line]) )
set y = SourceY - token.posY
if token.tokenType == TextToken.TOKEN_TYPE_IMAGE then
set TSPChar = char.createImage(textFont, token.value, x, y, z, lineHeight)
else
set TSPChar = char.createChar(textFont, token.value, x, y, z, lineHeight)
endif
set TSPChar.DefaultColor = token.isDefaultColor
set TSPChar.color = token.valueColor
set TSPChar.Show = visible
call SetImageRenderAlways(TSPChar.Img, visible)
set t[TSPCount] = integer(TSPChar)
set TSPCount=TSPCount+1
endif
set token = TextToken(integer(token) + 1)
endloop
set CurrentToken = token
endfunction
// destroys all chars of the textsplat
private function cleanSplat takes Table t, integer count returns nothing
local integer i=count-1
local integer j
loop
exitwhen i<0
set j=t[i]
if j>0 then
call char(j).destroy()
endif
set i=i-1
endloop
endfunction
struct textsplat
private font F
private Table Chars
private integer CharCount=0
private real X=0.
private real Y=0.
private real Z=0.
private real Dx=0.
private real Dy=0.
private real Dz=0.
private real Age=0.
private real Lifespan=0.
private real Fadepoint=0.
private real Width=0.
private real Height=0.
private boolean Suspended=false
private boolean Permanent=true
private boolean Visible=true
private string Text=""
private ARGB BGColor=ARGB(DEFAULT_COLOR)
private integer i
private static thistype array Structs
private static timer T=CreateTimer()
private static integer Count=0
method onDestroy takes nothing returns nothing
local integer i=0
call cleanSplat.evaluate(.Chars, .CharCount)
call .Chars.destroy()
// clean your struct here
set .Count=.Count-1
set .Structs[.i]=.Structs[.Count]
set .Structs[.i].i=.i
if .Count==0 then
call PauseTimer(.T)
endif
endmethod
private static method Callback takes nothing returns nothing
local integer i=.Count-1
local thistype s
local integer j
local char ch
local boolean b1
local real alphafactor
loop
exitwhen i<0
set s=.Structs[i]
if (not s.Suspended) then
if s.Lifespan>s.Age then
set s.Age=s.Age+TICK
if s.Age>=s.Lifespan then
if s.Permanent then
set s.Suspended=true
else
call s.destroy()
endif
endif
endif
if (s.Dx!=0 or s.Dy!=0 or s.Dz!=0) then
set s.X=s.X+s.Dx
set s.Y=s.Y+s.Dy
set s.Z=s.Z+s.Dz
set j=s.CharCount-1
set b1=s.Dz!=0.
if s.Age>s.Fadepoint then
set alphafactor=1-(s.Age-s.Fadepoint)/(s.Lifespan-s.Fadepoint)
else
set alphafactor=1.
endif
loop
exitwhen j<0
set ch=s.Chars[j]
if ch>0 then
set ch.X=ch.X+s.Dx
set ch.Y=ch.Y+s.Dy
call SetImagePosition(ch.Img, ch.X, ch.Y, 0)
if b1 then // s.Dz!=0.
set ch.Z=ch.Z+s.Dz
call SetImageConstantHeight(ch.Img, true, ch.Z)
endif
call SetImageColor(ch.Img, ch.ColorRed, ch.ColorGreen, ch.ColorBlue, R2I(ch.ColorAlpha*alphafactor))
endif
set j=j-1
endloop
endif
endif
set i=i-1
endloop
endmethod
method setText takes string text, real height, integer aligntype returns nothing
set TSPSourceStringLength=StringLength(text)
set CurrentLine=0
set CurrentColor=.BGColor
set IsDefaultColor = true
set MaxLineWidth=0
// lets clean up old stuff we dont need anymore
call cleanSplat.evaluate(.Chars, .CharCount)
call prepareText.evaluate(text)
set LineWidth[0]=0
//
set TSPCount=0
set CurrentToken = TextToken(0)
loop
exitwhen TSPCount >= TSPSourceStringLength // TSPCount gets incremented in processText
call tokenizeText.evaluate(CurrentToken)
endloop
set TokenAmount = integer(CurrentToken)
set CurrentToken = TextToken(0)
loop
exitwhen integer(CurrentToken) >= TokenAmount
call layoutText.evaluate(CurrentToken, .BGColor, .F, height)
endloop
if CurrentLine == 0 or LineWidth[CurrentLine] > MaxLineWidth then
set MaxLineWidth = LineWidth[CurrentLine]
endif
// actually display the shit
set SourceX = .X
set SourceY = .Y + CurrentLine * height * TEXT_SIZE_TO_IMAGE_SIZE
set TSPCount=0
set CurrentToken = TextToken(0)
loop
exitwhen integer(CurrentToken) >= TokenAmount
call displayText.evaluate(CurrentToken, height, aligntype, .Z, .Visible, .F, .Chars)
endloop
set .CharCount = TSPCount
set .Text = text
set .Width = MaxLineWidth
set .Height = (CurrentLine + 1) * height * TEXT_SIZE_TO_IMAGE_SIZE
endmethod
method setVelocity takes real xvel, real yvel, real zvel returns nothing
set .Dx = xvel * TICK
set .Dy = yvel * TICK
set .Dz = zvel * TICK
endmethod
method setColor takes integer red, integer green, integer blue, integer alpha returns nothing
local integer i=0
local char ch
local real alphafactor
set .BGColor=ARGB.create(alpha, red, green, blue)
if .Age>.Fadepoint and not(.Lifespan==.Fadepoint) then
set alphafactor=1-(.Age-.Fadepoint)/(.Lifespan-.Fadepoint)
else
set alphafactor=1.
endif
loop
exitwhen i>=.CharCount
set ch=char(.Chars[i])
if ch>0 and ch.DefaultColor then
set ch.ColorRed=red
set ch.ColorGreen=green
set ch.ColorBlue=blue
set ch.ColorAlpha=alpha
call SetImageColor(ch.Img, red, green, blue, R2I(alpha*alphafactor))
endif
set i=i+1
endloop
endmethod
method setPosition takes real x, real y, real z returns nothing
local integer i=.CharCount-1
local real dx=x-.X
local real dy=y-.Y
local real dz=z-.Z
local char c
set .X=x
set .Y=y
set .Z=z
loop
exitwhen i<0
set c=char(.Chars[i])
if c>0 then
set c.X=c.X+dx
set c.Y=c.Y+dy
set c.Z=c.Z+dz
call SetImagePosition(c.Img, c.X, c.Y, 0)
call SetImageConstantHeight(c.Img, true, c.Z)
endif
set i=i-1
endloop
endmethod
method setPosUnit takes unit u, real z returns nothing
call .setPosition(GetUnitX(u), GetUnitY(u), z)
endmethod
method operator age takes nothing returns real
return .Age
endmethod
method operator lifespan takes nothing returns real
return .Lifespan
endmethod
method operator fadepoint takes nothing returns real
return .Fadepoint
endmethod
method operator width takes nothing returns real
return .Width
endmethod
method operator height takes nothing returns real
return .Height
endmethod
method operator suspended takes nothing returns boolean
return .Suspended
endmethod
method operator permanent takes nothing returns boolean
return .Permanent
endmethod
method operator visible takes nothing returns boolean
return .Visible
endmethod
method operator font takes nothing returns font
return .F
endmethod
method operator age= takes real new returns nothing
set .Age=new
endmethod
method operator lifespan= takes real new returns nothing
set .Lifespan=new
endmethod
method operator fadepoint= takes real new returns nothing
set .Fadepoint=new
endmethod
//
// -- Width is readonly
//
//
// -- Height is readonly
//
method operator suspended= takes boolean flag returns nothing
set .Suspended=flag
endmethod
method operator permanent= takes boolean flag returns nothing
set .Permanent=flag
endmethod
method operator visible= takes boolean flag returns nothing
local integer i=0
local char c
set .Visible=flag
loop
exitwhen i>=.CharCount
set c=char(.Chars[i])
if c>0 then
set c.Show=flag
call SetImageRenderAlways(c.Img, flag)
endif
set i=i+1
endloop
endmethod
method operator font= takes font F returns nothing
set .F=F
endmethod
static method create takes font F returns thistype
local thistype s=.allocate()
set s.F=F
set s.Chars=Table.create()
set .Structs[.Count]=s
set s.i=.Count
if .Count==0 then
call TimerStart(.T, TICK, true, function thistype.Callback)
endif
set .Count=.Count+1
return s
endmethod
endstruct
// Standard API
// a replacement for the TextTag API
function CreateTextSplat takes font F returns textsplat
return textsplat.create(F)
endfunction
function DestroyTextSplat takes textsplat which returns nothing
call which.destroy()
endfunction
function SetTextSplatAge takes textsplat t, real age returns nothing
set t.age=age
endfunction
function SetTextSplatColor takes textsplat t, integer red, integer green, integer blue, integer alpha returns nothing
call t.setColor(red, green, blue, alpha)
endfunction
function SetTextSplatFadepoint takes textsplat t, real fadepoint returns nothing
set t.fadepoint=fadepoint
endfunction
function SetTextSplatLifespan takes textsplat t, real lifespan returns nothing
set t.lifespan=lifespan
endfunction
function SetTextSplatPermanent takes textsplat t, boolean flag returns nothing
set t.permanent=flag
endfunction
function SetTextSplatPos takes textsplat t, real x, real y, real heightOffset returns nothing
call t.setPosition(x,y, heightOffset)
endfunction
function SetTextSplatPosUnit takes textsplat t, unit whichUnit, real heightOffset returns nothing
call t.setPosUnit(whichUnit, heightOffset)
endfunction
function SetTextSplatSuspended takes textsplat t, boolean flag returns nothing
set t.suspended=flag
endfunction
function SetTextSplatText takes textsplat t, string s, real height returns nothing
call t.setText(s, height, TEXTSPLAT_TEXT_ALIGN_CENTER)
endfunction
function SetTextSplatVelocity takes textsplat t, real xvel, real yvel returns nothing
call t.setVelocity(xvel, yvel, 0)
endfunction
function SetTextSplatVisibility takes textsplat t, boolean flag returns nothing
set t.visible=flag
endfunction
//! textmacro Hex2DecUpper_Macro takes L
set Hex2Dec["$L$0"]=0x$L$0
set Hex2Dec["$L$1"]=0x$L$1
set Hex2Dec["$L$2"]=0x$L$2
set Hex2Dec["$L$3"]=0x$L$3
set Hex2Dec["$L$4"]=0x$L$4
set Hex2Dec["$L$5"]=0x$L$5
set Hex2Dec["$L$6"]=0x$L$6
set Hex2Dec["$L$7"]=0x$L$7
set Hex2Dec["$L$8"]=0x$L$8
set Hex2Dec["$L$9"]=0x$L$9
set Hex2Dec["$L$A"]=0x$L$A
set Hex2Dec["$L$B"]=0x$L$B
set Hex2Dec["$L$C"]=0x$L$C
set Hex2Dec["$L$D"]=0x$L$D
set Hex2Dec["$L$E"]=0x$L$E
set Hex2Dec["$L$F"]=0x$L$F
//! endtextmacro
private function Init takes nothing returns nothing
set Hex2Dec=StringTable.create()
//! runtextmacro Hex2DecUpper_Macro("0")
//! runtextmacro Hex2DecUpper_Macro("1")
//! runtextmacro Hex2DecUpper_Macro("2")
//! runtextmacro Hex2DecUpper_Macro("3")
//! runtextmacro Hex2DecUpper_Macro("4")
//! runtextmacro Hex2DecUpper_Macro("5")
//! runtextmacro Hex2DecUpper_Macro("6")
//! runtextmacro Hex2DecUpper_Macro("7")
//! runtextmacro Hex2DecUpper_Macro("8")
//! runtextmacro Hex2DecUpper_Macro("9")
//! runtextmacro Hex2DecUpper_Macro("A")
//! runtextmacro Hex2DecUpper_Macro("B")
//! runtextmacro Hex2DecUpper_Macro("C")
//! runtextmacro Hex2DecUpper_Macro("D")
//! runtextmacro Hex2DecUpper_Macro("E")
//! runtextmacro Hex2DecUpper_Macro("F")
set IsHex=StringTable.create()
set IsHex["0"]=1
set IsHex["1"]=1
set IsHex["2"]=1
set IsHex["3"]=1
set IsHex["4"]=1
set IsHex["5"]=1
set IsHex["6"]=1
set IsHex["7"]=1
set IsHex["8"]=1
set IsHex["9"]=1
set IsHex["A"]=1
set IsHex["B"]=1
set IsHex["C"]=1
set IsHex["D"]=1
set IsHex["E"]=1
set IsHex["F"]=1
set TextAlignBonus[TEXTSPLAT_TEXT_ALIGN_LEFT ] = 0.0
set TextAlignBonus[TEXTSPLAT_TEXT_ALIGN_CENTER ] = 0.5
set TextAlignBonus[TEXTSPLAT_TEXT_ALIGN_RIGHT ] = 1.0
endfunction
endlibrary