Why is Wpf's DrawingContext.DrawText so expensive?

后端 未结 3 1038

In Wpf (4.0) my listbox (using a VirtualizingStackPanel) contains 500 items. Each item is of a custom Type

class Page : FrameworkElement
...
protected over         


        
3条回答
  •  一个人的身影
    2020-12-31 14:33

    I found user638350's solution to be very useful; in my case i only use one font size so the following optimizations reduced the time to less than 0.0000 over 20,000 frames down from 0.0060ms every frame. Most of the slow down is from 'TryGetGlyphTypeface' and 'AdvanceWidths' and so these two are cached. Also, added calculating an offset position and tracking a total width.

        private static Dictionary _glyphWidths = new Dictionary();
        private static GlyphTypeface _glyphTypeface;
        public static GlyphRun CreateGlyphRun(string text, double size, Point position)
        {
            if (_glyphTypeface == null)
            {
                Typeface typeface = new Typeface("Arial");
                if (!typeface.TryGetGlyphTypeface(out _glyphTypeface))
                    throw new InvalidOperationException("No glyphtypeface found");                
            }
    
            ushort[] glyphIndexes = new ushort[text.Length];
            double[] advanceWidths = new double[text.Length];
    
            var totalWidth = 0d;
            double glyphWidth;
    
            for (int n = 0; n < text.Length; n++)
            {
                ushort glyphIndex = (ushort)(text[n] - 29);
                glyphIndexes[n] = glyphIndex;
    
                if (!_glyphWidths.TryGetValue(glyphIndex, out glyphWidth))
                {
                    glyphWidth = _glyphTypeface.AdvanceWidths[glyphIndex] * size;
                    _glyphWidths.Add(glyphIndex, glyphWidth);
                }
                advanceWidths[n] = glyphWidth;
                totalWidth += glyphWidth;
            }
    
            var offsetPosition = new Point(position.X - (totalWidth / 2), position.Y - 10 - size);
    
            GlyphRun glyphRun = new GlyphRun(_glyphTypeface, 0, false, size, glyphIndexes, offsetPosition, advanceWidths, null, null, null, null, null, null);
    
            return glyphRun;
        }
    

提交回复
热议问题