public static int FT_Open_Face(IntPtr library, FreeTypeStreamWrapper streamWrapper, long face_index, out FT_Face aface) { var args = streamWrapper.FT_Open_ArgsWin32; var result = _FT_Open_Face_Win32(library, ref args, (Win32Long)face_index, out var afacePointer); aface = new FT_Face(afacePointer); return(result); }
public static int FT_Load_Char(FT_Face face, ulong char_code, int load_flags) { return(_FT_Load_Char_Win32(face._pointer, (Win32ULong)char_code, load_flags)); }
public static int FT_Set_Pixel_Sizes(FT_Face face, uint pixel_width, uint pixel_height) { return(_FT_Set_Pixel_Sizes(face._pointer, pixel_width, pixel_height)); }
static extern FT_Error FT_New_Face_8(IntPtr library, string filepathname, FT_Long8 face_index, ref FT_Face aface);
static extern FT_Error FT_Done_Face_8(FT_Face face);
static extern FT_UInt FT_Get_Char_Index_8(FT_Face face, FT_ULong8 charcode);
static extern FT_Error FT_Load_Glyph_8(FT_Face face, FT_UInt glyph_index, Int32 load_flags);
// * // Run image manipulation // \return Pointer to image buffer which has been set in the constructor. // public override TextureBuffer process() { FT_Library ftlib = new FT_Library(); FT_Face face = new FT_Face(); FT_GlyphSlot slot = new FT_GlyphSlot(); FT_Error error = FT_Init_FreeType(ftlib); if (error == 0) { error = FT_New_Face(ftlib, getFontFileByName().c_str(), 0, face); if (error == FT_Err_Unknown_File_Format) Utils.log("FreeType ERROR: FT_Err_Unknown_File_Format"); else if (error != null) Utils.log("FreeType ERROR: FT_New_Face - " + StringConverter.toString(error)); else { FT_Set_Pixel_Sizes(face, 0, mFontSize); int px = (int)mX; int py = (int)mY; slot = face.glyph; for (int n = 0; n < mText.length(); n++) { error = FT_Load_Char(face, mText[n], FT_LOAD_RENDER); if (error != null) continue; for (int i = 0; i < (int)slot.bitmap.width; i++) { for (int j = 0; j < (int)slot.bitmap.rows; j++) { if (slot.bitmap.buffer[j * slot.bitmap.width + i] > 127) mBuffer.setPixel(px + i, py + j, mColour); } } px += slot.advance.x >> 6; py += slot.advance.y >> 6; } FT_Done_Face(face); Utils.log("Modify texture with text processing : " + mText); } FT_Done_FreeType(ftlib); } else Utils.log("FreeType ERROR: FT_Init_FreeType"); return mBuffer; }
static extern FT_Error FT_Set_Char_Size_8( FT_Face face, FT_F26Dot6_8 char_width, FT_F26Dot6_8 char_height, FT_UInt horz_resolution, FT_UInt vert_resolution);
// * // * Build a MultiShape from chars (one Shape per character) // * \exception Ogre::InternalErrorException Freetype error // * \todo Need to split shapes of multi region chars. For example the letter \c O // * has two shapes, but they are connected to one shape. // public MultiShape realizeShapes() { MultiShape retVal = new MultiShape(); FT_Library ftlib = new FT_Library(); FT_Face face = new FT_Face(); FT_GlyphSlot slot = new FT_GlyphSlot(); FT_Error error = FT_Init_FreeType(ftlib); if (error == 0) { error = FT_New_Face(ftlib, getFontFileByName().c_str(), 0, face); if (error == FT_Err_Unknown_File_Format) { //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __LINE__ macro: //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __FILE__ macro: throw ExceptionFactory.create(Mogre.ExceptionCodeType <Mogre.Exception.ExceptionCodes.ERR_INTERNAL_ERROR>(), "FreeType ERROR: FT_Err_Unknown_File_Format", "Procedural::TextShape::realizeShapes()", __FILE__, __LINE__); ; } else if (error != null) { //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __LINE__ macro: //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __FILE__ macro: throw ExceptionFactory.create(Mogre.ExceptionCodeType <Mogre.Exception.ExceptionCodes.ERR_INTERNAL_ERROR>(), "FreeType ERROR: FT_New_Face - " + StringConverter.toString(error), "Procedural::TextShape::realizeShapes()", __FILE__, __LINE__); ; } else { FT_Set_Pixel_Sizes(face, 0, mFontSize); int px = 0; int py = 0; slot = face.glyph; for (int n = 0; n < mText.length(); n++) { error = FT_Load_Char(face, mText[n], FT_LOAD_NO_BITMAP); if (error != null) { continue; } Shape s = new Shape(); int nContours = face.glyph.outline.n_contours; int startPos = 0; string tags = face.glyph.outline.tags; FT_Vector[] vec = face.glyph.outline.points; for (int k = 0; k < nContours; k++) { if (k > 0) { startPos = face.glyph.outline.contours[k - 1] + 1; } int endPos = face.glyph.outline.contours[k] + 1; Vector2 lastPoint = Vector2.ZERO; for (int j = startPos; j < endPos; j++) { if (FT_CURVE_TAG(tags[j]) == FT_CURVE_TAG_ON) { lastPoint = Vector2((float)vec[j].x, (float)vec[j].y); s.addPoint(lastPoint / 64.0f); } else { if (FT_CURVE_TAG(tags[j]) == FT_CURVE_TAG_CUBIC) { int prevPoint = j - 1; if (j == 0) { prevPoint = endPos - 1; } int nextIndex = j + 1; if (nextIndex >= endPos) { nextIndex = startPos; } Vector2[] nextPoint = new Vector2[nextIndex]((float)vec.x, (float)vec[nextIndex].y); if ((FT_CURVE_TAG(tags[prevPoint]) != FT_CURVE_TAG_ON) && (FT_CURVE_TAG(tags[prevPoint]) == FT_CURVE_TAG_CUBIC)) { BezierCurve2 bc = new BezierCurve2(); bc.addPoint(Vector2((float)vec[prevPoint].x, (float)vec[prevPoint].y) / 64.0f); bc.addPoint(Vector2((float)vec[j].x, (float)vec[j].y) / 64.0f); bc.addPoint(Vector2((float)vec[nextIndex].x, (float)vec[nextIndex].y) / 64.0f); s.appendShape(bc.realizeShape()); } } else { Vector2[] conicPoint = new Vector2[j]((float)vec.x, (float)vec[j].y); if (j == startPos) { if ((FT_CURVE_TAG(tags[endPos - 1]) != FT_CURVE_TAG_ON) && (FT_CURVE_TAG(tags[endPos - 1]) != FT_CURVE_TAG_CUBIC)) { Vector2[] lastConnic = new Vector2[endPos - 1]((float)vec.x, (float)vec[endPos - 1].y); lastPoint = (conicPoint + lastConnic) / 2; } } int nextIndex = j + 1; if (nextIndex >= endPos) { nextIndex = startPos; } Vector2[] nextPoint = new Vector2[nextIndex]((float)vec.x, (float)vec[nextIndex].y); bool nextIsConnic = (FT_CURVE_TAG(tags[nextIndex]) != FT_CURVE_TAG_ON) && (FT_CURVE_TAG(tags[nextIndex]) != FT_CURVE_TAG_CUBIC); if (nextIsConnic) { nextPoint = (conicPoint + nextPoint) / 2; } int pc = s.getPointCount(); BezierCurve2 bc = new BezierCurve2(); if (pc == 0) { bc.addPoint(Vector2.ZERO); } else { bc.addPoint(s.getPoint(pc - 1)); } bc.addPoint(lastPoint / 64.0f); bc.addPoint(conicPoint / 64.0f); bc.addPoint(nextPoint / 64.0f); if (pc == 0) { s.appendShape(bc.realizeShape()); } else { List <Vector2> subShape = bc.realizeShape().getPoints(); for (List <Vector2> .Enumerator iter = subShape.GetEnumerator(); iter.MoveNext(); iter++) { if (iter != subShape.GetEnumerator()) { s.addPoint(iter.Current); } } } if (nextIsConnic) { // //ORIGINAL LINE: lastPoint = nextPoint; lastPoint = (nextPoint); } } } } } s.close(); s.translate((float)px, (float)py); retVal.addShape(s); px += slot.advance.x >> 6; py += slot.advance.y >> 6; } FT_Done_Face(face); } FT_Done_FreeType(ftlib); } else { //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __LINE__ macro: //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __FILE__ macro: throw ExceptionFactory.create(Mogre.ExceptionCodeType <Mogre.Exception.ExceptionCodes.ERR_INTERNAL_ERROR>(), "FreeType ERROR: FT_Init_FreeTyp", "Procedural::TextShape::realizeShapes()", __FILE__, __LINE__); ; } return(retVal); }
public static void Main(string[] args) { //Init the Freetype library FreeType.Init(out FT_Library lib, out _); //Create a new FT_Face from a .ttf font file. FT_Face face = FT_Face.Create(lib, $@"{Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)}\Fonts\Roboto-Regular.ttf", 0); string s = ""; //Make an array of the chars we want to use. for (int i = 0; i < 256; i++) { s += (char)i; } //Create a new Textfont that we can use to render text with. Desired size is (auto, 48px) TextFont tf = new TextFont_Bitmap(face, new Vector2i(0, 48), s.ToCharArray()); //Initialize Glue, Glfw, Create a window/context set it as current and load the available OpenGL functions. Glue.Init(1280, 720, "Hello Text", out window); //Create a new TextMesh. TextMesh m = new TextMesh(); //Use the TextFont to create a texture atlas of the chars in the TextFont. tex = tf.CreateTexture2D(); Shader vertShader = new Shader(Shader.ShaderStage.Vertex, "#version 330 core", "layout (location = 0) in vec2 vertPos;", "layout (location = 1) in vec2 uv;", "uniform mat4 projMatr;", "uniform mat4 transMatr;", "out vec2 texCoord;", "void main()", "{", "gl_Position = projMatr * (vec4(vertPos,0,1.0) * transMatr);", "texCoord = uv;", "}"); Shader fragmentShader = new Shader(Shader.ShaderStage.Fragment, "#version 330 core", "in vec2 texCoord;", "out vec4 fragColor;", "uniform sampler2D fontBmp;", "void main()", "{", "fragColor = vec4(1,1,1,texture(fontBmp,texCoord).r);", "}"); vertShader.Compile(); fragmentShader.Compile(); ShaderProgram sp = new ShaderProgram(vertShader, fragmentShader); sp.Link(); sp.UseProgram(); GL.glEnable(GL.GL_CULL_FACE); GL.glEnable(GL.GL_BLEND); GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); GL.glFrontFace(GL.GL_CW); GL.glCullFace(GL.GL_BACK); Glfw.SwapInterval(1); int fontBmpLoc = sp.GetUniformLocation("fontBmp"); int projLoc = sp.GetUniformLocation("projMatr"); int transLoc = sp.GetUniformLocation("transMatr"); tex.Bind(0); GL.glUniform1i(fontBmpLoc, 0); Matrix4x4 ortho = Matrix4x4.CreateOrthographicProjection(0.0f, 1280f, 0.0f, 720f, -100f, 100f); Matrix4x4 transText = Matrix4x4.CreateTranslationMatrix(new Vector3(0f, 720f, 0f)); Matrix4x4 transBitmap = Matrix4x4.CreateTranslationMatrix(new Vector3(640f, 720f, 0f)); GL.glUniformMatrix4fv(projLoc, true, ortho); GL.glUniformMatrix4fv(transLoc, true, transText); CharacterString cs = new CharacterString(tf, ""); Mesh quad = Mesh.CreateScreenQuad(new Vector2i(640, 720)); while (!window.ShouldClose()) { GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); GL.glUniformMatrix4fv(transLoc, true, transText); m.Draw(); GL.glUniformMatrix4fv(transLoc, true, transBitmap); quad.Draw(); Thread.Sleep(16); cs.ReplaceCharacters(window.Input); m.SetText(cs, maxLineLength: 640); window.SwapBuffers(); Glfw.PollEvents(); } Glue.Terminate(); }
GlyphInfo RE_ConstructGlyphInfo(byte[] imageOut, out int xOut, out int yOut, out int maxHeight, FT_Face face, char c, bool calcHeight) { int i;
public TextFont_Bitmap(FT_Face face, Vector2i desiredSize, params char[] chars) : base(chars) { FT_Char[] ftChars = new FT_Char[chars.Length]; Vector2i largest = desiredSize; face.SetPixelSize((uint)desiredSize.x, (uint)desiredSize.y); for (int i = 0; i < chars.Length; i++) { FT_Char ftc = FT_Char.Load(face, chars[i], (int)FT_LOAD.RENDER); largest.x = ftc.Size.x > largest.x ? ftc.Size.x : largest.x; largest.y = ftc.Size.y > largest.y ? ftc.Size.y : largest.y; ftChars[i] = ftc; } //The size of a single char in the final bitmap. Vector2i charBmpSize = new Vector2i((int)Math.Ceiling(largest.x * 0.25f) * 4, (int)Math.Ceiling(largest.y * 0.25f) * 4); charLargestSize = charBmpSize; //Specifies the grid layout for all the glyphs. Vector2i charLayout = new Vector2i((int)Math.Sqrt(chars.Length), (int)Math.Ceiling((float)chars.Length / (int)Math.Sqrt(chars.Length))); //Final size of the font bitmap. Vector2i bmpSize = new Vector2i(charLayout.x * charBmpSize.x, charLayout.y * charBmpSize.y); size = bmpSize; bitmap = new byte[bmpSize.x * bmpSize.y]; //Add the data to the bitmap. for (int i = 0; i < ftChars.Length; i++) { //Calculate the cell we are going to write the data to. int y = (int)(i / (float)charLayout.x); int x = (int)(((i / (float)charLayout.x) - y) * charLayout.x); //Calculate the offset so that we keep the glyph centered in its cell. int xOffset = (int)((charBmpSize.x * (1f - ((float)ftChars[i].Size.x / charBmpSize.x))) * 0.5f); int yOffset = (int)((charBmpSize.y * (1f - ((float)ftChars[i].Size.y / charBmpSize.y))) * 0.5f); //Calculate where we should start writing the data. int sPos = (((y * charBmpSize.y) + yOffset) * bmpSize.x) + (x * charBmpSize.x) + xOffset; //Use a variable so we don't need to write ftChars[i] all the god damn time. FT_Char ftc = ftChars[i]; Character c = new Character(ftc, chars[i], new Box2D( new Vector2((float)((x * charBmpSize.x + xOffset) / (double)bmpSize.x), (float)((y * charBmpSize.y + yOffset) / (double)bmpSize.y)), new Vector2((float)((x * charBmpSize.x + xOffset + ftc.Size.x) / (double)bmpSize.x), (float)((y * charBmpSize.y + yOffset + ftc.Size.y) / (double)bmpSize.y)) ) ); characters.Add(chars[i], c); byte[] charBitmap = ftc.Bitmap; //Grab the bitmap for the character. //Write it to the final bitmap for (int _y = 0; _y < ftc.Size.y; _y++) { for (int _x = 0; _x < ftc.Size.x; _x++) { bitmap[sPos + (_y * bmpSize.x) + _x] = charBitmap[_x + (_y * ftc.Size.x)]; } } } }
// * // * Build a MultiShape from chars (one Shape per character) // * \exception Ogre::InternalErrorException Freetype error // * \todo Need to split shapes of multi region chars. For example the letter \c O // * has two shapes, but they are connected to one shape. // public MultiShape realizeShapes() { MultiShape retVal = new MultiShape(); FT_Library ftlib = new FT_Library(); FT_Face face = new FT_Face(); FT_GlyphSlot slot = new FT_GlyphSlot(); FT_Error error = FT_Init_FreeType(ftlib); if (error == 0) { error = FT_New_Face(ftlib, getFontFileByName().c_str(), 0, face); if (error == FT_Err_Unknown_File_Format) { //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __LINE__ macro: //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __FILE__ macro: throw ExceptionFactory.create(Mogre.ExceptionCodeType<Mogre.Exception.ExceptionCodes.ERR_INTERNAL_ERROR>(), "FreeType ERROR: FT_Err_Unknown_File_Format", "Procedural::TextShape::realizeShapes()", __FILE__, __LINE__); ; } else if (error != null) { //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __LINE__ macro: //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __FILE__ macro: throw ExceptionFactory.create(Mogre.ExceptionCodeType<Mogre.Exception.ExceptionCodes.ERR_INTERNAL_ERROR>(), "FreeType ERROR: FT_New_Face - " + StringConverter.toString(error), "Procedural::TextShape::realizeShapes()", __FILE__, __LINE__); ; } else { FT_Set_Pixel_Sizes(face, 0, mFontSize); int px = 0; int py = 0; slot = face.glyph; for (int n = 0; n < mText.length(); n++) { error = FT_Load_Char(face, mText[n], FT_LOAD_NO_BITMAP); if (error != null) continue; Shape s = new Shape(); int nContours = face.glyph.outline.n_contours; int startPos = 0; string tags = face.glyph.outline.tags; FT_Vector[] vec = face.glyph.outline.points; for (int k = 0; k < nContours; k++) { if (k > 0) startPos = face.glyph.outline.contours[k-1]+1; int endPos = face.glyph.outline.contours[k]+1; Vector2 lastPoint = Vector2.ZERO; for (int j = startPos; j < endPos; j++) { if (FT_CURVE_TAG(tags[j]) == FT_CURVE_TAG_ON) { lastPoint = Vector2((float)vec[j].x, (float)vec[j].y); s.addPoint(lastPoint / 64.0f); } else { if (FT_CURVE_TAG(tags[j]) == FT_CURVE_TAG_CUBIC) { int prevPoint = j - 1; if (j == 0) prevPoint = endPos - 1; int nextIndex = j + 1; if (nextIndex >= endPos) nextIndex = startPos; Vector2[] nextPoint = new Vector2[nextIndex]((float)vec.x, (float)vec[nextIndex].y); if ((FT_CURVE_TAG(tags[prevPoint]) != FT_CURVE_TAG_ON) && (FT_CURVE_TAG(tags[prevPoint]) == FT_CURVE_TAG_CUBIC)) { BezierCurve2 bc = new BezierCurve2(); bc.addPoint(Vector2((float)vec[prevPoint].x, (float)vec[prevPoint].y) / 64.0f); bc.addPoint(Vector2((float)vec[j].x, (float)vec[j].y) / 64.0f); bc.addPoint(Vector2((float)vec[nextIndex].x, (float)vec[nextIndex].y) / 64.0f); s.appendShape(bc.realizeShape()); } } else { Vector2[] conicPoint = new Vector2[j]((float)vec.x, (float)vec[j].y); if (j == startPos) { if ((FT_CURVE_TAG(tags[endPos-1]) != FT_CURVE_TAG_ON) && (FT_CURVE_TAG(tags[endPos-1]) != FT_CURVE_TAG_CUBIC)) { Vector2[] lastConnic = new Vector2[endPos - 1]((float)vec.x, (float)vec[endPos - 1].y); lastPoint = (conicPoint + lastConnic) / 2; } } int nextIndex = j + 1; if (nextIndex >= endPos) nextIndex = startPos; Vector2[] nextPoint = new Vector2[nextIndex]((float)vec.x, (float)vec[nextIndex].y); bool nextIsConnic = (FT_CURVE_TAG(tags[nextIndex]) != FT_CURVE_TAG_ON) && (FT_CURVE_TAG(tags[nextIndex]) != FT_CURVE_TAG_CUBIC); if (nextIsConnic) nextPoint = (conicPoint + nextPoint) / 2; int pc = s.getPointCount(); BezierCurve2 bc = new BezierCurve2(); if (pc == 0) bc.addPoint(Vector2.ZERO); else bc.addPoint(s.getPoint(pc - 1)); bc.addPoint(lastPoint / 64.0f); bc.addPoint(conicPoint / 64.0f); bc.addPoint(nextPoint / 64.0f); if (pc == 0) s.appendShape(bc.realizeShape()); else { List<Vector2> subShape = bc.realizeShape().getPoints(); for (List<Vector2>.Enumerator iter = subShape.GetEnumerator(); iter.MoveNext(); iter++) { if (iter != subShape.GetEnumerator()) s.addPoint(iter.Current); } } if (nextIsConnic) // //ORIGINAL LINE: lastPoint = nextPoint; lastPoint=(nextPoint); } } } } s.close(); s.translate((float)px, (float)py); retVal.addShape(s); px += slot.advance.x >> 6; py += slot.advance.y >> 6; } FT_Done_Face(face); } FT_Done_FreeType(ftlib); } else { //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __LINE__ macro: //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __FILE__ macro: throw ExceptionFactory.create(Mogre.ExceptionCodeType<Mogre.Exception.ExceptionCodes.ERR_INTERNAL_ERROR>(), "FreeType ERROR: FT_Init_FreeTyp", "Procedural::TextShape::realizeShapes()", __FILE__, __LINE__); ; } return retVal; }