#include <windows.h>
#include <boost/shared_array.hpp>
#include <math.h>
using TPointSharedArray = boost::shared_array<TPoint>;
const double PI = 3.14159265;
void __fastcall TForm1::TrackBar1Change(TObject *Sender)
{
Image1->Picture = NULL;
Image1->Picture->Bitmap->Width = Image1->Width;
Image1->Picture->Bitmap->Height = Image1->Height;
//
const int angle = TrackBar1->Position;
const String Str( L"C++Builder" );
const TPoint DrawPt( 100, 50 ); // 文字描画の開始位置
const int FontSize = 50;
//
// 描いた文字の点の情報を取得する
//-------------------------------------------------
// 文字をパスで描く
TCanvas* Canvas = Image1->Canvas;
BeginPath( Canvas->Handle );
Canvas->Brush->Style = bsClear;
Canvas->Font->Size = FontSize;
Canvas->Pen->Color = clBlack;
Canvas->TextOut( DrawPt.X, DrawPt.Y, Str );
EndPath( Canvas->Handle );
//パスを直線の集まりに変換
FlattenPath( Canvas->Handle );
// パス内の点の数を取得
const int count = GetPath( Canvas->Handle, NULL, NULL, 0 );
// 情報を格納する配列の作成:
boost::shared_array<TPoint> points( new TPoint[count] );
boost::shared_array<char> kinds( new char[count] );
// パス内の点情報を配列に格納する
GetPath( Canvas->Handle, (LPPOINT)(points.get()), (LPBYTE)(kinds.get()), count ); //
// 変形した点の情報を取得する
//---------------------------------------------------
// 変形した点の配列を取得する(別関数)
const int text_height = Canvas->TextHeight( Str );
const int text_width = Canvas->TextWidth( Str );
TPointSharedArray new_points
= get_points_transformed_parallelogram_horz
( points, count,
text_width,
text_height,
angle,
DrawPt );
// 変形した点の情報で文字を描く
//---------------------------------------------------
// 変形したパス情報をCanvasに戻す
BeginPath( Canvas->Handle );
PolyDraw( Canvas->Handle, (LPPOINT)(new_points.get()), (LPBYTE)(kinds.get()), count );
EndPath( Canvas->Handle );
// パス情報に従ってCanvasに描く
Canvas->Brush->Color = clBlack;
StrokeAndFillPath( Canvas->Handle );
}
//-------------------------------------------------
// 変形した点集合を取得する関数
//-------------------------------------------------
TPointSharedArray
TForm1::get_points_transformed_parallelogram_horz
( const TPointSharedArray& org_rect_points,
const int point_count,
const int org_width,
const int org_height,
const int angle,
const TPoint& org_offset )const
{
TPointSharedArray new_points( new TPoint[point_count] );
const double max_offset = org_height * tan( angle * PI / 180.0 );
for( int i = 0; i < point_count; ++i )
{
// Y位置はそのまま
new_points[i].Y = org_rect_points[i].Y;
// X位置をずらしていく
TPoint OrgInnerPt = org_rect_points[i];
OrgInnerPt.Offset( org_offset.X, -org_offset.Y );
const double height_per = OrgInnerPt.Y / (double)org_height;
new_points[i].X = org_rect_points[i].X + max_offset * ( 1.0 - height_per );
}
return new_points;
}