基本位图字体渲染
虽然我过去曾提出过这样的主题,但这从头到尾都是位图字体渲染的最基本方法。我希望有人能看到我在这里做错了什么。
虽然这是一篇很长的文章,但如果 Bug#1 得到修复,它就可以解决所有问题。此问题涉及 C#(Bug#1)和 C++(Bug#2、Bug#3)。
对于位图字体渲染,我做了两件事
1) 在 C# 中创建大小为 2056x2056 的位图。我首先在 512x512 图像上绘制一个字符,然后将图像大小调整为 128。我这样做的原因是我可以稍后向文本添加效果。这也引入了 Bug #1(见下文)。
2) 为每个字符渲染一个单独的矩形(参见 Bug#2 和 Bug#3)。
我遇到的问题是正确渲染序列中的单个字符。要么存在 UV 问题,要么存在字母间距问题。现在讨论 Bug
#1:字体大小 我渲染到 512px 图形上的字体是 120。图形大小将调整为 128,小了 4 倍。因此,我希望字体大小为 30。保存位图后,我将在 GIMP 中查看它以进行调查。我要做的一件事是在位图中的字符上绘制 GIMP 中的字符。这会产生有趣的结果,尽管我不确定它是否错误。正如您从下图中看到的,正确的绘制方式是让 GIMP 在“30 pt”处绘制字符,但是,如果我在“30px”处绘制它,它会小得多。之所以如此重要,是因为稍后在 C++ 中我会将地图模式设置为“SetMapMode(dc,MM_TEXT);”。虽然,MSDN 详细说明,MM_TEXT 是“每个逻辑单元映射到一个设备像素”。
事实证明,GIMP 将“30pt”翻译为“40px”。因此,对于我的 C++ 代码,当我将 MapMode 设置为像素文本设置时,我将创建大小为“40”的字体。这就是为什么首先修复错误是如此重要。如果这个 bug 得到修复,那么它就可以修复 bug #1 和 #2。
我对 Bug #1 的问题是,出了什么问题?我应该将地图模式设置为其他模式吗?我将把角色绘制成 512px 的图形,然后调整图形的大小。这是关键的一步,因此我可能会对角色的较大版本进行效果。
Bug#2:紫外线 由于我每 128 个像素存储一次字符,因此很容易获取每个字符的位图 X/Y 值。然而,我不确定将 UV 推进多远才能正确绘制它们。我尝试基本上做类似 Promit 为 AngelCode 位图字体渲染发布的事情,但是,因为我不确定它们如何生成它们的值,所以我在这里可能是错的。您可以在下面的两张图片中看到我计算的 UV 是错误的。
我对 Bug#2 的问题是,如何正确推进 UV?我找到位图 X/Y 的方式没有任何问题,只是我移动它们进行渲染的方式没有问题。
Bug #3:字母放置 我不知道如何正确移动我的角色,甚至不知道如何正确获取距离。目前我只做“A + B + C”。这张地图看起来是正确的,但是,如果您查看下面的 Arial 图像,您会发现“j”在“n”和“f”之间看起来不合适。 Arial 的“b”和“y”似乎也存在问题,Times New Roman 也存在一些问题。
我对 Bug #3 的问题是,我怎样才能正确地提升我的角色?
Arial 渲染:
泰晤士新罗马字体:
值得注意的是,我对使用任何外部库(例如 FreeType)或任何“黑客”来执行此操作不感兴趣。我希望看到使用 windows api 正确完成此操作。做其中任何一个都没有讨论的余地,如果我想使用它们,我很久以前就可以完成了。
由于板上的源代码标签已损坏,我将在 Pastebins 中发布示例源代码。
C#(位图绘制):http://pastebin.com/zpPPZVm0 C++(字体渲染):http://pastebin.com/mHrUatEb
While I have made a topic like this in the past, this is from start to finish the most basic approach to bitmap font render. I am hoping someone can see what I am doing wrong here.
Although this is a long post, if Bug#1 gets fixed, it could fix everything. This question deals with C# (Bug#1) and C++ (Bug#2, Bug#3).
For bitmap font rendering I am doing two things
1) Creating a bitmap that is the size 2056x2056 in C#. I am first drawing a character onto a 512x512 image, then I am resizing the image to 128. The reason I am doing this is so I may add affects to the text later. This also introduces Bug #1 (see below).
2) Rendering an individual rectangle for each character (see Bug#2 and Bug#3).
The problem I am having is rendering invidual characters in a sequence correctly. There will either be UV's issues, or letter spacing issues. Now onto the bugs
Bug #1: Font Size
The font that I render onto the 512px graphic is 120. The size that the graphic will be resize to is 128, which is 4 times small. There for, I would expect the font size to be 30. After I save the bitmap, I will look at it in GIMP to investigate. One thing I will do is draw a character from GIMP over a character in my bitmap. This will give interesting results, although I am not sure it is wrong or not. As you can see from the image below, the correct draw over is to have GIMP draw the character at "30 pt", however, if I draw it at "30px" it is significantly smaller. The reason why this is so important is because later in C++ I will set the map mode to "SetMapMode(dc,MM_TEXT);". Although, detailed by MSDN, MM_TEXT is "Each logical unit is mapped to one device pixel".
It turns out that GIMP translates "30pt" to "40px". As a result, for my C++ code I will be creating fonts with size "40" as I am setting my MapMode to a pixel text setting. This is why it is so important that is bug gets fixed first. If this bug were to get fixed, then it could fix bugs #1 and #2.
My question to Bug #1, what is going wrong? Should I be setting the map mode to something else? I will draw the character to a 512px graphic, then resize the graphic. This is a critical step so I may do effects to the larger version of the character.
Bug #2: UV's
Since I store my characters every 128 pixels, it is very easy to obtain the bitmap X/Y values for each character. However, I am not sure how far to advance the UV's to properly draw them. I tried basically doing something like Promit posted for AngelCode bitmap font render, however, since I am not sure how they generate their values, I may be wrong here. You can see in the two images below that I am calculating my UV's wrong.
My question to Bug#2, how can I correctly advance my UV's? There is nothing wrong with the way I find the bitmap X/Y, only how I move them for rendering.
Bug #3: Letter placement
I am not sure how to correct move my characters or even correctly get the distance. Currently I just do "A +B + C". This map seem correct, however, if you look at the Arial image below, the "j" looks out of place inbetween the "n" and "f". There is also what appears to be issues with "b" and "y" for Arial, along with some issues for Times New Roman.
My question to Bug #3, how can I properly advance my characters?
Arial Rendering:
Times New Roman:
It is worth noting that I am not interested in using any external libraries (such as FreeType), or any "hacks" to do this. I want to see this done correctly using the windows api. Doing either one of these is not up for discussion, if I wanted to use them I could have been done with this a long time ago.
Since the source tags in the board are broken, I will post the example source in pastebins.
C# (Bitmap drawing) : http://pastebin.com/zpPPZVm0
C++ (Font rendering) : http://pastebin.com/mHrUatEb
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
1 - 点和像素是不同的单位。所以那里没有错误。搜索“字体点像素”以获取解释。
3 - 对于比例字体(如 Arial),每个字符具有不同的宽度。在更高级的场景中,字符组合可以具有与其各个宽度之和不同的宽度。您可以开始阅读 MeasureString (http://msdn. microsoft.com/en-us/library/system.drawing.graphics.measurestring.aspx)并阅读有关字体渲染的相关文章。
1 - points and pixels are different units. So there is no bug there. Search for "fonts points pixels" for explanations.
3 - For proportional fonts (like Arial) each character have different width. In more advanced sceanrios combinations of characters can have different width compared to the sum of their individual widths. You can start reading at MeasureString ( http://msdn.microsoft.com/en-us/library/system.drawing.graphics.measurestring.aspx) and read related articles on font rendering.