public unsafe override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois) { PointD start = new PointD(0, 0); double theta = ((double)(Data.Angle + 180) * 2 * Math.PI) / 360.0; double alpha = (double)Data.Distance; PointD end = new PointD((float)alpha * Math.Cos(theta), (float)(-alpha * Math.Sin(theta))); if (Data.Centered) { start.X = -end.X / 2.0f; start.Y = -end.Y / 2.0f; end.X /= 2.0f; end.Y /= 2.0f; } PointD[] points = new PointD[((1 + Data.Distance) * 3) / 2]; if (points.Length == 1) { points[0] = new PointD(0, 0); } else { for (int i = 0; i < points.Length; ++i) { float frac = (float)i / (float)(points.Length - 1); points[i] = Utility.Lerp(start, end, frac); } } ColorBgra *samples = stackalloc ColorBgra[points.Length]; ColorBgra *src_dataptr = (ColorBgra *)src.DataPtr; int src_width = src.Width; int src_height = src.Height; foreach (Gdk.Rectangle rect in rois) { for (int y = rect.Top; y <= rect.GetBottom(); ++y) { ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); for (int x = rect.Left; x <= rect.GetRight(); ++x) { int sampleCount = 0; for (int j = 0; j < points.Length; ++j) { PointD pt = new PointD(points[j].X + (float)x, points[j].Y + (float)y); if (pt.X >= 0 && pt.Y >= 0 && pt.X <= (src_width - 1) && pt.Y <= (src_height - 1)) { samples[sampleCount] = src.GetBilinearSample(src_dataptr, src_width, src_height, (float)pt.X, (float)pt.Y); ++sampleCount; } } *dstPtr = ColorBgra.Blend(samples, sampleCount); ++dstPtr; } } } }
public unsafe override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois) { ColorBgra colPrimary = PintaCore.Palette.PrimaryColor.ToColorBgra(); ColorBgra colSecondary = PintaCore.Palette.SecondaryColor.ToColorBgra(); ColorBgra colTransparent = ColorBgra.Transparent; int aaSampleCount = Data.Quality * Data.Quality; Cairo.PointD *aaPoints = stackalloc Cairo.PointD[aaSampleCount]; Utility.GetRgssOffsets(aaPoints, aaSampleCount, Data.Quality); ColorBgra *samples = stackalloc ColorBgra[aaSampleCount]; TransformData td; foreach (Gdk.Rectangle rect in rois) { for (int y = rect.Top; y <= rect.GetBottom(); y++) { ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); double relativeY = y - Data.CenterOffset.Y; for (int x = rect.Left; x <= rect.GetRight(); x++) { double relativeX = x - Data.CenterOffset.X; int sampleCount = 0; for (int p = 0; p < aaSampleCount; ++p) { td.X = relativeX + aaPoints[p].X; td.Y = relativeY - aaPoints[p].Y; InverseTransform(ref td); float sampleX = (float)(td.X + Data.CenterOffset.X); float sampleY = (float)(td.Y + Data.CenterOffset.Y); ColorBgra sample = colPrimary; if (IsOnSurface(src, sampleX, sampleY)) { sample = src.GetBilinearSample(sampleX, sampleY); } else { switch (Data.EdgeBehavior) { case WarpEdgeBehavior.Clamp: sample = src.GetBilinearSampleClamped(sampleX, sampleY); break; case WarpEdgeBehavior.Wrap: sample = src.GetBilinearSampleWrapped(sampleX, sampleY); break; case WarpEdgeBehavior.Reflect: sample = src.GetBilinearSampleClamped(ReflectCoord(sampleX, src.Width), ReflectCoord(sampleY, src.Height)); break; case WarpEdgeBehavior.Primary: sample = colPrimary; break; case WarpEdgeBehavior.Secondary: sample = colSecondary; break; case WarpEdgeBehavior.Transparent: sample = colTransparent; break; case WarpEdgeBehavior.Original: sample = src.GetColorBgra(x, y); break; default: break; } } samples[sampleCount] = sample; ++sampleCount; } *dstPtr = ColorBgra.Blend(samples, sampleCount); ++dstPtr; } } } }