void DoWork() { ANT_Library library; ANT_Face face; ANT_GlyphSlot slot; ANT_Error error; string filename; string text; int num_chars; bool use_kerning; int previous; int pen_x, pen_y, n; filename = Common.Example_AltNETType_FontFileName; text = "AltNETType (transformation + centering + kerning)";// Common.Pangram; num_chars = text.Length; // ... initialize library ... // ... create face object ... // ... set character size ... { // initialize library error = ANT.ANT_Init_AltNETType(out library); // error handling omitted // create face object error = ANT.ANT_New_Face(library, filename, 0, out face); // error handling omitted if (error != ANT_Error.ANT_Err_Ok) { return; } // use 50pt at 100dpi // set character size error = ANT.ANT_Set_Char_Size(face, 28 * 64, 0, 96, 0); // error handling omitted } // a small shortcut slot = face.glyph; // start at (0,0) pen_x = 0; pen_y = 0; num_glyphs = 0; use_kerning = ANT.ANT_HAS_KERNING(face); previous = 0; ANT_Vector delta = new ANT_Vector(); for (n = 0; n < num_chars; n++) { glyph = glyphs[n]; if (glyph == null) { glyphs[n] = glyph = new TGlyph(); } // convert character code to glyph index glyph.index = ANT.ANT_Get_Char_Index(face, text[n]); // retrieve kerning distance and move pen position if (use_kerning && previous != 0 && glyph.index != 0) { ANT.ANT_Get_Kerning(face, previous, glyph.index, ANT_Kerning_Mode.ANT_KERNING_DEFAULT, delta); pen_x += delta.x >> 6; } // store current pen position if (glyph.pos == null) { glyph.pos = new ANT_Vector(); } glyph.pos.x = pen_x; glyph.pos.y = pen_y; // load glyph image into the slot without rendering error = ANT.ANT_Load_Glyph(face, glyph.index, ANT_LOAD.ANT_LOAD_DEFAULT); if (error != ANT_Error.ANT_Err_Ok) { // ignore errors, jump to next glyph continue; } // extract glyph image and store it in our table error = ANT.ANT_Get_Glyph(face.glyph, out glyph.image); if (error != ANT_Error.ANT_Err_Ok) { // ignore errors, jump to next glyph continue; } // translate the glyph image now ANT.ANT_Glyph_Transform(glyph.image, null, glyph.pos); // increment pen position pen_x += slot.advance.x >> 6; // record current glyph index previous = glyph.index; // increment number of glyphs num_glyphs++; } ANT_Vector start = new ANT_Vector(); // transformation matrix ANT_Matrix matrix = new ANT_Matrix(); ANT_Glyph image; ANT_Vector pen = new ANT_Vector(); ANT_BBox bbox = new ANT_BBox(); double angle; ANT_BBox string_bbox; compute_string_bbox(out string_bbox); int my_target_width = WIDTH; int my_target_height = HEIGHT; // compute string dimensions in integer pixels int string_width = string_bbox.xMax - string_bbox.xMin; int string_height = string_bbox.yMax - string_bbox.yMin; // use -30 degrees angle = (330.0 / 360) * 3.14159 * 2; // compute start pen position in 26.6 cartesian pixels start.x = (int)(((my_target_width - string_width * Math.Cos(angle) - string_height * Math.Sin(angle)) / 2 + string_bbox.yMax * Math.Sin(angle)) * 64); // start.y = ((my_target_height - string_height) / 2) * 64; // need to center bitmaps (not base line) start.y = (int)(((my_target_height - string_height * Math.Cos(angle) - string_width * Math.Sin(angle)) / 2 - string_bbox.yMin * Math.Cos(angle)) * 64); // set up transform (a rotation here) matrix.xx = (int)(Math.Cos(angle) * 0x10000L); matrix.xy = (int)(-Math.Sin(angle) * 0x10000L); matrix.yx = (int)(Math.Sin(angle) * 0x10000L); matrix.yy = (int)(Math.Cos(angle) * 0x10000L); pen.CopyFrom(start); for (n = 0; n < num_glyphs; n++) { // create a copy of the original glyph error = ANT.ANT_Glyph_Copy(glyphs[n].image, out image); if (error != ANT_Error.ANT_Err_Ok) { continue; } // transform copy (this will also translate it to the // correct position ANT.ANT_Glyph_Transform(image, matrix, pen); // check bounding box; if the transformed glyph image // is not in our target surface, we can avoid rendering it ANT.ANT_Glyph_Get_CBox(image, ANT_Glyph_BBox_Mode.ANT_GLYPH_BBOX_PIXELS, bbox); if (bbox.xMax <= 0 || bbox.xMin >= my_target_width || bbox.yMax <= 0 || bbox.yMin >= my_target_height) { //continue; } else { // convert glyph image to bitmap (destroy the glyph copy!) error = ANT.ANT_Glyph_To_Bitmap(ref image, ANT_Render_Mode.ANT_RENDER_MODE_NORMAL, null, // no additional translation true); // destroy copy in "image" if (error == ANT_Error.ANT_Err_Ok) { ANT_BitmapGlyph bit = (ANT_BitmapGlyph)image; draw_bitmap(bit.bitmap, bit.left, my_target_height - bit.top); } } // increment pen position -- // we don't have access to a slot structure, // so we have to use advances from glyph structure // (which are in 16.16 fixed float format) pen.x += image.advance.x >> 10; pen.y += image.advance.y >> 10; ANT.ANT_Done_Glyph(ref image); } // show_image(); ANT.ANT_Done_Face(ref face); ANT.ANT_Done_AltNETType(ref library); }
public void AddFont(string strFileName, int size, string szLetters) { if (string.IsNullOrEmpty(strFileName) || !Alt.IO.VirtualFile.Exists(strFileName)) { return; } if (m_Library == null) { if (ANT.ANT_Init_AltNETType(out m_Library) != ANT_Error.ANT_Err_Ok) { throw new Exception("ANT_Init_FreeType failed"); } } // The Object In Which FreeType Holds Information On A Given // Font Is Called A "face". ANT_Face face; string file = strFileName; // This Is Where We Load In The Font Information From The File. if (ANT.ANT_New_Face(m_Library, file, 0, out face) != ANT_Error.ANT_Err_Ok) { throw new Exception("no font: " + file); } // FreeType Measures Font Size In Terms Of 1/64ths Of Pixels. ANT.ANT_Set_Char_Size(face, size * 64, size * 64, 72, 72); int len = szLetters.Length; int n; ANTBitmapChar pFTBitmapChar; ANT_Glyph pGlyph; ANTBitmapFont pANTBitmapFont = new ANTBitmapFont(this); pANTBitmapFont.LineHeight = face.size.metrics.height >> 6; pANTBitmapFont.SetFTFace(face); m_BitmapFonts.Add(pANTBitmapFont); char c; int height; int yOffset; int ixGlyph; for (n = 0; n < len; n++) { c = szLetters[n]; // check that the character hasn't already been processed if (pANTBitmapFont.GetChar(c) == null) { // Load The Glyph For Our Character. ixGlyph = ANT.ANT_Get_Char_Index(face, c); if (ixGlyph == 0) { Console.WriteLine("character doesn't exist in font: '" + c + "'"); } else { if (ANT.ANT_Load_Glyph(face, ixGlyph, ANT_LOAD.ANT_LOAD_DEFAULT) != ANT_Error.ANT_Err_Ok) { throw new Exception("ANT_Load_Glyph failed"); } // Move The Face's Glyph Into A Glyph Object. if (ANT.ANT_Get_Glyph(face.glyph, out pGlyph) != ANT_Error.ANT_Err_Ok) { throw new Exception("ANT_Get_Glyph failed"); } pFTBitmapChar = new ANTBitmapChar(c); // all metrics dimensions are multiplied by 64, so we have to divide by 64 height = face.glyph.metrics.height >> 6; yOffset = pANTBitmapFont.LineHeight - (face.glyph.metrics.horiBearingY >> 6); pFTBitmapChar.SetOffsets(face.glyph.metrics.horiBearingX >> 6, yOffset); pFTBitmapChar.SetSize(face.glyph.metrics.width >> 6, height); pFTBitmapChar.SetXAdvance(face.glyph.metrics.horiAdvance >> 6); pFTBitmapChar.SetGlyph(pGlyph); m_BitmapChars.Add(pFTBitmapChar); pANTBitmapFont.AddChar(c, pFTBitmapChar); } } } }
void DoWork() { ANT_Library library; ANT_Face face; ANT_GlyphSlot slot; ANT_Error error; string filename; string text; int num_chars; int glyph_index; bool use_kerning; int previous; int pen_x, pen_y, n; filename = Common.Example_AltNETType_FontFileName; text = "AltNETType (kerning + centering)";// Common.Pangram; num_chars = text.Length; // ... initialize library ... // ... create face object ... // ... set character size ... { // initialize library error = ANT.ANT_Init_AltNETType(out library); // error handling omitted // create face object error = ANT.ANT_New_Face(library, filename, 0, out face); // error handling omitted if (error != ANT_Error.ANT_Err_Ok) { return; } // use 36pt at 100dpi // set character size error = ANT.ANT_Set_Char_Size(face, 36 * 64, 0, 96, 0); // error handling omitted } // a small shortcut slot = face.glyph; // start at (0,0) pen_x = 0; pen_y = 0; num_glyphs = 0; use_kerning = ANT.ANT_HAS_KERNING(face); previous = 0; ANT_Vector delta = new ANT_Vector(); for (n = 0; n < num_chars; n++) { // convert character code to glyph index glyph_index = ANT.ANT_Get_Char_Index(face, text[n]); // retrieve kerning distance and move pen position if (use_kerning && previous != 0 && glyph_index != 0) { ANT.ANT_Get_Kerning(face, previous, glyph_index, ANT_Kerning_Mode.ANT_KERNING_DEFAULT, delta); pen_x += delta.x >> 6; } // store current pen position if (pos[num_glyphs] == null) { pos[num_glyphs] = new ANT_Vector(); } pos[num_glyphs].x = pen_x; pos[num_glyphs].y = pen_y; // load glyph image into the slot without rendering error = ANT.ANT_Load_Glyph(face, glyph_index, ANT_LOAD.ANT_LOAD_DEFAULT); if (error != ANT_Error.ANT_Err_Ok) { // ignore errors, jump to next glyph continue; } // extract glyph image and store it in our table error = ANT.ANT_Get_Glyph(face.glyph, out glyphs[num_glyphs]); if (error != ANT_Error.ANT_Err_Ok) { // ignore errors, jump to next glyph continue; } // increment pen position pen_x += slot.advance.x >> 6; // record current glyph index previous = glyph_index; // increment number of glyphs num_glyphs++; } ANT_BBox string_bbox; compute_string_bbox(out string_bbox); int my_target_width = WIDTH; int my_target_height = HEIGHT; // compute string dimensions in integer pixels int string_width = string_bbox.xMax - string_bbox.xMin; int string_height = string_bbox.yMax - string_bbox.yMin; // compute start pen position in 26.6 cartesian pixels int start_x = ((my_target_width - string_width) / 2) * 64; // int start_y = ((my_target_height - string_height) / 2) * 64; // need to center bitmaps (not base line) int start_y = ((my_target_height - string_height) / 2 - string_bbox.yMin) * 64; ANT_Vector pen = new ANT_Vector(); for (n = 0; n < num_glyphs; n++) { ANT_Glyph image = glyphs[n]; pen.x = start_x + pos[n].x * 64; pen.y = start_y + pos[n].y * 64; error = ANT.ANT_Glyph_To_Bitmap(ref image, ANT_Render_Mode.ANT_RENDER_MODE_NORMAL, pen, false); if (error == ANT_Error.ANT_Err_Ok) { ANT_BitmapGlyph bit = (ANT_BitmapGlyph)image; draw_bitmap(bit.bitmap, bit.left, my_target_height - bit.top); ANT.ANT_Done_Glyph(ref image); } } // show_image(); ANT.ANT_Done_Face(ref face); ANT.ANT_Done_AltNETType(ref library); }