package com.partlyhuman.display { import flash.geom.*; import flash.display.*; import flash.text.*; /** * Wraps left-justified text around any DisplayObject to produce a right rag. * See more information on http://www.partlyhuman.com/blog/roger/dynamic-text-wrapping-in-actionscript-3 * * Work licensed under Creative Commons Attribution 3.0 United States License. * * * @author Roger Braunstein */ public class WrapTextUtility { private static const KILL_LIMIT:int = 100; private static const GUTTER:int = 2; private static const NEWLINE:String = "\r"; private static const WHITESPACE:RegExp = /[\s\-\_]/; public function WrapTextUtility() { } public static function convertToText(tf:TextField):void { tf.condenseWhite = false; tf.text = tf.text.replace(//ig, NEWLINE); } public static function wrapText(tf:TextField, edge:DisplayObject, paddingPx:int = 6, transparentBackground:Boolean = false, debugSurface:Graphics = null):void { if (debugSurface) debugSurface.clear(); if (!tf.hitTestObject(edge)) return; var edgeOffset:Point = edge.localToGlobal(new Point()).subtract(tf.localToGlobal(new Point())); var lineY:Number = GUTTER; var bitmapSlice:BitmapData = new BitmapData(edge.width, edge.height, true, 0x00000000); var i:int = 0; do { try { var lineMetrics:TextLineMetrics = tf.getLineMetrics(i); } catch (err:RangeError) { break; } var lineBaseline:Number = lineY + lineMetrics.ascent; bitmapSlice.fillRect(bitmapSlice.rect, 0x00000000); var clipRect:Rectangle = new Rectangle(0, lineY - edgeOffset.y, edge.width, lineMetrics.ascent + lineMetrics.descent); lineY += lineMetrics.height; if (clipRect.width <= 0 || clipRect.height <= 0) continue; if (clipRect.y >= edge.height || clipRect.y + clipRect.height <= 0) continue; if (debugSurface) { debugSurface.lineStyle(1, 0x808080); debugSurface.drawRect(edge.x + clipRect.x, edge.y + clipRect.y, clipRect.width, clipRect.height); } bitmapSlice.draw(edge, null, null, null, clipRect); var colorRect:Rectangle = bitmapSlice.getColorBoundsRect((transparentBackground? 0xFF000000 : 0xFFFFFFFF), 0x00000000, false); if (colorRect == null || colorRect.width <= 0 || colorRect.height <= 0) continue; if (debugSurface) { debugSurface.lineStyle(1, 0x00FF00); debugSurface.drawRect(edge.x + colorRect.x, edge.y + colorRect.y, colorRect.width, colorRect.height); debugSurface.lineStyle(1, 0xFF0000); debugSurface.moveTo(tf.x, tf.y + lineBaseline); debugSurface.lineTo(tf.x + colorRect.x + edgeOffset.x - paddingPx, tf.y + lineBaseline); } var wrapChar:int = tf.getCharIndexAtPoint(colorRect.x + edgeOffset.x - paddingPx, lineBaseline); var firstCharInLine:int = tf.getLineOffset(i); var allText:String = tf.text; if (wrapChar <= 0) continue; while (allText.charAt(wrapChar).match(WHITESPACE) == null && wrapChar > firstCharInLine) { --wrapChar; } if (wrapChar <= firstCharInLine) { tf.text = allText.slice(0, firstCharInLine) + NEWLINE + allText.slice(firstCharInLine); } else { tf.text = allText.slice(0, wrapChar) + NEWLINE + allText.slice(wrapChar + 1); } } while (++i < KILL_LIMIT); bitmapSlice.dispose(); } } }