with openGL.Tasks, openGL.Errors, GL.Binding, GL.Pointers, freetype_c.Binding, freetype_c.FT_Bitmap, interfaces.C; package body openGL.GlyphImpl.texture is ----------- -- Globals -- activeTextureID : openGL.texture.texture_Name; -- TODO: Check C source for how this is used. pragma Unreferenced (activeTextureID); -- -- The texture index of the currently active texture -- -- We keep track of the currently active texture to try to reduce the -- number of texture bind operations. procedure ResetActiveTexture is begin activeTextureID := 0; end ResetActiveTexture; --------- -- Forge -- function new_GlyphImpl (glyth_Slot : in freetype_c.FT_GlyphSlot.item; texture_Id : in openGL.Texture.texture_Name; xOffset, yOffset : in Integer; Width, Height : in Integer) return GlyphImpl.texture.view is use freetype_C, freetype_C.Binding, GL, GL.Binding; use type interfaces.C.unsigned, GLint; Self : constant GlyphImpl.texture.view := new GlyphImpl.texture.item; begin Tasks.check; Self.define (glyth_Slot); Self.destWidth := 0; Self.destHeight := 0; Self.glTextureID := texture_Id; Self.Err := FT_Render_Glyph (glyth_Slot, FT_RENDER_MODE_NORMAL); if Self.Err /= no_Error then raise openGL.Error with "FT_Render_Glyph failed with error code: " & Self.Err'Image; end if; if FT_GlyphSlot_Get_Format (glyth_Slot) /= get_FT_GLYPH_FORMAT_BITMAP then raise openGL.Error with "Glyph is not a bitmap format."; end if; declare use GL.Pointers; Bitmap : constant freetype_C.FT_Bitmap.item := FT_GlyphSlot_Get_Bitmap (glyth_Slot); begin Self.destWidth := Bitmap.Width; Self.destHeight := Bitmap.Rows; if Self.destWidth /= 0 and then Self.destHeight /= 0 then glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glBindTexture (GL_TEXTURE_2D, Self.glTextureID); Errors.log; glTexSubImage2D (GL_TEXTURE_2D, 0, GLint (xOffset), GLint (yOffset), Self.destWidth, Self.destHeight, GL_ALPHA, GL_UNSIGNED_BYTE, to_GLvoid_access (Bitmap.Buffer)); Errors.log; end if; end; -- 0 -- +----+ -- | | -- | | -- | | -- +----+ -- 1 Self.UV (1).S := Real (xOffset) / Real (Width); Self.UV (1).T := Real (yOffset) / Real (Height); Self.UV (2).S := Real (GLint (xOffset) + Self.destWidth) / Real (Width); Self.UV (2).T := Real (GLint (yOffset) + Self.destHeight) / Real (Height); Self.Corner := [Real (FT_GlyphSlot_Get_bitmap_left (glyth_Slot)), Real (FT_GlyphSlot_Get_bitmap_top (glyth_Slot)), 0.0]; declare use openGL.Primitive; the_Indices : constant openGL.Indices := [1, 2, 3, 4]; begin Self.Primitive := Primitive.indexed.new_Primitive (triangle_Fan, the_Indices); end; return Self; end new_GlyphImpl; -------------- -- Attributes -- function Quad (Self : in Item; Pen : in Vector_3) return Quad_t is dx : constant Real := Real'Floor (Pen (1) + Self.Corner (1)); dy : constant Real := Real'Floor (Pen (2) + Self.Corner (2)); the_Quad : aliased constant Quad_t := (NW => (Site => [dx, dy, 0.0], Coords => (S => Self.UV (1).S, T => Self.UV (1).T)), SW => (Site => [dx, dy - Real (Self.destHeight), 0.0], Coords => (S => Self.UV (1).S, T => Self.UV (2).T)), SE => (Site => [dx + Real (Self.destWidth), dy - Real (Self.destHeight), 0.0], Coords => (S => Self.UV (2).S, T => Self.UV (2).T)), NE => (Site => [dx + Real (Self.destWidth), dy, 0.0], Coords => (S => Self.UV (2).S, T => Self.UV (1).T)), Advance => Self.Advance); begin return the_Quad; end Quad; -------------- -- Operations -- function renderImpl (Self : in Item; Pen : in Vector_3; renderMode : in Integer) return Vector_3 is pragma unreferenced (renderMode); begin return Self.Advance; end renderImpl; end openGL.GlyphImpl.Texture;