[BlueLeaf1336]> PROGRAM>

フォントのアウトライン化

historyTOP

2005/12/28:作成

overviewTOP

「フォントのアウトライン化」ってどういう意味か説明できませんが、Illustratorの「アウトライン化」のイメージです。

コードTOP

無駄にクラスになってるんですが、GetMemory()FreeMemory() がメインです。それ以外はおまけ。

//=============================================================================
//  TFontOutLine
//=============================================================================

//-----------------------------------------------------------------------------
//  これやっとかないと array[0..0] of に [1] でアクセスできない
{$RANGECHECKS OFF}

//-----------------------------------------------------------------------------
type
    TPointsArray = array[0..0] of TPoint;
    PPointsArray = ^TPointsArray;
    TTypesArray = array[0..0] of Byte;
    PTypesArray = ^TTypesArray;

//-----------------------------------------------------------------------------
type
    TFontOutLine = class
    private
        FBitmap: TBitmap;
    private
        FText: string;
        FRect: TRect;
        procedure SetText(const Value: string);
    private
        FPtCount: Integer;
        FPoints: PPointsArray;
        FTypes: PTypesArray;
        procedure GetMemory();
        procedure FreeMemory();
    public
        constructor Create();
        destructor Destroy(); override;
    public
        procedure SetCanvas(Source: TCanvas);
        procedure SetFont(Source: TFont);
        procedure SetBrush(Source: TBrush);
        procedure SetPen(Source: TPen);
        property Text: string read FText write SetText;
        property Rect: TRect read FRect;
        property PtCount: Integer read FPtCount;
        property Points: PPointsArray read FPoints;
        property Types: PTypesArray read FTypes;
    end;

//-----------------------------------------------------------------------------
//  コンストラクタ
constructor TFontOutLine.Create();
begin
    inherited;
    FText := '';
    FPtCount := -1;
    FPoints := nil;
    FTypes := nil;
    FRect := Classes.Rect(0, 0, 0, 0);

    FBitmap := TBitmap.Create();
    FBitmap.PixelFormat := pf24bit;

    SetText(FText);
end;

//-----------------------------------------------------------------------------
//  デストラクタ
destructor TFontOutLine.Destroy();
begin
    FBitmap.Free;
    FreeMemory();
    inherited;
end;

//-----------------------------------------------------------------------------
//  メモリ確保
procedure TFontOutLine.GetMemory();
begin
    //-----------------------------------------------------
    //  パスを定義する点の個数取得
    FPtCount := GetPath(FBitmap.Canvas.Handle, FPoints^, FTypes^, 0);

    //-----------------------------------------------------
    //  個数分のメモリ確保
    GetMem(FPoints, SizeOf(TPoint) * FPtCount);
    GetMem(FTypes, SizeOf(Byte) * FPtCount);

    //-----------------------------------------------------
    //  点を取得
    GetPath(FBitmap.Canvas.Handle, FPoints^, FTypes^, FPtCount);
end;

//-----------------------------------------------------------------------------
//  メモリ開放
procedure TFontOutLine.FreeMemory();
begin
    if (FPtCount > 0) then
    begin
        FreeMem(FPoints);
        FreeMem(FTypes);
    end;
end;

//-----------------------------------------------------------------------------
//  内部キャンバスにフォントなどのプロパティをコピー
procedure TFontOutLine.SetCanvas(Source: TCanvas);
begin
    SetFont(Source.Font);
    SetBrush(Source.Brush);
    SetPen(Source.Pen);
end;

//-----------------------------------------------------------------------------
//  内部キャンバスにフォントのプロパティをコピー
procedure TFontOutLine.SetFont(Source: TFont);
begin
    FBitmap.Canvas.Font.Assign(Source);
    SetText(FText);
end;

//-----------------------------------------------------------------------------
//  内部キャンバスにブラシのプロパティをコピー
procedure TFontOutLine.SetBrush(Source: TBrush);
begin
    FBitmap.Canvas.Brush.Assign(Source);
    SetText(FText);
end;

//-----------------------------------------------------------------------------
//  内部キャンバスにペンのプロパティをコピー
procedure TFontOutLine.SetPen(Source: TPen);
begin
    FBitmap.Canvas.Pen.Assign(Source);
    SetText(FText);
end;

//-----------------------------------------------------------------------------
//  テキストを受け取ってアウトライン情報を作成
procedure TFontOutLine.SetText(const Value: string);
var
    DtFormat: Cardinal;
    DtParams: TDrawTextParams;
var
    OldMode: Integer;
begin
    FText := Value;

    //-----------------------------------------------------
    //  パラメータ準備
    FillChar(DtParams, SizeOf(DtParams), 0);
    DtParams.cbSize := SizeOf(DtParams);
    DtFormat := DT_LEFT or DT_TOP or DT_SINGLELINE or DT_CALCRECT;
    FRect := Classes.Rect(0, 0, 0, 0);

    //-----------------------------------------------------
    //  描画領域決定
    DrawTextEx(FBitmap.Canvas.Handle, PChar(FText), -1, FRect, DtFormat, @DtParams);
    FBitmap.Width := FRect.Right - FRect.Left;
    FBitmap.Height := FRect.Bottom - FRect.Top;

    //  改めてパラメータ設定
    DtFormat := DT_LEFT or DT_TOP or DT_SINGLELINE;

    //-----------------------------------------------------
    //  パス作成
    BeginPath(FBitmap.Canvas.Handle);
    OldMode := SetBkMode(FBitmap.Canvas.Handle, TRANSPARENT);
    DrawTextEx(FBitmap.Canvas.Handle, PChar(FText), -1, FRect, DtFormat, @DtParams);
    SetBkMode(FBitmap.Canvas.Handle, OldMode);
    EndPath(FBitmap.Canvas.Handle);

    //-----------------------------------------------------
    //  アウトライン情報取得
    FreeMemory();
    GetMemory();
end;

実行結果・ダウンロードTOP

GetPath ってぇ API がキャンバスに書かれたテキストを元に、始点・終点・通過点・ベジェ曲線用の制御点にバキバキと分割してくれて、戻ってきた点の配列とそれぞれの点の種類を、そのまま PolyDraw っていう API に渡してやると、ベジェ曲線の処理も含めて綺麗に書き出してくれます。

下の図は、PolyDraw が書いたテキストに、赤色で始点・終点・通過点を、青色でベジェ曲線用の制御点を重ね書きしただけです。なにかに使えそうな予感がするんですが、何に使うんだろう...

20051228FontOutlineTest.zip(189,459bytes)

EOFTOP