protected bool RenderText(String text, ref List<TextDrawItem> textDrawList, ViewUtil.ItemFont itemFont, double fontSize, double maxWidth, double maxHeight, double x, double baseline, ref double useHeight, SolidColorBrush fontColor, Matrix m) { double totalHeight = 0; double fontHeight = fontSize * itemFont.GlyphType.Height; string[] lineText = text.Replace("\r", "").Split('\n'); foreach (string line in lineText) { List<ushort> glyphIndexes = new List<ushort>(); List<double> advanceWidths = new List<double>(); //ベースラインの位置 double dpix = x * m.M11; double dpiy = (totalHeight + baseline) * m.M22; // ビットマップフォントがかすれる問題 とりあえず整数にしておく Point origin = new Point(Math.Round(dpix / m.M11), Math.Round(dpiy / m.M22)); //メイリオみたいに行間のあるフォントと MS P ゴシックみたいな行間のないフォントがあるので //なんとなく行間を作ってみる。 totalHeight += Math.Max(fontHeight, fontSize + 2); double totalWidth = 0; for (int n = 0; n < line.Length; n++) { // XAML に合わせて、行頭の空白を無視する if (glyphIndexes.Count == 0 && (line[n] == ' ' || line[n] == '\x3000')) continue; //この辞書検索が負荷の大部分を占めているのでテーブルルックアップする //(簡単なパフォーマンス計測をした結果、2~10倍くらい速くなったようだ) //ushort glyphIndex = itemFont.GlyphType.CharacterToGlyphMap[line[n]]; //double width = itemFont.GlyphType.AdvanceWidths[glyphIndex] * fontSize; ushort glyphIndex = itemFont.GlyphIndexCache[line[n]]; if (glyphIndex == 0) { itemFont.GlyphIndexCache[line[n]] = glyphIndex = itemFont.GlyphType.CharacterToGlyphMap[line[n]]; itemFont.GlyphWidthCache[glyphIndex] = (float)itemFont.GlyphType.AdvanceWidths[glyphIndex]; } double width = itemFont.GlyphWidthCache[glyphIndex] * fontSize; if (totalWidth + width > maxWidth) { if (glyphIndexes.Count > 0) { TextDrawItem item = new TextDrawItem(); item.FontColor = fontColor; item.Text = new GlyphRun(itemFont.GlyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); textDrawList.Add(item); } if (totalHeight > maxHeight) { //次の行無理 useHeight = totalHeight; return false; } else { //次の行いける dpiy = (totalHeight + baseline) * m.M22; origin = new Point(Math.Round(dpix / m.M11), Math.Round(dpiy / m.M22)); totalHeight += Math.Max(fontHeight, fontSize + 2); totalWidth = 0; glyphIndexes = new List<ushort>(); advanceWidths = new List<double>(); // XAML に合わせて、行頭の空白を無視する if (line[n] == ' ' || line[n] == '\x3000') continue; } } glyphIndexes.Add(glyphIndex); advanceWidths.Add(width); totalWidth += width; } if (glyphIndexes.Count > 0) { TextDrawItem item = new TextDrawItem(); item.FontColor = fontColor; item.Text = new GlyphRun(itemFont.GlyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); textDrawList.Add(item); } } useHeight = Math.Floor(totalHeight); return true; }
protected bool RenderText(String text, ref List <TextDrawItem> textDrawList, GlyphTypeface glyphType, double fontSize, double maxWidth, double maxHeight, double x, double y, ref double useHeight, SolidColorBrush fontColor, Matrix m) { double totalHeight = 0; string[] lineText = text.Replace("\r", "").Split('\n'); foreach (string line in lineText) { totalHeight += Math.Floor(2 + fontSize); List <ushort> glyphIndexes = new List <ushort>(); List <double> advanceWidths = new List <double>(); double totalWidth = 0; for (int n = 0; n < line.Length; n++) { ushort glyphIndex = glyphType.CharacterToGlyphMap[line[n]]; double width = glyphType.AdvanceWidths[glyphIndex] * fontSize; if (totalWidth + width > maxWidth) { if (totalHeight > maxHeight) { //次の行無理 // glyphIndex = glyphType.CharacterToGlyphMap['…']; // glyphIndexes[glyphIndexes.Count - 1] = glyphIndex; // advanceWidths[advanceWidths.Count - 1] = width; double dpix = Math.Ceiling((x + 2) * m.M11); double dpiy = Math.Ceiling((y + totalHeight) * m.M22); Point origin = new Point(dpix / m.M11, dpiy / m.M22); TextDrawItem item = new TextDrawItem(); item.FontColor = fontColor; item.Text = new GlyphRun(glyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); textDrawList.Add(item); useHeight = totalHeight; return(false); } else { //次の行いけるので今までの分出力 double dpix = Math.Ceiling((x + 2) * m.M11); double dpiy = Math.Ceiling((y + totalHeight) * m.M22); Point origin = new Point(dpix / m.M11, dpiy / m.M22); TextDrawItem item = new TextDrawItem(); item.FontColor = fontColor; item.Text = new GlyphRun(glyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); textDrawList.Add(item); totalHeight += fontSize + 2; glyphIndexes = new List <ushort>(); advanceWidths = new List <double>(); totalWidth = 0; } } glyphIndexes.Add(glyphIndex); advanceWidths.Add(width); totalWidth += width; } if (glyphIndexes.Count > 0) { double dpix = Math.Ceiling((x + 2) * m.M11); double dpiy = Math.Ceiling((y + totalHeight) * m.M22); Point origin = new Point(dpix / m.M11, dpiy / m.M22); TextDrawItem item = new TextDrawItem(); item.FontColor = fontColor; item.Text = new GlyphRun(glyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); textDrawList.Add(item); } } useHeight = Math.Floor(totalHeight); return(true); }
protected bool RenderText(String text, ref List<TextDrawItem> textDrawList, GlyphTypeface glyphType, double fontSize, double maxWidth, double maxHeight, double x, double y, ref double useHeight, SolidColorBrush fontColor, Matrix m) { double totalHeight = 0; string[] lineText = text.Replace("\r", "").Split('\n'); foreach (string line in lineText) { totalHeight += Math.Floor(2 + fontSize); List<ushort> glyphIndexes = new List<ushort>(); List<double> advanceWidths = new List<double>(); double totalWidth = 0; for (int n = 0; n < line.Length; n++) { ushort glyphIndex = glyphType.CharacterToGlyphMap[line[n]]; double width = glyphType.AdvanceWidths[glyphIndex] * fontSize; if (totalWidth + width > maxWidth) { if (glyphIndexes.Count > 0) { double dpix = Math.Ceiling((x + 2) * m.M11); double dpiy = Math.Ceiling((y + totalHeight) * m.M22); Point origin = new Point(dpix / m.M11, dpiy / m.M22); TextDrawItem item = new TextDrawItem(); item.FontColor = fontColor; item.Text = new GlyphRun(glyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); textDrawList.Add(item); } if (totalHeight > maxHeight) { //次の行無理 useHeight = totalHeight; return false; } else { //次の行いける totalHeight += fontSize + 2; glyphIndexes = new List<ushort>(); advanceWidths = new List<double>(); totalWidth = 0; } } glyphIndexes.Add(glyphIndex); advanceWidths.Add(width); totalWidth += width; } if (glyphIndexes.Count > 0) { double dpix = Math.Ceiling((x + 2) * m.M11); double dpiy = Math.Ceiling((y + totalHeight) * m.M22); Point origin = new Point(dpix / m.M11, dpiy / m.M22); TextDrawItem item = new TextDrawItem(); item.FontColor = fontColor; item.Text = new GlyphRun(glyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); textDrawList.Add(item); } } useHeight = Math.Floor(totalHeight); return true; }
protected bool RenderText(String text, ref List <TextDrawItem> textDrawList, ViewUtil.ItemFont itemFont, double fontSize, double maxWidth, double maxHeight, double x, double baseline, ref double useHeight, Brush fontColor, Matrix m) { double totalHeight = 0; double fontHeight = fontSize * itemFont.GlyphType.Height; string[] lineText = text.Replace("\r", "").Split('\n'); foreach (string line in lineText) { List <ushort> glyphIndexes = new List <ushort>(); List <double> advanceWidths = new List <double>(); //ベースラインの位置 double dpix = x * m.M11; double dpiy = (totalHeight + baseline) * m.M22; // ビットマップフォントがかすれる問題 とりあえず整数にしておく Point origin = new Point(Math.Round(dpix / m.M11), Math.Round(dpiy / m.M22)); //メイリオみたいに行間のあるフォントと MS P ゴシックみたいな行間のないフォントがあるので //なんとなく行間を作ってみる。 totalHeight += Math.Max(fontHeight, fontSize + 2); double totalWidth = 0; for (int n = 0; n < line.Length; n++) { // XAML に合わせて、行頭の空白を無視する if (glyphIndexes.Count == 0 && (line[n] == ' ' || line[n] == '\x3000')) { continue; } //この辞書検索が負荷の大部分を占めているのでテーブルルックアップする //(簡単なパフォーマンス計測をした結果、2~10倍くらい速くなったようだ) //ushort glyphIndex = itemFont.GlyphType.CharacterToGlyphMap[line[n]]; //double width = itemFont.GlyphType.AdvanceWidths[glyphIndex] * fontSize; ushort glyphIndex = itemFont.GlyphIndexCache[line[n]]; if (glyphIndex == 0) { itemFont.GlyphType.CharacterToGlyphMap.TryGetValue(line[n], out glyphIndex); itemFont.GlyphIndexCache[line[n]] = glyphIndex; itemFont.GlyphWidthCache[glyphIndex] = (float)itemFont.GlyphType.AdvanceWidths[glyphIndex]; } double width = itemFont.GlyphWidthCache[glyphIndex] * fontSize; if (totalWidth + width > maxWidth) { if (glyphIndexes.Count > 0) { TextDrawItem item = new TextDrawItem(); item.FontColor = fontColor; item.Text = new GlyphRun(itemFont.GlyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); textDrawList.Add(item); } if (totalHeight > maxHeight) { //次の行無理 useHeight = totalHeight; return(false); } else { //次の行いける dpiy = (totalHeight + baseline) * m.M22; origin = new Point(Math.Round(dpix / m.M11), Math.Round(dpiy / m.M22)); totalHeight += Math.Max(fontHeight, fontSize + 2); totalWidth = 0; glyphIndexes = new List <ushort>(); advanceWidths = new List <double>(); // XAML に合わせて、行頭の空白を無視する if (line[n] == ' ' || line[n] == '\x3000') { continue; } } } glyphIndexes.Add(glyphIndex); advanceWidths.Add(width); totalWidth += width; } if (glyphIndexes.Count > 0) { TextDrawItem item = new TextDrawItem(); item.FontColor = fontColor; item.Text = new GlyphRun(itemFont.GlyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); textDrawList.Add(item); } } useHeight = Math.Floor(totalHeight); return(true); }