public static TTFStringMeasurer Create(TrueTypeFile forfont, CMapEncoding encoding, TypeMeasureOptions options) { HorizontalMetrics table = forfont.Directories["hmtx"].Table as HorizontalMetrics; CMAPTable cmap = forfont.Directories["cmap"].Table as CMAPTable; OS2Table os2 = forfont.Directories["OS/2"].Table as OS2Table; FontHeader head = forfont.Directories["head"].Table as FontHeader; HorizontalHeader hhead = forfont.Directories["hhea"].Table as HorizontalHeader; CMAPSubTable map = cmap.GetOffsetTable(encoding); if (map == null) { encoding = CMapEncoding.Unicode_20; map = cmap.GetOffsetTable(CMapEncoding.Unicode_20); } if (map == null) { encoding = CMapEncoding.MacRoman; map = cmap.GetOffsetTable(CMapEncoding.MacRoman); } return(new TTFStringMeasurer(head.UnitsPerEm, map, os2, hhead, table.HMetrics, forfont, encoding, options)); }
public LineSize MeasureString(CMapEncoding encoding, string s, int startOffset, double emsize, double available, bool wordboundary, out int charsfitted, FontUnitType useUnits = FontUnitType.UseFontPreference) { HorizontalMetrics table = this.Directories["hmtx"].Table as HorizontalMetrics; CMAPTable cmap = this.Directories["cmap"].Table as CMAPTable; OS2Table os2 = this.Directories["OS/2"].Table as OS2Table; CMAPSubTable mac = cmap.GetOffsetTable(encoding); if (mac == null) { mac = cmap.GetOffsetTable(CMapEncoding.MacRoman); } HorizontalHeader hhead = this.Directories["hhea"].Table as HorizontalHeader; FontHeader head = this.Directories["head"].Table as FontHeader; available = (available * head.UnitsPerEm) / emsize; double len = 0.0; double lastwordlen = 0.0; int lastwordcount = 0; charsfitted = 0; for (int i = startOffset; i < s.Length; i++) { char c = s[i]; if (char.IsWhiteSpace(c)) { lastwordlen = len; lastwordcount = charsfitted; } int moffset = (int)mac.GetCharacterGlyphOffset(c); //System.Diagnostics.Debug.WriteLine("Character '" + chars[i].ToString() + "' (" + ((byte)chars[i]).ToString() + ") has offset '" + moffset.ToString() + "' in mac encoding and '" + woffset + "' in windows encoding"); if (moffset >= table.HMetrics.Count) { moffset = table.HMetrics.Count - 1; } Scryber.OpenType.SubTables.HMetric metric; metric = table.HMetrics[moffset]; if (i == 0) { len = -metric.LeftSideBearing; } len += metric.AdvanceWidth; //check if we can fit more if (len > available) { len -= metric.AdvanceWidth; break; } charsfitted++; } bool isboundary = false; if ((charsfitted + startOffset < s.Length) && wordboundary && lastwordlen > 0) { len = lastwordlen; charsfitted = lastwordcount; isboundary = true; } len = len / (double)head.UnitsPerEm; len = len * emsize; double h = GetLineHeight(useUnits, os2, hhead, head, emsize); return(new LineSize((float)len, (float)h, charsfitted, startOffset, isboundary)); }
/// <summary> /// Measures the size of the provided string at the specified font size (starting at a specific offset), /// stopping when the available space is full and returning the number of characters fitted. /// </summary> /// <param name="encoding">The encoding to use to map the characters</param> /// <param name="s">The string to measure the size of</param> /// <param name="startOffset">The starting (zero based) offset in that string to start measuring from</param> /// <param name="emsize">The M size in font units</param> /// <param name="availablePts">The max width allowed for this string</param> /// <param name="wordspace">The spacing between words in font units. Default 0</param> /// <param name="charspace">The spacing between characters in font units. Default 0</param> /// <param name="hscale">The horizontal scaling of all characters. Default 100</param> /// <param name="vertical">If true then this is vertical writing</param> /// <param name="wordboundary">If True the measuring will stop at a boundary to a word rather than character.</param> /// <param name="charsfitted">Set to the number of characters that can be renered at this size within the width.</param> /// <returns></returns> public LineSize MeasureString(CMapEncoding encoding, string s, int startOffset, double emsize, double availablePts, double?wordspacePts, double charspacePts, double hscale, bool vertical, bool wordboundary, out int charsfitted, FontUnitType useUnits = FontUnitType.UseFontPreference) { HorizontalMetrics table = this.Directories["hmtx"].Table as HorizontalMetrics; CMAPTable cmap = this.Directories["cmap"].Table as CMAPTable; OS2Table os2 = this.Directories["OS/2"].Table as OS2Table; CMAPSubTable mac = cmap.GetOffsetTable(encoding); if (mac == null) { mac = cmap.GetOffsetTable(CMapEncoding.MacRoman); } HorizontalHeader hhead = this.Directories["hhea"].Table as HorizontalHeader; FontHeader head = this.Directories["head"].Table as FontHeader; double availableFU = availablePts * ((double)head.UnitsPerEm / emsize); double charspaceFU = NoCharacterSpace; if (charspacePts != NoCharacterSpace) { charspaceFU = charspacePts * ((double)head.UnitsPerEm / emsize); } double wordspaceFU = NoWordSpace; if (wordspacePts.HasValue) { wordspaceFU = (wordspacePts.Value * ((double)head.UnitsPerEm / emsize)); } else if (charspacePts != NoCharacterSpace) { //If we dont have explicit wordspacing then we use the character spacing wordspaceFU = charspaceFU; } double len = 0.0; double lastwordlen = 0.0; int lastwordcount = 0; charsfitted = 0; for (int i = startOffset; i < s.Length; i++) { char c = s[i]; if (char.IsWhiteSpace(c)) { lastwordlen = len; lastwordcount = charsfitted; } int moffset = (int)mac.GetCharacterGlyphOffset(c); if (moffset >= table.HMetrics.Count) { moffset = table.HMetrics.Count - 1; } Scryber.OpenType.SubTables.HMetric metric; metric = table.HMetrics[moffset]; double w = metric.AdvanceWidth; if (i == 0) { w -= metric.LeftSideBearing; } if (c == ' ') { if (wordspaceFU != NoWordSpace) { w += wordspaceFU; } } else if (charspaceFU != NoCharacterSpace) { w += charspaceFU; } if (hscale != NoHorizontalScale) { w *= hscale; } len += w; //check if we can fit more if (len > availableFU) { len -= w; break; } charsfitted++; } bool isboundary = false; if ((charsfitted + startOffset < s.Length) && wordboundary && lastwordlen > 0) { len = lastwordlen; charsfitted = lastwordcount; isboundary = true; } len = len * emsize; len = len / (double)head.UnitsPerEm; double h = GetLineHeight(useUnits, os2, hhead, head, emsize); return(new LineSize(len, h, charsfitted, startOffset, isboundary)); }