Skip to content

Commit

Permalink
Apply ColorTransform directly when rendering text and shapes
Browse files Browse the repository at this point in the history
This patch refactors and de-duplicates code in the
 Cairo and Canvas rendering classes and implements
 the application of color transforms to TextFields
 and (Shape) Graphics.

It introduces 2 new macros to ColorTransform that
 help calculate the RGBA values without temporary
 allocations. If and when Haxe supports multiple
 inline return values, these could be rewritten.

Drawing Bitmaps with ColorTransform is untested
 and not implemented by this patch.
  • Loading branch information
vizanto committed Aug 22, 2016
1 parent dad42b2 commit e154237
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 141 deletions.
93 changes: 43 additions & 50 deletions openfl/_internal/renderer/cairo/CairoGraphics.hx
Expand Up @@ -19,6 +19,7 @@ import openfl.display.GradientType;
import openfl.display.Graphics;
import openfl.display.InterpolationMethod;
import openfl.display.SpreadMethod;
import openfl.geom.ColorTransform;
import openfl.geom.Matrix;
import openfl.geom.Point;
import openfl.geom.Rectangle;
Expand Down Expand Up @@ -82,7 +83,18 @@ class CairoGraphics {
}


private static function createGradientPattern (type:GradientType, colors:Array<Dynamic>, alphas:Array<Dynamic>, ratios:Array<Dynamic>, matrix:Matrix, spreadMethod:SpreadMethod, interpolationMethod:InterpolationMethod, focalPointRatio:Float):CairoPattern {
private static function createRGBAPattern(colorTransform : ColorTransform, input_rgb : Int, input_a : Float) : CairoPattern
{
return CairoUtils.applyColorTransform(colorTransform, input_rgb, input_a,
if (a >= 1.0)
CairoPattern.createRGB (r, g, b)
else
CairoPattern.createRGBA (r, g, b, a)
);
}


private static function createGradientPattern (type:GradientType, colors:Array<Dynamic>, alphas:Array<Dynamic>, ratios:Array<Dynamic>, matrix:Matrix, spreadMethod:SpreadMethod, interpolationMethod:InterpolationMethod, focalPointRatio:Float, colorTransform:ColorTransform):CairoPattern {

var pattern:CairoPattern = null;

Expand Down Expand Up @@ -114,22 +126,15 @@ class CairoGraphics {
pattern = CairoPattern.createLinear (point1.x, point1.y, point2.x, point2.y);

}

for (i in 0...colors.length) {

var rgb = colors[i];
var alpha = alphas[i];
var r = ((rgb & 0xFF0000) >>> 16) / 0xFF;
var g = ((rgb & 0x00FF00) >>> 8) / 0xFF;
var b = (rgb & 0x0000FF) / 0xFF;


for (i in 0...colors.length) CairoUtils.applyColorTransform(colorTransform, colors[i], alphas[i],
{
var ratio = ratios[i] / 0xFF;
if (ratio < 0) ratio = 0;
if (ratio > 1) ratio = 1;

pattern.addColorStopRGBA (ratio, r, g, b, alpha);

}
pattern.addColorStopRGBA (ratio, r, g, b, a);
});

var mat = pattern.matrix;

Expand Down Expand Up @@ -194,19 +199,19 @@ class CairoGraphics {
}


private static function endFill ():Void {
private static function endFill (colorTransform:ColorTransform):Void {

cairo.newPath ();
playCommands (fillCommands, false);
playCommands (fillCommands, colorTransform, false);
fillCommands.clear ();

}


private static function endStroke ():Void {
private static function endStroke (colorTransform:ColorTransform):Void {

cairo.newPath ();
playCommands (strokeCommands, true);
playCommands (strokeCommands, colorTransform, true);
cairo.closePath ();
strokeCommands.clear ();

Expand Down Expand Up @@ -300,8 +305,8 @@ class CairoGraphics {
case END_FILL:

data.readEndFill ();
endFill ();
endStroke ();
endFill (null);
endStroke (null);

if (hasFill && cairo.inFill (x, y)) {

Expand All @@ -322,8 +327,8 @@ class CairoGraphics {

case BEGIN_BITMAP_FILL, BEGIN_FILL, BEGIN_GRADIENT_FILL:

endFill ();
endStroke ();
endFill (null);
endStroke (null);

if (hasFill && cairo.inFill (x, y)) {

Expand Down Expand Up @@ -393,13 +398,13 @@ class CairoGraphics {

if (fillCommands.length > 0) {

endFill ();
endFill (null);

}

if (strokeCommands.length > 0) {

endStroke ();
endStroke (null);

}

Expand Down Expand Up @@ -475,7 +480,7 @@ class CairoGraphics {
}


private static function playCommands (commands:DrawCommandBuffer, stroke:Bool = false):Void {
private static function playCommands (commands:DrawCommandBuffer, colorTransform:ColorTransform, stroke:Bool = false):Void {

if (commands.length == 0) return;

Expand Down Expand Up @@ -635,20 +640,8 @@ class CairoGraphics {
}

cairo.miterLimit = c.miterLimit;

var r = ((c.color & 0xFF0000) >>> 16) / 0xFF;
var g = ((c.color & 0x00FF00) >>> 8) / 0xFF;
var b = (c.color & 0x0000FF) / 0xFF;

if (c.alpha == 1) {

strokePattern = CairoPattern.createRGB (r, g, b);

} else {

strokePattern = CairoPattern.createRGBA (r, g, b, c.alpha);

}

strokePattern = createRGBAPattern(colorTransform, c.color, c.alpha);

}

Expand All @@ -657,12 +650,12 @@ class CairoGraphics {
var c = data.readLineGradientStyle ();
if (stroke && hasStroke) {

closePath ();
closePath (hasStroke);

}

cairo.moveTo (positionX - offsetX, positionY - offsetY);
strokePattern = createGradientPattern (c.type, c.colors, c.alphas, c.ratios, c.matrix, c.spreadMethod, c.interpolationMethod, c.focalPointRatio);
strokePattern = createGradientPattern (c.type, c.colors, c.alphas, c.ratios, c.matrix, c.spreadMethod, c.interpolationMethod, c.focalPointRatio, colorTransform);

hasStroke = true;

Expand All @@ -671,7 +664,7 @@ class CairoGraphics {
var c = data.readLineBitmapStyle ();
if (stroke && hasStroke) {

closePath ();
closePath (hasStroke);

}

Expand Down Expand Up @@ -705,7 +698,7 @@ class CairoGraphics {

}

fillPattern = CairoPattern.createRGBA (((c.color & 0xFF0000) >>> 16) / 0xFF, ((c.color & 0x00FF00) >>> 8) / 0xFF, (c.color & 0x0000FF) / 0xFF, c.alpha);
fillPattern = createRGBAPattern(colorTransform, c.color, c.alpha);
hasFill = true;

}
Expand All @@ -721,7 +714,7 @@ class CairoGraphics {

}

fillPattern = createGradientPattern (c.type, c.colors, c.alphas, c.ratios, c.matrix, c.spreadMethod, c.interpolationMethod, c.focalPointRatio);
fillPattern = createGradientPattern (c.type, c.colors, c.alphas, c.ratios, c.matrix, c.spreadMethod, c.interpolationMethod, c.focalPointRatio, colorTransform);

hasFill = true;
bitmapFill = null;
Expand Down Expand Up @@ -988,7 +981,7 @@ class CairoGraphics {
}


public static function render (graphics:Graphics, renderSession:RenderSession, parentTransform:Matrix):Void {
public static function render (graphics:Graphics, renderSession:RenderSession, parentTransform:Matrix, colorTransform:ColorTransform):Void {

#if lime_cairo

Expand Down Expand Up @@ -1081,8 +1074,8 @@ class CairoGraphics {
case END_FILL:

data.readEndFill ();
endFill ();
endStroke ();
endFill (colorTransform);
endStroke (colorTransform);
hasFill = false;
bitmapFill = null;

Expand All @@ -1103,8 +1096,8 @@ class CairoGraphics {

case BEGIN_BITMAP_FILL, BEGIN_FILL, BEGIN_GRADIENT_FILL:

endFill ();
endStroke ();
endFill (colorTransform);
endStroke (colorTransform);

if (type == BEGIN_BITMAP_FILL) {

Expand Down Expand Up @@ -1165,13 +1158,13 @@ class CairoGraphics {

if (fillCommands.length > 0) {

endFill ();
endFill (colorTransform);

}

if (strokeCommands.length > 0) {

endStroke ();
endStroke (colorTransform);

}

Expand Down
2 changes: 1 addition & 1 deletion openfl/_internal/renderer/cairo/CairoShape.hx
Expand Up @@ -22,7 +22,7 @@ class CairoShape {

if (graphics != null) {

CairoGraphics.render (graphics, renderSession, shape.__worldTransform);
CairoGraphics.render (graphics, renderSession, shape.__worldTransform, shape.__worldColorTransform);

var bounds = graphics.__bounds;

Expand Down
34 changes: 15 additions & 19 deletions openfl/_internal/renderer/cairo/CairoTextField.hx
Expand Up @@ -12,6 +12,7 @@ import lime.graphics.cairo.CairoImageSurface;
import openfl._internal.renderer.RenderSession;
import openfl._internal.text.TextEngine;
import openfl.display.BitmapData;
import openfl.geom.ColorTransform;
import openfl.geom.Matrix;
import openfl.geom.Rectangle;
import openfl.text.TextField;
Expand All @@ -24,6 +25,14 @@ import openfl.text.TextFormat;


class CairoTextField {


private static inline function setSourceRGB(cairo : Cairo, colorTransform : ColorTransform, input_rgb : Int) : Void
{
CairoUtils.applyColorTransform(colorTransform, input_rgb, 1.0,
cairo.setSourceRGB (r, g, b)
);
}


public static function render (textField:TextField, renderSession:RenderSession, transform:Matrix) {
Expand All @@ -32,6 +41,7 @@ class CairoTextField {

var textEngine = textField.__textEngine;
var bounds = textEngine.bounds;
var colorTransform = textField.__worldColorTransform.__isDefault() ? null : textField.__worldColorTransform;
var graphics = textField.__graphics;
var cairo = graphics.__cairo;

Expand Down Expand Up @@ -137,24 +147,14 @@ class CairoTextField {

} else {

var color = textEngine.backgroundColor;
var r = ((color & 0xFF0000) >>> 16) / 0xFF;
var g = ((color & 0x00FF00) >>> 8) / 0xFF;
var b = (color & 0x0000FF) / 0xFF;

cairo.setSourceRGB (r, g, b);
setSourceRGB(cairo, colorTransform, textEngine.backgroundColor);
cairo.fillPreserve ();

}

if (textEngine.border) {

var color = textEngine.borderColor;
var r = ((color & 0xFF0000) >>> 16) / 0xFF;
var g = ((color & 0x00FF00) >>> 8) / 0xFF;
var b = (color & 0x0000FF) / 0xFF;

cairo.setSourceRGB (r, g, b);
setSourceRGB(cairo, colorTransform, textEngine.borderColor);
cairo.lineWidth = 1;
cairo.stroke ();

Expand Down Expand Up @@ -191,19 +191,15 @@ class CairoTextField {

}

var color, r, g, b, font, size, advance;
var font, size, advance;

for (group in textEngine.layoutGroups) {

if (group.lineIndex < textField.scrollV - 1) continue;
if (group.lineIndex > textField.scrollV + textEngine.bottomScrollV - 2) break;

color = group.format.color;
r = ((color & 0xFF0000) >>> 16) / 0xFF;
g = ((color & 0x00FF00) >>> 8) / 0xFF;
b = (color & 0x0000FF) / 0xFF;

cairo.setSourceRGB (r, g, b);
setSourceRGB(cairo, colorTransform, group.format.color);


font = TextEngine.getFontInstance (group.format);

Expand Down
30 changes: 30 additions & 0 deletions openfl/_internal/renderer/cairo/CairoUtils.hx
@@ -0,0 +1,30 @@
package openfl._internal.renderer.cairo;


import haxe.macro.Expr;
import openfl.geom.ColorTransform;


class CairoUtils
{
public static inline var scale = 1/0xFF;

public static macro function applyColorTransform(colorTransform : ExprOf<ColorTransform>, rgb : ExprOf<Int>, a : ExprOf<Float>, rgbaExpr : Expr) : Expr
{
return macro ColorTransform.__with_var_rgba($rgb, $a,
{
var r:Float = r;
var g:Float = g;
var b:Float = b;

if ($colorTransform != null)
colorTransform.__apply_to_var_rgba();

r *= CairoUtils.scale;
g *= CairoUtils.scale;
b *= CairoUtils.scale;
$rgbaExpr;
}
);
}
}

0 comments on commit e154237

Please sign in to comment.