{ FONTMAKER 26.08.2003 - 2019
by MATOSIMI
}
unit Main;
interface
uses
{$IFDEF MSWINDOWS}
Windows, ShellApi, jpeg,
{$ENDIF}
SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, ComCtrls, Buttons,
AtariColorSelector, System.Actions, Vcl.ActnList,
System.JSON, Clipbrd, Vcl.AppEvnts;
type
TCharLine2color=array[0..7] of byte;
TCharLine5color=array[0..3] of byte;
TCharacter2color=array[0..7,0..7] of byte;
TCharacter5color=array[0..7,0..7] of byte;
TMegaCopyStatus = (None,Selecting,Selected,Pasting);
type
TMainForm = class(TForm)
i_view: TImage;
I_fn: TImage;
i_ch: TImage;
Bevel3: TBevel;
b_ror: TButton;
b_rol: TButton;
b_inv: TButton;
b_hmir: TButton;
b_vmir: TButton;
b_shr: TButton;
b_shl: TButton;
b_shu: TButton;
b_shd: TButton;
b_clr: TButton;
b_resd: TButton;
b_ress: TButton;
p_xx: TPanel;
p_hh: TPanel;
b_load: TButton;
b_save: TButton;
b_new: TButton;
b_about: TButton;
b_quit: TButton;
p_zz: TPanel;
b_gfx: TButton;
b_lview: TButton;
b_sview: TButton;
i_col: TImage;
Bevel4: TBevel;
b_clrview: TButton;
Ic1: TImage;
Ic2: TImage;
Bevel5: TBevel;
Bevel6: TBevel;
i_abo: TImage;
d_open: TOpenDialog;
d_save: TSaveDialog;
b_cpy: TButton;
b_pst: TButton;
b_savedual: TButton;
i_chset: TImage;
ch_dual: TCheckBox;
b_save1: TButton;
b_save2: TButton;
Timer1: TTimer;
b_exportBMP: TButton;
i_actcol: TImage;
p_status: TPanel;
l_char: TLabel;
l_col: TLabel;
Shape1: TShape;
b_colorSwitch: TButton;
b_colorSwSetup: TSpeedButton;
p_color_switch: TPanel;
lb_cs1: TListBox;
lb_cs2: TListBox;
i_rec2: TImage;
i_rec1: TImage;
ComboBoxWriteMode: TComboBox;
ActionListNormalModeOnly: TActionList;
//ActionList contains actions with different TAG parameter, legend:
//0 - action that does not modify character data
//1 - action that modifies character data
//2 - action that modifies character data applicable only on Mode 2
Previous_char: TAction;
Next_char: TAction;
Rotate_left: TAction;
Rotate_right: TAction;
Mirror_horizontal: TAction;
Mirror_vertical: TAction;
Color1: TAction;
Color2: TAction;
Color3: TAction;
ActionList2: TActionList;
Shape2v: TShape;
SpeedButtonMegaCopy: TSpeedButton;
Shape2: TShape;
Shape1v: TShape;
ApplicationEvents1: TApplicationEvents;
ImageMegacopy: TImage;
ImageMegaCopyV: TImage;
EscapePressed: TAction;
Shift_left: TAction;
Shift_right: TAction;
Shift_up: TAction;
Shift_down: TAction;
Invert: TAction;
Clear: TAction;
Restore_default: TAction;
Restore_lastSaved: TAction;
SpeedButtonUndo: TSpeedButton;
SpeedButtonRedo: TSpeedButton;
DebugTimer: TTimer;
ListBoxDebug: TListBox;
procedure SetColor(colorNum: integer);
procedure DoChar;
procedure RedrawSet;
procedure Load_font(filename: string; number:integer);
procedure Button3Click(Sender: TObject);
procedure i_chMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormCreate(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure default_pal;
procedure redrawpal;
procedure redrawchar;
procedure DefaultView;
procedure redrawview;
procedure redrawviewchar;
procedure grid;
procedure DrawChars(targetImage:TImage; data:string; chars:string; x,y:integer;
dataWidth,dataHeight: integer; gr0:boolean; pixelsize: integer);
procedure DrawChar(targetImage:TImage; data:string; char: string; x,y:integer;
gr0:boolean; pixelsize: integer);
procedure LoadPalette();
procedure SetCharCursor();
function MouseValidView(X,Y : integer) : boolean;
function MouseValidFont(X,Y : integer) : boolean;
procedure I_fnMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure i_colMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure b_gfxClick(Sender: TObject);
procedure Ic1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Ic2MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure b_aboutClick(Sender: TObject);
procedure i_aboMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure b_newClick(Sender: TObject);
procedure b_quitClick(Sender: TObject);
procedure b_loadClick(Sender: TObject);
procedure b_saveClick(Sender: TObject);
procedure b_clrviewClick(Sender: TObject);
procedure i_viewMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure b_lviewClick(Sender: TObject);
procedure b_sviewClick(Sender: TObject);
procedure i_chMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure i_chMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure i_chsetMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ch_dualClick(Sender: TObject);
procedure b_save1Click(Sender: TObject);
procedure b_save2Click(Sender: TObject);
procedure b_pstClick(Sender: TObject);
procedure b_savedualClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
procedure b_exportBMPClick(Sender: TObject);
procedure b_colorSwSetupClick(Sender: TObject);
procedure b_colorSwitchClick(Sender: TObject);
procedure ColorSwitch(idx1:integer;idx2:integer);
procedure lb_cs1Click(Sender: TObject);
procedure lb_cs2Click(Sender: TObject);
procedure i_viewMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure i_viewMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure ButtonMegaCopyClick(Sender: TObject);
procedure Previous_charExecute(Sender: TObject);
procedure Next_charExecute(Sender: TObject);
procedure Rotate_leftExecute(Sender: TObject);
procedure Rotate_rightExecute(Sender: TObject);
procedure Mirror_horizontalExecute(Sender: TObject);
procedure Mirror_verticalExecute(Sender: TObject);
procedure Clipboard_copyExecute(Sender: TObject); overload;
procedure Clipboard_pasteExecute(Sender: TObject); overload;
procedure Color1Execute(Sender: TObject);
procedure Color2Execute(Sender: TObject);
procedure Color3Execute(Sender: TObject);
procedure RevalidateClipboard();
procedure Shape2vMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Shape2vMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Shape2vMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure Shape1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Shape1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure I_fnMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure Shape1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure I_fnMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Shape2MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Shape2MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure Shape2MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure SpeedButtonMegaCopyClick(Sender: TObject);
procedure Shape2vMouseLeave(Sender: TObject);
procedure Shape2MouseLeave(Sender: TObject);
procedure I_fnMouseEnter(Sender: TObject);
procedure ImageMegacopyMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure ImageMegacopyMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ImageMegaCopyVMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure ImageMegaCopyVMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure i_viewMouseLeave(Sender: TObject);
procedure Shape1vMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Shape1vMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure Shape1vMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ResetMegaCopyStatus; //(TargetMegaCopyStatus: TMegaCopyStatus);
procedure EscapePressedExecute(Sender: TObject);
procedure Shift_leftExecute(Sender: TObject);
procedure b_shrClick(Sender: TObject);
procedure b_shdClick(Sender: TObject);
procedure b_shuClick(Sender: TObject);
procedure b_invClick(Sender: TObject);
procedure b_clrClick(Sender: TObject);
procedure b_resdClick(Sender: TObject);
procedure b_ressClick(Sender: TObject);
procedure RevalidateCharButtons();
procedure LoadViewFile(filename:string);
procedure SaveViewFile(filename:string);
procedure UpdateFormCaption;
procedure Add2Undo(difference:boolean);
procedure Add2UndoInitial();
procedure Add2UndoFullDifferenceScan();
function Undo:bool;
function Redo:bool;
function GetPrevUndoIndex():word;
procedure UpdateUndoButtons(edited:boolean);
procedure ActionListNormalModeOnlyExecute(Action: TBasicAction;
var Handled: Boolean);
procedure SpeedButtonUndoClick(Sender: TObject);
procedure SpeedButtonRedoClick(Sender: TObject);
function CharacterEdited():boolean;
procedure DebugTimerTimer(Sender: TObject);
private
chsline:array[0..25] of byte; //urcuje aky font je v line v viewWIN
pathf:string;
fname1,fname2,fdual:string;
gfx:boolean; //false-gr.0 true-gr.12
ac:byte; //actual color
cpal:array[0..5] of byte;
//ch,c2:ch2c; //1 character gr.0
//cj,c5:ch5c; //1 character gr.12
// ft:array[0..2047] of byte; //font table (pre 2 fonty)
selectedCharacterIndex:word; //character pointer
//hp:word; //character pointer in font table
vw:array[0..31,0..25] of byte;
clx,cly:integer; // klik (edit znaku)
clxv,clyv:integer; //klik (view window)
clck:boolean;
ButtonHeld:TMouseButton; //mousebutton that is being hold
clckv:boolean; //click view w.
clipboardLocal: string; //contents of local clipboard
megaCopyStatus: TMegaCopyStatus; //if mega copy selection has been done
palette:TMyPalette;
copyRange: TRect;
copyTarget: TPoint;
{ Private declarations }
procedure Clipboard_pasteExecute(Sender: TObject; targetIsView: boolean); overload;
procedure Clipboard_copyExecute(Sender: TObject; sourceIsView: boolean); overload;
const colorIndex2bits: array[0..5] of byte = (0,0,1,2,3,3);
const bits2colorIndex: array[0..3] of byte = (1,2,3,4);
UNDOBUFFERSIZE = 100;
public
{ Public declarations }
ft:array[0..2047] of byte; //font table (pre 2 fonty)
undoBuffer: array[0..UNDOBUFFERSIZE,0..2047] of byte;
undoBufferFlags: array[0..UNDOBUFFERSIZE] of longint;
undoBufferIndex:word; //pointing to LAST saved font in buffer
end;
var
MainForm: TMainForm;
const
title='Atari FontMaker v1.5 (29.12.2019) Rev49';
type
TMyPalette = array[0..255] of TColor;
implementation
{$R *.dfm}
{$IFDEF UNIX}
uses ExportWindow, LCLType, LCLIntf;
function GetRValue(rgb: DWORD): BYTE;
begin
GetRValue := Byte(rgb);
end;
function GetGValue(rgb: DWORD): BYTE;
begin
GetGValue := Byte((Word(rgb) shr 8));
end;
function GetBValue(rgb: DWORD): BYTE;
begin
GetBValue := Byte(rgb shr 16);
end;
function RGB(cRed, cGreen, cBlue: BYTE): DWORD;
begin
RGB := DWORD(cRed or (WORD(cGreen) shl 8) or (DWORD(cBlue) shl 16));
end;
{$ELSE}
uses ExportWindow;
function OpenURL(AURL: PChar):Boolean;
begin
ShellExecute(MainForm.handle,'open',AURL,'','',sw_show);
Result := True;
end;
{$ENDIF}
function GetCharacterPointer(character: word) : word;
var rx,ry: word;
begin
ry:=character div 32;
rx:=character mod 32;
if (ry>3)and(ry<12) then dec(ry,4);
if (ry>11)and(ry<16) then dec(ry,8);
Result := ry*32*8+rx*8;
end;
function DecodeBW(ln:byte):TCharLine2color;
var v:byte;
c:shortint;
op:TCharLine2color;
begin
for c := 7 downto 0 do
begin
op[c] := ln mod 2;
ln := ln shr 1;
end;
result := op;
end;
function DecodeCL(ln:byte):TCharLine5color;
var v:byte;
c:shortint;
op:TCharLine5color;
begin
for c := 3 downto 0 do
begin
op[c] := ln mod 4;
ln := ln shr 2;
end;
result := op;
end;
function EncodeBW(cd:TCharLine2color):byte;
var v,c,o:byte;
begin
v:=128;c:=0;o:=0;
repeat
o:=o+v*ord(cd[c]);
inc(c);
v:=v div 2;
until v=0;
result:=o;
end;
function EncodeCL(cd:TCharLine5color):byte;
var v,c,o:byte;
begin
v:=64;c:=0;o:=0;
repeat
o:=o+v*cd[c];
inc(c);
v:=v div 4;
until v=0;
result:=o;
end;
function Get5ColorCharacter(character: word) : TCharacter5color;
var charPtr: word;
i,j: byte;
clData: TCharLine5color;
begin
charPtr := GetCharacterPointer(character);
for i := 0 to 7 do
begin
clData := DecodeCL(MainForm.ft[charPtr]);
for j := 0 to 3 do
Result[j,i] := clData[j];
inc(charPtr);
end;
end;
function Get2ColorCharacter(character: word) : TCharacter2color;
var charPtr: word;
i,j: byte;
clData: TCharLine2color;
begin
charPtr := GetCharacterPointer(character);
for i := 0 to 7 do
begin
clData := DecodeBW(MainForm.ft[charPtr + i]);
for j := 0 to 7 do
Result[j,i] := cldata[j];
end;
end;
procedure Set2ColorCharacter(character2color: TCharacter2color; character: word);
var a,b:byte;
fontByteIndex:word;
charline2:TCharLine2color;
begin
fontByteIndex := GetCharacterPointer(character);
for a := 0 to 7 do
begin
for b := 0 to 7 do
charline2[b] := character2color[b,a];
MainForm.ft[fontByteIndex + a] := encodeBW(charline2);
end;
end;
procedure Set5ColorCharacter(character5color: TCharacter5color; character: word);
var a,b:byte;
fontByteIndex:word;
charline5:TCharLine5color;
begin
fontByteIndex := GetCharacterPointer(character);
for a := 0 to 7 do
begin
for b := 0 to 3 do
charline5[b] := character5color[b,a];
MainForm.ft[fontByteIndex + a] := encodeCL(charline5);
end;
end;
//**************************************
// END OF GENERIC FUNCTIONS DECLARATION
//**************************************
procedure TMainForm.LoadPalette();
var palfile:file of byte;
buffer: array[0..767] of byte;
i: Integer;
begin
AssignFile(palfile, 'laoo.act');
Reset(palfile);
BlockRead(palfile, buffer, 768, i);
CloseFile(palfile);
if i < 768 then ShowMessage('Palette load error');
for i := 0 to 255 do
palette[i] := RGB(buffer[i*3], buffer[i*3+1], buffer[i*3+2]);
end;
//updates undo/redo button state based on info if character has been edited and whats the buffer index
procedure TMainForm.UpdateUndoButtons(edited:boolean);
var val:longint;
nextUndoBufferIndex,prevUndoBufferIndex:word;
begin
nextUndoBufferIndex := (undoBufferIndex + 1) mod UNDOBUFFERSIZE;
prevUndoBufferIndex := GetPrevUndoIndex();
//redo button handling
if undobufferflags[nextUndoBufferIndex] = -1 then SpeedButtonRedo.enabled := false
else
begin
if edited then SpeedButtonRedo.enabled := false
else SpeedButtonRedo.enabled := true;
end;
//undo button handling
if edited then
speedbuttonUndo.enabled := true
else
begin
if (undobufferflags[undoBufferIndex] > undobufferflags[prevUndoBufferIndex]) and (undobufferflags[prevUndoBufferIndex] > -1) then
speedbuttonUndo.enabled := true
else
speedbuttonUndo.enabled := false;
end;
end;
procedure TMainForm.ActionListNormalModeOnlyExecute(Action: TBasicAction;
var Handled: Boolean);
var edited:boolean;
begin
//does not make sense
{ edited := false;
//action.tag defines if action changes character data or not
if action.Tag > 0 then
begin
edited := CharacterEdited();
UpdateUndoButtons(edited);
end;
}
end;
Procedure TMainForm.Add2UndoFullDifferenceScan();
var difference:boolean;
i:word;
begin
difference := false;
i := 0;
//check the difference between last undobuffer and current font
while (i < 2048) and (not difference) do
begin
if ft[i] <> undoBuffer[undoBufferIndex,i] then difference := true;
inc(i);
end;
if difference then Add2Undo(True);
UpdateUndoButtons(false);
end;
Procedure TMainForm.Add2UndoInitial();
var i:integer;
difference:boolean;
prevUndoIndex:word;
begin
prevUndoIndex := undoBufferIndex;
for i := 0 to 2047 do
undobuffer[undoBufferIndex,i] := ft[i];
undoBufferFlags[undoBufferIndex] := undoBufferFlags[prevUndoIndex] + 1;
undoBufferFlags[(undoBufferIndex + 1) mod UNDOBUFFERSIZE] := -1; //disallow redo when change
end;
//adds current font in undo buffer
Procedure TMainForm.Add2Undo(difference:boolean);
var i,x:integer;
prevUndoIndex:word;
begin
//handle initial state
{ if SpeedButtonUndo.Enabled then
begin
difference := True;
end;
}
{
if undoBufferFlags[undoBufferIndex] = -1 then
difference := true
else
begin
i := 0;
difference := false;
//check the difference between last undobuffer and current font
while (i < 2048) or (not difference) do
begin
if ft[i] <> undoBuffer[(undoBufferIndex-1) mod UNDOBUFFERSIZE,i] then difference := true;
inc(i);
end;
end;
}
if difference then
begin
prevUndoIndex := undoBufferIndex;
undoBufferIndex := (undobufferindex + 1) mod UNDOBUFFERSIZE; //size of undo buffer
for i := 0 to 2047 do
undobuffer[undoBufferIndex,i] := ft[i];
undoBufferFlags[undoBufferIndex] := undoBufferFlags[prevUndoIndex] + 1;
undoBufferFlags[(undoBufferIndex + 1) mod UNDOBUFFERSIZE] := -1; //disallow redo when change
end;
end;
// returns true if character has been edited (different to last saved in undo buffer)
function TMainForm.CharacterEdited:boolean;
var i:byte;
ptr:word;
begin
i := 0;
Result := false;
ptr := selectedCharacterIndex*8;
while (i < 8) and (Result = false) do
begin
Result := ft[ptr + i] <> undoBuffer[undoBufferIndex, ptr + i];
inc(i);
end;
end;
function TMainForm.GetPrevUndoIndex():word;
begin
if (undobufferindex - 1 < 0) then
result := UNDOBUFFERSIZE - 1
else
result := undobufferindex - 1;
end;
function TMainForm.Undo:bool;
var i:integer;
down:byte;
nextUndoIndex,prevUndoIndex:word;
begin
nextUndoIndex := (undoBufferIndex + 1) mod UNDOBUFFERSIZE;
if (undoBufferFlags[nextUndoIndex] = -1)and(CharacterEdited()) then
begin
Add2Undo(true); //add 2 undo but dont change index
end;
prevUndoIndex := GetPrevUndoIndex();
{ down := 1;
if characterEdited then begin;Add2Undo(false);down := 2;end;
undoBufferIndex := (undoBufferIndex - down) mod UNDOBUFFERSIZE;
}
for i := 0 to 2047 do
ft[i] := undobuffer[prevUndoIndex,i];
undoBufferIndex := prevUndoIndex;
UpdateUndoButtons(CharacterEdited());
redrawchar;
redrawset;
redrawview;
result := True;
end;
function TMainForm.Redo:bool;
var i:integer;
nextUndoIndex:word;
begin
nextUndoIndex := (undoBufferIndex + 1) mod UNDOBUFFERSIZE;
if (undoBufferFlags[nextUndoIndex] > -1) then
for i := 0 to 2047 do
ft[i] := undobuffer[nextUndoIndex,i];
undoBufferIndex := nextUndoIndex;
UpdateUndoButtons(CharacterEdited());
redrawchar;
redrawset;
redrawview;
result := True;
end;
procedure TMainForm.DebugTimerTimer(Sender: TObject);
var a:integer;
begin
ListBoxDebug.Visible := true;
ListBoxDebug.Items.Clear;
listboxdebug.Items.Add('undoindex:' + inttostr(undoBufferIndex));
listboxdebug.Items.Add('undoflags:' + inttostr(undoBufferFlags[undoBufferIndex]));
listboxdebug.Items.Add('charchanged:' + inttostr(ord(CharacterEdited)));
for a := 0 to UNDOBUFFERSIZE-1 do
ListBoxDebug.Items.add('undobuffer(' + inttostr(a) + '): ' + inttostr(undobufferflags[a]));
// listboxdebug.Items.Add('undoindex:' + inttostr(undoBufferIndex));
// listboxdebug.Items.Add('undoindex:' + inttostr(undoBufferIndex));
end;
Procedure tMainForm.DefaultView;
const dt=#52+'he'+#0+'quick'+#0+'brown'+#0+'fox'+#0+'jumps';
dy='over'+#0+'the'+#0+'lazy'+#0+'dog';
var a:byte;
begin
for a:=1 to length(dt) do
begin
vw[a+2,2]:=ord(dt[a]);
end;
for a:=1 to length(dy) do
begin
vw[a+6,3]:=ord(dy[a]);
end;
i_chset.Canvas.Brush.Color:=ClBlack;
i_chset.Canvas.FillRect(bounds(0,0,i_chset.Width,i_chset.Height));
i_chset.Canvas.Font.Color:=clWhite;
for a:=0 to 25 do
begin
chsline[a]:=1;
i_chset.Canvas.TextOut(4,2+a*16,'1');
end;
end;
//redraw whole view area by copying characters from font area
procedure tMainForm.redrawview;
var a,b,rx,ry:byte;
begin
for b:=0 to 25 do begin
for a:=0 to 31 do begin
rx:=vw[a,b] mod 32;
ry:=(vw[a,b] div 32);
if chsline[b]=2 then ry:=(ry OR 8);
i_view.Canvas.CopyRect(bounds(a*16,b*16,16,16),i_fn.Canvas,bounds(rx*16,ry*16,16,16));
end;
end;
end;
//redraw all occurences of character (selectedCharacterIndex) in view area
procedure tMainForm.redrawviewchar;
var a,b,rx,ry,ny,dp,ep:word;
begin
rx:=selectedCharacterIndex mod 32;
ry:=selectedCharacterIndex div 32;
for b:=0 to 25 do begin
ry:=(ry OR 8);
if chsline[b]=1 then ry:=(ry XOR 8);
ny:=ry XOR 4; //ny obsahuje invertnuty znak (ry)
ep:=(rx+ry*32) mod 256;
dp:=(rx+ny*32) mod 256;
for a:=0 to 31 do begin
if vw[a,b]=ep then begin i_view.Canvas.CopyRect(bounds(a*16,b*16,16,16),i_fn.Canvas,bounds(rx*16,ry*16,16,16));end;
if vw[a,b]=dp then begin i_view.Canvas.CopyRect(bounds(a*16,b*16,16,16),i_fn.Canvas,bounds(rx*16,ny*16,16,16));end;
end;
end;
end;
procedure drawTxt(ic:Timage; x:integer; y:integer; num:integer; color:integer);
const texty:array[0..5] of string = ('LUM','BAK - 00','PF0 - 01','PF1 - 10','PF2 - 11','PF3 - 11');
begin
ic.Canvas.Brush.Style := bsClear;
if (GetGValue(color)) > 128 then
ic.Canvas.Font.Color := clBlack
else
ic.Canvas.Font.Color := clWhite;
ic.Canvas.TextOut(x,y,texty[num]);
end;
procedure tMainForm.redrawpal;
var a,b:byte;
begin
for a:=0 to 2 do
begin
for b:=0 to 1 do
begin
i_col.Canvas.Brush.Color:=palette[cpal[b+a*2]];
i_col.Canvas.FillRect(bounds(b*45,a*18,45,22));
drawTxt(i_col,b*45,a*18,b+a*2,palette[cpal[b+a*2]]);
end;
end;
ic1.Canvas.Brush.Color:=palette[cpal[ic1.Tag]];
ic1.Canvas.FillRect(bounds(0,0,49,17));
drawTxt(ic1,1,1,ic1.Tag,palette[cpal[ic1.Tag]]);
ic2.Canvas.Brush.Color:=palette[cpal[ic2.Tag]];
ic2.Canvas.FillRect(bounds(0,0,49,17));
drawTxt(ic2,1,1,ic2.Tag,palette[cpal[ic2.Tag]]);
i_actcol.Canvas.Brush.Color:=palette[cpal[ac]];
i_actcol.Canvas.FillRect(bounds(0,0,49,17));
drawTxt(i_actcol,1,1,ac,palette[cpal[ac]]);
end;
procedure tMainForm.default_pal;
begin
cpal[0]:=14;
cpal[1]:=0;
cpal[2]:=40;
cpal[3]:=202;
cpal[4]:=148;
cpal[5]:=70;
end;
procedure TMainForm.grid;
var a,b:byte;
begin
i_ch.Canvas.Brush.Color:=palette[cpal[1]];
i_ch.Canvas.FillRect(bounds(0,0,i_ch.Width,i_ch.Height));
for b:=0 to 7 do begin
for a:=0 to 7 do begin
i_ch.Canvas.Pixels[a*20,b*20]:=clWhite;
end;
end;
end;
procedure TMainForm.Load_font(filename: string; number:integer);
var fil:file of byte;
b:integer;
begin
filemode:=fmopenread;
//pathf:=extractfilepath(application.ExeName);
assignfile(fil, filename); //pathf+PathDelim+'default.fnt');
reset(fil);
b:=0;
if (number = 2) then
BlockRead(fil,ft[0],2048,b)
else
BlockRead(fil,ft[number*1024],1024,b);
//seek(fil,0);
//BlockRead(fil,ft[1024],1024,b); //zdvojene nacitanie
closefile(fil);
end;
procedure TMainForm.Rotate_leftExecute(Sender: TObject);
var src2,tmp2:TCharacter2color;
src5,tmp5:TCharacter5color;
a,b:byte;
begin
if not gfx then
begin
src2 := Get2ColorCharacter(selectedCharacterIndex);
for a:=0 to 7 do
for b:=0 to 7 do
tmp2[b,a] := src2[7-a,b];
Set2ColorCharacter(tmp2, selectedCharacterIndex);
DoChar;
RedrawChar;
Redrawviewchar;
end;
end;
procedure TMainForm.Rotate_rightExecute(Sender: TObject);
var src2,tmp2:TCharacter2color;
a,b:byte;
begin
if not gfx then
begin
src2 := Get2ColorCharacter(selectedCharacterIndex);
for a:=0 to 7 do
for b:=0 to 7 do
tmp2[b,a] := src2[a,7-b];
Set2ColorCharacter(tmp2, selectedCharacterIndex);
DoChar;
RedrawChar;
Redrawviewchar;
end;
end;
procedure TMainForm.Mirror_horizontalExecute(Sender: TObject);
var src,tmp:TCharacter2color;
src5,tmp5:TCharacter5color;
a,b,i:byte;
begin
if not gfx then //mode 2
begin
src := Get2ColorCharacter(selectedCharacterIndex);
for a:=0 to 7 do
for b:=0 to 7 do
tmp[b,a]:=src[7-b,a];
Set2ColorCharacter(tmp,selectedCharacterIndex);
end
else
begin //mode 4
src5 := Get5ColorCharacter(selectedCharacterIndex);
for a:=0 to 7 do
for b:=0 to 3 do
tmp5[b,a]:=src5[3-b,a];
Set5ColorCharacter(tmp5,selectedCharacterIndex);
end;
DoChar;
RedrawChar;
Redrawviewchar;
end;
procedure TMainForm.Mirror_verticalExecute(Sender: TObject);
var src,tmp:TCharacter2color;
a,b:byte;
begin
src := Get2ColorCharacter(selectedCharacterIndex);
for a := 0 to 7 do
for b:= 0 to 7 do
tmp[a,b] := src[a,7-b];
Set2ColorCharacter(tmp,selectedCharacterIndex);
DoChar;
RedrawChar;
Redrawviewchar;
end;
procedure TMainForm.Previous_charExecute(Sender: TObject);
var bx,by:integer;
begin
Dec(selectedCharacterIndex);
SetCharCursor();
end;
procedure TMainForm.Next_charExecute(Sender: TObject);
begin
Inc(selectedCharacterIndex);
SetCharCursor();
end;
procedure TMainForm.ButtonMegaCopyClick(Sender: TObject);
begin
//AtariColorSelectorForm.SetPalette(palette);
end;
procedure TMainForm.EscapePressedExecute(Sender: TObject);
begin
if SpeedButtonMegaCopy.Down then
begin
case megaCopyStatus of
None: ;
Selecting:
ResetMegaCopyStatus;//(None);
Selected: ;
Pasting:
ResetMegaCopyStatus;//(Selected);
end;
end;
end;
procedure TMainForm.Shift_leftExecute(Sender: TObject);
var src,tmp:TCharacter2color;
a,b,h,i:byte;
repeatTime:byte;
begin
repeatTime := ord(gfx); //perform same shift twice in mode 4
src := Get2ColorCharacter(selectedCharacterIndex);
for i := 0 to repeatTime do
begin
for a:=0 to 7 do
begin
for b:=0 to 7 do
begin
if b<7 then h := b + 1 else h := 0;
tmp[b,a] := src[h,a];
end;
end;
src := tmp;
end;
Set2ColorCharacter(tmp,selectedCharacterIndex);
DoChar;
RedrawChar;
Redrawviewchar;
end;
procedure tMainForm.Button3Click(Sender: TObject);
begin
redrawset;
end;
//redraws whole font area
procedure TMainForm.redrawset;
var a,b,c,d,fb:byte;
ou,ou2:TCharLine2color;
ov,ov2:TCharLine5color;
begin
if not gfx then begin //gr.0:
i_fn.Canvas.Brush.Color:=palette[cpal[1]];
i_fn.Canvas.FillRect(bounds(0,0,512,i_fn.Height));
i_fn.Canvas.Brush.Color:=palette[cpal[0]];
for d:=0 to 3 do
begin
for a:=0 to 31 do
begin
for b:=0 to 7 do
begin
ou:=decodeBW(ft[a*8+b+d*32*8]);
ou2:=decodeBW(ft[a*8+b+d*32*8+1024]);
for c:=0 to 7 do
begin
if ou[c] = 1 then i_fn.Canvas.fillrect(bounds(a*16+c*2,b*2+d*16,2,2))
else i_fn.Canvas.fillrect(bounds(a*16+c*2,b*2+d*16+64,2,2));
if ou2[c] = 1 then i_fn.Canvas.fillrect(bounds(a*16+c*2,b*2+d*16+128,2,2))
else i_fn.Canvas.fillrect(bounds(a*16+c*2,b*2+d*16+192,2,2));
end;
end;
end;
end;
end else begin //gr.12
for d:=0 to 3 do
begin
for a:=0 to 31 do
begin
for b:=0 to 7 do
begin
ov:=decodeCL(ft[a*8+b+d*32*8]);
ov2:=decodeCL(ft[a*8+b+d*32*8+1024]);
for c:=0 to 3 do
begin
fb:=ov[c]+1;
i_fn.Canvas.Brush.Color:=palette[cpal[fb]];
i_fn.Canvas.fillrect(bounds(a*16+c*4,b*2+d*16,4,2));
if fb=4 then i_fn.Canvas.Brush.Color:=palette[cpal[5]];
i_fn.Canvas.fillrect(bounds(a*16+c*4,b*2+d*16+64,4,2));
fb:=ov2[c]+1;
i_fn.Canvas.Brush.Color:=palette[cpal[fb]];
i_fn.Canvas.fillrect(bounds(a*16+c*4,b*2+d*16+128,4,2));
if fb=4 then i_fn.Canvas.Brush.Color:=palette[cpal[5]];
i_fn.Canvas.fillrect(bounds(a*16+c*4,b*2+d*16+192,4,2));
end;
end;
end;
end;
end;
end;
procedure TMainForm.i_chMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var rx,ry:byte;
charline2col:TCharLine2color;
charline5col:TCharLine5color;
a:byte;
hp: word;
begin
clck:=true;
buttonHeld:=Button;
if ssCtrl in Shift then clck := false; //ctrl+click nezapina toggle
hp := GetCharacterPointer(selectedCharacterIndex);
ry:=y div 20;
cly:=ry;
if not gfx then
begin
charline2col := DecodeBW(ft[hp + ry]);
rx:=x div 20;
clx:=rx;
if Button = mbLeft then
if ComboBoxWriteMode.ItemIndex = 0 then //rewrite (default)
if charline2col[rx]=0 then charline2col[rx] := 1 else charline2col[rx] := 0
else
charline2col[rx] := 1 //insert
else if Button = mbRight then
charline2col[rx] := 0; //delete
ft[hp + ry] := EncodeBW(charline2col);
DoChar;
if charline2col[rx] = 1 then i_ch.Canvas.Brush.Color := palette[cpal[0]]
else i_ch.Canvas.Brush.Color := palette[cpal[1]];
i_ch.Canvas.FillRect(bounds(rx*20,ry*20,20,20));
i_ch.Canvas.Pixels[rx*20,ry*20] := palette[cpal[0]];
end
else
begin
charline5col := DecodeCL(ft[hp + ry]);
for a:=0 to 3 do charline5col[a] := bits2colorIndex[charline5col[a]];
rx:=x div 40;
clx:=rx;
if Button = mbLeft then
if ComboBoxWriteMode.ItemIndex = 0 then //rewrite (default)
if charline5col[rx]<>ac then charline5col[rx] := ac else charline5col[rx] := 1
else
charline5col[rx] := ac //insert
else if Button = mbRight then
charline5col[rx] := 1; //delete
//draw pixel
i_ch.Canvas.Brush.Color:=palette[cpal[charline5col[rx]]];
i_ch.canvas.FillRect(bounds(rx*40,ry*20,40,20));
//recode to byte and save to charset
for a:=0 to 3 do charline5col[a] := colorindex2bits[charline5col[a]];
ft[hp + ry] := EncodeCL(charline5col);
DoChar;
end;
redrawviewchar;
UpdateUndoButtons(CharacterEdited());
end;
procedure CheckResources();
var
RStream: TResourceStream;
begin
if not FileExists('default.fnt') then
begin
RStream := TResourceStream.CreateFromID(HInstance, 1, RT_FONT);
try
RStream.SaveToFile('Default.fnt');
finally
RStream.Free;
end;
end;
if not FileExists('default.fn2') then
begin
RStream := TResourceStream.Create(HInstance, 'fn2', RT_RCDATA);
try
RStream.SaveToFile('Default.fn2');
finally
RStream.Free;
end;
end;
if not FileExists('laoo.act') then
begin
RStream := TResourceStream.Create(HInstance, 'act', RT_RCDATA);
try
RStream.SaveToFile('laoo.act');
finally
RStream.Free;
end;
end;
end;
procedure TMainForm.FormCreate(Sender: TObject);
var a:integer;
ext:string;
const pfs:array[0..3] of string = ('BAK (00)','PF0 (01)','PF1 (10)','PF2 (11)');
begin
CheckResources;
LoadPalette;
timer1.Enabled:=true;
copyRange.Create(0,0,0,0);
//undobuffer initialization
undobufferindex := 0;
for a := 0 to UNDOBUFFERSIZE do
undoBufferFlags[a] := -1;
selectedCharacterIndex := 0;
for a:=0 to 25 do chsline[a]:=1;
p_xx.DoubleBuffered:=true;
doublebuffered:=true;
pathf:=extractfilepath(application.ExeName);
if (ParamCount = 1) then
begin
ext := ExtractFileExt(paramstr(1));
if (ext = '.fn2') then
begin
ch_dual.Checked := true;
fdual:=ParamStr(1);
Load_font(fdual, 2);
end
else if (ext = '.fnt') then
begin
fname1:=paramstr(1);
end
else
begin
ShowMessage('wrong imput file');
Application.Terminate;
end;
end
else
begin
fname1:=pathf+PathDelim + 'Default.fnt';
fdual:=pathf+PathDelim + 'Default.fn2';
end;
fname2:=pathf+ PathDelim + 'Default.fnt';
ac:=2;
Default_pal;
redrawpal;
grid;
if (ext <> '.fn2') then
begin
load_font(fname1,0);
load_font(fname2,1);
UpdateFormCaption;
end
else
begin
UpdateFormCaption;
end;
redrawset;
defaultview;
redrawview;
for a := 0 to 3 do
begin
lb_cs1.Items.Add(pfs[a]);
lb_cs2.Items.Add(pfs[a]);
end;
lb_cs1.ItemIndex := 0;
lb_cs2.ItemIndex := 0;
lb_cs1Click(Nil);
lb_cs2Click(Nil);
Add2UndoInitial; //initial undobuffer entry
UpdateUndoButtons(false);
end;
procedure TMainForm.SetCharCursor();
var bx,by:integer;
begin
if characterEdited() then Add2Undo(true);
selectedCharacterIndex := selectedCharacterIndex mod 512;
bx:=selectedCharacterIndex mod 32;
by:=selectedCharacterIndex div 32;
i_fnMouseDown(nil,mbLeft,[],bx*16+4,by*16+4);
end;
procedure TMainForm.ResetMegaCopyStatus();
begin
case megaCopyStatus of
None: ;
Selecting:
begin
megaCopyStatus := None;
//font window
shape1.Width := 20;
shape1.Height := 20;
shape1.Left := -30;
//view window
shape1v.Width := 20;
shape1v.Height := 20;
shape1v.Left := -30;
end;
Selected: ;
Pasting:
begin
megaCopyStatus := Selected;
shape2.Visible := false;
ImageMegacopy.Visible := false;
shape2v.Visible := false;
ImageMegacopyV.Visible := false;
end;
end;
end;
procedure TMainForm.I_fnMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var rx,ry,a,b:byte;
g:TCharLine2color;
w:TCharLine5color;
fontchar:integer;
fontnr:integer;
hp:word;
begin
if (x >= i_fn.Width) or (y >= i_fn.Height) then exit;
if not SpeedButtonMegaCopy.Down then
if CharacterEdited() then Add2Undo(true);
rx:=x div 16;
ry:=y div 16;
selectedCharacterIndex:=rx+ry*32;
if selectedCharacterIndex > 255 then
begin
fontchar := selectedCharacterIndex mod 256;
fontnr := 2
end
else
begin
fontchar := selectedCharacterIndex;
fontnr := 1;
end;
if SpeedButtonMegaCopy.Down then
begin
case megaCopyStatus of
None,Selected:
begin
if ssLeft in Shift then
begin
//define copy origin point
copyRange.Top := ry;
copyRange.Left := rx;
megaCopyStatus := Selecting;
shape1.Left := i_fn.left + x - x mod 16 - 2;
shape1.Top := i_fn.Top + y - y mod 16 - 2;
shape1.Width := 20;
shape1.Height := 20;
shape1.Visible := true;
shape1v.Visible := false;
end;
end;
{ Selecting:
begin
shape1.Visible := true;
//define copy end point
{
megaCopyRange.Bottom := ry;
megaCopyRange.Right := rx;
megacopystatus := Selected;
}
//size coming from mousemove
//shape1.Width := (megaCopyRange.Width + 1)*16+4;
//shape1.Height := (megaCopyRange.Height + 1)*16+4;
{
end;}
Pasting:
begin
//paste
if not MouseValidFont(x,y) then exit;
if (ssLeft in Shift) then
begin
copyTarget := Point(rx,ry);
Add2UndoFullDifferenceScan();
Clipboard_pasteExecute(sender, false);
ResetMegaCopyStatus;
end;
//reset selection by right doubleclick
if (ssDouble in Shift) and (ssRight in Shift) then
ResetMegaCopyStatus;
end;
end;
end
else
begin
shape1.Left := i_fn.left + x - x mod 16 - 2;
shape1.Top := i_fn.Top + y - y mod 16 - 2;
copyRange.Top := ry;
copyRange.Left := rx;
copyRange.Width := 0;
copyRange.Height := 0;
l_char.Caption := 'Char: Font ' + inttostr(fontnr) + ' $' + inttohex(fontchar,2) + ' #' + inttostr(fontchar);
redrawchar;
end;
end;
procedure TMainForm.I_fnMouseEnter(Sender: TObject);
begin
end;
//returns true if mouse is in valid position in view area
function TMainForm.MouseValidView(X,Y : integer) : boolean;
begin
if (x >= i_view.width - (copyRange.width)*16) or
(y >= i_view.Height - (copyRange.Height)*16) then
result := false
else
result := true;
end;
//returns true if mouse is in valid position in font area
function TMainForm.MouseValidFont(X,Y : integer) : boolean;
begin
if (x >= i_fn.width - (copyRange.width)*16) or
(y >= i_fn.Height - (copyRange.Height)*16) then
result := false
else
result := true;
end;
procedure TMainForm.I_fnMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
rx,ry,temp:integer;
begin
{memo1.Text := inttostr(copyrange.left) + '-' + inttostr(copyrange.Right) +
' : ' + inttostr(copyRange.Width) + sLineBreak + inttostr(copyrange.top) + '-' + inttostr(copyrange.Bottom) +
' : ' + inttostr(copyRange.Height);
}
if SpeedButtonMegaCopy.Down then
begin
case megaCopyStatus of
{ None:
begin
shape1.Left := i_fn.left + x - x mod 16 - 2;
shape1.Top := i_fn.Top + y - y mod 16 - 2;
shape1.Width := 20;
shape1.Height := 20;
shape1.Visible := true;
end; }
Selecting:
begin
if (x >= i_fn.Width) or (y >= i_fn.Height) then exit;
rx:=x div 16;
ry:=y div 16;
temp := (rx - copyRange.Left + 1) * 16 + 4;
if temp < 20 then shape1.Width := 20
else shape1.Width := temp;
temp := (ry - copyRange.Top + 1) * 16 + 4;
if temp < 20 then shape1.Height := 20
else shape1.Height := temp;
end;
Pasting:
begin
if not MouseValidFont(X,Y) then
begin
Shape2.Visible := false;
ImageMegacopy.Visible := false;
exit;
end;
shape2.Left := i_fn.left + x - x mod 16 - 2;
shape2.Top := i_fn.Top + y - y mod 16 - 2;
ImageMegacopy.Left := shape2.Left + 2;
ImageMegacopy.Top := shape2.Top + 2;
shape2.Visible := true;
ImageMegacopy.Visible := true;
shape2v.Visible := false;
ImageMegaCopyV.Visible := false;
end;
end;
end;
end;
procedure TMainForm.I_fnMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
rx,ry:integer;
begin
if (x >= i_fn.Width) or (y >= i_fn.Height) then exit;
//x := x mod I_fn.Width;
//y := y mod I_fn.Height;
rx:=x div 16;
ry:=y div 16;
if SpeedButtonMegaCopy.Down then
begin
case megaCopyStatus of
Selecting:
begin
if (ry <= copyRange.Top) then
copyRange.Height := 0
else
copyRange.Bottom := ry;
if (rx <= copyRange.Left) then
copyRange.Width := 0
else
copyRange.Right := rx;
megaCopyStatus := Selected;
//Clipboard_copyExecute(sender);
{shape2.Left := i_fn.left + x - x mod 16 - 2;
shape2.Top := i_fn.Top + y - y mod 16 - 2;
Shape2.Width := Shape1.Width;
Shape2.Height := Shape1.Height;
Shape2.Visible := True;
}
end;
end;
end;
end;
//redraws character that is being edited/selected in character edit window
procedure tMainForm.redrawchar;
var a,b:byte;
character5color:TCharacter5color;
character2color:TCharacter2color;
begin
if not gfx then
begin //gr.0
character2color := Get2ColorCharacter(selectedCharacterIndex);
for a:=0 to 7 do
for b:=0 to 7 do
begin
if character2color[b,a] = 0 then i_ch.Canvas.Brush.Color := palette[cpal[1]]
else i_ch.Canvas.Brush.Color := palette[cpal[0]];
i_ch.Canvas.fillRect(bounds(b*20,a*20,20,20));
i_ch.Canvas.Pixels[b*20,a*20] := clWhite;
end;
end
else
begin //gr.12
character5color := Get5ColorCharacter(selectedCharacterIndex);
for a:=0 to 7 do
for b:=0 to 3 do
begin
i_ch.Canvas.Brush.color := palette[cpal[bits2colorIndex[character5color[b,a]]]];
i_ch.Canvas.fillrect(bounds(b*40,a*20,40,20));
end;
end;
end;
procedure TMainForm.DrawChars(targetImage:TImage; data:string; chars:string; x,y:integer;
dataWidth,dataHeight:integer; gr0:boolean; pixelsize: integer);
var i,j: integer;
begin
for i := 0 to dataheight-1 do
for j := 0 to datawidth-1 do
begin
DrawChar(targetImage, data.Substring((i*dataWidth+j)*16,16), chars.Substring((i*dataWidth+j)*2,2), x+8*pixelsize*j,
y+8*pixelsize*i, gr0, pixelsize);
end;
end;
procedure TMainForm.DrawChar(targetImage:TImage; data:string; char: string; x,y:integer;
gr0:boolean; pixelsize: integer);
var line:byte;
i,j:integer;
bwdata:TCharLine2color;
cldata:TCharLine5color;
inverse:boolean;
begin
inverse := strtoint('$' + char) > 127;
if gr0 then
begin
for i := 0 to 7 do
begin
line := strtoint('$' + data.Substring(i*2,2));
bwdata := DecodeBW(line);
for j := 0 to 7 do
begin
targetImage.Canvas.Brush.Color := palette[cpal[ord(not inverse xor (bwdata[j] = 1))]];
targetImage.Canvas.FillRect(bounds(x+j*pixelsize,y+i*pixelsize,pixelsize,pixelsize));
end;
end;
end
else
begin
for i := 0 to 7 do
begin
line := strtoint('$' + data.Substring(i*2,2));
cldata := DecodeCL(line);
for j := 0 to 3 do
begin
if (inverse) and (cldata[j] = 3) then
targetImage.Canvas.Brush.Color := palette[cpal[5]]
else
targetImage.Canvas.Brush.Color := palette[cpal[1+cldata[j]]];
targetImage.Canvas.FillRect(bounds(x+j*pixelsize*2,y+i*pixelsize,2*pixelsize,pixelsize));
end;
end;
end;
end;
//repaint actual character in font area
procedure TMainForm.DoChar;
var a,b,rx,ry:byte;
line2color:TCharLine2color;
line5color:TCharLine5color;
hp:word;
begin
UpdateUndoButtons(CharacterEdited());
ry:=selectedCharacterIndex div 32;
rx:=selectedCharacterIndex mod 32;
if (ry>3)and(ry<12) then dec(ry,4);
if (ry>11)and(ry<16) then dec(ry,8);
hp := ry*32*8+rx*8;
if not gfx then
begin
for a:=0 to 7 do
begin
line2color := decodeBW(ft[hp + a]);
for b:=0 to 7 do
begin
// if line2color[b] = 1 then i_fn.Canvas.Brush.Color := palette[cpal[0]]
// else i_fn.Canvas.Brush.Color := palette[cpal[1]];
if (hp<1024) then
begin
i_fn.Canvas.Brush.Color := palette[cpal[1 - ord(line2color[b])]];
i_fn.Canvas.FillRect(bounds(rx*16+b*2,ry*16+a*2,2,2));
i_fn.Canvas.Brush.Color := palette[cpal[ord(line2color[b])]];
i_fn.Canvas.FillRect(bounds(rx*16+b*2,ry*16+a*2+64,2,2));
end
else
begin
i_fn.Canvas.Brush.Color := palette[cpal[1 - ord(line2color[b])]];
i_fn.Canvas.FillRect(bounds(rx*16+b*2,ry*16+a*2+64,2,2));
i_fn.Canvas.Brush.Color := palette[cpal[ord(line2color[b])]];
i_fn.Canvas.FillRect(bounds(rx*16+b*2,ry*16+a*2+128,2,2));
end;
end;
end;
end
else
begin
for a:=0 to 7 do
begin
line5color := decodeCL(ft[hp + a]);
for b:=0 to 3 do
begin
if hp<1024 then
begin
i_fn.Canvas.Brush.Color := palette[cpal[bits2colorIndex[line5color[b]]]];
i_fn.Canvas.FillRect(bounds(rx*16+b*4,ry*16+a*2,4,2));
if line5color[b] = 3 then i_fn.Canvas.Brush.Color := palette[cpal[5]];
i_fn.Canvas.FillRect(bounds(rx*16+b*4,ry*16+a*2+64,4,2));
end
else
begin
i_fn.Canvas.Brush.Color := palette[cpal[bits2colorIndex[line5color[b]]]];
i_fn.Canvas.FillRect(bounds(rx*16+b*4,ry*16+a*2+64,4,2));
if line5color[b] = 3 then i_fn.Canvas.Brush.Color := palette[cpal[5]];
i_fn.Canvas.FillRect(bounds(rx*16+b*4,ry*16+a*2+128,4,2));
end;
end;
end;
end;
end;
procedure TMainForm.i_colMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var wh:byte;
ok:boolean;
od:integer;
begin
if AtariColorSelectorForm.GetPalette[1] = clBlack then
AtariColorSelectorForm.SetPalette(palette);
if ssshift in shift then begin
od := Application.MessageBox('Restore default colors?','Atari FontMaker',MB_ICONQUESTION+MB_YESNO);
//od:=Application.messagebox('Restore default colors?','Atari FontMaker',mb_yesno+mb_iconquestion);
if od=idyes then begin;default_pal;redrawpal;gfx:=not gfx;b_gfxclick(nil);end;
end else begin
wh:=x div 45+(y div 18)*2;
AtariColorSelectorForm.SetSelectedColorIndex(cpal[wh]);
AtariColorSelectorForm.ShowModal();
case wh of
0 : begin;
cpal[0] := AtariColorSelectorForm.selectedColorindex mod 16 + (cpal[1] div 16)*16;
end;
1 : begin;
cpal[1] := AtariColorSelectorForm.selectedColorIndex;
cpal[0] := (cpal[1] div 16)*16 + cpal[0] mod 16;
end;
else
cpal[wh] := AtariColorSelectorForm.selectedColorIndex;
end;
end;
redrawpal;
redrawset;
redrawchar;
redrawview;
end;
procedure TMainForm.RevalidateCharButtons();
var i:integer;
begin
if not gfx then
begin
b_colorSwitch.Enabled := false;
b_colorSwSetup.Enabled := false;
for i := 0 to ActionListNormalModeOnly.ActionCount-1 do
if ActionListNormalModeOnly.Actions[i].Tag = 2 then ActionListNormalModeOnly.Actions[i].Enabled := True;
end
else
begin
b_colorSwitch.Enabled := true;
b_colorSwSetup.Enabled := true;
for i := 0 to ActionListNormalModeOnly.ActionCount-1 do
if ActionListNormalModeOnly.Actions[i].Tag = 2 then ActionListNormalModeOnly.Actions[i].Enabled := False;
end;
end;
procedure TMainForm.b_gfxClick(Sender: TObject);
var i:integer;
begin
//b_pst.Enabled:=false;
gfx := not gfx;
redrawset;
redrawview;
i_fnmousedown(nil,mbleft,[],(selectedCharacterIndex mod 32)*16,(selectedCharacterIndex div 32)*16);
if not SpeedButtonMegaCopy.Down then
RevalidateCharButtons;
end;
procedure TMainForm.b_invClick(Sender: TObject);
var a,b:byte;
hp: word;
begin
if not gfx then
begin
hp := GetCharacterPointer(selectedCharacterIndex);
for a:=0 to 7 do
ft[hp + a] := Not ft[hp + a];
DoChar;
RedrawChar;
Redrawviewchar;
end
else
beep;
end;
procedure TMainForm.Ic1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var bu:byte;
begin
bu:=ic1.tag;
ic1.Tag:=ac;
ac:=bu;
redrawpal;
end;
procedure TMainForm.Ic2MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var bu:byte;
begin
bu:=ic2.tag;
ic2.Tag:=ac;
ac:=bu;
redrawpal;
end;
procedure TMainForm.ImageMegacopyMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
I_fnMouseDown(sender,button,shift,
x+ImageMegacopy.Left-i_fn.Left,
y+ImageMegacopy.Top-i_fn.Top);
end;
procedure TMainForm.ImageMegacopyMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
begin
I_fnMouseMove(sender,shift,x+ImageMegacopy.Left-i_fn.Left,
y+ImageMegacopy.Top-i_fn.Top);
end;
procedure TMainForm.ImageMegaCopyVMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
I_viewMouseDown(sender,button,shift,
x+ImageMegacopyV.Left-i_view.Left,
y+ImageMegacopyV.Top-i_view.Top);
end;
procedure TMainForm.ImageMegaCopyVMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
begin
I_viewMouseMove(sender,shift,x+ImageMegacopyV.Left-i_view.Left,
y+ImageMegacopyV.Top-i_view.Top);
end;
procedure TMainForm.Clipboard_copyExecute(Sender: TObject);
begin
Clipboard_copyExecute(Sender, false);
end;
procedure TMainForm.Clipboard_copyExecute(Sender: TObject; sourceIsView: Boolean);
var jo:TJSONObject;
characterBytes,fontBytes:string;
i,j,k,charInFont: Integer;
begin
characterBytes := '';
fontBytes := '';
{memo1.Text := inttostr(copyrange.left) + '-' + inttostr(copyrange.Right) +
' : ' + inttostr(copyRange.Width) + sLineBreak + inttostr(copyrange.top) + '-' + inttostr(copyrange.Bottom) +
' : ' + inttostr(copyRange.Height);
}
if (SpeedButtonMegaCopy.Down and (megaCopyStatus = Selected)) or
(not SpeedButtonMegaCopy.Down) then
begin
if shape1.Visible then sourceisview := false;
if shape1v.Visible then sourceisview := true;
if not shape1.Visible and not shape1v.Visible then exit;
for i := copyRange.Top to copyRange.Bottom do
for j := copyRange.Left to copyRange.Right do
begin
if sourceIsView then
begin
characterBytes := characterBytes + IntToHex(vw[j,i],2);
charInFont := vw[j,i]*8 + (chsline[i]-1)*1024;
end
else
begin
characterBytes := characterBytes + IntToHex(i*32+j mod 256,2);
if (i div 8 = 0) then
charInFont := ((i mod 4)*32+j)*8 //first font
else
charInFont := ((i mod 4 + 4)*32+j)*8; //second font
end;
for k := 0 to 7 do
fontBytes := fontBytes + IntToHex(ft[charInFont+k],2);
end;
jo := TJSONObject.Create();
jo.AddPair(TJSONPair.Create('width',inttostr(copyRange.Width + 1)));
jo.AddPair(TJSONPair.Create('height',inttostr(copyRange.Height + 1)));
jo.AddPair(TJSONPair.Create('chars',characterBytes));
jo.AddPair(TJSONPair.Create('data',fontBytes));
//ShowMessage(jo.ToString);
Clipboard.AsText := jo.ToString;
//RevalidateClipboard;
clipboardLocal := jo.ToString;
jo.Free;
end;
//TODO: change to json format and utilize real clipboard
{
"width": 1,
"height": 1,
"chars": "aa",
"data": "0011223344556677"
}
// https://stackoverflow.com/questions/4350886/how-to-parse-a-json-string-in-delphi
end;
procedure TMainForm.Clipboard_pasteExecute(Sender: TObject);
begin
Clipboard_pasteExecute(Sender, false);
end;
procedure TMainForm.b_pstClick(Sender: TObject);
var jtext:string;
begin
if SpeedButtonMegaCopy.Down then
begin
if Clipboard.AsText <> clipboardLocal then
begin
Shape1.Visible := false;
Shape1v.Visible := false;
end;
RevalidateClipboard;
megaCopyStatus := Pasting;
end
else
begin
Clipboard_pasteExecute(Sender, False);
end;
end;
procedure TMainForm.Clipboard_pasteExecute(Sender: TObject; targetIsView: boolean);
var jtext:string;
width,height:integer;
jo:TJSONObject;
jv:TJSONValue;
characterBytes,fontBytes:string;
i,j,ii,jj,k,charInFont: Integer;
hp:word;
begin
jtext := Clipboard.AsText;
jo := TJSONObject.Create();
jv := jo.ParseJSONValue(jtext);
try
width := jv.GetValue<integer>('width');
height := jv.GetValue<integer>('height');
characterBytes := jv.GetValue<string>('chars');
fontBytes := jv.GetValue<string>('data');
except
showmessage('Clipboard data parsing error');
exit;
end;
if SpeedButtonMegaCopy.Down then
begin
if targetIsView then
begin
for ii := 0 to height-1 do
for jj := 0 to width-1 do
begin
i := ii + copyTarget.Y;
j := jj + copyTarget.X;
vw[j,i] := StrToInt('$' + characterBytes.Substring((ii*width+jj)*2, 2));
end;
redrawview;
end
else
begin
for ii := 0 to height-1 do
for jj := 0 to width-1 do
begin
i := ii + copyTarget.Y;
j := jj + copyTarget.X;
selectedCharacterIndex := i*32+j;
if (i div 8 = 0) then
charInFont := ((i mod 4)*32+j)*8 //first font
else
charInFont := ((i mod 4 + 4)*32+j)*8; //second font
for k := 0 to 7 do
ft[charInFont + k] := StrToInt('$'+fontBytes.Substring(((ii*width+jj)*8 + k)*2,2));
//SetCharCursor;
DoChar;
RedrawChar;
Redrawviewchar;
end;
Add2UndoFullDifferenceScan;
end;
end
else
begin
if width + height > 2 then
begin
ShowMessage('Unable to paste clipboard outside megacopy mode. Clipboard contains ' +
inttostr(width) + 'x' + inttostr(height) + ' data.');
exit;
end;
hp := GetCharacterPointer(selectedCharacterIndex);
for i := 0 to 7 do
ft[hp+i] := StrToInt('$'+fontBytes.Substring(i*2,2));
SetCharCursor;
DoChar;
RedrawChar;
Redrawviewchar;
end;
end;
{
procedure tMainForm.CLtomem;
var a,b,d:byte;
op:TCharLine5color;
begin
for a:=0 to 7 do begin
for b:=0 to 3 do begin
op[b]:=cj[b,a];
end;
d:=encodeCL(op);
ft[hp+a]:=d;
end;
end;
}
procedure TMainForm.b_aboutClick(Sender: TObject);
begin
i_abo.Visible:=not i_abo.Visible;
end;
procedure TMainForm.i_aboMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
//if (x<225)and(y>80) then
OpenURL('http://matosimi.atari.org');
//if (x>295)and(y>80) then shellexecute(form1.handle,'open','mailto:matosimi@centrum.sk','','',sw_show);
i_abo.Visible:=false;
end;
procedure exitowiec();
var re:integer;
begin
re:=Application.messagebox('Are you sure you wanna quit?','Atari FontMaker',mb_iconquestion+mb_yesno);
if re=idyes then Application.Terminate;
end;
procedure TMainForm.RevalidateClipboard();
var jtext:string;
width,height:integer;
jo:TJSONObject;
jv:TJSONValue;
characterBytes,fontBytes:string;
i,j,ii,jj,k,charInFont: Integer;
begin
//exit; //debug
//revalidate content in clipboard
//if (Clipboard.AsText = clipboardLocal) then exit; //no change
jtext := Clipboard.AsText;
jo := TJSONObject.Create();
jv := jo.ParseJSONValue(jtext);
if jv = nil then exit;
try
width := jv.GetValue<integer>('width');
height := jv.GetValue<integer>('height');
characterBytes := jv.GetValue<string>('chars');
fontBytes := jv.GetValue<string>('data');
except
//showmessage('clipboard data parsing error');
exit;
end;
if SpeedButtonMegaCopy.Down then
begin
ImageMegacopy.Width := 16*(width + 0);
ImageMegacopy.Height := 16*(height + 0);
ImageMegacopy.Picture.Bitmap.Width := ImageMegacopy.Width;
ImageMegacopy.Picture.Bitmap.Height := ImageMegacopy.Height;
ImageMegaCopyV.Width := ImageMegacopy.Width;
ImageMegaCopyV.Height := ImageMegacopy.Height;
DrawChars(ImageMegacopy, fontBytes,characterBytes,0,0,Width,Height, not gfx, 2);
ImageMegaCopyV.Picture := ImageMegacopy.Picture;
shape2.Width := 4 + ImageMegacopy.Width;
shape2.Height := 4 + ImageMegacopy.Height;
shape2v.Width := shape2.Width;
shape2v.Height := shape2.Height;
end;
{
megaCopyStatus := Selected;
//hide source frames
if clipboardLocal = Clipboard.AsText then
begin
//show source shape
shape1.Visible := true;
end
else
begin
shape1.Visible := false;
end;
Shape2.Width := 4+16*width;
Shape2.Height := 4+16*height;
Shape2v.Width := Shape2.Width;
Shape2v.Height := Shape2.Height;
end; }
end;
procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
CanClose := False;
exitowiec();
end;
procedure TMainForm.b_newClick(Sender: TObject);
var re:integer;
begin
re:=Application.messagebox('Are you sure to load default character sets?','Atari FontMaker',mb_iconquestion+mb_yesno);
if re=idyes then
begin
fname1:=pathf + PathDelim + 'Default.fnt';
fname2:=fname1;
Load_font(fname1,0);
Load_font(fname2,1);
fdual:=pathf + PathDelim + 'Default.fn2';
if ch_dual.Checked then MainForm.Caption:=title+' - '+extractfilename(fdual)
else MainForm.Caption:=title+' - '+extractfilename(fname1)+'/'+extractfilename(fname2);
RedrawSet;
i_fnmousedown(nil,mbleft,[],(selectedCharacterIndex mod 32)*16,(selectedCharacterIndex div 32)*16);
Redrawview;
end;
end;
procedure TMainForm.b_quitClick(Sender: TObject);
begin
exitowiec();
end;
procedure TMainForm.b_resdClick(Sender: TObject);
var fil:file of byte;
a,pt,snd:byte;
begin
//if cp>127 then pt:=cp-127 else pt:=cp;
pt:=selectedCharacterIndex AND 127;
filemode:=fmopenread;
assignfile(fil,extractfilepath(application.exename)+ PathDelim + 'Default.fnt');
reset(fil);
seek(fil,pt*8);
snd:=ord(selectedCharacterIndex>255);
for a:=0 to 7 do
begin
read(fil,ft[pt*8+a+snd*1024]);
end;
closefile(fil);
dochar;
Redrawviewchar;
i_fnmousedown(nil,mbleft,[],(selectedCharacterIndex mod 32)*16,(selectedCharacterIndex div 32)*16);
end;
procedure TMainForm.b_ressClick(Sender: TObject);
var fil:file of byte;
a,pt,ptr:byte;
filseek:word;
begin
//if cp>127 then pt:=cp-127 else pt:=cp;
pt:=selectedCharacterIndex AND 127;
filemode:=fmopenread;
ptr:=ord(ch_dual.Checked);
if selectedCharacterIndex>255 then ptr:=ptr+2;
//ptr=0:font1 ptr=1:dualfont ptr=2:font2 ptr=3:dual2
case ptr of
0: assignfile(fil,fname1);
1: assignfile(fil,fdual);
2: assignfile(fil,fname2);
3: assignfile(fil,fdual);
end;
reset(fil);
filseek:=pt*8;
if ptr>2 then filseek:=filseek+1024;
seek(fil,filseek);
if ptr=2 then filseek:=filseek+1024;
for a:=0 to 7 do
begin
read(fil,ft[filseek+a]);
end;
closefile(fil);
dochar;
Redrawviewchar;
i_fnmousedown(nil,mbleft,[],(selectedCharacterIndex mod 32)*16,(selectedCharacterIndex div 32)*16);
end;
procedure TMainForm.b_loadClick(Sender: TObject);
var ok:boolean;
b:integer;
fil:file of byte;
begin
d_open.FileName:='';
d_open.InitialDir:=pathf;
d_open.DefaultExt:='fn2';
if ch_dual.Checked then d_open.Filter:='Atari dual font (*.fn2)|*.fn2'
else d_open.Filter:='Atari font 1(*.fnt)|*.fnt|Atari font 2 (*.fnt)|*.fnt';
ok:=d_open.Execute;
if ok then
begin
assignfile(fil,d_open.FileName);
reset(fil);
if ch_dual.Checked then BlockRead(fil,ft,2048,b)
else if d_open.FilterIndex=1 then BlockRead(fil,ft,1024,b)
else BlockRead(fil,ft[1024],1024,b);
if (b<(2048 div (ord(not ch_dual.Checked)+1))) then Application.MessageBox('Not enough data! (bad load file???)','Error',mb_ok+mb_iconwarning);
closefile(fil);
pathf:=extractfilepath(d_open.filename);
if ch_dual.Checked then
fdual:=d_open.filename
else
begin
if d_open.FilterIndex=1 then fname1:=d_open.filename
else fname2:=d_open.filename;
end;
UpdateFormCaption;
redrawset;
i_fnmousedown(nil,mbleft,[],(selectedCharacterIndex mod 32)*16,(selectedCharacterIndex div 32)*16);
redrawview;
Add2UndoFullDifferenceScan(); //full font scan
end;
end;
procedure TMainForm.b_saveClick(Sender: TObject);
var ok:boolean;
b:integer;
fil:file of byte;
begin
d_save.FileName:='';
d_save.initialdir:=pathf;
d_save.DefaultExt:='fn2';
if ch_dual.Checked then d_save.Filter:='Atari dual font (*.fn2)|*.fn2'
else d_save.Filter:='Atari font 1(*.fnt)|*.fnt|Atari font 2 (*.fnt)|*.fnt';
ok:=d_save.Execute;
if ok then begin
assignfile(fil,d_save.FileName);
rewrite(fil);
if ch_dual.Checked then BlockWrite(fil,ft,2048,b)
else if d_save.FilterIndex=1 then BlockWrite(fil,ft,1024,b)
else BlockWrite(fil,ft[1024],1024,b);
closefile(fil);
pathf:=extractfilepath(d_save.filename);
if ch_dual.Checked then
fdual:=d_save.filename
else
begin
if d_save.FilterIndex=1 then fname1:=d_save.filename
else fname2:=d_save.filename;
end;
UpdateFormCaption;
end;
end;
procedure TMainForm.b_clrClick(Sender: TObject);
var a,b:byte;
hp: word;
begin
hp := GetCharacterPointer(selectedCharacterIndex);
for a:=0 to 7 do
ft[hp + a] := 0;
DoChar;
RedrawChar;
Redrawviewchar;
end;
procedure TMainForm.b_clrviewClick(Sender: TObject);
var a,b:byte;
ok:integer;
begin
ok:=Application.messagebox('Clear view window?','Atari FontMaker',mb_yesno+mb_iconquestion);
if ok=idyes then begin
for a:=0 to 31 do begin
for b:=0 to 25 do begin
vw[a,b]:=0;
end;
end;
redrawview;
end;
end;
procedure TMainForm.i_viewMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var rx,ry,bx,by:byte;
znak:word;
begin
if (x >= i_view.Width) or (y >= i_view.Height) then exit;
rx:=x div 16;
ry:=y div 16;
if SpeedButtonMegaCopy.Down then
begin
case megaCopyStatus of
None,Selected:
begin
if ssLeft in Shift then
begin
//define copy origin point
copyRange.Top := ry;
copyRange.Left := rx;
megaCopyStatus := Selecting;
shape1v.Left := i_view.left + x - x mod 16 - 2;
shape1v.Top := i_view.Top + y - y mod 16 - 2;
shape1v.Width := 20;
shape1v.Height := 20;
shape1v.Visible := true;
shape1.Visible := false;
end;
end;
{ Selecting:
begin
shape1v.Visible := true;
end; }
Pasting:
begin
if not MouseValidView(x,y) then exit;
//paste
if (ssLeft in Shift) then
begin
copyTarget := Point(rx,ry);
Clipboard_pasteExecute(Sender, true);
ResetMegaCopyStatus;
end;
//reset selection by right doubleclick
if (ssDouble in Shift) and (ssRight in Shift) then
ResetMegaCopyStatus;
end;
end;
end
else
begin
clckv:=true;
if ssCtrl in Shift then clckv := false; //ctrl+click nezapina toggle
if ry >= i_view.Height div 16 then exit;
clxv := rx;
clyv := ry;
if Button=mbLeft then
begin
vw[rx,ry]:=selectedCharacterIndex mod 256;
redrawviewchar;
end;
if Button=mbRight then
begin
znak:=vw[rx,ry];
bx:=znak mod 32;
by:=znak div 32;
if chsline[ry]=2 then by:=by OR 8;
i_fnMouseDown(nil,mbLeft,[],bx*16+4,by*16+4);
end;
end;
end;
procedure TMainForm.i_viewMouseLeave(Sender: TObject);
begin
shape2v.Visible := false;
ImageMegaCopyV.Visible := false;
end;
//TColor > palette index approximator
function FindClosest(rr,gg,bb:byte;pal:AtariColorSelector.TMyPalette):byte;
var dist:array[0..2] of integer;
best,i,j:byte;
Color: Longint;
r, g, b: Byte;
bestDistance,newDistance: longint;
begin
bestDistance := 9999999;
for j := 0 to 127 do
begin
i := j*2; //only compare with EVEN palette indexes
Color := ColorToRGB(pal[i]);
r := Color;
g := Color shr 8;
b := Color shr 16;
dist[0] := rr - r;
dist[1] := gg - g;
dist[2] := bb - b;
newDistance := dist[0]*dist[0]+dist[1]*dist[1]+dist[2]*dist[2];
if bestDistance > newDistance then
begin
bestDistance := newDistance;
best := i;
end;
end;
Result := best;
end;
//save view file new edition
procedure TMainForm.SaveViewFile(filename:string);
var jo:TJSONObject;
characterBytes,lineTypes,colors,fontBytes:string;
i,j,k,charInFont: Integer;
fil:textfile;
begin
characterBytes := '';
lineTypes := '';
colors := '';
fontBytes := '';
jo := TJSONObject.Create();
//version
jo.AddPair(TJSONPair.Create('version','1911'));
//gfxmode
jo.AddPair(TJSONPair.Create('coloredGfx',IntToStr(ord(gfx))));
//characters
for i := 0 to 25 do
for j := 0 to 31 do
characterBytes := characterBytes + IntToHex(vw[j,i],2);
charInFont := vw[j,i]*8 + (chsline[i]-1)*1024;
jo.AddPair(TJSONPair.Create('chars',characterBytes));
//line types
for i := 0 to 25 do
lineTypes := lineTypes + IntToHex(chsline[i]-1,2);
jo.AddPair(TJSONPair.Create('lines',lineTypes));
//colors
for i := 0 to 5 do
colors := colors + IntToHex(cpal[i]);
jo.AddPair(TJSONPair.Create('colors',colors));
//fontnames
jo.AddPair(TJSONPair.Create('fontname1',fname1));
jo.AddPair(TJSONPair.Create('fontname2',fname2));
jo.AddPair(TJSONPair.Create('fontdualname',fdual));
//fontdata
for i := 0 to 2047 do
fontBytes := fontBytes + IntToHex(ft[i],2);
jo.AddPair(TJSONPair.Create('data',fontBytes));
AssignFile(fil, filename);
Rewrite(fil);
Write(fil,jo.ToString());
CloseFile(fil);
end;
procedure TMainForm.LoadViewFile(filename:string);
var jtext:string;
coloredGfx,version:integer;
filenames:array[0..2] of string;
jo:TJSONObject;
jv:TJSONValue;
characterBytes,lineTypes,colors,fontBytes:string;
i,j,ii,jj,k,charInFont: Integer;
hp:word;
fil:textfile;
begin
AssignFile(fil, filename);
Reset(fil);
Read(fil,jtext);
CloseFile(fil);
jo := TJSONObject.Create();
jv := jo.ParseJSONValue(jtext);
try
version := jv.GetValue<integer>('version');
except
showmessage('Viewfile broken');
exit;
end;
if version = 1911 then
begin
try
characterBytes := jv.GetValue<string>('chars');
lineTypes := jv.GetValue<string>('lines');
colors := jv.GetValue<string>('colors');
fontBytes := jv.GetValue<string>('data');
filenames[0] := jv.GetValue<string>('fontname1');
filenames[1] := jv.GetValue<string>('fontname2');
filenames[2] := jv.GetValue<string>('fontdualname');
coloredGfx := jv.GetValue<integer>('coloredGfx');
except
on E : Exception do
begin
showmessage('Viewfile broken: ' + E.Message);
exit;
end;
end;
for ii := 0 to 25 do
begin
chsline[ii] := StrToInt('$' + lineTypes.Substring(ii*2,2)) + 1;
for jj := 0 to 31 do
vw[jj,ii] := StrToInt('$' + characterBytes.Substring((ii*32+jj)*2, 2));
end;
for i := 0 to 5 do
cpal[i] := StrToInt('$' + colors.Substring(i*2, 2));
gfx := coloredGfx = 1;
if Application.MessageBox('Would you like to load fonts embedded in this view file?','Load embedded fonts',MB_YESNO) = IDYES then
begin
fname1 := filenames[0];
fname2 := filenames[1];
fdual := filenames[2];
for i := 0 to 2047 do
ft[i] := StrToInt('$' + fontBytes.Substring(i*2,2));
UpdateFormCaption;
Add2UndoFullDifferenceScan(); //full font scan
end;
end;
end;
procedure TMainForm.b_lviewClick(Sender: TObject);
var fil:file of byte;
a,c:byte;
version:byte;
b:integer;
rr,gg,bb:byte;
ok:boolean;
buf:array[0..2047] of byte;
begin
d_open.FileName:='';
d_open.InitialDir:=pathf;
d_open.Filter:='Atari FontMaker View (*.atrview|*.atrview|Atari FontMaker View (*.vf2)|*.vf2|Atari FontMaker View OLD (*.vfn)|*.vfn';
ok:=d_open.Execute;
if ok then
begin
if d_open.FilterIndex = 1 then //handle new json version of view file
begin
LoadViewFile(d_open.FileName);
pathf := extractfilepath(d_open.filename);
redrawset;
redrawview;
redrawpal;
redrawviewchar;
Exit;
end;
assignfile(fil,d_open.filename); //handle old binary versions of view file
reset(fil);
if d_open.FilterIndex=2 then
begin
read(fil,version);
if version>3 then
begin
Application.MessageBox('File was created in newer version of FontMaker (bad load file???)','Error',mb_ok+mb_iconerror);
Exit;
end;
end;
read(fil,c);
if c=0 then gfx:=true else gfx:=false;
b_gfxclick(nil);
if d_open.FilterIndex=2 then
for a:=0 to 7 do read(fil,chsline[a]);
for a:=0 to 5 do
begin
read(fil,rr,gg,bb);
cpal[a] := FindClosest(rr,gg,bb,palette);
end;
if d_open.FilterIndex=2 then //vf2
begin
case version of
2: begin;
BlockRead(fil,buf,248,b);
for a:=0 to 7 do
for b:=0 to 30 do vw[b,a]:=buf[a*31+b];
//cislo fontu
for a:=0 to 7 do i_chset.Canvas.TextOut(4,2+a*16,inttostr(chsline[a]));
end;
3: begin;
BlockRead(fil,buf,32*26,b);
for a:=0 to 25 do
for b:=0 to 31 do vw[b,a]:=buf[a*32+b];
//cislo fontu
for a:=0 to 25 do i_chset.Canvas.TextOut(4,2+a*16,inttostr(chsline[a]));
end;
end;
end
else //vfn
begin
BlockRead(fil,buf,186,b);
for b:=0 to 30 do
begin
for a:=0 to 5 do vw[b,a]:=buf[a+b*6];
for a:=6 to 7 do vw[b,a]:=0;
end;
end;
closefile(fil);
redrawset;
redrawview;
redrawpal;
redrawviewchar;
pathf := extractfilepath(d_open.filename);
end;
end;
procedure TMainForm.b_sviewClick(Sender: TObject);
var ok:boolean;
begin
d_save.FileName:='';
d_save.InitialDir:=pathf;
d_save.DefaultExt:='atrview';
d_save.Filter:='Atari FontMaker View (*.atrview|*.atrview';
ok:=d_save.Execute;
if ok then
begin
SaveViewFile(d_save.FileName);
{ assignfile(fil,d_save.filename);
rewrite(fil);
a:=3;write(fil,a); //verzia view dat (3 - 20.6.2013)
a:=ord(gfx);
write(fil,a);
if d_save.FilterIndex=1 then
for a:=0 to 7 do write(fil,chsline[a]);
for a:=1 to 6 do
begin
} {rr:=getrvalue(cpal[a]);
gg:=getgvalue(cpal[a]);
bb:=getbvalue(cpal[a]);}
//todo: conversion
{ write(fil,rr,gg,bb);
end;
for b:=0 to 25 do begin
for a:=0 to 31 do begin
write(fil,vw[a,b]);
end;
end;
}
pathf:=extractfilepath(d_save.filename);
//closefile(fil);
end;
end;
procedure TMainForm.i_chMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var nx,ny:integer;
je:boolean;
begin
je:=false;
if clck then begin
ny:=y div 20;
if gfx then nx:=x div 40 else nx:=x div 20;
if (x<0)or(x>i_ch.Width)or(y<0)or(y>i_ch.Height) then je:=true;
if (not je)and((nx<>clx)or(ny<>cly)) then i_chmousedown(nil,buttonHeld,[],x,y);
end;
end;
procedure TMainForm.i_chMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
clck:=false;
end;
procedure TMainForm.i_chsetMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var ry,a:byte;
begin
ry:=Y div 16;
if chsline[ry]=2 then chsline[ry]:=1 else chsline[ry]:=2;
for a:=0 to 25 do i_chset.Canvas.TextOut(4,2+a*16,inttostr(chsline[a]));
RedrawView;
end;
procedure TMainForm.UpdateFormCaption();
begin
if ch_dual.Checked then
begin
MainForm.Caption:=title+' - '+extractfilename(fdual);
b_savedual.Visible:=true;
b_save1.Visible:=false;
b_save2.Visible:=false;
end
else
begin
MainForm.Caption:=title+' - '+extractfilename(fname1)+'/'+extractfilename(fname2);
b_savedual.Visible:=false;
b_save1.Visible:=true;
b_save2.Visible:=true;
end;
end;
procedure TMainForm.ch_dualClick(Sender: TObject);
begin
UpdateFormCaption;
end;
procedure TMainForm.b_save1Click(Sender: TObject);
var fil:file of byte;
b:integer;
begin
assignfile(fil,fname1);
rewrite(fil);
BlockWrite(fil,ft,1024,b);
closefile(fil);
end;
procedure TMainForm.b_save2Click(Sender: TObject);
var fil:file of byte;
b:integer;
begin
assignfile(fil,fname2);
rewrite(fil);
BlockWrite(fil,ft[1024],1024,b);
closefile(fil);
end;
procedure TMainForm.b_savedualClick(Sender: TObject);
var fil:file of byte;
b:integer;
begin
assignfile(fil,fdual);
rewrite(fil);
BlockWrite(fil,ft,2048,b);
closefile(fil);
end;
procedure TMainForm.b_shdClick(Sender: TObject);
var src,tmp:TCharacter2color;
tn:TCharacter5color;
a,b,h:byte;
begin
src := Get2ColorCharacter(selectedCharacterIndex);
for a:=0 to 7 do
begin
for b:=0 to 7 do
begin
if a > 0 then h := a - 1 else h := 7;
tmp[b,a] := src[b,h];
end;
end;
Set2ColorCharacter(tmp,selectedCharacterIndex);
DoChar;
RedrawChar;
Redrawviewchar;
end;
procedure TMainForm.b_shrClick(Sender: TObject);
var src,tmp:TCharacter2color;
a,b,h,i:byte;
repeatTime:byte;
begin
repeatTime := ord(gfx); //perform same shift twice in mode 4
src := Get2ColorCharacter(selectedCharacterIndex);
for i := 0 to repeatTime do
begin
for a:=0 to 7 do
begin
for b:=0 to 7 do
begin
if b > 0 then h := b - 1 else h := 7;
tmp[b,a] := src[h,a];
end;
end;
src := tmp;
end;
Set2ColorCharacter(tmp,selectedCharacterIndex);
DoChar;
RedrawChar;
Redrawviewchar;
end;
procedure TMainForm.b_shuClick(Sender: TObject);
var src,tmp:TCharacter2color;
tn:TCharacter5color;
a,b,h:byte;
begin
src := Get2ColorCharacter(selectedCharacterIndex);
for a:=0 to 7 do
begin
for b:=0 to 7 do
begin
if a < 7 then h := a + 1 else h := 0;
tmp[b,a] := src[b,h];
end;
end;
Set2ColorCharacter(tmp,selectedCharacterIndex);
DoChar;
RedrawChar;
Redrawviewchar;
end;
procedure TMainForm.Timer1Timer(Sender: TObject);
begin
i_abo.Visible:=false;
Timer1.Enabled:=false;
end;
procedure TMainForm.FormMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var bx,by,nextCharacterIndex:integer;
begin
if not SpeedButtonMegaCopy.Down then
begin
if ssMiddle in Shift then
begin
if WheelDelta > 0 then
Ic1MouseDown(nil,mbLeft,[],0,0)
else
Ic2MouseDown(nil,mbLeft,[],0,0);
Handled := true;
end
else
begin
if WheelDelta > 0 then
nextCharacterIndex := selectedCharacterIndex - 1
else
nextCharacterIndex := selectedCharacterIndex + 1;
nextCharacterIndex := nextCharacterIndex mod 512;
bx := nextCharacterIndex mod 32;
by := nextCharacterIndex div 32;
i_fnMouseDown(nil,mbLeft,[],bx*16+4,by*16+4);
Handled := true;
end;
end;
end;
{Form 2 Function moved
procedure saveFontBMP(fi:integer;fn:string;bmp1:tbitmap);//img:timage);
var bmp2:tbitmap;
x,y:byte;
fntIndex:integer;
begin
if fi = 1 then
fntIndex := 0
else
fntIndex := 128;
bmp2 := TBitmap.Create;
bmp2.PixelFormat:=pf24bit;
bmp2.Width := 256;
bmp2.Height := 64;
for y := 0 to 63 do
for x := 0 to 255 do
begin
bmp2.Canvas.Pixels[x,y] := bmp1.Canvas.Pixels[x*2,y*2 + fntIndex];
end;
//img.Picture.Graphic := bmp2; //debug
bmp2.SaveToFile(fn);
end;
}
procedure TMainForm.b_exportBMPClick(Sender: TObject);
begin
ExportWindowForm.MemoExport.Text := '';
ExportWindowForm.ShowModal;
end;
procedure TMainForm.b_colorSwSetupClick(Sender: TObject);
begin
p_color_switch.Visible := not p_color_switch.Visible;
end;
procedure TMainForm.SetColor(colorNum: Integer);
begin
//colorNum := colorNum + 2; //added offset in font palette
if ac <> colorNum then
begin
if Ic1.Tag = colorNum then
Ic1MouseDown(nil,mbLeft,[],0,0)
else
Ic2MouseDown(nil,mbLeft,[],0,0);
end;
end;
procedure TMainForm.Shape1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
//memo1.Text := memo1.Text + 'X:' + inttostr(x) + ' Y:' + inttostr(y);
I_fnMouseDown(Sender, Button, Shift, X + shape1.Left - i_fn.left, Y + shape1.Top - i_fn.top);
end;
procedure TMainForm.Shape1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
i_fnMouseMove(Sender, Shift, X + shape1.Left - i_fn.left, Y + shape1.Top - i_fn.top);
end;
procedure TMainForm.Shape1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
I_fnMouseUp(Sender, Button, Shift, X + shape1.Left - i_fn.left, Y + shape1.Top - i_fn.top);
end;
procedure TMainForm.Shape1vMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
I_viewMouseDown(Sender, Button, Shift, X + shape1v.Left - i_view.left, Y + shape1v.Top - i_view.top);
end;
procedure TMainForm.Shape1vMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
I_viewMouseMove(Sender, Shift, X + shape1v.Left - i_view.left, Y + shape1v.Top - i_view.top);
end;
procedure TMainForm.Shape1vMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
I_viewMouseUp(Sender, Button, Shift, X + shape1v.Left - i_view.left, Y + shape1v.Top - i_view.top);
end;
procedure TMainForm.Shape2vMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
i_viewMouseDown(nil,button,shift,shape2v.Left+x-i_view.Left,shape2v.Top+Y-i_view.top);
end;
procedure TMainForm.Shape2vMouseLeave(Sender: TObject);
begin
Shape2v.Visible := false;
ImageMegaCopyV.Visible := false;
end;
procedure TMainForm.Shape2vMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
i_viewMouseMove(nil,shift,shape2v.Left+x-i_view.Left,shape2v.Top+y-i_view.Top);
end;
procedure TMainForm.Shape2vMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
i_viewMouseUp(nil,Button,Shift,shape2v.Left+x-i_view.Left,shape2v.Top+Y-i_view.top);
end;
procedure TMainForm.Shape2MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
i_fnMouseDown(nil,button,shift,shape2.Left+x-i_fn.Left,shape2.Top+Y-i_fn.top);
end;
procedure TMainForm.Shape2MouseLeave(Sender: TObject);
begin
Shape2.Visible := false;
ImageMegacopy.Visible := false;
end;
procedure TMainForm.Shape2MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
i_fnMouseMove(nil,shift,shape2.Left+x-i_fn.Left,shape2.Top+y-i_fn.Top);
end;
procedure TMainForm.Shape2MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
i_fnMouseUp(nil,Button,Shift,shape2.Left+x-i_fn.Left,shape2.Top+Y-i_fn.top);
end;
procedure TMainForm.SpeedButtonMegaCopyClick(Sender: TObject);
var ena:boolean;
action:TContainedAction;
bx,by:integer;
begin
//enable/disable actions between modes
ena := SpeedButtonMegaCopy.Down;
//hide character edit window
i_ch.Visible := not ena;
for action in ActionListNormalModeOnly do
action.Enabled := not ena;
if ena then
begin
megaCopyStatus := None;
b_colorSwitch.Enabled := false;
b_colorSwSetup.Enabled := false;
end
else
begin
shape1.Width := 20;
shape1.Height := 20;
shape1.Visible := true;
shape1v.Visible := false;
shape2v.Width := 20;
shape2v.Height := 20;
bx := selectedCharacterIndex mod 32;
by := selectedCharacterIndex div 32;
i_fnMouseDown(nil,mbLeft,[],bx*16+4,by*16+4);
RevalidateCharButtons;
end;
end;
procedure TMainForm.SpeedButtonRedoClick(Sender: TObject);
begin
if not Redo() then beep;
end;
procedure TMainForm.SpeedButtonUndoClick(Sender: TObject);
begin
if not Undo() then beep;
end;
procedure TMainForm.Color1Execute(Sender: TObject);
begin
SetColor(2);
end;
procedure TMainForm.Color2Execute(Sender: TObject);
begin
SetColor(3);
end;
procedure TMainForm.Color3Execute(Sender: TObject);
begin
SetColor(4);
end;
procedure TMainForm.ColorSwitch(idx1:integer;idx2:integer);
var x,y:integer;
src:TCharacter5color;
begin
src := Get5ColorCharacter(selectedCharacterIndex);
for y:=0 to 7 do
for x:=0 to 3 do
begin
if src[x][y] = idx1 then
src[x][y] := idx2
else
if src[x][y] = idx2 then
src[x][y] := idx1;
end;
Set5ColorCharacter(src, selectedCharacterIndex);
{
ow[x] := cj[x,y];
//switch:
if cj[x,y] = idx1 then
ow[x] := idx2;
if cj[x,y] = idx2 then
ow[x] := idx1;
cj[x,y] := ow[x];
end;
ft[hp + y] := encodeCL(ow);
end;
}
DoChar;
redrawchar;
redrawview;
end;
//button renamed to RECOLOR
procedure TMainForm.b_colorSwitchClick(Sender: TObject);
begin
ColorSwitch(lb_cs1.ItemIndex, lb_cs2.ItemIndex);
end;
procedure TMainForm.lb_cs1Click(Sender: TObject);
begin
i_rec1.Canvas.Brush.Color := palette[cpal[lb_cs1.ItemIndex + 1]];
i_rec1.Canvas.FillRect(bounds(0,0,49,17));
drawTxt(i_rec1,1,1,lb_cs1.ItemIndex + 2,palette[cpal[lb_cs1.ItemIndex + 1]]);
end;
procedure TMainForm.lb_cs2Click(Sender: TObject);
begin
i_rec2.Canvas.Brush.Color := palette[cpal[lb_cs2.ItemIndex + 1]];
i_rec2.Canvas.FillRect(bounds(0,0,49,17));
drawTxt(i_rec2,1,1,lb_cs2.ItemIndex + 2,palette[cpal[lb_cs2.ItemIndex + 1]]);
end;
procedure TMainForm.i_viewMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
rx,ry:integer;
begin
clckv:=false;
if (x >= i_fn.Width) or (y >= i_fn.Height) then exit;
//x := x mod I_fn.Width;
//y := y mod I_fn.Height;
rx:=x div 16;
ry:=y div 16;
if SpeedButtonMegaCopy.Down then
begin
case megaCopyStatus of
Selecting:
begin
if (ry <= copyRange.Top) then
copyRange.Height := 0
else
copyRange.Bottom := ry;
if (rx <= copyRange.Left) then
copyRange.Width := 0
else
copyRange.Right := rx;
megaCopyStatus := Selected;
//Clipboard_copyExecute(sender,true);
{shape2.Left := i_fn.left + x - x mod 16 - 2;
shape2.Top := i_fn.Top + y - y mod 16 - 2;
Shape2.Width := Shape1.Width;
Shape2.Height := Shape1.Height;
Shape2.Visible := True;
}
end;
end;
end;
end;
procedure TMainForm.i_viewMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var je:boolean;
rx,ry,temp:integer;
begin
{ nx:=x div 16;
ny:=y div 16;
if (ny >= i_view.Height div 16) or (nx >= i_view.Width div 16) then exit;
}
if SpeedButtonMegaCopy.Down then
begin
case megaCopyStatus of
{ none:
begin
shape1v.Left := i_view.Left + nx*16 - 2;
shape1v.Top := i_view.Top + ny*16 - 2;
shape1v.Width := 20;
shape1v.Height := 20;
shape1v.Visible := true;
end; }
Selecting:
begin
if (x >= i_view.Width) or (y >= i_view.Height) then exit;
rx:=x div 16;
ry:=y div 16;
temp := (rx - copyRange.Left + 1) * 16 + 4;
if temp < 20 then shape1v.Width := 20
else shape1v.Width := temp;
temp := (ry - copyRange.Top + 1) * 16 + 4;
if temp < 20 then shape1v.Height := 20
else shape1v.Height := temp;
end;
Pasting:
begin
if not MouseValidView(X,Y) then
begin
Shape2v.Visible := false;
ImageMegaCopyV.Visible := false;
exit;
end;
shape2v.Left := i_view.Left + x - x mod 16 - 2;
shape2v.Top := i_view.Top + y - y mod 16 - 2;
shape2v.Visible := true;
ImageMegaCopyV.Visible := true;
shape2.Visible := false;
ImageMegacopy.Visible := false;
ImageMegaCopyV.Left := shape2v.Left + 2;
ImageMegaCopyV.Top := shape2v.Top + 2;
end;
end;
end
else
begin
je:=false;
//if (ny >= i_view.Height div 16) or (nx >= i_view.Width div 16) then exit;
if clckv then begin
if (x<0)or(x>i_view.Width)or(y<0)or(y>i_view.Height) then je:=true;
if (not je)and((x div 16<>clxv)or(y div 16<>clyv)) then i_viewmousedown(nil,mbleft,[],x,y);
end;
shape2v.Width := 20;
shape2v.Height := 20;
shape2v.Left := i_view.Left + x - x mod 16 - 2;
shape2v.Top := i_view.Top + y - y mod 16 - 2;
shape2v.Visible := true;
end;
end;
end.