📄 aafont.pas
字号:
end;
end;
end;
//对蒙板图进行垂直镜象处理
procedure TAAMask.VertMirror;
var
pSrc, pDst, pBuf: PByteArray;
i: Integer;
begin
GetMem(pBuf, BytesLineMask);
try
for i := 0 to FHeight div 2 - 1 do
begin
pSrc := ScanLine(i);
pDst := ScanLine(FHeight - 1 - i);
CopyMemory(pBuf, pSrc, BytesLineMask);
CopyMemory(pSrc, pDst, BytesLineMask);
CopyMemory(pDst, pBuf, BytesLineMask);
end;
finally
FreeMem(pBuf);
end;
end;
//象素地址
function TAAMask.PixelAddr(x, y: Integer): Pointer;
begin
if (x < 0) or (x > Width - 1) or (y < 0) or (y > Height - 1) then
raise EInvalidPixel.Create('Invalid pixel!')
else
Result := Pointer(Integer(FpMaskBuff) + (Height - 1 + y) * BytesLineMask + x);
end;
//象素
function TAAMask.Pixel(x, y: Integer): Byte;
begin
if (x < 0) or (x > Width - 1) or (y < 0) or (y > Height - 1) then
raise EInvalidPixel.Create('Invalid pixel!')
else
Result := PByteArray(Integer(FpMaskBuff) + (Height - 1 + y) * BytesLineMask)[x];
end;
//扫描线地址
function TAAMask.ScanLine(Line: Integer): Pointer;
begin
if (Line < 0) or (Line > Height - 1) then
raise EInvalidLine.Create('Invalid line!')
else
Result := Pointer(Integer(FpMaskBuff) + (Height - 1 - Line) * BytesLineMask);
end;
function TAAMask.ScanLine(Line: Integer; pAData: PByteArray): PByteArray;
begin
Result := PByteArray(Integer(pAData) + (Height - 1 - Line) * BytesLineMask);
end;
//设置精度
procedure TAAMask.SetQuality(const Value: TAAQuality);
begin
FQuality := Value;
case FQuality of
aqHigh: Scale := 4;
aqNormal: Scale := 3;
aqLow: Scale := 2;
aqNone: Scale := 1;
else
Scale := 1;
end;
end;
function GetRotateSize(Size: TSize; Angle: Double; var StartPoint: TPoint): TSize;
var
p1, p2, p3, p4: TPoint;
cAngle, sAngle: Double;
wCos, hCos, wSin, hSin: Double;
SrcW2, SrcH2: Double;
Rect: TRect;
begin
sAngle := Sin(-Angle);
cAngle := Cos(-Angle);
// 计算目标顶点位置
SrcW2 := Size.cx / 2;
SrcH2 := Size.cy / 2;
wCos := SrcW2 * cAngle;
hCos := SrcH2 * cAngle;
wSin := SrcW2 * sAngle;
hSin := SrcH2 * sAngle;
p1.x := Round(-wCos + hSin); // 左下
p1.y := Round(-wSin - hCos);
p2.x := Round(wCos + hSin); // 右下
p2.y := Round(wSin - hCos);
p3.x := Round(-wCos - hSin); // 左上
p3.y := Round(-wSin + hCos);
p4.x := Round(wCos - hSin); // 右上
p4.y := Round(wSin + hCos);
// 计算包含矩形
Rect.Left := MinIntValue([p1.x, p2.x, p3.x, p4.x]);
Rect.Right := MaxIntValue([p1.x, p2.x, p3.x, p4.x]);
Rect.Top := MinIntValue([p1.y, p2.y, p3.y, p4.y]);
Rect.Bottom := MaxIntValue([p1.y, p2.y, p3.y, p4.y]);
Result.cx := Rect.Right - Rect.Left;
Result.cy := Rect.Bottom - Rect.Top;
StartPoint.x := p1.x + Result.cx div 2;
StartPoint.y := p1.y + Result.cy div 2;
end;
//文本高、宽,旋转后起始位置
function TAAMask.TextExtentEx(s: string; var Point: TPoint): TSize;
var
LogFont: TLogFont;
TempFont, SaveFont: HFONT;
DC: HDC;
Beta: Double;
begin
Result.cx := 0;
Result.cy := 0;
if (AAFont = nil) or (AAFont.Canvas = nil) then
Exit;
DC := GetDC(0);
try
GetObject(AAFont.Canvas.Font.Handle, SizeOf(TLogFont), @LogFont);
with LogFont do
begin
lfHeight := lfHeight * Scale;
lfWidth := lfWidth * Scale;
Beta := lfEscapement * Pi / 1800;
end;
TempFont := CreateFontIndirect(LogFont);
try
SaveFont := SelectObject(DC, TempFont);
GetTextExtentPoint32(DC, PChar(s), Length(s), Result);
Result.cx := (Result.cx + Scale - 1) div Scale;
Result.cy := (Result.cy + Scale - 1) div Scale;
if (fsItalic in AAFont.Canvas.Font.Style) and (Length(s) > 0) then
Result.cx := Result.cx + Round(Result.cx / Length(s) * ItalicAdjust);
SelectObject(DC, SaveFont);
if Beta <> 0 then
begin
Result := GetRotateSize(Result, Beta, Point);
end;
finally
DeleteObject(TempFont);
end;
finally
ReleaseDC(0, DC);
end;
end;
//文本高、宽
function TAAMask.TextExtent(s: string): TSize;
var
Point: TPoint;
begin
Result := TextExtentEx(s, Point);
end;
//文本高度
function TAAMask.TextHeight(s: string): Integer;
begin
Result := TextExtent(s).cy;
end;
//文本宽度
function TAAMask.TextWidth(s: string): Integer;
begin
Result := TextExtent(s).cx;
end;
{ TAABlend }
//--------------------------------------------------------//
//前景背景蒙板混合类 //
//--------------------------------------------------------//
//初始化
constructor TAABlend.Create(AOwner: TAAFont);
begin
AAFont := AOwner;
FForeBmp := TBitmap.Create;
FForeBmp.PixelFormat := pf24bit;
RGBBmp := TBitmap.Create;
RGBBmp.PixelFormat := pf24bit;
end;
//释放
destructor TAABlend.Destroy;
begin
ForeBmp.Free;
RGBBmp.Free;
inherited;
end;
//赋值
procedure TAABlend.Assign(Source: TPersistent);
begin
if Source is TAABlend then
ForeBmp.Assign(TAABlend(Source).ForeBmp)
else
inherited Assign(Source);
end;
//文本按前景色与背景混合
procedure TAABlend.Blend(x, y: Integer; AColor: TColor; Alpha: TAlpha;
Mask: TAAMask);
var
r, b, g: Byte;
AAlpha: DWORD;
pMask: PByteArray;
pRGB: PRGBArray;
Weight: Byte;
i, j: Integer;
Color: TColor;
begin
if (AAFont = nil) or (AAFont.Canvas = nil) then
Exit;
RGBBmp.Width := Mask.Width;
RGBBmp.Height := Mask.Height;
Color := ColorToRGB(AColor); //实际前景色
r := GetRValue(Color); //色彩分量
g := GetGValue(Color);
b := GetBValue(Color);
AAlpha := Alpha * $100 div 100; //透明度
RGBBmp.Canvas.Brush.Assign(AAFont.Canvas.Brush);
if RGBBmp.Canvas.Brush.Style <> bsSolid then
Bitblt(RGBBmp.Canvas.Handle, 0, 0, RGBBmp.Width, RGBBmp.Height,
AAFont.Canvas.Handle, x, y, SRCCOPY) //透明
else
FillRect(RGBBmp.Canvas.Handle, Bounds(0, 0, RGBBmp.Width, RGBBmp.Height), 0);
for j := 0 to RGBBmp.Height - 1 do
begin
pMask := Mask.ScanLine(j);
pRGB := RGBBmp.ScanLine[j];
for i := 0 to RGBBmp.Width - 1 do
begin
Weight := pMask^[i] * AAlpha shr 8; //混合系数
if Weight <> 0 then
begin
if Weight = 255 then
begin //前景色
pRGB^[i].rgbtBlue := b;
pRGB^[i].rgbtGreen := g;
pRGB^[i].rgbtRed := r;
end
else
begin //混合
Inc(pRGB^[i].rgbtBlue, Weight * (b - pRGB^[i].rgbtBlue) shr 8);
Inc(pRGB^[i].rgbtGreen, Weight * (g - pRGB^[i].rgbtGreen) shr 8);
Inc(pRGB^[i].rgbtRed, Weight * (r - pRGB^[i].rgbtRed) shr 8);
end;
end;
end;
end;
Bitblt(AAFont.Canvas.Handle, x, y, RGBBmp.Width, RGBBmp.Height,
RGBBmp.Canvas.Handle, 0, 0, SRCCOPY); //输出
end;
//文本按纹理与背景混合
procedure TAABlend.BlendEx(x, y: Integer; Alpha: TAlpha; Mask: TAAMask);
var
AAlpha: WORD;
pMask: PByteArray;
pRGB: PRGBArray;
pFore: PRGBArray;
Weight: Byte;
i, j: Integer;
begin
if (AAFont = nil) or (AAFont.Canvas = nil) then
Exit;
if (ForeBmp.Width <> Mask.Width) or (ForeBmp.Height <> Mask.Height)
or (ForeBmp.PixelFormat <> pf24bit) then
begin //错误的纹理图
raise EInvalidForeBmp.Create('Invalid foreground bitmap!');
Exit;
end;
RGBBmp.Width := Mask.Width;
RGBBmp.Height := Mask.Height;
AAlpha := Alpha * $100 div 100; //透明度
RGBBmp.Canvas.Brush.Assign(AAFont.Canvas.Brush);
if RGBBmp.Canvas.Brush.Style <> bsSolid then
Bitblt(RGBBmp.Canvas.Handle, 0, 0, RGBBmp.Width, RGBBmp.Height,
AAFont.Canvas.Handle, x, y, SRCCOPY) //透明
else
FillRect(RGBBmp.Canvas.Handle, Bounds(0, 0, RGBBmp.Width, RGBBmp.Height), 0);
for j := 0 to RGBBmp.Height - 1 do
begin
pMask := Mask.ScanLine(j);
pRGB := RGBBmp.ScanLine[j];
pFore := ForeBmp.ScanLine[j];
for i := 0 to RGBBmp.Width - 1 do
begin
Weight := pMask^[i] * AAlpha shr 8; //混合系数
if Weight = 255 then
begin
pRGB^[i].rgbtBlue := pFore^[i].rgbtBlue;
pRGB^[i].rgbtGreen := pFore^[i].rgbtGreen;
pRGB^[i].rgbtRed := pFore^[i].rgbtRed;
end
else if Weight <> 0 then //混合
begin
Inc(pRGB^[i].rgbtBlue, Weight * (pFore^[i].rgbtBlue - pRGB^[i].rgbtBlue) shr
8);
Inc(pRGB^[i].rgbtGreen, Weight * (pFore^[i].rgbtGreen - pRGB^[i].rgbtGreen) shr
8);
Inc(pRGB^[i].rgbtRed, Weight * (pFore^[i].rgbtRed - pRGB^[i].rgbtRed) shr 8);
end;
end;
end;
Bitblt(AAFont.Canvas.Handle, x, y, RGBBmp.Width, RGBBmp.Height,
RGBBmp.Canvas.Handle, 0, 0, SRCCOPY); //输出
end;
//设置前景纹理图
procedure TAABlend.SetForeBmp(const Value: TBitmap);
begin
FForeBmp.Assign(Value);
end;
{ TAAFont }
//--------------------------------------------------------//
//平滑字体类 //
//--------------------------------------------------------//
//初始化
constructor TAAFont.Create(ACanvas: TCanvas);
begin
FCanvas := ACanvas;
Mask := TAAMask.Create(Self);
Blend := TAABlend.Create(Self);
end;
//释放
destructor TAAFont.Destroy;
begin
Mask.Free;
Blend.Free;
inherited;
end;
//取显示精度
function TAAFont.GetQuality: TAAQuality;
begin
Result := Mask.Quality;
end;
//设置显示精度
procedure TAAFont.SetQuality(const Value: TAAQuality);
begin
Mask.Quality := Value;
end;
//文本高、宽
function TAAFont.TextExtent(s: string): TSize;
begin
Result := Mask.TextExtent(s);
end;
//文本高度
function TAAFont.TextHeight(s: string): Integer;
begin
Result := TextExtent(s).cy;
end;
//文本宽度
function TAAFont.TextWidth(s: string): Integer;
begin
Result := TextExtent(s).cx;
end;
//平滑文本输出
procedure TAAFont.TextOut(x, y: Integer; s: string; Alpha: TAlpha;
Blur: TBlurStrength);
begin
if (Canvas = nil) or (s = '') then
Exit;
Mask.DrawMask(s); //创建字体蒙板
if Blur > 0 then
Mask.Blur(Blur); //模糊
Blend.Blend(x, y, Canvas.Font.Color, Alpha, Mask); //与前景色混合
end;
{ TAAFontEx }
//---------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -