예제 #1
0
        public void DrawImage(INativeImage image, int x, int y)
        {
            x -= origin.X;
            y -= origin.Y;

            // todo: allow null?
            X11Image x11Image = (X11Image)image;

            XRenderPictureAttributes attr = new XRenderPictureAttributes();
            var tempPictureId             = LibXRender.XRenderCreatePicture(display, x11Image.PixmapId, pictFormatPtr, 0, ref attr);

            try
            {
                LibXRender.XRenderComposite
                (
                    display,
                    PictOp.PictOpOver,
                    tempPictureId,
                    0,
                    pictureId,
                    0, 0,
                    0, 0,
                    x, y,
                    (uint)x11Image.Width, (uint)x11Image.Height
                );
            }
            finally
            {
                LibXRender.XRenderFreePicture(display, tempPictureId);
            }
        }
예제 #2
0
        public static X11Graphics Create(IntPtr display)
        {
            int   defaultScreen     = LibX11.XDefaultScreen(display);
            ulong defaultRootWindow = LibX11.XDefaultRootWindow(display);

            //todo: is is safe to keep pictFormatPtr after reading it into XRenderPictFormat
            IntPtr pictFormatPtr = LibXRender.XRenderFindStandardFormat(display, StandardPictFormat.PictStandardARGB32);

            if (pictFormatPtr == IntPtr.Zero)
            {
                throw new InvalidOperationException("Display does not support 32-bit ARGB.");
            }

            XRenderPictFormat pictFormat = Marshal.PtrToStructure <XRenderPictFormat>(pictFormatPtr);

            int status = LibX11.XMatchVisualInfo
                         (
                display,
                defaultScreen,
                pictFormat.depth,
                VisualClass.TrueColor,
                out XVisualInfo visualInfo
                         );

            if (status == 0)
            {
                throw new InvalidOperationException($"TrueColor visual with depth {pictFormat.depth} does not exist.");
            }

            ulong colorMap = LibX11.XCreateColormap(display, defaultRootWindow, visualInfo.visual, CreateColormapOption.AllocNone);

            return(new X11Graphics(display, defaultScreen, defaultRootWindow, visualInfo.visual, colorMap, pictFormat, pictFormatPtr));
        }
예제 #3
0
        public void DrawString(Color color, FontConfig font, int x, int y, string text)
        {
            x -= origin.X;
            y -= origin.Y;

            var xftColorPtr = Marshal.AllocHGlobal(Marshal.SizeOf <XftColor>());

            try
            {
                XRenderColor xColor = new XRenderColor(color);
                LibXft.XftColorAllocValue(
                    display,
                    visual,
                    colormap,
                    ref xColor,
                    xftColorPtr
                    );

                try
                {
                    XftFontExt fontExt  = objectCache.GetXftFont(font);
                    var        fontInfo = Marshal.PtrToStructure <XftFont>(fontExt.MainFont);

                    int xOffset = DrawString(xftDraw, xftColorPtr, fontExt, x, y + fontInfo.ascent, text);

                    if (font.IsUnderline)
                    {
                        int lineHeight = Convert.ToInt32(Math.Max(font.Size / 10, 1));
                        LibXRender.XRenderFillRectangle(
                            display, PictOp.PictOpOver, pictureId, ref xColor,
                            x,
                            y + fontInfo.ascent + (fontInfo.descent - lineHeight) / 2,
                            (uint)xOffset,
                            (uint)lineHeight
                            );
                    }

                    if (font.IsStrikeout)
                    {
                        int lineHeight = Convert.ToInt32(Math.Max(font.Size / 20, 1));
                        LibXRender.XRenderFillRectangle
                        (
                            display, PictOp.PictOpOver, pictureId, ref xColor,
                            x,
                            y + fontInfo.ascent - (2 * fontInfo.ascent + 3 * lineHeight) / 6,
                            (uint)xOffset,
                            (uint)lineHeight
                        );
                    }
                }
                finally
                {
                    LibXft.XftColorFree(display, visual, colormap, xftColorPtr);
                }
            }
            finally
            {
                Marshal.FreeHGlobal(xftColorPtr);
            }
        }
예제 #4
0
        public void SetClipRectangle(int x, int y, int width, int height)
        {
            x -= origin.X;
            y -= origin.Y;

            clipRectangles = new[] { new XRectangle(x, y, width, height) };
            LibXRender.XRenderSetPictureClipRectangles(display, pictureId, 0, 0, clipRectangles, 1);
            LibXft.XftDrawSetClipRectangles(xftDraw, 0, 0, clipRectangles, 1);
        }
예제 #5
0
        private void DrawPathWithXRenderCompositeTriStrip(Color color, int width, Point[] points)
        {
            if (width == 0)
            {
                width = 1;
            }

            XRenderColor xColor = new XRenderColor(color);
            // todo: cache brush
            ulong brush = LibXRender.XRenderCreateSolidFill(display, ref xColor);

            try
            {
                XPointFixed[] stripPoints = new XPointFixed[(points.Length - 1) * 3 + 1];
                for (int i = 1, t = 0, m = 1; i < points.Length; i++, m = -m)
                {
                    Point p1 = points[i - 1];
                    Point p2 = points[i];

                    p1.Offset(-origin.X, -origin.Y);
                    p2.Offset(-origin.X, -origin.Y);

                    int    dx  = p2.X - p1.X;
                    int    dy  = p2.Y - p1.Y;
                    double len = Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2));
                    // todo: handle 0 points and zero-length segments
                    int ox = Convert.ToInt32(-dy / len * 32768 * width) * m;
                    int oy = Convert.ToInt32(dx / len * 32768 * width) * m;

                    if (i == 1)
                    {
                        // todo: handle separately without if
                        stripPoints[t++] = new XPointFixed {
                            x = (p1.X << 16) + ox, y = (p1.Y << 16) + oy
                        };
                    }

                    stripPoints[t++] = new XPointFixed {
                        x = (p1.X << 16) - ox, y = (p1.Y << 16) - oy
                    };
                    stripPoints[t++] = new XPointFixed {
                        x = (p2.X << 16) + ox, y = (p2.Y << 16) + oy
                    };
                    stripPoints[t++] = new XPointFixed {
                        x = (p2.X << 16) - ox, y = (p2.Y << 16) - oy
                    };
                }

                LibXRender.XRenderCompositeTriStrip(display, PictOp.PictOpOver, brush, pictureId, pictFormatPtr, 0, 0, stripPoints, stripPoints.Length);
            }
            finally
            {
                LibXRender.XRenderFreePicture(display, brush);
            }
        }
예제 #6
0
        private void DrawPathWithXRenderCompositeDoublePoly(Color color, int width, Point[] points)
        {
            if (width == 0)
            {
                width = 1;
            }

            XRenderColor xColor = new XRenderColor(color);
            // todo: cache brush
            ulong brush = LibXRender.XRenderCreateSolidFill(display, ref xColor);

            try
            {
                XPointDouble[] polyPoints = new XPointDouble[points.Length * 2];
                for (int i = 1, t = polyPoints.Length - 2; i < points.Length; i++, t--)
                {
                    Point p1 = points[i - 1];
                    Point p2 = points[i];

                    p1.Offset(-origin.X, -origin.Y);
                    p2.Offset(-origin.X, -origin.Y);

                    int    dx  = p2.X - p1.X;
                    int    dy  = p2.Y - p1.Y;
                    double len = Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2));
                    double ox  = -dy / len * width / 2;
                    double oy  = dx / len * width / 2;

                    polyPoints[i] = new XPointDouble {
                        x = points[i].X + ox, y = points[i].Y + oy
                    };
                    polyPoints[t] = new XPointDouble {
                        x = points[i].X - ox, y = points[i].Y - oy
                    };

                    if (i == 1)
                    {
                        // todo: handle separately without if
                        polyPoints[0] = new XPointDouble {
                            x = points[0].X + ox, y = points[0].Y + oy
                        };
                        polyPoints[polyPoints.Length - 1] = new XPointDouble {
                            x = points[0].X - ox, y = points[0].Y - oy
                        };
                    }
                }

                LibXRender.XRenderCompositeDoublePoly(display, PictOp.PictOpOver, brush, pictureId, pictFormatPtr, 0, 0, 0, 0, polyPoints, polyPoints.Length, 1);
            }
            finally
            {
                LibXRender.XRenderFreePicture(display, brush);
            }
        }
예제 #7
0
        public static X11Canvas CreateForDrawable(
            IntPtr display,
            int screenNum,
            X11ObjectCache objectCache,
            IntPtr visual,
            ulong colormap,
            IntPtr pictFormatPtr,
            ulong drawableId
            )
        {
            const XRenderPictureAttributeMask attrMask =
                XRenderPictureAttributeMask.CPPolyEdge |
                XRenderPictureAttributeMask.CPPolyMode;

            XRenderPictureAttributes attr = new XRenderPictureAttributes
            {
                poly_edge = XRenderPolyEdge.Smooth,
                poly_mode = XRenderPolyMode.Imprecise
            };

            ulong pictureId = LibXRender.XRenderCreatePicture
                              (
                display,
                drawableId,
                pictFormatPtr,
                attrMask,
                ref attr
                              );

            IntPtr    xftDraw = IntPtr.Zero;
            X11Canvas canvas  = null;

            try
            {
                xftDraw = LibXft.XftDrawCreate(display, drawableId, visual, colormap);
                canvas  = new X11Canvas(display, screenNum, objectCache, visual, colormap, pictFormatPtr, drawableId, pictureId, xftDraw);
                xftDraw = IntPtr.Zero;
            }
            finally
            {
                if (canvas == null)
                {
                    if (xftDraw != IntPtr.Zero)
                    {
                        LibXft.XftDrawDestroy(xftDraw);
                    }

                    LibXRender.XRenderFreePicture(display, pictureId);
                }
            }

            return(canvas);
        }
예제 #8
0
        public void FillRectangle(Color color, int x, int y, int width, int height)
        {
            // todo: <= 0 instead?
            if (width < 0 || height < 0)
            {
                return;
            }

            x -= origin.X;
            y -= origin.Y;

            XRenderColor xColor = new XRenderColor(color);

            LibXRender.XRenderFillRectangle(display, PictOp.PictOpOver, pictureId, ref xColor, x, y, (uint)width, (uint)height);
        }
예제 #9
0
 public void Dispose()
 {
     LibXft.XftDrawDestroy(xftDraw);
     LibXRender.XRenderFreePicture(display, pictureId);
 }