I would change the code to this:
class Window_Test < Window_Base
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
super (0,0,640,160)
self.contents = Bitmap.new (width - 32, height - 32)
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
self.contents.font.name = 'Arial'
self.contents.font.size = 22
# self.contents.font.italic = true
x = 0
# Draw all numbers
for i in 0...10
colour = Color.new ((i*80)%255, (i*60)%255, (i*100)%255, 130)
ts = self.contents.text_size (i.to_s)
ts.width += 3
bitmap = Bitmap.new (ts.width, ts.height)
bitmap.font = self.contents.font
bitmap.fill_rect (0,0,ts.width, ts.height, colour)
bitmap.draw_text (0,0,ts.width,ts.height, i.to_s)
self.contents.blt (x, 0, bitmap, Rect.new (0,0,ts.width, ts.height))
x += ts.width
end
x = 0
x2 = 0
# Draw all letters
for i in 65...91
# Get a random color
colour = Color.new ((i*20)%255, (i*30)%255, (i*60)%255, 100)
letter = i.chr
# For all uppercase letters
ts = self.contents.text_size (letter)
ts.width += 3
bitmap = Bitmap.new (ts.width, ts.height)
bitmap.font = self.contents.font
bitmap.fill_rect (0,0,ts.width, ts.height, colour)
bitmap.draw_text (0,0,ts.width,ts.height, letter)
self.contents.blt (x, 32, bitmap, Rect.new (0,0,ts.width, ts.height))
x += ts.width
# For all lowercase letters
letter.downcase!
ts = self.contents.text_size (letter)
ts.width += 3
bitmap = Bitmap.new (ts.width, ts.height)
bitmap.font = self.contents.font
bitmap.fill_rect (0,0,ts.width, ts.height, colour)
bitmap.draw_text (0,0,ts.width,ts.height, letter)
self.contents.blt (x2, 64, bitmap, Rect.new (0,0,ts.width, ts.height))
x2 += ts.width
end
# For other common characters
others = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=',
'+', "'", '"', ';', ':', '/', '?', '.', '>', '<', ',', '`',
'~', '\\', '|']
x = 0
for i in 0...others.size
char = others[i]
colour = Color.new ((i*20)%255, (i*30)%255, (i*60)%255, 100)
ts = self.contents.text_size (char)
ts.width += 3
bitmap = Bitmap.new (ts.width, ts.height)
bitmap.font = self.contents.font
bitmap.fill_rect (0,0,ts.width, ts.height, colour)
bitmap.draw_text (0,0,ts.width,ts.height, char)
self.contents.blt (x, 96, bitmap, Rect.new (0,0,ts.width, ts.height))
x += ts.width
end
end
end
This way you will also solve the problem of the text_size not giving correct values for italicized text. (It explicitly states in the help file that text_size "
Does not include the angled portions of italicized text.")
However the idea of adding +3 to the width seems to fix the problem. (I tried with font size 72, still look fine.)
The prize of this fix is slightly larger bitmaps. But it is surely much faster than any image analysis used on the bitmaps to figure out whether the letter has been squeezed or not.
It seems that you seek a general purpose solution for this. I am afraid there is no general solution.
If you really want to have one instead of just running this test to fiddle the font size correctly I suggest utilize the Factory Method pattern. Though you have to consider that the text_size method most likely has been written in C. This means that almost no matter what you do it will have a negative effect efficiency wise.
I am afraid that you will have to analyze the given string. A process that might be costly.
Though if implemented correctly all you have to do would be to create a subclass of the Creator for each font. It will require some fiddling around with each font you are to use. You can just use the script you put in here. All it takes is some time.
What I can't answer is whether such a solution would be too costly. As a guideline you can say that as long as the speed is insignificant compared to the time of drawing the text on the bitmap you are fine.