CnPack Forum


 
Subject: 请CNPACK专家帮忙,能在CnFont中增加描边字功能么?
天堂游子
新警察
Rank: 1



UID 47616
Digest Posts 0
Credits 20
Posts 7
点点分 20
Reading Access 10
Registered 2010-5-4
Status Offline
Post at 2010-5-6 13:41  Profile | Blog | P.M. 
请CNPACK专家帮忙,能在CnFont中增加描边字功能么?

请CNPACK专家帮忙,能在CnFont中增加描边字功能么?

本人想做一个类似于 卡拉OK 字幕,需要在视频前显示文字,为提高文字清晰度,想要给所显示文字加描边框。

[ 本帖最后由 天堂游子 于 2010-5-6 13:48 编辑 ]


Image Attachment: [描边字样本] 未标题-1.jpg (2010-5-6 13:48, 38.74 K)

Top
天堂游子
新警察
Rank: 1



UID 47616
Digest Posts 0
Credits 20
Posts 7
点点分 20
Reading Access 10
Registered 2010-5-4
Status Offline
Post at 2010-5-6 14:02  Profile | Blog | P.M. 
这是我写的BCB描边字笨办法,效率不高,没有利用cnFont字体类的功能。


void __fastcall TForm2::Button1Click(TObject *Sender)
{
  int nPosX,nPosY,i,j,k,nFontBorderWidth;
  TColor crFontBorderColor,crFontColor;
  AnsiString sRollMessage;
  crFontBorderColor=clRed;
  crFontColor=clYellow;
  TCanvas   *lpCvs=PaintBoxRollMessage->Canvas;
  nFontBorderWidth=4;
  sRollMessage="这是传说中的描边字";
  nPosX=5+nFontBorderWidth;
  nPosY=5+nFontBorderWidth;
  SetBkMode(lpCvs->Handle,TRANSPARENT);
  lpCvs->Font->Color = crFontBorderColor;   //文字边框色。
  for( i=0; i<=nFontBorderWidth; i++ )
  {
  j=RoundTo(sqrt( nFontBorderWidth*nFontBorderWidth - i*i ),0);
  for( k=0; k<=j; k++ )
  {
    lpCvs->TextOutA(nPosX+i,nPosY+k,sRollMessage);
    lpCvs->TextOutA(nPosX-i,nPosY+k,sRollMessage);
    lpCvs->TextOutA(nPosX+i,nPosY-k,sRollMessage);
    lpCvs->TextOutA(nPosX-i,nPosY-k,sRollMessage);
  }
  }
  lpCvs->Font->Color = crFontColor;   //文字色。
  lpCvs->TextOutA(nPosX,nPosY,sRollMessage);
  //lpCvs->TextOutA(nPosX,nPosY,sRollMessage);
  //lpCvs->TextOutA(nPosX,nPosY,sRollMessage);
}


请专家指点能否利用阴影参数做一下改动和程序编写,增加描边功能。(如设置 阴影偏量y=-20时,则阴影偏量x为描边宽度,阴影颜色为描边色,如何在cnPack包中修改。
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2010-5-6 16:45  Profile | Site | Blog | P.M. 
你可以试试修改 CnAAFont.pas 中的 TCnAAFontEx.TextOut 方法,字体绘制的主要处理都在里面了。
需要注意的是,因为 AAFont 要支持半透明等效果,字体绘制不是直接在画布上输出,而是先绘制到蒙板Mask,最后再Blend输出的。




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
天堂游子
新警察
Rank: 1



UID 47616
Digest Posts 0
Credits 20
Posts 7
点点分 20
Reading Access 10
Registered 2010-5-4
Status Offline
Post at 2010-5-10 12:24  Profile | Blog | P.M. 
谢谢专家的指点,已修改CnAAFont.pas 代码

//增强平滑文本输出
procedure TCnAAFontEx.TextOut(x, y: Integer; s: string);
var
  TextPoint, ShadowPoint: TPoint;
  OldBrushStyle: TBrushStyle;
  ShadowMask: TCnAAMask;
  LogFont: TLogFont;
  TempFont: HFONT;
  SaveFont: TFont;

  // 是否为描边字(设置阴影偏移量为Y=20时,X为描边宽度) 2010.05.10 By WYH
  IsBorder: Boolean;
  BorderWidth ,i,j :Integer ; //描边宽度

begin
  if (Canvas = nil) or (s = '') then
    Exit;
  TempFont := 0;
  SaveFont := nil;
  try
    if Effect.Angle <> 0 then
    begin
      SaveFont := TFont.Create;
      SaveFont.Assign(Canvas.Font);
      GetObject(Canvas.Font.Handle, SizeOf(TLogFont), @LogFont);
      LogFont.lfEscapement := Effect.Angle * 10;
      TempFont := CreateFontIndirect(LogFont);
      Canvas.Font.Handle := TempFont;
    end;
    if Effect.Shadow.Enabled then         //阴影计算
    begin
      TextPoint := GetTextPoint;
      ShadowPoint := GetShadowPoint;

      //添加判断描边字参数判断 2010.05.10 WYH
      IsBorder := false;
      BorderWidth :=0;
      if ShadowPoint.y = 20 then
      begin
        if ShadowPoint.x > 0 then
        begin
          IsBorder :=true;
          BorderWidth :=ShadowPoint.x;
        end;
      end;

      TextPoint.x := TextPoint.x + x;
      TextPoint.y := TextPoint.y + y;
      ShadowPoint.x := ShadowPoint.x + x;
      ShadowPoint.y := ShadowPoint.y + y;
    end
    else
    begin
      TextPoint := Point(x, y);
    end;
    Mask.DrawMask(s);                     //创建字体蒙板
    if Effect.Outline then
      Mask.Outline;
    if Effect.Spray > 0 then
      Mask.Spray(Effect.Spray);
    if Effect.HorzMirror then
      Mask.HorzMirror;
    if Effect.VertMirror then
      Mask.VertMirror;
    OldBrushStyle := Canvas.Brush.Style;
    if Effect.Shadow.Enabled then         //阴影处理
    begin
      ShadowMask := TCnAAMask.Create(Self);
      ShadowMask.Assign(Mask);            //阴影蒙板

      if Effect.Shadow.Blur > 0 then
        ShadowMask.Blur(Effect.Shadow.Blur); //阴影模糊

      // 判断是否是描边字
      if IsBorder then
      begin
        for i := 0 to BorderWidth do
        begin
           j := Round( sqrt ( BorderWidth*BorderWidth - i*i ));
             Blend.Blend(TextPoint.x + i, TextPoint.y +j, Effect.Shadow.Color,
                         Effect.Shadow.Alpha * Effect.Alpha div 100, ShadowMask);
             Blend.Blend(TextPoint.x + i, TextPoint.y -j, Effect.Shadow.Color,
                         Effect.Shadow.Alpha * Effect.Alpha div 100, ShadowMask);
             Blend.Blend(TextPoint.x - i, TextPoint.y +j, Effect.Shadow.Color,
                         Effect.Shadow.Alpha * Effect.Alpha div 100, ShadowMask);
             Blend.Blend(TextPoint.x - i, TextPoint.y -j, Effect.Shadow.Color,
                         Effect.Shadow.Alpha * Effect.Alpha div 100, ShadowMask);
        end;
      end
      else
      begin
        Blend.Blend(ShadowPoint.x, ShadowPoint.y, Effect.Shadow.Color,
             Effect.Shadow.Alpha * Effect.Alpha div 100, ShadowMask);
      end;
      
      ShadowMask.Free;
      Canvas.Brush.Style := bsClear;      //透明
    end;
    if Effect.Blur > 0 then               //文本模糊
      Mask.Blur(Effect.Blur);
    if Effect.Texture.Enabled and Assigned(Effect.Texture.Picture.Graphic) and
      not Effect.Texture.Picture.Graphic.Empty then
    begin
      CreateForeBmp;                      //创建字体纹理图
      if Effect.Noise > 0 then
        AddNoise(Effect.Noise);
      Blend.BlendEx(TextPoint.x, TextPoint.y, Effect.Alpha, Mask);
    end
    else if Effect.Gradual.Enabled then
    begin                                 //创建渐变色前景图
      CreateGradual;
      if Effect.Noise > 0 then
        AddNoise(Effect.Noise);
      Blend.BlendEx(TextPoint.x, TextPoint.y, Effect.Alpha, Mask);
    end
    else
    begin                                 //混合输出
      if Effect.Noise > 0 then
      begin
        CreateNoiseBmp;
        Blend.BlendEx(TextPoint.x, TextPoint.y, Effect.Alpha, Mask);
      end
      else
        Blend.Blend(TextPoint.x, TextPoint.y, Canvas.Font.Color, Effect.Alpha, Mask);
    end;
    if Effect.Shadow.Enabled then
      Canvas.Brush.Style := OldBrushStyle;
  finally
    if Effect.Angle <> 0 then
    begin
      Canvas.Font.Assign(SaveFont);
      SaveFont.Free;
      DeleteObject(TempFont);
    end;
  end;
end;


效果如下图


Image Attachment: 未标题-2.jpg (2010-5-10 12:24, 67.89 K)

Top
天堂游子
新警察
Rank: 1



UID 47616
Digest Posts 0
Credits 20
Posts 7
点点分 20
Reading Access 10
Registered 2010-5-4
Status Offline
Post at 2010-5-10 12:27  Profile | Blog | P.M. 
但还存在一个问题,当描边宽度大于4时,会出现上描边被截现象(如上图第二例子),主要原因是原字符串偏移量不够,但不知在哪里修改,再次请教!!!
Top
 




All times are GMT++8, the time now is 2022-1-25 00:41

    本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.0.0  © 2001-2006 Comsenz Inc.
Processed in 0.009670 second(s), 9 queries , Gzip enabled

Clear Cookies - Contact Us - CnPack Website - Archiver - WAP