Pages: 1 2 3 4
Author Topic: GML: All draw_text functions +(string_width, _height, _width_ext, _height_ext)  (251,075 Views)
Offline (Unknown gender) TheExDeus

Developer
Joined: Apr 2008
Posts: 1,860
View profile
Reply #45 Posted on: July 09, 2011, 08:12:37 PM
QuoteThat code doesn't consider newlines.
Yes, the full code is this (tested and works):
void draw_text(int x,int y,string str)
{
  font *fnt = fontstructarray[currentfont];

  if (bound_texture != fnt->texture)
    glBindTexture(GL_TEXTURE_2D, bound_texture = fnt->texture);

  int xx, yy = y+fnt->yoffset, line = 0;
  if (halign == fa_left){
    xx = x;
  }else if (halign == fa_middle){
    xx = x-string_width_line(str,0)/2;
  }else{ //fa_right
    xx = x-string_width_line(str,0);
  }
  glBegin(GL_QUADS);
  for (unsigned i = 0; i < str.length(); i++)
  {
    if (str[i] == '\r'){
      line +=1, yy += fnt->height, i += str[i+1] == '\n';
      if (halign == fa_left){
          xx = x;
      }else if (halign == fa_middle){
          xx = x-string_width_line(str,line)/2;
      }else{ //fa_right
          xx = x-string_width_line(str,line);
      }
    }else if (str[i] == '\n'){
      line +=1, yy += fnt->height;
      if (halign == fa_left){
          xx = x;
      }else if (halign == fa_middle){
          xx = x-string_width_line(str,line)/2;
      }else{ //fa_right
          xx = x-string_width_line(str,line);
      }
    }else if (str[i] == ' ')
      xx += fnt->height/3; // FIXME: what's GM do about this?
    else
    {
      fontglyph &g = fnt->glyphs[(unsigned char)(str[i] - fnt->glyphstart) % fnt->glyphcount];
        glTexCoord2f(g.tx,  g.ty);
          glVertex2i(xx + g.x,  yy + g.y);
        glTexCoord2f(g.tx2, g.ty);
          glVertex2i(xx + g.x2, yy + g.y);
        glTexCoord2f(g.tx2, g.ty2);
          glVertex2i(xx + g.x2, yy + g.y2);
        glTexCoord2f(g.tx,  g.ty2);
          glVertex2i(xx + g.x,  yy + g.y2);
      xx += g.xs;
    }
  }
  glEnd();
}
QuoteNot having the code as fa_left fucks everything up, efficiency wise.
Agreed.
QuoteYou're best to fork up front.
Could you elaborate? You mean having separate drawing functions for all six alignments? Then how will that be backwards compatible with GM? Or how will draw_set_halign/valign actually work in that case?
QuoteThere should be functions added for draw_get_halign / valign these are missing from gml.
I will. That is easy.

edit: Also, why do I need this:    if (str[i] == '\r')
      xx = x, yy += fnt->height, i += str[i+1] == '\n';
    else if (str[i] == '\n')
      xx = x, yy += fnt->height;
and can't have simply:    if (str[i] == '\r' or str[i] == '\n')
      xx = x, yy += fnt->height;
I left that in legacy sake and I know that there are several end line characters, but why I have to  i += str[i+1] == '\n' which actually doesn't make sense (I insert \n as far as I know, but that's funny way to write that). This part was written by Josh or TGMG a long time ago.
Offline (Unknown gender) Josh @ Dreamland

Prince of all Goldfish
Developer
Joined: Feb 2008
Posts: 2,950
View profile
Reply #46 Posted on: July 09, 2011, 08:39:00 PM
QuoteCould you elaborate? You mean having separate drawing functions for all six alignments? Then how will that be backwards compatible with GM? Or how will draw_set_halign/valign actually work in that case?
No, just put the original function in a big if for align being top-left, and then put the rest of the code in the else with whatever hackery is required, that way you don't have to iterate the string for draw_text() when the aligns are default.

QuoteAlso, why do I need this: ...
Otherwise, \r\n will put two newlines, or if you place ", u+= str[i]=='\n';" at the end of the proposed replacement, '\n\n' will be treated as one line.
Offline (Unknown gender) TheExDeus

Developer
Joined: Apr 2008
Posts: 1,860
View profile
Reply #47 Posted on: July 09, 2011, 09:14:22 PM
QuoteNo, just put the original function in a big if for align being top-left, and then put the rest of the code in the else with whatever hackery is required, that way you don't have to iterate the string for draw_text() when the aligns are default.
So like this?
void draw_text(int x,int y,string str)
{
  font *fnt = fontstructarray[currentfont];

  if (bound_texture != fnt->texture)
    glBindTexture(GL_TEXTURE_2D, bound_texture = fnt->texture);

  if (halign == fa_left){
      int xx = x, yy = y+fnt->yoffset;
      glBegin(GL_QUADS);
      for (unsigned i = 0; i < str.length(); i++)
      {
        if (str[i] == '\r')
          xx = x, yy += fnt->height, i += str[i+1] == '\n';
        else if (str[i] == '\n')
          xx = x, yy += fnt->height;
        else if (str[i] == ' ')
          xx += fnt->height/3; // FIXME: what's GM do about this?
        else
        {
          fontglyph &g = fnt->glyphs[(unsigned char)(str[i] - fnt->glyphstart) % fnt->glyphcount];
            glTexCoord2f(g.tx,  g.ty);
              glVertex2i(xx + g.x,  yy + g.y);
            glTexCoord2f(g.tx2, g.ty);
              glVertex2i(xx + g.x2, yy + g.y);
            glTexCoord2f(g.tx2, g.ty2);
              glVertex2i(xx + g.x2, yy + g.y2);
            glTexCoord2f(g.tx,  g.ty2);
              glVertex2i(xx + g.x,  yy + g.y2);
          xx += g.xs;
        }
      }
      glEnd();
  }else{
      int xx, yy = y+fnt->yoffset, line = 0;
      if (halign == fa_middle){
        xx = x-string_width_line(str,0)/2;
      }else{ //fa_right
        xx = x-string_width_line(str,0);
      }
      glBegin(GL_QUADS);
      for (unsigned i = 0; i < str.length(); i++)
      {
        if (str[i] == '\r'){
          line +=1, yy += fnt->height, i += str[i+1] == '\n';
          if (halign == fa_middle){
              xx = x-string_width_line(str,line)/2;
          }else{ //fa_right
              xx = x-string_width_line(str,line);
          }
        }else if (str[i] == '\n'){
          line +=1, yy += fnt->height;
          if (halign == fa_middle){
              xx = x-string_width_line(str,line)/2;
          }else{ //fa_right
              xx = x-string_width_line(str,line);
          }
        }else if (str[i] == ' ')
          xx += fnt->height/3; // FIXME: what's GM do about this?
        else
        {
          fontglyph &g = fnt->glyphs[(unsigned char)(str[i] - fnt->glyphstart) % fnt->glyphcount];
            glTexCoord2f(g.tx,  g.ty);
              glVertex2i(xx + g.x,  yy + g.y);
            glTexCoord2f(g.tx2, g.ty);
              glVertex2i(xx + g.x2, yy + g.y);
            glTexCoord2f(g.tx2, g.ty2);
              glVertex2i(xx + g.x2, yy + g.y2);
            glTexCoord2f(g.tx,  g.ty2);
              glVertex2i(xx + g.x,  yy + g.y2);
          xx += g.xs;
        }
      }
      glEnd();
  }
}
Offline (Unknown gender) Josh @ Dreamland

Prince of all Goldfish
Developer
Joined: Feb 2008
Posts: 2,950
View profile
Reply #48 Posted on: July 09, 2011, 09:33:03 PM
Yep. That way, string_width is never called for simple left-aligned text.
Offline (Unknown gender) TheExDeus

Developer
Joined: Apr 2008
Posts: 1,860
View profile
Reply #49 Posted on: July 09, 2011, 10:07:07 PM
It actually wasn't called in the previous example code either. Though there was an if statement at every newline character while in this code there isn't. So that's something I guess. Now about valign. That actually requires a lot less code, and it doesn't require anything in the for loop. So should I write like this:
void draw_text(int x,int y,string str)
{
  font *fnt = fontstructarray[currentfont];

  if (bound_texture != fnt->texture)
    glBindTexture(GL_TEXTURE_2D, bound_texture = fnt->texture);

  if (halign == fa_left){
      int xx = x, yy = y+fnt->yoffset;
      if (valign == fa_middle)
        yy -= string_height(str)/2;
      else if (valign == fa_bottom)
        yy -= string_height(str);
      glBegin(GL_QUADS);
      for (unsigned i = 0; i < str.length(); i++)
      {
        if (str[i] == '\r')
          xx = x, yy += fnt->height, i += str[i+1] == '\n';
        else if (str[i] == '\n')
          xx = x, yy += fnt->height;
        else if (str[i] == ' ')
          xx += fnt->height/3; // FIXME: what's GM do about this?
        else
        {
          fontglyph &g = fnt->glyphs[(unsigned char)(str[i] - fnt->glyphstart) % fnt->glyphcount];
            glTexCoord2f(g.tx,  g.ty);
              glVertex2i(xx + g.x,  yy + g.y);
            glTexCoord2f(g.tx2, g.ty);
              glVertex2i(xx + g.x2, yy + g.y);
            glTexCoord2f(g.tx2, g.ty2);
              glVertex2i(xx + g.x2, yy + g.y2);
            glTexCoord2f(g.tx,  g.ty2);
              glVertex2i(xx + g.x,  yy + g.y2);
          xx += g.xs;
        }
      }
      glEnd();
  }else{
      int xx, yy = y+fnt->yoffset, line = 0;
      if (valign == fa_middle)
        yy -= string_height(str)/2;
      else if (valign == fa_bottom)
        yy -= string_height(str);
      if (halign == fa_center){
        xx = x-string_width_line(str,0)/2;
      }else{ //fa_right
        xx = x-string_width_line(str,0);
      }
      glBegin(GL_QUADS);
      for (unsigned i = 0; i < str.length(); i++)
      {
        if (str[i] == '\r'){
          line +=1, yy += fnt->height, i += str[i+1] == '\n';
          if (halign == fa_center){
              xx = x-string_width_line(str,line)/2;
          }else{ //fa_right
              xx = x-string_width_line(str,line);
          }
        }else if (str[i] == '\n'){
          line +=1, yy += fnt->height;
          if (halign == fa_center){
              xx = x-string_width_line(str,line)/2;
          }else{ //fa_right
              xx = x-string_width_line(str,line);
          }
        }else if (str[i] == ' ')
          xx += fnt->height/3; // FIXME: what's GM do about this?
        else
        {
          fontglyph &g = fnt->glyphs[(unsigned char)(str[i] - fnt->glyphstart) % fnt->glyphcount];
            glTexCoord2f(g.tx,  g.ty);
              glVertex2i(xx + g.x,  yy + g.y);
            glTexCoord2f(g.tx2, g.ty);
              glVertex2i(xx + g.x2, yy + g.y);
            glTexCoord2f(g.tx2, g.ty2);
              glVertex2i(xx + g.x2, yy + g.y2);
            glTexCoord2f(g.tx,  g.ty2);
              glVertex2i(xx + g.x,  yy + g.y2);
          xx += g.xs;
        }
      }
      glEnd();
  }
}
Or split again? The code size will double if I split.
edit: Fixed "thou" into "though". I know I use it wrong, but no one corrects me so its hard to learn.
Anyway, sleep time. If this code is good then I will implement draw_set_halign and valign tomorrow. There will just be a question about declarations out of the functions (because I need to declare fa_ constants in both .h and .cpp file.. more on that later).
Offline (Unknown gender) Josh @ Dreamland

Prince of all Goldfish
Developer
Joined: Feb 2008
Posts: 2,950
View profile
Reply #50 Posted on: July 10, 2011, 01:46:59 AM
How on earth does valign have any effect on draw_text? O_o
If it just centers the text around the given y coordinate, then there's no need to fork again. Just set the initial yy to valign == fa_top ? y : valign == fa_middle ? y - string_height(str)/2 : y - string_height(str).

And yeah, it's "though." But no one really cares if you abbreviate, even unintentionally. :P
Offline (Unknown gender) TheExDeus

Developer
Joined: Apr 2008
Posts: 1,860
View profile
Reply #51 Posted on: July 10, 2011, 12:52:15 PM
Quotevalign == fa_top ? y : valign == fa_middle ? y - string_height(str)/2 : y - string_height(str)
That's basically what I did, though I typed the whole if statement. Does it actually increase speed with using the shorter if statement then the long one?
The end code is this:
void draw_text(int x,int y,string str)
{
  font *fnt = fontstructarray[currentfont];

  if (bound_texture != fnt->texture)
    glBindTexture(GL_TEXTURE_2D, bound_texture = fnt->texture);
  int yy = valign == fa_top ? y+fnt->yoffset : valign == fa_middle ? y +fnt->yoffset - string_height(str)/2 : y + fnt->yoffset - string_height(str);
  if (halign == fa_left){
      int xx = x;
      glBegin(GL_QUADS);
      for (unsigned i = 0; i < str.length(); i++)
      {
        if (str[i] == '\r')
          xx = x, yy += fnt->height, i += str[i+1] == '\n';
        else if (str[i] == '\n')
          xx = x, yy += fnt->height;
        else if (str[i] == ' ')
          xx += fnt->height/3; // FIXME: what's GM do about this?
        else
        {
          fontglyph &g = fnt->glyphs[(unsigned char)(str[i] - fnt->glyphstart) % fnt->glyphcount];
            glTexCoord2f(g.tx,  g.ty);
              glVertex2i(xx + g.x,  yy + g.y);
            glTexCoord2f(g.tx2, g.ty);
              glVertex2i(xx + g.x2, yy + g.y);
            glTexCoord2f(g.tx2, g.ty2);
              glVertex2i(xx + g.x2, yy + g.y2);
            glTexCoord2f(g.tx,  g.ty2);
              glVertex2i(xx + g.x,  yy + g.y2);
          xx += g.xs;
        }
      }
      glEnd();
  }else{
      int xx = halign == fa_center ? x-string_width_line(str,0)/2 : x-string_width_line(str,0), line = 0;
      glBegin(GL_QUADS);
      for (unsigned i = 0; i < str.length(); i++)
      {
        if (str[i] == '\r'){
          line +=1, yy += fnt->height, i += str[i+1] == '\n';
          xx = halign == fa_center ? x-string_width_line(str,line)/2 : x-string_width_line(str,line);
        }else if (str[i] == '\n'){
          line +=1, yy += fnt->height;
          xx = halign == fa_center ? x-string_width_line(str,line)/2 : x-string_width_line(str,line);
        }else if (str[i] == ' ')
          xx += fnt->height/3; // FIXME: what's GM do about this?
        else
        {
          fontglyph &g = fnt->glyphs[(unsigned char)(str[i] - fnt->glyphstart) % fnt->glyphcount];
            glTexCoord2f(g.tx,  g.ty);
              glVertex2i(xx + g.x,  yy + g.y);
            glTexCoord2f(g.tx2, g.ty);
              glVertex2i(xx + g.x2, yy + g.y);
            glTexCoord2f(g.tx2, g.ty2);
              glVertex2i(xx + g.x2, yy + g.y2);
            glTexCoord2f(g.tx,  g.ty2);
              glVertex2i(xx + g.x,  yy + g.y2);
          xx += g.xs;
        }
      }
      glEnd();
  }
}

QuoteBut no one really cares if you abbreviate
That's not an abbreviation, I just thought its how its spelled. The word thou is a second person singular pronoun in English.
Offline (Unknown gender) IsmAvatar

LateralGM Developer
LGM Developer
Joined: Apr 2008
Posts: 877
View profile
Reply #52 Posted on: July 10, 2011, 04:51:40 PM
QuoteThat's not an abbreviation, I just thought its how its spelled. The word thou is a second person singular pronoun in English.
It is now largely archaic.

"Thou shalt not eat from the tree of knowledge."
Nobody talks like that anymore unless you're trying to sound biblical. In other contexts, if you use the word "thou" or "tho", we assume you're abbreviating "though" (actually, the more recognized abbreviation on the interwebs is "tho", so we assume the "u" is an accidental extra).
Pages: 1 2 3 4