/// <summary> Draw the image in the indicated window, using the indicated graphics context. </summary>
        /// <param name="window"> The window to draw the pitmap on. <see cref="System.IntPtr"/> </param>
        /// <param name="gc"> The crapchics context to use for drawing. <see cref="System.IntPtr"/> </param>
        /// <param name="destX"> The x coordinate, which is relative to the origin of the window and is the coordinate of the subimage. <see cref="TInt"/> </param>
        /// <param name="destY"> The y coordinate, which is relative to the origin of the window and is the coordinate of the subimage. <see cref="TInt"/> </param>
        public void Draw(IntPtr window, IntPtr gc, TInt dstX, TInt dstY)
        {
            // Possible optimization: Keep the graphicGc between the exposure events.
            // Problem: Every graphic allocates a graphics context (limited server resource).
            if (_transpXImage != IntPtr.Zero)
            {
                // Prepare the clip mask (for transparency) that must be a XPixmap.
                if (_transpXPixmap == IntPtr.Zero)
                {
                    // Server side storage.
                    _transpXPixmap = X11lib.XCreatePixmap(_display, window, (TUint)_width, (TUint)_height, (TUint)_clipDepth);
                    IntPtr maskGc = X11lib.XCreateGC(_display, _transpXPixmap, (TUlong)0, IntPtr.Zero);
                    if (maskGc != IntPtr.Zero)
                    {
                        X11lib.XPutImage(_display, _transpXPixmap, maskGc, _transpXImage, (TInt)0, (TInt)0, (TInt)0, (TInt)0, (TUint)_width, (TUint)_height);
                        // Console.WriteLine (CLASS_NAME + "::Draw () Delete transparency mask image GC.");
                        X11lib.XFreeGC(_display, maskGc);
                        maskGc = IntPtr.Zero;
                    }
                    else
                    {
                        Console.WriteLine(CLASS_NAME + "::Draw () ERROR: Can not create graphics context for mask pixmap.");
                    }
                }

                // Prepare the clipping graphics context.
                IntPtr graphicGc = X11lib.XCreateGC(_display, window, (TUlong)0, IntPtr.Zero);
                if (graphicGc != IntPtr.Zero)
                {
                    X11lib.XSetClipMask(_display, graphicGc, _transpXPixmap);
                    X11lib.XSetClipOrigin(_display, graphicGc, dstX, dstY);

                    // Draw graphic using the clipping graphics context.
                    X11lib.XPutImage(_display, window, graphicGc, _graphicXImage, (TInt)0, (TInt)0, (TInt)dstX, (TInt)dstY, (TUint)_width, (TUint)_height);

                    // Restore previous behaviour and clean up.
                    X11lib.XSetClipMask(_display, graphicGc, IntPtr.Zero);
                    X11lib.XSetClipOrigin(_display, graphicGc, (TInt)0, (TInt)0);
                    // Console.WriteLine (CLASS_NAME + "::Draw () Delete clipping image GC.");
                    X11lib.XFreeGC(_display, graphicGc);
                    graphicGc = IntPtr.Zero;
                }
                else
                {
                    Console.WriteLine(CLASS_NAME + "::Draw () ERROR: Can not create graphics context for transparency application.");
                }
            }
            else
            {
                X11lib.XPutImage(_display, window, gc, _graphicXImage, 0, 0, dstX, dstY, (TUint)_width, (TUint)_height);
            }
        }
        /// <summary> Provide a bitmap, containing the transparency mask, that can be used independent from this class. </summary>
        /// <param name="display"> The display pointer, that specifies the connection to the X server. <see cref="System.IntPtr"/> </param>
        /// <param name="window"> The target window to create the pixmap for. <see cref="IntPtr"/> </param>
        /// <returns> The (server side) pixmap (that must be feed) on success, or IntPtr.Zero otherwise. <see cref="IntPtr"/> </returns>
        public IntPtr CreateIndependentMaskPixmap(IntPtr display, IntPtr window)
        {
            if (_transpXImage == IntPtr.Zero)
            {
                return(IntPtr.Zero);
            }

            IntPtr pixmap   = X11lib.XCreatePixmap(display, window, (TUint)_width, (TUint)_height, (TUint)_clipDepth);
            IntPtr pixmapGc = X11lib.XCreateGC(display, pixmap, (TUlong)0, IntPtr.Zero);

            if (pixmapGc != IntPtr.Zero)
            {
                X11lib.XPutImage(display, pixmap, pixmapGc, _transpXImage, (TInt)0, (TInt)0, (TInt)0, (TInt)0, (TUint)_width, (TUint)_height);
                // Console.WriteLine (CLASS_NAME + "::CreateIndependentMaskPixmap () Delete transparency mask image GC.");
                X11lib.XFreeGC(display, pixmapGc);
                pixmapGc = IntPtr.Zero;
            }
            else
            {
                Console.WriteLine(CLASS_NAME + "::CreateIndependentMaskPixmap () ERROR: Can not create graphics context for mask pixmap.");
            }
            return(pixmap);
        }
Example #3
0
        // ###############################################################################
        // ### M E T H O D S
        // ###############################################################################

        #region Methods

        /// <summary>Prepare a font or fonteset for utilization with Xrw.</summary>
        /// <param name="fontSpecification">The font specification, that identifies a font/fontset.<see cref="System.String"/></param>
        /// <param name="x11display">The display pointer, that specifies the connection to the X server.<see cref="IntPtr"/></param>
        /// <param name="useFontset">The flag defining whether to use a fontset or a single font.<see cref="System.Boolean"/></param>
        /// <param name="fontData">The resulting font data on success, or null otherwise.<see cref="X11.X11FontData"/></param>
        /// <returns>True on success, or false otherwise.<see cref="System.Boolean"/></returns>
        public static bool PrepareFont(string fontSpecification, IntPtr x11display, bool useFontset, ref X11.X11FontData fontData)
        {
            fontData = null;

            foreach (KeyValuePair <FontDataKey, X11FontData> loadedFont in _loadedFonts)
            {
                if (loadedFont.Key.FontSpecification == fontSpecification && loadedFont.Key.X11Display == x11display && loadedFont.Key.UseFontset)
                {
                    fontData = loadedFont.Value;
                    return(true);
                }
            }

            FontDataKey key = new FontDataKey(fontSpecification, x11display, useFontset);

            if (useFontset)
            {
                IntPtr  missingCharsetList;
                TInt    missingCharsetCount;
                X11.XID fontsetResourceId = X11lib.XCreateFontSet(x11display, fontSpecification, out missingCharsetList,
                                                                  out missingCharsetCount, IntPtr.Zero);
                // Check whether directly matching fontset has been loaded, and - if not - load the most similar fontset (fuzzy).
                int    fuzzyFactor            = 0;
                string fuzzyFontSpecification = (fontsetResourceId == (X11.XID) 0 ? fontSpecification : null);
                while (fontsetResourceId == (X11.XID) 0 && fuzzyFactor < 3)
                {
                    string lastFuzzyFontSpecification = fuzzyFontSpecification;
                    if (fuzzyFactor == 0)
                    {
                        fuzzyFontSpecification = X11FontData.ModifyFontSpecificationStretch(fuzzyFontSpecification, "*");
                    }
                    if (fuzzyFactor == 1)
                    {
                        fuzzyFontSpecification = X11FontData.ModifyFontSpecificationWieght(fuzzyFontSpecification, "*");
                    }
                    if (fuzzyFactor == 2)
                    {
                        fuzzyFontSpecification = X11FontData.ModifyFontSpecificationSlant(fuzzyFontSpecification, "*");
                    }

                    fuzzyFactor++;
                    // Safe time if no change has been made.
                    if (lastFuzzyFontSpecification == fuzzyFontSpecification)
                    {
                        continue;
                    }

                    if (!string.IsNullOrEmpty(lastFuzzyFontSpecification) && lastFuzzyFontSpecification.Trim() != "")
                    {
                        fontsetResourceId = X11lib.XCreateFontSet(x11display, fuzzyFontSpecification, out missingCharsetList,
                                                                  out missingCharsetCount, IntPtr.Zero);
                        if (fontsetResourceId != (X11.XID) 0)
                        {
                            SimpleLog.LogLine(TraceEventType.Information, CLASS_NAME +
                                              "::PrepareFont () Fuzzy load fontset with specification '" + fuzzyFontSpecification + "' " +
                                              "instead of '" + fontSpecification + "' succeeded.");
                        }
                    }
                }

                // Check whether directly matching or most similar fontset has been loaded, and - if not - load a fallback fontset.
                string extFontSpecification = null;
                if (fontsetResourceId == (X11.XID) 0)
                {
                    // Let the font server guess a fallback fontset.
                    if (!string.IsNullOrEmpty(fontSpecification) && fontSpecification.Trim() != "" && !fontSpecification.Trim().EndsWith(",*"))
                    {
                        extFontSpecification = fontSpecification + ",*";

                        SimpleLog.LogLine(TraceEventType.Warning, CLASS_NAME +
                                          "::PrepareFont () Can not load a fontset with specification '" + fontSpecification + "'.");
                        SimpleLog.LogLine(TraceEventType.Information, CLASS_NAME +
                                          "::PrepareFont () Retry to load a fontset with specification '" + extFontSpecification + "'.");

                        fontsetResourceId = X11lib.XCreateFontSet(x11display, extFontSpecification, out missingCharsetList,
                                                                  out missingCharsetCount, IntPtr.Zero);
                    }
                    // The font specification already includs a joker to guess a fallback fontset.
                    else
                    {
                        SimpleLog.LogLine(TraceEventType.Error, CLASS_NAME +
                                          "::PrepareFont () Can not load a fontset with specification '" + fontSpecification + "'.");

                        // No success at all - even with a guess of a fallback fontset!
                        return(false);
                    }
                }

                // Check whether matching fontset has been loaded.
                if (fontsetResourceId == (X11.XID) 0)
                {
                    SimpleLog.LogLine(TraceEventType.Error, CLASS_NAME +
                                      "::PrepareFont () Can not load a fontset with specification '" + extFontSpecification + "'.");

                    // No success at all - even with a guess of a fallback fontset!
                    return(false);
                }

                if (!string.IsNullOrEmpty(extFontSpecification))
                {
                    SimpleLog.LogLine(TraceEventType.Information, CLASS_NAME +
                                      "::PrepareFont () Successfully loaded best matching fontset for specification '" + fontSpecification + "' " +
                                      "using specification '" + extFontSpecification + "'.");
                }
                else if (!string.IsNullOrEmpty(fuzzyFontSpecification))
                {
                    SimpleLog.LogLine(TraceEventType.Information, CLASS_NAME +
                                      "::PrepareFont () Successfully loaded best matching fontset for specification '" + fontSpecification + "' " +
                                      "using specification '" + fuzzyFontSpecification + "'.");
                }
                else
                {
                    SimpleLog.LogLine(TraceEventType.Information, CLASS_NAME +
                                      "::PrepareFont () Successfully loaded best matching fontset for specification '" + fontSpecification + "'.");
                }

                for (int countCharSet = 0; countCharSet < (int)missingCharsetCount; countCharSet++)
                {
                    IntPtr p = Marshal.ReadIntPtr(missingCharsetList, countCharSet * Marshal.SizeOf(typeof(IntPtr)));
                    string s = Marshal.PtrToStringAuto(p);
                    if (!string.IsNullOrEmpty(extFontSpecification))
                    {
                        SimpleLog.LogLine(TraceEventType.Warning, CLASS_NAME +
                                          "::PrepareFont () Fontset for specification '" + extFontSpecification + "' is missing font for charset  '" + s + "'.");
                    }
                    else if (!string.IsNullOrEmpty(fuzzyFontSpecification))
                    {
                        SimpleLog.LogLine(TraceEventType.Warning, CLASS_NAME +
                                          "::PrepareFont () Fontset for specification '" + fuzzyFontSpecification + "' is missing font for charset  '" + s + "'.");
                    }
                    else
                    {
                        SimpleLog.LogLine(TraceEventType.Warning, CLASS_NAME +
                                          "::PrepareFont () Fontset for specification '" + fontSpecification + "' is missing font for charset  '" + s + "'.");
                    }
                }

                // Calculate maximum font height, ascent and descent.
                int ascent  = 0;
                int descent = 0;
                X11lib.XFontSetExtents extents = X11lib.XExtentsOfFontSet(fontsetResourceId);

                X11lib.XFontStruct[] fontStructArray;
                string[]             fontNameArray;
                int maxFonts;

                maxFonts = X11lib.XFontsOfFontSet(fontsetResourceId, out fontStructArray, out fontNameArray);
                for (int countFonts = 0; countFonts < maxFonts; countFonts++)
                {
                    if (ascent < (int)fontStructArray[countFonts].ascent)
                    {
                        ascent = (int)fontStructArray[countFonts].ascent;
                    }
                    if (descent < (int)fontStructArray[countFonts].descent)
                    {
                        descent = (int)fontStructArray[countFonts].descent;
                    }
                }

                string finalFontSpecification = null;
                if (!string.IsNullOrEmpty(extFontSpecification))
                {
                    finalFontSpecification = extFontSpecification;
                }
                else if (!string.IsNullOrEmpty(fuzzyFontSpecification))
                {
                    finalFontSpecification = fuzzyFontSpecification;
                }
                else
                {
                    finalFontSpecification = fontSpecification;
                }

                // Maximum font height, ascent and descent might be frequently used for calculation.
                fontData = X11FontData.NewFontSetData(finalFontSpecification, x11display, fontsetResourceId,
                                                      (int)extents.max_logical_extent.height, ascent, descent);

                IntPtr gc = X11lib.XCreateGC(x11display, X11lib.XDefaultRootWindow(x11display), 0, IntPtr.Zero);
                if (gc != IntPtr.Zero)
                {
                    fontData.SetTypicalCharWidth(AverageCharacterWidth(x11display, gc, fontData));
                    X11lib.XFreeGC(x11display, gc);
                }
                _loadedFonts.Add(key, fontData);
                return(true);
            }
            // Use font, if fontset isn't supported.
            else             // of (useFontset)
            {
                // Load font and query font structure (to get maximum font height, ascent and descent).
                IntPtr fontStructure = X11lib.XLoadQueryFont(x11display, fontSpecification);

                // Check whether directly matching font has been loaded, and - if not - load the most similar font (fuzzy).
                int    fuzzyFactor            = 0;
                string fuzzyFontSpecification = (fontStructure == IntPtr.Zero ? fontSpecification : null);
                while (fontStructure == IntPtr.Zero && fuzzyFactor < 3)
                {
                    string lastFuzzyFontSpecification = fuzzyFontSpecification;
                    if (fuzzyFactor == 0)
                    {
                        fuzzyFontSpecification = X11FontData.ModifyFontSpecificationStretch(fuzzyFontSpecification, "*");
                    }
                    if (fuzzyFactor == 1)
                    {
                        fuzzyFontSpecification = X11FontData.ModifyFontSpecificationWieght(fuzzyFontSpecification, "*");
                    }
                    if (fuzzyFactor == 2)
                    {
                        fuzzyFontSpecification = X11FontData.ModifyFontSpecificationSlant(fuzzyFontSpecification, "*");
                    }

                    fuzzyFactor++;
                    // Safe time if no change has been made.
                    if (lastFuzzyFontSpecification == fuzzyFontSpecification)
                    {
                        continue;
                    }

                    if (!string.IsNullOrEmpty(lastFuzzyFontSpecification) && lastFuzzyFontSpecification.Trim() != "")
                    {
                        fontStructure = X11lib.XLoadQueryFont(x11display, lastFuzzyFontSpecification);
                        if (fontStructure != IntPtr.Zero)
                        {
                            SimpleLog.LogLine(TraceEventType.Information, CLASS_NAME +
                                              "::PrepareFont () Fuzzy load font with specification '" + fuzzyFontSpecification + "' " +
                                              "instead of '" + fontSpecification + "' succeeded.");
                        }
                    }
                }

                // Check whether directly matching or most similar font has been loaded, and - if not - load a fallback font.
                string extFontSpecification = null;
                if (fontStructure != IntPtr.Zero)
                {
                    // Let the font server guess a fallback fontset.
                    if (!string.IsNullOrEmpty(fontSpecification) && fontSpecification.Trim() != "" && !fontSpecification.Trim().EndsWith(",*"))
                    {
                        extFontSpecification = fontSpecification + ",*";

                        SimpleLog.LogLine(TraceEventType.Warning, CLASS_NAME +
                                          "::PrepareFont () Can not load a fontset with specification '" + fontSpecification + "'.");
                        SimpleLog.LogLine(TraceEventType.Information, CLASS_NAME +
                                          "::PrepareFont () Retry to load a fontset with specification '" + extFontSpecification + "'.");

                        fontStructure = X11lib.XLoadQueryFont(x11display, extFontSpecification);
                    }
                    // The font specification already includs a joker to guess a fallback fontset.
                    else
                    {
                        SimpleLog.LogLine(TraceEventType.Error, CLASS_NAME +
                                          "::PrepareFont () Can not load a font with specification '" + fontSpecification + "'.");

                        // No success at all - even with a guess of a fallback font!
                        return(false);
                    }
                }

                // Check whether matching font has been loaded.
                if (fontStructure == IntPtr.Zero)
                {
                    SimpleLog.LogLine(TraceEventType.Error, CLASS_NAME +
                                      "::PrepareFont () Can not load a font with specification '" + fontSpecification + "'.");
                    // No success at all - even with a guess of a fallback font!
                    return(false);
                }

                if (!string.IsNullOrEmpty(extFontSpecification))
                {
                    SimpleLog.LogLine(TraceEventType.Information, CLASS_NAME +
                                      "::PrepareFont () Successfully loaded best matching font for specification '" + fontSpecification + "' " +
                                      "using specification '" + extFontSpecification + "'.");
                }
                else if (!string.IsNullOrEmpty(fuzzyFontSpecification))
                {
                    SimpleLog.LogLine(TraceEventType.Information, CLASS_NAME +
                                      "::PrepareFont () Successfully loaded best matching font for specification '" + fontSpecification + "' " +
                                      "using specification '" + fuzzyFontSpecification + "'.");
                }
                else
                {
                    SimpleLog.LogLine(TraceEventType.Information, CLASS_NAME +
                                      "::PrepareFont () Successfully loaded best matching font for specification '" + fontSpecification + "'.");
                }

                X11lib.XFontStruct fs = (X11lib.XFontStruct)Marshal.PtrToStructure(fontStructure, typeof(X11lib.XFontStruct));

                string finalFontSpecification = null;
                if (!string.IsNullOrEmpty(extFontSpecification))
                {
                    finalFontSpecification = extFontSpecification;
                }
                else if (!string.IsNullOrEmpty(fuzzyFontSpecification))
                {
                    finalFontSpecification = fuzzyFontSpecification;
                }
                else
                {
                    finalFontSpecification = fontSpecification;
                }

                // Maximum font height, ascent and descent might be frequently used for calculation.
                fontData = X11FontData.NewSingleFontData(finalFontSpecification, x11display, fs.fid,
                                                         (int)fs.ascent + (int)fs.descent, (int)fs.ascent, (int)fs.descent);

                IntPtr gc = X11lib.XCreateGC(x11display, X11lib.XDefaultRootWindow(x11display), 0, IntPtr.Zero);
                if (gc != IntPtr.Zero)
                {
                    fontData.SetTypicalCharWidth(AverageCharacterWidth(x11display, gc, fontData));
                    X11lib.XFreeGC(x11display, gc);
                }
                _loadedFonts.Add(key, fontData);
                return(true);
            }
        }
        /// <summary> Provide a bitmap, containing the transparent graphic, that can be used independent from this class. </summary>
        /// <param name="display"> The display pointer, that specifies the connection to the X server. <see cref="System.IntPtr"/> </param>
        /// <param name="window"> The target window to create the pixmap for. <see cref="IntPtr"/> </param>
        /// <param name="backgroundColorPixel"> The background color behind any transparent pixel. <see cref="TPixel"/> </param>
        /// <param name="maskPixmap"> The mask pixmap to distinguish transparent from intransparent pixel. <see cref="IntPtr"/> </param>
        /// <returns> The (server side) pixmap (that must be feed) on success, or IntPtr.Zero otherwise. <see cref="IntPtr"/> </returns>
        public IntPtr CreateIndependentPixmap(IntPtr display, IntPtr window, TPixel backgroundColorPixel, IntPtr maskPixmap)
        {
            if (_graphicXImage == IntPtr.Zero)
            {
                return(IntPtr.Zero);
            }

            IntPtr pixmap = X11lib.XCreatePixmap(display, window, (TUint)_width, (TUint)_height, (TUint)_graphicDepth);

            // Fill pixmap with background color.
            IntPtr bgGc = X11lib.XCreateGC(display, window, (TUlong)0, IntPtr.Zero);

            X11lib.XSetForeground(display, bgGc, backgroundColorPixel);
            X11lib.XFillRectangle(display, pixmap, bgGc, (TInt)0, (TInt)0, (TUint)_width, (TUint)_height);
            X11lib.XFreeGC(display, bgGc);
            bgGc = IntPtr.Zero;

            // Overlay the image.
            IntPtr pixmapGc = X11lib.XCreateGC(display, window, (TUlong)0, IntPtr.Zero);

            if (pixmapGc != IntPtr.Zero)
            {
                if (maskPixmap != IntPtr.Zero)
                {
                    // Prepare the clipping graphics context.
                    IntPtr graphicGc = X11lib.XCreateGC(display, window, (TUlong)0, IntPtr.Zero);
                    if (graphicGc != IntPtr.Zero)
                    {
                        X11lib.XSetClipMask(display, graphicGc, maskPixmap);
                        X11lib.XSetClipOrigin(display, graphicGc, (TInt)0, (TInt)0);

                        // Draw graphic using the clipping graphics context.
                        X11lib.XPutImage(display, pixmap, graphicGc, _graphicXImage, (TInt)0, (TInt)0,
                                         (TInt)0, (TInt)0, (TUint)_width, (TUint)_height);

                        // Restore previous behaviour and clean up.
                        X11lib.XSetClipMask(display, graphicGc, IntPtr.Zero);
                        X11lib.XSetClipOrigin(display, graphicGc, (TInt)0, (TInt)0);
                        // Console.WriteLine (CLASS_NAME + "::Draw () Delete clipping image GC.");
                        X11lib.XFreeGC(display, graphicGc);
                        graphicGc = IntPtr.Zero;
                    }
                    else
                    {
                        Console.WriteLine(CLASS_NAME + "::Draw () ERROR: Can not create graphics context for transparency application.");
                    }
                }
                else
                {
                    X11lib.XPutImage(display, pixmap, pixmapGc, _graphicXImage, (TInt)0, (TInt)0, (TInt)0, (TInt)0, (TUint)_width, (TUint)_height);
                    // Console.WriteLine (CLASS_NAME + "::CreateIndependentGraphicPixmap () Delete graphic image GC.");
                    X11lib.XFreeGC(display, pixmapGc);
                    pixmapGc = IntPtr.Zero;
                }
            }
            else
            {
                Console.WriteLine(CLASS_NAME + "::CreateIndependentGraphicPixmap () ERROR: Can not create graphics context for graphic pixmap.");
            }
            return(pixmap);
        }