/// <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); }
// ############################################################################### // ### 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); }