type {高 <----------- 優先順位 -----------> 低}
TTileState = (tsLeft, tsTop, tsRight, tsBottom, tsCenter);
TTileStates = set of TTileState;
procedure DrawTile(TileStates: TTileStates; Dest: TCanvas; DstWidth,
DstHeight: Integer; Graphic: TGraphic);
implementation
function CalcStartPos(SrcH, DefValue: Integer): Integer;
//DefValue <= 0 になるまでSrcHでデクリメント-------------------------------
begin
while DefValue > 0 do
Dec(DefValue, SrcH);
Result := DefValue;
end;
procedure CustomTileDraw(Dest: TCanvas; const X, Y, Width, Height: Integer;
Graphic: TGraphic);
//実際に描画を行う関数-----------------------------------------------------
var
px, py: Integer;
begin
{ 描画開始位置を初期化 }
py := Y;
px := X;
{ 描画開始位置がWidthとHeightを超えないようにループしながら }
{ 描画していくだけでタイリングが出来ます }
while py < Height do
begin
while px < Width do
begin
Dest.Draw(px, py, Graphic);
Inc(px, Graphic.Width);
end;
Inc(py, Graphic.Height);
px := X;//X座標を元に戻す
end;
end;
procedure DrawTile(TileStates: TTileStates; Dest: TCanvas; DstWidth,
DstHeight: Integer; Graphic: TGraphic);
//タイリング関数-----------------------------------------------------------
var
X, Y: Integer;
begin
{ DrawStartExsには共存できないフラグがあるので注意して下さい。}
{ 集合の要素の優先順位は要素の順序型の値が低い程高くなります。}
{ (つまりdteLeftが最も高くdteCenterが最も低い) }
{ [dteLeft, dteTop, dteRight, dteBottom]は[dteLeft, dteTop]に }
{ 解釈されます。空の集合は[dteLeft, dteTop]と解釈されます。 }
if (Graphic = nil) or (Dest = nil) then Exit;
with Graphic do
begin
if tsCenter in TileStates then
begin
//tsCenterが含まれている場合
{ tsCenterよりも他のフラグの方が優先順位が高いので... }
if tsLeft in TileStates then
X := 0//左基準
else
if tsRight in TileStates then
X := CalcStartPos(Width, DstWidth - Width)//右基準
else//tsLeft, tsRightが含まれない場合中央基準
X := CalcStartPos(Width , (DstWidth - Width ) div 2);
if tsTop in TileStates then
Y := 0//上基準
else
if tsBottom in TileStates then
Y := CalcStartPos(Height, DstHeight - Height)//下基準
else//tsTop, tsBottomが含まれない場合は中央基準
Y := CalcStartPos(Height, (DstHeight - Height) div 2);
end else begin
//tsCenterが含まれない場合
if not (tsRight in TileStates) then
X := 0//tsRightよりもtsLeft(空も含め)他方が優先順位が高い
else
X := CalcStartPos(Width, DstWidth - Width);
if not (tsBottom in TileStates) then
Y := 0//tsBottomよりもtsTop(空も含め)他方が優先順位が高い
else
Y := CalcStartPos(Height, DstHeight - Height);
end;
//座標の計算が終わったらタイリングを行う関数に渡す
CustomTileDraw(Dest, X, Y, DstWidth, DstHeight, Graphic);
end;
end;
|