public bool AddKerning(int first, int second, ref double x, ref double y) { if (m_CurrentFace != null && first != 0 && second != 0 && ANT.ANT_HAS_KERNING(m_CurrentFace.face_flags)) { ANT_Vector add_kerning_delta = new ANT_Vector(); ANT.ANT_Get_Kerning(m_CurrentFace, first, second, ANT_Kerning_Mode.ANT_KERNING_DEFAULT, add_kerning_delta); double dx = ANT.ANT_int26p6_to_double(add_kerning_delta.x); double dy = ANT.ANT_int26p6_to_double(add_kerning_delta.y); if (m_GlyphRenderType == GlyphRenderType.Outline) { m_Matrix.Transform2x2(ref dx, ref dy); } x += dx; y += dy; return(true); } return(false); }
public void FinishCreating() { bool hasKerning = false; if (m_pFTFace != null) { hasKerning = ANT.ANT_HAS_KERNING(m_pFTFace); } if (!hasKerning || !m_pFontAtlas.UseKerning) { ReleaseFace(); } }
public int DrawString(Graphics graphics, Bitmap bitmap, int x, int y, string text) { char c; int currX = x; int n = 0; ANT_Vector kerning = new ANT_Vector(); int ixGlyph; int ixGlyphPrev = 0; bool hasKerning = false; if (m_pFTFace != null) { hasKerning = ANT.ANT_HAS_KERNING(m_pFTFace); } int len = text.Length; while (n < len) { c = text[n]; ANTBitmapChar iter; if (m_mapBitmapChar.TryGetValue(c, out iter)) { if (hasKerning) { // get kerning ixGlyph = ANT.ANT_Get_Char_Index(m_pFTFace, c); if (hasKerning && ixGlyphPrev != 0 && ixGlyph != 0) { ANT.ANT_Get_Kerning(m_pFTFace, ixGlyphPrev, ixGlyph, ANT_Kerning_Mode.ANT_KERNING_DEFAULT, kerning); currX += kerning.x >> 6; } ixGlyphPrev = ixGlyph; } iter.Render(graphics, bitmap, currX, y); currX += iter.GetXAdvance(); } n++; } return(currX); }
public int GetWidth(string text) { int currX = 0; int n = 0; char c; ANT_Vector kerning = new ANT_Vector(); int ixGlyph; int ixGlyphPrev = 0; bool hasKerning = false; if (m_pFTFace != null) { hasKerning = ANT.ANT_HAS_KERNING(m_pFTFace); } while (text[n] != 0) { c = text[n]; ANTBitmapChar iter; if (m_mapBitmapChar.TryGetValue(c, out iter)) { if (hasKerning) { // get kerning ixGlyph = ANT.ANT_Get_Char_Index(m_pFTFace, c); if (hasKerning && ixGlyphPrev != 0 && ixGlyph != 0) { ANT.ANT_Get_Kerning(m_pFTFace, ixGlyphPrev, ixGlyph, ANT_Kerning_Mode.ANT_KERNING_DEFAULT, kerning); currX += kerning.x >> 6; } ixGlyphPrev = ixGlyph; } currX += iter.GetXAdvance(); } n++; } return(currX); }
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); }
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); }