using FastReport.Utils;
using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace FastReport
{
///
/// Represents a cache of graphics objects such as pens, brushes, fonts and text formats.
///
///
/// Cache holds all used graphics objects. There is no need to dispose objects returned
/// by GetXXX calls.
///
/// This example demonstrates how to use graphic cache.
///
/// public void Draw(FRPaintEventArgs e)
/// {
/// Brush brush = e.Cache.GetBrush(BackColor);
/// Pen pen = e.Cache.GetPen(BorderColor, 1, BorderStyle);
/// e.Graphics.FillRectangle(brush, Bounds);
/// e.Graphics.DrawRectangle(pen, Bounds);
/// }
///
///
public class GraphicCache : IDisposable
{
private Hashtable pens;
private Hashtable brushes;
private Hashtable fonts;
private Hashtable stringFormats;
///
/// Gets a pen with specified settings.
///
/// Color of a pen.
/// Width of a pen.
/// Dash style of a pen.
/// The Pen object.
public Pen GetPen(Color color, float width, DashStyle style)
{
return GetPen(color, width, style, LineJoin.Miter);
}
///
/// Gets a pen with specified settings.
///
/// Color of a pen.
/// Width of a pen.
/// Dash style of a pen.
/// Line join of a pen.
/// The Pen object.
public Pen GetPen(Color color, float width, DashStyle style, LineJoin lineJoin)
{
int hash = color.GetHashCode() ^ width.GetHashCode() ^ style.GetHashCode() ^ lineJoin.GetHashCode();
Pen result = pens[hash] as Pen;
if (result == null)
{
result = new Pen(color, width);
result.DashStyle = style;
result.LineJoin = lineJoin;
pens[hash] = result;
}
return result;
}
///
/// Gets a brush with specified color.
///
/// Color of a brush.
/// The SolidBrush object.
public SolidBrush GetBrush(Color color)
{
int hash = color.GetHashCode();
SolidBrush result = brushes[hash] as SolidBrush;
if (result == null)
{
result = new SolidBrush(color);
brushes[hash] = result;
}
return result;
}
///
/// Gets a font with specified settings.
///
/// Family of a font.
/// Size of a font.
/// Style of a font.
/// The Font object.
public Font GetFont(FontFamily name, float size, FontStyle style)
{
int hash = name.GetHashCode() ^ size.GetHashCode() ^ style.GetHashCode();
Font result = fonts[hash] as Font;
if (result == null)
{
result = new Font(name, size, style);
fonts[hash] = result;
}
return result;
}
///
/// Gets a string format with specified settings.
///
/// Text alignment information on the vertical plane.
/// Line alignment on the horizontal plane.
/// StringTrimming enumeration.
/// StringFormatFlags enumeration that contains formatting information.
/// The number of spaces between the beginning of a line of text and the first tab stop.
/// Distance between tab stops.
/// The StringFormat object.
public StringFormat GetStringFormat(StringAlignment align, StringAlignment lineAlign,
StringTrimming trimming, StringFormatFlags flags, float firstTab, float tabWidth)
{
int hash = align.GetHashCode() ^ (lineAlign.GetHashCode() << 2) ^ (trimming.GetHashCode() << 5) ^
(flags.GetHashCode() << 16) ^ (100 - firstTab).GetHashCode() ^ tabWidth.GetHashCode();
StringFormat result = stringFormats[hash] as StringFormat;
if (result == null)
{
result = new StringFormat();
result.Alignment = align;
result.LineAlignment = lineAlign;
result.Trimming = trimming;
result.FormatFlags = flags;
float[] tabStops = new float[64];
// fixed issue 2823
tabStops[0] = firstTab < 0 ? 0 : firstTab;
for (int i = 1; i < 64; i++)
{
tabStops[i] = tabWidth < 0 ? 0 : tabWidth;
}
result.SetTabStops(0, tabStops);
stringFormats[hash] = result;
}
return result;
}
///
/// Gets a string format with specified settings.
///
/// Text alignment information on the vertical plane.
/// Line alignment on the horizontal plane.
/// StringTrimming enumeration.
/// StringFormatFlags enumeration that contains formatting information.
/// The number of spaces between the beginning of a line of text and the first tab stop.
/// Distance between tab stops.
/// Default distance between default tabs stops.
/// The StringFormat object.
public StringFormat GetStringFormat(StringAlignment align, StringAlignment lineAlign,
StringTrimming trimming, StringFormatFlags flags, float firstTab, FloatCollection tabWidth,
float defaultTab = 48)
{
int hash = align.GetHashCode() ^ (lineAlign.GetHashCode() << 2) ^ (trimming.GetHashCode() << 5) ^
(flags.GetHashCode() << 16) ^ (100 - firstTab).GetHashCode() ^ tabWidth.GetHashCode();
StringFormat result = stringFormats[hash] as StringFormat;
if (result == null)
{
result = new StringFormat();
result.Alignment = align;
result.LineAlignment = lineAlign;
result.Trimming = trimming;
result.FormatFlags = flags;
float[] tabStops = new float[64];
float sumWidth = firstTab;
// fixed issue 2823
tabStops[0] = firstTab < 0 ? 0 : firstTab;
for (int i = 1; i < 64; i++)
{
if (i > tabWidth.Count)
{
tabStops[i] = defaultTab < 0 ? 0 : defaultTab;
//tab stops have static positions we need to go back to them
if (sumWidth % defaultTab != 0)
tabStops[i] = defaultTab - sumWidth % defaultTab;
sumWidth += tabStops[i];
continue;
}
tabStops[i] = tabWidth[i - 1] < 0 ? 0 : tabWidth[i - 1];
sumWidth += tabStops[i];
}
result.SetTabStops(0, tabStops);
stringFormats[hash] = result;
}
return result;
}
///
/// Disposes resources used by this object.
///
public void Dispose()
{
foreach (Pen pen in pens.Values)
{
pen.Dispose();
}
foreach (Brush brush in brushes.Values)
{
brush.Dispose();
}
foreach (Font font in fonts.Values)
{
font.Dispose();
}
foreach (StringFormat format in stringFormats.Values)
{
format.Dispose();
}
pens.Clear();
brushes.Clear();
fonts.Clear();
stringFormats.Clear();
}
///
/// Initializes a new instance of the GraphicCache class with default settings.
///
public GraphicCache()
{
pens = new Hashtable();
brushes = new Hashtable();
fonts = new Hashtable();
stringFormats = new Hashtable();
}
}
}