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

Thread: vector fonts? (freetype for pascal?)

  1. #1

    vector fonts? (freetype for pascal?)

    Is it possible to use vector fonts with opengl? I know of wgl, but that is windows only.
    Now there is also freetype2. It is supposed to be able to give access to the vector data of the glyph. That give me 3 questions:
    1. Is there a delphi/pascal unit for freetype2?
    2. How does rendering a glyph work? Bezier->Polygon->Triangulate?
    3. Has someone else already done the hard work?

    With knowing how point 2 works. The font can also be save in like a milkshape ascii format. So the original font is not needed.
    http://3das.noeska.com - create adventure games without programming

  2. #2

    Re: vector fonts? (freetype for pascal?)

    Quote Originally Posted by noeska
    Is it possible to use vector fonts with opengl? I know of wgl, but that is windows only.
    Now there is also freetype2. It is supposed to be able to give access to the vector data of the glyph. That give me 3 questions:
    1. Is there a delphi/pascal unit for freetype2?
    2. How does rendering a glyph work? Bezier->Polygon->Triangulate?
    3. Has someone else already done the hard work?

    With knowing how point 2 works. The font can also be save in like a milkshape ascii format. So the original font is not needed.
    1. no
    2. yes
    3. no

    I was considering doing this a while ago, but i did experiments (using WGL font outlines and converting them to mesh using feedback buffer), but the renderings were, well let me put it simply, the renderings looked like crap at low scale without AA, and you can't force users to use AA.. so they weren't useable for anything else but large text (it was totally unsuitable for hud text etc..).
    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

  3. #3

    vector fonts? (freetype for pascal?)

    Maybe this could be of any help: http://nopaste.info/51922ec7d4.html.

  4. #4

    vector fonts? (freetype for pascal?)

    As always torry is verry helpful as it provides a ttf2vector component. Now this solutions is also windows only. But gives access to the font coords. And allowed me to render with GL_LINES.
    http://www.torry.net/quicksearchd.ph...ctor&Title=Yes
    so with this i should also be able to extrude etc. I have yet to test it with my experimental 2dpolygon render to see if it can render it solid also, but i expect no problems there. It just needs a good cleanup.
    And more importantly it is possible to save the font coords. So it is possible to render a font that is not available on the end user system. The ony thing to worry about is precission.

    Only the font generator application would only run on windows only.

    But for linux support freetype(2) is really needed.

    Example:

    Init
    Code:
      TTF2Vector := TTTFToVectorConverter.Create(DGLForm);
      TTF2Vector.Font := TFont.Create();
      TTF2Vector.Font.Name := 'Arial';
      // Setup spline precision (1 min, 100 max)
      TTF2Vector.Precision := 1;
    Render
    Code:
      // Get glyphs' strokes
        glyphs := TTF2Vector.GetCharacterGlyphs( ord('m') );
        if glyphs = nil then // May be a "empty" glyph !!!!
          beep;
        // Get character bounds
        cbounds := glyphs.Bounds;
        xm := (cbounds.Right-cbounds.Left+1) div 2;
        ym := (cbounds.Bottom-cbounds.Top+1) div 2;
        // Compute the scaling factors
        sx := 0.5;//(PaintBox.Width-20)/(cbounds.Right-cbounds.Left+1);
        sy := 0.5;//(PaintBox.Height-20)/(cbounds.Bottom-cbounds.Top+1);
    
        for i := 0 to glyphs.Count-1 do
        begin
          // Get a stroke
          stroke := glyphs.Stroke[i];
    
            x1 := 10 + round( (stroke.Pt1.X-cbounds.Left) * sx );
            x2 := 10 + round( (stroke.Pt2.X-cbounds.Left) * sx );
            y1 := 10 + round( (stroke.Pt1.Y-cbounds.Top) * sy );
            y2 := 10 + round( (stroke.Pt2.Y-cbounds.Top) * sy );
    
          // Draw the stroke
          glBegin(GL_LINES);
            glVertex3f(x1/1000, (y1-1)/1000, 0);
            glVertex3f(x2/1000, (y2-1)/1000,0);
          glEnd();
    
        end;
        // Free the glyphs
        glyphs.Free;
    http://3das.noeska.com - create adventure games without programming

  5. #5

    vector fonts? (freetype for pascal?)

    Any pictures of how the font looks rendered?
    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

    vector fonts? (freetype for pascal?)

    for the moment not as good as expected:


    But that is due to my polygon tesselation that goes haywire on the i character.
    http://3das.noeska.com - create adventure games without programming

  7. #7

    vector fonts? (freetype for pascal?)

    You might want to triangulate the polygon's yourself using earclipping. As far as i can tell, it's not that hard to do.

    It looks good so far. Great efforts.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  8. #8

    vector fonts? (freetype for pascal?)

    I am using glu tesselation now. And with good results. Only how do i implement it as part of an class?

    gluTessCallback(tess, GLU_TESS_BEGIN, @tessBeginCB);

    @tessBeginCB cannot be part of the class and has to be an real procedure with stdcall.
    http://3das.noeska.com - create adventure games without programming

  9. #9

    vector fonts? (freetype for pascal?)

    Quote Originally Posted by noeska
    I am using glu tesselation now. And with good results. Only how do i implement it as part of an class?

    gluTessCallback(tess, GLU_TESS_BEGIN, @tessBeginCB);

    @tessBeginCB cannot be part of the class and has to be an real procedure with stdcall.
    sort of userdata pointer and global function?
    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

  10. #10

    vector fonts? (freetype for pascal?)

    My TPolygon Class: (MPL license)

    Code:
    unit Polygon;
    
    interface
    
    uses DGLOpenGL;
    
    type
    TPoint = packed record
      x: single;
      y: single;
      z: single;
      r: single;
      g: single;
      b: single;
      a: single;
    end;
    
    TPolygon = class
    private
      FPoints: array of TPoint; //polygon point
      FVertex: array of TPoint; //triangulated data
      FColor: TPoint;
      FCount: integer;
      FVertexCount: integer;
      FTesselated: boolean;
      procedure SetPoint(I: integer; Value: TPoint);
      procedure AddVertex(x: single; y: single; z: single; r: single; g: single; b: single; a:single);
      function GetPoint(I: integer): TPoint;
      function GetCount(): integer;
      procedure tessBegin(which: GLenum);
      procedure tessEnd();
      procedure tessVertex(x: single; y: single; z: single; r: single; g: single; b: single; a:single);
    public
      constructor Create();
      destructor Destroy();
      procedure SetColor(R: single; G: single; B: single;A: single);
      procedure Add(X: single; Y: single); overload;
      procedure Add(X: single; Y: single; Z: single); overload;
      procedure Add(X: single; Y: single; Z: single; R: single; G: single; B: single; A: single); overload;
      procedure Render();
      procedure Tesselate();
      property Points[I: integer]: TPoint read GetPoint write SetPoint;
      property Count: integer read GetCount;
    end;
    
    implementation
    
    type
         TGLArrayd6 = array[0..5] of GLDouble;
         PGLArrayd6 = ^TGLArrayd6;
         TGLArrayvertex4 = array[0..3] of PGLArrayd6;
         PGLArrayvertex4 = ^TGLArrayvertex4;
         PGLArrayf4 = ^TGLArrayf4;
    
    threadvar
      PolygonClass: TPolygon;
    
    procedure TPolygon.SetColor(R: single; G: single; B: single;A: single);
    begin
      FColor.r := R;
      FColor.g := G;
      FColor.b := B;
      FColor.a := A;
    end;
    
    procedure TPolygon.tessBegin(which: GLenum);
    begin
        glBegin(which);
    end;
    
    procedure TPolygon.tessEnd();
    begin
        glEnd();
    end;
    
    procedure TPolygon.tessVertex(x: single; y: single; z: single; r: single; g: single; b: single; a:single);
    begin
        glcolor3f(r,g,b);
        glVertex3f(x,y,z);
    end;
    
    procedure TPolygon.AddVertex(x: single; y: single; z: single; r: single; g: single; b: single; a:single);
    begin
        FVertexCount := FVertexCount + 1;
        SetLength(FVertex, FVertexCount);
    
        FVertex[FVertexCount-1].R := R;
        FVertex[FVertexCount-1].G := G;
        FVertex[FVertexCount-1].B := B;
    
        FVertex[FVertexCount-1].X := X;
        FVertex[FVertexCount-1].Y := Y;
        FVertex[FVertexCount-1].Z := Z;
    end;
    
    constructor TPolygon.Create();
    begin
      inherited Create();
      FCount := 0;
      FVertexCount := 0;
      FTesselated := false;
      FColor.R := 0.0;
      FColor.G := 0.0;
      FColor.B := 0.0;
      FColor.A := 0.0;
    end;
    
    destructor TPolygon.Destroy();
    begin
      FTesselated := false;
      FCount := 0;
      FVertexCount := 0;
      SetLength(FPoints, FCount);
      SetLength(FVertex, FVertexCount);
      inherited Destroy;
    end;
    
    procedure TPolygon.SetPoint(I: integer; Value: TPoint);
    begin
      FTesselated := false; //check first on changed values
      FPoints[I] := Value;
    end;
    
    function TPolygon.GetPoint(I: integer): TPoint;
    begin
      result := FPoints[I];
    end;
    
    function TPolygon.GetCount(): integer;
    begin
      result := FCount;
    end;
    
    procedure TPolygon.Add(X: single; Y: single);
    begin
      FTesselated := false;
      FCount := FCount + 1;
      SetLength(FPoints, FCount);
      FPoints[FCount-1].X := X;
      FPoints[FCount-1].Y := Y;
      FPoints[FCount-1].Z := 0.0;
      FPoints[FCount-1].R := FColor.R;
      FPoints[FCount-1].G := FColor.G;
      FPoints[FCount-1].B := FColor.B;
      FPoints[FCount-1].A := FColor.A;
    end;
    
    procedure TPolygon.Add(X: single; Y: single; Z: single);
    begin
      FTesselated := false;
      FCount := FCount + 1;
      SetLength(FPoints, FCount);
      FPoints[FCount-1].X := X;
      FPoints[FCount-1].Y := Y;
      FPoints[FCount-1].Z := Z;
      FPoints[FCount-1].R := FColor.R;
      FPoints[FCount-1].G := FColor.G;
      FPoints[FCount-1].B := FColor.B;
      FPoints[FCount-1].A := FColor.A;
    end;
    
    procedure TPolygon.Add(X: single; Y: single; Z: single; R: single; G: single; B: single; A: single);
    begin
      FTesselated := false;
      FCount := FCount + 1;
      SetLength(FPoints, FCount);
      FPoints[FCount-1].X := X;
      FPoints[FCount-1].Y := Y;
      FPoints[FCount-1].Z := Z;
      FPoints[FCount-1].R := R;
      FPoints[FCount-1].G := G;
      FPoints[FCount-1].B := B;
      FPoints[FCount-1].A := A;
    end;
    
    Procedure TPolygon.Render();
    var
      loop: integer;
    begin
      if FTesselated = false then Tesselate;
    
      glbegin(GL_TRIANGLES);
      for loop:=0 to FVertexCount-1 do
      begin
        glcolor3f(FVertex[loop].R,FVertex[loop].G,FVertex[loop].B);
        glvertex3f(FVertex[loop].X,FVertex[loop].Y,FVertex[loop].Z);
      end;
      glend;
    end;
    
    procedure TPolygon.Tesselate();
    var
      loop: integer;
      tess: pointer;
      test: TGLArrayd3;
      pol: PGLArrayd6;
    
      MyTest: string;
    
    procedure iTessBeginCB(which: GLenum); {$IFDEF Win32}stdcall; {$ELSE}cdecl; {$ENDIF}
    begin
      //PolygonClass.tessBegin(which);
    end;
    
    procedure iTessEndCB(); {$IFDEF Win32}stdcall; {$ELSE}cdecl; {$ENDIF}
    begin
      //PolygonClass.tessEnd();
    end;
    
    procedure iTessEdgeCB(flag: GLboolean; lpContext: pointer); {$IFDEF Win32}stdcall; {$ELSE}cdecl; {$ENDIF}
    begin
          //just do nothing to force GL_TRIANGLES !!!
    end;
    
    procedure iTessVertexCB(data: PGLArrayd6); {$IFDEF Win32}stdcall; {$ELSE}cdecl; {$ENDIF}
    begin
      //PolygonClass.tessVertex(data[0], data[1], data[2], data[3], data[4], data[5],0);
      PolygonClass.AddVertex(data[0], data[1], data[2], data[3], data[4], data[5],0);
    end;
    
    
    procedure iTessCombineCB(newVertex : PGLArrayd6; neighborVertex : Pointer;
                          neighborWeight : Pointer; var outData : Pointer); {$IFDEF Win32}stdcall; {$ELSE}cdecl; {$ENDIF}
    var
      vertex: PGLArrayd6;
      loop: integer;
      colorloop: integer;
      color: double;
    begin
      new(vertex);
    
      vertex[0] := newVertex^[0];
      vertex[1] := newVertex^[1];
      vertex[2] := newVertex^[2];
    
      for colorloop := 3 to 5 do
      begin
        vertex[colorloop] := 0.0;
        for loop:=0 to 3 do
        begin
          if PGLArrayf4&#40;neighborWeight&#41;^&#91;loop&#93; <> 0 then
          begin
            vertex&#91;colorloop&#93; &#58;= vertex&#91;colorloop&#93; +
                 PGLArrayf4&#40;neighborWeight&#41;^&#91;loop&#93; *
                 PGLArrayvertex4&#40;neighborVertex&#41;^&#91;loop&#93;&#91;colorloop&#93;
          end;
        end;
      end;
    
      // return output data &#40;vertex coords and others&#41;
      outData&#58;= vertex;
    end;
    
    begin
      PolygonClass &#58;= Self;
    
      tess &#58;= gluNewTess&#40;&#41;;
    
      gluTessCallback&#40;tess, GLU_TESS_BEGIN, @iTessBeginCB &#41;;
      gluTessCallback&#40;tess, GLU_TESS_END, @iTessEndCB&#41;;
      gluTessCallback&#40;tess, GLU_TESS_VERTEX, @iTessVertexCB&#41;;
      gluTessCallback&#40;tess, GLU_TESS_COMBINE, @iTessCombineCB&#41;;  //does not work for font?
      gluTessCallback&#40;tess, GLU_TESS_EDGE_FLAG_DATA, @iTessEdgeCB&#41;; //force triangles
    
      gluTessProperty&#40;tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO &#41;;
    
      gluTessBeginPolygon&#40;tess, nil&#41;;                   // with NULL data
      gluTessBeginContour&#40;tess&#41;;
    
      for loop &#58;= 0 to FCount-1 do
      begin
          new&#40;pol&#41;;
          pol&#91;3&#93;&#58;=FPoints&#91;loop&#93;.R; //color
          pol&#91;4&#93;&#58;=FPoints&#91;loop&#93;.G;
          pol&#91;5&#93;&#58;=FPoints&#91;loop&#93;.B;
    
          pol&#91;0&#93;&#58;=FPoints&#91;loop&#93;.X;
          pol&#91;1&#93;&#58;=FPoints&#91;loop&#93;.Y;
          pol&#91;2&#93;&#58;=0;
    
          test&#91;0&#93; &#58;= pol&#91;0&#93;;
          test&#91;1&#93; &#58;= pol&#91;1&#93;;
          test&#91;2&#93; &#58;= pol&#91;2&#93;;
          gluTessVertex&#40;tess, test, pol&#41;;
      end;
    
      gluTessEndContour&#40;tess&#41;;
      gluTessEndPolygon&#40;tess&#41;;
      gluDeleteTess&#40;tess&#41;;        // delete after tessellation
    
      PolygonClass &#58;= nil;
      FTesselated &#58;= true;
    end;
    
    end.
    http://3das.noeska.com - create adventure games without programming

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
  •