Пример #1
0
        protected bool RenderText(String text, DrawingContext dc, ViewUtil.ItemFont itemFont, Brush brush, double fontSize, double maxWidth, double maxHeight, double x, double baseline, ref double useHeight, bool nowrap = false)
        {
            if (x <= 0 || maxWidth <= 0)
            {
                useHeight = 0;
                return(false);
            }

            double totalHeight = 0;
            double fontHeight  = fontSize * itemFont.GlyphType.Height;

            string[] lineText = text.Replace("\r", "").Split('\n');
            foreach (string line in lineText)
            {
                //高さ確認
                if (totalHeight + fontHeight > maxHeight)
                {
                    //これ以上は無理
                    useHeight = totalHeight;
                    return(false);
                }

                // ベースラインの位置の計算
                // ビットマップフォントがかすれる問題 とりあえず整数にしておく
                Point origin = new Point(Math.Round(x), Math.Round(totalHeight + baseline));

                //メイリオみたいに行間のあるフォントと MS P ゴシックみたいな行間のないフォントがあるので
                //なんとなく行間を作ってみる。
                totalHeight += Math.Max(fontHeight, fontSize + 2);
                double totalWidth = 0;

                List <ushort> glyphIndexes  = new List <ushort>();
                List <double> advanceWidths = new List <double>();
                for (int n = 0; n < line.Length; n++)
                {
                    // XAML に合わせて、行頭の空白を無視する
                    if (glyphIndexes.Count == 0 && (line[n] == ' ' || line[n] == '\x3000'))
                    {
                        continue;
                    }

                    //ushort glyphIndex = glyphType.CharacterToGlyphMap[line[n]];
                    //double width = 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 (nowrap == true)
                        {
                            break;                //改行しない場合ここで終り
                        }
                        if (totalWidth == 0)
                        {
                            return(false);                //一文字も置けなかった(glyphIndexesなどのCount=0のまま)
                        }
                        if (totalHeight + fontHeight > maxHeight)
                        {
                            //次の行無理
                            //glyphIndex = glyphType.CharacterToGlyphMap['…'];
                            //double widthEllipsis = glyphType.AdvanceWidths[glyphIndex] * fontSize;
                            glyphIndex = itemFont.GlyphType.CharacterToGlyphMap['…'];
                            double widthEllipsis = itemFont.GlyphType.AdvanceWidths[glyphIndex] * fontSize;
                            while (totalWidth - advanceWidths.Last() + widthEllipsis > maxWidth)
                            {
                                totalWidth -= advanceWidths.Last();
                                glyphIndexes.RemoveAt(glyphIndexes.Count - 1);
                                advanceWidths.RemoveAt(advanceWidths.Count - 1);
                            }
                            glyphIndexes[glyphIndexes.Count - 1]   = glyphIndex;
                            advanceWidths[advanceWidths.Count - 1] = widthEllipsis;

                            GlyphRun glyphRun = new GlyphRun(itemFont.GlyphType, 0, false, fontSize,
                                                             glyphIndexes, origin, advanceWidths, null, null, null, null,
                                                             null, null);

                            dc.DrawGlyphRun(brush, glyphRun);

                            useHeight = totalHeight;
                            return(false);
                        }
                        else
                        {
                            //次の行いけるので今までの分出力
                            GlyphRun glyphRun = new GlyphRun(itemFont.GlyphType, 0, false, fontSize,
                                                             glyphIndexes, origin, advanceWidths, null, null, null, null,
                                                             null, null);

                            dc.DrawGlyphRun(brush, glyphRun);

                            origin        = new Point(Math.Round(x), Math.Round(totalHeight + baseline));
                            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)
                {
                    GlyphRun glyphRun = new GlyphRun(itemFont.GlyphType, 0, false, fontSize,
                                                     glyphIndexes, origin, advanceWidths, null, null, null, null,
                                                     null, null);

                    dc.DrawGlyphRun(brush, glyphRun);
                }
            }
            useHeight = totalHeight;
            return(true);
        }
Пример #2
0
        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);
        }