protected override bool OnExposeEvent(Gdk.EventExpose ev) { base.OnExposeEvent(ev); if (thumbnail == null) { UpdateThumbnail(); } Rectangle rect = GdkWindow.GetBounds(); Cairo.PointD pos = PositionToClientPt(Position); Cairo.Color black = new Cairo.Color(0, 0, 0); using (Cairo.Context g = CairoHelper.Create(GdkWindow)) { //background g.SetSource(thumbnail, 0.0, 0.0); g.Paint(); g.DrawRectangle(new Cairo.Rectangle(rect.X + 1, rect.Y + 1, rect.Width - 1, rect.Height - 1), new Cairo.Color(.75, .75, .75), 1); g.DrawRectangle(new Cairo.Rectangle(rect.X + 2, rect.Y + 2, rect.Width - 3, rect.Height - 3), black, 1); //cursor g.DrawLine(new Cairo.PointD(pos.X + 1, rect.Top + 2), new Cairo.PointD(pos.X + 1, rect.Bottom - 2), black, 1); g.DrawLine(new Cairo.PointD(rect.Left + 2, pos.Y + 1), new Cairo.PointD(rect.Right - 2, pos.Y + 1), black, 1); //point g.DrawEllipse(new Cairo.Rectangle(pos.X - 1, pos.Y - 1, 3, 3), black, 2); } return(true); }
public static Pixbuf CreateColorSwatch(int size, Color color) { using (var surf = CairoExtensions.CreateImageSurface(Cairo.Format.Argb32, size, size)) using (var g = new Cairo.Context(surf)) { g.FillRectangle(new Cairo.Rectangle(0, 0, size, size), color.ToCairoColor()); g.DrawRectangle(new Cairo.Rectangle(0, 0, size, size), new Cairo.Color(0, 0, 0), 1); return(surf.ToPixbuf()); } }
public static Pixbuf CreateTransparentColorSwatch(bool drawBorder) { var size = 16; using (var surface = CairoExtensions.CreateTransparentBackgroundSurface(size)) using (var g = new Cairo.Context(surface)) { if (drawBorder) { g.DrawRectangle(new Cairo.Rectangle(0, 0, size, size), new Cairo.Color(0, 0, 0), 1); } return(surface.ToPixbuf()); } }
/// <summary> /// Create a cursor icon with a shape that visually represents the tool's thickness. /// </summary> /// <param name="imgName">A string containing the name of the tool's icon image to use.</param> /// <param name="shape">The shape to draw.</param> /// <param name="shapeWidth">The width of the shape.</param> /// <param name="imgToShapeX">The horizontal distance between the image's top-left corner and the shape center.</param> /// <param name="imgToShapeY">The verical distance between the image's top-left corner and the shape center.</param> /// <param name="shapeX">The X position in the returned Pixbuf that will be the center of the shape.</param> /// <param name="shapeY">The Y position in the returned Pixbuf that will be the center of the shape.</param> /// <returns>The new cursor icon with an shape that represents the tool's thickness.</returns> public static Gdk.Pixbuf CreateIconWithShape(string imgName, CursorShape shape, int shapeWidth, int imgToShapeX, int imgToShapeY, out int shapeX, out int shapeY) { Gdk.Pixbuf img = PintaCore.Resources.GetIcon(imgName); double zoom = 1d; if (PintaCore.Workspace.HasOpenDocuments) { zoom = Math.Min(30d, PintaCore.Workspace.ActiveDocument.Workspace.Scale); } shapeWidth = (int)Math.Min(800d, ((double)shapeWidth) * zoom); int halfOfShapeWidth = shapeWidth / 2; // Calculate bounding boxes around the both image and shape // relative to the image top-left corner. Gdk.Rectangle imgBBox = new Gdk.Rectangle(0, 0, img.Width, img.Height); Gdk.Rectangle shapeBBox = new Gdk.Rectangle( imgToShapeX - halfOfShapeWidth, imgToShapeY - halfOfShapeWidth, shapeWidth, shapeWidth); // Inflate shape bounding box to allow for anti-aliasing shapeBBox.Inflate(2, 2); // To determine required size of icon, // find union of the image and shape bounding boxes // (still relative to image top-left corner) Gdk.Rectangle iconBBox = imgBBox.Union(shapeBBox); // Image top-left corner in icon co-ordinates int imgX = imgBBox.Left - iconBBox.Left; int imgY = imgBBox.Top - iconBBox.Top; // Shape center point in icon co-ordinates shapeX = imgToShapeX - iconBBox.Left; shapeY = imgToShapeY - iconBBox.Top; using (var i = CairoExtensions.CreateImageSurface(Cairo.Format.ARGB32, iconBBox.Width, iconBBox.Height)) { using (var g = new Cairo.Context(i)) { // Don't show shape if shapeWidth less than 3, if (shapeWidth > 3) { int diam = Math.Max(1, shapeWidth - 2); Cairo.Rectangle shapeRect = new Cairo.Rectangle(shapeX - halfOfShapeWidth, shapeY - halfOfShapeWidth, diam, diam); Cairo.Color outerColor = new Cairo.Color(255, 255, 255, 0.75); Cairo.Color innerColor = new Cairo.Color(0, 0, 0); switch (shape) { case CursorShape.Ellipse: g.DrawEllipse(shapeRect, outerColor, 2); shapeRect = shapeRect.Inflate(-1, -1); g.DrawEllipse(shapeRect, innerColor, 1); break; case CursorShape.Rectangle: g.DrawRectangle(shapeRect, outerColor, 1); shapeRect = shapeRect.Inflate(-1, -1); g.DrawRectangle(shapeRect, innerColor, 1); break; } } // Draw the image g.DrawPixbuf(img, new Cairo.Point(imgX, imgY)); } return(CairoExtensions.ToPixbuf(i)); } }
protected override bool OnExposeEvent(EventExpose e) { base.OnExposeEvent(e); if (!PintaCore.Workspace.HasOpenDocuments) { return(true); } double scale = PintaCore.Workspace.Scale; int x = (int)PintaCore.Workspace.Offset.X; int y = (int)PintaCore.Workspace.Offset.Y; // Translate our expose area for the whole drawingarea to just our canvas Rectangle canvas_bounds = new Rectangle(x, y, PintaCore.Workspace.CanvasSize.Width, PintaCore.Workspace.CanvasSize.Height); canvas_bounds.Intersect(e.Area); if (canvas_bounds.IsEmpty) { return(true); } canvas_bounds.X -= x; canvas_bounds.Y -= y; // Resize our offscreen surface to a surface the size of our drawing area if (canvas == null || canvas.Width != canvas_bounds.Width || canvas.Height != canvas_bounds.Height) { if (canvas != null) { (canvas as IDisposable).Dispose(); } canvas = new Cairo.ImageSurface(Cairo.Format.Argb32, canvas_bounds.Width, canvas_bounds.Height); } cr.Initialize(PintaCore.Workspace.ImageSize, PintaCore.Workspace.CanvasSize); using (Cairo.Context g = CairoHelper.Create(GdkWindow)) { // Draw our 1 px black border g.DrawRectangle(new Cairo.Rectangle(x, y, PintaCore.Workspace.CanvasSize.Width + 1, PintaCore.Workspace.CanvasSize.Height + 1), new Cairo.Color(0, 0, 0), 1); // Set up our clip rectangle g.Rectangle(new Cairo.Rectangle(x, y, PintaCore.Workspace.CanvasSize.Width, PintaCore.Workspace.CanvasSize.Height)); g.Clip(); g.Translate(x, y); bool checker = true; // Resize each layer and paint it to the screen foreach (Layer layer in PintaCore.Layers.GetLayersToPaint()) { cr.Render(layer.Surface, canvas, canvas_bounds.Location, checker); g.SetSourceSurface(canvas, canvas_bounds.X + (int)(layer.Offset.X * scale), canvas_bounds.Y + (int)(layer.Offset.Y * scale)); g.PaintWithAlpha(layer.Opacity); if (layer == PintaCore.Layers.CurrentLayer && PintaCore.LivePreview.IsEnabled) { cr.Render(PintaCore.LivePreview.LivePreviewSurface, canvas, canvas_bounds.Location, checker); g.Save(); g.Scale(scale, scale); g.AppendPath(PintaCore.Layers.SelectionPath); g.Clip(); g.Scale(1 / scale, 1 / scale); g.SetSourceSurface(canvas, canvas_bounds.X, canvas_bounds.Y); g.PaintWithAlpha(layer.Opacity); g.Restore(); } checker = false; } // If we are at least 200% and grid is requested, draw it if (PintaCore.Actions.View.PixelGrid.Active && cr.ScaleFactor.Ratio <= 0.5d) { gr.Render(canvas, canvas_bounds.Location); g.SetSourceSurface(canvas, canvas_bounds.X, canvas_bounds.Y); g.Paint(); } // Selection outline if (PintaCore.Layers.ShowSelection) { g.Save(); g.Translate(0.5, 0.5); g.Scale(scale, scale); g.AppendPath(PintaCore.Layers.SelectionPath); if (PintaCore.Tools.CurrentTool.Name.Contains("Select") && !PintaCore.Tools.CurrentTool.Name.Contains("Selected")) { g.Color = new Cairo.Color(0.7, 0.8, 0.9, 0.2); g.FillRule = Cairo.FillRule.EvenOdd; g.FillPreserve(); } g.LineWidth = 1 / scale; // Draw a white line first so it shows up on dark backgrounds g.Color = new Cairo.Color(1, 1, 1); g.StrokePreserve(); // Draw a black dashed line over the white line g.SetDash(new double[] { 2 / scale, 4 / scale }, 0); g.Color = new Cairo.Color(0, 0, 0); g.Stroke(); g.Restore(); } } return(true); }
/// <summary> /// Draws the text. /// </summary> /// <param name="showCursor">Whether or not to show the mouse cursor in the drawing.</param> /// <param name="useTextLayer">Whether or not to use the TextLayer (as opposed to the Userlayer).</param> private void RedrawText(bool showCursor, bool useTextLayer) { Rectangle r = CurrentTextEngine.GetLayoutBounds(); r.Inflate(10 + OutlineWidth, 10 + OutlineWidth); InflateAndInvalidate(r); CurrentTextBounds = r; Rectangle cursorBounds = Rectangle.Zero; Cairo.ImageSurface surf; if (!useTextLayer) { //Draw text on the current UserLayer's surface as finalized text. surf = PintaCore.Workspace.ActiveDocument.CurrentUserLayer.Surface; } else { //Draw text on the current UserLayer's TextLayer's surface as re-editable text. surf = PintaCore.Workspace.ActiveDocument.CurrentUserLayer.TextLayer.Layer.Surface; ClearTextLayer(); } using (var g = new Cairo.Context(surf)) { g.Save(); // Show selection if on text layer if (useTextLayer) { // Selected Text Cairo.Color c = new Cairo.Color(0.7, 0.8, 0.9, 0.5); foreach (Rectangle rect in CurrentTextEngine.SelectionRectangles) { g.FillRectangle(rect.ToCairoRectangle(), c); } } if (selection != null) { g.AppendPath(selection.SelectionPath); g.FillRule = Cairo.FillRule.EvenOdd; g.Clip(); } g.MoveTo(new Cairo.PointD(CurrentTextEngine.Origin.X, CurrentTextEngine.Origin.Y)); g.SetSourceColor(PintaCore.Palette.PrimaryColor); //Fill in background if (BackgroundFill) { using (var g2 = new Cairo.Context(surf)) { g2.FillRectangle(CurrentTextEngine.GetLayoutBounds().ToCairoRectangle(), PintaCore.Palette.SecondaryColor); } } // Draw the text if (FillText) { Pango.CairoHelper.ShowLayout(g, CurrentTextEngine.Layout); } if (FillText && StrokeText) { g.SetSourceColor(PintaCore.Palette.SecondaryColor); g.LineWidth = OutlineWidth; Pango.CairoHelper.LayoutPath(g, CurrentTextEngine.Layout); g.Stroke(); } else if (StrokeText) { g.SetSourceColor(PintaCore.Palette.PrimaryColor); g.LineWidth = OutlineWidth; Pango.CairoHelper.LayoutPath(g, CurrentTextEngine.Layout); g.Stroke(); } if (showCursor) { var loc = CurrentTextEngine.GetCursorLocation(); g.Antialias = Cairo.Antialias.None; g.DrawLine(new Cairo.PointD(loc.X, loc.Y), new Cairo.PointD(loc.X, loc.Y + loc.Height), new Cairo.Color(0, 0, 0, 1), 1); g.DrawRectangle(new Cairo.Rectangle(loc.X - 1, loc.Y - 1, 3, loc.Height + 2), new Cairo.Color(255, 255, 255), 1); cursorBounds = Rectangle.Inflate(loc, 2, 10); } g.Restore(); if (useTextLayer && (is_editing || ctrlKey) && !CurrentTextEngine.IsEmpty()) { //Draw the text edit rectangle. g.Save(); g.Translate(.5, .5); using (Cairo.Path p = g.CreateRectanglePath(CurrentTextBounds.ToCairoRectangle())) { g.AppendPath(p); } g.LineWidth = 1; g.SetSourceColor(new Cairo.Color(1, 1, 1)); g.StrokePreserve(); g.SetDash(new double[] { 2, 4 }, 0); g.SetSourceColor(new Cairo.Color(1, .1, .2)); g.Stroke(); g.Restore(); } } InflateAndInvalidate(PintaCore.Workspace.ActiveDocument.CurrentUserLayer.previousTextBounds); PintaCore.Workspace.Invalidate(old_cursor_bounds); InflateAndInvalidate(r); PintaCore.Workspace.Invalidate(cursorBounds); old_cursor_bounds = cursorBounds; }
protected override bool OnExposeEvent(EventExpose e) { base.OnExposeEvent(e); if (!PintaCore.Workspace.HasOpenDocuments) { return(true); } double scale = PintaCore.Workspace.Scale; int x = (int)PintaCore.Workspace.Offset.X; int y = (int)PintaCore.Workspace.Offset.Y; // Translate our expose area for the whole drawingarea to just our canvas Rectangle canvas_bounds = new Rectangle(x, y, PintaCore.Workspace.CanvasSize.Width, PintaCore.Workspace.CanvasSize.Height); canvas_bounds.Intersect(e.Area); if (canvas_bounds.IsEmpty) { return(true); } canvas_bounds.X -= x; canvas_bounds.Y -= y; // Resize our offscreen surface to a surface the size of our drawing area if (canvas == null || canvas.Width != canvas_bounds.Width || canvas.Height != canvas_bounds.Height) { if (canvas != null) { (canvas as IDisposable).Dispose(); } canvas = new Cairo.ImageSurface(Cairo.Format.Argb32, canvas_bounds.Width, canvas_bounds.Height); } cr.Initialize(PintaCore.Workspace.ImageSize, PintaCore.Workspace.CanvasSize); using (Cairo.Context g = CairoHelper.Create(GdkWindow)) { // Draw our canvas drop shadow g.DrawRectangle(new Cairo.Rectangle(x - 1, y - 1, PintaCore.Workspace.CanvasSize.Width + 2, PintaCore.Workspace.CanvasSize.Height + 2), new Cairo.Color(.5, .5, .5), 1); g.DrawRectangle(new Cairo.Rectangle(x - 2, y - 2, PintaCore.Workspace.CanvasSize.Width + 4, PintaCore.Workspace.CanvasSize.Height + 4), new Cairo.Color(.8, .8, .8), 1); g.DrawRectangle(new Cairo.Rectangle(x - 3, y - 3, PintaCore.Workspace.CanvasSize.Width + 6, PintaCore.Workspace.CanvasSize.Height + 6), new Cairo.Color(.9, .9, .9), 1); // Set up our clip rectangle g.Rectangle(new Cairo.Rectangle(x, y, PintaCore.Workspace.CanvasSize.Width, PintaCore.Workspace.CanvasSize.Height)); g.Clip(); g.Translate(x, y); // Render all the layers to a surface var layers = PintaCore.Layers.GetLayersToPaint(); if (layers.Count == 0) { canvas.Clear(); } cr.Render(layers, canvas, canvas_bounds.Location); // Paint the surface to our canvas g.SetSourceSurface(canvas, canvas_bounds.X + (int)(0 * scale), canvas_bounds.Y + (int)(0 * scale)); g.Paint(); // Selection outline if (PintaCore.Layers.ShowSelection) { bool fillSelection = PintaCore.Tools.CurrentTool.Name.Contains("Select") && !PintaCore.Tools.CurrentTool.Name.Contains("Selected"); PintaCore.Workspace.ActiveDocument.Selection.Draw(g, scale, fillSelection); } } return(true); }
protected override bool OnExposeEvent(EventExpose e) { base.OnExposeEvent(e); if (!PintaCore.Workspace.HasOpenDocuments) { return(true); } double scale = PintaCore.Workspace.Scale; int x = (int)PintaCore.Workspace.Offset.X; int y = (int)PintaCore.Workspace.Offset.Y; // Translate our expose area for the whole drawingarea to just our canvas Rectangle canvas_bounds = new Rectangle(x, y, PintaCore.Workspace.CanvasSize.Width, PintaCore.Workspace.CanvasSize.Height); canvas_bounds.Intersect(e.Area); if (canvas_bounds.IsEmpty) { return(true); } canvas_bounds.X -= x; canvas_bounds.Y -= y; // Resize our offscreen surface to a surface the size of our drawing area if (canvas == null || canvas.Width != canvas_bounds.Width || canvas.Height != canvas_bounds.Height) { if (canvas != null) { (canvas as IDisposable).Dispose(); } canvas = new Cairo.ImageSurface(Cairo.Format.Argb32, canvas_bounds.Width, canvas_bounds.Height); } cr.Initialize(PintaCore.Workspace.ImageSize, PintaCore.Workspace.CanvasSize); using (Cairo.Context g = CairoHelper.Create(GdkWindow)) { // Draw our canvas drop shadow g.DrawRectangle(new Cairo.Rectangle(x, y, PintaCore.Workspace.CanvasSize.Width + 1, PintaCore.Workspace.CanvasSize.Height + 1), new Cairo.Color(.5, .5, .5), 1); g.DrawRectangle(new Cairo.Rectangle(x - 1, y - 1, PintaCore.Workspace.CanvasSize.Width + 3, PintaCore.Workspace.CanvasSize.Height + 3), new Cairo.Color(.8, .8, .8), 1); g.DrawRectangle(new Cairo.Rectangle(x - 2, y - 2, PintaCore.Workspace.CanvasSize.Width + 5, PintaCore.Workspace.CanvasSize.Height + 5), new Cairo.Color(.9, .9, .9), 1); // Set up our clip rectangle g.Rectangle(new Cairo.Rectangle(x, y, PintaCore.Workspace.CanvasSize.Width, PintaCore.Workspace.CanvasSize.Height)); g.Clip(); g.Translate(x, y); // Render all the layers to a surface var layers = PintaCore.Layers.GetLayersToPaint(); if (layers.Count == 0) { canvas.Clear(); } cr.Render(layers, canvas, canvas_bounds.Location); // Paint the surface to our canvas g.SetSourceSurface(canvas, canvas_bounds.X + (int)(0 * scale), canvas_bounds.Y + (int)(0 * scale)); g.Paint(); // Selection outline if (PintaCore.Layers.ShowSelection) { g.Save(); g.Translate(0.5, 0.5); g.Scale(scale, scale); g.AppendPath(PintaCore.Workspace.ActiveDocument.Selection.SelectionPath); if (PintaCore.Tools.CurrentTool.Name.Contains("Select") && !PintaCore.Tools.CurrentTool.Name.Contains("Selected")) { g.Color = new Cairo.Color(0.7, 0.8, 0.9, 0.2); g.FillRule = Cairo.FillRule.EvenOdd; g.FillPreserve(); } g.LineWidth = 1 / scale; // Draw a white line first so it shows up on dark backgrounds g.Color = new Cairo.Color(1, 1, 1); g.StrokePreserve(); // Draw a black dashed line over the white line g.SetDash(new double[] { 2 / scale, 4 / scale }, 0); g.Color = new Cairo.Color(0, 0, 0); g.Stroke(); g.Restore(); } } return(true); }