Thanks for the quick response. It works using this approach, then blitting with my base WriteableBitmap.
On performance, I'm seeing ~600uS to create each label and cache it in a WriteableBitmap object. For my use case of ~100K items (1 item = rectangle and label), the time to create each and cache for subsequent blitting would be >55s which is too much. Is this the most performant text approach that I should expect? Would the Silverlight UIElement conversion take about the same time? Maybe this is just my wake up call that drawing text is expensive.
As for the blitting of a cached text bitmap into the base, the performance is quite reasonable averaging 720nS per-blit; thus 72ms for my 100K case, although I plan to only conditionally add the text if determined it will be readable.
Benchmark system: Core i7 Q740, 1.73Ghz, 8GB RAM, W7 x64
//-----------------------------------
To summarize my approach for others, given the performance seen:
On performance, I'm seeing ~600uS to create each label and cache it in a WriteableBitmap object. For my use case of ~100K items (1 item = rectangle and label), the time to create each and cache for subsequent blitting would be >55s which is too much. Is this the most performant text approach that I should expect? Would the Silverlight UIElement conversion take about the same time? Maybe this is just my wake up call that drawing text is expensive.
As for the blitting of a cached text bitmap into the base, the performance is quite reasonable averaging 720nS per-blit; thus 72ms for my 100K case, although I plan to only conditionally add the text if determined it will be readable.
Benchmark system: Core i7 Q740, 1.73Ghz, 8GB RAM, W7 x64
//-----------------------------------
To summarize my approach for others, given the performance seen:
-
Create a WriteableBitmap for the text (created on-demand and cached for future repeated use)
a) DrawingVisual's DrawingContext.DrawText (<FormattedText>, new Point(0,0))
b) Use the bounds of the FormattedText object as the 'sourceRect'
c) Convert the DrawingVisual to a RenderTargetBitmap using sourceRect from (b)
d) Create a WriteableBitmap object dimensioned the same size as sourceRect
FormattedText text = new FormattedText(displayLabel,
new System.Globalization.CultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface(new FontFamily("Arial"), FontStyles.Normal, FontWeights.Normal, new FontStretch()),
12,
Brushes.Black);
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
drawingContext.DrawText(text, new Point(0, 0));
drawingContext.Close();
Rect sourceRect = new Rect(0, 0, (int)text.Width, (int)text.Height);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)sourceRect.Width, (int)sourceRect.Height, 96, 96, PixelFormats.Pbgra32);
rtb.Render(drawingVisual);
LabelBitmapCache = BitmapFactory.New((int)sourceRect.Width, (int)sourceRect.Height);
rtb.CopyPixels(new Int32Rect(0, 0, rtb.PixelWidth, rtb.PixelHeight),
LabelBitmapCache.BackBuffer,
LabelBitmapCache.BackBufferStride * LabelBitmapCache.PixelHeight,
LabelBitmapCache.BackBufferStride);
- Conditionally blit the text cached WriteableBitmap with my base (if determined it will be readable - not shown)
_bmp.Blit(new Rect(left, 5, i.LabelBitmapCache.PixelWidth, i.LabelBitmapCache.PixelHeight), i.LabelBitmapCache,
new Rect(0,0,i.LabelVisual.ContentBounds.Width, i.LabelVisual.ContentBounds.Height));