551 lines
18 KiB
C#
551 lines
18 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Drawing.Imaging;
|
|
|
|
namespace TextDesignerCSLibrary
|
|
{
|
|
public class BmpOutlineText
|
|
{
|
|
public BmpOutlineText()
|
|
{
|
|
m_pbmpResult = null;
|
|
m_pbmpMask = null;
|
|
m_pbmpShadow = null;
|
|
m_clrBkgd = Color.FromArgb(0, 255, 0);
|
|
m_clrOutline = Color.FromArgb(255,0,0);
|
|
m_clrText = Color.FromArgb(0,0,255);
|
|
|
|
m_PngOutlineText = new PngOutlineText();
|
|
m_PngShadow = new PngOutlineText();
|
|
}
|
|
|
|
public Bitmap Render(
|
|
uint nTextX,
|
|
uint nTextY,
|
|
Bitmap pbmpText,
|
|
uint nOutlineX,
|
|
uint nOutlineY,
|
|
Bitmap pbmpOutline)
|
|
{
|
|
if(pbmpText==null)
|
|
return null;
|
|
if(pbmpOutline==null)
|
|
return null;
|
|
|
|
m_pbmpResult = new Bitmap((int)(pbmpOutline.Width+nOutlineX), (int)(pbmpOutline.Height+nOutlineY), PixelFormat.Format32bppArgb);
|
|
|
|
|
|
|
|
Bitmap png = m_PngOutlineText.GetPngImage();
|
|
BitmapData bitmapDataResult = new BitmapData();
|
|
BitmapData bitmapDataText = new BitmapData();
|
|
BitmapData bitmapDataOutline = new BitmapData();
|
|
BitmapData bitmapDataPng = new BitmapData();
|
|
Rectangle rectResult = new Rectangle(0, 0, m_pbmpResult.Width, m_pbmpResult.Height );
|
|
Rectangle rectText = new Rectangle(0, 0, pbmpText.Width, pbmpText.Height );
|
|
Rectangle rectOutline = new Rectangle(0, 0, pbmpOutline.Width, pbmpOutline.Height );
|
|
Rectangle rectPng = new Rectangle(0, 0, m_pbmpMask.Width, m_pbmpMask.Height );
|
|
|
|
m_pbmpResult.LockBits(
|
|
rectResult,
|
|
ImageLockMode.WriteOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapDataResult );
|
|
pbmpText.LockBits(
|
|
rectText,
|
|
ImageLockMode.ReadOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapDataText );
|
|
pbmpOutline.LockBits(
|
|
rectOutline,
|
|
ImageLockMode.ReadOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapDataOutline );
|
|
png.LockBits(
|
|
rectPng,
|
|
ImageLockMode.ReadOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapDataPng );
|
|
|
|
unsafe
|
|
{
|
|
uint* pixelsResult = (uint*)bitmapDataResult.Scan0;
|
|
uint* pixelsText = (uint*)bitmapDataText.Scan0;
|
|
uint* pixelsOutline = (uint*)bitmapDataOutline.Scan0;
|
|
uint* pixelsPng = (uint*)bitmapDataPng.Scan0;
|
|
|
|
if( pixelsResult==null || pixelsText==null || pixelsOutline==null || pixelsPng==null )
|
|
return null;
|
|
|
|
uint col = 0;
|
|
int strideResult = bitmapDataResult.Stride >> 2;
|
|
int strideOutline = bitmapDataOutline.Stride >> 2;
|
|
int strideText = bitmapDataText.Stride >> 2;
|
|
int stridePng = bitmapDataPng.Stride >> 2;
|
|
|
|
for(uint row = 0; row < bitmapDataResult.Height; ++row)
|
|
{
|
|
for(col = 0; col < bitmapDataResult.Width; ++col)
|
|
{
|
|
uint indexResult = (uint)(row * strideResult + col);
|
|
uint indexText = (uint)((row-nTextY)* strideText + (col-nTextX));
|
|
uint indexOutline = (uint)((row-nOutlineY) * strideOutline + (col-nOutlineX));
|
|
uint indexPng = (uint)(row * stridePng + col);
|
|
byte red = (byte)((pixelsPng[indexPng] & 0xff0000) >> 16);
|
|
byte blue = (byte)(pixelsPng[indexPng] & 0xff);
|
|
|
|
if(red>0&&blue>0)
|
|
{
|
|
uint nOutlineColor = pixelsOutline[indexOutline];
|
|
byte aOutline = (byte)((nOutlineColor & 0xff000000) >> 24);
|
|
byte rOutline = (byte)((nOutlineColor & 0xff0000) >> 16);
|
|
byte gOutline = (byte)((nOutlineColor & 0xff00) >> 8);
|
|
byte bOutline = (byte)(nOutlineColor & 0xff);
|
|
|
|
if (aOutline > 0)
|
|
{
|
|
aOutline = (byte)((red * aOutline) >> 8);
|
|
rOutline = (byte)((red * rOutline) >> 8);
|
|
gOutline = (byte)((red * gOutline) >> 8);
|
|
bOutline = (byte)((red * bOutline) >> 8);
|
|
}
|
|
else
|
|
{
|
|
rOutline = 0;
|
|
gOutline = 0;
|
|
bOutline = 0;
|
|
}
|
|
|
|
uint nTextColor = pixelsText[indexText];
|
|
byte aText = (byte)((nTextColor & 0xff000000) >> 24);
|
|
byte rText = (byte)((nTextColor & 0xff0000) >> 16);
|
|
byte gText = (byte)((nTextColor & 0xff00) >> 8);
|
|
byte bText = (byte)(nTextColor & 0xff);
|
|
|
|
if (aText > 0)
|
|
{
|
|
aText = (byte)((blue * aText) >> 8);
|
|
rText = (byte)((blue * rText) >> 8);
|
|
gText = (byte)((blue * gText) >> 8);
|
|
bText = (byte)((blue * bText) >> 8);
|
|
}
|
|
else
|
|
{
|
|
rText = 0;
|
|
gText = 0;
|
|
bText = 0;
|
|
}
|
|
|
|
if (aText > 0 && aOutline > 0)
|
|
{
|
|
pixelsResult[indexResult] = (uint)((0xff << 24) | (Clamp((uint)(rOutline + rText)) << 16) | (Clamp((uint)(gOutline + gText)) << 8) | Clamp((uint)(bOutline + bText)));
|
|
}
|
|
else if (aOutline > 0)
|
|
pixelsResult[indexResult] = (uint)((aOutline << 24) | (Clamp((uint)(rOutline + rText)) << 16) | (Clamp((uint)(gOutline + gText)) << 8) | Clamp((uint)(bOutline + bText)));
|
|
else if (aText > 0)
|
|
pixelsResult[indexResult] = (uint)((aText << 24) | (Clamp((uint)(rOutline + rText)) << 16) | (Clamp((uint)(gOutline + gText)) << 8) | Clamp((uint)(bOutline + bText)));
|
|
else
|
|
pixelsResult[indexResult] = 0;
|
|
}
|
|
else if(red>0)
|
|
{
|
|
uint nOutlineColor = pixelsOutline[indexOutline];
|
|
byte a = (byte)((nOutlineColor & 0xff000000) >> 24);
|
|
byte r = (byte)((nOutlineColor & 0xff0000) >> 16);
|
|
byte g = (byte)((nOutlineColor & 0xff00) >> 8);
|
|
byte b = (byte)(nOutlineColor & 0xff);
|
|
|
|
if (a > 0)
|
|
pixelsResult[indexResult] = (uint)((red << 24) | (r << 16) | (g << 8) | b);
|
|
else
|
|
pixelsResult[indexResult] = 0;
|
|
}
|
|
else if(blue>0)
|
|
{
|
|
uint nTextColor = pixelsText[indexText];
|
|
byte a = (byte)((nTextColor & 0xff000000) >> 24);
|
|
byte r = (byte)((nTextColor & 0xff0000) >> 16);
|
|
byte g = (byte)((nTextColor & 0xff00) >> 8);
|
|
byte b = (byte)(nTextColor & 0xff);
|
|
|
|
if (a > 0)
|
|
pixelsResult[indexResult] = (uint)((blue << 24) | (r << 16) | (g << 8) | b);
|
|
else
|
|
pixelsResult[indexResult] = 0;
|
|
}
|
|
else
|
|
{
|
|
pixelsResult[indexResult] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
png.UnlockBits(
|
|
bitmapDataPng );
|
|
pbmpOutline.UnlockBits(
|
|
bitmapDataOutline );
|
|
pbmpText.UnlockBits(
|
|
bitmapDataText );
|
|
m_pbmpResult.UnlockBits(
|
|
bitmapDataResult );
|
|
|
|
return m_pbmpResult;
|
|
}
|
|
|
|
public bool DrawString(
|
|
Graphics pGraphics,
|
|
FontFamily pFontFamily,
|
|
FontStyle fontStyle,
|
|
int nfontSize,
|
|
string pszText,
|
|
Point ptDraw,
|
|
StringFormat pStrFormat,
|
|
int nThickness,
|
|
int nWidth,
|
|
int nHeight,
|
|
bool bGlow,
|
|
byte nGlowAlpha)
|
|
{
|
|
if (bGlow)
|
|
m_PngOutlineText.TextGlow(m_clrText, Color.FromArgb(nGlowAlpha, m_clrOutline.R, m_clrOutline.G, m_clrOutline.B), nThickness);
|
|
else
|
|
m_PngOutlineText.TextOutline(m_clrText, m_clrOutline, nThickness);
|
|
m_PngOutlineText.EnableReflection(false);
|
|
m_PngOutlineText.EnableShadow(false);
|
|
|
|
m_pbmpMask = new Bitmap(nWidth, nHeight, PixelFormat.Format32bppArgb);
|
|
|
|
|
|
Graphics graph = Graphics.FromImage(m_pbmpMask);
|
|
SolidBrush brush = new SolidBrush(m_clrBkgd);
|
|
graph.FillRectangle(brush, 0, 0, m_pbmpMask.Width, m_pbmpMask.Height);
|
|
|
|
m_PngOutlineText.SetPngImage(m_pbmpMask);
|
|
|
|
m_PngOutlineText.DrawString(
|
|
pGraphics,
|
|
pFontFamily,
|
|
fontStyle,
|
|
nfontSize,
|
|
pszText,
|
|
ptDraw,
|
|
pStrFormat);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
public bool DrawString(
|
|
Graphics pGraphics,
|
|
FontFamily pFontFamily,
|
|
FontStyle fontStyle,
|
|
int nfontSize,
|
|
string pszText,
|
|
Rectangle rtDraw,
|
|
StringFormat pStrFormat,
|
|
int nThickness,
|
|
int nWidth,
|
|
int nHeight,
|
|
bool bGlow,
|
|
byte nGlowAlpha)
|
|
{
|
|
if (bGlow)
|
|
m_PngOutlineText.TextGlow(m_clrText, Color.FromArgb(nGlowAlpha, m_clrOutline.R, m_clrOutline.G, m_clrOutline.B), nThickness);
|
|
else
|
|
m_PngOutlineText.TextOutline(m_clrText, m_clrOutline, nThickness);
|
|
m_PngOutlineText.EnableReflection(false);
|
|
m_PngOutlineText.EnableShadow(false);
|
|
|
|
m_pbmpMask = new Bitmap(nWidth, nHeight, PixelFormat.Format32bppArgb);
|
|
|
|
|
|
Graphics graph = Graphics.FromImage(m_pbmpMask);
|
|
SolidBrush brush = new SolidBrush(m_clrBkgd);
|
|
graph.FillRectangle(brush, 0, 0, m_pbmpMask.Width, m_pbmpMask.Height);
|
|
|
|
m_PngOutlineText.SetPngImage(m_pbmpMask);
|
|
|
|
m_PngOutlineText.DrawString(
|
|
pGraphics,
|
|
pFontFamily,
|
|
fontStyle,
|
|
nfontSize,
|
|
pszText,
|
|
rtDraw,
|
|
pStrFormat);
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool DrawString(
|
|
Graphics pGraphics,
|
|
FontFamily pFontFamily,
|
|
FontStyle fontStyle,
|
|
int nfontSize,
|
|
string pszText,
|
|
Point ptDraw,
|
|
StringFormat pStrFormat,
|
|
int nThickness,
|
|
int nWidth,
|
|
int nHeight,
|
|
bool bGlow,
|
|
byte nGlowAlpha,
|
|
bool bShadow,
|
|
Color clrShadow,
|
|
int nShadowOffsetX,
|
|
int nShadowOffsetY)
|
|
{
|
|
if (bGlow)
|
|
m_PngOutlineText.TextGlow(m_clrText, Color.FromArgb(nGlowAlpha, m_clrOutline.R, m_clrOutline.G, m_clrOutline.B), nThickness);
|
|
else
|
|
m_PngOutlineText.TextOutline(m_clrText, m_clrOutline, nThickness);
|
|
m_PngOutlineText.EnableReflection(false);
|
|
m_PngOutlineText.EnableShadow(false);
|
|
|
|
if(bShadow)
|
|
{
|
|
m_PngShadow.SetNullTextEffect();
|
|
m_PngShadow.EnableShadow(true);
|
|
m_PngShadow.Shadow(clrShadow, nThickness, new Point(nShadowOffsetX, nShadowOffsetY));
|
|
m_PngShadow.SetShadowBkgd(Color.FromArgb(0,0,0), nWidth, nHeight);
|
|
}
|
|
else
|
|
m_PngShadow.EnableShadow(false);
|
|
|
|
m_pbmpMask = new Bitmap(nWidth, nHeight, PixelFormat.Format32bppArgb);
|
|
|
|
|
|
using (Graphics graph = Graphics.FromImage(m_pbmpMask))
|
|
{
|
|
using (SolidBrush brush = new SolidBrush(m_clrBkgd))
|
|
{
|
|
graph.FillRectangle(brush, 0, 0, m_pbmpMask.Width, m_pbmpMask.Height);
|
|
}
|
|
}
|
|
m_PngOutlineText.SetPngImage(m_pbmpMask);
|
|
|
|
m_PngOutlineText.DrawString(
|
|
pGraphics,
|
|
pFontFamily,
|
|
fontStyle,
|
|
nfontSize,
|
|
pszText,
|
|
ptDraw,
|
|
pStrFormat);
|
|
|
|
if (bShadow)
|
|
{
|
|
m_pbmpShadow = new Bitmap(nWidth, nHeight, PixelFormat.Format32bppArgb);
|
|
|
|
m_PngShadow.SetPngImage(m_pbmpShadow);
|
|
|
|
m_PngShadow.DrawString(
|
|
pGraphics,
|
|
pFontFamily,
|
|
fontStyle,
|
|
nfontSize,
|
|
pszText,
|
|
ptDraw,
|
|
pStrFormat);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool DrawString(
|
|
Graphics pGraphics,
|
|
FontFamily pFontFamily,
|
|
FontStyle fontStyle,
|
|
int nfontSize,
|
|
string pszText,
|
|
Rectangle rtDraw,
|
|
StringFormat pStrFormat,
|
|
int nThickness,
|
|
int nWidth,
|
|
int nHeight,
|
|
bool bGlow,
|
|
byte nGlowAlpha,
|
|
bool bShadow,
|
|
Color clrShadow,
|
|
int nShadowOffsetX,
|
|
int nShadowOffsetY)
|
|
{
|
|
if (bGlow)
|
|
m_PngOutlineText.TextGlow(m_clrText, Color.FromArgb(nGlowAlpha, m_clrOutline.R, m_clrOutline.G, m_clrOutline.B), nThickness);
|
|
else
|
|
m_PngOutlineText.TextOutline(m_clrText, m_clrOutline, nThickness);
|
|
m_PngOutlineText.EnableReflection(false);
|
|
m_PngOutlineText.EnableShadow(false);
|
|
|
|
if (bShadow)
|
|
{
|
|
m_PngShadow.SetNullTextEffect();
|
|
m_PngShadow.EnableShadow(true);
|
|
m_PngShadow.Shadow(clrShadow, nThickness, new Point(nShadowOffsetX, nShadowOffsetY));
|
|
m_PngShadow.SetShadowBkgd(Color.FromArgb(0, 0, 0), nWidth, nHeight);
|
|
}
|
|
else
|
|
m_PngShadow.EnableShadow(false);
|
|
|
|
m_pbmpMask = new Bitmap(nWidth, nHeight, PixelFormat.Format32bppArgb);
|
|
|
|
using (Graphics graph = Graphics.FromImage(m_pbmpMask))
|
|
{
|
|
using (SolidBrush brush = new SolidBrush(m_clrBkgd))
|
|
{
|
|
graph.FillRectangle(brush, 0, 0, m_pbmpMask.Width, m_pbmpMask.Height);
|
|
}
|
|
}
|
|
m_PngOutlineText.SetPngImage(m_pbmpMask);
|
|
|
|
m_PngOutlineText.DrawString(
|
|
pGraphics,
|
|
pFontFamily,
|
|
fontStyle,
|
|
nfontSize,
|
|
pszText,
|
|
rtDraw,
|
|
pStrFormat);
|
|
|
|
if(bShadow)
|
|
{
|
|
m_pbmpShadow = new Bitmap(nWidth, nHeight, PixelFormat.Format32bppArgb);
|
|
|
|
m_PngShadow.SetPngImage(m_pbmpShadow);
|
|
|
|
m_PngShadow.DrawString(
|
|
pGraphics,
|
|
pFontFamily,
|
|
fontStyle,
|
|
nfontSize,
|
|
pszText,
|
|
rtDraw,
|
|
pStrFormat);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static bool Measure(
|
|
Bitmap png,
|
|
out uint nTextX, out uint nTextY, out uint nTextWidth, out uint nTextHeight,
|
|
out uint nOutlineX, out uint nOutlineY, out uint nOutlineWidth, out uint nOutlineHeight)
|
|
{
|
|
nTextX = nTextY = nTextWidth = nTextHeight = 0;
|
|
nOutlineX = nOutlineY = nOutlineWidth = nOutlineHeight = 0;
|
|
|
|
BitmapData bitmapData = new BitmapData();
|
|
Rectangle rect = new Rectangle(0, 0, png.Width, png.Height );
|
|
|
|
png.LockBits(
|
|
rect,
|
|
ImageLockMode.ReadOnly,
|
|
PixelFormat.Format32bppArgb,
|
|
bitmapData );
|
|
|
|
unsafe
|
|
{
|
|
uint* pixels = (uint*)bitmapData.Scan0;
|
|
|
|
if( pixels==null )
|
|
return false;
|
|
|
|
uint col = 0;
|
|
int stride = bitmapData.Stride >> 2;
|
|
nTextX = 50000;
|
|
nTextY = 50000;
|
|
nTextWidth = 0;
|
|
nTextHeight = 0;
|
|
|
|
nOutlineX = 50000;
|
|
nOutlineY = 50000;
|
|
nOutlineWidth = 0;
|
|
nOutlineHeight = 0;
|
|
for(uint row = 0; row < bitmapData.Height; ++row)
|
|
{
|
|
for(col = 0; col < bitmapData.Width; ++col)
|
|
{
|
|
uint index = (uint)(row * stride + col);
|
|
byte red = (byte)((pixels[index] & 0xff0000) >> 16);
|
|
byte blue = (byte)(pixels[index] & 0xff);
|
|
|
|
if(red>0)
|
|
{
|
|
if(col<nOutlineX)
|
|
nOutlineX = col;
|
|
if(row<nOutlineY)
|
|
nOutlineY = row;
|
|
if(col>nOutlineWidth)
|
|
nOutlineWidth = col;
|
|
if(row>nOutlineHeight)
|
|
nOutlineHeight = row;
|
|
}
|
|
if(blue>0)
|
|
{
|
|
if(col<nTextX)
|
|
nTextX = col;
|
|
if(row<nTextY)
|
|
nTextY = row;
|
|
if(col>nTextWidth)
|
|
nTextWidth = col;
|
|
if(row>nTextHeight)
|
|
nTextHeight = row;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
png.UnlockBits(bitmapData);
|
|
|
|
nTextWidth -= nTextX;
|
|
nTextHeight -= nTextY;
|
|
|
|
nOutlineWidth -= nOutlineX;
|
|
nOutlineHeight -= nOutlineY;
|
|
|
|
++nTextWidth;
|
|
++nTextHeight;
|
|
|
|
++nOutlineWidth;
|
|
++nOutlineHeight;
|
|
|
|
return true;
|
|
}
|
|
|
|
public Bitmap GetInternalMaskImage()
|
|
{
|
|
return m_pbmpMask;
|
|
}
|
|
|
|
public Bitmap GetResultImage()
|
|
{
|
|
return m_pbmpResult;
|
|
}
|
|
|
|
public Bitmap GetShadowImage()
|
|
{
|
|
return m_pbmpShadow;
|
|
}
|
|
|
|
private byte Clamp(uint val)
|
|
{
|
|
if(val>255)
|
|
return 255;
|
|
else
|
|
return (byte)(val);
|
|
}
|
|
|
|
private Bitmap m_pbmpResult;
|
|
private Bitmap m_pbmpMask;
|
|
private Bitmap m_pbmpShadow;
|
|
private Color m_clrBkgd;
|
|
private Color m_clrOutline;
|
|
private Color m_clrText;
|
|
private TextDesignerCSLibrary.PngOutlineText m_PngOutlineText;
|
|
private TextDesignerCSLibrary.PngOutlineText m_PngShadow;
|
|
|
|
}
|
|
}
|