设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 2953|回复: 20
打印 上一主题 下一主题

[交流讨论] 关于Bitmap#draw_text的压缩比例

[复制链接]

Lv5.捕梦者 (版主)

梦石
28
星屑
10170
在线时间
4673 小时
注册时间
2011-8-22
帖子
1279

开拓者

跳转到指定楼层
1
发表于 2018-8-23 08:02:13 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
关于draw_text,F1帮助是这么写的:
“If the text length exceeds the box's width, the text width will automatically be reduced by up to 60 percent.”
“如果文字长度超过了框的宽度(draw_text里的宽度参数),文字宽度会自动压缩到至多60%。”


这是我的测试结果。数字表示绘制Hello的时候用的宽度参数。可以看到文字被压缩了,但并不是一次性压缩到60%,也不是直接根据宽度连续变化的(因为有的时候压缩比例不变,比如44和46)。
目前RGD在这里的处理暂时还有点问题,不知道有没有人研究过这个缩放,有没有具体的计算公式可以用?

Lv3.寻梦者

梦石
0
星屑
1934
在线时间
403 小时
注册时间
2015-8-30
帖子
395
2
发表于 2018-8-23 10:52:04 | 只看该作者
本帖最后由 有丘直方 于 2018-8-23 11:22 编辑

我感觉EB的RGSS在draw_text的文字压缩处理方面做得不好,不建议走EB的那一套

RGSS3测试代码:
RUBY 代码复制
  1. rows = Graphics.height / Font.default_size
  2. columns = 3
  3. column_width = Graphics.width / columns
  4. text = "Hello"
  5. max_width = 65
  6. bitmap_width = 100
  7.  
  8. sprites = []
  9. bitmaps = []
  10. (0...(rows * columns)).each do |i|
  11.   bitmaps[i] = Bitmap.new(bitmap_width, Font.default_size)
  12.   bitmaps[i].draw_text(0, 0, max_width - i, Font.default_size, text)
  13.   bitmaps[i].draw_text(0, 0, bitmap_width, Font.default_size, max_width - i, 2)
  14.   sprites[i] = Sprite.new
  15.   sprites[i].bitmap = bitmaps[i]
  16.   sprites[i].y = i % rows * Font.default_size
  17.   sprites[i].x = i / rows * column_width
  18. end
  19. p bitmaps[0].text_size(text).width
  20.  
  21. loop { Graphics.update }
测试结果(这是张544*416大小的图):

控制台输出:
代码复制
  1. 60
帮助文档信息:
テキストの長さが矩形の幅を超える場合は、幅を 60% まで自動的に縮小して描画します。
若文字长度超过区域的宽度,文字宽度会自动缩小到 60%。
根据帮助文档所说,当以下代码返回true时
RUBY 代码复制
  1. width < bitmap.text_size(text).width
绘制的文字的宽度将会是原来的60%
然而实际上,确实如楼主所说,宽度并不会一下子缩小到60%

从测试结果来看,实际上还没等绘制文字的宽度小于文字宽度时,实际绘制的文字宽度就开始减小了
比如在本次测试中,文字Hello的宽度在正常情况下应该是控制台所说的60,经过测量也确实是60
不过可以看到,当绘制的宽度为61时,文字的宽度就已经开始缩水了,尽管此时还是可以笃定地画的
经过测量,此时文字宽度变成了42,也就是原来的70%

第二次缩水在绘制的文字的宽度为56时出现,变成了36,也就是原来的60%
此时已经达到了帮助文档所说的60%了,但是文字宽度还会再缩小
当绘制宽度为50时,成功缩水到了50%

此后宽度不会再缩水了,因此当绘制文字的宽度小于正常宽度的50%时,文字就会开始残缺
可以看到当宽度为29时,文字残缺了一块

结论:帮助文档完全在瞎写八写,而且文字缩小机制非常愚蠢地浪费大量位图空间
小仙女一枚~
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (版主)

梦石
28
星屑
10170
在线时间
4673 小时
注册时间
2011-8-22
帖子
1279

开拓者

3
 楼主| 发表于 2018-8-23 12:11:19 | 只看该作者
有丘直方 发表于 2018-8-23 10:52
我感觉EB的RGSS在draw_text的文字压缩处理方面做得不好,不建议走EB的那一套
RGSS3测试代码:rows = Graphi ...

感谢测试结果!
因为一些已有的工程会受到这方面影响,所以只能尽量还原RGSS的默认行为了,请见谅吧。

这些里面我觉得最有趣的是62还能维持100%大小,到61就已经缩小到了70%以下。但是在我那个例子里48->46是缩小到了80%以上。说明比例不是由两者的差或者比值决定的。可能还有一些其他的影响因素甚至常量。这样关系就复杂了……
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (版主)

遠航の猫咪

梦石
3
星屑
22437
在线时间
2335 小时
注册时间
2005-10-15
帖子
1160

开拓者

4
发表于 2018-8-23 23:09:12 | 只看该作者
本帖最后由 SailCat 于 2018-8-24 11:00 编辑

看来这是RGSS3的bug, RGSS1和2的表现和有丘直方说的是一样的
(已编辑在楼下)
SailCat (小猫子·要开心一点) 共上站 24 次,发表过 11 篇文章 上 次 在: [2006年01月28日11:41:18 星期六] 从 [162.105.120.91] 到本站一游。
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
13559
在线时间
2753 小时
注册时间
2014-10-4
帖子
756

R考场第七期纪念奖

5
发表于 2018-8-23 23:45:48 | 只看该作者
本帖最后由 SixRC 于 2018-8-24 10:23 编辑

缩放机制大致上是这样的
传入宽和字符串
先根据字符串用 GetGlyphOutline 计算出需要的总宽度  假如要描边 把这个宽度加上 2 得到新的总宽
比较传入的宽度和总宽度 若大于等于则跳
若小于则得到缩放系数 = 传入宽/总宽 - 0.15
将缩放系数和 0.6 比较 若小于则调整为 0.6
根据这个系数结合字体高等数据计算新的字体宽再通过 CreateFontIndirect 生成新字体   这我不太懂 对这些函数没有研究
它的公式是 字体宽 = 字体高 * 系数 * 7 / 16      这里的字体宽大概就是一个均宽 是得到具体字数据的一个参数  16 和 7 分别是 GetTextMetrics 得到的 tmHeight 和 tmAveCharWidth 最初默认的字体高和宽?
这个宽会截断为整数 例如 24(高)*0.76*7/16 = 7.98 会截取为 7 作为字宽
所以虽然系数最低是 0.6 但是输出后可能最低不止这样 (即 0.6 不是最终的系数 缩放不是直接缩成 0.6 的)
再重新计算总宽
根据这个结果绘制字体 超出部分不画了

总体来讲就是  传入宽+所需宽 => 缩放系数 => 绘制字的宽度系数 => 输出

点评

嗯 谢谢 没注意到 已修改  发表于 2018-8-24 10:24
当且仅当描边为true时加2  发表于 2018-8-24 10:02
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (版主)

梦石
28
星屑
10170
在线时间
4673 小时
注册时间
2011-8-22
帖子
1279

开拓者

6
 楼主| 发表于 2018-8-24 07:34:01 | 只看该作者
SixRC 发表于 2018-8-23 23:45
缩放机制大致上是这样的
传入宽和字符串
先根据字符串用 GetGlyphOutline 计算出需要的总宽度 把这个宽度加 ...

经过修正以后我也用上了宽度比例-0.15的计算方法,得到了似乎“比RM更连续变化”的结果。
“四舍五入为整数”这一步比较在意,可能这就是RM在44和46下宽度一样的原因。但这里的转换过程请问是什么样的?零点几的浮点数,莫非是直接转成8位的整数?否则不至于精度损失这么大……
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (版主)

遠航の猫咪

梦石
3
星屑
22437
在线时间
2335 小时
注册时间
2005-10-15
帖子
1160

开拓者

7
发表于 2018-8-24 08:15:17 | 只看该作者
本帖最后由 SailCat 于 2018-8-24 09:50 编辑

可以参考下RGSS1和2的draw_text实现,这个是没有上面所说问题的

测试代码如下,注意text_size返回的是60,这点和RGSS3一样

RUBY 代码复制
  1. Font.default_size = 24
  2.  
  3.  
  4. b = Bitmap.new(640, 480)
  5. s = Sprite.new
  6. s.bitmap = b
  7. s.x = 0
  8. s.y = 0
  9.  
  10.  
  11. 75.downto(16) do |i|
  12.   b.draw_text((75 - i) / 20 * 210, (75 - i) % 20 * 24, i, 24, "Hello", 0)
  13.   b.draw_text((75 - i) / 20 * 210 + 100, (75 - i) % 20 * 24, 24, 24, i.to_s, 0)
  14. end


另外请注意一下,不到60就开始缩小的原因,是否因为在RGSS3开启了描边模式(默认开启)?
经测试:不到60就开始缩小的原因就是这个

以下描边模式设为true



以下描边模式设为false

点评

我不知道你说的“连续变化”是什么意思,在RGSS1中,当绘制不下时,宽度是1像素1像素往下减的,减到合适(或下限60%)为止,但是在RGSS3中不是如此  发表于 2018-8-24 10:43
感谢测试。我觉得还是有上面提到的问题:49-45,以及44-40的时候文字的长度都一样,但明明绘制的宽度已经改变了……  发表于 2018-8-24 08:19
SailCat (小猫子·要开心一点) 共上站 24 次,发表过 11 篇文章 上 次 在: [2006年01月28日11:41:18 星期六] 从 [162.105.120.91] 到本站一游。
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
13559
在线时间
2753 小时
注册时间
2014-10-4
帖子
756

R考场第七期纪念奖

8
发表于 2018-8-24 10:14:25 | 只看该作者
⑨姐姐 发表于 2018-8-24 07:34
经过修正以后我也用上了宽度比例-0.15的计算方法,得到了似乎“比RM更连续变化”的结果。
“四舍五入为整 ...

是直接截断为整数的 24(高)*0.76(系数)*7/16=7.98 截取为 7
是用了 cvttsd2si 这个指令
昨天四舍五入是猜的 原来是直接截断

点评

嗯 是的  发表于 2018-8-24 10:48
突然理解了,是不是RM需要让每个文字都“等量”地缩放,而不是对整体进行一次缩放?  发表于 2018-8-24 10:46
是啊,我也觉得数字可以那么解释,但和我们需要的“功能”并不是那么相关……  发表于 2018-8-24 10:36
一点是为什么不直接取绘制的字高的字宽去乘那个系数 一点是为什么不四舍五入 挺奇怪的  发表于 2018-8-24 10:29
那个 16 和 7 我有解释的 就是默认的字高和字宽 rm 单纯的作了一个 字高/字高*字宽=字宽 的处理...虽然感觉不太好  发表于 2018-8-24 10:26
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (版主)

遠航の猫咪

梦石
3
星屑
22437
在线时间
2335 小时
注册时间
2005-10-15
帖子
1160

开拓者

9
发表于 2018-8-24 10:40:23 | 只看该作者
本帖最后由 SailCat 于 2018-8-24 11:02 编辑

反复测试了不同初始字号下的最小字宽(均为显示"Hello")
字号  原始字宽  最小字宽
16     8              4
17     9              5
18     9              5
19     10            6
20     10            6
21     11            6
22     11            6
23     12            7
24     12            7
25     13            7
26     13            7
27     14            8
28     14            8
29     15            9
30     15            9

非等宽字体我没条件测试。手头的vl gothic也是等宽的。


上面字号=30的情况,似乎也不是连续变化,而是15-13-12-10-9
感觉是
100%(15)-90%(13.5即13)-80%(12)-70%(10.5即10)-60%(9)
共5级变化

但在RGSS3中,情况又不一样了

第一个不同是可以看到,第一次缩放就从字宽15直接变成了10,然后9,8,7……
而在RGSS1/2中,字宽的缩放是按百分比依次-10%的
第二个不同是,字宽的下限不仅不是60%,而且远低于60%,连50%也不到
而在RGSS1/2中,字宽的下限是严格的60%(向下取整)
第三个不同是,除第一次缩小的节点是放不下(74)以外,以后的字宽缩小节点,根本和是否放的下没有一毛钱关系
而在RGSS1/2中,字宽缩小的节点一定是放不下

点评

但在RGSS3中,情况完全不是那么回事……  发表于 2018-8-24 10:57
确实和字宽有关的话可以解释RM那个公式……  发表于 2018-8-24 10:45
SailCat (小猫子·要开心一点) 共上站 24 次,发表过 11 篇文章 上 次 在: [2006年01月28日11:41:18 星期六] 从 [162.105.120.91] 到本站一游。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-4-26 00:57

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表