diff --git a/Vocaluxe/Base/Font/CFont.cs b/Vocaluxe/Base/Font/CFont.cs index fb4fc0ee..39ecd7c9 100644 --- a/Vocaluxe/Base/Font/CFont.cs +++ b/Vocaluxe/Base/Font/CFont.cs @@ -82,74 +82,52 @@ namespace Vocaluxe.Base.Font return new System.Drawing.Font(_Family, CFonts.Height, CFonts.GetFontStyle(), GraphicsUnit.Pixel); } - public void DrawGlyph(char chr, float x, float y, float h, float z, SColorF color) + public void DrawGlyph(char chr, float x, float y, float z, SColorF color) { STexture texture; SRectF rect; - _GetGlyphTextureAndRect(chr, x, y, z, h, out texture, out rect); + GetOrAddGlyph(chr).GetTextureAndRect(x, y, z, out texture, out rect); CDraw.DrawTexture(texture, rect, color); } - public void DrawGlyph(char chr, float x, float y, float h, float z, SColorF color, float begin, float end) + public void DrawGlyph(char chr, float x, float y, float z, SColorF color, float begin, float end) { STexture texture; SRectF rect; - _GetGlyphTextureAndRect(chr, x, y, z, h, out texture, out rect); + GetOrAddGlyph(chr).GetTextureAndRect(x, y, z, out texture, out rect); CDraw.DrawTexture(texture, rect, color, begin, end); } - public void DrawGlyphReflection(char chr, float x, float y, float h, float z, SColorF color, float rspace, float rheight) + public void DrawGlyphReflection(char chr, float x, float y, float z, SColorF color, float rspace, float rheight) { STexture texture; SRectF rect; - _GetGlyphTextureAndRect(chr, x, y, z, h, out texture, out rect); + GetOrAddGlyph(chr).GetTextureAndRect(x, y, z, out texture, out rect); CDraw.DrawTextureReflection(texture, rect, color, rect, rspace, rheight); } - private void _GetGlyphTextureAndRect(char chr, float x, float y, float z, float h, out STexture texture, out SRectF rect) - { - AddGlyph(chr); - - CFonts.Height = h; - CGlyph glyph = _Glyphs[chr]; - texture = glyph.Texture; - float factor = h / texture.Height; - float width = texture.Width * factor; - float d = glyph.Sizeh / 5f * factor; - rect = new SRectF(x - d, y, width, h, z); - } - public float GetWidth(char chr) { - AddGlyph(chr); - - CGlyph glyph = _Glyphs[chr]; - float factor = CFonts.Height / glyph.Texture.Height; - return glyph.Width * factor; + return GetOrAddGlyph(chr).Width; } public float GetHeight(char chr) { - return CFonts.Height; - /*WTF??? - AddGlyph(chr); - - CGlyph glyph = _Glyphs[chr]; - float factor = CFonts.Height / glyph.Texture.height; - return glyph.Texture.height * factor;*/ + return GetOrAddGlyph(chr).Height; } - public void AddGlyph(char chr) + public CGlyph GetOrAddGlyph(char chr) { - if (_Glyphs.ContainsKey(chr)) - return; - - float h = CFonts.Height; - _Glyphs.Add(chr, new CGlyph(chr, _Sizeh)); - CFonts.Height = h; + CGlyph glyph; + if (!_Glyphs.TryGetValue(chr, out glyph)) + { + glyph = new CGlyph(chr, _Sizeh); + _Glyphs.Add(chr, glyph); + } + return glyph; } - public void UnloadAllGlyphs() + public void UnloadGlyphs() { foreach (CGlyph glyph in _Glyphs.Values) glyph.UnloadTexture(); @@ -162,7 +140,7 @@ namespace Vocaluxe.Base.Font { _Fonts.Dispose(); _Fonts = null; - UnloadAllGlyphs(); + UnloadGlyphs(); } GC.SuppressFinalize(this); } diff --git a/Vocaluxe/Base/Font/CFonts.cs b/Vocaluxe/Base/Font/CFonts.cs index 21922d7a..72dd9cc3 100644 --- a/Vocaluxe/Base/Font/CFonts.cs +++ b/Vocaluxe/Base/Font/CFonts.cs @@ -121,7 +121,7 @@ namespace Vocaluxe.Base.Font float dx = x; foreach (char chr in text) { - font.DrawGlyph(chr, dx, y, Height, z, color); + font.DrawGlyph(chr, dx, y, z, color); dx += font.GetWidth(chr); } } @@ -140,7 +140,7 @@ namespace Vocaluxe.Base.Font float dx = x; foreach (char chr in text) { - font.DrawGlyphReflection(chr, dx, y, Height, z, color, rspace, rheight); + font.DrawGlyphReflection(chr, dx, y, z, color, rspace, rheight); dx += font.GetWidth(chr); } } @@ -179,7 +179,7 @@ namespace Vocaluxe.Base.Font { if (e > 1f) e = 1f; - font.DrawGlyph(chr, dx, y, Height, z, color, b, e); + font.DrawGlyph(chr, dx, y, z, color, b, e); } } dx += w2; @@ -397,10 +397,10 @@ namespace Vocaluxe.Base.Font { if (_Fonts[index].IsThemeFont && _Fonts[index].ThemeName == themeName) { - _Fonts[index].Normal.UnloadAllGlyphs(); - _Fonts[index].Italic.UnloadAllGlyphs(); - _Fonts[index].Bold.UnloadAllGlyphs(); - _Fonts[index].BoldItalic.UnloadAllGlyphs(); + _Fonts[index].Normal.UnloadGlyphs(); + _Fonts[index].Italic.UnloadGlyphs(); + _Fonts[index].Bold.UnloadGlyphs(); + _Fonts[index].BoldItalic.UnloadGlyphs(); _Fonts.RemoveAt(index); } else @@ -449,7 +449,7 @@ namespace Vocaluxe.Base.Font private static void _BuildGlyphs() { - const string text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPGRSTUVWGXZ1234567890"; + const string text = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; for (int i = 0; i < _Fonts.Count; i++) { @@ -458,13 +458,13 @@ namespace Vocaluxe.Base.Font foreach (char chr in text) { Style = EStyle.Normal; - _Fonts[_CurrentFont].Normal.AddGlyph(chr); + _Fonts[_CurrentFont].Normal.GetOrAddGlyph(chr); Style = EStyle.Bold; - _Fonts[_CurrentFont].Bold.AddGlyph(chr); + _Fonts[_CurrentFont].Bold.GetOrAddGlyph(chr); Style = EStyle.Italic; - _Fonts[_CurrentFont].Italic.AddGlyph(chr); + _Fonts[_CurrentFont].Italic.GetOrAddGlyph(chr); Style = EStyle.BoldItalic; - _Fonts[_CurrentFont].BoldItalic.AddGlyph(chr); + _Fonts[_CurrentFont].BoldItalic.GetOrAddGlyph(chr); } } Style = EStyle.Normal; diff --git a/Vocaluxe/Base/Font/CGlyph.cs b/Vocaluxe/Base/Font/CGlyph.cs index a8b5bdc8..1b036bb1 100644 --- a/Vocaluxe/Base/Font/CGlyph.cs +++ b/Vocaluxe/Base/Font/CGlyph.cs @@ -20,7 +20,9 @@ using System; using System.Drawing; using System.Drawing.Drawing2D; +using System.Drawing.Imaging; using System.Drawing.Text; +using System.Runtime.InteropServices; using System.Windows.Forms; using VocaluxeLib.Menu; @@ -28,91 +30,190 @@ namespace Vocaluxe.Base.Font { class CGlyph { - public float Sizeh { get; private set; } + private STexture _Texture; + private readonly SizeF _BoundingBox; + private readonly Point _Offset; - public STexture Texture; - public readonly int Width; + public float Width + { + get { return _BoundingBox.Width * _GetFactor(); } + } + + public float Height + { + get { return _BoundingBox.Height * _GetFactor(); } + } public CGlyph(char chr, float maxHigh) { - Sizeh = maxHigh; - + float oldHeight = CFonts.Height; float outline = CFonts.Outline; - const TextFormatFlags flags = TextFormatFlags.NoPadding | TextFormatFlags.NoPrefix; + float outlineSize = outline * maxHigh; + string chrString = chr.ToString(); - float factor = _GetFactor(chr, flags); - CFonts.Height = Sizeh * factor; - System.Drawing.Font fo; - Size sizeB; - SizeF size; + CFonts.Height = maxHigh; // *factor; + //float factor = _GetFactor(chr, flags); + System.Drawing.Font fo = CFonts.GetFont(); + SizeF fullSize; using (Graphics g = Graphics.FromHwnd(IntPtr.Zero)) { - fo = CFonts.GetFont(); - sizeB = TextRenderer.MeasureText(g, chr.ToString(), fo, new Size(int.MaxValue, int.MaxValue), flags); - - size = g.MeasureString(chr.ToString(), fo); + fullSize = g.MeasureString(chrString, fo); + fullSize.Width += outlineSize; + if (chr != ' ') + { + SizeF boundingSize = g.MeasureString(chrString, fo, -1, new StringFormat(StringFormat.GenericTypographic)); + boundingSize.Width += outlineSize; + _BoundingBox = boundingSize; + } + else + { + _BoundingBox = fullSize; + fullSize.Width = 1; + fullSize.Height = 1; + } } - - using (Bitmap bmp = new Bitmap((int)(sizeB.Width * 2f), sizeB.Height)) + using (Bitmap bmp = new Bitmap((int)(fullSize.Width), (int)(fullSize.Height), PixelFormat.Format32bppArgb)) { Graphics g = Graphics.FromImage(bmp); g.Clear(Color.Transparent); - g.SmoothingMode = SmoothingMode.AntiAlias; - g.InterpolationMode = InterpolationMode.HighQualityBicubic; - g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; - CFonts.Height = Sizeh; - fo = CFonts.GetFont(); - - PointF point = new PointF( - outline * Math.Abs(sizeB.Width - size.Width) + (sizeB.Width - size.Width) / 2f + Sizeh / 5f, - (sizeB.Height - size.Height - (size.Height + Sizeh / 4f) * (1f - factor)) / 2f); - - using (GraphicsPath path = new GraphicsPath()) + if (chr != ' ') { - path.AddString( - chr.ToString(), - fo.FontFamily, - (int)fo.Style, - Sizeh, - point, - new StringFormat()); + g.SmoothingMode = SmoothingMode.AntiAlias; + g.InterpolationMode = InterpolationMode.HighQualityBicubic; + g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; - using (Pen pen = new Pen( - Color.FromArgb( - (int)CFonts.OutlineColor.A * 255, - (int)CFonts.OutlineColor.R * 255, - (int)CFonts.OutlineColor.G * 255, - (int)CFonts.OutlineColor.B * 255), - Sizeh * outline)) + PointF point = new PointF(outlineSize / 2, 0); + + using (GraphicsPath path = new GraphicsPath()) { - pen.LineJoin = LineJoin.Round; - g.DrawPath(pen, path); - g.FillPath(Brushes.White, path); + path.AddString(chrString, fo.FontFamily, (int)fo.Style, CFonts.Height, point, new StringFormat()); + + using (Pen pen = new Pen(CFonts.OutlineColor.AsColor(), outlineSize)) + { + pen.LineJoin = LineJoin.Round; + g.DrawPath(pen, path); + g.FillPath(Brushes.White, path); + } } } + _Texture = CDraw.AddTexture(bmp); + + if (false) + { + if (outline > 0) + bmp.Save("font/" + chr + "o" + CFonts.Style + "2.png", ImageFormat.Png); + else + bmp.Save("font/" + chr + CFonts.Style + "2.png", ImageFormat.Png); + } - /* - g.DrawString( - chr.ToString(), - fo, - Brushes.White, - point); - * */ - Texture = CDraw.AddTexture(bmp); - //bmp.Save("font/" + chr + CFonts.Style + ".png", ImageFormat.Png); - Width = (int)((1f + outline / 2f) * sizeB.Width * Texture.Width / factor / bmp.Width); g.Dispose(); } fo.Dispose(); + CFonts.Height = oldHeight; + } + + private float _GetFactor() + { + return CFonts.Height / _BoundingBox.Height; } public void UnloadTexture() { - CDraw.RemoveTexture(ref Texture); + CDraw.RemoveTexture(ref _Texture); } - private float _GetFactor(char chr, TextFormatFlags flags) + public void GetTextureAndRect(float x, float y, float z, out STexture texture, out SRectF rect) + { + texture = _Texture; + rect = new SRectF(x, y, Width, Height, z); + } + + private Point _TrimBmp(ref Bitmap bmp) + { + int minX = 0, minY = 0, maxX = bmp.Width - 1, maxY = bmp.Width - 1; + BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); + int values = bmpData.Width * bmp.Height; + Int32[] rgbValues = new Int32[values]; + Marshal.Copy(bmpData.Scan0, rgbValues, 0, values); + int index = 0; + bool found = false; + //find from top + for (int y = 0; y < bmp.Height && !found; y++) + { + for (int x = 0; x < bmp.Width; x++) + { + if (rgbValues[index] != 0) + { + minX = x; + maxX = x; + minY = y; + found = true; + break; + } + index++; + } + } + found = false; + //find from bottom + for (int y = bmp.Height - 1; y >= minY && !found; y--) + { + for (int x = 0; x < bmp.Width; x++) + { + if (rgbValues[index] != 0) + { + if (x < minX) + minX = x; + else if (x > maxX) + maxX = x; + maxY = y; + found = true; + break; + } + index++; + } + } + //find left + for (int x = minX - 1; x >= 0; x--) + { + found = false; + index = minY * bmp.Width + x; + for (int y = minY; y <= maxY; y++) + { + if (rgbValues[index] != 0) + { + found = true; + minX = x; + break; + } + index += bmp.Width; + } + if (!found) + break; + } + //find right + for (int x = maxX + 1; x < bmp.Width; x++) + { + found = false; + index = minY * bmp.Width + x; + for (int y = minY; y <= maxY; y++) + { + if (rgbValues[index] != 0) + { + found = true; + maxX = x; + break; + } + index += bmp.Width; + } + if (!found) + break; + } + bmp = bmp.Clone(new Rectangle(minX, minY, maxX - minX, maxY - minY), PixelFormat.Format32bppArgb); + return new Point(minX, minY); + } + + private float _GetStyleFactor(char chr, TextFormatFlags flags) { if (CFonts.Style == EStyle.Normal) return 1f; @@ -120,7 +221,6 @@ namespace Vocaluxe.Base.Font EStyle style = CFonts.Style; CFonts.Style = EStyle.Normal; - CFonts.Height = Sizeh; float hStyle, hNormal; using (Graphics g = Graphics.FromHwnd(IntPtr.Zero)) { diff --git a/Vocaluxe/Lib/Draw/CDirect3D.cs b/Vocaluxe/Lib/Draw/CDirect3D.cs index 37a09046..bda3026b 100644 --- a/Vocaluxe/Lib/Draw/CDirect3D.cs +++ b/Vocaluxe/Lib/Draw/CDirect3D.cs @@ -1256,6 +1256,8 @@ namespace Vocaluxe.Lib.Draw rx2 -= 0.5f; ry2 -= 0.5f; + color.A *= CGraphics.GlobalAlpha; + if (color.A > 1) color.A = 1; if (color.R > 1) @@ -1265,7 +1267,7 @@ namespace Vocaluxe.Lib.Draw if (color.B > 1) color.B = 1; - Color c = Color.FromArgb((int)(color.A * 255 * CGraphics.GlobalAlpha), (int)(color.R * 255), (int)(color.G * 255), (int)(color.B * 255)); + Color c = color.AsColor(); if (!mirrored) { @@ -1319,7 +1321,9 @@ namespace Vocaluxe.Lib.Draw rx2 -= 0.5f; ry2 -= 0.5f; - Color c = Color.FromArgb((int)(color.A * 255 * CGraphics.GlobalAlpha), (int)(color.R * 255), (int)(color.G * 255), (int)(color.B * 255)); + color.A *= CGraphics.GlobalAlpha; + + Color c = color.AsColor(); STexturedColoredVertex[] vert = new STexturedColoredVertex[4]; vert[0] = new STexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, y1), c.ToArgb()); @@ -1401,8 +1405,10 @@ namespace Vocaluxe.Lib.Draw rx2 -= 0.5f; ry2 -= 0.5f; - Color c = Color.FromArgb((int)(color.A * 255 * CGraphics.GlobalAlpha), (int)(color.R * 255), (int)(color.G * 255), (int)(color.B * 255)); - Color transparent = Color.FromArgb(0, (int)(color.R * 255), (int)(color.G * 255), (int)(color.B * 255)); + color.A *= CGraphics.GlobalAlpha; + Color c = color.AsColor(); + color.A = 0; + Color transparent = color.AsColor(); STexturedColoredVertex[] vert = new STexturedColoredVertex[4]; vert[0] = new STexturedColoredVertex(new Vector3(rx1, -ry1, rect.Z + CGraphics.ZOffset), new Vector2(x1, y2), c.ToArgb()); diff --git a/Vocaluxe/Screens/CScreenTest.cs b/Vocaluxe/Screens/CScreenTest.cs index 3fa3f2e4..307661ca 100644 --- a/Vocaluxe/Screens/CScreenTest.cs +++ b/Vocaluxe/Screens/CScreenTest.cs @@ -36,6 +36,24 @@ namespace Vocaluxe.Screens private int _TestMusic = -1; */ + public override void Init() + { + base.Init(); + const string test = " ÖÄÜabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPGRSTUVWGXZ1234567890"; + CText text = new CText(10, 50, 1, EAlignment.Left, 32, 0, 1, 0, 0, 1, EStyle.Normal, "Normal", "Normal Text" + test); + _AddText(text); + text = new CText(10, 90, 1, EAlignment.Left, 32, 0, 1, 0, 0, 1, EStyle.Bold, "Normal", "Bold Text" + test); + _AddText(text); + text = new CText(10, 130, 1, EAlignment.Left, 32, 0, 1, 0, 0, 1, EStyle.Italic, "Normal", "Italic Text" + test); + _AddText(text); + text = new CText(10, 170, 1, EAlignment.Left, 32, 0, 1, 0, 0, 1, EStyle.Normal, "Outline", "Normal Text" + test); + _AddText(text); + text = new CText(10, 210, 1, EAlignment.Left, 32, 0, 1, 0, 0, 1, EStyle.Bold, "Outline", "Bold Text" + test); + _AddText(text); + text = new CText(10, 250, 1, EAlignment.Left, 32, 0, 1, 0, 0, 1, EStyle.Italic, "Outline", "Italic Text" + test); + _AddText(text); + } + public override bool HandleInput(SKeyEvent keyEvent) { if (keyEvent.KeyPressed && !Char.IsControl(keyEvent.Unicode)) {} diff --git a/VocaluxeLib/Menu/CButton.cs b/VocaluxeLib/Menu/CButton.cs index b3a69d15..976da6b4 100644 --- a/VocaluxeLib/Menu/CButton.cs +++ b/VocaluxeLib/Menu/CButton.cs @@ -312,7 +312,7 @@ namespace VocaluxeLib.Menu if (_Reflection) { CBase.Drawing.DrawTextureReflection(texture, Rect, Color, Rect, _ReflectionSpace, _ReflectionHeight); - Text.DrawRelative(Rect.X, Rect.Y, _ReflectionSpace, _ReflectionHeight, Rect.H); + Text.DrawRelative(Rect.X, Rect.Y, _ReflectionHeight, _ReflectionSpace, Rect.H); } else Text.DrawRelative(Rect.X, Rect.Y); @@ -326,7 +326,7 @@ namespace VocaluxeLib.Menu if (_Reflection) { CBase.Drawing.DrawTextureReflection(texture, Rect, SelColor, Rect, _ReflectionSpace, _ReflectionHeight); - Text.DrawRelative(Rect.X, Rect.Y, _ReflectionSpace, _ReflectionHeight, Rect.H); + Text.DrawRelative(Rect.X, Rect.Y, _ReflectionHeight, _ReflectionSpace, Rect.H); } else Text.DrawRelative(Rect.X, Rect.Y); @@ -340,7 +340,7 @@ namespace VocaluxeLib.Menu if (_Reflection) { CBase.Drawing.DrawTextureReflection(texture, Rect, SelColor, Rect, _ReflectionSpace, _ReflectionHeight); - _SelText.DrawRelative(Rect.X, Rect.Y, _ReflectionSpace, _ReflectionHeight, Rect.H); + _SelText.DrawRelative(Rect.X, Rect.Y, _ReflectionHeight, _ReflectionSpace, Rect.H); } else _SelText.DrawRelative(Rect.X, Rect.Y); diff --git a/VocaluxeLib/Menu/CText.cs b/VocaluxeLib/Menu/CText.cs index 6284e88b..695b060a 100644 --- a/VocaluxeLib/Menu/CText.cs +++ b/VocaluxeLib/Menu/CText.cs @@ -697,12 +697,7 @@ namespace VocaluxeLib.Menu CBase.Drawing.DrawColor(new SColorF(0.5f, 1f, 0.5f, 0.5f), new SRectF(x, Y, bounds.Width, bounds.Height, Z)); } - public void DrawRelative(float x, float y, float reflectionSpace, float reflectionHeigth, float rectHeight) - { - DrawRelative(x, y, true, reflectionSpace, reflectionHeigth, rectHeight); - } - - public void DrawRelative(float rx, float ry, bool reflection = false, float reflectionSpace = 0f, float reflectionHeight = 0f, float rectHeight = 0f) + public void DrawRelative(float rx, float ry, float reflectionHeight = 0f, float reflectionSpace = 0f, float rectHeight = 0f) { // Update Text Text = Text; @@ -724,14 +719,11 @@ namespace VocaluxeLib.Menu h *= factor; switch (HAlign) { - case EHAlignment.Top: - y += step * 0.25f; - break; case EHAlignment.Center: y += step * 0.50f; break; case EHAlignment.Bottom: - y += step * 0.75f; + y += step; break; } @@ -749,9 +741,7 @@ namespace VocaluxeLib.Menu } - SColorF currentColor = new SColorF(Color); - if (Selected) - currentColor = new SColorF(SelColor); + SColorF currentColor = (Selected) ? SelColor : Color; SColorF color = new SColorF(currentColor.R, currentColor.G, currentColor.B, currentColor.A * Alpha); @@ -760,7 +750,7 @@ namespace VocaluxeLib.Menu CBase.Fonts.DrawText(_Text, h, x, y, Z, color); - if (reflection) + if (reflectionHeight > 0) { float space = (rectHeight - Y - bounds.Height) * 2f + reflectionSpace; float height = reflectionHeight - (rectHeight - Y) + bounds.Height; diff --git a/VocaluxeLib/Menu/Structs.cs b/VocaluxeLib/Menu/Structs.cs index 76dbc466..062379fe 100644 --- a/VocaluxeLib/Menu/Structs.cs +++ b/VocaluxeLib/Menu/Structs.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.Windows.Forms; using VocaluxeLib.Menu.SingNotes; @@ -48,6 +49,11 @@ namespace VocaluxeLib.Menu B = color.B; A = color.A; } + + public Color AsColor() + { + return Color.FromArgb((int)(A * 255), (int)(R * 255), (int)(G * 255), (int)(B * 255)); + } } public struct SRectF