/// <summary> /// Takes a texture and applies some text to it. /// </summary> /// <param name="text">The text to texture.</param> /// <param name="font">The font of the text.</param> /// <param name="width">The width of the text.</param> /// <param name="height">The height of the text.</param> /// <param name="loadedTexture">The texture to be loaded on to.</param> /// <param name="background">The background of the text. (default: none/null)</param> /// <param name="orientation">The orientation of the text. (default: left)</param> public void GenOrUpdateTextTexture(string text, CairoFont font, int width, int height, ref LoadedTexture loadedTexture, TextBackground background = null, EnumTextOrientation orientation = EnumTextOrientation.Left, bool demulAlpha = false) { if (background == null) { background = defaultBackground; } ElementBounds bounds = new ElementBounds().WithFixedSize(width, height); ImageSurface surface = new ImageSurface(Format.Argb32, width, height); Context ctx = new Context(surface); GuiElementTextBase elTeBa = new GuiElementTextBase(capi, text, font, bounds); ctx.SetSourceRGBA(background.FillColor); GuiElement.RoundRectangle(ctx, 0, 0, width, height, background.Radius); if (background.BorderWidth > 0) { ctx.FillPreserve(); ctx.Operator = Operator.Atop; ctx.LineWidth = background.BorderWidth; ctx.SetSourceRGBA(background.BorderColor); ctx.Stroke(); ctx.Operator = Operator.Over; } else { ctx.Fill(); } //ctx.Antialias = Antialias.Subpixel; elTeBa.textUtil.AutobreakAndDrawMultilineTextAt(ctx, font, text, background.Padding, background.Padding, width, orientation); //int textureId = capi.Gui.LoadCairoTexture(surface, true); - WTF! What was this for?! if (demulAlpha) { surface.DemulAlpha(); } capi.Gui.LoadOrUpdateCairoTexture(surface, true, ref loadedTexture); //surface.WriteToPng("test.png"); surface.Dispose(); ctx.Dispose(); }
/// <summary> /// Tells the composer to compose the gui. /// </summary> /// <param name="focusFirstElement">Whether or not to put the first element in focus.</param> public GuiComposer Compose(bool focusFirstElement = true) { if (Composed) { if (focusFirstElement && MaxTabIndex >= 0) { FocusElement(0); } return(this); } foreach (GuiElement element in staticElements.Values) { element.BeforeCalcBounds(); } bounds.Initialized = false; try { bounds.CalcWorldBounds(); } catch (Exception e) { Api.World.Logger.Error("Exception thrown when trying to calculate world bounds for gui composite " + dialogName + ": " + e); } bounds.IsDrawingSurface = true; // So here's yet another snippet of weird code. It *seems* as if most graphics cards really don't like // when you delete and reallocate textures often (maybe causes memory fragmentation and then spends extra time defragmenting? o.O) // So instead we allocate a larger space and re-use the previous texture, if we already have one that fits int wdt = (int)bounds.OuterWidth; int hgt = (int)bounds.OuterHeight; if (staticElementsTexture.TextureId != 0) { wdt = Math.Max(wdt, staticElementsTexture.Width); hgt = Math.Max(hgt, staticElementsTexture.Height); } ImageSurface surface = new ImageSurface(Format.Argb32, wdt, hgt); Context ctx = new Context(surface); ctx.SetSourceRGBA(0, 0, 0, 0); ctx.Paint(); ctx.Antialias = Antialias.Best; foreach (GuiElement element in staticElements.Values) { element.ComposeElements(ctx, surface); } interactiveElementsInDrawOrder.Clear(); foreach (GuiElement element in interactiveElements.Values) { int insertPos = 0; foreach (GuiElement addedElem in interactiveElementsInDrawOrder) { if (element.DrawOrder >= addedElem.DrawOrder) { insertPos++; } else { break; } } interactiveElementsInDrawOrder.Insert(insertPos, element); } if (!premultipliedAlpha) { surface.DemulAlpha(); } Api.Gui.LoadOrUpdateCairoTexture(surface, true, ref staticElementsTexture); ctx.Dispose(); surface.Dispose(); Composed = true; if (focusFirstElement && MaxTabIndex >= 0) { FocusElement(0); } return(this); }