// Compute outline for a single glyph // if flatten is true convert curve into a list of segments // out parameter advance is set to the default glyph advancement // if embold <> 0, embold the outline by the desired strength public Outline GetGlyphOutline(uint idx, out Outline.Point advance, bool flatten, float embold, int isteps) { // TODO: add outline caching ? // load glyph for c in face slot //int code = FT.FT_Load_Char(face_, (uint)c, FT.FT_LOAD_DEFAULT); // FT_LOAD_DEFAULT, FT_LOAD_NO_BITMAP, FT_LOAD_NO_SCALE ? int code = FT.FT_Load_Glyph(face_, idx, FT.FT_LOAD_DEFAULT); FT.CheckError(code); // Check that the glyph is in Outline format FT.FT_FaceRec facerec = FT.HandleToRecord <FT.FT_FaceRec>(face_); IntPtr slot = facerec.glyph; FT.FT_GlyphSlotRec slotrec = FT.HandleToRecord <FT.FT_GlyphSlotRec>(slot); if (slotrec.format != FT.GLYPH_FORMAT_OUTLINE) { throw new FTError(string.Format("Bad glyph format (0x{0:x4})", slotrec.format)); //throw new FTError("Bad glyph format (" + slotrec.format + ")"); } // Get glyph outline in gptr IntPtr gptr; code = FT.FT_Get_Glyph(slotrec, out gptr); FT.CheckError(code); // Embold outline if (embold != 0) { // Console.WriteLine("EMBOLD=" + embold); // IntPtr optr = FT.fthelper_glyph_get_outline_address(slot); FT.FT_Outline_Embolden(slotrec.outline, (int)(embold * 64 * 100)); // convert to 26.6 fractional format } // Decompose outline Outline outline = null; if (flatten) { outline = Outline.FlattenGlyph(slotrec, vectorScale_, isteps); } else { outline = Outline.DecomposeGlyph(slotrec, vectorScale_, isteps); } FT.FT_Done_Glyph(gptr); advance = new Outline.Point(slotrec.advance, vectorScale_); return(outline); }
public unsafe UnityEngine.Texture2D RenderIntoTexture(char c) { int code; FT.FT_FaceRec facerec = FT.HandleToRecord <FT.FT_FaceRec>(face_); IntPtr slot = facerec.glyph; code = FT.FT_Load_Char(face_, c, FT.FT_LOAD_RENDER /*|FT.FT_LOAD_TARGET_NORMAL*/); if (code != 0) { return(null); } FT.FT_GlyphSlotRec slotrec = FT.HandleToRecord <FT.FT_GlyphSlotRec>(slot); FTSharp.FT.FT_Bitmap ftbm = slotrec.bitmap; UnityEngine.Texture2D texbuffer = new UnityEngine.Texture2D((int)ftbm.width, (int)ftbm.rows, UnityEngine.TextureFormat.ARGB32, false); if (((int)ftbm.pixel_mode) != 2) { UnityEngine.Debug.LogError("Unsupported bitmap depth :" + ((int)ftbm.pixel_mode).ToString()); return(null); } // FT_PIXEL_MODE_MONO, //FT_PIXEL_MODE_GRAY, UnityEngine.Color32 [] clrs = texbuffer.GetPixels32(); int i = 0; // UNSAFE DOES NOT WORK IN THE WEB PLAYER ! for (int y = 0; y < ftbm.rows; y++) { long j = (((ftbm.rows - (1 + y)) * ftbm.pitch)); byte *bo = ((byte *)ftbm.buffer); for (int x = 0; x < ftbm.width; x++) { clrs[i].a = clrs[i].r = clrs[i].g = clrs[i].b = (bo[j + x]); i++; } } texbuffer.SetPixels32(clrs); texbuffer.Apply(); return(texbuffer); }
// Compute the Bounding box of a single glyph public BBox Measure(char c, out Outline.Point advance) { // load glyph for c in face slot int code = FT.FT_Load_Char(face_, (uint)c, (int)(FT.FT_LOAD_DEFAULT | (1 << 3))); // FT_LOAD_DEFAULT, FT_LOAD_NO_BITMAP, FT_LOAD_NO_SCALE ? FT.CheckError(code); // Check that the glyph is in Outline format FT.FT_FaceRec facerec = FT.HandleToRecord <FT.FT_FaceRec>(face_); IntPtr slot = facerec.glyph; FT.FT_GlyphSlotRec slotrec = FT.HandleToRecord <FT.FT_GlyphSlotRec>(slot); if (slotrec.format != FT.GLYPH_FORMAT_OUTLINE) { throw new FTError("Bad glyph format (" + slotrec.format + ")"); } // get glyph in gptr IntPtr gptr; code = FT.FT_Get_Glyph(slotrec, out gptr); FT.CheckError(code); FT.FT_BBox ft_bbox; FT.FT_Glyph_Get_CBox(gptr, 0, out ft_bbox); FT.FT_Done_Glyph(gptr); BBox bbox = new BBox(ft_bbox, vectorScale_); advance = new Outline.Point(slotrec.advance, vectorScale_); return(bbox); }
float vectorScale_; // (point_size * resolution)/ (72 * face->units_per_em) public Font(string path, float height, uint dpi) { lib = FTLibrary.Instance; dpi_ = dpi; int code = FT.FT_New_Face(lib.Handle, path, 0, out face_); FT.CheckError(code); FT.FT_FaceRec facerec = FT.HandleToRecord <FT.FT_FaceRec>(face_); familyName_ = facerec.family_name; styleName_ = facerec.style_name; face_has_kerning_ = ((facerec.face_flags & FT.FT_FACE_FLAG_KERNING) != 0); face_units_per_EM_ = facerec.units_per_EM; face_height_ = facerec.height; //Console.WriteLine("new FONT = unit-per-em=" + face_units_per_EM_); //setCharSize(pointsize); setCharHeight(height); }
public void RenderText(string text, DrawBitmapF drawBitmap, int penx, int peny) { int code; FT.FT_FaceRec facerec = FT.HandleToRecord <FT.FT_FaceRec>(face_); IntPtr slot = facerec.glyph; foreach (char c in text) { code = FT.FT_Load_Char(face_, c, FT.FT_LOAD_RENDER /*|FT.FT_LOAD_TARGET_NORMAL*/); if (code != 0) { continue; } FT.FT_GlyphSlotRec slotrec = FT.HandleToRecord <FT.FT_GlyphSlotRec>(slot); //Bitmap bitmap = new Bitmap(slotrec.bitmap); // drawBitmap(bitmap, penx + slotrec.bitmap_left, peny + slotrec.bitmap_top); //drawBitmap(bitmap, penx + slotrec.bitmap_left, peny - slotrec.bitmap_top); drawBitmap(slotrec.bitmap, penx + slotrec.bitmap_left, peny - slotrec.bitmap_top); penx += (slotrec.advance.x >> 6); } }