Page 1 of 2 12 LastLast
Results 1 to 10 of 16

Thread: word wrap? no problem! [SRC | FREE]

  1. #1

    word wrap? no problem! [SRC | FREE]

    You probably wondered in early days how to add word wrap and line returns to your opengl text routines, basicly this is just what you want, this function will draw a text and wrap it by character (not words!) to fir the width you want.

    Code:
    Procedure DrawFont(x, y, mx, my: single; const text: string; fontn, wordwrap: integer);
    var
    i: integer;
    b: byte;
    cw: integer;
    ta, tb, tc, td: single;
    va, vb, vc, vd: single;
    
    // current left edge
    L: single;
    // skip this much of characters from being parsed
    SK: integer;
    
    procedure wrap;
    begin
    cw:= 0;
    L:= L + (FontGeo[32].H * my);
    end;
    
    procedure EatColor; // changes font color depending on keyword
    begin
    if text[i + 2] = 'W' then glcolor3f(1, 1, 1);
    if text[i + 2] = 'N' then glcolor3f(0, 0, 0);
    if text[i + 2] = 'R' then glcolor3f(1, 0, 0);
    if text[i + 2] = 'G' then glcolor3f(0, 1, 0);
    if text[i + 2] = 'B' then glcolor3f(0, 0, 1);
    SK:= 2; // skip 2 chars so the color coding is like ~G~
    end;
    
    begin
    
    if length(text) = 0 then exit; // idiot proof fuse
    
    // ensure variables are reset
    cw:= 0;
    L:= 0;
    SK:= 0;
    
    glBindTexture(GL_TEXTURE_2D, Font.tex[fontn].GLID);
    glBegin(GL_quads);
    
    for i:= 0 to length(text) do begin
    
    if SK <> 0 then begin SK&#58;= SK -1; continue; end;
    
    b&#58;= byte&#40;text&#91;i + 1&#93;&#41;; // we need a integer type to use for array access,
    
    // next character would wrap
    if &#40;wordwrap <> 0&#41; and &#40;cw + trunc&#40;FontGeo&#91;b&#93;.spacing * mx&#41; > wordwrap&#41; then wrap;
    
    // return character - go to new line
    if b = 13 then begin wrap; continue; end;
    // ~X~ color coding keyword
    if b = 126 then begin eatcolor; continue; end;
    
    // get tex coords from array
    ta&#58;= FontGeo&#91;b&#93;.X / 256;
    tb&#58;= FontGeo&#91;b&#93;.X / 256 + FontGeo&#91;b&#93;.W / 256;
    tc&#58;= FontGeo&#91;b&#93;.Y / 256;
    td&#58;= FontGeo&#91;b&#93;.Y / 256 + FontGeo&#91;b&#93;.H / 256;
    
    // build vertices
    va&#58;= cw;                                          // top left
    vb&#58;= va + &#40;FontGeo&#91;b&#93;.W * mx&#41;;                    // top right
    vc&#58;= &#40;FontGeo&#91;b&#93;.YOFS * my&#41; + L;  // bottom left
    vd&#58;= vc + &#40;FontGeo&#91;b&#93;.H * my&#41;;                    // bottom right
    
    // crunch
    gltexcoord2f&#40;ta, tc&#41;; glvertex2fwin&#40;x + va, y + vc&#41;;
    gltexcoord2f&#40;ta, td&#41;; glvertex2fwin&#40;x + va, y + vd&#41;;
    gltexcoord2f&#40;tb, td&#41;; glvertex2fwin&#40;x + vb, y + vd&#41;;
    gltexcoord2f&#40;tb, tc&#41;; glvertex2fwin&#40;x + vb, y + vc&#41;;
    
    // add character size to left edge
    cw&#58;= cw + trunc&#40;FontGeo&#91;b&#93;.spacing * mx&#41;;
    
    end;
    
    glend;
    
    end;
    character support records:

    Code:
    Glyph = packed record
    X, Y, W, H, YOFS, SPACING&#58; byte;
    end;
    
    FontGeo&#58; array&#91;0..255&#93; of Glyph;
    license: none, you can even eat it or whatever you want, but i take no responsibility for aynthing.

    2d opengl routines:

    Code:
    //this draws a vertex in windows coordinate system
    procedure glvertex2fwin&#40;const x, y&#58; single&#41;;
    begin
    glvertex2f&#40;x, win_height - y&#41;;
    end;
    how to get into this 2d mode?


    Code:
    // Dwarf with Axe - GAMEDEV forums&#58; 18 July 2002 6&#58;12&#58;57 PM
    //
    // There have been thousands of posts along the lines of
    // "How do I do 2d in OpenGL" to "Duuuhde, I wunt too maek
    // a two dee gaem in ohpun jee el; how do eye set uhp two dee???!?"
    //
    // I have developed a simple, nice, pretty way for all of you to have your 2D fun.
    
    procedure GlEnable2D;
    var
    vport&#58; array&#91;0..3&#93; of integer;
    begin
    glGetIntegerv&#40;GL_VIEWPORT, @vPort&#41;;
    
    glMatrixMode&#40;GL_PROJECTION&#41;;
    glPushMatrix;
    glLoadIdentity;
    glOrtho&#40;0, vPort&#91;2&#93;, 0, vPort&#91;3&#93;, -1, 1&#41;;
    
    glMatrixMode&#40;GL_MODELVIEW&#41;;
    glPushMatrix;
    glLoadIdentity;
    end;
    
    procedure GlDisable2D;
    begin
    glMatrixMode&#40;GL_PROJECTION&#41;;
    glPopMatrix;
    glMatrixMode&#40;GL_MODELVIEW&#41;;
    glPopMatrix;
    end;
    This is my game project - Top Down City:
    http://www.pascalgamedevelopment.com...y-Topic-Reboot

    My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
    http://www.pascalgamedevelopment.com...source+manager

  2. #2

    word wrap? no problem! [SRC | FREE]

    Excellent, I will see if I can use that somewhere. Thanks for posting it.
    <br /><br />There are a lot of people who are dead while they are still alive. I want to be alive until the day I die.<br />-= Paulo Coelho =-

  3. #3

    word wrap? no problem! [SRC | FREE]

    just wondering, i'd rather have it wrap by whole words, any ideas how would this be easiest to implement?
    This is my game project - Top Down City:
    http://www.pascalgamedevelopment.com...y-Topic-Reboot

    My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
    http://www.pascalgamedevelopment.com...source+manager

  4. #4

    word wrap? no problem! [SRC | FREE]

    At the wrap point I would scan backwards until I find a space. I did that for a JEDI-SDL word-wrap function I wrote. I posted it on these forums as well, but can't seem to find it right now.
    <br /><br />There are a lot of people who are dead while they are still alive. I want to be alive until the day I die.<br />-= Paulo Coelho =-

  5. #5

    word wrap? no problem! [SRC | FREE]

    Quote Originally Posted by savage
    At the wrap point I would scan backwards until I find a space. I did that for a JEDI-SDL word-wrap function I wrote. I posted it on these forums as well, but can't seem to find it right now.
    yes i had a similar idea, but what about the characters i already drawn in first line that should then wrap to second line?
    This is my game project - Top Down City:
    http://www.pascalgamedevelopment.com...y-Topic-Reboot

    My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
    http://www.pascalgamedevelopment.com...source+manager

  6. #6

    word wrap? no problem! [SRC | FREE]

    I think I created a dynamic array of strings and pre-parsed the text so that each array element contained the string for that line. So my word wrapping code was part of this routine not part of the drawing code.
    Then when it comes to drawing, I just loop through the array knowing that each index represents 1 line of text and space them vertically appropriately.
    <br /><br />There are a lot of people who are dead while they are still alive. I want to be alive until the day I die.<br />-= Paulo Coelho =-

  7. #7

    word wrap? no problem! [SRC | FREE]

    related function using Jedi

    Code:
    // ----------------------------------------------------------------------------
    procedure AIRConsole.AddBrokenDisplay&#40;const aLine&#58; string&#41;;
    var
      myOriginal&#58; string;
      myBroken&#58; string;
      myLen&#58; integer;
      i&#58; integer;
    begin
      myOriginal &#58;= aLine;
      myLen &#58;= 160;
      if StrLen&#40;PAnsiChar&#40;myOriginal&#41;&#41; > myLen then
      begin
        i &#58;= 0;
        while StrLen&#40;PAnsiChar&#40;myOriginal&#41;&#41; > myLen do
        begin
          myBroken   &#58;= StrLeft&#40;myOriginal, myLen&#41;;
          myOriginal &#58;= StrRestOf&#40;myOriginal, myLen&#41;;
          if i=0 then
            Display.Add&#40;myBroken&#41;
          else
            Display.Add&#40;'\' + myBroken&#41;;
          i &#58;= i + 1;
        end;
        Display.Add&#40;'\' + myOriginal&#41;;
      end
      else
        Display.Add&#40;myOriginal&#41;;
    end;
    edit: oops, thought this did word wrap too, but it doesnt. nm ops:

  8. #8

    word wrap? no problem! [SRC | FREE]

    Quote Originally Posted by savage
    I think I created a dynamic array of strings and pre-parsed the text so that each array element contained the string for that line. So my word wrapping code was part of this routine not part of the drawing code.
    Then when it comes to drawing, I just loop through the array knowing that each index represents 1 line of text and space them vertically appropriately.
    this seems like a good idea, but i think what im going to do is this:

    I will parse whole text, and remember at which character the lines should wrap (store it in a fixed array - im expecting maximum like 5-10 so wraps), then cache the data, when i will draw it i will know where will the characters should wrap :idea:
    This is my game project - Top Down City:
    http://www.pascalgamedevelopment.com...y-Topic-Reboot

    My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
    http://www.pascalgamedevelopment.com...source+manager

  9. #9

    word wrap? no problem! [SRC | FREE]

    Quote Originally Posted by Delfi
    this seems like a good idea, but i think what im going to do is this:

    I will parse whole text, and remember at which character the lines should wrap (store it in a fixed array - im expecting maximum like 5-10 so wraps), then cache the data, when i will draw it i will know where will the characters should wrap :idea:
    Sounds good as well, and less resource hungry.
    <br /><br />There are a lot of people who are dead while they are still alive. I want to be alive until the day I die.<br />-= Paulo Coelho =-

  10. #10

    word wrap? no problem! [SRC | FREE]

    Ok, it works great now! here is the updated function:

    [pascal]Procedure DrawFont(x, y, mx, my, trans: single; const text: string; fontn, wordwrap: integer);
    var
    i: integer;
    b: byte;
    cw: integer;
    ta, tb, tc, td: single;
    va, vb, vc, vd: single;

    // current left edge
    L: single;
    // skip this much of characters from being parsed
    SK: integer;

    wraps: array[0..31] of word; // i dont think my game will ever need / have more than 32 word wraps
    maxwrap: integer;
    currwrap: integer;
    lastspace: integer; // faster word wrap

    procedure Vwrap(c: integer);
    begin
    cw:= 0;
    wraps[maxwrap]:= c;
    maxwrap:= maxwrap +1;
    // since there is no array bounds checking this takes care for safety
    if maxwrap > high(wraps) then maxwrap:= high(wraps);
    end;

    // this function processes the string and remembers all locations where lines should wrap (line returns, word wraps, etc..)
    procedure MeasureWraps;
    var
    i: integer;
    begin
    maxwrap:= 0;
    lastspace:= -1; // faster word wrap

    for i:= 0 to length(text) do begin

    if SK <> 0 then begin SK:= SK -1; continue; end; // skipping text coding characters

    b:= byte(text[i + 1]); // we need a integer type to use for array access,

    if b = 32 then lastspace:= i; // remember last space for word wrapping

    if b = 126 then begin sk:= 2; continue; end; // skip ~X~ color coding keyword

    // next character would fall over the specified text width dimension, wrap at last known space character
    if (wordwrap <> 0) and (cw + trunc(FontGeo[fontn, b].spacing * mx) > wordwrap) then begin
    Vwrap(lastspace); continue;
    end;

    if b = 13 then begin Vwrap(i); continue; end; // return character - go to new line

    // add character width to this line text width
    cw:= cw + trunc(FontGeo[fontn, b].spacing * mx);

    end;
    end;

    // go to next line
    procedure wrap;
    begin
    cw:= 0;
    L:= L + (FontGeo[fontn, 32].H * my);
    end;

    // process color codes
    procedure EatColor; // changes font color depending on keyword
    begin
    if text[i + 2] = 'W' then glcolor4f(1, 1, 1, trans); // white
    if text[i + 2] = 'N' then glcolor4f(0, 0, 0, trans); // none - black
    if text[i + 2] = 'R' then glcolor4f(0.9, 0, 0, trans); // red
    if text[i + 2] = 'G' then glcolor4f(0, 0.9, 0, trans); // green
    if text[i + 2] = 'B' then glcolor4f(0, 0, 0.9, trans); // blue

    if text[i + 2] = 'Y' then glcolor4f(1.0, 1, 0, trans); // red
    if text[i + 2] = 'T' then glcolor4f(0, 1, 1, trans); // green
    if text[i + 2] = 'O' then glcolor4f(1, 0.7734375, 0.09765625, trans); // blue


    {yellow #FFFF00
    teal #00FFFF
    orange #FFC619 }


    SK:= 2; // skip 2 chars so the color coding is like '~C~' where C is color
    end;


    begin

    if length(text) = 0 then exit; // idiot proof fuse

    // ensure variables are reset for preprocessing

    cw:= 0;
    SK:= 0;
    fillchar(wraps, sizeof(wraps), $FF);
    MeasureWraps;

    // ensure variables are reset for rendering
    cw:= 0;
    L:= 0;
    SK:= 0;
    currwrap:= 0;

    glBindTexture(GL_TEXTURE_2D, Font.tex[fontn].GLID);
    glBegin(GL_quads);

    for i:= 0 to length(text) do begin

    if SK <> 0 then begin SK:= SK -1; continue; end;

    b:= byte(text[i + 1]); // we need a integer type to use for array access

    if b = 126 then begin eatcolor; continue; end;

    // find out if we are supposed to wrap at this character
    if currwrap < maxwrap then
    if wraps[currwrap] = i then begin wrap; currwrap:= currwrap +1; continue; end;

    // get tex coords from array
    ta:= FontGeo[fontn, b].X / 256;
    tb:= FontGeo[fontn, b].X / 256 + FontGeo[fontn, b].W / 256;
    tc:= FontGeo[fontn, b].Y / 256;
    td:= FontGeo[fontn, b].Y / 256 + FontGeo[fontn, b].H / 256;

    // build vertices
    va:= cw; // top left
    vb:= va + (FontGeo[fontn, b].W * mx); // top right
    vc:= (FontGeo[fontn, b].YOFS * my) + L; // bottom left
    vd:= vc + (FontGeo[fontn, b].H * my); // bottom right

    // crunch
    gltexcoord2f(ta, tc); glvertex2fwin(x + va, y + vc);
    gltexcoord2f(ta, td); glvertex2fwin(x + va, y + vd);
    gltexcoord2f(tb, td); glvertex2fwin(x + vb, y + vd);
    gltexcoord2f(tb, tc); glvertex2fwin(x + vb, y + vc);

    // add character size to left edge
    cw:= cw + trunc(FontGeo[fontn, b].spacing * mx);

    end;

    glend;

    end;[/pascal]
    This is my game project - Top Down City:
    http://www.pascalgamedevelopment.com...y-Topic-Reboot

    My OpenAL audio wrapper with Intelligent Source Manager to use unlimited:
    http://www.pascalgamedevelopment.com...source+manager

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •