public unsafe override void Render(Surface dst, System.Drawing.Point offset) { if (OwnerList.ScaleFactor < new ScaleFactor(2, 1)) { return; } int[] d2SLookupX = OwnerList.Dst2SrcLookupX; int[] d2SLookupY = OwnerList.Dst2SrcLookupY; int[] s2DLookupX = OwnerList.Src2DstLookupX; int[] s2DLookupY = OwnerList.Src2DstLookupY; ColorBgra[] blackAndWhite = new ColorBgra[2] { ColorBgra.White, ColorBgra.Black }; // draw horizontal lines int sTop = d2SLookupY[offset.Y]; int sBottom = d2SLookupY[offset.Y + dst.Height]; for (int srcY = sTop; srcY <= sBottom; ++srcY) { int dstY = s2DLookupY[srcY]; int dstRow = dstY - offset.Y; if (dst.IsRowVisible(dstRow)) { ColorBgra *dstRowPtr = dst.GetRowAddress(dstRow); ColorBgra *dstRowEndPtr = dstRowPtr + dst.Width; dstRowPtr += offset.X & 1; while (dstRowPtr < dstRowEndPtr) { *dstRowPtr = ColorBgra.Black; dstRowPtr += 2; } } } // draw vertical lines int sLeft = d2SLookupX[offset.X]; int sRight = d2SLookupX[offset.X + dst.Width]; for (int srcX = sLeft; srcX <= sRight; ++srcX) { int dstX = s2DLookupX[srcX]; int dstCol = dstX - offset.X; if (dst.IsColumnVisible(dstX - offset.X)) { byte *dstColPtr = (byte *)dst.GetPointAddress(dstCol, 0); byte *dstColEndPtr = dstColPtr + dst.Stride * dst.Height; dstColPtr += (offset.Y & 1) * dst.Stride; while (dstColPtr < dstColEndPtr) { *((ColorBgra *)dstColPtr) = ColorBgra.Black; dstColPtr += 2 * dst.Stride; } } } }
public static void RenderZoomOutRotatedGridMultisampling(Surface dst, Surface source, Point offset, Size destinationSize) { unsafe { const int fpShift = 12; const int fpFactor = (1 << fpShift); Size sourceSize = source.Size; long fDstLeftLong = ((long)offset.X * fpFactor * (long)sourceSize.Width) / (long)destinationSize.Width; long fDstTopLong = ((long)offset.Y * fpFactor * (long)sourceSize.Height) / (long)destinationSize.Height; long fDstRightLong = ((long)(offset.X + dst.Width) * fpFactor * (long)sourceSize.Width) / (long)destinationSize.Width; long fDstBottomLong = ((long)(offset.Y + dst.Height) * fpFactor * (long)sourceSize.Height) / (long)destinationSize.Height; int fDstLeft = (int)fDstLeftLong; int fDstTop = (int)fDstTopLong; int fDstRight = (int)fDstRightLong; int fDstBottom = (int)fDstBottomLong; int dx = (fDstRight - fDstLeft) / dst.Width; int dy = (fDstBottom - fDstTop) / dst.Height; for (int dstRow = 0, fDstY = fDstTop; dstRow < dst.Height && fDstY < fDstBottom; ++dstRow, fDstY += dy) { int srcY1 = fDstY >> fpShift; // y int srcY2 = (fDstY + (dy >> 2)) >> fpShift; // y + 0.25 int srcY3 = (fDstY + (dy >> 1)) >> fpShift; // y + 0.50 int srcY4 = (fDstY + (dy >> 1) + (dy >> 2)) >> fpShift; // y + 0.75 #if DEBUG Debug.Assert(source.IsRowVisible(srcY1)); Debug.Assert(source.IsRowVisible(srcY2)); Debug.Assert(source.IsRowVisible(srcY3)); Debug.Assert(source.IsRowVisible(srcY4)); Debug.Assert(dst.IsRowVisible(dstRow)); #endif ColorBgra* src1 = source.GetRowAddressUnchecked(srcY1); ColorBgra* src2 = source.GetRowAddressUnchecked(srcY2); ColorBgra* src3 = source.GetRowAddressUnchecked(srcY3); ColorBgra* src4 = source.GetRowAddressUnchecked(srcY4); ColorBgra* dstPtr = dst.GetRowAddressUnchecked(dstRow); int checkerY = dstRow + offset.Y; int checkerX = offset.X; int maxCheckerX = checkerX + dst.Width; for (int fDstX = fDstLeft; checkerX < maxCheckerX && fDstX < fDstRight; ++checkerX, fDstX += dx) { int srcX1 = (fDstX + (dx >> 2)) >> fpShift; // x + 0.25 int srcX2 = (fDstX + (dx >> 1) + (dx >> 2)) >> fpShift; // x + 0.75 int srcX3 = fDstX >> fpShift; // x int srcX4 = (fDstX + (dx >> 1)) >> fpShift; // x + 0.50 #if DEBUG Debug.Assert(source.IsColumnVisible(srcX1)); Debug.Assert(source.IsColumnVisible(srcX2)); Debug.Assert(source.IsColumnVisible(srcX3)); Debug.Assert(source.IsColumnVisible(srcX4)); #endif ColorBgra* p1 = src1 + srcX1; ColorBgra* p2 = src2 + srcX2; ColorBgra* p3 = src3 + srcX3; ColorBgra* p4 = src4 + srcX4; int r = (2 + p1->R + p2->R + p3->R + p4->R) >> 2; int g = (2 + p1->G + p2->G + p3->G + p4->G) >> 2; int b = (2 + p1->B + p2->B + p3->B + p4->B) >> 2; int a = (2 + p1->A + p2->A + p3->A + p4->A) >> 2; // Blend it over the checkerboard background int v = ((checkerX ^ checkerY) & 8) * 8 + 191; a = a + (a >> 7); int vmia = v * (256 - a); r = ((r * a) + vmia) >> 8; g = ((g * a) + vmia) >> 8; b = ((b * a) + vmia) >> 8; dstPtr->Bgra = (uint)b + ((uint)g << 8) + ((uint)r << 16) + 0xff000000; ++dstPtr; } } } }
public static void RenderZoomOutRotatedGridMultisampling(Surface dst, Surface source, Point offset, Size destinationSize) { unsafe { const int fpShift = 12; const int fpFactor = (1 << fpShift); Size sourceSize = source.Size; long fDstLeftLong = ((long)offset.X * fpFactor * (long)sourceSize.Width) / (long)destinationSize.Width; long fDstTopLong = ((long)offset.Y * fpFactor * (long)sourceSize.Height) / (long)destinationSize.Height; long fDstRightLong = ((long)(offset.X + dst.Width) * fpFactor * (long)sourceSize.Width) / (long)destinationSize.Width; long fDstBottomLong = ((long)(offset.Y + dst.Height) * fpFactor * (long)sourceSize.Height) / (long)destinationSize.Height; int fDstLeft = (int)fDstLeftLong; int fDstTop = (int)fDstTopLong; int fDstRight = (int)fDstRightLong; int fDstBottom = (int)fDstBottomLong; int dx = (fDstRight - fDstLeft) / dst.Width; int dy = (fDstBottom - fDstTop) / dst.Height; for (int dstRow = 0, fDstY = fDstTop; dstRow < dst.Height && fDstY < fDstBottom; ++dstRow, fDstY += dy) { int srcY1 = fDstY >> fpShift; // y int srcY2 = (fDstY + (dy >> 2)) >> fpShift; // y + 0.25 int srcY3 = (fDstY + (dy >> 1)) >> fpShift; // y + 0.50 int srcY4 = (fDstY + (dy >> 1) + (dy >> 2)) >> fpShift; // y + 0.75 #if DEBUG Debug.Assert(source.IsRowVisible(srcY1)); Debug.Assert(source.IsRowVisible(srcY2)); Debug.Assert(source.IsRowVisible(srcY3)); Debug.Assert(source.IsRowVisible(srcY4)); Debug.Assert(dst.IsRowVisible(dstRow)); #endif ColorBgra *src1 = source.GetRowAddressUnchecked(srcY1); ColorBgra *src2 = source.GetRowAddressUnchecked(srcY2); ColorBgra *src3 = source.GetRowAddressUnchecked(srcY3); ColorBgra *src4 = source.GetRowAddressUnchecked(srcY4); ColorBgra *dstPtr = dst.GetRowAddressUnchecked(dstRow); int checkerY = dstRow + offset.Y; int checkerX = offset.X; int maxCheckerX = checkerX + dst.Width; for (int fDstX = fDstLeft; checkerX < maxCheckerX && fDstX < fDstRight; ++checkerX, fDstX += dx) { int srcX1 = (fDstX + (dx >> 2)) >> fpShift; // x + 0.25 int srcX2 = (fDstX + (dx >> 1) + (dx >> 2)) >> fpShift; // x + 0.75 int srcX3 = fDstX >> fpShift; // x int srcX4 = (fDstX + (dx >> 1)) >> fpShift; // x + 0.50 #if DEBUG Debug.Assert(source.IsColumnVisible(srcX1)); Debug.Assert(source.IsColumnVisible(srcX2)); Debug.Assert(source.IsColumnVisible(srcX3)); Debug.Assert(source.IsColumnVisible(srcX4)); #endif ColorBgra *p1 = src1 + srcX1; ColorBgra *p2 = src2 + srcX2; ColorBgra *p3 = src3 + srcX3; ColorBgra *p4 = src4 + srcX4; int r = (2 + p1->R + p2->R + p3->R + p4->R) >> 2; int g = (2 + p1->G + p2->G + p3->G + p4->G) >> 2; int b = (2 + p1->B + p2->B + p3->B + p4->B) >> 2; int a = (2 + p1->A + p2->A + p3->A + p4->A) >> 2; // Blend it over the checkerboard background int v = ((checkerX ^ checkerY) & 8) * 8 + 191; a = a + (a >> 7); int vmia = v * (256 - a); r = ((r * a) + vmia) >> 8; g = ((g * a) + vmia) >> 8; b = ((b * a) + vmia) >> 8; dstPtr->Bgra = (uint)b + ((uint)g << 8) + ((uint)r << 16) + 0xff000000; ++dstPtr; } } } }
private unsafe void DrawText(Surface dst, Font textFont, string text, Point pt, Size measuredSize, bool antiAliasing, Surface brush8x8) { Point pt2 = pt; Size measuredSize2 = measuredSize; int offset = (int)textFont.Height; pt.X -= offset; measuredSize.Width += 2 * offset; Rectangle dstRect = new Rectangle(pt, measuredSize); Rectangle dstRectClipped = Rectangle.Intersect(dstRect, ScratchSurface.Bounds); if (dstRectClipped.Width == 0 || dstRectClipped.Height == 0) { return; } // We only use the first 8,8 of brush using (RenderArgs renderArgs = new RenderArgs(this.ScratchSurface)) { renderArgs.Graphics.FillRectangle(Brushes.White, pt.X, pt.Y, measuredSize.Width, measuredSize.Height); if (measuredSize.Width > 0 && measuredSize.Height > 0) { using (Surface s2 = renderArgs.Surface.CreateWindow(dstRectClipped)) { using (RenderArgs renderArgs2 = new RenderArgs(s2)) { SystemLayer.Fonts.DrawText( renderArgs2.Graphics, this.font, text, new Point(dstRect.X - dstRectClipped.X + offset, dstRect.Y - dstRectClipped.Y), AppEnvironment.AntiAliasing, AppEnvironment.FontSmoothing); } } } // Mask out anything that isn't within the user's clip region (selected region) using (PdnRegion clip = Selection.CreateRegion()) { clip.Xor(renderArgs.Surface.Bounds); // invert clip.Intersect(new Rectangle(pt, measuredSize)); renderArgs.Graphics.FillRegion(Brushes.White, clip.GetRegionReadOnly()); } int skipX; if (pt.X < 0) { skipX = -pt.X; } else { skipX = 0; } int xEnd = Math.Min(dst.Width, pt.X + measuredSize.Width); bool blending = 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 = ScratchSurface.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; if (srcPtr->R == 255) // could use R, G, or B -- arbitrary choice { // 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; } } } } }