Skip to content

Commit

Permalink
Finish implementing switch from PDN blend modes to Cairo blend modes.
Browse files Browse the repository at this point in the history
  • Loading branch information
jpobst committed Mar 30, 2015
1 parent fb67804 commit 81c8eef
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 130 deletions.
26 changes: 16 additions & 10 deletions Pinta.Core/Classes/Document.cs
Original file line number Diff line number Diff line change
Expand Up @@ -475,15 +475,21 @@ public ImageSurface GetClippedLayer (int index)
/// </summary>
public ColorBgra GetComputedPixel (int x, int y)
{
var pixel = ColorBgra.Zero;
using (var dst = new ImageSurface (Format.Argb32, 1, 1)) {
using (var g = new Context (dst)) {
foreach (var layer in GetLayersToPaint ()) {
var color = layer.Surface.GetColorBgraUnchecked (x, y).ToCairoColor ();

foreach (var layer in GetLayersToPaint ()) {
var blend_op = UserBlendOps.GetBlendOp (layer.BlendMode, layer.Opacity);
g.SetBlendMode (layer.BlendMode);
g.SetSourceColor (color);

pixel = blend_op.Apply (pixel, layer.Surface.GetColorBgraUnchecked (x, y));
}
g.Rectangle (dst.GetBounds ().ToCairoRectangle ());
g.PaintWithAlpha (layer.Opacity);
}
}

return pixel;
return dst.GetPixel (0, 0).ToColorBgra ();
}
}

public ImageSurface GetFlattenedImage ()
Expand All @@ -493,8 +499,8 @@ public ImageSurface GetFlattenedImage ()

// Blend each visible layer onto our surface
foreach (var layer in GetLayersToPaint ()) {
var blendop = UserBlendOps.GetBlendOp (layer.BlendMode, layer.Opacity);
blendop.Apply (surf, layer.Surface);
using (var g = new Context (surf))
layer.Draw (g);
}

surf.MarkDirty ();
Expand Down Expand Up @@ -573,8 +579,8 @@ public void MergeCurrentLayerDown ()
var dest = UserLayers[current_layer - 1];

// Blend the layers
var blendop = UserBlendOps.GetBlendOp (source.BlendMode, source.Opacity);
blendop.Apply (dest.Surface, source.Surface);
using (var g = new Context (dest.Surface))
source.Draw (g);

DeleteCurrentLayer ();
}
Expand Down
5 changes: 2 additions & 3 deletions Pinta.Core/Classes/Layer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,8 @@ public void Draw (Context ctx, ImageSurface surface, double opacity, bool transf
if (transform)
ctx.Transform (Transform);

ctx.SetBlendMode (BlendMode);
ctx.SetSourceSurface (surface, 0, 0);
ctx.PaintWithAlpha (opacity);
ctx.BlendSurface (surface, BlendMode, opacity);

ctx.Restore ();
}

Expand Down
82 changes: 8 additions & 74 deletions Pinta.Core/Effects/UserBlendOps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,98 +27,32 @@ namespace Pinta.Core
/// </summary>
public sealed partial class UserBlendOps
{
private static UserBlendOp[] cached_ops;
private static Dictionary<string, BlendMode> blend_modes = new Dictionary<string,BlendMode> ();

static UserBlendOps ()
{
cached_ops = new UserBlendOp[] {
new NormalBlendOp (),
new MultiplyBlendOp (),
new AdditiveBlendOp (),
new ColorBurnBlendOp (),
new ColorDodgeBlendOp (),
new ReflectBlendOp (),
new GlowBlendOp (),
new OverlayBlendOp (),
new DifferenceBlendOp (),
new NegationBlendOp (),
new LightenBlendOp (),
new DarkenBlendOp (),
new ScreenBlendOp (),
new XorBlendOp ()
};

blend_modes.Add (Catalog.GetString ("Normal"), BlendMode.Normal);
blend_modes.Add (Catalog.GetString ("Multiply"), BlendMode.Multiply);
blend_modes.Add (Catalog.GetString ("Additive"), BlendMode.Additive);
blend_modes.Add (Catalog.GetString ("Color Burn"), BlendMode.ColorBurn);
blend_modes.Add (Catalog.GetString ("Color Dodge"), BlendMode.ColorDodge);
blend_modes.Add (Catalog.GetString ("Reflect"), BlendMode.Reflect);
blend_modes.Add (Catalog.GetString ("Glow"), BlendMode.Glow);
blend_modes.Add (Catalog.GetString ("Overlay"), BlendMode.Overlay);
blend_modes.Add (Catalog.GetString ("Difference"), BlendMode.Difference);
blend_modes.Add (Catalog.GetString ("Negation"), BlendMode.Negation);
blend_modes.Add (Catalog.GetString ("Lighten"), BlendMode.Lighten);
blend_modes.Add (Catalog.GetString ("Darken"), BlendMode.Darken);
blend_modes.Add (Catalog.GetString ("Screen"), BlendMode.Screen);
blend_modes.Add (Catalog.GetString ("Xor"), BlendMode.Xor);
}
blend_modes.Add (Catalog.GetString ("Xor"), BlendMode.Xor);
blend_modes.Add (Catalog.GetString ("Hard Light"), BlendMode.HardLight);
blend_modes.Add (Catalog.GetString ("Soft Light"), BlendMode.SoftLight);
blend_modes.Add (Catalog.GetString ("Color"), BlendMode.Color);
blend_modes.Add (Catalog.GetString ("Luminosity"), BlendMode.Luminosity);
blend_modes.Add (Catalog.GetString ("Hue"), BlendMode.Hue);
blend_modes.Add (Catalog.GetString ("Saturation"), BlendMode.Saturation);
}

private UserBlendOps ()
{
}

/// <summary>
/// Returns an array of Type objects that lists all of the pixel ops contained
/// within this class. You can then use Utility.GetStaticName to retrieve the
/// value of the StaticName property.
/// </summary>
/// <returns></returns>
public static Type[] GetBlendOps ()
{
Type[] allTypes = typeof (UserBlendOps).GetNestedTypes ();
List<Type> types = new List<Type> (allTypes.Length);

foreach (Type type in allTypes) {
if (type.IsSubclassOf (typeof (UserBlendOp)) && !type.IsAbstract) {
types.Add (type);
}
}

return types.ToArray ();
}

public static string GetBlendOpFriendlyName (Type opType)
{
return Utility.GetStaticName (opType);
}

public static UserBlendOp CreateBlendOp (Type opType)
{
ConstructorInfo ci = opType.GetConstructor (System.Type.EmptyTypes);
UserBlendOp op = (UserBlendOp)ci.Invoke (null);
return op;
}

public static UserBlendOp CreateDefaultBlendOp ()
{
return new NormalBlendOp ();
}

public static Type GetDefaultBlendOp ()
{
return typeof (NormalBlendOp);
}

public static UserBlendOp GetBlendOp (BlendMode mode, double opacity)
{
if (opacity == 1.0)
return cached_ops[(int)mode];

return cached_ops[(int)mode].CreateWithOpacity ((int)(opacity * 255));
}

public static IEnumerable<string> GetAllBlendModeNames ()
{
return blend_modes.Keys;
Expand Down
12 changes: 7 additions & 5 deletions Pinta.Core/Enumerations/BlendMode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,19 @@ public enum BlendMode
{
Normal,
Multiply,
Additive,
ColorBurn,
ColorDodge,
Reflect,
Glow,
Overlay,
Difference,
Negation,
Lighten,
Darken,
Screen,
Xor
Xor,
HardLight,
SoftLight,
Color,
Luminosity,
Hue,
Saturation
}
}
70 changes: 58 additions & 12 deletions Pinta.Core/Extensions/CairoExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,16 @@ public static void Clear (this ImageSurface surface)
}
}

public static void Clear (this Context g, Rectangle roi)
{
g.Save ();
g.Rectangle (roi.X, roi.Y, roi.Width, roi.Height);
g.Clip ();
g.Operator = Operator.Clear;
g.Paint ();
g.Restore ();
}

[DllImport(CairoLib, CallingConvention = CallingConvention.Cdecl)]
private static extern void cairo_path_extents(IntPtr cr, out double x1, out double y1, out double x2, out double y2);

Expand Down Expand Up @@ -1668,6 +1678,36 @@ public static Pattern ToTiledPattern (this Surface surface)
return pattern;
}

public static void BlendSurface (this Context g, Surface src, BlendMode mode = BlendMode.Normal, double opacity = 1.0)
{
g.Save ();
g.SetBlendMode (mode);
g.SetSourceSurface (src, 0, 0);
g.PaintWithAlpha (opacity);
g.Restore ();
}

public static void BlendSurface (this Context g, Surface src, Rectangle roi, BlendMode mode = BlendMode.Normal, double opacity = 1.0)
{
g.Save ();
g.Rectangle (roi);
g.Clip ();
g.SetBlendMode (mode);
g.SetSourceSurface (src, 0, 0);
g.PaintWithAlpha (opacity);
g.Restore ();
}

public static void BlendSurface (this Context g, Surface src, Point offset, BlendMode mode = BlendMode.Normal, double opacity = 1.0)
{
g.Save ();
g.Translate (offset.X, offset.Y);
g.SetBlendMode (mode);
g.SetSourceSurface (src, 0, 0);
g.PaintWithAlpha (opacity);
g.Restore ();
}

public static void SetBlendMode (this Context g, BlendMode mode)
{
switch (mode) {
Expand All @@ -1677,30 +1717,36 @@ public static void SetBlendMode (this Context g, BlendMode mode)
case BlendMode.Multiply:
g.Operator = (Operator)ExtendedOperators.Multiply;
break;
case BlendMode.Additive:
g.Operator = Operator.Add;
break;
case BlendMode.ColorBurn:
g.Operator = (Operator)ExtendedOperators.ColorBurn;
break;
case BlendMode.ColorDodge:
g.Operator = (Operator)ExtendedOperators.ColorDodge;
break;
//case BlendMode.Reflect:
// g.Operator = (Operator)ExtendedOperators.HardLight;
// break;
//case BlendMode.Glow:
// g.Operator = (Operator)ExtendedOperators.SoftLight;
// break;
case BlendMode.HardLight:
g.Operator = (Operator)ExtendedOperators.HardLight;
break;
case BlendMode.SoftLight:
g.Operator = (Operator)ExtendedOperators.SoftLight;
break;
case BlendMode.Overlay:
g.Operator = (Operator)ExtendedOperators.Overlay;
break;
case BlendMode.Difference:
g.Operator = (Operator)ExtendedOperators.Difference;
break;
//case BlendMode.Negation:
// g.Operator = (Operator)21;
// break;
case BlendMode.Color:
g.Operator = (Operator)ExtendedOperators.HslColor;
break;
case BlendMode.Luminosity:
g.Operator = (Operator)ExtendedOperators.HslLuminosity;
break;
case BlendMode.Hue:
g.Operator = (Operator)ExtendedOperators.HslHue;
break;
case BlendMode.Saturation:
g.Operator = (Operator)ExtendedOperators.HslSaturation;
break;
case BlendMode.Lighten:
g.Operator = (Operator)ExtendedOperators.Lighten;
break;
Expand Down
40 changes: 24 additions & 16 deletions Pinta.Core/ImageFormats/OraFormat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,22 +233,14 @@ private string BlendModeToStandard (BlendMode mode)
return "svg:src-over";
case BlendMode.Multiply:
return "svg:multiply";
case BlendMode.Additive:
return "svg:plus";
case BlendMode.ColorBurn:
return "svg:color-burn";
case BlendMode.ColorDodge:
return "svg:color-dodge";
case BlendMode.Reflect:
return "pinta-reflect";
case BlendMode.Glow:
return "pinta-glow";
case BlendMode.Overlay:
return "svg:overlay";
case BlendMode.Difference:
return "svg:difference";
case BlendMode.Negation:
return "pinta-negation";
case BlendMode.Lighten:
return "svg:lighten";
case BlendMode.Darken:
Expand All @@ -257,6 +249,18 @@ private string BlendModeToStandard (BlendMode mode)
return "svg:screen";
case BlendMode.Xor:
return "svg:xor";
case BlendMode.HardLight:
return "svg:hard-light";
case BlendMode.SoftLight:
return "svg:soft-light";
case BlendMode.Color:
return "svg:color";
case BlendMode.Luminosity:
return "svg:luminosity";
case BlendMode.Hue:
return "svg:hue";
case BlendMode.Saturation:
return "svg:saturation";
}
}

Expand All @@ -267,22 +271,14 @@ private BlendMode StandardToBlendMode (string mode)
return BlendMode.Normal;
case "svg:multiply":
return BlendMode.Multiply;
case "svg:plus":
return BlendMode.Additive;
case "svg:color-burn":
return BlendMode.ColorBurn;
case "svg:color-dodge":
return BlendMode.ColorDodge;
case "pinta-reflect":
return BlendMode.Reflect;
case "pinta-glow":
return BlendMode.Glow;
case "svg:overlay":
return BlendMode.Overlay;
case "svg:difference":
return BlendMode.Difference;
case "pinta-negation":
return BlendMode.Negation;
case "svg:lighten":
return BlendMode.Lighten;
case "svg:darken":
Expand All @@ -291,6 +287,18 @@ private BlendMode StandardToBlendMode (string mode)
return BlendMode.Screen;
case "svg:xor":
return BlendMode.Xor;
case "svg:hard-light":
return BlendMode.HardLight;
case "svg:soft-light":
return BlendMode.SoftLight;
case "svg:color":
return BlendMode.Color;
case "svg:luminosity":
return BlendMode.Luminosity;
case "svg:hue":
return BlendMode.Hue;
case "svg:saturation":
return BlendMode.Saturation;
default:
Console.WriteLine ("Unrecognized composite-op: {0}, using Normal.", mode);
return BlendMode.Normal;
Expand Down
Loading

0 comments on commit 81c8eef

Please sign in to comment.