Mapping TextFormat Ranges
There are several reasons you might want to know where one TextFormat ends and another begins. If your application supports any HTML authoring, you’ll likely need something like this, even if your HTML support is fairly basic. I’ve been working on a font loading management utility, so I needed something to detect which portions of the text use which font. Once I have this, I can use Font.hasGlyphs to determine whether I need to load a deeper subset of glyphs or can get away with a more minimal unicode range. (You can quit drooling. That code will be posted here when it’s ready.)
Doing this requires two classes. The first determines whether two TextFormat instances are equal.
-
package {
-
public class TextFormatUtil {
-
public static var defaultPropertySet:Array /* of String property names */ = [‘font’, ‘size’, ‘color’, ‘underline’, ‘bold’, ‘italic’, ‘url’];
-
{
-
if (propertySet == null)
-
{
-
propertySet = defaultPropertySet
-
}
-
{
-
var prop = propertySet[i]
-
//trace (i + ” ” + prop + ” ” + f1[prop] + ” ” + f2[prop])
-
if (f1[prop] != f2[prop])
-
{
-
match = false
-
break
-
}
-
}
-
return match
-
}
-
}
-
}
Easy enough. Now, you could just walk through each character in the TextField one at a time testing for TextFormat equality. But that’s really inefficient. Instead, I implemented a binary search.
-
package {
-
public class TextFormatMapper {
-
public function TextFormatMapper() {
-
}
-
{
-
textField = tf
-
}
-
mapTextFormat()
-
}
-
public function mapTextFormat()
-
{
-
var startIndex = 0
-
while (startIndex < textField.text.length)
-
{
-
while (lo < hi) {
-
if ( TextFormatUtil.equals (format1,format2, TextFormatUtil.fontOnlyPropertySet) )
-
{
-
//try a larger span if possible
-
lo = mid //+ 1
-
}
-
else
-
{
-
//try a smaller span if possible
-
hi = mid – 1
-
}
-
}
-
charsInTextFormatAtIndex.push ( charsInTextFormat )
-
startIndex = hi
-
}
-
}
-
return charsInTextFormatAtIndex;
-
}
-
}
-
}
To use it, you create a new TextFormatMapper and pass your TextField to the setTextField method. You can see I’m automatically calling the mapTextFormat method when the Event.CHANGE fires on the TextField. For testing, I hardcoded it to only test against the font property, but you can see how to easily change this to another property set on line 44. Once it’s finished, you can call getCharsInTextFormatAtIndex to get an array containing the length (in characters) of each distinct TextFormat (in this case, distinct font) encountered in the TextField.
This class will change a bit as I move forward with it, but I was really pleased to get this far.