Example #1
0
        public unsafe void Render(Cairo.ImageSurface dst, Gdk.Point offset)
        {
            if (cr.ScaleFactor > new ScaleFactor (1, 2))
                return;

            int[] d2SLookupX = cr.Dst2SrcLookupX;
            int[] d2SLookupY = cr.Dst2SrcLookupY;
            int[] s2DLookupX = cr.Src2DstLookupX;
            int[] s2DLookupY = cr.Src2DstLookupY;

            ColorBgra[] blackAndWhite = new ColorBgra[2] { ColorBgra.White, ColorBgra.Black };

            // draw horizontal lines
            int dstHeight = dst.Height;
            int dstWidth = dst.Width;
            int dstStride = dst.Stride;
            int sTop = d2SLookupY[offset.Y];
            int sBottom = d2SLookupY[offset.Y + dstHeight];

            for (int srcY = sTop; srcY <= sBottom; ++srcY) {
                int dstY = s2DLookupY[srcY];
                int dstRow = dstY - offset.Y;

                if (dstRow >= 0 && dstRow < dstHeight) {
                    ColorBgra* dstRowPtr = dst.GetRowAddressUnchecked (dstRow);
                    ColorBgra* dstRowEndPtr = dstRowPtr + dstWidth;

                    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 + dstWidth];

            for (int srcX = sLeft; srcX <= sRight; ++srcX) {
                int dstX = s2DLookupX[srcX];
                int dstCol = dstX - offset.X;

                if (dstCol >= 0 && dstCol < dstWidth) {
                    byte* dstColPtr = (byte*)dst.GetPointAddress (dstCol, 0);
                    byte* dstColEndPtr = dstColPtr + dstStride * dstHeight;

                    dstColPtr += (offset.Y & 1) * dstStride;

                    while (dstColPtr < dstColEndPtr) {
                        *((ColorBgra*)dstColPtr) = ColorBgra.Black;
                        dstColPtr += 2 * dstStride;
                    }
                }
            }
        }
Example #2
0
        private unsafe void RenderZoomOut(List<Layer> layers, Cairo.ImageSurface dst, Gdk.Point offset, Gdk.Size destinationSize)
        {
            // The first layer should be blended with the transparent checkerboard
            var checker = true;
            CheckerBoardOperation checker_op = null;

            for (int i = 0; i < layers.Count; i++) {
                var layer = layers[i];

                // If we're in LivePreview, substitute current layer with the preview layer
                if (layer == PintaCore.Layers.CurrentLayer && PintaCore.LivePreview.IsEnabled)
                    layer = CreateLivePreviewLayer (layer);

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

                var src = layer.Surface;

                // Get the blend mode for this layer and opacity
                var blend_op = UserBlendOps.GetBlendOp (layer.BlendMode, layer.Opacity);

                if (checker)
                    checker_op = new CheckerBoardOperation (layer.Opacity);

                const int fpShift = 12;
                const int fpFactor = (1 << fpShift);

                Gdk.Size sourceSize = src.GetBounds ().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;

                ColorBgra* src_ptr = (ColorBgra*)src.DataPtr;
                ColorBgra* dst_ptr = (ColorBgra*)dst.DataPtr;
                int src_width = src.Width;
                int dst_width = dst.Width;

                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

                    ColorBgra* src1 = src.GetRowAddressUnchecked (src_ptr, src_width, srcY1);
                    ColorBgra* src2 = src.GetRowAddressUnchecked (src_ptr, src_width, srcY2);
                    ColorBgra* src3 = src.GetRowAddressUnchecked (src_ptr, src_width, srcY3);
                    ColorBgra* src4 = src.GetRowAddressUnchecked (src_ptr, src_width, srcY4);
                    ColorBgra* dstPtr = dst.GetRowAddressUnchecked (dst_ptr, dst_width, 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
                        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
                        if (checker)
                            *dstPtr = checker_op.Apply (ColorBgra.FromUInt32 ((uint)b + ((uint)g << 8) + ((uint)r << 16) + ((uint)a << 24)), checkerX, checkerY);
                        else
                            *dstPtr = blend_op.Apply (*dstPtr, ColorBgra.FromUInt32 ((uint)b + ((uint)g << 8) + ((uint)r << 16) + ((uint)a << 24)));

                        ++dstPtr;
                    }
                }

                // Only checker the first layer
                checker = false;
            }
        }
Example #3
0
        private unsafe void RenderZoomIn(List<Layer> layers, Cairo.ImageSurface dst, Gdk.Point offset)
        {
            // The first layer should be blended with the transparent checkerboard
            var checker = true;
            CheckerBoardOperation checker_op = null;

            for (int i = 0; i < layers.Count; i++) {
                var layer = layers[i];

                // If we're in LivePreview, substitute current layer with the preview layer
                if (layer == PintaCore.Layers.CurrentLayer && PintaCore.LivePreview.IsEnabled)
                    layer = CreateLivePreviewLayer (layer);

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

                var src = layer.Surface;

                // Get the blend mode for this layer and opacity
                var blend_op = UserBlendOps.GetBlendOp (layer.BlendMode, layer.Opacity);

                if (checker)
                    checker_op = new CheckerBoardOperation (layer.Opacity);

                ColorBgra* src_ptr = (ColorBgra*)src.DataPtr;
                ColorBgra* dst_ptr = (ColorBgra*)dst.DataPtr;

                int src_width = src.Width;
                int dst_width = dst.Width;
                int dst_height = dst.Height;

                if (!generated) {
                    d2sLookupX = CreateLookupX (src_width, destination_size.Width, scale_factor);
                    d2sLookupY = CreateLookupY (src.Height, destination_size.Height, scale_factor);
                    s2dLookupX = CreateS2DLookupX (src_width, destination_size.Width, scale_factor);
                    s2dLookupY = CreateS2DLookupY (src.Height, destination_size.Height, scale_factor);

                    generated = true;
                }

                for (int dstRow = 0; dstRow < dst_height; ++dstRow) {
                    int nnY = dstRow + offset.Y;
                    int srcY = d2sLookupY[nnY];

                    ColorBgra* dstPtr = dst.GetRowAddressUnchecked (dst_ptr, dst_width, dstRow);
                    ColorBgra* srcRow = src.GetRowAddressUnchecked (src_ptr, src_width, srcY);

                    for (int dstCol = 0; dstCol < dst_width; ++dstCol) {
                        int nnX = dstCol + offset.X;
                        int srcX = d2sLookupX[nnX];

                        // Blend it over the checkerboard background
                        if (checker)
                            *dstPtr = checker_op.Apply (*(srcRow + srcX), dstCol + offset.X, dstRow + offset.Y);
                        else
                            *dstPtr = blend_op.Apply (*dstPtr, *(srcRow + srcX));

                        ++dstPtr;
                    }
                }

                // Only checker the first layer
                checker = false;
            }

            // If we are at least 200% and grid is requested, draw it
            if (PintaCore.Actions.View.PixelGrid.Active && scale_factor.Ratio <= 0.5d)
                RenderPixelGrid (dst, offset);
        }
Example #4
0
        private unsafe void RenderPixelGrid(Cairo.ImageSurface dst, Gdk.Point offset)
        {
            // Draw horizontal lines
            var dst_ptr = (ColorBgra*)dst.DataPtr;
            int dstHeight = dst.Height;
            int dstWidth = dst.Width;
            int dstStride = dst.Stride;
            int sTop = d2sLookupY[offset.Y];
            int sBottom = d2sLookupY[offset.Y + dstHeight];

            for (int srcY = sTop; srcY <= sBottom; ++srcY) {
                int dstY = s2dLookupY[srcY];
                int dstRow = dstY - offset.Y;

                if (dstRow >= 0 && dstRow < dstHeight) {
                    ColorBgra* dstRowPtr = dst.GetRowAddressUnchecked (dst_ptr, dstWidth, dstRow);
                    ColorBgra* dstRowEndPtr = dstRowPtr + dstWidth;

                    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 + dstWidth];

            for (int srcX = sLeft; srcX <= sRight; ++srcX) {
                int dstX = s2dLookupX[srcX];
                int dstCol = dstX - offset.X;

                if (dstCol >= 0 && dstCol < dstWidth) {
                    byte* dstColPtr = (byte*)dst.GetPointAddress (dstCol, 0);
                    byte* dstColEndPtr = dstColPtr + dstStride * dstHeight;

                    dstColPtr += (offset.Y & 1) * dstStride;

                    while (dstColPtr < dstColEndPtr) {
                        *((ColorBgra*)dstColPtr) = ColorBgra.Black;
                        dstColPtr += 2 * dstStride;
                    }
                }
            }
        }
Example #5
0
        private unsafe void RenderOneToOne(List<Layer> layers, Cairo.ImageSurface dst, Gdk.Point offset)
        {
            // The first layer should be blended with the transparent checkerboard
            var checker = true;
            CheckerBoardOperation checker_op = null;

            for (int i = 0; i < layers.Count; i++) {
                var layer = layers[i];

                // If we're in LivePreview, substitute current layer with the preview layer
                if (layer == PintaCore.Layers.CurrentLayer && PintaCore.LivePreview.IsEnabled)
                    layer = CreateLivePreviewLayer (layer);

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

                var src = layer.Surface;

                // Get the blend mode for this layer and opacity
                var blend_op = UserBlendOps.GetBlendOp (layer.BlendMode, layer.Opacity);

                if (checker)
                    checker_op = new CheckerBoardOperation (layer.Opacity);

                // Figure out where our source and destination intersect
                var srcRect = new Gdk.Rectangle (offset, dst.GetBounds ().Size);
                srcRect.Intersect (src.GetBounds ());

                // Get pointers to our surfaces
                var src_ptr = (ColorBgra*)src.DataPtr;
                var dst_ptr = (ColorBgra*)dst.DataPtr;

                // Cache widths
                int src_width = src.Width;
                int dst_width = dst.Width;

                for (int dstRow = 0; dstRow < srcRect.Height; ++dstRow) {
                    ColorBgra* dstRowPtr = dst.GetRowAddressUnchecked (dst_ptr, dst_width, dstRow);
                    ColorBgra* srcRowPtr = src.GetPointAddressUnchecked (src_ptr, src_width, offset.X, dstRow + offset.Y);

                    int dstCol = offset.X;
                    int dstColEnd = offset.X + srcRect.Width;
                    int checkerY = dstRow + offset.Y;

                    while (dstCol < dstColEnd) {
                        // Blend it over the checkerboard background
                        if (checker)
                            *dstRowPtr = checker_op.Apply (*srcRowPtr, dstCol, checkerY);
                        else
                            *dstRowPtr = blend_op.Apply (*dstRowPtr, *srcRowPtr);

                        ++dstRowPtr;
                        ++srcRowPtr;
                        ++dstCol;
                    }
                }

                // Only checker the first layer
                checker = false;
            }
        }
Example #6
0
        private unsafe void RenderZoomOut(Cairo.ImageSurface src, Cairo.ImageSurface dst, Gdk.Point offset, Gdk.Size destinationSize, bool checker)
        {
            const int fpShift = 12;
            const int fpFactor = (1 << fpShift);

            Gdk.Size sourceSize = src.GetBounds ().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;

            ColorBgra* src_ptr = (ColorBgra*)src.DataPtr;
            ColorBgra* dst_ptr = (ColorBgra*)dst.DataPtr;
            int src_width = src.Width;
            int dst_width = dst.Width;

            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

                ColorBgra* src1 = src.GetRowAddressUnchecked (src_ptr, src_width, srcY1);
                ColorBgra* src2 = src.GetRowAddressUnchecked (src_ptr, src_width, srcY2);
                ColorBgra* src3 = src.GetRowAddressUnchecked (src_ptr, src_width, srcY3);
                ColorBgra* src4 = src.GetRowAddressUnchecked (src_ptr, src_width, srcY4);
                ColorBgra* dstPtr = dst.GetRowAddressUnchecked (dst_ptr, dst_width, 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
                    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;

                    if (checker) {
                        // 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;
                    } else {
                        dstPtr->Bgra = (uint)b + ((uint)g << 8) + ((uint)r << 16) + ((uint)a << 24);
                    }

                    ++dstPtr;
                }
            }
        }
Example #7
0
        private unsafe void RenderZoomIn(Cairo.ImageSurface src, Cairo.ImageSurface dst, Gdk.Point offset, bool checker)
        {
            ColorBgra* src_ptr = (ColorBgra*)src.DataPtr;
            ColorBgra* dst_ptr = (ColorBgra*)dst.DataPtr;

            int src_width = src.Width;
            int dst_width = dst.Width;
            int dst_height = dst.Height;

            if (!generated) {
                d2sLookupX = CreateLookupX (src_width, destination_size.Width, scale_factor);
                d2sLookupY = CreateLookupY (src.Height, destination_size.Height, scale_factor);
                s2dLookupX = CreateS2DLookupX (src_width, destination_size.Width, scale_factor);
                s2dLookupY = CreateS2DLookupY (src.Height, destination_size.Height, scale_factor);

                generated = true;
            }

            for (int dstRow = 0; dstRow < dst_height; ++dstRow) {
                int nnY = dstRow + offset.Y;
                int srcY = d2sLookupY[nnY];

                ColorBgra* dstPtr = dst.GetRowAddressUnchecked (dst_ptr, dst_width, dstRow);
                ColorBgra* srcRow = src.GetRowAddressUnchecked (src_ptr, src_width, srcY);

                for (int dstCol = 0; dstCol < dst_width; ++dstCol) {
                    int nnX = dstCol + offset.X;
                    int srcX = d2sLookupX[nnX];

                    if (checker) {
                        ColorBgra src2 = *(srcRow + srcX);
                        int b = src2.B;
                        int g = src2.G;
                        int r = src2.R;
                        int a = src2.A;

                        // Blend it over the checkerboard background
                        int v = (((dstCol + offset.X) ^ (dstRow + offset.Y)) & 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) + ((uint)255 << 24);
                    } else {
                        *dstPtr = *(srcRow + srcX);
                    }

                    ++dstPtr;
                }
            }
        }
Example #8
0
        private unsafe void RenderOneToOne(Cairo.ImageSurface src, Cairo.ImageSurface dst, Gdk.Point offset, bool checker)
        {
            Gdk.Rectangle srcRect = new Gdk.Rectangle (offset, dst.GetBounds ().Size);
            srcRect.Intersect (src.GetBounds ());

            ColorBgra* src_ptr = (ColorBgra*)src.DataPtr;
            ColorBgra* dst_ptr = (ColorBgra*)dst.DataPtr;

            int src_width = src.Width;
            int dst_width = dst.Width;
            int dst_height = dst.Height;

            for (int dstRow = 0; dstRow < srcRect.Height; ++dstRow) {
                ColorBgra* dstRowPtr = dst.GetRowAddressUnchecked (dst_ptr, dst_width, dstRow);
                ColorBgra* srcRowPtr = src.GetPointAddressUnchecked (src_ptr, src_width, offset.X, dstRow + offset.Y);

                int dstCol = offset.X;
                int dstColEnd = offset.X + srcRect.Width;
                int checkerY = dstRow + offset.Y;

                while (dstCol < dstColEnd) {
                    // Blend it over the checkerboard background
                    if (checker) {
                        int b = srcRowPtr->B;
                        int g = srcRowPtr->G;
                        int r = srcRowPtr->R;
                        int a = srcRowPtr->A;

                        int v = (((dstCol ^ checkerY) & 8) << 3) + 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;

                        dstRowPtr->Bgra = (uint)b + ((uint)g << 8) + ((uint)r << 16) + ((uint)255 << 24);
                    } else {
                        *dstRowPtr = *srcRowPtr;
                    }

                    ++dstRowPtr;
                    ++srcRowPtr;
                    ++dstCol;
                }
            }
        }
Example #9
0
        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;
                    }
                }
                //}

            }
        }
Example #10
0
		public void Apply (Cairo.ImageSurface dst, Cairo.ImageSurface lhs, Cairo.ImageSurface rhs)
		{
			if (dst.GetSize () != lhs.GetSize ()) {
				throw new ArgumentException ("dst.Size != lhs.Size");
			}

			if (lhs.GetSize () != rhs.GetSize ()) {
				throw new ArgumentException ("lhs.Size != rhs.Size");
			}

			unsafe {
				for (int y = 0; y < dst.Height; ++y) {
					ColorBgra* dstPtr = dst.GetRowAddressUnchecked (y);
					ColorBgra* lhsPtr = lhs.GetRowAddressUnchecked (y);
					ColorBgra* rhsPtr = rhs.GetRowAddressUnchecked (y);

					Apply (dstPtr, lhsPtr, rhsPtr, dst.Width);
				}
			}
		}
Example #11
0
		public void Apply (Cairo.ImageSurface dst, Cairo.ImageSurface src)
		{
			if (dst.GetSize () != src.GetSize ()) {
				throw new ArgumentException ("dst.Size != src.Size");
			}

			unsafe {
				for (int y = 0; y < dst.Height; ++y) {
					ColorBgra* dstPtr = dst.GetRowAddressUnchecked (y);
					ColorBgra* srcPtr = src.GetRowAddressUnchecked (y);
					Apply (dstPtr, srcPtr, dst.Width);
				}
			}
		}
Example #12
0
        private unsafe void CopyScaledZoomOut (Cairo.ImageSurface src, Cairo.ImageSurface dst, Rectangle roi)
        {
            // Tell Cairo we need the latest raw data
            dst.Flush ();

            const int fpShift = 12;
            const int fpFactor = (1 << fpShift);

            var source_size = src.GetBounds ().Size;

            // Find destination bounds
            var dst_left = (int)(((long)roi.X * fpFactor * (long)source_size.Width) / (long)destination_size.Width);
            var dst_top = (int)(((long)roi.Y * fpFactor * (long)source_size.Height) / (long)destination_size.Height);
            var dst_right = (int)(((long)(roi.X + dst.Width) * fpFactor * (long)source_size.Width) / (long)destination_size.Width);
            var dst_bottom = (int)(((long)(roi.Y + dst.Height) * fpFactor * (long)source_size.Height) / (long)destination_size.Height);
            var dx = (dst_right - dst_left) / dst.Width;
            var dy = (dst_bottom - dst_top) / dst.Height;

            // Cache pointers to surface raw data and sizes
            var src_ptr = (ColorBgra*)src.DataPtr;
            var dst_ptr = (ColorBgra*)dst.DataPtr;
            var src_width = src.Width;
            var dst_width = dst.Width;
            var dst_height = dst.Height;

            for (int dstRow = 0, fDstY = dst_top; dstRow < dst_height && fDstY < dst_bottom; ++dstRow, fDstY += dy) {
                var srcY1 = fDstY >> fpShift;                            // y
                var srcY2 = (fDstY + (dy >> 2)) >> fpShift;              // y + 0.25
                var srcY3 = (fDstY + (dy >> 1)) >> fpShift;              // y + 0.50
                var srcY4 = (fDstY + (dy >> 1) + (dy >> 2)) >> fpShift;  // y + 0.75

                var src1 = src.GetRowAddressUnchecked (src_ptr, src_width, srcY1);
                var src2 = src.GetRowAddressUnchecked (src_ptr, src_width, srcY2);
                var src3 = src.GetRowAddressUnchecked (src_ptr, src_width, srcY3);
                var src4 = src.GetRowAddressUnchecked (src_ptr, src_width, srcY4);
                var dstPtr = dst.GetRowAddressUnchecked (dst_ptr, dst_width, dstRow);

                var checkerY = dstRow + roi.Y;
                var checkerX = roi.X;
                var maxCheckerX = checkerX + dst.Width;

                for (var fDstX = dst_left; checkerX < maxCheckerX && fDstX < dst_right; ++checkerX, fDstX += dx) {
                    var srcX1 = (fDstX + (dx >> 2)) >> fpShift;             // x + 0.25
                    var srcX2 = (fDstX + (dx >> 1) + (dx >> 2)) >> fpShift; // x + 0.75
                    var srcX3 = fDstX >> fpShift;                           // x
                    var srcX4 = (fDstX + (dx >> 1)) >> fpShift;             // x + 0.50

                    var p1 = src1 + srcX1;
                    var p2 = src2 + srcX2;
                    var p3 = src3 + srcX3;
                    var p4 = src4 + srcX4;

                    var r = (2 + p1->R + p2->R + p3->R + p4->R) >> 2;
                    var g = (2 + p1->G + p2->G + p3->G + p4->G) >> 2;
                    var b = (2 + p1->B + p2->B + p3->B + p4->B) >> 2;
                    var a = (2 + p1->A + p2->A + p3->A + p4->A) >> 2;

                    // Copy color to destination
                    *dstPtr++ = ColorBgra.FromUInt32 ((uint)b + ((uint)g << 8) + ((uint)r << 16) + ((uint)a << 24));
                }
            }

            // Tell Cairo we changed the raw data
            dst.MarkDirty ();
        }
Example #13
0
        private unsafe void CopyScaledZoomIn (Cairo.ImageSurface src, Cairo.ImageSurface dst, Rectangle roi)
        {
            // Tell Cairo we need the latest raw data
            dst.Flush ();

            EnsureLookupTablesCreated ();

            // Cache pointers to surface raw data
            var src_ptr = (ColorBgra*)src.DataPtr;
            var dst_ptr = (ColorBgra*)dst.DataPtr;

            // Cache surface sizes
            var src_width = src.Width;
            var dst_width = dst.Width;
            var dst_height = dst.Height;

            for (var dst_row = 0; dst_row < dst_height; ++dst_row) {
                // For each dest row, look up the src row to copy from
                var nnY = dst_row + roi.Y;
                var srcY = d2sLookupY[nnY];

                // Get pointers to src and dest rows
                var dst_row_ptr = dst.GetRowAddressUnchecked (dst_ptr, dst_width, dst_row);
                var src_row_ptr = src.GetRowAddressUnchecked (src_ptr, src_width, srcY);

                for (var dstCol = 0; dstCol < dst_width; ++dstCol) {
                    // Look up the src column to copy from
                    var nnX = dstCol + roi.X;
                    var srcX = d2sLookupX[nnX];

                    // Copy source to destination
                    *dst_row_ptr++ = *(src_row_ptr + srcX);
                }
            }

            // Tell Cairo we changed the raw data
            dst.MarkDirty ();
        }