Skip to content

Commit

Permalink
TextRenderer Refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
Kagamia committed Jul 22, 2017
1 parent fa46ba1 commit 79c4f70
Show file tree
Hide file tree
Showing 7 changed files with 556 additions and 360 deletions.
2 changes: 1 addition & 1 deletion WzComparerR2.Common/Rendering/XnaFont.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ private Rectangle CreateCharBuffer(char c)
SizeF size;

size = g.MeasureString(text, this.baseFont, byte.MaxValue, StringFormat.GenericTypographic);
GDIRect originRect = new GDIRect(gdiBufferX, 0, (int)Math.Ceiling(size.Width), (int)Math.Round(size.Height));
GDIRect originRect = new GDIRect(gdiBufferX, 0, (int)Math.Ceiling(size.Width), (int)Math.Ceiling(size.Height));
if (originRect.Width == 0)
{
originRect.Width = (int)(this.baseFont.Size / 2);
Expand Down
71 changes: 71 additions & 0 deletions WzComparerR2.Common/Rendering/XnaFontRenderer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using WzComparerR2.Text;

namespace WzComparerR2.Rendering
{
public class XnaFontRenderer : TextRenderer<XnaFont>
{
public XnaFontRenderer(SpriteBatchEx spriteBatch)
{
this.SpriteBatch = spriteBatch;
}

public SpriteBatchEx SpriteBatch { get; set; }


protected override void MeasureRuns(List<Run> runs)
{
int x = 0;
foreach (var run in runs)
{
if (run.IsBreakLine)
{
run.X = x;
run.Length = 0;
}
else
{
var size = base.font.MeasureString(base.sb, run.StartIndex, run.Length);
run.X = x;
run.Width = (int)size.X;
x += run.Width;
}
}
}

protected override Rectangle[] MeasureChars(int startIndex, int length)
{
var regions = new Rectangle[length];
int x = 0;
for (int i = 0; i < length; i++)
{
var rect = this.font.TryGetRect(this.sb[startIndex + i]);
regions[i] = new Rectangle(x, 0, rect.Width, rect.Height);
x += rect.Width;
}
return regions;
}

protected override void Flush(StringBuilder sb, int startIndex, int length, int x, int y, string colorID)
{
var color = this.GetColor(colorID);
var pos = new Microsoft.Xna.Framework.Vector2(x, y);
this.SpriteBatch.DrawStringEx(this.font, sb, startIndex, length, pos, color);
}

public virtual Microsoft.Xna.Framework.Color GetColor(string colorID)
{
switch (colorID)
{
case "c":
return new Microsoft.Xna.Framework.Color(255, 153, 0);
default:
return Microsoft.Xna.Framework.Color.White;
}
}
}
}
24 changes: 24 additions & 0 deletions WzComparerR2.Common/Text/DocumentElements.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace WzComparerR2.Text
{
public abstract class DocElement
{
}

public sealed class Span : DocElement
{
public string ColorID { get; set; }
public string Text { get; set; }
}

public sealed class LineBreak : DocElement
{
private LineBreak() { }
public static readonly LineBreak Instance = new LineBreak();
}
}
111 changes: 111 additions & 0 deletions WzComparerR2.Common/Text/Parser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WzComparerR2.Text
{
public class Parser
{
private Parser()
{
}

public static IList<DocElement> Parse(string format)
{
var elements = new List<DocElement>();
var sb = new StringBuilder();
var colorStack = new Stack<string>();
colorStack.Push("");

int strPos = 0;
char curChar;

int offset = 0;

Action flushRun = () =>
{
if (offset < format.Length)
{
elements.Add(new Span()
{
Text = sb.ToString(offset, sb.Length - offset),
ColorID = colorStack.Peek()
});
offset = sb.Length;
}
};

while (strPos < format.Length)
{
curChar = format[strPos++];
if (curChar == '\\')
{
if (strPos < format.Length)
{
curChar = format[strPos++];
switch (curChar)
{
case 'r': curChar = '\r'; break;
case 'n': curChar = '\n'; break;
}
}
else //结束符处理
{
curChar = '#';
}
}

switch (curChar)
{
case '#':
if (strPos < format.Length && format[strPos] == 'c')//遇到#c 换橙刷子并flush
{
flushRun();
colorStack.Push("c");
strPos++;
}
else if (strPos < format.Length && format[strPos] == 'g')//遇到#g(自定义) 换绿刷子并flush
{
flushRun();
colorStack.Push("g");
strPos++;
}
else if (strPos < format.Length && format[strPos] == '$')//遇到#$(自定义) 换青色刷子并flush
{
flushRun();
colorStack.Push("$");
strPos++;
}
else if (colorStack.Count == 1) //同#c
{
flushRun();
colorStack.Push("c");
strPos++;
}
else//遇到# 换白刷子并flush
{
flushRun();
colorStack.Pop();
}
break;

case '\r': //忽略
break;

case '\n': //插入换行
flushRun();
elements.Add(LineBreak.Instance);
break;

default:
sb.Append(curChar);
break;
}
}

flushRun();
return elements;
}
}
}

6 comments on commit 79c4f70

@Sunaries
Copy link

@Sunaries Sunaries commented on 79c4f70 Jul 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated my version with all your commits. I have noticed this change:

BEFORE

AFTER

The alignment has been slightly shifted towards the right and the color of the set info is white as if you see it equipped. It should be gray.

EDIT 2:

It should be noted that for the color change to White. I did this commit before you pushed the update: KENNYSOFT@07dd56e (SetItemTooltipRender.cs > lines 241, 249, 264, 270)

I have fixed this issue of white text by reverting the code as linked above.

EDIT 3:

In-game

Simulation before your update

Simulation after your update

//绘制属性变化
                Gear.StandardProps.TryGetValue(type, out value); //standard value
                if (value > 0 || Gear.Props[type] > 0)
                {
                    var propStr = ItemStringHelper.GetGearPropDiffString(type, Gear.Props[type], value);
                    GearGraphics.DrawString(g, propStr, font, 8, 256, ref picH, 15);//changes the vertical distance of stats in tooltip, such as STR, DEX, INT etc.
                    hasPart2 = true;

Before the update, it was GearGraphics.DrawString(g, propStr, font, 11, 256, ref picH, 15) (Almost everything in GearTooltipRender2.cs has 11 as value because it matched. I now changed it to 8 to match it, but as you can see the potential icon and text below is not exactly aligned.

@Kagamia
Copy link
Owner Author

@Kagamia Kagamia commented on 79c4f70 Jul 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sunaries Maybe this example will tell you how the bugs come out.

	var bmp = new Bitmap(300,100);
	var g = Graphics.FromImage(bmp);
	g.Clear(Color.Black);
	var font = new Font("Simsun", 12f, GraphicsUnit.Pixel);
	g.DrawLine(Pens.White, 9, 0, 9, 100);
	g.DrawString("测试文字", font, Brushes.White, new PointF(10,0));
	g.DrawString("测试文字", font, Brushes.White, new PointF(10,14), StringFormat.GenericTypographic);
	TextRenderer.DrawText(g, "测试文字", font, new System.Drawing.Point(10, 28), Color.White);
	TextRenderer.DrawText(g, "测试文字", font, new System.Drawing.Point(10, 42), Color.White, TextFormatFlags.NoPadding);
	bmp.Dump();

image

@Sunaries
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I'm still puzzled.

@Kagamia
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sunaries So.. maybe I missed NoPadding flags in GDI version,(Yes it's a bug and should be fixed :) ) and all of the antient GDI+(g.DrawString) codes missed StringFormat.GenericTypographic parameter, so there are two offsets in the code.

@KENNYSOFT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha, there's StringFormat.GenericTypography flag! That function is why I changed to GDI functions in KMS version. Now I can go back with GDI+.

@Sunaries
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Kagamia Adding NoPadding worked. :) Thank you.

@KENNYSOFT Ah, I see. GDI+ is more beneficial than GDI.

Please sign in to comment.