public TTFTextOutline GetGlyph(Font f, char c) { AndroidJNI.PushLocalFrame(0); AndroidJavaObject path = AndroidISysFont.Call <AndroidJavaObject>("GetGlyph", f.typeface, "" + c ); AndroidJavaObject pm = AndroidISysFont.Call <AndroidJavaObject>("GetPathMeasure", path ); TTFTextOutline tto = new TTFTextOutline(); bool cont = true; while (cont) { List <Vector3> tb = new List <Vector3>(); float [] res = AndroidISysFont.Call <float []>("GetBoundary", pm, 0); int rl2 = res.Length / 2; for (int ci = 0; ci < rl2; ci++) { tb.Add(new Vector3(res[ci * 2], res[ci * 2 + 1], 0)); } tto.AddBoundary(tb); cont = AndroidISysFont.Call <bool>("NextBoundary", pm); } path.Dispose(); pm.Dispose(); AndroidJNI.PopLocalFrame(System.IntPtr.Zero); return(tto); }
public BEnumerator(TTFTextOutline o, int begin, int end) { outline = o; begin_ = begin; end_ = end; curr_ = begin_ - 1; }
public TTFTextOutline GetGlyph(Font f, char c) { AndroidJNI.PushLocalFrame(0); AndroidJavaObject path=AndroidISysFont.Call<AndroidJavaObject>("GetGlyph", f.typeface, ""+c ); AndroidJavaObject pm= AndroidISysFont.Call<AndroidJavaObject>("GetPathMeasure", path ); TTFTextOutline tto=new TTFTextOutline(); bool cont=true ; while (cont) { List<Vector3> tb=new List<Vector3>(); float [] res=AndroidISysFont.Call<float []>("GetBoundary",pm,0); int rl2=res.Length/2; for (int ci=0;ci<rl2;ci++) { tb.Add(new Vector3(res[ci*2],res[ci*2+1],0)); } tto.AddBoundary(tb); cont=AndroidISysFont.Call<bool>("NextBoundary",pm); } path.Dispose(); pm.Dispose(); AndroidJNI.PopLocalFrame(System.IntPtr.Zero); return tto; }
// Copy an outline public TTFTextOutline(TTFTextOutline other) { nvertices = other.nvertices; points = new List <Vector3> (other.points); blengthes = new List <int> (other.blengthes); max = other.max; min = other.min; size = other.size; advance = other.advance; }
public Boundary(TTFTextOutline o, int begin, int end) { if (end > o.points.Count) { Debug.LogError("Bad boundary!"); } outline = o; begin_ = begin; end_ = end; }
public void Append(TTFTextOutline o, Vector3 offset) { foreach (TTFTextOutline.Boundary boundary in o.boundaries) { List <Vector3> lst = new List <Vector3> (boundary.Count); foreach (Vector3 v in boundary) { lst.Add(v + offset); } AddBoundary(lst); } advance += o.advance; }
public override TTFTextOutline Apply(TTFTextOutline outline, object parameters) { AnimationCurve ac1 = ((TTFTextStyle.SerializableAnimationCurve)((parameters as Parameters).XMorph)).GetAnimcurve(); foreach (Boundary v in outline.boundaries) { int vlen = v.Count; for (int i = 0; i < vlen; ++i) { v[i] = new Vector3(ac1.Evaluate(v[i].x), v[i].y, v[i].z); } } return(outline); }
public override TTFTextOutline Apply(TTFTextOutline outline, object parameters) { Parameters p = (parameters as Parameters); float amount = p.Amount / 100f; foreach (Boundary v in outline.boundaries) { int vlen = v.Count; for (int i = 0; i < vlen; ++i) { v[i] += new Vector3(Random.Range(-amount, amount), Random.Range(-amount, amount), Random.Range(-amount, amount)); } } return(outline); }
public override TTFTextOutline Apply(TTFTextOutline outline, object parameters) { float strength = (parameters as Parameters).Amount; strength /= 40f; if (strength == 0f) { return(new TTFTextOutline(outline)); } Vector3 so = new Vector3(strength, strength, 0); TTFTextOutline res = new TTFTextOutline(); Vector3[] nv = new Vector3[outline.nvertices]; Vector3[] d = new Vector3[outline.nvertices]; foreach (Boundary v in outline.boundaries) { int vlen = v.Count; for (int i = 0; i < vlen; ++i) { d[i] = (Quaternion.AngleAxis(90f, Vector3.forward) * (v[(i + 1) % vlen] - v[i])).normalized * strength; } for (int i = 0; i < vlen; ++i) { int ni = (i + 1) % vlen; if (!TTFTextInternal.Intersection.GetIntersection(v[i] + d[i], v[ni] + d[i], v[ni] + d[ni], v[(i + 2) % vlen] + d[ni], out nv[ni])) { nv[ni] = so + Vector3.Lerp(v[ni] + d[i], v[ni] + d[ni], 0.5f); } } res.AddBoundary(nv, vlen); } res.advance = outline.advance; return(res); }
public static Mesh Triangulate(TTFTextOutline outline, bool expecode) { Mesh mesh = new Mesh(); #if !TTFTEXT_LITE if (expecode) { return(P2TTriangulate(outline, mesh)); } else { #endif #if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_EDITOR return(TTriangulate(outline, mesh)); #else Debug.LogError("Triangulate need to be called with Poly2Tri Lib"); return(null); #endif #if !TTFTEXT_LITE } #endif }
// this version will block until all character are downloaded... public IEnumerable SyncGetOutlineForLetter(string fontid, string characters) { TTFTextOutline [] res = new TTFTextOutline[characters.Length]; // for each character TTFTextFontStoreFont f = GetFont(fontid); if (f == null) { IEnumerable r = null; do { r = DoSyncDownloadOutline(fontid, f.additionalChar); if (r.GetType() == typeof(WaitForSeconds)) { yield return(r); } } while (r.GetType() == typeof(WaitForSeconds)); } foreach (char c in characters) { if (!f.HasCharacter(c)) { f.AddRequiredCharacters(characters); IEnumerable r = null; do { r = DoSyncDownloadOutline(fontid, f.additionalChar); if (r.GetType() == typeof(WaitForSeconds)) { yield return(r); } } while (r.GetType() == typeof(WaitForSeconds)); } } yield return(res); }
// Use this for initialization void Start() { ttm = transform.parent.GetComponent <TTFText>(); tts = GetComponent <TTFSubtext>(); TTFTextOutline o = TTFTextInternal.Engine.MakeOutline(tts.Text, ttm.Hspacing, ttm.Embold, ttm); foreach (TTFTextOutline.Boundary bn in o.boundaries) { b = bn; break; } sz2 = o.GetSize() / 2; if (b != null) { but = b.GetUniformTraverser(); flare = transform.FindChild("Flare"); flare2 = transform.FindChild("Flare2"); flare3 = transform.FindChild("Flare3"); } }
/// <summary> /// Tries to build a whole charset according current parameters of a textmesh object /// </summary> public void BuildCharSet(TTFText tm) { #if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_EDITOR int istep=TTFTextFontStore.Instance.defaultInterpolationSteps; charset = new TTFTextOutline[0x80]; charset_advance = new Vector3[0x80]; System.Text.ASCIIEncoding ae = new System.Text.ASCIIEncoding(); TTF.Font font = TTFTextInternal.Utilities.TryOpenFont(tm.InitTextStyle,1); if (font == null) { Debug.LogError("(TTFText) BuildCharSet: no font found"); return; } height=font.Height; for (byte i = 0x20; i < 0x7F; i++) { string s = ae.GetString(new byte [] {i}); charset[i] = TTFTextInternal.Engine.MakeNativeOutline(s, 1,0,font,tm.OrientationReversed,istep); charset_advance[i] = charset[i].advance; } // Additional Custom Characters AddRequiredCharacters(TTFTextFontStore.Instance.defaultAdditionalCharacters + (tm.InitTextStyle.GetFontEngineParameters(1) as TTFTextInternal.FontStoreFontEngine.Parameters).additionalCharacters); addCharset = new TTFTextOutline[additionalChar.Length]; int idx = 0; foreach (char c in additionalChar) { addCharset[idx] = TTFTextInternal.Engine.MakeNativeOutline("" + c, 1, 0, font,tm.OrientationReversed,istep); ++idx; } font.Dispose(); _needRebuild=false; #endif }
public override TTFTextOutline Apply(TTFTextOutline outline, object parameters) { Parameters p = (parameters as Parameters); TTFTextOutline no = new TTFTextOutline(); Vector3 [] tv = new Vector3[p.ngons]; foreach (Boundary v in outline.boundaries) { int vlen = v.Count; for (int i = 0; i < vlen; ++i) { for (int r = 0; r < p.ngons; r++) { float a = -(p.phase + (((float)r) / p.ngons)) * Mathf.PI * 2; tv[r] = v[i] + new Vector3(Mathf.Cos(a) * p.radius * 0.01f, Mathf.Sin(a) * p.radius * 0.01f, 0); } no.AddBoundary(tv); } } return(no); }
public TTFTextOutline ApplyMask(bool [] b) { int cnt = 0; TTFTextOutline r = new TTFTextOutline(); foreach (Boundary cb in boundaries) { List <Vector3> nb = new List <Vector3> (); foreach (Vector3 v in cb) { if (b [cnt++]) { nb.Add(v); } } if (nb.Count > 0) { r.AddBoundary(nb); } } r.advance = advance; return(r); }
// This is an alternative way of generating a mesh from a contour // TODO: Improve /ensure pipe orientation is correct public static void Piped(ref Mesh extrudedMesh, TTFTextOutline outline, float r, int nr) { extrudedMesh.Clear(); if (outline.numVertices < 2) { return; } int nc = outline.numVertices * nr; Vector3 [] vertices = new Vector3[nc]; Vector2 [] uvs = new Vector2[nc]; int [] et = new int[nc * 6]; int cnt = 0; int ecnt = 0; foreach (TTFTextOutline.Boundary contour in outline.boundaries) { if (contour.Count >= 2) { Vector3 pv = contour[contour.Count - 1]; Vector3 cv = contour[0]; Vector3 nv = contour[1]; int bcnt = cnt; for (int i = 0; i < contour.Count; i++) { //Vector3 ov=(nv-pv); Quaternion q1 = Quaternion.FromToRotation((nv - cv), (cv - pv)); Quaternion q2 = Quaternion.Slerp(Quaternion.identity, q1, 0.5f); Vector3 ov = q2 * (nv - cv); ov.Normalize(); for (int j = 0; j < nr; j++) { //vertices[cnt]=cv+Quaternion.AngleAxis(j*360f/nr,ov)*Quaternion.Euler(0,90,90)*ov*r; vertices[cnt] = cv + Quaternion.AngleAxis(j * 360f / nr, ov) * Vector3.forward * r; uvs[cnt] = Vector2.zero; int ni = (i + 1) % contour.Count; et[ecnt++] = bcnt + nr * i + ((j + 1) % nr); et[ecnt++] = bcnt + nr * i + j; et[ecnt++] = bcnt + nr * ni + j; et[ecnt++] = bcnt + nr * ni + ((j + 1) % nr); et[ecnt++] = bcnt + nr * i + ((j + 1) % nr); et[ecnt++] = bcnt + nr * ni + j; cnt++; } pv = cv; cv = nv; nv = contour[(i + 2) % contour.Count]; } } } extrudedMesh.Clear(); extrudedMesh.name = "piped"; extrudedMesh.vertices = vertices; extrudedMesh.uv = uvs; extrudedMesh.subMeshCount = 1; extrudedMesh.SetTriangles(et, 0); extrudedMesh.RecalculateNormals(); }
public override TTFTextOutline Apply(TTFTextOutline outline, object parameters) { float rotate; float strength = (parameters as Parameters).Amount; strength /= 40f; //Vector3 so = new Vector3(strength/2f,strength/2f,0); //Vector3 so = new Vector3 (strength, strength, 0); Vector3 tr = Vector3.zero; Vector3 so = Vector3.zero; if (Mathf.Abs(strength) < 0.001f) { return(new TTFTextOutline(outline)); } int orientation = 1; if (orientation == 1) // True type ? { rotate = -Mathf.PI / 2; } else { rotate = Mathf.PI / 2; } TTFTextOutline r = new TTFTextOutline(); foreach (Boundary cb in outline.boundaries) { int clen = cb.Count; Vector3 [] nb = new Vector3 [clen]; if (clen > 0) { Vector3 pv = cb [clen - 1], v = cb [0], nv; for (int ctr = 0; ctr < (clen + 20); ctr++) { nv = cb [(ctr + 1) % clen]; bool skip_this_vertex = false; // We have actually keep all vertice // because extrusion rely on all outline having the same num of vertices if ((nv - v).magnitude < 0.001f) { if (ctr == 0) { //nb [0] = (v + so + tr); nb [ctr % clen] = (v + so); } else { nb [ctr % clen] = nb [(ctr - 1) % clen]; } skip_this_vertex = true; } if (!skip_this_vertex) { Vector2 d1 = v - pv; Vector3 d2 = nv - v; Vector3 d3; float angle_in = Mathf.Atan2(d1.x, d1.y); float angle_out = Mathf.Atan2(d2.x, d2.y); float angle_diff2 = ((angle_out - angle_in + 3 * Mathf.PI) % (Mathf.PI * 2) - Mathf.PI) / 2f; float scale = Mathf.Sign(Mathf.Cos(angle_diff2)); // * Mathf.Cos( angle_diff2/8 ); //float scale=Mathf.Tan(Mathf.Cos(angle_diff2)*1000)/Mathf.PI; //if (scale==0) {scale=1;} scale = 1; //float e = angle_in /*+ rotate*/ + angle_diff2; float e = angle_in + rotate + angle_diff2; // we progress in the direction of the bissetrix //d3=(new Vector3(Mathf.Cos(-e),Mathf.Sin(-e)))/strength; //d3=(new Vector3(Mathf.Cos(-e),Mathf.Sin(-e)))*strength; //d3=nv-pv;d3.Normalize(); //d3=(new Vector3(Mathf.Cos(-e),Mathf.Sin(-e)))*(strength / scale); //d3=(new Vector3(Mathf.Cos(-e),Mathf.Sin(-e)))*strength; d3 = (new Vector3(Mathf.Cos(-e), Mathf.Sin(-e))) * (strength * scale); tr = new Vector2(-d3.y, d3.x); nb [ctr % clen] = (v + so + tr); //nb [ctr % clen] =v+so; //nb [ctr % clen] = (v + tr); //} pv = v; v = nv; } } } if (nb.Length > 0) { r.AddBoundary(nb); } } r.advance = outline.advance; //Debug.Log(r.MaxDist()); //Debug.Log(r.boundaries) //r.Check(); return(r); }
public virtual TTFTextOutline Apply(TTFTextOutline outline, object parameters) { return(outline); }
// This is an alternative way of generating a mesh from a contour // TODO: Improve /ensure pipe orientation is correct public static void Piped(ref Mesh extrudedMesh, TTFTextOutline outline , float r, int nr) { extrudedMesh.Clear(); if (outline.numVertices < 2) { return; } int nc=outline.numVertices * nr; Vector3 [] vertices=new Vector3[nc]; Vector2 [] uvs=new Vector2[nc]; int []et =new int[nc*6]; int cnt=0; int ecnt=0; foreach(TTFTextOutline.Boundary contour in outline.boundaries) { if (contour.Count>=2) { Vector3 pv=contour[contour.Count-1]; Vector3 cv=contour[0]; Vector3 nv=contour[1]; int bcnt=cnt; for(int i=0;i<contour.Count;i++) { //Vector3 ov=(nv-pv); Quaternion q1=Quaternion.FromToRotation((nv-cv),(cv-pv)); Quaternion q2=Quaternion.Slerp(Quaternion.identity,q1,0.5f); Vector3 ov=q2*(nv-cv); ov.Normalize(); for (int j=0;j<nr;j++) { //vertices[cnt]=cv+Quaternion.AngleAxis(j*360f/nr,ov)*Quaternion.Euler(0,90,90)*ov*r; vertices[cnt]=cv+Quaternion.AngleAxis(j*360f/nr,ov)*Vector3.forward*r; uvs[cnt]=Vector2.zero; int ni=(i+1)%contour.Count; et[ecnt++]=bcnt+nr*i+((j+1)%nr); et[ecnt++]=bcnt+nr*i+j; et[ecnt++]=bcnt+nr*ni+j; et[ecnt++]=bcnt+nr*ni+((j+1)%nr); et[ecnt++]=bcnt+nr*i+((j+1)%nr); et[ecnt++]=bcnt+nr*ni+j; cnt++; } pv=cv; cv=nv; nv=contour[(i+2)%contour.Count]; } } } extrudedMesh.Clear(); extrudedMesh.name= "piped"; extrudedMesh.vertices = vertices; extrudedMesh.uv = uvs; extrudedMesh.subMeshCount = 1; extrudedMesh.SetTriangles(et, 0); extrudedMesh.RecalculateNormals(); }
// This method modifies the mesh extruded mesh by creating an extrusion in between the front face mesh and the back face mesh // the outlines may be decimated/simplified qccouting to a vertice_filter public static void ExtrudeOutlines(ref Mesh extrudedMesh, Mesh front, Mesh back, TTFTextOutline[] outlines, bool[] vertice_filter ) { extrudedMesh.Clear(); if (outlines.Length <= 1) { Debug.LogError("Extrude not enough outlines :" + outlines.Length); return ; } int[] frontTriangles = front != null ? front.triangles : new int[0]; Vector3[] frontVertices = front != null ? front.vertices : new Vector3[0]; int[] backTriangles = back.triangles; Vector3[] backVertices = back.vertices; int npos=0; for (int i = 0; i < vertice_filter.Length; i++) { if (vertice_filter[i]) { npos++; } } Vector3[] vertices = new Vector3[outlines.Length * npos + frontVertices.Length + backVertices.Length]; int[] et = new int[(outlines.Length - 1) * npos * 6 + frontTriangles.Length + backTriangles.Length]; int cnt=0; for (int i = 0; i < outlines.Length; i++) { if (outlines[i].numVertices != vertice_filter.Length) { throw new System.Exception("Incompatible outlines"); } int cj=0; foreach(TTFTextOutline.Boundary vl in outlines[i].boundaries) { for(int ii=0;ii<vl.Count;ii++) { if (vertice_filter[cj]) { vertices[cnt++]=vl[ii]; } cj++; } } if (cj!=outlines[i].numVertices) { Debug.Log("Error in vertice count");} } int frontIdx = cnt; int backIdx = frontIdx + frontVertices.Length; System.Array.Copy(frontVertices, 0, vertices, frontIdx, frontVertices.Length); System.Array.Copy(backVertices, 0, vertices, backIdx, backVertices.Length); int xcnt,ecnt=0; int j,jb; for (int i=0;i<(outlines.Length-1);i++) { j=0; xcnt=0; foreach(TTFTextOutline.Boundary vl in outlines[i].boundaries) { if (vl.Count<=1) { Debug.LogWarning("Pathlogical boundary"); } jb=j; // the first index of that boundary for(int kc=0;kc<vl.Count;kc++) { if (vertice_filter[xcnt]) { et[ecnt++]=npos*i+(j+1); et[ecnt++]=npos*i+j; et[ecnt++]=npos*(i+1)+j; et[ecnt++]=npos*(i+1)+(j+1); et[ecnt++]=npos*i+(j+1); et[ecnt++]=npos*(i+1)+j; j++; } xcnt++; } if (ecnt>=6) { // fixup last triangle et[ecnt-6]=npos*i+jb; et[ecnt-5]=npos*i+(j-1); et[ecnt-4]=npos*(i+1)+(j-1); et[ecnt-3]=npos*(i+1)+jb; et[ecnt-2]=npos*i+jb; et[ecnt-1]=npos*(i+1)+(j-1); } } } // reindex front side for (int i = 0; i < frontTriangles.Length; ++i) { frontTriangles[i] = frontTriangles[i] + frontIdx; } // reindex back side for (int i = 0; i < backTriangles.Length; ++i) { backTriangles[i] = backTriangles[i] + backIdx; } extrudedMesh.name= "Extruded"; extrudedMesh.vertices = vertices; extrudedMesh.subMeshCount = 3; extrudedMesh.SetTriangles(frontTriangles, 0); extrudedMesh.SetTriangles(et, 1); extrudedMesh.SetTriangles(backTriangles, 2); extrudedMesh.RecalculateNormals(); //extrudedMesh.Optimize(); //extrudedMesh.RecalculateBounds(); }
// FreeHand Curve Extrusion public static TTFTextOutline[] MakeFreeHandOutlines (TTFTextInternal.LineLayout ll, TTFText tm, TTFTextStyle ts) { //Vector3 min=Vector3.zero; Vector3 max=Vector3.zero; Keyframe[] keys = ts.FreeHandCurve.keys; int NS = keys.Length; TTFTextOutline[] outlines = new TTFTextOutline[NS]; float[] z = new float[NS]; //min = Vector3.zero; //max = Vector3.zero; //Vector3 [] szs = new Vector3[NS]; for (int i=0; i<NS; i++) { // Vector3 min_, max_; z [i] = keys [i].time * ts.ExtrusionDepth; outlines [i] = MakeOutline (ll, ts.Embold + keys [i].value * ts.BevelForce, tm); outlines [i].Translate (Vector3.forward * z [i]); if (ts.Slant != 0) { outlines [i].Slant (ts.Slant); } //outlines[i].GetMinMax(out min_, out max_); //szs[i]=max_-min_; //min = Vector3.Min(min, min_); //max = Vector3.Max(max, max_); } //Vector3 sz=max-min; //for (int i=0;i<NS;i++) { // outlines[i].Translate((sz-szs[i])/2); //} return outlines; }
public static Mesh P2TTriangulate(TTFTextOutline outline, Mesh outMesh) { float Z = outline.Min.z; // Assume all vertices have the same Z coord List <List <ClipperLib.IntPoint> > ipolygones = new List <List <ClipperLib.IntPoint> >(); foreach (TTFTextOutline.Boundary lv in outline.boundaries) { if (Intersection.isSimple(lv)) { ipolygones.Add(Vec2LIP(lv)); } else { //Debug.LogWarning("Complex Contour"); try { foreach (List <Vector3> p in Intersection.Decompose(lv)) // decompose outlines { ipolygones.Add(Vec2LIP(p)); } } catch (System.Exception) { // parallel segments //Debug.LogWarning("Bad contour:" + ex.ToString()); } } } ClipperLib.Clipper c = new ClipperLib.Clipper(); List <ClipperLib.ExPolygon> res = new List <ClipperLib.ExPolygon>(); c.AddPolygons(ipolygones, ClipperLib.PolyType.ptSubject); c.Execute(ClipperLib.ClipType.ctUnion, res, ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero); //c.Execute(ClipperLib.ClipType.ctUnion,res,ClipperLib.PolyFillType.pftEvenOdd,ClipperLib.PolyFillType.pftEvenOdd); //c.Execute(ClipperLib.ClipType.ctUnion,res,ClipperLib.PolyFillType.pftPositive,ClipperLib.PolyFillType.pftPositive); //c.Execute(ClipperLib.ClipType.ctUnion,res,ClipperLib.PolyFillType.pftPositive,ClipperLib.PolyFillType.pftPositive); List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); Dictionary <Vector3, int> vDic = new Dictionary <Vector3, int>(); foreach (ClipperLib.ExPolygon p in res) { Vector3 mv = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity); Vector3 Mv = new Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity); List <Vector3> np = LIP2Vec(p.outer); for (int i = 0; i < np.Count; i++) { mv = Vector3.Min(mv, np[i]); Mv = Vector3.Max(Mv, np[i]); } Vector3 sv = (Mv - mv); //int oc=np.Count; np = Simplify(np, 0.05f); // set of all vertices for this triangulation step HashSet <Vector3> whole = new HashSet <Vector3>(); if ((np.Count >= 4) && ((sv.x * sv.y) > 0.001f) && Intersection.isSimple(np) && !HasDup(np)) { foreach (Vector3 v in np) { whole.Add(v); } Polygon cp = new Polygon(Vec2PP(np)); foreach (List <ClipperLib.IntPoint> h in p.holes) { List <Vector3> ph = Simplify(LIP2Vec(h), 0.05f); // Poli2tri doesnt support intersection and dupplicate vertices // skip all holes which does not respect thoses conditions if ((!Intersection.isSimple(ph)) || HasDup(ph)) { //Debug.LogWarning("Skipping Complex hole"); } else if (ContainsAny(whole, ph)) { //Debug.LogWarning("Duplicate vertices in holes"); } else { foreach (Vector3 v in ph) { whole.Add(v); } cp.AddHole(new Polygon(Vec2PP(ph))); } } try { P2T.Triangulate(cp); foreach (DelaunayTriangle dt in cp.Triangles) { Vector3 v; int idx; for (int i = 0; i < 3; ++i) { v = new Vector3(dt.Points[i].Xf, dt.Points[i].Yf, Z); if (!vDic.TryGetValue(v, out idx)) { idx = vertices.Count; vertices.Add(v); vDic.Add(v, idx); } triangles.Add(idx); } } } catch (System.Exception e) { Debug.LogWarning(e); } } else { //Debug.LogWarning("Skip Polygon: count=" + np.Count + " size=" + sv + " simple=" + Intersection.isSimple(np) + " dup:" + HasDup(np)); } } outMesh.Clear(); outMesh.vertices = vertices.ToArray(); outMesh.triangles = triangles.ToArray(); outMesh.RecalculateBounds(); outMesh.RecalculateNormals(); outMesh.Optimize(); return(outMesh); }
public override TTFTextOutline Apply(TTFTextOutline outline, object parameters) { Parameters p = (parameters as Parameters); TTFTextOutline no = new TTFTextOutline(); //Vector3 [] tv=new Vector3[p.interpolation]; foreach (Boundary v in outline.boundaries) { float [] cumdist = v.cumDists(); Vector3 [] sg = new Vector3[p.interpolation]; Vector3 [] sr = new Vector3[p.interpolation]; Vector3 [] si = new Vector3[p.interpolation]; Vector3 [] sm = new Vector3[p.interpolation]; Vector3 [] sp = new Vector3[p.interpolation]; //Debug.Log(cumdist[cumdist.Length-1]); for (int i = 0; i < p.interpolation; ++i) { sg[i] = v.interpolatePosition1(cumdist, (((float)i) / ((float)(p.interpolation - 1))) ); } float sf = (2 * Mathf.PI) / ((float)p.interpolation); float af = 1f / ((float)p.interpolation); for (int i = 0; i < p.interpolation; ++i) { for (int j = 0; j < p.interpolation; ++j) { sr[i] += af * Mathf.Cos(j * i * sf) * sg[j]; si[i] += af * Mathf.Sin(j * i * sf) * sg[j]; } float q = p.ac.GetAnimcurve().Evaluate(1 - Mathf.Abs((((float)i) / p.interpolation) * 2 - 1)); sm[i] = new Vector3( Mathf.Sqrt(sr[i].x * sr[i].x + si[i].x * si[i].x) * q, Mathf.Sqrt(sr[i].y * sr[i].y + si[i].y * si[i].y) * q, Mathf.Sqrt(sr[i].z * sr[i].z + si[i].z * si[i].z) * q); sp[i] = new Vector3( (sm[i].x != 0)?Mathf.Atan2(si[i].x, sr[i].x):0, (sm[i].y != 0)?Mathf.Atan2(si[i].y, sr[i].y):0, (sm[i].z != 0)?Mathf.Atan2(si[i].z, sr[i].z):0 ) ; } for (int j = 0; j < p.interpolation; ++j) { sg[j] = Vector3.zero; } for (int i = 0; i < p.interpolation; ++i) { for (int j = 0; j < p.interpolation; ++j) { float alphax = sp[j].x + i * j * sf; float alphay = sp[j].y + i * j * sf; float alphaz = sp[j].z + i * j * sf; sg[i] += /*af**/ new Vector3( Mathf.Cos(alphax) * sm[j].x /*+Mathf.Sin(alphax)*sm[i].x*/, Mathf.Cos(alphay) * sm[j].y /*+Mathf.Sin(alphay)*sm[i].y*/, Mathf.Cos(alphaz) * sm[j].z /*+Mathf.Sin(alphaz)*sm[i].z*/ ) ; } } no.AddBoundary(sg); } //Debug.Log(no.Min); //Debug.Log(no.Max); return(no); }
public override TTFTextOutline Apply(TTFTextOutline outline, object parameters) { float amount = (parameters as Parameters).Amount; return(outline.Simplify(amount, 1)); }
public static TTFTextOutline[] OutlineOutlines (TTFTextOutline[] outlines, float str) { int len = outlines.Length; if (len == 0 || str <= 0) { return outlines; } TTFTextOutline[] res = new TTFTextOutline[len + 2]; res [0] = outlines [0].Embolden (-str); for (int i = 0; i < len; ++i) { res [i + 1] = outlines [i];//new Outline(outlines[i]); } res [len + 1] = outlines [len - 1].Embolden (-str); return res; }
static TTFTextOutline[] MakeBevelOutlines (TTFTextInternal.LineLayout ll, TTFText tm, TTFTextStyle ts) { //Vector3 min=Vector3.zero; Vector3 max=Vector3.zero; //Vector3 min_; Vector3 max_; int NS = tm.NbDiv; if (NS < 2) { NS = 2; } TTFTextOutline[] outlines = new TTFTextOutline[NS * 2]; //Vector3[] szs = new Vector3[NS*2]; float bevelDepth = ts.BevelDepth * ts.ExtrusionDepth / 2; for (int i = 0; i < NS; ++i) { float f = ((float)i) / ((float)NS - 1); // [0,1] float embold = ts.Embold + Mathf.Sin (Mathf.Acos (1 - f)) * ts.BevelForce; TTFTextOutline o = MakeOutline (ll, embold, tm); o.Slant (ts.Slant); outlines [i] = o; outlines [2 * NS - 1 - i] = new TTFTextOutline (o); //outlines[i].GetMinMax(out min_, out max_); //szs[i]=max_-min_; float z = f * bevelDepth; outlines [i].Translate (Vector3.forward * z); outlines [2 * NS - 1 - i].Translate (Vector3.forward * (ts.ExtrusionDepth - z)); //szs[2*NS-1-i]=max_-min_; //min = Vector3.Min(min, min_); //max = Vector3.Max(max, max_); } //Vector3 sz=max-min; //for (int i=0;i<(2*NS);i++) { // outlines[i].Translate((sz-szs[i])/2); //} return outlines; }
// Simple extrusion public static TTFTextOutline[] MakeSimpleOutlines (TTFTextInternal.LineLayout ll, TTFText tm, TTFTextStyle ts) { TTFTextOutline o = MakeOutline (ll, ts.Embold, tm); if (ts.Slant != 0) { o.Slant (ts.Slant); } TTFTextOutline[] outlines = new TTFTextOutline[2]; outlines [0] = o; outlines [1] = new TTFTextOutline (o); outlines [0].Translate (Vector3.forward * (-ts.ExtrusionDepth) / 2); outlines [1].Translate (Vector3.forward * ts.ExtrusionDepth / 2); return outlines; }
// this version will block until all character are downloaded... public IEnumerable SyncGetOutlineForLetter(string fontid, string characters) { TTFTextOutline []res = new TTFTextOutline[characters.Length]; // for each character TTFTextFontStoreFont f=GetFont(fontid); if (f==null) { IEnumerable r=null; do { r=DoSyncDownloadOutline(fontid,f.additionalChar); if (r.GetType()==typeof(WaitForSeconds)) { yield return r; } } while (r.GetType()==typeof(WaitForSeconds)); } foreach(char c in characters) { if (! f.HasCharacter(c)) { f.AddRequiredCharacters(characters); IEnumerable r=null; do { r=DoSyncDownloadOutline(fontid,f.additionalChar); if (r.GetType()==typeof(WaitForSeconds)) { yield return r; } } while (r.GetType()==typeof(WaitForSeconds)); } } yield return res; }
static TTFTextOutline[] MakeBentOutlines (TTFTextInternal.LineLayout ll, TTFText tm, TTFTextStyle ts) { //Vector3 min=Vector3.zero; Vector3 max=Vector3.zero; int NS = ts.ExtrusionSteps.Length; TTFTextOutline[] outlines = new TTFTextOutline[NS]; //Vector3 [] szs = new Vector3[NS]; for (int i = 0; i < NS; i++) { //Vector3 min_, max_; float embold = ts.Embold + ts.BevelForce * Mathf.Sin (i * Mathf.PI / (NS - 1)); // wierd error with poly2tri/embold for the backface if (i == NS - 1) { embold = ts.Embold; } outlines [i] = MakeOutline (ll, embold, tm); float z = (ts.ExtrusionSteps [i] - 0.5f) * ts.ExtrusionDepth;// - tm.exstrusionDepth / 2; outlines [i].Translate (Vector3.forward * z); if (ts.Slant != 0) { outlines [i].Slant (ts.Slant); } //outlines[i].GetMinMax(out min_, out max_); //szs[i]=max_-min_; //min = Vector3.Min(min, min_); //max = Vector3.Max(max, max_); } //Vector3 sz=max-min; //for (int i=0;i<NS;i++) { // outlines[i].Translate((sz-szs[i])/2); //} return outlines; }
public override TTFTextOutline Apply(TTFTextOutline outline, object parameters) { float rotate; int octr = 0; float strength = (parameters as Parameters).Amount; int interpolation = (parameters as Parameters).Interpolation; strength /= 40f; //Vector3 so = new Vector3(strength/2f,strength/2f,0); //Vector3 so = new Vector3 (strength, strength, 0); Vector3 tr = Vector3.zero; Vector3 so = Vector3.zero; if (Mathf.Abs(strength) < 0.001f) { return(new TTFTextOutline(outline)); } int orientation = 1; if (orientation == 1) // True type ? { rotate = -Mathf.PI / 2; } else { rotate = Mathf.PI / 2; } TTFTextOutline r = new TTFTextOutline(); foreach (Boundary cb in outline.boundaries) { int clen = cb.Count; Vector3 [] nb = new Vector3 [clen * interpolation]; if (clen > 0) { Vector3 pv = cb [clen - 1], v = cb [0], nv; for (int ctr = 0; ctr < (clen + 20); ctr++) { nv = cb [(ctr + 1) % clen]; bool skip_this_vertex = false; // We have actually keep all vertice // because extrusion rely on all outline having the same num of vertices if ((nv - v).magnitude < 0.001f) { if (ctr == 0) { //nb [0] = (v + so + tr); for (int ci = 0; ci < interpolation; ci++) { nb [octr++ % (clen * interpolation)] = (v + so); } } else { for (int ci = 0; ci < interpolation; ci++) { nb [octr++ % (clen * interpolation)] = nb [(ctr - 1) % clen]; } } skip_this_vertex = true; } if (!skip_this_vertex) { Vector2 d1 = v - pv; Vector3 d2 = nv - v; Vector3 d3; float angle_in = Mathf.Atan2(d1.x, d1.y); float angle_out = Mathf.Atan2(d2.x, d2.y); for (int ci = 0; ci < interpolation; ci++) { float angle_diff2 = ((angle_out - angle_in + 3 * Mathf.PI) % (Mathf.PI * 2) - Mathf.PI) * ((float)(1 + ci)) / (1 + interpolation); float scale = Mathf.Sign(Mathf.Cos(angle_diff2)); // * Mathf.Cos( angle_diff2/8 ); scale = 1; float e = angle_in + rotate + angle_diff2; d3 = (new Vector3(Mathf.Cos(-e), Mathf.Sin(-e))) * (strength * scale); tr = new Vector2(-d3.y, d3.x); nb [octr++ % (clen * interpolation)] = (v + so + tr); } pv = v; v = nv; } } } if (nb.Length > 0) { r.AddBoundary(nb); } } r.advance = outline.advance; return(r); }
/// <summary> /// Core function generating the outline for a portion of text /// </summary> /// <returns> /// The outline. /// </returns> /// <param name='txt'> /// The text to be rendered /// </param> /// <param name='charSpacing'> /// The default character spacing /// </param> /// <param name='embold'> /// Current embold /// </param> /// <param name='tm'> /// Link to the TTFText object /// </param> /// <param name='reversed'> /// Orientation of the outlines /// </param> /// <param name='charpositions'> /// Position of the character /// </param> /// <param name='charstyleidx'> /// Style index of each character /// </param> /// <param name='charmetadata'> /// Metadata associated to special character such as images and bitmap characters /// </param> /// <exception cref='System.Exception'> /// Is thrown when the exception. /// </exception> public static TTFTextOutline MakeOutline (string txt, float charSpacing, float embold, TTFText tm, bool reversed, float [] charpositions, int [] charstyleidx, object [] charmetadata) { TTFTextOutline outline = new TTFTextOutline (); int fp = 0; string currentfontid = ""; object cfont = null; object parameters = null; TTFTextStyle cttfstyle = null; if (charstyleidx == null) { cttfstyle = tm.InitTextStyle; fp = cttfstyle.PreferredEngine (Application.platform); #if ! TTFTEXT_LITE cfont = cttfstyle.GetFont (ref fp, ref currentfontid, ref parameters); #else fp=0; currentfontid=cttfstyle.FontId; parameters=cttfstyle.GetFontEngineParameters(0); if (parameters==null) { System.Type t = TTFTextInternal.TTFTextFontEngine.font_engines [0].GetType ().GetNestedType ("Parameters"); cttfstyle.SetFontEngineParameters(0,t.InvokeMember (t.Name, BindingFlags.CreateInstance, null, null, null)); parameters=cttfstyle.GetFontEngineParameters(0); } cfont= TTFTextInternal.TTFTextFontEngine.font_engines[0].GetFont(parameters,currentfontid); #endif if (cfont == null) { throw new System.Exception ("(TTFText) Font not found :" + tm.InitTextStyle.FontId); } } if (charpositions != null && charpositions.Length < txt.Length) { Debug.LogError ("(TTFText) Bad char position len=" + charpositions.Length + " txt = " + txt + " (len=" + txt.Length + ")"); charpositions = null; } int i = 0; foreach (char c in txt) { TTFTextOutline o = null; if (charstyleidx != null) { if ((cfont == null) || (currentfontid != tm.UsedStyles [charstyleidx [i]].GetFontEngineFontId (tm.UsedStyles [charstyleidx [i]].PreferredEngine (Application.platform)))) { cttfstyle = tm.UsedStyles [charstyleidx [i]]; fp = cttfstyle.PreferredEngine (Application.platform); //Debug.Log(fp); #if ! TTFTEXT_LITE cfont = cttfstyle.GetFont (ref fp, ref currentfontid, ref parameters); #else fp=0; currentfontid=cttfstyle.FontId; parameters=cttfstyle.GetFontEngineParameters(0); if (parameters==null) { System.Type t = TTFTextInternal.TTFTextFontEngine.font_engines [0].GetType ().GetNestedType ("Parameters"); cttfstyle.SetFontEngineParameters(0,t.InvokeMember (t.Name, BindingFlags.CreateInstance, null, null, null)); parameters=cttfstyle.GetFontEngineParameters(0); } cfont= TTFTextInternal.TTFTextFontEngine.font_engines[0].GetFont(parameters,currentfontid); #endif if (cfont == null) { throw new System.Exception ("Font not found :" + tm.InitTextStyle.FontId); } } } if ((charmetadata == null) || (charmetadata [i] == null)) { // a normal character if (TTFTextFontEngine.font_engines [fp].IsBitmapFontProvider (parameters)) { TTFTextTexturePortion p = TTFTextFontEngine.font_engines [fp].GetGlyphBitmap (parameters, cfont, c); o = new TTFTextOutline (); float w = ((float)p.w); float h = ((float)p.h); Vector3 b = new Vector3 (p.x, p.y, 0); //Vector3[] quad = {Vector3.zero,Vector3.right*w,new Vector3(w,h,0),Vector3.up*h}; Vector3[] quad = {b,b + Vector3.up * h,b + new Vector3 (w, h, 0),b + Vector3.right * w}; o.AddBoundary (quad); TTFTextInternal.TextureElement tel = new TTFTextInternal.TextureElement (); tel.width = w; tel.height = h; tel.material = p.material; tel.shouldReleaseMaterial = p.shouldReleaseMaterial; tel.texture = p.texture; tel.shouldReleaseTexture = p.shouldReleaseTexture; tel.UVstartx = p.sx; tel.UVstarty = p.sy; tel.UVwidth = p.dx; tel.UVheight = p.dy; charmetadata [i] = tel; } else { o = TTFTextFontEngine.font_engines [fp].GetGlyphOutline (parameters, cfont, c); if (charstyleidx != null) { for (int ii=0; ii<tm.UsedStyles[charstyleidx[i]].GetOutlineEffectStackElementLength(); ii++) { TTFTextStyle.TTFTextOutlineEffectStackElement tse = tm.InitTextStyle.GetOutlineEffectStackElement (ii); o = TTFTextOutline.AvailableOutlineEffects [tse.id].Apply (o, tse.parameters); } } else { for (int ii=0; ii<tm.InitTextStyle.GetOutlineEffectStackElementLength(); ii++) { TTFTextStyle.TTFTextOutlineEffectStackElement tse = tm.InitTextStyle.GetOutlineEffectStackElement (ii); o = TTFTextOutline.AvailableOutlineEffects [tse.id].Apply (o, tse.parameters); } } } } else { // it is some kind of special object (an embedded image... ?) //Debug.Log("Not yet implemented"); o = new TTFTextOutline (); float w = 1; float h = 1; Vector3[] quad = {Vector3.zero,Vector3.right * w,new Vector3 (w, h, 0),Vector3.up * h}; o.AddBoundary (quad); } o = o.Embolden (((charstyleidx != null) ? tm.UsedStyles [charstyleidx [i]].Embold : tm.Embold) + embold); o.Rescale ((charstyleidx != null) ? tm.UsedStyles [charstyleidx [i]].Size : tm.Size); if (charpositions == null) { outline.Append (o, outline.advance); } else { outline.Append (o, Vector3.right * charpositions [i]); } i += 1; } return outline; }
/* * public static Mesh Triangulate(IList<Vector3> path, Mesh outMesh * * List<Vector3> vertices = new List<Vector3>(path.Count * 2); * List<int> triangles = new List<int>(); * Debug.Log("prev tess"); * T.Tesselator<int>.combineVertexD combineIdx = delegate (double[] loc, int[] inVertices, float[] weight) { * * int idx = vertices.Count; * * vertices.Add(new Vector3((float) loc[0], (float) loc[1], (float) loc[2])); * * return idx; * }; * * using (T.Tesselator<int> tess = new T.Tesselator<int>(combineIdx)) { * * tess.VertexEv += delegate(T.Tesselator<int> t, int idx) { * triangles.Add(idx); * }; * * tess.BeginPolygon(); * tess.BeginContour(); * * for (int i = 0; i < path.Count; ++i) { * int idx = vertices.Count; * Vector3 v = path[i]; * vertices.Add(v); * // uv.Add(inUV[i]); * double[] coords = { v.x, v.y, v.z }; * tess.AddVertex(coords, idx); * } * * tess.EndContour(); * tess.EndPolygon(); * } * * outMesh.Clear(); * outMesh.vertices = vertices.ToArray(); * outMesh.triangles = triangles.ToArray(); * //outMesh.uv = uv.ToArray(); * * return outMesh; * } * * * public static Mesh Triangulate(IList<Vector3> path) { * Mesh mesh = new Mesh(); * mesh.name = "triangulation"; * return Triangulate(path, mesh); * } * */ public static Mesh TTriangulate(TTFTextOutline outline, Mesh outMesh) { List <Vector3> vertices = new List <Vector3>(outline.numVertices * 2); List <int> triangles = new List <int>(); T.Tesselator <int> .combineVertexD combineIdx = delegate(double[] loc, int[] inVertices, float[] weight) { int idx = vertices.Count; vertices.Add(new Vector3((float)loc[0], (float)loc[1], (float)loc[2])); return(idx); }; using (T.Tesselator <int> tess = new T.Tesselator <int>(combineIdx)) { //Debug.Log("SetWindingRule"); tess.SetWindingRule(Triangulation.Glu.TessWinding.WindingPositive); tess.VertexEv += delegate(T.Tesselator <int> t, int idx) { triangles.Add(idx); }; double [][][] tcoords = new double[outline.blengthes.Count][][]; //using () { tess.BeginPolygon(); // int i=0; int cp = 0; //Debug.Log ("Tess Beg Poly"); foreach (TTFTextOutline.Boundary lv in outline.boundaries) { tcoords[cp] = new double[lv.Count][]; int ci = 0; tess.BeginContour(); foreach (Vector3 v in lv) { int idx = vertices.Count; vertices.Add(v); //double[] coords = { v.x, v.y, v.z }; double [] ttcoords = { v.x, v.y, v.z }; tcoords[cp][ci] = ttcoords; tess.AddVertex(tcoords[cp][ci], idx); //tess.AddVertex(coords, idx); //i++; ci++; } tess.EndContour(); cp++; } //Debug.Log ("Tess End Poly"); tess.EndPolygon(); //for (int ix=0;ix<tcoords.Length;ix++) { // tcoords[ix]=null; //} //} } outMesh.Clear(); outMesh.vertices = vertices.ToArray(); outMesh.triangles = triangles.ToArray(); //outMesh.uv = uv.ToArray(); return(outMesh); }
/// <summary> /// Builds a whole charset for a specific fontid /// </summary> public void BuildCharSet(string fontid) { #if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_EDITOR int istep=TTFTextFontStore.Instance.defaultInterpolationSteps; bool reversed=false; charset = new TTFTextOutline[0x80]; charset_advance = new Vector3[0x80]; System.Text.ASCIIEncoding ae = new System.Text.ASCIIEncoding(); TTF.Font font = TTFTextInternal.Utilities.TryOpenFont(fontid,ref reversed,"",72); // TODO: < Check the last bool if (font == null) { Debug.LogError("BuildCharSet: no font found"); return; } for (byte i = 0x20; i < 0x7F; i++) { string s = ae.GetString(new byte [] {i}); charset[i] = TTFTextInternal.Engine.MakeNativeOutline(s, 1,0,font,reversed,istep); //TTFTextInternal.MakeOutline(s, font, 1, 0, null,false,null,null); charset_advance[i] = charset[i].advance; } addCharset = new TTFTextOutline[additionalChar.Length]; int idx = 0; foreach (char c in additionalChar) { addCharset[idx] = TTFTextInternal.Engine.MakeNativeOutline( "" + c, 1,0,font, reversed,istep); ++idx; } font.Dispose(); _needRebuild=false; #endif }
/// <summary> /// Appends some text to the line. /// </summary> /// <param name='s'> /// text to be appended. /// </param> /// <exception cref='System.Exception'> /// Is thrown when the font may not be found, or when we /// are unable to compute the layout info /// </exception> public void AppendText(string s) { if (s.Length == 0) { return; } int l0 = linetext.Length; linetext += s; #if TTFTEXT_LITE if (tm.DemoMode) { #endif SetCharStyle(l0, l0 + s.Length, tm.currentStyleIdx); #if TTFTEXT_LITE } else { SetCharStyle(l0, l0 + s.Length, 0); } #endif // UPDATE THE METRIC INFO object f = null; object parameters = null; ; int fp = 0; float sumadvance = 0; for (int i = 0; i < l0; i++) { sumadvance += charadvances[i]; } string currentfontid = ""; //f = tm.InitTextStyle.GetFont (ref fp, ref currentfontid, ref parameters); //f = tm.CurrentTextStyle.GetFont (ref fp, ref currentfontid, ref parameters); #if !TTFTEXT_LITE f = tm.CurrentTextStyle.GetFont(ref fp, ref currentfontid, ref parameters); #else fp = 0; currentfontid = tm.CurrentTextStyle.FontId; parameters = tm.CurrentTextStyle.GetFontEngineParameters(0); if (parameters == null) { System.Type t = TTFTextInternal.TTFTextFontEngine.font_engines [0].GetType().GetNestedType("Parameters"); tm.CurrentTextStyle.SetFontEngineParameters(0, t.InvokeMember(t.Name, BindingFlags.CreateInstance, null, null, null)); parameters = tm.CurrentTextStyle.GetFontEngineParameters(0); } f = TTFTextInternal.TTFTextFontEngine.font_engines[0].GetFont(parameters, currentfontid); #endif if (f == null) { //throw new System.Exception ("Font not found :" + fp + "/" + tm.InitTextStyle.GetFontEngineFontId (fp)); throw new System.Exception("Font not found :" + fp + "/" + tm.CurrentTextStyle.GetFontEngineFontId(fp)); } for (int i = 0; i < s.Length; i++) { TTFTextStyle cttfstyle = GetCharStyle(l0 + i); if ((cttfstyle != null) && (currentfontid != cttfstyle.GetFontEngineFontIdD(fp))) { TTFTextFontEngine.font_engines [fp].DisposeFont(f); // f = cttfstyle.GetFont (ref fp, ref currentfontid, ref parameters); #if !TTFTEXT_LITE f = cttfstyle.GetFont(ref fp, ref currentfontid, ref parameters); #else fp = 0; currentfontid = cttfstyle.FontId; parameters = cttfstyle.GetFontEngineParameters(0); if (parameters == null) { System.Type t = TTFTextInternal.TTFTextFontEngine.font_engines [0].GetType().GetNestedType("Parameters"); cttfstyle.SetFontEngineParameters(0, t.InvokeMember(t.Name, BindingFlags.CreateInstance, null, null, null)); parameters = tm.CurrentTextStyle.GetFontEngineParameters(0); } f = TTFTextInternal.TTFTextFontEngine.font_engines[0].GetFont(parameters, currentfontid); #endif if (f == null) { //throw new System.Exception ("Font not found :" + fp + "/" + tm.InitTextStyle.GetFontEngineFontId (fp)); throw new System.Exception("Font not found :" + fp + "/" + tm.CurrentTextStyle.GetFontEngineFontId(fp)); } } charadvances [l0 + i] = TTFTextFontEngine.font_engines [fp].GetAdvance(parameters, f, s [i]).x *cttfstyle.Size; charheights [l0 + i] = TTFTextFontEngine.font_engines [fp].GetHeight(parameters, f); charmetadata [l0 + i] = null; if (!TTFTextFontEngine.font_engines[fp].IsBitmapFontProvider(parameters)) { TTFTextOutline o = TTFTextFontEngine.font_engines [fp].GetGlyphOutline(parameters, f, s [i]); o.Rescale(cttfstyle.Size); if (l0 + i == 0) { Xmin0 = o.Min.x; } if (l0 + i == line.Length - 1) { XmaxN = o.Max.x; } } else { //Debug.LogWarning("NYI !"); sumadvance += charadvances [l0 + i]; if (l0 + i == 0) { Xmin0 = 0; } if (l0 + i == line.Length - 1) { XmaxN = sumadvance; } } } TTFTextFontEngine.font_engines [fp].DisposeFont(f); // can happen when the first or last char is non printable, like a space for example if (float.IsNaN(XmaxN) || float.IsInfinity(XmaxN)) { XmaxN = 0; } if (float.IsNaN(Xmin0) || float.IsInfinity(Xmin0)) { Xmin0 = 0; } }