private unsafe void DrawText(Cairo.ImageSurface dst, string textFont, string text, Point pt, Size measuredSize, bool antiAliasing, Cairo.ImageSurface brush8x8) { Point pt2 = pt; Size measuredSize2 = measuredSize; int offset = FontHeight; pt.X -= offset; measuredSize.Width += 2 * offset; Rectangle dstRect = new Rectangle (pt, measuredSize); Rectangle dstRectClipped = Rectangle.Intersect (dstRect, PintaCore.Layers.ToolLayer.Surface.GetBounds ()); PintaCore.Layers.ToolLayer.Clear (); if (dstRectClipped.Width == 0 || dstRectClipped.Height == 0) { return; } // We only use the first 8,8 of brush using (Cairo.Context toolctx = new Cairo.Context (PintaCore.Layers.ToolLayer.Surface)) { //toolctx.FillRectangle (new Cairo.Rectangle(0, 0, 800, 600), new Cairo.Color (0, 0, 0)); toolctx.FillRectangle (dstRect.ToCairoRectangle (), new Cairo.Color (1, 1, 1)); Cairo.ImageSurface surf = PintaCore.Layers.ToolLayer.Surface; //TODO find how create a surface a of a particular area of a bigger surface! //for moment work with the whole surface! if (measuredSize.Width > 0 && measuredSize.Height > 0) { //dstRectClipped using (Cairo.Context ctx = new Cairo.Context (PintaCore.Layers.ToolLayer.Surface)) { Cairo.TextExtents te = TextExtents (ctx, text); //new Cairo.PointD(dstRect.X - dstRectClipped.X + offset, dstRect.Y - dstRectClipped.Y), ctx.DrawText (new Cairo.PointD (dstRect.X + offset - te.XBearing, dstRect.Y - te.YBearing), textFont, FontSlant, FontWeight, FontSize, PintaCore.Palette.PrimaryColor, text); if (underscore_btn.Active) { int lineSize = 1; Cairo.FontExtents fe = FontExtents (ctx, text); ctx.DrawLine (new Cairo.PointD (pt2.X, dstRect.Bottom + fe.Descent), new Cairo.PointD (dstRect.Right - offset, dstRect.Bottom + fe.Descent), PintaCore.Palette.PrimaryColor, lineSize); } } PintaCore.Workspace.Invalidate (dstRectClipped); } // Mask out anything that isn't within the user's clip region (selected region) using (Region clip = Region.Rectangle (PintaCore.Layers.SelectionPath.GetBounds ())) { clip.Xor (Region.Rectangle (dstRectClipped)); // invert clip.Intersect (Region.Rectangle (new Rectangle (pt, measuredSize))); toolctx.FillRegion (clip, new Cairo.Color (1, 1, 1, 1)); } int skipX; if (pt.X < 0) { skipX = -pt.X; } else { skipX = 0; } int xEnd = Math.Min (dst.Width, pt.X + measuredSize.Width); bool blending = false; //AppEnvironment.AlphaBlending; //if (dst.IsColumnVisible(pt.X + skipX)) //{ for (int y = pt.Y; y < pt.Y + measuredSize.Height; ++y) { //if (!dst.IsRowVisible(y)) //{ // continue; //} ColorBgra* dstPtr = dst.GetPointAddressUnchecked (pt.X + skipX, y); ColorBgra* srcPtr = PintaCore.Layers.ToolLayer.Surface.GetPointAddress (pt.X + skipX, y); ColorBgra* brushPtr = brush8x8.GetRowAddressUnchecked (y & 7); for (int x = pt.X + skipX; x < xEnd; ++x) { ColorBgra srcPixel = *srcPtr; ColorBgra dstPixel = *dstPtr; ColorBgra brushPixel = brushPtr[x & 7]; int alpha = ((255 - srcPixel.R) * brushPixel.A) / 255; // we could use srcPixel.R, .G, or .B -- the choice here is arbitrary brushPixel.A = (byte)alpha; // could use R, G, or B -- arbitrary choice if (srcPtr->R == 255) { // do nothing -- leave dst alone } else if (alpha == 255 || !blending) { // copy it straight over *dstPtr = brushPixel; } else { // do expensive blending *dstPtr = UserBlendOps.NormalBlendOp.ApplyStatic (dstPixel, brushPixel); } ++dstPtr; ++srcPtr; } } //} } }
/// <summary> /// Draw a box model /// </summary> /// <param name="g">the Cairo context</param> /// <param name="rect">the rect (of the border-box) in which to draw this box model </param> /// <param name="content">content of the box mode</param> /// <param name="style">style of the box model</param> internal static void DrawBoxModel(this Cairo.Context g, Rect rect, string text, GUIStyle style) { //Widths of border var bt = style.BorderTop; var br = style.BorderRight; var bb = style.BorderBottom; var bl = style.BorderLeft; //Widths of padding var pt = style.PaddingTop; var pr = style.PaddingRight; var pb = style.PaddingBottom; var pl = style.PaddingLeft; //4 corner of the border-box var btl = new Point(rect.Left, rect.Top); var btr = new Point(rect.Right, rect.Top); var bbr = new Point(rect.Right, rect.Bottom); var bbl = new Point(rect.Left, rect.Bottom); var borderBoxRect = new Rect(btl, bbr); //4 corner of the padding-box var ptl = new Point(btl.X + bl, btl.Y + bt); var ptr = new Point(btr.X - br, btr.Y + bt); var pbr = new Point(bbr.X - br, bbr.Y - bb); var pbl = new Point(bbl.X + bl, bbl.Y - bb); var paddingBoxRect = new Rect(ptl, pbr); //4 corner of the content-box var ctl = new Point(ptl.X + pl, ptl.Y + pt); var ctr = new Point(ptr.X - pr, ptr.Y + pr); var cbr = new Point(pbr.X - pr, pbr.Y - pb); var cbl = new Point(pbl.X + pl, pbl.Y - pb); var contentBoxRect = new Rect(ctl, cbr); /* * Render from inner to outer: Content, Padding, Border, Margin, Outline */ //Content //Content-box background(draw as a filled rectangle now) g.FillRectangle(rect, style.BackgroundColor); //Content-box if (text != null) { g.DrawText(contentBoxRect, text, style.FontSize, style.FontColor); } //Border // Top if (bt != 0) { g.FillPolygon(new[] { ptl, btl, btr, ptr }, style.BorderTopColor); } // Right if (br != 0) { g.FillPolygon(new[] { ptr, btr, bbr, pbr }, style.BorderRightColor); } // Bottom if (bb != 0) { g.FillPolygon(new[] { pbr, bbr, bbl, pbl }, style.BorderBottomColor); } // Left if (bl != 0) { g.FillPolygon(new[] { pbl, bbl, btl, ptl }, style.BorderLeftColor); } //Outline if (style.OutlineWidth != 0) { g.Rectangle(borderBoxRect.TopLeft.ToPointD(), borderBoxRect.Width, borderBoxRect.Height); g.LineWidth = style.OutlineWidth; g.SetSourceColor(style.OutlineColor); g.Stroke(); } #if DrawPaddingBox g.Rectangle(paddingBoxRect.TopLeft.ToPointD(), paddingBoxRect.Width, paddingBoxRect.Height); g.LineWidth = 1; g.SetSourceColor(CairoEx.ColorRgb(0, 100, 100)); g.Stroke(); #endif #if DrawContentBox g.Rectangle(contentBoxRect.TopLeft.ToPointD(), contentBoxRect.Width, contentBoxRect.Height); g.LineWidth = 1; g.SetSourceColor(CairoEx.ColorRgb(100, 0, 100)); g.Stroke(); #endif }