RMRK is retiring.
Registration is disabled. The site will remain online, but eventually become a read-only archive. More information.

RMRK.net has nothing to do with Blockchains, Cryptocurrency or NFTs. We have been around since the early 2000s, but there is a new group using the RMRK name that deals with those things. We have nothing to do with them.
NFTs are a scam, and if somebody is trying to persuade you to buy or invest in crypto/blockchain/NFT content, please turn them down and save your money. See this video for more information.
Text_Size Limitation

0 Members and 1 Guest are viewing this topic.

*
Rep:
Level 97
2014 Most Unsung Member2014 Best RPG Maker User - Engine2013 Best RPG Maker User (Scripting)2012 Most Mature Member2012 Favorite Staff Member2012 Best RPG Maker User (Scripting)2012 Best MemberSecret Santa 2012 ParticipantProject of the Month winner for July 20092011 Best Use of Avatar and Signature Space2011 Best RPG Maker User (Scripting)2011 Most Mature Member2011 Favourite Staff Member2011 Best Veteran2010 Most Mature Member2010 Favourite Staff Member
I have recently come to the realization that the text_size method of Bitmap sometimes does not give an accurate estimation of the actual text size in all fonts, and this is because it does not give an accurate estimation of specific letters. For this reason I wrote a little script which will display all commonly used characters and show you which letters are not accurately documented, so that you can modify the text size method in order to fix this for each font you use. For instance, when you put the font Arial at Font 22 through the script, it returns this:



and that shows that the text_sixe returned for A, V, f, v. w, /, and \ is  inaccurate. Then, all you need to do is alias text_size and adjust the width returned when the font is Arial. Anyone who wants to use it can, I've attached the demo below and I wrote up the script pretty quickly so it's kind of ugly:

Code: [Select]
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
    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)
      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 + 3
    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)
      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 + 3
      # For all lowercase letters
      letter.downcase!
      ts = self.contents.text_size (letter)
      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 + 3
    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)
      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 + 3
    end
  end
end

In any case, the problem I am encountering is whether it is worth it to write a new text_size method or just go with this. It works perfectly fine, but I am trying to think of a nice way to make a more accurate text size. So far my best idea is to make a large bitmap, draw it, then analyze each pixel row of the bitmap for the amount of pixels that have a colour other then default. It will add up the amount in each row, and then just take the row with the most non-default colors and set that as the width. However, I was wondering if anyone knew a better way then that. How does the regular text_size method function? Would my way be too time-consuming? And is it worth it given that I can use what I have already written to manually adjust for the fonts I use? Also, would my method even work properly?
« Last Edit: October 20, 2007, 11:34:48 PM by modern algebra »

*
? ? ? ? ? ? ? ? ? The nice kind of alien~
Rep:
Level 92
Martian - Occasionally kind
I would change the code to this:
Code: [Select]
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.
« Last Edit: October 23, 2007, 08:56:50 PM by Zeriab »

*
Rep:
Level 97
2014 Most Unsung Member2014 Best RPG Maker User - Engine2013 Best RPG Maker User (Scripting)2012 Most Mature Member2012 Favorite Staff Member2012 Best RPG Maker User (Scripting)2012 Best MemberSecret Santa 2012 ParticipantProject of the Month winner for July 20092011 Best Use of Avatar and Signature Space2011 Best RPG Maker User (Scripting)2011 Most Mature Member2011 Favourite Staff Member2011 Best Veteran2010 Most Mature Member2010 Favourite Staff Member
Yeah, I was looking for the general solution, but I think it will probably be best to just use my original thought and just make exceptions for each font used. I don't want to add a set number to the width simply because exactness is pretty key in the situation I want to use it in, specifically as displaying text as the usser is typing. This is simply because it draws character by character, which means whatever constant I add it to will add that constant between each letter. It would also make the Paragraph Formatter look a little goofy. Thanks for the advice, and the revision.

*
Crew Slut
Rep:
Level 93
You'll love it!
For taking a crack at the RMRK Wiki
This seems super nice and helpful!  ;8

*
? ? ? ? ? ? ? ? ? The nice kind of alien~
Rep:
Level 92
Martian - Occasionally kind
Notice that I use up the space you have placed between the letters ^_^
That way you won't have problems with letters overlapping.
Anyway, you could always use a fixed-width font :P

*
Rep:
Level 97
2014 Most Unsung Member2014 Best RPG Maker User - Engine2013 Best RPG Maker User (Scripting)2012 Most Mature Member2012 Favorite Staff Member2012 Best RPG Maker User (Scripting)2012 Best MemberSecret Santa 2012 ParticipantProject of the Month winner for July 20092011 Best Use of Avatar and Signature Space2011 Best RPG Maker User (Scripting)2011 Most Mature Member2011 Favourite Staff Member2011 Best Veteran2010 Most Mature Member2010 Favourite Staff Member
This is basically what I am considering doing:

Code: [Select]

  #------------------------------------------------------------------------
  # * Text Size (Aliased for 'Arial' Font exception)
  #------------------------------------------------------------------------
  alias arial_font_exception_size text_size
  def text_size (string)
    # Get original text size
    rect = arial_font_exception_size (string)
    if self.font.name == 'Arial'
      # Set all inaccurate letters in an array
      bad_letters == ['A', 'V', 'f', 'v', 'w', '/', "\\"]
      for i in 0...string.size
        if bad_letters.include? (string[i,1])
          # Add 1 to the width for each of the offending characters in the string
          rect.width += 1
          # Add an additional pixel for each f
          rect.width += 1 if string[i,1] == 'f'
        end
      end
    end
    return rect
  end

And when the Paragraph Formatter is ready and the Journal is ready, I will just give them the script I wrote here and instruct them in writing codes like this to add to make the widths appropriate. I think that will probably be the quickest way to get a correct text_size. Maybe I should use a Table :P
« Last Edit: October 26, 2007, 09:07:41 PM by modern algebra »

*
? ? ? ? ? ? ? ? ? The nice kind of alien~
Rep:
Level 92
Martian - Occasionally kind
You have an error in that text: 'bad_letters == ['A', 'V', 'f', 'v', 'w', '/', "\\"]'
Should be 'bad_letters = ['A', 'V', 'f', 'v', 'w', '/', "\\"]'

Nah, don't use a Table.
Instead you should use a binary search tree.
Considering how few bad letters there are this might simply be an overkill.

Another thing you didn't include was if the font were italicized. In that case you should add +2 to the width regardless of them being bad letters or not.

*
Rep:
Level 97
2014 Most Unsung Member2014 Best RPG Maker User - Engine2013 Best RPG Maker User (Scripting)2012 Most Mature Member2012 Favorite Staff Member2012 Best RPG Maker User (Scripting)2012 Best MemberSecret Santa 2012 ParticipantProject of the Month winner for July 20092011 Best Use of Avatar and Signature Space2011 Best RPG Maker User (Scripting)2011 Most Mature Member2011 Favourite Staff Member2011 Best Veteran2010 Most Mature Member2010 Favourite Staff Member
Ah, yeah, I forgot about italicized. Thanks for reminding me. And yeah, I figured out the problem with bad_letters when I tested and it threw me an uninitialized local variable error. Thanks for noticing that though.

I think I'll just add in the line:

rect.width += 2*string.size if self.font.italic

Thanks for reminding me