Skip to content

Commit

Permalink
feature: Rotate selection and selected
Browse files Browse the repository at this point in the history
  • Loading branch information
Volodymyr committed Jul 14, 2012
1 parent 0664403 commit 064f2b4
Show file tree
Hide file tree
Showing 13 changed files with 306 additions and 98 deletions.
9 changes: 2 additions & 7 deletions Pinta.Core/Classes/Document.cs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ public void DestroySelectionLayer ()
{
ShowSelectionLayer = false;
SelectionLayer.Clear ();
SelectionLayer.Offset = new PointD (0, 0);
SelectionLayer.Transform.InitIdentity();
}

// Duplicate current layer
Expand Down Expand Up @@ -402,12 +402,7 @@ public void FinishSelection ()
Layer layer = SelectionLayer;

using (Cairo.Context g = new Cairo.Context (CurrentLayer.Surface)) {
g.Save ();

g.SetSourceSurface (layer.Surface, (int)layer.Offset.X, (int)layer.Offset.Y);
g.PaintWithAlpha (layer.Opacity);

g.Restore ();
layer.Draw(g);
}

DestroySelectionLayer ();
Expand Down
30 changes: 27 additions & 3 deletions Pinta.Core/Classes/Layer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class Layer : ObservableObject
private bool hidden;
private string name;
private BlendMode blend_mode;
private Matrix transform = new Matrix();

public Layer () : this (null)
{
Expand All @@ -50,8 +51,7 @@ public Layer (ImageSurface surface) : this (surface, false, 1f, "")
public Layer (ImageSurface surface, bool hidden, double opacity, string name)
{
Surface = surface;
Offset = new PointD (0, 0);


this.hidden = hidden;
this.opacity = opacity;
this.name = name;
Expand All @@ -60,7 +60,7 @@ public Layer (ImageSurface surface, bool hidden, double opacity, string name)

public ImageSurface Surface { get; set; }
public bool Tiled { get; set; }
public PointD Offset { get; set; }
public Matrix Transform { get { return transform; } }

public static readonly string OpacityProperty = "Opacity";
public static readonly string HiddenProperty = "Hidden";
Expand Down Expand Up @@ -123,6 +123,30 @@ public void FlipVertical ()
Surface = dest.Surface;
(old as IDisposable).Dispose ();
}

public void Draw(Context ctx)
{
Draw(ctx, Surface, Opacity, 0, 0, 1);
}

public void Draw(Context ctx, ImageSurface surface, double opacity)
{
Draw(ctx, surface, opacity, 0, 0, 1);
}

public void Draw(Context ctx, ImageSurface surface, double opacity, double offsetX, double offsetY, double scale)
{
ctx.Save();

ctx.Translate(offsetX, offsetY);
ctx.Scale(scale, scale);
ctx.Transform(Transform);
ctx.Scale(1 / scale, 1 / scale);
ctx.SetSourceSurface(surface, 0, 0);
ctx.PaintWithAlpha(opacity);

ctx.Restore();
}

/// <summary>
/// Rotates layer by the specified angle (in degrees).
Expand Down
48 changes: 46 additions & 2 deletions Pinta.Core/Extensions/CairoExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,8 @@ public static Gdk.Size ToSize (this Cairo.Point point)

public static ImageSurface Clone (this ImageSurface surf)
{
return new ImageSurface ((byte[])surf.Data.Clone (), surf.Format, surf.Width, surf.Height, surf.Stride);
byte[] temp = (byte[])surf.Data.Clone ();
return new ImageSurface (ref temp, surf.Format, surf.Width, surf.Height, surf.Stride);
}

public static unsafe bool ContainsTranslucent (this ImageSurface surf)
Expand Down Expand Up @@ -847,7 +848,7 @@ public static Gdk.Rectangle GetBounds (this Path path)
Rectangle rect;

using (Context g = new Context (PintaCore.Layers.CurrentLayer.Surface)) {
g.AppendPath (PintaCore.Layers.SelectionPath);
g.AppendPath (path);

// We don't want the bounding box to include a stroke width
// of 1, but setting it to 0 returns an empty rectangle. Set
Expand Down Expand Up @@ -1404,5 +1405,48 @@ public static bool IsEmpty (this PointD point)
{
return point.X == 0 && point.Y == 0;
}

public static void TransformPoint(this Matrix matrix, ref PointD point)
{
double x = point.X;
double y = point.Y;

matrix.TransformPoint(ref x, ref y);

point.X = x;
point.Y = y;
}

public static void InitMatrix(this Matrix matrix, Matrix source)
{
matrix.X0 = source.X0;
matrix.Xx = source.Xx;
matrix.Xy = source.Xy;

matrix.Y0 = source.Y0;
matrix.Yx = source.Yx;
matrix.Yy = source.Yy;
}

public static void InitRectToRect(this Matrix matrix, Rectangle src, Rectangle dst)
{
matrix.InitIdentity();

matrix.Xx = dst.Width / src.Width;
matrix.Yy = dst.Height / src.Height;
matrix.X0 = dst.X - (matrix.Xx * src.X);
matrix.Y0 = dst.Y - (matrix.Yy * src.Y);
}

public static Rectangle FromLTRB(double left, double top, double right, double bottom)
{
return new Rectangle(Math.Min(left, right), Math.Min(top, bottom),
Math.Abs(right - left), Math.Abs(bottom - top));
}

public static PointD GetCenter(this Cairo.Rectangle rect)
{
return new PointD(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
}
}
}
4 changes: 4 additions & 0 deletions Pinta.Core/Extensions/GtkExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ namespace Pinta.Core
{
public static class GtkExtensions
{
public const int MouseLeftButton = 1;
public const int MouseMiddleButton = 2;
public const int MouseRightButton = 3;

public static void AddWidgetItem (this Toolbar tb, Widget w)
{
w.Show ();
Expand Down
18 changes: 10 additions & 8 deletions Pinta.Core/HistoryItems/FinishPixelsHistoryItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ namespace Pinta.Core
public class FinishPixelsHistoryItem : BaseHistoryItem
{
private ImageSurface old_selection_layer;
private PointD old_offset;
private ImageSurface old_surface;
private readonly Matrix old_transform = new Matrix();

public override bool CausesDirty { get { return false; } }

Expand All @@ -48,15 +48,16 @@ public override void Undo ()
{
PintaCore.Layers.ShowSelectionLayer = true;

PointD swap_offset = PintaCore.Layers.SelectionLayer.Offset;
Matrix swap_transfrom = new Matrix();
swap_transfrom.InitMatrix(PintaCore.Layers.SelectionLayer.Transform);
ImageSurface swap_surf = PintaCore.Layers.CurrentLayer.Surface;
ImageSurface swap_sel = PintaCore.Layers.SelectionLayer.Surface;

PintaCore.Layers.SelectionLayer.Surface = old_selection_layer;
PintaCore.Layers.SelectionLayer.Offset = old_offset;
PintaCore.Layers.SelectionLayer.Transform.InitMatrix(old_transform);
PintaCore.Layers.CurrentLayer.Surface = old_surface;

old_offset = swap_offset;
old_transform.InitMatrix(swap_transfrom);
old_surface = swap_surf;
old_selection_layer = swap_sel;

Expand All @@ -66,17 +67,18 @@ public override void Undo ()

public override void Redo ()
{
PointD swap_offset = PintaCore.Layers.SelectionLayer.Offset;
Matrix swap_transfrom = new Matrix();
swap_transfrom.InitMatrix(PintaCore.Layers.SelectionLayer.Transform);
ImageSurface swap_surf = PintaCore.Layers.CurrentLayer.Surface.Clone ();
ImageSurface swap_sel = PintaCore.Layers.SelectionLayer.Surface;

PintaCore.Layers.CurrentLayer.Surface = old_surface;
PintaCore.Layers.SelectionLayer.Surface = old_selection_layer;
PintaCore.Layers.SelectionLayer.Offset = old_offset;
PintaCore.Layers.SelectionLayer.Transform.InitMatrix(old_transform);

old_surface = swap_surf;
old_selection_layer = swap_sel;
old_offset = swap_offset;
old_transform.InitMatrix(swap_transfrom);

PintaCore.Layers.DestroySelectionLayer ();
PintaCore.Workspace.Invalidate ();
Expand All @@ -91,8 +93,8 @@ public override void Dispose ()
public void TakeSnapshot ()
{
old_selection_layer = PintaCore.Layers.SelectionLayer.Surface.Clone ();
old_offset = PintaCore.Layers.SelectionLayer.Offset;
old_surface = PintaCore.Layers.CurrentLayer.Surface.Clone ();
old_transform.InitMatrix(PintaCore.Layers.CurrentLayer.Transform);
}
}
}
11 changes: 6 additions & 5 deletions Pinta.Core/HistoryItems/MovePixelsHistoryItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class MovePixelsHistoryItem : BaseHistoryItem
// around the temporary layer
private Document doc;
private Path old_path;
private PointD old_offset;
private readonly Matrix old_transform = new Matrix();
private ImageSurface old_surface;
private int layer_index;
private bool lifted; // Whether this item has lift
Expand Down Expand Up @@ -69,14 +69,15 @@ public override void Dispose ()

private void Swap ()
{
Matrix swap_transform = new Matrix();
Path swap_path = PintaCore.Layers.SelectionPath;
PointD swap_offset = PintaCore.Layers.SelectionLayer.Offset;
swap_transform.InitMatrix(PintaCore.Layers.SelectionLayer.Transform);

PintaCore.Layers.SelectionPath = old_path;
PintaCore.Layers.SelectionLayer.Offset = old_offset;
PintaCore.Layers.SelectionLayer.Transform.InitMatrix(old_transform);

old_path = swap_path;
old_offset = swap_offset;
old_transform.InitMatrix(swap_transform);

if (lifted) {
// Grab the original surface
Expand Down Expand Up @@ -106,7 +107,7 @@ public void TakeSnapshot (bool lift)
}

old_path = PintaCore.Layers.SelectionPath.Clone ();
old_offset = PintaCore.Layers.SelectionLayer.Offset;
old_transform.InitMatrix(PintaCore.Layers.SelectionLayer.Transform);
}
}
}
14 changes: 5 additions & 9 deletions Pinta.Core/Managers/LivePreviewManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ public void Start (BaseEffect effect)

// Paint the pre-effect layer surface into into the working surface.
using (var ctx = new Cairo.Context (live_preview_surface)) {
ctx.SetSourceSurface (layer.Surface, (int) layer.Offset.X, (int) layer.Offset.Y);
ctx.Paint ();
layer.Draw(ctx, layer.Surface, 1);
}

if (effect.EffectData != null)
Expand Down Expand Up @@ -150,24 +149,22 @@ public void RenderLivePreviewLayer (Cairo.Context ctx, double opacity)
ctx.Rectangle (0, 0, imageSize.Width, imageSize.Height);
ctx.AppendPath (selection_path);
ctx.Clip ();
ctx.SetSourceSurface (layer.Surface, (int)layer.Offset.X, (int)layer.Offset.Y);
ctx.PaintWithAlpha (opacity);
layer.Draw(ctx, layer.Surface, opacity);
ctx.ResetClip ();

// Paint area inside the selection path, with the post-effect image.
ctx.AppendPath (selection_path);
ctx.Clip ();

ctx.SetSourceSurface (live_preview_surface, (int)layer.Offset.X, (int)layer.Offset.Y);
layer.Draw(ctx, live_preview_surface, opacity);
ctx.PaintWithAlpha (opacity);

ctx.AppendPath (selection_path);
ctx.FillRule = Cairo.FillRule.EvenOdd;
ctx.Clip ();
} else {

ctx.SetSourceSurface (live_preview_surface, (int)layer.Offset.X, (int)layer.Offset.Y);
ctx.PaintWithAlpha (opacity);
layer.Draw(ctx, live_preview_surface, opacity);
}
ctx.Restore ();
}
Expand Down Expand Up @@ -247,8 +244,7 @@ void HandleApply ()

ctx.Operator = Cairo.Operator.Source;

ctx.SetSourceSurface (live_preview_surface, (int)layer.Offset.X, (int)layer.Offset.Y);
ctx.Paint ();
layer.Draw(ctx, live_preview_surface, 1);
ctx.Restore ();
}

Expand Down
13 changes: 6 additions & 7 deletions Pinta.Gui.Widgets/Widgets/Canvas/CanvasRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ private Layer CreateLivePreviewLayer (Layer original)
var preview_layer = new Layer (PintaCore.LivePreview.LivePreviewSurface);

preview_layer.BlendMode = original.BlendMode;
preview_layer.Offset = original.Offset;
preview_layer.Transform.InitMatrix(original.Transform);
preview_layer.Opacity = original.Opacity;
preview_layer.Hidden = original.Hidden;

Expand All @@ -87,12 +87,11 @@ private Layer CreateOffsetLayer (Layer original, Point canvas_offset)
offset.Surface.Clear ();

using (var g = new Cairo.Context (offset.Surface)) {
g.SetSourceSurface (original.Surface, canvas_offset.X + (int)original.Offset.X, canvas_offset.Y + (int)original.Offset.Y);
g.Paint ();
original.Draw(g, original.Surface, 1, canvas_offset.X, canvas_offset.Y, 1);
}

offset.BlendMode = original.BlendMode;
offset.Offset = original.Offset;
offset.Transform.InitMatrix(original.Transform);
offset.Opacity = original.Opacity;

return offset;
Expand All @@ -113,7 +112,7 @@ private unsafe void RenderOneToOne (List<Layer> layers, Cairo.ImageSurface dst,
layer = CreateLivePreviewLayer (layer);

// If the layer is offset, handle it here
if (!layer.Offset.IsEmpty ())
if (!layer.Transform.IsIdentity ())
layer = CreateOffsetLayer (layer, offset);

var src = layer.Surface;
Expand Down Expand Up @@ -177,7 +176,7 @@ private unsafe void RenderZoomIn (List<Layer> layers, Cairo.ImageSurface dst, Gd
layer = CreateLivePreviewLayer (layer);

// If the layer is offset, handle it here
if (!layer.Offset.IsEmpty ())
if (!layer.Transform.IsIdentity ())
layer = CreateOffsetLayer (layer, offset);

var src = layer.Surface;
Expand Down Expand Up @@ -248,7 +247,7 @@ private unsafe void RenderZoomOut (List<Layer> layers, Cairo.ImageSurface dst, G
layer = CreateLivePreviewLayer (layer);

// If the layer is offset, handle it here
if (!layer.Offset.IsEmpty ())
if (!layer.Transform.IsIdentity ())
layer = CreateOffsetLayer (layer, offset);

var src = layer.Surface;
Expand Down
3 changes: 1 addition & 2 deletions Pinta.Gui.Widgets/Widgets/PointPickerGraphic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ private void UpdateThumbnail ()
using (Cairo.Context g = new Cairo.Context (thumbnail)) {
g.Scale (scalex, scaley);
foreach (Layer layer in PintaCore.Layers.GetLayersToPaint ()) {
g.SetSourceSurface (layer.Surface, (int)layer.Offset.X, (int)layer.Offset.Y);
g.PaintWithAlpha (layer.Opacity);
layer.Draw(g);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions Pinta.Tools/Pinta.Tools.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Xml" />
<Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<Reference Include="Mono.Cairo" />
Expand Down Expand Up @@ -110,6 +109,7 @@
<Compile Include="Brushes\PlainBrush.cs" />
<Compile Include="Brushes\CircleBrush.cs" />
<Compile Include="Tools\ToolControl\ToolControl.cs" />
<Compile Include="Tools\BaseTransformTool.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Pinta.Core\Pinta.Core.csproj">
Expand Down
Loading

0 comments on commit 064f2b4

Please sign in to comment.