Files
lace/3-mid/opengl/source/lean/text/private/opengl-fontimpl-texture.adb

342 lines
10 KiB
Ada

with
openGL.Glyph.texture,
openGL.Glyph.Container,
openGL.Palette,
openGL.Tasks,
GL.Binding,
GL.lean,
GL.Pointers,
freetype_c.Binding;
package body openGL.FontImpl.Texture
is
---------
-- Forge
--
function to_FontImpl_texture (ftFont : access Font.item'Class;
fontFilePath : in String) return fontImpl.texture.item
is
use freetype_c.Binding;
Success : Boolean;
begin
return Self : fontImpl.texture.item
do
define (Self'Access, ftFont, fontFilePath);
Self.load_Flags := freetype_c.FT_Int (FT_LOAD_NO_HINTING_flag or FT_LOAD_NO_BITMAP_flag);
Self.numGlyphs := Self.Face.GlyphCount;
Self.remGlyphs := Self.numGlyphs;
Success := Self.FaceSize (20);
if not Success then
raise Error with "Unable to set font facesize for '" & fontFilePath & "'.";
end if;
end return;
end to_FontImpl_texture;
function new_FontImpl_texture (ftFont : access Font.item'Class;
fontFilePath : in String) return access fontImpl.texture.item'Class
is
use freetype_c.Binding;
Self : constant fontImpl.texture.view := new fontImpl.texture.item;
Success : Boolean;
begin
define (Self, ftFont, fontFilePath);
Self.load_Flags := freetype_c.FT_Int (FT_LOAD_NO_HINTING_flag or FT_LOAD_NO_BITMAP_flag);
Self.numGlyphs := Self.Face.GlyphCount;
Self.remGlyphs := Self.numGlyphs;
Success := Self.FaceSize (20);
if not Success then
raise Error with "Unable to set font facesize for '" & fontFilePath & "'.";
end if;
return Self;
end new_FontImpl_texture;
function to_FontImpl_texture (ftFont : access openGL.Font.item'Class;
pBufferBytes : in unsigned_char_Pointer;
bufferSizeInBytes : in Natural) return fontImpl.texture.item
is
use freetype_c.Binding;
begin
return Self : fontImpl.texture.item
do
define (Self'Access, ftFont, pBufferBytes, bufferSizeInBytes);
Self.load_Flags := freetype_c.FT_Int ( FT_LOAD_NO_HINTING_flag
or FT_LOAD_NO_BITMAP_flag);
Self.numGlyphs := Self.face.GlyphCount;
Self.remGlyphs := Self.numGlyphs;
end return;
end to_FontImpl_texture;
function new_FontImpl_texture (ftFont : access Font.item'Class;
pBufferBytes : in unsigned_char_Pointer;
bufferSizeInBytes : in Natural) return fontImpl.texture.view
is
begin
return new fontImpl.texture.item' (to_FontImpl_texture (ftFont,
pBufferBytes,
bufferSizeInBytes));
end new_FontImpl_texture;
procedure free_Textures (Self : in out Item)
is
use texture_name_Vectors,
GL.lean;
Cursor : texture_name_Vectors.Cursor := Self.textureIDList.First;
the_Name : aliased openGL.Texture.texture_Name;
begin
Tasks.check;
while has_Element (Cursor)
loop
the_Name := Element (Cursor);
glDeleteTextures (1, the_Name'Access);
next (Cursor);
end loop;
end free_Textures;
overriding
procedure destruct (Self : in out Item)
is
use type ada.Containers.Count_type;
begin
destruct (FontImpl.item (Self)); -- Destroy base class.
if Self.textureIDList.Length > 0
then
Self.free_Textures;
end if;
end destruct;
--------------
-- Attributes
--
overriding
function FaceSize (Self : access Item; Size : in Natural;
x_Res, y_Res : in Natural := 72) return Boolean
is
type access_FontImpl is access all FontImpl.item;
Success : Boolean;
begin
if not Self.textureIDList.is_empty
then
Self.free_Textures;
Self.textureIDList.clear;
Self.numGlyphs := Self.Face.GlyphCount;
Self.remGlyphs := Self.numGlyphs;
end if;
Success := access_FontImpl (Self).FaceSize (Size, x_Res, y_Res);
return Success;
end FaceSize;
function Render (Self : access Item; Text : in String;
Length : in Integer;
Position : in Vector_3;
Spacing : in Vector_3;
Mode : in renderMode) return Vector_3
is
use GL,
GL.Binding;
Tmp : Vector_3;
begin
Tasks.check;
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable (GL_TEXTURE_2D);
GlyphImpl.texture.ResetActiveTexture;
Tmp := FontImpl.item (Self.all).Render (Text,
Length,
Position,
Spacing,
Mode'enum_Rep);
return Tmp;
end Render;
function MakeGlyphImpl (Self : access Item; ftGlyph : in freetype_c.FT_GlyphSlot.item) return access Glyph.item'Class
is
tempGlyph : Glyph.Container.Glyph_view;
begin
Self.glyphHeight := Integer (Self.charSize.Height + 0.5);
Self.glyphWidth := Integer (Self.charSize.Width + 0.5);
if Self.glyphHeight < 1 then Self.glyphHeight := 1; end if;
if Self.glyphWidth < 1 then Self.glyphWidth := 1; end if;
if Self.textureIDList.is_empty
then
Self.textureIDList.append (Self.CreateTexture);
Self.xOffset := Self.Padding;
Self.yOffset := Self.Padding;
end if;
if Self.xOffset > (Integer (Self.textureWidth) - Self.glyphWidth)
then
Self.xOffset := Self.Padding;
Self.yOffset := Self.yOffset + Self.glyphHeight;
if Self.yOffset > (Integer (Self.textureHeight) - Self.glyphHeight)
then
Self.textureIDList.append (Self.CreateTexture);
Self.yOffset := Self.Padding;
end if;
end if;
tempGlyph := openGL.Glyph.texture.new_Glyph (ftGlyph,
Self.textureIDList.last_Element,
Self.xOffset,
Self.yOffset,
Integer (Self.textureWidth),
Integer (Self.textureHeight)).all'Access;
Self.xOffset := Self.xOffset + Integer ( tempGlyph.BBox.Box.Upper (1)
- tempGlyph.BBox.Box.Lower (1)
+ Real (Self.Padding)
+ 0.5);
Self.remGlyphs := Self.remGlyphs - 1;
return tempGlyph;
end MakeGlyphImpl;
function Quad (Self : access Item; for_Character : in Character) return GlyphImpl.texture.Quad_t
is
use freetype.charMap;
Success : constant Boolean := Self.CheckGlyph (to_characterCode (for_Character)) with unreferenced;
the_Glyph : constant Glyph.Container.Glyph_view := Self.glyphList.Glyph (to_characterCode (for_Character));
begin
return Glyph.texture.item (the_Glyph.all).Quad ([0.0, 0.0, 0.0]);
end Quad;
procedure CalculateTextureSize (Self : in out Item)
is
use openGL.Texture,
GL,
GL.Binding;
use type GL.GLsizei;
H : Integer;
begin
Tasks.check;
if Self.maximumGLTextureSize = 0
then
Self.maximumGLTextureSize := 1024;
glGetIntegerv (GL_MAX_TEXTURE_SIZE, Self.maximumGLTextureSize'Access);
pragma assert (Self.maximumGLTextureSize /= 0); -- If you hit this then you have an invalid openGL context.
end if;
begin
Self.textureWidth := Power_of_2_Ceiling ( (Self.remGlyphs * Self.glyphWidth)
+ (Self.Padding * 2));
exception
when constraint_Error =>
Self.textureWidth := Self.maximumGLTextureSize;
end;
if Self.textureWidth > Self.maximumGLTextureSize
then Self.textureWidth := Self.maximumGLTextureSize;
end if;
H := Integer ( Real (Integer (Self.textureWidth) - (Self.Padding * 2))
/ Real (Self.glyphWidth)
+ 0.5);
Self.textureHeight := Power_of_2_Ceiling ( ((Self.numGlyphs / H) + 1)
* Self.glyphHeight);
if Self.textureHeight > Self.maximumGLTextureSize
then Self.textureHeight := Self.maximumGLTextureSize;
end if;
end CalculateTextureSize;
function CreateTexture (Self : access Item) return openGL.Texture.texture_Name
is
use openGL.Palette,
GL,
GL.Binding;
begin
Tasks.check;
Self.CalculateTextureSize;
declare
use GL.Pointers;
the_Image : Image (1 .. Index_t (self.textureHeight),
1 .. Index_t (Self.textureWidth)) := (others => [others => +Black]);
textID : aliased openGL.Texture.texture_Name;
begin
glGenTextures (1, textID'Access);
glBindTexture (GL_TEXTURE_2D, textID);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D (GL_TEXTURE_2D,
0, GL_ALPHA,
Self.textureWidth, Self.textureHeight,
0, GL_ALPHA,
GL_UNSIGNED_BYTE,
to_GLvoid_access (the_Image (1, 1).Red'Access));
return textID;
end;
end CreateTexture;
function gl_Texture (Self : in Item) return openGL.Texture.texture_Name
is
begin
return Self.textureIDList.last_Element;
end gl_Texture;
end openGL.FontImpl.Texture;