[Log in / Register]
| News | Chat | Pastebin | Donations | Tutorials | Rules | Forums |
| Maps | Skins | Icons | Models | Spells | Tools | Jass | Packs | Hosted Projects | Starcraft II Modding | Starcraft II Resources | Galaxy Wiki |
(Keeps Hive Alive)
Go Back   The Hive Workshop > Spells


Reply
 
Thread Tools
The Hive Workshop Spells:
TextSplat 1.3.1
by Deaod
Images
Highslide JS
Details
Uploaded:15:40, 18th Oct 2009
Last Updated:23:38, 27th Feb 2010
Keywords:TextSplat, TextTag, image, text
Type:System
Category:vJASS

Some of you might remember PitzerMike's TextSplat system. Well, this one does nearly the same his did (some features have been cut off, like gradients or monospaced textsplats or attaching a textsplat to a unit), but works with 1.24.
All features that have been cut off can be replicated with the API provided by this library.

So what exactly does this library do?
Well, it tries to replicate what texttags do, which is displaying text somewhere on the map, but has some additional features, which are outlined by the documentation.

This library uses vJass, ImageUtils, ARGB and Table.

A huge thanks goes out to PitzerMike, not only for the original incarnation of TextSplat, but also for the font i used for demonstration purposes.

Changelog
18/10/09 - Version 1.0.0
- initial release

23/10/09 - Version 1.1.0
- fixed a few problems related to hitting the op-limit
- fonts now have a parent, where unknown chars will be looked up (if you dont want a font to have a parent, simply input 0 into the font.create() method).

24/10/09 - Version 1.2.0
- fixed a bug related to previous fixes concerning the op-limit
- you can now display images (smilies, ...) inside text. Refer to the documentation of both libraries for detailed information
- optimizations.

25/10/09 - Version 1.2.1
- fixed images.
- some optimizations with eye on the op-limit.
- fixed an older bug related to using the .setPosition method.

23/01/10 - Version 1.3.0
- various optimizations
- added height member
- made Font compatible to 1.23a
- you cant destroy fonts anymore (anyone who did this should burn in hell anyway, i didnt maintain backwards compat)
- requires the latest version of ImageUtils, please update it.

28/02/2010 - Version 1.3.1
- fixed errors from ImageUtils popping up


Font Code + Credits + Documentation
Jass:
// *************************************************************
// *                  Font -- Version 1.3.1
// *                        by Deaod
// *************************************************************
// *
// *    CREDITS:
// *        - 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 Table into your map
// *
// *    HOW TO USE:
// *
// *        * declare a variable of type font
// *
// *        * use font.create(font Parent) to create a new font
// *          - Parent is the font thats accessed should a char not be available in this font
// *
// *        * you can add a new symbol to the font by calling the method yourfont.addChar(string which, real width, string path).
// *          - which is the symbol you want to add to the font
// *          - width is the width of the symbol in pixels
// *          - path is the path to the image file thatll be used to display the symbol.
// *          PitzerMike attached a program for creating new fonts to his TextSplat system. I suggest you use it.
// *          The paths of the imported blps dont matter, but you should copy the width of the individual chars from the .j file that program creates.
// *          Refer to [url]http://www.wc3c.net/showthread.php?t=87798[/url] (--> Importing custom Fonts) for a guide on how to create custom fonts.
// *
// *        * you can access the width of individual characters like this: CustomFont["C"].width.
// *          To access the path associated with the character use the path attribute.
// *          Example: CustomFont["C"].path
// *          "C" can be replaced with any character that has been previously added to the font using CustomFont.addChar()
// *          The double quote character can be used like this: \" (dont be scared by the broken highlighting of TESH, itll save just fine)
// *          The backslash character like this: \\
// *
// *        * you can add custom images to a font by calling the method .addImage(string which, real width, string path)
// *          Parameters work almost exactly like the ones of .addChar(), with the exception of which being case-insensitive
// *          and "slash-insensitive" (/ and \ being the same).
// *          Images are fully compatible with parents.
// *
// *        * to access such an image you have to use CustomFont.getImage(string which)
// *          which being the same or an equivalent (slash/case-insensitivity!) of the which you passed to .addImage().
// *
// *        * Fonts are not meant to be destroyed. Just dont do it.
// *
// *************************************************************
library Font initializer Init requires Table
    
    globals
        private constant    integer             ASCII_CHAR_COUNT            = 256
        private constant    integer             COLLISION_DEPTH             = 2 // how many individual chars collide at most
    endglobals
    
    globals
        private StringTable Collisions
        private StringTable Single
        private string array CollisionMapping
        private integer array CollisionResult
    endglobals
    
    private function ASCII2Int takes string char returns integer
    local integer id
    local integer i
        set char=SubString(char, 0, 1)
        if char == "" or char == null then // manually filter out 0
            return 0
        endif
        set id=Single[char] // see if the char is a non-colliding char
        if id>0 then // if it is,
            return id // return immediately
        else // if it isnt
            set id=Collisions[char] // get the ID of the collision
            set i=0
            loop // and see which char of the two colliding ones it is
                exitwhen i>=COLLISION_DEPTH
                if CollisionMapping[id*COLLISION_DEPTH+i]==char then 
                    return CollisionResult[id*COLLISION_DEPTH+i] // found it! Return immediately, to shorten the algorithm
                endif
                set i=i+1
            endloop
        endif
        debug call BJDebugMsg("TextSplat: Faulty Setup of Collisions for ASCII2Int.")
        return 0 // this line normally shouldnt be reached. If however, it is reached, you have a faulty Setup of the Collisions
    endfunction
    
    private struct fontchar
        string path
        real width
        
        static method create takes string path, real width returns thistype
        local thistype s=.allocate()
            set s.path=path
            set s.width=width
            return s
        endmethod
    endstruct
    
    private struct fontimage
        string path
        real width
        
        static method create takes string path, real width returns thistype
        local thistype s=.allocate()
            set s.path=path
            set s.width=width
            return s
        endmethod
    endstruct
    
    struct font
        private font parent=0
        private fontchar array Symbol[ASCII_CHAR_COUNT]
        
        private StringTable Images
        
        method operator [] takes string ch returns fontchar
        local fontchar f=.Symbol[ASCII2Int(ch)]
            if f==0 then
                if .parent!=0 then
                    return .parent[ch]
                debug else
                debug     call BJDebugMsg("TextSplat: Char '"+ch+"' is not available in font "+I2S(this)+".")
                endif
            endif
            return f
        endmethod
        
        method addChar takes string which, real width, string path returns nothing
        local integer i=ASCII2Int(which)
            if i>0 then
                if .Symbol[i]==0 then
                    set .Symbol[i]=fontchar.create(path, width)
                else
                    set .Symbol[i].path=path
                    set .Symbol[i].width=width
                endif
            debug else
            debug     call BJDebugMsg("TextSplat: font.addChar: '"+which+"' could not be found in the CharMap!")
            endif
        endmethod
        
        method getImage takes string which returns fontimage
        local fontimage fi=fontimage(.Images[which])
            if fi==0 then
                if .parent!=0 then
                    return .parent.getImage(which)
                debug else
                debug     call BJDebugMsg("TextSplat: Image '"+which+"' is not available in font "+I2S(this)+".")
                endif
            endif
            return fi
        endmethod
        
        method addImage takes string which, real width, string path returns nothing
            if .Images[which]>0 then
                set fontimage(.Images[which]).path=path
                set fontimage(.Images[which]).width=width
            else
                set .Images[which]=fontimage.create(path, width)
            endif
        endmethod
        
        static method create takes font Parent returns thistype
        local thistype s=.allocate()
            set s.parent=Parent
            set s.Images=StringTable.create()
            return s
        endmethod
        
        private method destroy takes nothing returns nothing
            
        endmethod
    endstruct
    
    // What im doing here is basically precalculating some things thatll lead to a speed gain in the ASCII2Int function
    private function Init takes nothing returns nothing
        set Collisions=StringTable.create()
        set Single=StringTable.create()
        
        // First, all chars that dont collide.
        // Note that they must be !=0
        set Single["\b"]=8
        set Single["\t"]=9
        set Single["\n"]=10
        set Single["\f"]=12
        set Single["\r"]=13
        set Single[" "]=32
        set Single["!"]=33
        set Single["\""]=34
        set Single["#"]=35
        set Single["$"]=36
        set Single["%"]=37
        set Single["&"]=38
        set Single["'"]=39
        set Single["("]=40
        set Single[")"]=41
        set Single["*"]=42
        set Single["+"]=43
        set Single[","]=44
        set Single["-"]=45
        set Single["."]=46
        set Single["0"]=48
        set Single["1"]=49
        set Single["2"]=50
        set Single["3"]=51
        set Single["4"]=52
        set Single["5"]=53
        set Single["6"]=54
        set Single["7"]=55
        set Single["8"]=56
        set Single["9"]=57
        set Single[":"]=58
        set Single[";"]=59
        set Single["<"]=60
        set Single["="]=61
        set Single[">"]=62
        set Single["?"]=63
        set Single["@"]=64
        set Single["["]=91
        set Single["]"]=93
        set Single["^"]=94
        set Single["_"]=95
        set Single["`"]=96
        set Single["{"]=123
        set Single["|"]=124
        set Single["}"]=125
        set Single["~"]=126
        
        // -------------------
        
        // This is the initialization of the arrays that will map from individual chars to integers later on
        set CollisionResult[(0*COLLISION_DEPTH)+0]=65
        set CollisionResult[(1*COLLISION_DEPTH)+0]=66
        set CollisionResult[(2*COLLISION_DEPTH)+0]=67
        set CollisionResult[(3*COLLISION_DEPTH)+0]=68
        set CollisionResult[(4*COLLISION_DEPTH)+0]=69
        set CollisionResult[(5*COLLISION_DEPTH)+0]=70
        set CollisionResult[(6*COLLISION_DEPTH)+0]=71
        set CollisionResult[(7*COLLISION_DEPTH)+0]=72
        set CollisionResult[(8*COLLISION_DEPTH)+0]=73
        set CollisionResult[(9*COLLISION_DEPTH)+0]=74
        set CollisionResult[(10*COLLISION_DEPTH)+0]=75
        set CollisionResult[(11*COLLISION_DEPTH)+0]=76
        set CollisionResult[(12*COLLISION_DEPTH)+0]=77
        set CollisionResult[(13*COLLISION_DEPTH)+0]=78
        set CollisionResult[(14*COLLISION_DEPTH)+0]=79
        set CollisionResult[(15*COLLISION_DEPTH)+0]=80
        set CollisionResult[(16*COLLISION_DEPTH)+0]=81
        set CollisionResult[(17*COLLISION_DEPTH)+0]=82
        set CollisionResult[(18*COLLISION_DEPTH)+0]=83
        set CollisionResult[(19*COLLISION_DEPTH)+0]=84
        set CollisionResult[(20*COLLISION_DEPTH)+0]=85
        set CollisionResult[(21*COLLISION_DEPTH)+0]=86
        set CollisionResult[(22*COLLISION_DEPTH)+0]=87
        set CollisionResult[(23*COLLISION_DEPTH)+0]=88
        set CollisionResult[(24*COLLISION_DEPTH)+0]=89
        set CollisionResult[(25*COLLISION_DEPTH)+0]=90
        set CollisionResult[(26*COLLISION_DEPTH)+0]=47
        
        set CollisionResult[(0*COLLISION_DEPTH)+1]=97
        set CollisionResult[(1*COLLISION_DEPTH)+1]=98
        set CollisionResult[(2*COLLISION_DEPTH)+1]=99
        set CollisionResult[(3*COLLISION_DEPTH)+1]=100
        set CollisionResult[(4*COLLISION_DEPTH)+1]=101
        set CollisionResult[(5*COLLISION_DEPTH)+1]=102
        set CollisionResult[(6*COLLISION_DEPTH)+1]=103
        set CollisionResult[(7*COLLISION_DEPTH)+1]=104
        set CollisionResult[(8*COLLISION_DEPTH)+1]=105
        set CollisionResult[(9*COLLISION_DEPTH)+1]=106
        set CollisionResult[(10*COLLISION_DEPTH)+1]=107
        set CollisionResult[(11*COLLISION_DEPTH)+1]=108
        set CollisionResult[(12*COLLISION_DEPTH)+1]=109
        set CollisionResult[(13*COLLISION_DEPTH)+1]=110
        set CollisionResult[(14*COLLISION_DEPTH)+1]=111
        set CollisionResult[(15*COLLISION_DEPTH)+1]=112
        set CollisionResult[(16*COLLISION_DEPTH)+1]=113
        set CollisionResult[(17*COLLISION_DEPTH)+1]=114
        set CollisionResult[(18*COLLISION_DEPTH)+1]=115
        set CollisionResult[(19*COLLISION_DEPTH)+1]=116
        set CollisionResult[(20*COLLISION_DEPTH)+1]=117
        set CollisionResult[(21*COLLISION_DEPTH)+1]=118
        set CollisionResult[(22*COLLISION_DEPTH)+1]=119
        set CollisionResult[(23*COLLISION_DEPTH)+1]=120
        set CollisionResult[(24*COLLISION_DEPTH)+1]=121
        set CollisionResult[(25*COLLISION_DEPTH)+1]=122
        set CollisionResult[(26*COLLISION_DEPTH)+1]=92
        
        // --------------------
        
        // This maps the ID of the collision onto the colliding chars, which are stored in this virtual 2D array
        set CollisionMapping[ 0*(COLLISION_DEPTH)+0]="A"
        set CollisionMapping[ 1*(COLLISION_DEPTH)+0]="B"
        set CollisionMapping[ 2*(COLLISION_DEPTH)+0]="C"
        set CollisionMapping[ 3*(COLLISION_DEPTH)+0]="D"
        set CollisionMapping[ 4*(COLLISION_DEPTH)+0]="E"
        set CollisionMapping[ 5*(COLLISION_DEPTH)+0]="F"
        set CollisionMapping[ 6*(COLLISION_DEPTH)+0]="G"
        set CollisionMapping[ 7*(COLLISION_DEPTH)+0]="H"
        set CollisionMapping[ 8*(COLLISION_DEPTH)+0]="I"
        set CollisionMapping[ 9*(COLLISION_DEPTH)+0]="J"
        set CollisionMapping[10*(COLLISION_DEPTH)+0]="K"
        set CollisionMapping[11*(COLLISION_DEPTH)+0]="L"
        set CollisionMapping[12*(COLLISION_DEPTH)+0]="M"
        set CollisionMapping[13*(COLLISION_DEPTH)+0]="N"
        set CollisionMapping[14*(COLLISION_DEPTH)+0]="O"
        set CollisionMapping[15*(COLLISION_DEPTH)+0]="P"
        set CollisionMapping[16*(COLLISION_DEPTH)+0]="Q"
        set CollisionMapping[17*(COLLISION_DEPTH)+0]="R"
        set CollisionMapping[18*(COLLISION_DEPTH)+0]="S"
        set CollisionMapping[19*(COLLISION_DEPTH)+0]="T"
        set CollisionMapping[20*(COLLISION_DEPTH)+0]="U"
        set CollisionMapping[21*(COLLISION_DEPTH)+0]="V"
        set CollisionMapping[22*(COLLISION_DEPTH)+0]="W"
        set CollisionMapping[23*(COLLISION_DEPTH)+0]="X"
        set CollisionMapping[24*(COLLISION_DEPTH)+0]="Y"
        set CollisionMapping[25*(COLLISION_DEPTH)+0]="Z"
        set CollisionMapping[26*(COLLISION_DEPTH)+0]="/"
        
        set CollisionMapping[ 0*(COLLISION_DEPTH)+1]="a"
        set CollisionMapping[ 1*(COLLISION_DEPTH)+1]="b"
        set CollisionMapping[ 2*(COLLISION_DEPTH)+1]="c"
        set CollisionMapping[ 3*(COLLISION_DEPTH)+1]="d"
        set CollisionMapping[ 4*(COLLISION_DEPTH)+1]="e"
        set CollisionMapping[ 5*(COLLISION_DEPTH)+1]="f"
        set CollisionMapping[ 6*(COLLISION_DEPTH)+1]="g"
        set CollisionMapping[ 7*(COLLISION_DEPTH)+1]="h"
        set CollisionMapping[ 8*(COLLISION_DEPTH)+1]="i"
        set CollisionMapping[ 9*(COLLISION_DEPTH)+1]="j"
        set CollisionMapping[10*(COLLISION_DEPTH)+1]="k"
        set CollisionMapping[11*(COLLISION_DEPTH)+1]="l"
        set CollisionMapping[12*(COLLISION_DEPTH)+1]="m"
        set CollisionMapping[13*(COLLISION_DEPTH)+1]="n"
        set CollisionMapping[14*(COLLISION_DEPTH)+1]="o"
        set CollisionMapping[15*(COLLISION_DEPTH)+1]="p"
        set CollisionMapping[16*(COLLISION_DEPTH)+1]="q"
        set CollisionMapping[17*(COLLISION_DEPTH)+1]="r"
        set CollisionMapping[18*(COLLISION_DEPTH)+1]="s"
        set CollisionMapping[19*(COLLISION_DEPTH)+1]="t"
        set CollisionMapping[20*(COLLISION_DEPTH)+1]="u"
        set CollisionMapping[21*(COLLISION_DEPTH)+1]="v"
        set CollisionMapping[22*(COLLISION_DEPTH)+1]="w"
        set CollisionMapping[23*(COLLISION_DEPTH)+1]="x"
        set CollisionMapping[24*(COLLISION_DEPTH)+1]="y"
        set CollisionMapping[25*(COLLISION_DEPTH)+1]="z"
        set CollisionMapping[26*(COLLISION_DEPTH)+1]="\\"
        
        
        // --------------------
        
        // These are all the chars that collide
        // Note that i have left out their counterparts (with which they would collide)
        set Collisions["A"]= 0
        set Collisions["B"]= 1
        set Collisions["C"]= 2
        set Collisions["D"]= 3
        set Collisions["E"]= 4
        set Collisions["F"]= 5
        set Collisions["G"]= 6
        set Collisions["H"]= 7
        set Collisions["I"]= 8
        set Collisions["J"]= 9
        set Collisions["K"]=10
        set Collisions["L"]=11
        set Collisions["M"]=12
        set Collisions["N"]=13
        set Collisions["O"]=14
        set Collisions["P"]=15
        set Collisions["Q"]=16
        set Collisions["R"]=17
        set Collisions["S"]=18
        set Collisions["T"]=19
        set Collisions["U"]=20
        set Collisions["V"]=21
        set Collisions["W"]=22
        set Collisions["X"]=23
        set Collisions["Y"]=24
        set Collisions["Z"]=25
        set Collisions["/"]=26
        set Collisions["\\"]=26
    endfunction
    
endlibrary
TextSplat Code + Credits + Documentation
Jass:
// *************************************************************
// *                TextSplat -- Version 1.3.1
// *                        by Deaod
// *************************************************************
// *
// *    CREDITS:
// *        - 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                 CHARS_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 function IsHexadecimal takes string s returns boolean
    local integer i=0
    local integer l=StringLength(s)
        loop
            exitwhen i>=l
            if IsHex[SubString(s, i, i+1)]==0 then
                // one illegal char aborts
                return false
            endif
            set i=i+1
        endloop
        return true
    endfunction
    
    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
    
    globals
        private real array TSPCharXOffset
        private real array TSPCharYOffset
        private ARGB array TSPCharColor
        private integer array TSPCharLine
        private boolean array TSPCharUsesDefaultColor
        private real array TSPLineWidth
        private real TSPWidth
        private integer TSPCount
        private integer TSPChunkCount
        private integer TSPSourceStringLength
        private integer TSPCurrentLine
        private ARGB TSPCurrentColor
        private boolean TSPCustomColor
        private string TSPCurrentChar
        private string TSPResultingString
        private char TSPChar
        private real TSPSourceX
        private real TSPSourceY
        private real TSPOffsetCorrection
        
        private location LocZ=Location(0,0)
    endglobals
    
    // this is a bit hacky... but necessary to avoid hitting the op limit.
    private function processText takes ARGB clr, font F, string text, real height, integer aligntype, integer base returns nothing
        loop
            exitwhen TSPChunkCount-base>=CHARS_PER_CHUNK or TSPCount>=TSPSourceStringLength
            set TSPCurrentChar=SubString(text, TSPCount, TSPCount+1)
            
            if TSPCurrentChar=="\n" or TSPCurrentChar=="\r" or (TSPCurrentChar=="|" and SubString(text, TSPCount+1,TSPCount+2)=="n") then
                // new line
                if TSPLineWidth[TSPCurrentLine]>TSPWidth or TSPCurrentLine==0 then
                    set TSPWidth=TSPLineWidth[TSPCurrentLine]
                endif
                set TSPCurrentLine=TSPCurrentLine+1
                set TSPLineWidth[TSPCurrentLine]=0
                if TSPCurrentChar=="|" then
                    set TSPCount=TSPCount+1
                endif
            elseif TSPCurrentChar=="|" and SubString(text, TSPCount+1, TSPCount+2)=="c" and StringLength(SubString(text, TSPCount+2, TSPCount+10))==8 and IsHexadecimal(SubString(text, TSPCount+2, TSPCount+10)) then
                // color tag
                set TSPCustomColor=true
                set TSPCurrentColor=ARGB.create(Hex2Dec[SubString(text, TSPCount+2, TSPCount+4)], Hex2Dec[SubString(text, TSPCount+4, TSPCount+6)], Hex2Dec[SubString(text, TSPCount+6, TSPCount+8)], Hex2Dec[SubString(text, TSPCount+8, TSPCount+10)])
                set TSPCount=TSPCount+9
            elseif TSPCurrentChar=="|" and SubString(text, TSPCount+1, TSPCount+2)=="r" then
                // reset color
                set TSPCustomColor=false
                set TSPCurrentColor=clr
                set TSPCount=TSPCount+1
            else
                // normal char
                set TSPResultingString=TSPResultingString+TSPCurrentChar
                set TSPLineWidth[TSPCurrentLine]=TSPLineWidth[TSPCurrentLine]+(F[TSPCurrentChar].width*TEXT_SIZE_TO_IMAGE_SIZE*height/DEFAULT_IMAGE_SIZE)
                set TSPCharYOffset[TSPChunkCount]=TSPCurrentLine*height*TEXT_SIZE_TO_IMAGE_SIZE
                if (TSPChunkCount==0) or (TSPCharYOffset[TSPChunkCount-1]<TSPCharYOffset[TSPChunkCount]) then
                    set TSPCharXOffset[TSPChunkCount]=0
                else
                    set TSPCharXOffset[TSPChunkCount]=TSPCharXOffset[TSPChunkCount-1]+(F[SubString(TSPResultingString, TSPChunkCount-1, TSPChunkCount)].width*TEXT_SIZE_TO_IMAGE_SIZE*height/DEFAULT_IMAGE_SIZE)
                endif
                set TSPCharColor[TSPChunkCount]=TSPCurrentColor
                set TSPCharLine[TSPChunkCount]=TSPCurrentLine
                set TSPCharUsesDefaultColor[TSPChunkCount]=not TSPCustomColor
                set TSPChunkCount=TSPChunkCount+1
            endif
            
            set TSPCount=TSPCount+1
        endloop
    endfunction
    
    private function displayText takes real height, integer aligntype, real z, boolean visible, font F, Table t, integer base returns nothing
    local integer i
    local boolean b
        loop
            exitwhen TSPCount-base>=CHARS_PER_CHUNK or TSPCount>=TSPChunkCount
            if TSPCount==0 or TSPCharLine[TSPCount]>TSPCharLine[TSPCount-1] then
                set TSPOffsetCorrection=0
            endif
            set TSPCurrentChar=SubString(TSPResultingString, TSPCount, TSPCount+1)
            if TSPCurrentChar=="|" and SubString(TSPResultingString, TSPCount+1, TSPCount+2)=="i" then
                // image
                set i=TSPCount+2
                set b=false
                loop
                    exitwhen SubString(TSPResultingString, i, i+1)=="|" and SubString(TSPResultingString, i+1, i+2)=="i"
                    if i>=TSPSourceStringLength-2 then
                        // weve reached the end of the text we want to display
                        // dont do anything
                        set b=true
                        exitwhen true
                    endif
                    set i=i+1
                endloop
                if (not b) and F.getImage(SubString(TSPResultingString, TSPCount+2, i))>0 then
                    set TSPChar=char.createImage(F, SubString(TSPResultingString, TSPCount+2, i), TSPSourceX+TSPCharXOffset[TSPCount]+( TextAlignBonus[aligntype]*(TSPWidth-TSPLineWidth[TSPCharLine[TSPCount]]) )-TSPOffsetCorrection, TSPSourceY-TSPCharYOffset[TSPCount], z, height)
                    set TSPOffsetCorrection=TSPOffsetCorrection+(TSPCharXOffset[i+2])-(TSPCharXOffset[TSPCount])-(F.getImage(SubString(TSPResultingString, TSPCount+2, i)).width/DEFAULT_IMAGE_SIZE*height*TEXT_SIZE_TO_IMAGE_SIZE)
                    loop
                        exitwhen TSPCount>=i+1
                        set t[TSPCount]=0
                        set TSPCount=TSPCount+1
                    endloop
                else
                    set TSPChar=char.createImage(F, TSPCurrentChar, TSPSourceX+TSPCharXOffset[TSPCount]+( TextAlignBonus[aligntype]*(TSPWidth-TSPLineWidth[TSPCharLine[TSPCount]]) )-TSPOffsetCorrection, TSPSourceY-TSPCharYOffset[TSPCount], z, height)
                endif
            else
                set TSPChar=char.createChar(F, TSPCurrentChar, TSPSourceX+TSPCharXOffset[TSPCount]+( TextAlignBonus[aligntype]*(TSPWidth-TSPLineWidth[TSPCharLine[TSPCount]]) )-TSPOffsetCorrection, TSPSourceY-TSPCharYOffset[TSPCount], z, height)
            endif
            set TSPChar.DefaultColor=TSPCharUsesDefaultColor[TSPCount]
            set TSPChar.color=TSPCharColor[TSPCount]
            set TSPChar.Show=visible
            call SetImageRenderAlways(TSPChar.Img, visible)
            set t[TSPCount]=integer(TSPChar)
            set TSPCount=TSPCount+1
        endloop
    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 TSPChunkCount=0
            set TSPSourceStringLength=StringLength(text)
            set TSPCurrentLine=0
            set TSPCurrentColor=.BGColor
            set TSPCustomColor=false
            set TSPResultingString=""
            set TSPWidth=0
            
            // lets clean up old stuff we dont need anymore
            call cleanSplat.evaluate(.Chars, .CharCount)
            
            set TSPLineWidth[0]=0
            //
            set TSPCount=0
            loop
                exitwhen TSPCount>=TSPSourceStringLength // TSPCount gets incremented in processText
                call processText.evaluate(.BGColor, .F, text, height, aligntype, TSPChunkCount)
            endloop
            
            if TSPCurrentLine==0 or TSPLineWidth[TSPCurrentLine]>TSPWidth then
                set TSPWidth=TSPLineWidth[TSPCurrentLine]
            endif
            
            // actually display the shit
            set TSPSourceX=.X
            set TSPSourceY=.Y+TSPCurrentLine*height*TEXT_SIZE_TO_IMAGE_SIZE
            set TSPOffsetCorrection=0
            set TSPCount=0
            loop
                exitwhen TSPCount>=TSPChunkCount
                call displayText.evaluate(height, aligntype, .Z, .Visible, .F, .Chars, TSPCount)
            endloop
            set .CharCount=TSPCount
            set .Text=text
            set .Width=TSPWidth
            set .Height=(TSPCurrentLine+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

Font + Textsplat Demo
Jass:
library Init initializer Init uses TextSplat
    
    private function Init takes nothing returns nothing
    local unit u=CreateUnit(Player(0), 'hfoo', 0,0,0)
    local textsplat t=CreateTextSplat(TREBUCHET)
    local string str = "This is just a simple\ndemonstration of multi-\nline, centered textsplats"
        call SetCameraPosition(0,0)
        call t.setText(str, 10, TEXTSPLAT_TEXT_ALIGN_CENTER)
        call SetTextSplatPos(t, -t.width/2, -256, 0)
        call SetTextSplatVelocity(t, 0, 48)
        call SetTextSplatLifespan(t, 10)
        call SetTextSplatFadepoint(t, 8)
        call SetTextSplatPermanent(t, false)
    endfunction
    
endlibrary

library FontInit initializer Init uses Font
    
    globals
                            font                TREBUCHET
    endglobals
    
    private function Init takes nothing returns nothing
        set TREBUCHET=font.create(0) // no parent
        call TREBUCHET.addChar(" ", 16, "Trebuchet\\32.blp")
        call TREBUCHET.addChar("!",  8, "Trebuchet\\33.blp")
        call TREBUCHET.addChar("\"", 10, "Trebuchet\\34.blp")
        call TREBUCHET.addChar("#", 19, "Trebuchet\\35.blp")
        call TREBUCHET.addChar("$", 16, "Trebuchet\\36.blp")
        call TREBUCHET.addChar("%", 20, "Trebuchet\\37.blp")
        call TREBUCHET.addChar("&", 22, "Trebuchet\\38.blp")
        call TREBUCHET.addChar("'",  6, "Trebuchet\\39.blp")
        call TREBUCHET.addChar("(", 11, "Trebuchet\\40.blp")
        call TREBUCHET.addChar(")", 10, "Trebuchet\\41.blp")
        call TREBUCHET.addChar("*", 14, "Trebuchet\\42.blp")
        call TREBUCHET.addChar("+", 16, "Trebuchet\\43.blp")
        call TREBUCHET.addChar(",",  9, "Trebuchet\\44.blp")
        call TREBUCHET.addChar("-", 10, "Trebuchet\\45.blp")
        call TREBUCHET.addChar(".",  8, "Trebuchet\\46.blp")
        call TREBUCHET.addChar("/", 15, "Trebuchet\\47.blp")
        call TREBUCHET.addChar("0", 18, "Trebuchet\\48.blp")
        call TREBUCHET.addChar("1", 11, "Trebuchet\\49.blp")
        call TREBUCHET.addChar("2", 18, "Trebuchet\\50.blp")
        call TREBUCHET.addChar("3", 16, "Trebuchet\\51.blp")
        call TREBUCHET.addChar("4", 19, "Trebuchet\\52.blp")
        call TREBUCHET.addChar("5", 16, "Trebuchet\\53.blp")
        call TREBUCHET.addChar("6", 18, "Trebuchet\\54.blp")
        call TREBUCHET.addChar("7", 18, "Trebuchet\\55.blp")
        call TREBUCHET.addChar("8", 18, "Trebuchet\\56.blp")
        call TREBUCHET.addChar("9", 17, "Trebuchet\\57.blp")
        call TREBUCHET.addChar(":",  8, "Trebuchet\\58.blp")
        call TREBUCHET.addChar(";",  9, "Trebuchet\\59.blp")
        call TREBUCHET.addChar("<", 15, "Trebuchet\\60.blp")
        call TREBUCHET.addChar("=", 17, "Trebuchet\\61.blp")
        call TREBUCHET.addChar(">", 15, "Trebuchet\\62.blp")
        call TREBUCHET.addChar("?", 13, "Trebuchet\\63.blp")
        call TREBUCHET.addChar("@", 24, "Trebuchet\\64.blp")
        call TREBUCHET.addChar("A", 22, "Trebuchet\\65.blp")
        call TREBUCHET.addChar("B", 18, "Trebuchet\\66.blp")
        call TREBUCHET.addChar("C", 20, "Trebuchet\\67.blp")
        call TREBUCHET.addChar("D", 19, "Trebuchet\\68.blp")
        call TREBUCHET.addChar("E", 17, "Trebuchet\\69.blp")
        call TREBUCHET.addChar("F", 18, "Trebuchet\\70.blp")
        call TREBUCHET.addChar("G", 21, "Trebuchet\\71.blp")
        call TREBUCHET.addChar("H", 20, "Trebuchet\\72.blp")
        call TREBUCHET.addChar("I",  7, "Trebuchet\\73.blp")
        call TREBUCHET.addChar("J", 15, "Trebuchet\\74.blp")
        call TREBUCHET.addChar("K", 20, "Trebuchet\\75.blp")
        call TREBUCHET.addChar("L", 17, "Trebuchet\\76.blp")
        call TREBUCHET.addChar("M", 26, "Trebuchet\\77.blp")
        call TREBUCHET.addChar("N", 19, "Trebuchet\\78.blp")
        call TREBUCHET.addChar("O", 22, "Trebuchet\\79.blp")
        call TREBUCHET.addChar("P", 18, "Trebuchet\\80.blp")
        call TREBUCHET.addChar("Q", 26, "Trebuchet\\81.blp")
        call TREBUCHET.addChar("R", 19, "Trebuchet\\82.blp")
        call TREBUCHET.addChar("S", 16, "Trebuchet\\83.blp")
        call TREBUCHET.addChar("T", 21, "Trebuchet\\84.blp")
        call TREBUCHET.addChar("U", 19, "Trebuchet\\85.blp")
        call TREBUCHET.addChar("V", 21, "Trebuchet\\86.blp")
        call TREBUCHET.addChar("W", 29, "Trebuchet\\87.blp")
        call TREBUCHET.addChar("X", 20, "Trebuchet\\88.blp")
        call TREBUCHET.addChar("Y", 21, "Trebuchet\\89.blp")
        call TREBUCHET.addChar("Z", 18, "Trebuchet\\90.blp")
        call TREBUCHET.addChar("[", 11, "Trebuchet\\91.blp")
        call TREBUCHET.addChar("\\", 14, "Trebuchet\\92.blp")
        call TREBUCHET.addChar("]", 11, "Trebuchet\\93.blp")
        call TREBUCHET.addChar("^", 15, "Trebuchet\\94.blp")
        call TREBUCHET.addChar("_", 20, "Trebuchet\\95.blp")
        call TREBUCHET.addChar("`",  9, "Trebuchet\\96.blp")
        call TREBUCHET.addChar("a", 16, "Trebuchet\\97.blp")
        call TREBUCHET.addChar("b", 13, "Trebuchet\\98.blp")
        call TREBUCHET.addChar("c", 15, "Trebuchet\\99.blp")
        call TREBUCHET.addChar("d", 14, "Trebuchet\\100.blp")
        call TREBUCHET.addChar("e", 12, "Trebuchet\\101.blp")
        call TREBUCHET.addChar("f", 13, "Trebuchet\\102.blp")
        call TREBUCHET.addChar("g", 16, "Trebuchet\\103.blp")
        call TREBUCHET.addChar("h", 14, "Trebuchet\\104.blp")
        call TREBUCHET.addChar("i",  5, "Trebuchet\\105.blp")
        call TREBUCHET.addChar("j", 11, "Trebuchet\\106.blp")
        call TREBUCHET.addChar("k", 15, "Trebuchet\\107.blp")
        call TREBUCHET.addChar("l", 13, "Trebuchet\\108.blp")
        call TREBUCHET.addChar("m", 19, "Trebuchet\\109.blp")
        call TREBUCHET.addChar("n", 14, "Trebuchet\\110.blp")
        call TREBUCHET.addChar("o", 16, "Trebuchet\\111.blp")
        call TREBUCHET.addChar("p", 14, "Trebuchet\\112.blp")
        call TREBUCHET.addChar("q", 18, "Trebuchet\\113.blp")
        call TREBUCHET.addChar("r", 14, "Trebuchet\\114.blp")
        call TREBUCHET.addChar("s", 12, "Trebuchet\\115.blp")
        call TREBUCHET.addChar("t", 16, "Trebuchet\\116.blp")
        call TREBUCHET.addChar("u", 14, "Trebuchet\\117.blp")
        call TREBUCHET.addChar("v", 16, "Trebuchet\\118.blp")
        call TREBUCHET.addChar("w", 21, "Trebuchet\\119.blp")
        call TREBUCHET.addChar("x", 15, "Trebuchet\\120.blp")
        call TREBUCHET.addChar("y", 16, "Trebuchet\\121.blp")
        call TREBUCHET.addChar("z", 13, "Trebuchet\\122.blp")
        call TREBUCHET.addChar("{", 14, "Trebuchet\\123.blp")
        call TREBUCHET.addChar("|",  6, "Trebuchet\\124.blp")
        call TREBUCHET.addChar("}", 14, "Trebuchet\\125.blp")
        call TREBUCHET.addChar("~", 15, "Trebuchet\\126.blp")
    endfunction
    
endlibrary

NOTE: Fonts are prone to hitting the op-limit when initializing. For that reason i suggest you only initialize one font per library initializer, and only use the ASCII set of characters.

I attached a (really simple) demo map demonstrating basic usage of this library.

You might wonder why i split it up into two libraries (Font and TextSplat). Well, someone might want to remake TextSplat, but keep Font as a foundation, and i think its more readable that way. But i dont think the Font library has any use outside the context of a TextSplat library, so i combined those two.

Additional Fonts
Morpheus + Tooltip Images (by Earth-Fury)

If you have a font you want to share, contact me with a link to where you published your font and ill add it to this list!
Rating - 4.50 (2 votes)
(Hover and click)
Moderator Comments
Recommended
17:31, 19th Oct 2009
The_Reborn_Devil:

The code looks pretty good and this is definitely useful.
It's well documented too.
Status: Approved.
Rating: Recommended.

This spell is approved and works properly.


Download TextSplat_1.3.1.w3x
(81.62 KB, 482 Downloads)

Old 10-19-2009, 04:41 AM   #2 (permalink)
Registered User Lambdadelta
User
 
Lambdadelta's Avatar
 
Join Date: Jul 2009
Posts: 903
Lambdadelta is a glorious beacon of light (423)Lambdadelta is a glorious beacon of light (423)Lambdadelta is a glorious beacon of light (423)Lambdadelta is a glorious beacon of light (423)Lambdadelta is a glorious beacon of light (423)Lambdadelta is a glorious beacon of light (423)
Nice! Nothing else to say. Looks useful.
Lambdadelta is offline   Reply With Quote
Old 10-19-2009, 08:54 AM   #3 (permalink)
Registered User Anachron
May Jesus bless you
 
Anachron's Avatar
 
Join Date: Sep 2007
Posts: 6,506
Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)
Hosted Project of the Year - 2009: Diablo III Warcraft 
This must use more memory as texttags, because they are not thought to do this. Additionally when do I need more as 90 textsplats? It would lagg anyway.
Anachron is offline   Reply With Quote
Old 10-19-2009, 09:02 AM   #4 (permalink)
Registered User X-OMG-X
Amira Tower Defence
 
X-OMG-X's Avatar
 
Join Date: Nov 2008
Posts: 2,247
X-OMG-X is a jewel in the rough (240)X-OMG-X is a jewel in the rough (240)X-OMG-X is a jewel in the rough (240)X-OMG-X is a jewel in the rough (240)
Dont know anything about vJass but looks good.
__________________
X-OMG-X is offline   Reply With Quote
Old 10-19-2009, 10:44 AM   #5 (permalink)
Registered User Lambdadelta
User
 
Lambdadelta's Avatar
 
Join Date: Jul 2009
Posts: 903
Lambdadelta is a glorious beacon of light (423)Lambdadelta is a glorious beacon of light (423)Lambdadelta is a glorious beacon of light (423)Lambdadelta is a glorious beacon of light (423)Lambdadelta is a glorious beacon of light (423)Lambdadelta is a glorious beacon of light (423)
Quote:
Originally Posted by Anachron View Post
This must use more memory as texttags, because they are not thought to do this. Additionally when do I need more as 90 textsplats? It would lagg anyway.
Who cares about codeand lag (Everyone but me probably). It looks very class
Lambdadelta is offline   Reply With Quote
Old 10-19-2009, 10:59 AM   #6 (permalink)
Registered User Anachron
May Jesus bless you
 
Anachron's Avatar
 
Join Date: Sep 2007
Posts: 6,506
Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)
Hosted Project of the Year - 2009: Diablo III Warcraft 
Players care about lagg.
I care about lagg.
Anachron is offline   Reply With Quote
Old 10-19-2009, 01:54 PM   #7 (permalink)
Registered User pippo
Have a good time
 
pippo's Avatar
 
Join Date: Mar 2008
Posts: 574
pippo will become famous soon enough (98)pippo will become famous soon enough (98)pippo will become famous soon enough (98)
If it's laggy, I give 2/5 :/
__________________
Custom Hero Defense
Terrain - llllllllllllllllllllllllllllll = 40%
Heroes/Spells - lllllllllllllllllllllll = 100%
Items -llllllllllllllllllllllllllllll =90%
Units (Creeps) -llllllllllllllllllllllllllllll = 15%
Triggers -llllllllllllllllllllllllllllll = 95%

Overall -llllllllllllllllllllllllllllll = 70%
pippo is offline   Reply With Quote
Old 10-19-2009, 04:06 PM   #8 (permalink)
Registered User Deaod
GUI sucks. Don't use it.
 
Join Date: Nov 2007
Posts: 841
Deaod has disabled reputation
Okay, shut up about lag. If you know a more efficient way to do this, tell me and ill update.
Its not laggy (and most probably wont ever be the primary cause of lag).

Also, please TRY to look for things you dont understand, or that you think are bad. I cant improve this resource (and myself) if everyone says "looks good".

Also, i never said its a good alternative to texttags. In some cases texttags are just as good or even better. But people who are restrained by the texttag limit might want to look into this. Itd also be cool for those wanting to center text on units.
Deaod is offline   Reply With Quote
Old 10-19-2009, 04:14 PM   #9 (permalink)
Registered User Anachron
May Jesus bless you
 
Anachron's Avatar
 
Join Date: Sep 2007
Posts: 6,506
Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)
Hosted Project of the Year - 2009: Diablo III Warcraft 
Quote:
Okay, shut up about lag. If you know a more efficient way to do this, tell me and ill update.
There is none, and it has its reasons.

Quote:
Its not laggy (and most probably wont ever be the primary cause of lag).
Textsplats are totally diffrent handled by the wc3 engine, they use more memory and I still see no reason why anyone needs over 90 texttags at the same time. Thats just crazy.
Anachron is offline   Reply With Quote
Old 10-19-2009, 04:37 PM   #10 (permalink)
Registered User Deaod
GUI sucks. Don't use it.
 
Join Date: Nov 2007
Posts: 841
Deaod has disabled reputation
You not seeing an application after i already outlined two doesnt mean shit. Really.

Have you actually stress tested this library? Because i havent. But if you do, attach the code you used for testing.
Deaod is offline   Reply With Quote
Old 10-19-2009, 04:43 PM   #11 (permalink)
Registered User Anachron
May Jesus bless you
 
Anachron's Avatar
 
Join Date: Sep 2007
Posts: 6,506
Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)
Hosted Project of the Year - 2009: Diablo III Warcraft 
I haven't even tested it.

I just say that this will has no use mostly.
Anachron is offline   Reply With Quote
Old 10-25-2009, 07:59 PM   #12 (permalink)
Registered User Deaod
GUI sucks. Don't use it.
 
Join Date: Nov 2007
Posts: 841
Deaod has disabled reputation
Version 1.2.1

So much for "No further optimization possible".
Deaod is offline   Reply With Quote
Old 10-25-2009, 08:31 PM   #13 (permalink)
Registered User Anachron
May Jesus bless you
 
Anachron's Avatar
 
Join Date: Sep 2007
Posts: 6,506
Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)Anachron has much of which to be proud (1119)
Hosted Project of the Year - 2009: Diablo III Warcraft 
How much space does a custom font require?
Anachron is offline   Reply With Quote
Old 10-25-2009, 08:58 PM   #14 (permalink)
Registered User Deaod
GUI sucks. Don't use it.
 
Join Date: Nov 2007
Posts: 841
Deaod has disabled reputation
Trebuchet uses 70-300 Bytes per char (compressed, that is).
Lets assume the average is 220 Byte per char.
(126-32)=94
94*220=20680 Byte=20.2 KiB

That should be about it. Give or take one or two KiB for initialization code.
Deaod is offline   Reply With Quote
Old 10-28-2009, 06:56 AM   #15 (permalink)
Registered User Diehard@Azeroth
User
 
Diehard@Azeroth's Avatar
 
Join Date: Sep 2007
Posts: 565
Diehard@Azeroth will become famous soon enough (91)Diehard@Azeroth will become famous soon enough (91)Diehard@Azeroth will become famous soon enough (91)
i got to hand it to you man, this actually amazed me. You did really good coding there bro; especially the ASCII arranging and whatnot, great job mate. This should be a definite 5/5.
Diehard@Azeroth is offline   Reply With Quote
Reply

Bookmarks

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off


All times are GMT. The time now is 01:32 PM.





Powered by vBulletin
Copyright 2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.5.1 PL2
Copyright © Ralle