From b4d56fa979e9efc2c3cf24aa878e7ab6eff8d464 Mon Sep 17 00:00:00 2001 From: Wizzup? Date: Fri, 4 Dec 2009 20:57:00 +0000 Subject: [PATCH] Changes in doc and code. git-svn-id: http://www.villavu.com/repositories/merlijn/mufasa@267 3f818213-9676-44b0-a9b4-5e4c4e03d09d --- Doc/mufasa_handbook.tex | 19 +++++-- Doc/mufasa_ps_handbook.tex | 69 ++++++++++++++++++++++++ Projects/MufasaTests/project1.lpr | 63 ++++++++++++++++------ Tests/PS/FileTests.mufa | 90 +++++++++++++++++++++++++++++++ Units/MMLCore/dtm.pas | 16 +++++- Units/MMLCore/dtmutil.pas | 4 ++ Units/MMLCore/finder.pas | 28 ---------- Units/MMLCore/mufasatypes.pas | 1 + Units/MMLCore/ocr.pas | 3 +- 9 files changed, 244 insertions(+), 49 deletions(-) create mode 100644 Tests/PS/FileTests.mufa diff --git a/Doc/mufasa_handbook.tex b/Doc/mufasa_handbook.tex index bb293db..8ab312c 100644 --- a/Doc/mufasa_handbook.tex +++ b/Doc/mufasa_handbook.tex @@ -21,15 +21,14 @@ Developer notes include: \item Bugs \end{itemize} - \chapter{Core} \section{TClient} The TClient class bundles all the other Core classes. It's main use is to make using the Mufasa Macro Library trivial, by bundling -the for Mufasa classes into one class, and provides the methods to make them -cooperate. +the core Mufasa classes into one class, and providing the methods to make those +classes cooperate. \section{TMWindow} @@ -48,6 +47,20 @@ Retreiving information from the target Application/Window. \section{TMDTM} +The TMDTM class is a DTM manager. It provides methods to add, store, load +and free DTM's. It has a few few other features. One of it's other features +is keeping track of what DTMs are unfreed. It can, for example, help you find +a bug in your code, by printing out information of the DTM that you forgot to +free. You can also give names to DTMs, which eases debugging further. + +If you try to access an invalid DTM, the MML will throw an exception. + + +\subsection{AddDTM} +\subsection{GetDTM} +\subsection{DTMFromString} +\subsection{FreeDTM} + \section{TMOCR} \chapter{Add on} diff --git a/Doc/mufasa_ps_handbook.tex b/Doc/mufasa_ps_handbook.tex index 47f4ed1..16e2b09 100644 --- a/Doc/mufasa_ps_handbook.tex +++ b/Doc/mufasa_ps_handbook.tex @@ -19,6 +19,75 @@ the Mufasa macro library exports to it's Interpreter, PS\footnote{Pascal Script}. For a real in depth explanation, the Mufasa Handbook would be a better place to look. +\chapter{Exceptions} + +\section{Motivation} +Mufasa takes debugging to a new level by using exceptions for error handling, +this allows you to even catch possible errors in your script, thus allowing +the script to continue it's exection. We strongly believe Exceptions are the +way to go. They were implemented for a reason. + +\section{When do we throw Exceptions} + +There are a lot of occasions where Mufasa may throw exceptions. + +Consider the following program: + +\begin{verbatim} +program new; +var + bmp:integer; + x, y:integer; +begin + bmp:=bitmapfromstring(200, 200, ''); + x := -1; + y := -1; + fastsetpixel(bmp, x, y, clwhite); +end. +\end{verbatim} + +This code is, always invalid. If you try this in SCAR, it will execute and do +nothing. \\ + +Very useful, right? \\ + +Now, when we execute the same code with MML, we get this: + +\begin{verbatim} +Error: Exception: You are accessing an invalid point, (-1,-1) at bitmap[0] at line 8 +\end{verbatim} + +Further expanding the example: +\begin{verbatim} +\end{verbatim} + +Results in: + +\begin{verbatim} +Compiled succesfully in 8 ms. +We failed to do a setpixel with x = .-1, y = -1 +Succesfully executed +\end{verbatim} + +\subsection{Going beyond script debugging} +Exceptions are even in the very core of Mufasa. This greatly improves +debugging in general, as we will also be able to easily spot errors in Mufasa. +When they occured, what the values of the variables were, et cetera. + +Let's look at a function known as ReturnData(), which returns the client data. +It for example checks if the points that are passed are consistent. +If they are not, an Exception is thrown. If Mufasa does not catch that +particular Exception\footnote{Which it doesn't, as a feature.}, then it will +be thrown in your script. This will indicate that somehow ReturnData got +invalid coordinates. Usually this Exception is not throw, as other functions +also check their input for sanity, and then it is possible to throw a more +detailed exception. + +\subsection{How to Handle Exceptions} + +An exception is handled with a $try$ ... $except$ ... $finally$ statement. +See the example in the previous section for more details. + \chapter{Input} \section{Mouse} diff --git a/Projects/MufasaTests/project1.lpr b/Projects/MufasaTests/project1.lpr index f1fdbea..da4d6bb 100644 --- a/Projects/MufasaTests/project1.lpr +++ b/Projects/MufasaTests/project1.lpr @@ -10,7 +10,7 @@ uses Forms,Interfaces, LCLIntf, Client, - bitmaps,x ,mufasatypes,dtm,dtmutil + bitmaps,x ,mufasatypes,dtm,dtmutil, ocrutil { you can add units after this }; @@ -30,6 +30,28 @@ type { MufasaTests } +const + CW = 800; + CH = 600; + +function randomdtm(a: integer): pdtm; +var + i: integer; +begin + initdtm(result, a); + for i := 1 to result.l - 1 do + begin + result.p[i] := point(random(30) - 15, random(30) - 15); + result.c[i] := 0; + result.t[i] := random(255); + result.asz [i] := random(5); + result.ash[i] := 0; + writeln(format('dtm: (%d, %d) c: %d, t: %d, asz: %d', [result.p[i].x, + result.p[i].y, result.c[i], result.t[i], result.asz[i]])); + end; + result.c[0] := 255; +end; + procedure MufasaTests.DoRun; var @@ -61,38 +83,47 @@ begin C := TClient.Create; bmp := TMufasaBitmap.Create; - bmp.SetSize(800,600); - FillChar(bmp.FData[0],sizeof(trgb32)*800*600, 0); + bmp.SetSize(CW,CH); + Writeln(Format('Client W/H: %d, %d', [CW, CH])); + FillChar(bmp.FData[0],sizeof(trgb32)*CW*CH, 0); Randomize; - for i := 0 to 200 do - bmp.fastsetpixel(random(800), random(600), 255); - {bmp.FastSetPixel(8,8,255); + for i := 0 to 500 do + bmp.fastsetpixel(random(CW), random(CH), 255); + { bmp.FastSetPixel(8,8,255); bmp.FastSetPixel(9,9,255); bmp.FastSetPixel(7,7,255); bmp.FastSetPixel(9,8,255); - bmp.FastSetPixel(8,9,255); } + bmp.FastSetPixel(8,9,255); } C.MWindow.SetTarget(bmp); - initdtm(dtm, 3); + { initdtm(dtm, 5); dtm.p[0] := Point(2, 2); dtm.p[1] := Point(-3, -3); dtm.p[2] := Point(0, 0); + dtm.p[3] := Point(1, 1); + dtm.p[4] := Point(3, 3); dtm.c[0] := 255; - dtm.t[0] := 255; + dtm.t[0] := 0; dtm.asz[1] := 1; - dtm.ash[1] := dtm_Rectangle; + dtm.ash[1] := dtm_Rectangle; } - setlength(p, 1); + dtm := randomdtm(20); + + // setlength(p, 1); + time := GetTickCount; + C.MFinder.FindDTMs(dtm, p, 0, 0,CW-1, CH-1, 0); + writeln(inttostr(gettickcount - time) + 'ms'); + setlength(p,0); time := GetTickCount; - C.MFinder.FindDTMs(dtm, p, 0, 0,799, 599, 0); - //C.MFinder.FindDTM(dtm, p[0].x, p[0].y, 0, 0,799, 599); - writeln(inttostr(gettickcount - time)); - writeln(inttostr(length(p))); + C.MFinder.FindDTMs(dtm, p, 0, 0,CW-1, CH-1, 0); + //C.MFinder.FindDTM(dtm, p[0].x, p[0].y, 0, 0,CW-1, CH-1); + writeln(inttostr(gettickcount - time) + 'ms'); + writeln(inttostr(length(p))+ ' points found'); {for i := 0 to high(p) do - writeln(format('%d: (%d, %d)', [i, p[i].x, p[i].y])); } + writeln(format('%d: (%d, %d)', [i, p[i].x, p[i].y])); } //bmp.OnDestroy:=nil; diff --git a/Tests/PS/FileTests.mufa b/Tests/PS/FileTests.mufa new file mode 100644 index 0000000..5135302 --- /dev/null +++ b/Tests/PS/FileTests.mufa @@ -0,0 +1,90 @@ +program Hoi; + +{ + Description: Test file to test the consistency of + the following Functions: + + AppPath, DirectoryExists, FileExists, ExeExt, + DirectorySeperator, OpenFile, CreateFile, RewriteFile, + WriteFileString, ReadFileString, SetFileCharPointer, + FileSize, EndOfFile, FileContents. + + Notes: + Needs: GetFiles. + + Bugs: + Using ./test as TestPath crashes on Linux. + Usage: + Run it. Set the TestPath to a different directory if you are on Windows. :) +} + +Const + TestPath = './test'; + + fsFromBeginning = 0; // offset must be pos or 0 + fsFromCurrent = 1; // offset pos or neg + fsFromEnd = 2; // offset only neg or 0 + +var + s, s2: string; + myFile, myFile2: Integer; + +begin + s := apppath; + Writeln('Our current path is: ' + s); + { If DirectoryExists(s) Then + writeln('Directory ' + s + ' exists.'); } + + { If FileExists(s + DirectorySeperator + 'Cogat' + ExeExt) Then + writeln('We exist!'); } + + myFile := CreateFile(TestPath); + WriteFileString(myFile, 'wat'); + WriteFileString(myFile, 'watnumber2'); + CloseFile(myFile); + + myFile := OpenFile(TestPath, False); + ReadFileString(myFile, s2, 2); + writeln('s2: ' + s2); + CloseFile(myFile); + + myFile := CreateFile(TestPath + '2'); + WriteFileString(myFile, 'wat222'); + + CloseFile(myFile); + + // TestPath now contains; 'watwatnumber2'. We will make it write 'number', + // and then 2. + myFile := OpenFile(TestPath, False); + SetFileCharPointer(myFile, 6, fsFromBeginning); + ReadFileString(myFile, s2, 6); + writeln('s2: ' + s2); + s2 := ''; + + SetFileCharPointer(myFile, -1, fsFromEnd); + ReadFileString(myFile, s2, 1); + writeln('s2: ' + s2); + CloseFile(myFile); + + // myFile2 should be -1. + myFile := RewriteFile(TestPath, False); + myFile2 := RewriteFile(TestPath, False); + writeln(inttostr(myFile) + ' : ' + inttostr(myFile2)); + + // myFile2 should be -1. + myFile2 := OpenFile(TestPath, False); + writeln(inttostr(myFile) + ' : ' + inttostr(myFile2)); + + // Now, we will test EndOfFile, and FileSize. + + While Not EndOfFile(myFile) Do + Begin + ReadFileString(myFile, s2, 1); + Writeln(s2); + End; + + CloseFile(myFile); + + //Writeln(FileContents(TestPath)); + writeln('wat'); +end. diff --git a/Units/MMLCore/dtm.pas b/Units/MMLCore/dtm.pas index 371c93f..14480cf 100644 --- a/Units/MMLCore/dtm.pas +++ b/Units/MMLCore/dtm.pas @@ -41,7 +41,9 @@ type function AddpDTM(d: pDTM): Integer; function GetDTM(index: Integer; out dtm: pDTM): Boolean; procedure FreeDTM(DTM: Integer); - Function StringToDTM(S: String): pDTM; + function StringToDTM(S: String): pDTM; + function SetDTMName(DTM: Integer; S: String): boolean; + { function FindDTM(DTM: Integer; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean; @@ -272,6 +274,18 @@ begin end end; +function TMDTM.SetDTMName(DTM: Integer; s: string): boolean; +var + dtm_: pDTM; +begin + if(GetDTM(dtm, dtm_)) then + begin + dtm_.n := s; + Exit(True); + end; + Exit(False); +end; + {/\ Unloads the DTM at the given index from the DTM Array. Notes: diff --git a/Units/MMLCore/dtmutil.pas b/Units/MMLCore/dtmutil.pas index 588f6a3..f7e55ec 100644 --- a/Units/MMLCore/dtmutil.pas +++ b/Units/MMLCore/dtmutil.pas @@ -57,6 +57,7 @@ var i: integer; begin d.l := len; + d.n := ''; setlength(d.p, len); setlength(d.c, len); setlength(d.t, len); @@ -78,10 +79,13 @@ var i : integer; begin; i := 0; + if tdtm.n <> '' then + writeln('Name: ' + tdtm.n); WriteLn('MainPoint ' + inttostr(tDTM.p[i].x) + ', ' + inttostr(tDTM.p[i].y) + ' col: ' + inttostr(tDTM.c[i]) + ', tol: ' + inttostr(tDTM.t[i]) + '; ashape ' + inttostr(tdtm.ash[i]) + ' asize ' + inttostr(tdtm.asz[i])); for I := 1 to High(tDTM.p) do WriteLn('SubPoint['+IntToStr(I) + '] ' + inttostr(tDTM.p[i].x) + ', ' + inttostr(tDTM.p[i].y) + ' col: ' + inttostr(tDTM.c[i]) + ', tol: ' + inttostr(tDTM.t[i]) + '; ashape ' + inttostr(tdtm.ash[i]) + ' asize ' + inttostr(tdtm.asz[i])); end; + Function pDTMToTDTM(Const DTM: pDTM): TDTM; Var diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index cd3a946..2644f71 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -1654,16 +1654,9 @@ begin // C = DTM.C C := DTM.c; - // Now, we must find the occurances of all colours. - // This part should be turned into a more general function (for DTM Finding). - // Something like FindColorsMultiBooleanArray (?) - // Retreive Client Data. PtrData := TClient(Client).MWindow.ReturnData(x1, y1, W + 1, H + 1); - // Do we want to "cache" these vars? - // We will, for now. Easier to type. - cd := CalculateRowPtrs(PtrData, h + 1); //writeln(format('w,h: %d, %d', [w,h])); @@ -1728,24 +1721,3 @@ begin end; end. - - -{ crap code } - - // this is the probably the slowest part of the algorithm. -{ for yy := y1 to y2 do - begin - for xx := x1 to x2 do - begin - {for i := 0 to dtm.l - 1 do - begin - // optimise this later... - if TClient(Client).MFinder.SimilarColors(dtm.c[i], RGBToColor(Ptr^.R,Ptr^.G,Ptr^.B) , dtm.t[i]) then - B[xx][yy] := B[xx][yy] or (1 shl i); - end; } - inc(Ptr); - end; - inc(Ptr, PtrInc); - end; - } - diff --git a/Units/MMLCore/mufasatypes.pas b/Units/MMLCore/mufasatypes.pas index 933d448..d054095 100644 --- a/Units/MMLCore/mufasatypes.pas +++ b/Units/MMLCore/mufasatypes.pas @@ -91,6 +91,7 @@ type l: Integer; p: TPointArray; c, t, asz, ash: TIntegerArray; + n: String; // DOEN end; { Other DTM Types } diff --git a/Units/MMLCore/ocr.pas b/Units/MMLCore/ocr.pas index 0dfc0f2..f9c2eee 100644 --- a/Units/MMLCore/ocr.pas +++ b/Units/MMLCore/ocr.pas @@ -83,9 +83,10 @@ begin result := true; OCRPath := path + DS; if DirectoryExists(path + DS + 'UpChars' + DS) then - OCRData[0] := InitOCR(path + DS + 'UpChars' + DS) + OCRData[0] := ocrutil.InitOCR(path + DS + 'UpChars' + DS) else result := false; + end; function TMOCR.GetUpTextAt(atX, atY: integer): string;