using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
namespace TextDesignerCSLibrary
{
///
/// Class to store the font info to pass as parameter to the drawing methods.
///
public class TextContext
{
public TextContext()
{
fontFamily = new System.Drawing.FontFamily("Arial");
fontStyle = System.Drawing.FontStyle.Regular;
nfontSize = 20;
pszText = null;
ptDraw = new System.Drawing.Point(0, 0);
strFormat = new System.Drawing.StringFormat();
}
///
/// fontFamily is the font family
///
public System.Drawing.FontFamily fontFamily;
///
/// fontStyle is the font style, eg, bold, italic or bold
///
public System.Drawing.FontStyle fontStyle;
///
/// nfontSize is font size
///
public int nfontSize;
///
/// pszText is the text to be displayed
///
public string pszText;
///
/// ptDraw is the point to draw
///
public System.Drawing.Point ptDraw;
///
/// strFormat is the string format
///
public System.Drawing.StringFormat strFormat;
}
///
/// Class to draw text outlines
///
public class Canvas
{
///
/// Generate Text Glow strategy
///
/// is the color of the text
/// is the color of the glow outline
/// is the thickness of the outline in pixels
/// valid ITextStrategy pointer if successful
public static ITextStrategy TextGlow(
System.Drawing.Color clrText,
System.Drawing.Color clrOutline,
int nThickness)
{
TextGlowStrategy strat = new TextGlowStrategy();
strat.Init(clrText, clrOutline, nThickness);
return strat;
}
///
/// Generate Text Glow strategy
///
/// is the brush of the text
/// is the color of the glow outline
/// is the thickness of the outline in pixels
/// valid ITextStrategy pointer if successful
public static ITextStrategy TextGlow(
System.Drawing.Brush brushText,
System.Drawing.Color clrOutline,
int nThickness)
{
TextGlowStrategy strat = new TextGlowStrategy();
strat.Init(brushText, clrOutline, nThickness);
return strat;
}
///
/// Generate Text Outline strategy
///
/// is the color of the text
/// is the color of the outline
/// is the thickness of the outline in pixels
/// valid ITextStrategy pointer if successful
public static ITextStrategy TextOutline(
System.Drawing.Color clrText,
System.Drawing.Color clrOutline,
int nThickness)
{
TextOutlineStrategy strat = new TextOutlineStrategy();
strat.Init(clrText, clrOutline, nThickness);
return strat;
}
///
/// Generate Text Outline strategy
///
/// is the brush of the text
/// is the color of the outline
/// is the thickness of the outline in pixels
/// valid ITextStrategy pointer if successful
public static ITextStrategy TextOutline(
System.Drawing.Brush brushText,
System.Drawing.Color clrOutline,
int nThickness)
{
TextOutlineStrategy strat = new TextOutlineStrategy();
strat.Init(brushText, clrOutline, nThickness);
return strat;
}
///
/// Setting Gradient Outlined Text effect
///
/// is the text color
/// is the inner outline color
/// is the outer outline color
/// is the outline thickness
/// valid ITextStrategy pointer if successful
public static ITextStrategy TextGradOutline(
System.Drawing.Color clrText,
System.Drawing.Color clrOutline1,
System.Drawing.Color clrOutline2,
int nThickness)
{
TextGradOutlineStrategy strat = new TextGradOutlineStrategy();
strat.Init(clrText, clrOutline1, clrOutline2, nThickness);
return strat;
}
///
/// Setting Gradient Outlined Text effect
///
/// is the text brush
/// is the inner outline color
/// is the outer outline color
/// is the outline thickness
/// valid ITextStrategy pointer if successful
public static ITextStrategy TextGradOutline(
System.Drawing.Brush brushText,
System.Drawing.Color clrOutline1,
System.Drawing.Color clrOutline2,
int nThickness)
{
TextGradOutlineStrategy strat = new TextGradOutlineStrategy();
strat.Init(brushText, clrOutline1, clrOutline2, nThickness);
return strat;
}
///
/// Setting just Text effect with no outline
///
/// is the text color
/// valid ITextStrategy pointer if successful
public static ITextStrategy TextNoOutline(
System.Drawing.Color clrText)
{
TextNoOutlineStrategy strat = new TextNoOutlineStrategy();
strat.Init(clrText);
return strat;
}
///
/// Setting just Text effect with no outline
///
/// is the text brush
/// valid ITextStrategy pointer if successful
public static ITextStrategy TextNoOutline(
System.Drawing.Brush brushText)
{
TextNoOutlineStrategy strat = new TextNoOutlineStrategy();
strat.Init(brushText);
return strat;
}
///
/// Setting Outlined Text effect with no text fill
///
/// is the outline color
/// is the outline thickness
/// specifies rounded or sharp edges
/// valid ITextStrategy pointer if successful
public static ITextStrategy TextOnlyOutline(
System.Drawing.Color clrOutline,
int nThickness,
bool bRoundedEdge)
{
TextOnlyOutlineStrategy strat = new TextOnlyOutlineStrategy();
strat.Init(clrOutline, nThickness, bRoundedEdge);
return strat;
}
///
/// Generate a canvas image based on width and height
///
/// is the image width
/// is the image height
/// a valid canvas image if successful
public static System.Drawing.Bitmap GenImage(int width, int height)
{
return new System.Drawing.Bitmap(width, height, PixelFormat.Format32bppArgb);
}
///
/// Generate a canvas image based on width and height
///
/// is the image width
/// is the image height
/// is the list of colors for the gradient
/// specifies whether the gradient is horizontal
/// a valid canvas image if successful
public static System.Drawing.Bitmap GenImage(int width, int height, List colors, bool horizontal)
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height, PixelFormat.Format32bppArgb);
DrawGradient.Draw(bmp, colors, horizontal);
return bmp;
}
///
/// Generate a canvas image based on width and height
///
/// is the image width
/// is the image height
/// is the color to paint the image
/// a valid canvas image if successful
public static System.Drawing.Bitmap GenImage(int width, int height, System.Drawing.Color clr)
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height, PixelFormat.Format32bppArgb);
BitmapData bitmapData = new BitmapData();
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
bmp.LockBits(
rect,
ImageLockMode.WriteOnly,
PixelFormat.Format32bppArgb,
bitmapData);
unsafe
{
uint* pixels = (uint*)bitmapData.Scan0;
if (pixels == null)
return null;
uint col = 0;
int stride = bitmapData.Stride >> 2;
uint color = (uint)(clr.A << 24 | clr.R << 16 | clr.G << 8 | clr.G);
for (uint row = 0; row < bitmapData.Height; ++row)
{
for (col = 0; col < bitmapData.Width; ++col)
{
uint index = (uint)(row * stride + col);
pixels[index] = color;
}
}
}
bmp.UnlockBits(bitmapData);
return bmp;
}
///
/// Generate a canvas image based on width and height
///
/// is the image width
/// is the image height
/// is the color to paint the image
/// is alpha of the color
/// a valid canvas image if successful
public static System.Drawing.Bitmap GenImage(int width, int height, System.Drawing.Color clr, byte alpha)
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height, PixelFormat.Format32bppArgb);
BitmapData bitmapData = new BitmapData();
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
bmp.LockBits(
rect,
ImageLockMode.WriteOnly,
PixelFormat.Format32bppArgb,
bitmapData);
unsafe
{
uint* pixels = (uint*)bitmapData.Scan0;
if (pixels == null)
return null;
uint col = 0;
int stride = bitmapData.Stride >> 2;
uint color = (uint)(alpha << 24 | clr.R << 16 | clr.G << 8 | clr.G);
for (uint row = 0; row < bitmapData.Height; ++row)
{
for (col = 0; col < bitmapData.Width; ++col)
{
uint index = (uint)(row * stride + col);
pixels[index] = color;
}
}
}
bmp.UnlockBits(bitmapData);
return bmp;
}
///
/// Generate mask image of the text strategy.
///
/// is text strategy
/// is the mask image width
/// is the mask image height
/// offsets the text (typically used for shadows)
/// is text context
/// a valid mask image if successful
public static System.Drawing.Bitmap GenMask(
ITextStrategy strategy,
int width,
int height,
System.Drawing.Point offset,
TextContext textContext)
{
if (strategy == null || textContext == null)
return null;
System.Drawing.Bitmap pBmp = new System.Drawing.Bitmap(width, height, PixelFormat.Format32bppArgb);
using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(pBmp))
{
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
strategy.DrawString(graphics,
textContext.fontFamily,
textContext.fontStyle,
textContext.nfontSize,
textContext.pszText,
new System.Drawing.Point(textContext.ptDraw.X + offset.X, textContext.ptDraw.Y + offset.Y),
textContext.strFormat);
}
return pBmp;
}
///
/// Measure the mask image based on the mask color.
///
/// is the mask image to be measured
/// is mask color used in mask image
/// returns the topmost Y
/// returns the leftmost X
/// returns the bottommost Y
/// returns the rightmost X
/// true if successful
public static bool MeasureMaskLength(
System.Drawing.Bitmap mask,
System.Drawing.Color maskColor,
ref uint top,
ref uint left,
ref uint bottom,
ref uint right)
{
top = 30000;
left = 30000;
bottom = 0;
right = 0;
if (mask == null)
return false;
BitmapData bitmapDataMask = new BitmapData();
Rectangle rect = new Rectangle(0, 0, mask.Width, mask.Height);
mask.LockBits(
rect,
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb,
bitmapDataMask);
unsafe
{
uint* pixelsMask = (uint*)bitmapDataMask.Scan0;
if (pixelsMask == null)
return false;
uint col = 0;
int stride = bitmapDataMask.Stride >> 2;
for (uint row = 0; row < bitmapDataMask.Height; ++row)
{
for (col = 0; col < bitmapDataMask.Width; ++col)
{
uint index = (uint)(row * stride + col);
byte nAlpha = 0;
if (MaskColor.IsEqual(maskColor, MaskColor.Red))
nAlpha = (Byte)((pixelsMask[index] & 0xff0000) >> 16);
else if (MaskColor.IsEqual(maskColor, MaskColor.Green))
nAlpha = (Byte)((pixelsMask[index] & 0xff00) >> 8);
else if (MaskColor.IsEqual(maskColor, MaskColor.Blue))
nAlpha = (Byte)(pixelsMask[index] & 0xff);
if (nAlpha > 0)
{
if (col < left)
left = col;
if (row < top)
top = row;
if (col > right)
right = col;
if (row > bottom)
bottom = row;
}
}
}
}
mask.UnlockBits(bitmapDataMask);
return true;
}
///
/// Apply image to mask onto the canvas
///
/// is the image to be used
/// is the mask image to be read
/// is the destination image to be draw upon
/// is mask color used in mask image
/// true if successful
public static bool ApplyImageToMask(
System.Drawing.Bitmap image,
System.Drawing.Bitmap mask,
System.Drawing.Bitmap canvas,
System.Drawing.Color maskColor)
{
if (image == null || mask == null || canvas == null)
return false;
BitmapData bitmapDataImage = new BitmapData();
BitmapData bitmapDataMask = new BitmapData();
BitmapData bitmapDataCanvas = new BitmapData();
Rectangle rectCanvas = new Rectangle(0, 0, canvas.Width, canvas.Height);
Rectangle rectMask = new Rectangle(0, 0, mask.Width, mask.Height);
Rectangle rectImage = new Rectangle(0, 0, image.Width, image.Height);
image.LockBits(
rectImage,
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb,
bitmapDataImage);
mask.LockBits(
rectMask,
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb,
bitmapDataMask);
canvas.LockBits(
rectCanvas,
ImageLockMode.WriteOnly,
PixelFormat.Format32bppArgb,
bitmapDataCanvas);
unsafe
{
uint* pixelsImage = (uint*)bitmapDataImage.Scan0;
uint* pixelsMask = (uint*)bitmapDataMask.Scan0;
uint* pixelsCanvas = (uint*)bitmapDataCanvas.Scan0;
if (pixelsImage == null || pixelsMask == null || pixelsCanvas == null)
return false;
uint col = 0;
int stride = bitmapDataCanvas.Stride >> 2;
for (uint row = 0; row < bitmapDataCanvas.Height; ++row)
{
for (col = 0; col < bitmapDataCanvas.Width; ++col)
{
if (row >= bitmapDataImage.Height || col >= bitmapDataImage.Width)
continue;
if (row >= bitmapDataMask.Height || col >= bitmapDataMask.Width)
continue;
uint index = (uint)(row * stride + col);
uint indexMask = (uint)(row * (bitmapDataMask.Stride >> 2) + col);
uint indexImage = (uint)(row * (bitmapDataImage.Stride >> 2) + col);
byte maskByte = 0;
if (MaskColor.IsEqual(maskColor, MaskColor.Red))
maskByte = (Byte)((pixelsMask[indexMask] & 0xff0000) >> 16);
else if (MaskColor.IsEqual(maskColor, MaskColor.Green))
maskByte = (Byte)((pixelsMask[indexMask] & 0xff00) >> 8);
else if (MaskColor.IsEqual(maskColor, MaskColor.Blue))
maskByte = (Byte)(pixelsMask[indexMask] & 0xff);
if (maskByte > 0)
pixelsCanvas[index] = Alphablend(pixelsCanvas[index], pixelsImage[indexImage], (Byte)(pixelsMask[indexMask] >> 24), (Byte)(pixelsMask[indexMask] >> 24));
}
}
}
canvas.UnlockBits(bitmapDataCanvas);
mask.UnlockBits(bitmapDataMask);
image.UnlockBits(bitmapDataImage);
return true;
}
///
/// Apply color to mask onto the canvas
///
/// is the color to be used
/// is the mask image to be read
/// is the destination image to be draw upon
/// is mask color used in mask image
/// true if successful
public static bool ApplyColorToMask(
System.Drawing.Color clr,
System.Drawing.Bitmap mask,
System.Drawing.Bitmap canvas,
System.Drawing.Color maskColor)
{
if (mask == null || canvas == null)
return false;
BitmapData bitmapDataMask = new BitmapData();
BitmapData bitmapDataCanvas = new BitmapData();
Rectangle rectCanvas = new Rectangle(0, 0, canvas.Width, canvas.Height);
Rectangle rectMask = new Rectangle(0, 0, mask.Width, mask.Height);
mask.LockBits(
rectMask,
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb,
bitmapDataMask);
canvas.LockBits(
rectCanvas,
ImageLockMode.WriteOnly,
PixelFormat.Format32bppArgb,
bitmapDataCanvas);
unsafe
{
uint* pixelsMask = (uint*)bitmapDataMask.Scan0;
uint* pixelsCanvas = (uint*)bitmapDataCanvas.Scan0;
if (pixelsMask == null || pixelsCanvas == null)
return false;
uint col = 0;
int stride = bitmapDataCanvas.Stride >> 2;
for (uint row = 0; row < bitmapDataCanvas.Height; ++row)
{
for (col = 0; col < bitmapDataCanvas.Width; ++col)
{
if (row >= bitmapDataMask.Height || col >= bitmapDataMask.Width)
continue;
uint index = (uint)(row * stride + col);
uint indexMask = (uint)(row * (bitmapDataMask.Stride >> 2) + col);
byte maskByte = 0;
if (MaskColor.IsEqual(maskColor, MaskColor.Red))
maskByte = (Byte)((pixelsMask[indexMask] & 0xff0000) >> 16);
else if (MaskColor.IsEqual(maskColor, MaskColor.Green))
maskByte = (Byte)((pixelsMask[indexMask] & 0xff00) >> 8);
else if (MaskColor.IsEqual(maskColor, MaskColor.Blue))
maskByte = (Byte)(pixelsMask[indexMask] & 0xff);
uint color = (uint)(0xff << 24 | clr.R << 16 | clr.G << 8 | clr.B);
if (maskByte > 0)
pixelsCanvas[index] = Alphablend(pixelsCanvas[index], color, (Byte)(pixelsMask[indexMask] >> 24), (Byte)(pixelsMask[indexMask] >> 24));
}
}
}
canvas.UnlockBits(bitmapDataCanvas);
mask.UnlockBits(bitmapDataMask);
return true;
}
///
/// Apply color to mask onto the canvas
///
/// is the color to be used
/// is the mask image to be read
/// is the destination image to be draw upon
/// is mask color used in mask image
/// determine how much to offset the mask
/// true if successful
public static bool ApplyColorToMask(
System.Drawing.Color clr,
System.Drawing.Bitmap mask,
System.Drawing.Bitmap canvas,
System.Drawing.Color maskColor,
System.Drawing.Point offset)
{
if (mask == null || canvas == null)
return false;
BitmapData bitmapDataMask = new BitmapData();
BitmapData bitmapDataCanvas = new BitmapData();
Rectangle rectCanvas = new Rectangle(0, 0, canvas.Width, canvas.Height);
Rectangle rectMask = new Rectangle(0, 0, mask.Width, mask.Height);
mask.LockBits(
rectMask,
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb,
bitmapDataMask);
canvas.LockBits(
rectCanvas,
ImageLockMode.WriteOnly,
PixelFormat.Format32bppArgb,
bitmapDataCanvas);
unsafe
{
uint* pixelsMask = (uint*)bitmapDataMask.Scan0;
uint* pixelsCanvas = (uint*)bitmapDataCanvas.Scan0;
if (pixelsMask == null || pixelsCanvas == null)
return false;
uint col = 0;
int stride = bitmapDataCanvas.Stride >> 2;
for (uint row = 0; row < bitmapDataCanvas.Height; ++row)
{
for (col = 0; col < bitmapDataCanvas.Width; ++col)
{
if ((row - offset.Y) >= bitmapDataMask.Height || (col - offset.X) >= bitmapDataMask.Width ||
(row - offset.Y) < 0 || (col - offset.X) < 0)
continue;
uint index = (uint)(row * stride + col);
uint indexMask = (uint)((row - offset.Y) * (bitmapDataMask.Stride >> 2) + (col - offset.X));
byte maskByte = 0;
if (MaskColor.IsEqual(maskColor, MaskColor.Red))
maskByte = (Byte)((pixelsMask[indexMask] & 0xff0000) >> 16);
else if (MaskColor.IsEqual(maskColor, MaskColor.Green))
maskByte = (Byte)((pixelsMask[indexMask] & 0xff00) >> 8);
else if (MaskColor.IsEqual(maskColor, MaskColor.Blue))
maskByte = (Byte)(pixelsMask[indexMask] & 0xff);
uint color = (uint)(0xff << 24 | clr.R << 16 | clr.G << 8 | clr.B);
if (maskByte > 0)
pixelsCanvas[index] = Alphablend(pixelsCanvas[index], color, (Byte)(pixelsMask[indexMask] >> 24), (Byte)(pixelsMask[indexMask] >> 24));
}
}
}
canvas.UnlockBits(bitmapDataCanvas);
mask.UnlockBits(bitmapDataMask);
return true;
}
///
/// Draw outline on image
///
/// is text strategy
/// is the image to be draw upon
/// offsets the text (typically used for shadows)
/// is text context
/// true if successful
public static bool DrawTextImage(
ITextStrategy strategy,
System.Drawing.Bitmap image,
System.Drawing.Point offset,
TextContext textContext)
{
if (strategy == null || image == null || textContext == null)
return false;
bool bRet = false;
using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(image))
{
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
bRet = strategy.DrawString(graphics,
textContext.fontFamily,
textContext.fontStyle,
textContext.nfontSize,
textContext.pszText,
new System.Drawing.Point(textContext.ptDraw.X + offset.X, textContext.ptDraw.Y + offset.Y),
textContext.strFormat);
}
return bRet;
}
///
/// Set alpha to color
///
/// is destination color in ARGB
/// is source color in ARGB
/// is nAlpha is alpha channel
///
private static UInt32 AddAlpha(UInt32 dest, UInt32 source, Byte nAlpha)
{
if (0 == nAlpha)
return dest;
if (255 == nAlpha)
return source;
Byte nSrcRed = (Byte)((source & 0xff0000) >> 16);
Byte nSrcGreen = (Byte)((source & 0xff00) >> 8);
Byte nSrcBlue = (Byte)((source & 0xff));
Byte nRed = (Byte)(nSrcRed);
Byte nGreen = (Byte)(nSrcGreen);
Byte nBlue = (Byte)(nSrcBlue);
return (UInt32)(nAlpha << 24 | nRed << 16 | nGreen << 8 | nBlue);
}
///
/// Performs Alphablend
///
/// is destination color in ARGB
/// is source color in ARGB
/// is nAlpha is alpha channel
/// sets alpha channel of the returned UInt32
/// destination color
private static UInt32 Alphablend(UInt32 dest, UInt32 source, Byte nAlpha, Byte nAlphaFinal)
{
if (0 == nAlpha)
return dest;
if (255 == nAlpha)
return source;
Byte nInvAlpha = (Byte)(~nAlpha);
Byte nSrcRed = (Byte)((source & 0xff0000) >> 16);
Byte nSrcGreen = (Byte)((source & 0xff00) >> 8);
Byte nSrcBlue = (Byte)((source & 0xff));
Byte nDestRed = (Byte)((dest & 0xff0000) >> 16);
Byte nDestGreen = (Byte)((dest & 0xff00) >> 8);
Byte nDestBlue = (Byte)(dest & 0xff);
Byte nRed = (Byte)((nSrcRed * nAlpha + nDestRed * nInvAlpha) >> 8);
Byte nGreen = (Byte)((nSrcGreen * nAlpha + nDestGreen * nInvAlpha) >> 8);
Byte nBlue = (Byte)((nSrcBlue * nAlpha + nDestBlue * nInvAlpha) >> 8);
return (UInt32)(nAlphaFinal << 24 | nRed << 16 | nGreen << 8 | nBlue);
}
///
/// Performs Alphablend
///
/// is destination color in ARGB
/// is source color in ARGB
/// destination color
private static UInt32 PreMultipliedAlphablend(UInt32 dest, UInt32 source)
{
Byte Alpha = (Byte)((source & 0xff000000) >> 24);
Byte nInvAlpha = (Byte)(255 - Alpha);
Byte nSrcRed = (Byte)((source & 0xff0000) >> 16);
Byte nSrcGreen = (Byte)((source & 0xff00) >> 8);
Byte nSrcBlue = (Byte)((source & 0xff));
Byte nDestRed = (Byte)((dest & 0xff0000) >> 16);
Byte nDestGreen = (Byte)((dest & 0xff00) >> 8);
Byte nDestBlue = (Byte)(dest & 0xff);
Byte nRed = (Byte)(nSrcRed + ((nDestRed * nInvAlpha) >> 8));
Byte nGreen = (Byte)(nSrcGreen + ((nDestGreen * nInvAlpha) >> 8));
Byte nBlue = (Byte)(nSrcBlue + ((nDestBlue * nInvAlpha) >> 8));
return (UInt32)(0xff << 24 | nRed << 16 | nGreen << 8 | nBlue);
}
}
}