Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 136 additions & 55 deletions flixel/text/FlxText.hx
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,14 @@ class FlxText extends FlxSprite
public var autoSize(get, set):Bool;

var _autoHeight:Bool = true;


var _shadowOffset:FlxPoint;
/**
* Offset that is applied to the shadow border style, if active.
* `x` and `y` are multiplied by `borderSize`. Default is `(1, 1)`, or lower-right corner.
*/
public var shadowOffset(default, null):FlxPoint;
@:deprecated("shadowOffset is deprecated, use setBorderStyle(SHADOW_CUSTOM(offsetX, offsetY)), instead")
public var shadowOffset(get, never):FlxPoint;

var _defaultFormat:TextFormat;
var _formatAdjusted:TextFormat;
Expand Down Expand Up @@ -240,7 +242,7 @@ class FlxText extends FlxSprite

drawFrame();

shadowOffset = FlxPoint.get(1, 1);
_shadowOffset = FlxPoint.get(1, 1);
}

/**
Expand All @@ -252,7 +254,7 @@ class FlxText extends FlxSprite
_font = null;
_defaultFormat = null;
_formatAdjusted = null;
shadowOffset = FlxDestroyUtil.put(shadowOffset);
_shadowOffset = FlxDestroyUtil.put(_shadowOffset);
super.destroy();
}

Expand Down Expand Up @@ -841,6 +843,11 @@ class FlxText extends FlxSprite
regenGraphic();
return super.get_height();
}

inline function get_shadowOffset()
{
return _shadowOffset;
}

override function updateColorTransform():Void
{
Expand All @@ -865,33 +872,47 @@ class FlxText extends FlxSprite
{
if (textField == null || !_regen)
return;

var oldWidth:Int = 0;
var oldHeight:Int = VERTICAL_GUTTER;

if (graphic != null)

final oldWidth:Int = graphic != null ? graphic.width : 0;
final oldHeight:Int = graphic != null ? graphic.height : VERTICAL_GUTTER;

final newWidthFloat:Float = textField.width;
final newHeightFloat:Float = _autoHeight ? textField.textHeight + VERTICAL_GUTTER : textField.height;

var borderWidth:Float = 0;
var borderHeight:Float = 0;
switch(borderStyle)
{
oldWidth = graphic.width;
oldHeight = graphic.height;
case SHADOW if (_shadowOffset.x == 1 && _shadowOffset.y == 1):
borderWidth += Math.abs(borderSize);
borderHeight += Math.abs(borderSize);

case SHADOW: // with non-default shadowOffset value
borderWidth += Math.abs(_shadowOffset.x);
borderHeight += Math.abs(_shadowOffset.y);

case SHADOW_CUSTOM(offsetX, offsetY):
borderWidth += Math.abs(offsetX);
borderHeight += Math.abs(offsetY);

case OUTLINE_FAST | OUTLINE:
borderWidth += Math.abs(borderSize) * 2;
borderHeight += Math.abs(borderSize) * 2;

case NONE:
}

var newWidth:Int = Math.ceil(textField.width);
var textfieldHeight = _autoHeight ? textField.textHeight : textField.height;
var vertGutter = _autoHeight ? VERTICAL_GUTTER : 0;
// Account for gutter
var newHeight:Int = Math.ceil(textfieldHeight) + vertGutter;


final newWidth:Int = Math.ceil(newWidthFloat + borderWidth);
final newHeight:Int = Math.ceil(newHeightFloat + borderHeight);

// prevent text height from shrinking on flash if text == ""
if (textField.textHeight == 0)
{
newHeight = oldHeight;
}

if (oldWidth != newWidth || oldHeight != newHeight)
if (textField.textHeight != 0 && (oldWidth != newWidth || oldHeight != newHeight))
{
// Need to generate a new buffer to store the text graphic
var key:String = FlxG.bitmap.getUniqueKey("text");
final key:String = FlxG.bitmap.getUniqueKey("text");
makeGraphic(newWidth, newHeight, FlxColor.TRANSPARENT, false, key);
width = Math.ceil(newWidthFloat);
height = Math.ceil(newHeightFloat);

#if FLX_TRACK_GRAPHICS
graphic.trackingInfo = 'text($ID, $text)';
Expand Down Expand Up @@ -1019,38 +1040,92 @@ class FlxText extends FlxSprite
regenGraphic();
super.calcFrame(RunOnCpp);
}

function applyBorderStyle():Void
{
var iterations:Int = Std.int(borderSize * borderQuality);
if (iterations <= 0)
// offset entire image to fit the border
switch(borderStyle)
{
iterations = 1;
case SHADOW if (_shadowOffset.x == 1 && _shadowOffset.y == 1):
if (borderSize < 0)
offset.set(-borderSize, -borderSize);

case SHADOW: // with non-default shadowOffset value
offset.x = _shadowOffset.x < 0 ? -_shadowOffset.x : 0;
offset.y = _shadowOffset.y < 0 ? -_shadowOffset.y : 0;

case SHADOW_CUSTOM(offsetX, offsetY):
offset.x = offsetX < 0 ? -offsetX : 0;
offset.y = offsetY < 0 ? -offsetY : 0;

case OUTLINE_FAST | OUTLINE if (borderSize < 0):
offset.set(-borderSize, -borderSize);

case NONE | OUTLINE_FAST | OUTLINE:
}
var delta:Float = borderSize / iterations;

_matrix.translate(offset.x, offset.y);
switch (borderStyle)
{
case SHADOW:
case SHADOW if (_shadowOffset.x == 1 && _shadowOffset.y == 1):
// Render a shadow beneath the text
// (do one lower-right offset draw call)
applyFormats(_formatAdjusted, true);


final originX = _matrix.tx;
final originY = _matrix.ty;

final iterations = borderQuality < 1 ? 1 : Std.int(Math.abs(borderSize) * borderQuality);
var i = iterations + 1;
while (i-- > 1)
{
copyTextWithOffset(borderSize / iterations * i, borderSize / iterations * i);
// reset to origin
_matrix.tx = originX;
_matrix.ty = originY;
}

case SHADOW: // with non-default shadowOffset value
// Render a shadow beneath the text using the shadowOffset property
applyFormats(_formatAdjusted, true);

var iterations = borderQuality < 1 ? 1 : Std.int(Math.abs(borderSize) * borderQuality);
final delta = borderSize / iterations;
for (i in 0...iterations)
{
copyTextWithOffset(delta, delta);
}

_matrix.translate(-shadowOffset.x * borderSize, -shadowOffset.y * borderSize);


_matrix.translate(-_shadowOffset.x * borderSize, -_shadowOffset.y * borderSize);

case SHADOW_CUSTOM(offsetX, offsetY):
// Render a shadow beneath the text with the specified offset
applyFormats(_formatAdjusted, true);

final originX = _matrix.tx;
final originY = _matrix.ty;

// Size is average of both, so (4, 4) has 4 iterations, just like SHADOW
final size = (Math.abs(offsetX) + Math.abs(offsetY)) / 2;
final iterations = borderQuality < 1 ? 1 : Std.int(size * borderQuality);
var i = iterations + 1;
while (i-- > 1)
{
copyTextWithOffset(offsetX / iterations * i, offsetY / iterations * i);
// reset to origin
_matrix.tx = originX;
_matrix.ty = originY;
}

case OUTLINE:
// Render an outline around the text
// (do 8 offset draw calls)
applyFormats(_formatAdjusted, true);

var curDelta:Float = delta;
for (i in 0...iterations)

final iterations = FlxMath.maxInt(1, Std.int(borderSize * borderQuality));
var i = iterations + 1;
while (i-- > 1)
{
final curDelta = borderSize / iterations * i;
copyTextWithOffset(-curDelta, -curDelta); // upper-left
copyTextWithOffset(curDelta, 0); // upper-middle
copyTextWithOffset(curDelta, 0); // upper-right
Expand All @@ -1059,29 +1134,29 @@ class FlxText extends FlxSprite
copyTextWithOffset(-curDelta, 0); // lower-middle
copyTextWithOffset(-curDelta, 0); // lower-left
copyTextWithOffset(0, -curDelta); // lower-left

_matrix.translate(curDelta, 0); // return to center
curDelta += delta;
}

case OUTLINE_FAST:
// Render an outline around the text
// (do 4 diagonal offset draw calls)
// (this method might not work with certain narrow fonts)
applyFormats(_formatAdjusted, true);

var curDelta:Float = delta;
for (i in 0...iterations)

final iterations = FlxMath.maxInt(1, Std.int(borderSize * borderQuality));
var i = iterations + 1;
while (i-- > 1)
{
final curDelta = borderSize / iterations * i;
copyTextWithOffset(-curDelta, -curDelta); // upper-left
copyTextWithOffset(curDelta * 2, 0); // upper-right
copyTextWithOffset(0, curDelta * 2); // lower-right
copyTextWithOffset(-curDelta * 2, 0); // lower-left

_matrix.translate(curDelta, -curDelta); // return to center
curDelta += delta;
}

case NONE:
}
}
Expand Down Expand Up @@ -1237,20 +1312,26 @@ class FlxTextFormatMarkerPair
enum FlxTextBorderStyle
{
NONE;

/**
* A simple shadow to the lower-right.
* Use `FlxText.shadowOffset` for custom placement.
* A simple shadow to the lower-right
*/
SHADOW;


/**
* A shadow that allows custom placement
* **Note:** Ignores borderSize
*/
SHADOW_CUSTOM(offsetX:Float, offsetY:Float);

/**
* Outline on all 8 sides
*/
OUTLINE;

/**
* Outline, optimized using only 4 draw calls (might not work for narrow and/or 1-pixel fonts)
* Outline, optimized using only 4 draw calls
* **Note:** Might not work for narrow and/or 1-pixel fonts
*/
OUTLINE_FAST;
}
Expand Down