diff --git a/Quik.Media.Defaults/QFontFreeType.cs b/Quik.Media.Defaults/QFontFreeType.cs index 7b72701..c07be0b 100644 --- a/Quik.Media.Defaults/QFontFreeType.cs +++ b/Quik.Media.Defaults/QFontFreeType.cs @@ -54,7 +54,7 @@ namespace Quik.Media.Defaults return null; } - QImageBuffer image = new QImageBuffer(QImageFormat.RedU8, (int)bitmap.Width, (int)bitmap.Rows); + QImageBuffer image = new QImageBuffer(QImageFormat.AlphaU8, (int)bitmap.Width, (int)bitmap.Rows); image.LockBits2d(out QImageLock lk, QImageLockOptions.Default); unsafe diff --git a/Quik/Controls/Control.cs b/Quik/Controls/Control.cs new file mode 100644 index 0000000..cf93de2 --- /dev/null +++ b/Quik/Controls/Control.cs @@ -0,0 +1,67 @@ +using System; +using Quik.CommandMachine; + +namespace Quik.Controls +{ + public abstract class Control : UIBase + { + private readonly CommandList drawCommands = new CommandList(); + + public Style Style { get; set; } = new Style(); + public float Padding + { + get => (float)(Style["padding"] ?? 0.0f); + set => Style["padding"] = value; + } + + public bool IsVisualsValid { get; private set; } + + public void InvalidateVisual() + { + IsVisualsValid = false; + OnVisualsInvalidated(this, EventArgs.Empty); + } + + protected abstract void ValidateVisual(CommandList cmd); + protected override void PaintBegin(CommandList cmd) + { + base.PaintBegin(cmd); + + if (!IsVisualsValid) + { + ValidateVisual(drawCommands); + OnVisualsValidated(this, EventArgs.Empty); + IsVisualsValid = true; + } + + cmd.PushStyle(Style); + cmd.PushViewport(); + cmd.StoreViewport(AbsoluteBounds); + + cmd.Splice(drawCommands); + + cmd.PopViewport(); + cmd.PopStyle(); + } + + public event EventHandler StyleChanged; + public event EventHandler VisualsInvalidated; + public event EventHandler VisualsValidated; + + protected virtual void OnStyleChanged(object sender, EventArgs ea) + { + StyleChanged?.Invoke(sender, ea); + InvalidateVisual(); + } + + protected virtual void OnVisualsInvalidated(object sender, EventArgs ea) + { + VisualsInvalidated?.Invoke(sender, ea); + } + + protected virtual void OnVisualsValidated(object sender, EventArgs ea) + { + VisualsValidated?.Invoke(sender, ea); + } + } +} \ No newline at end of file diff --git a/Quik/Controls/Label.cs b/Quik/Controls/Label.cs new file mode 100644 index 0000000..020f00c --- /dev/null +++ b/Quik/Controls/Label.cs @@ -0,0 +1,21 @@ +using Quik.CommandMachine; +using Quik.Media; +using Quik.Typography; + +namespace Quik.Controls +{ + public class Label : Control + { + public string Text { get; set; } + public QFont TextFont { get; set; } + public float TextSize { get; set; } + + protected override void ValidateVisual(CommandList cmd) + { + float padding = Padding; + QVec2 origin = new QVec2(padding, padding); + + cmd.TypesetHorizontalDirect(Text, origin, TextSize, TextFont); + } + } +} \ No newline at end of file diff --git a/Quik/Media/Font/FontAtlas.cs b/Quik/Media/Font/FontAtlas.cs index 6e8edb1..621c73e 100644 --- a/Quik/Media/Font/FontAtlas.cs +++ b/Quik/Media/Font/FontAtlas.cs @@ -120,7 +120,7 @@ namespace Quik.Media.Font public AtlasPage(int width, int height, int expansion) { - Image = new QImageBuffer(QImageFormat.RedU8, width, height); + Image = new QImageBuffer(QImageFormat.AlphaU8, width, height); Expansion = expansion; Reset(); } diff --git a/Quik/OpenGL/GL21Driver.cs b/Quik/OpenGL/GL21Driver.cs index 5583a96..bc132be 100644 --- a/Quik/OpenGL/GL21Driver.cs +++ b/Quik/OpenGL/GL21Driver.cs @@ -100,24 +100,30 @@ namespace Quik.OpenGL // This already binds the vertex array for me. draw.PrepareFrame(); - QVec2 size = view.Size; - QMat4.Orthographic(out QMat4 matrix, view); + QVec2 size = view.Size; + QMat4.Orthographic(out QMat4 viewMatrix, view); + + GL.Viewport(0, 0, (int)view.Size.X, (int)view.Size.Y); GL.UseProgram(program); GL.Uniform1(fMaxZ, (float)(queue.ZDepth+1)); - GL.UniformMatrix4(m4Transforms, false, in matrix); GL.Uniform1(fSdfThreshold, 0.5f); GL.Uniform1(tx2d, 0); GL.Enable(GL_BLEND); GL.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL.Enable(GL_SCISSOR_TEST); foreach (DrawCall call in queue) { - GL.Viewport( - (int)call.Bounds.Left, - (int)(view.Bottom - call.Bounds.Bottom), - (int)call.Bounds.Right, - (int)(view.Bottom - call.Bounds.Top)); + GL.Scissor( + (int)MathF.Round(call.Bounds.Left), + (int)MathF.Round(view.Bottom - call.Bounds.Bottom), + (int)MathF.Round(call.Bounds.Right), + (int)MathF.Round(view.Bottom - call.Bounds.Top)); + QMat4.Translation(out QMat4 modelMatrix, call.Bounds.Min.X, call.Bounds.Min.Y, 0); + QMat4 modelView = viewMatrix * modelMatrix; + GL.UniformMatrix4(m4Transforms, false, in modelView); + GL.ActiveTexture(GL_TEXTURE0); GL.BindTexture(GL_TEXTURE_2D, 0); if (call.Texture != null) @@ -389,6 +395,24 @@ namespace Quik.OpenGL GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + switch (image2d.InternalFormat) + { + case QImageFormat.RedU8: + case QImageFormat.RedF: + GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED); + GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED); + GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); + GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE); + break; + case QImageFormat.AlphaU8: + case QImageFormat.AlphaF: + GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ONE); + GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_ONE); + GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ONE); + GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA); + break; + } + return texture; } diff --git a/tests/QuikDemo/Program.cs b/tests/QuikDemo/Program.cs index d5574f5..a1d8744 100644 --- a/tests/QuikDemo/Program.cs +++ b/tests/QuikDemo/Program.cs @@ -1,11 +1,9 @@ -using System; -using Quik; +using Quik; using Quik.CommandMachine; using Quik.Controls; using Quik.OpenTK; using Quik.Media.Defaults; using Quik.Media; -using Quik.Typography; using Quik.PAL; namespace QuikDemo @@ -23,6 +21,7 @@ namespace QuikDemo public class EmptyView : View { private QFont font; + private readonly Label Label = new Label() { Text = "Hello world!", Size = new QVec2(256, 32), Position = new QVec2(300, 300) }; protected override void PaintBegin(CommandList cmd) { @@ -32,13 +31,14 @@ namespace QuikDemo { IFontDataBase db = FontDataBaseProvider.Instance; font = new QFontFreeType(db.FontFileInfo(db.Sans).OpenRead()); + + Label.TextFont = font; + Label.TextSize = 16; + Label.InvalidateVisual(); } cmd.Rectangle(new QRectangle(16, 16, 0, 0)); - cmd.TypesetHorizontalDirect( - "The quick brown fox jumps over the lazy dog.\n" + - "hi?", - new QVec2(64.33f, 0.77f), 9, font); + Label.Paint(cmd); } } } \ No newline at end of file