Skip to content

Commit d26c765

Browse files
committed
Add some string comparision capabilities to TPixelFont
1 parent eba43d4 commit d26c765

2 files changed

Lines changed: 78 additions & 6 deletions

File tree

Source/script/imports/simba.import_pixelocr.pas

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,22 @@ implementation
2121
PPixelFont = ^TPixelFont;
2222
PPixelOCR = ^TPixelOCR;
2323

24+
procedure _LapePixelFont_SameChar(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
25+
begin
26+
PBoolean(Result)^ := PPixelFont(Params^[0])^.SameGlyph(PChar(Params^[1])^, PChar(Params^[2])^);
27+
end;
28+
29+
procedure _LapePixelFont_SameText(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
30+
begin
31+
PBoolean(Result)^ := PPixelFont(Params^[0])^.SameText(PString(Params^[1])^, PString(Params^[2])^);
32+
end;
33+
34+
procedure _LapePixelFont_ReplaceSameGlyphs(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV
35+
begin
36+
PPixelFont(Params^[0])^.ReplaceSameGlyphs(PString(Params^[1])^, PString(Params^[2])^);
37+
end;
38+
39+
2440
procedure _LapePixelOCR_LoadFont(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
2541
begin
2642
PPixelFont(Result)^ := TPixelOCR.LoadFont(PString(Params^[0])^, PInteger(Params^[1])^);
@@ -59,6 +75,8 @@ procedure ImportPixelOCR(Script: TSimbaScript);
5975
'record',
6076
' Value: Char;',
6177
'',
78+
' Hash: UInt32;',
79+
'',
6280
' Width: Int16;',
6381
' Height: Int16;',
6482
' ForegroundBounds: TBox;',
@@ -114,6 +132,9 @@ procedure ImportPixelOCR(Script: TSimbaScript);
114132
if (getGlobalType('TPixelOCR').Size <> SizeOf(TPixelOCR)) then
115133
SimbaException('TPixelOCR import is wrong');
116134

135+
addGlobalFunc('function TPixelFont.SameGlyph(const a, b: Char): Boolean;', @_LapePixelFont_SameChar);
136+
addGlobalFunc('function TPixelFont.SameText(const s1, s2: String): Boolean;', @_LapePixelFont_SameText);
137+
addGlobalFunc('procedure TPixelFont.ReplaceSameGlyphs(var s1: String; const s2: String);', @_LapePixelFont_ReplaceSameGlyphs);
117138
addGlobalFunc('function TPixelOCR.LoadFont(Path: String; SpaceWidth: Integer): TPixelFont; static;', @_LapePixelOCR_LoadFont);
118139
addGlobalFunc('function TPixelOCR.TextToTPA(constref Font: TPixelFont; Text: String): TPointArray; static;', @_LapePixelOCR_TextToTPA);
119140
addGlobalFunc('function TPixelOCR.Locate(Image: TImage; constref Font: TPixelFont; Text: String): Single;', @_LapePixelOCR_Locate);

Source/simba.pixelocr.pas

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ interface
2525
TPixelFontGlyph = record
2626
Value: Char;
2727

28+
Hash: UInt32;
29+
2830
Width: Int16; // image width
2931
Height: Int16; // image height
3032
ForegroundBounds: TBox; // foreground meaning points and shadow
@@ -44,6 +46,11 @@ TPixelFont = record
4446
SpaceWidth: Integer;
4547
MaxGlyphWidth: Integer;
4648
MaxGlyphHeight: Integer;
49+
public
50+
function GetGlyph(const c: Char): PPixelFontGlyph; inline;
51+
function SameGlyph(const a, b: Char): Boolean; inline;
52+
function SameText(const s1, s2: String): Boolean; inline;
53+
procedure ReplaceSameGlyphs(var s1: String; const s2: String); inline;
4754
end;
4855
PPixelFont = ^TPixelFont;
4956

@@ -112,18 +119,58 @@ function IsShadow(const Image: TSimbaImage; const X, Y: Integer; const Tol: Sing
112119
Result := (R <= Tol) and (G <= Tol) and (B <= Tol + 5); // allow a little more in the blue channel only
113120
end;
114121

115-
function GetGlyph(const Font: PPixelFont; const c: Char): PPixelFontGlyph; inline;
122+
//slacky hashing algorithm
123+
function HashPoints(const points: TPointArray): UInt32; inline;
124+
var
125+
pt: TPoint;
126+
begin
127+
{$PUSH}
128+
{$Q-}{$R-}
129+
Result := $811C9DC5;
130+
for pt in points do
131+
Result := (Result xor (UInt32(pt.X) shl 16 or UInt32(pt.Y))) * $01000193;
132+
{$POP}
133+
end;
134+
135+
function TPixelFont.GetGlyph(const c: Char): PPixelFontGlyph; inline;
116136
var
117137
I: Integer;
118138
begin
119-
for I := 0 to High(Font^.Glyphs) do
120-
if (Font^.Glyphs[I].Value = c) then
121-
Exit(@Font^.Glyphs[I]);
139+
for I := 0 to High(Self.Glyphs) do
140+
if (Self.Glyphs[I].Value = c) then
141+
Exit(@Self.Glyphs[I]);
122142

123143
SimbaException('Character %s does exist in the Font', [c]);
124144
Result := nil;
125145
end;
126146

147+
function TPixelFont.SameGlyph(const a, b: Char): Boolean; inline;
148+
begin
149+
Result := Self.GetGlyph(a)^.Hash = Self.GetGlyph(b)^.Hash;
150+
end;
151+
152+
function TPixelFont.SameText(const s1, s2: String): Boolean; inline;
153+
var
154+
i: Integer;
155+
begin
156+
if Length(s1) <> Length(s2) then
157+
Exit(False);
158+
for i := 1 to Length(s1) do
159+
if not Self.SameGlyph(s1[i], s2[i]) then
160+
Exit(False);
161+
Result := True;
162+
end;
163+
164+
procedure TPixelFont.ReplaceSameGlyphs(var s1: String; const s2: String); inline;
165+
var
166+
i: Integer;
167+
begin
168+
for i := 1 to Min(Length(s1), Length(s2)) do
169+
if Self.SameGlyph(s1[i], s2[i]) then
170+
s1[i] := s2[i];
171+
end;
172+
173+
127174
// text contains >= 50% alphanum
128175
function IsAlphaNumSym(const Text: String): Boolean; inline;
129176
var
@@ -364,6 +411,7 @@ class function TPixelOCR.LoadFont(Dir: String; SpaceWidth: Integer): TPixelFont;
364411
Character: String;
365412
Glyph: TPixelFontGlyph;
366413
B: TBox;
414+
Pt: TPoint;
367415
begin
368416
Result := Default(TPixelFont);
369417
Result.SpaceWidth := SpaceWidth;
@@ -410,6 +458,8 @@ class function TPixelOCR.LoadFont(Dir: String; SpaceWidth: Integer): TPixelFont;
410458
Glyph.BackgroundBounds := B;
411459
Glyph.PointsShadowWidth := B.Width;
412460

461+
Glyph.Hash := HashPoints(TPointArray(Glyph.Points + Glyph.Shadow));
462+
413463
if (Length(Glyph.Shadow) > 0) then
414464
Glyph.BestMatch := Length(Glyph.Points) + Length(Glyph.Shadow)
415465
else
@@ -442,7 +492,7 @@ class function TPixelOCR.TextToTPA(constref Font: TPixelFont; Text: String; out
442492
X := 0;
443493
Count := 0;
444494
for I := 1 to Length(Text) do
445-
with GetGlyph(@Font, Text[I])^ do
495+
with Font.GetGlyph(Text[I])^ do
446496
begin
447497
if (Points <> nil) then
448498
begin
@@ -460,7 +510,7 @@ class function TPixelOCR.TextToTPA(constref Font: TPixelFont; Text: String; out
460510

461511
Count := 0;
462512
for I := 1 to Length(Text) do
463-
with GetGlyph(@Font, Text[I])^ do
513+
with Font.GetGlyph(Text[I])^ do
464514
begin
465515
for J := 0 to High(Points) do
466516
begin
@@ -652,4 +702,5 @@ function TPixelOCR.RecognizeLines(Image: TSimbaImage; constref Font: TPixelFont;
652702
end;
653703
end;
654704

705+
655706
end.

0 commit comments

Comments
 (0)