Skip to content

Commit cb014c3

Browse files
committed
hanxin: Optimise mask layer generation and placement
The identity mask function yields an all-zero layer, so skip building it and evaluate the unmasked symbol directly. Fill the three remaining mask layers together in a single sequential walk of the grid, testing for data modules once per position, keeping the generic single-layer build for a user-specified mask. Walk the bitstream placement by sequential position with the index on the stack rather than by coordinates, and keep the module index on the stack when extracting each masked symbol. Tests are added pinning the symbol for each user-specified mask, including the identity mask 1, whose layer is skipped.
1 parent 5bd1ec9 commit cb014c3

2 files changed

Lines changed: 181 additions & 37 deletions

File tree

src/hanxin.ps.src

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,47 +1156,72 @@ begin
11561156

11571157
(matrix.layout.data) //hanxin.before exec
11581158

1159-
/maskfuncs //hanxin.maskfuncs def
1160-
mask -1 ne { % User specifies a mask
1161-
/maskfuncs [//hanxin.maskfuncs mask 1 sub get] def
1162-
/bestmaskval mask 1 sub def
1163-
} if
1164-
11651159
%
1166-
% Build a candidate mask layer for each mask function
1160+
% Build the candidate mask layers, walking positions sequentially and
1161+
% testing for data modules once per position. The identity mask
1162+
% function would yield an all-zero layer, denoted null so that
1163+
% evaluation can use the unmasked symbol directly; the other layers
1164+
% are filled together in a single pass.
11671165
%
1168-
/masks maskfuncs length array def
1169-
0 1 masks length 1 sub {
1170-
/m exch def
1171-
/mask size size mul array def
1172-
0 1 size 1 sub {
1173-
/j exch def
1174-
0 1 size 1 sub {
1175-
/i exch def
1176-
i 1 add j 1 add maskfuncs m get exec 0 eq
1177-
pixs i j qmv get -1 eq and {1} {0} ifelse
1178-
mask i j qmv 3 -1 roll put
1166+
mask -1 eq {
1167+
/masks [ null //hanxin.maskfuncs length 1 sub { size size mul array } repeat ] def
1168+
/mf2 //hanxin.maskfuncs 1 get def /lyr2 masks 1 get def
1169+
/mf3 //hanxin.maskfuncs 2 get def /lyr3 masks 2 get def
1170+
/mf4 //hanxin.maskfuncs 3 get def /lyr4 masks 3 get def
1171+
/pos 0 def
1172+
1 1 size {
1173+
/jp exch def
1174+
1 1 size { % ip on stack
1175+
pixs pos get -1 eq {
1176+
dup jp mf2 exec 0 eq {1} {0} ifelse lyr2 pos 3 -1 roll put
1177+
dup jp mf3 exec 0 eq {1} {0} ifelse lyr3 pos 3 -1 roll put
1178+
jp mf4 exec 0 eq {1} {0} ifelse lyr4 pos 3 -1 roll put
1179+
} {
1180+
pop
1181+
lyr2 pos 0 put
1182+
lyr3 pos 0 put
1183+
lyr4 pos 0 put
1184+
} ifelse
1185+
/pos pos 1 add def
11791186
} for
11801187
} for
1181-
masks m mask put
1182-
} for
1188+
} { % User specifies a mask: build just its layer
1189+
/bestmaskval mask 1 sub def
1190+
//hanxin.maskfuncs bestmaskval get //hanxin.maskfuncs 0 get eq {
1191+
/masks [ null ] def
1192+
} {
1193+
/mfunc //hanxin.maskfuncs bestmaskval get def
1194+
/msklyr size size mul array def
1195+
/pos 0 def
1196+
1 1 size {
1197+
/jp exch def
1198+
1 1 size { % ip on stack
1199+
pixs pos get -1 eq {
1200+
jp mfunc exec 0 eq {1} {0} ifelse
1201+
} {
1202+
pop 0
1203+
} ifelse
1204+
msklyr pos 3 -1 roll put
1205+
/pos pos 1 add def
1206+
} for
1207+
} for
1208+
/masks [ msklyr ] def
1209+
} ifelse
1210+
} ifelse
11831211

11841212
%
1185-
% Walk the symbol placing the bitstream
1213+
% Walk the symbol placing the bitstream in the data modules
11861214
%
1187-
/posx 0 def
1188-
/posy 0 def
11891215
/num 0 def
1190-
{ % loop
1191-
posy size eq {exit} if
1192-
pixs posx posy qmv get -1 eq {
1193-
cws num 8 idiv get 7 num 8 mod sub neg bitshift 1 and
1194-
pixs posx posy qmv 3 -1 roll put
1216+
0 1 size size mul 1 sub { % pos
1217+
pixs 1 index get -1 eq {
1218+
cws num 8 idiv get 7 num 8 mod sub neg bitshift 1 and % pos bit
1219+
pixs 3 1 roll put
11951220
/num num 1 add def
1196-
} if
1197-
/posx posx 1 add def
1198-
posx size eq {/posx 0 def /posy posy 1 add def} if
1199-
} loop
1221+
} {
1222+
pop
1223+
} ifelse
1224+
} for
12001225

12011226
(matrix.layout.data) //hanxin.after exec
12021227

@@ -1293,11 +1318,15 @@ begin
12931318
/bestscore 999999999 def
12941319
0 1 masks length 1 sub {
12951320
/m exch def
1296-
/masksym size size mul array def
1297-
0 1 size size mul 1 sub {
1298-
/i exch def
1299-
masksym i pixs i get masks m get i get xor put
1300-
} for
1321+
/msklyr masks m get def
1322+
msklyr null eq { % Identity mask
1323+
/masksym pixs def
1324+
} {
1325+
/masksym size size mul array def
1326+
0 1 size size mul 1 sub {
1327+
masksym exch dup pixs exch get msklyr 2 index get xor put
1328+
} for
1329+
} ifelse
13011330
masks length 1 ne {
13021331
masksym evalfull /score exch def
13031332
score bestscore lt {

tests/ps_tests/hanxin.ps.test

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,3 +541,118 @@
541541

542542
% strictspec smoke test
543543
{ 0 0 moveto (This is Han Xin) (strictspec xdim=0.330) hanxin true } true isEqual
544+
545+
% User-specified masks: pinned symbols for each mask pattern applied to
546+
% the same data, including the identity mask 1
547+
{
548+
(12345) (mask=1 dontdraw) hanxin /pixs get
549+
} [
550+
1 1 1 1 1 1 1 0 1 0 0 0 1 0 0 0 1 1 1 1 1 1 1
551+
1 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1
552+
1 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 1
553+
1 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 1
554+
1 0 1 0 1 1 1 0 1 1 1 0 0 0 0 0 1 1 1 0 1 0 1
555+
1 0 1 0 1 1 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1 0 1
556+
1 0 1 0 1 1 1 0 0 0 0 0 0 1 0 0 1 1 1 0 1 0 1
557+
0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 0 0 0 0 0 0 0 0
558+
0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 1 1 0 1 0 1 0 1
559+
0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 0 0 0
560+
0 0 0 0 0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1
561+
0 0 1 1 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 1 0 0
562+
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
563+
1 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1
564+
1 0 1 0 1 0 1 1 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0
565+
0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0
566+
1 1 1 1 1 1 1 0 0 1 0 0 0 1 0 0 1 1 1 0 1 0 1
567+
0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 1 1 1 0 1 0 1
568+
1 1 1 1 1 0 1 0 0 0 0 0 0 1 1 0 1 1 1 0 1 0 1
569+
0 0 0 0 1 0 1 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 1
570+
1 1 1 0 1 0 1 0 0 1 0 0 0 0 0 0 1 1 1 1 1 0 1
571+
1 1 1 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1
572+
1 1 1 0 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 1 1 1 1
573+
] debugIsEqual
574+
575+
{
576+
(12345) (mask=2 dontdraw) hanxin /pixs get
577+
} [
578+
1 1 1 1 1 1 1 0 0 0 1 0 0 0 1 0 1 1 1 1 1 1 1
579+
1 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 1
580+
1 0 1 1 1 1 1 0 0 0 1 0 1 0 0 0 1 1 1 1 1 0 1
581+
1 0 1 0 0 0 0 0 1 1 1 0 1 1 1 0 0 0 0 0 1 0 1
582+
1 0 1 0 1 1 1 0 0 1 0 0 1 0 0 0 1 1 1 0 1 0 1
583+
1 0 1 0 1 1 1 0 1 1 0 1 0 1 1 0 1 1 1 0 1 0 1
584+
1 0 1 0 1 1 1 0 0 0 1 0 1 1 0 0 1 1 1 0 1 0 1
585+
0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
586+
0 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1
587+
0 1 0 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 0 0 1 0
588+
1 0 1 0 1 1 1 0 0 1 0 0 1 0 1 0 1 0 1 0 1 1 0
589+
0 1 1 0 0 1 0 1 0 1 0 1 0 0 1 1 0 0 0 1 1 1 0
590+
1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 0 1
591+
1 1 0 1 0 0 1 1 0 1 0 1 0 1 0 1 0 0 0 1 1 1 1
592+
1 0 1 0 1 0 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 0
593+
0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 0 0 0 0 0 0 0
594+
1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 0 1 1 1 0 1 0 1
595+
0 0 0 0 0 0 1 0 1 0 0 1 0 1 1 0 1 1 1 0 1 0 1
596+
1 1 1 1 1 0 1 0 0 0 1 0 1 1 0 0 1 1 1 0 1 0 1
597+
0 0 0 0 1 0 1 0 1 1 1 0 1 1 1 0 0 0 0 0 1 0 1
598+
1 1 1 0 1 0 1 0 0 1 1 0 1 0 0 0 1 1 1 1 1 0 1
599+
1 1 1 0 1 0 1 0 1 1 0 1 0 1 0 0 0 0 0 0 0 0 1
600+
1 1 1 0 1 0 1 0 1 0 1 0 1 0 0 0 1 1 1 1 1 1 1
601+
] debugIsEqual
602+
603+
{
604+
(12345) (mask=3 dontdraw) hanxin /pixs get
605+
} [
606+
1 1 1 1 1 1 1 0 0 0 1 0 1 1 0 0 1 1 1 1 1 1 1
607+
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
608+
1 0 1 1 1 1 1 0 0 1 1 1 1 1 1 0 1 1 1 1 1 0 1
609+
1 0 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 1
610+
1 0 1 0 1 1 1 0 0 1 1 1 0 0 0 0 1 1 1 0 1 0 1
611+
1 0 1 0 1 1 1 0 0 1 1 1 1 1 0 0 1 1 1 0 1 0 1
612+
1 0 1 0 1 1 1 0 1 0 1 0 0 0 1 0 1 1 1 0 1 0 1
613+
0 0 0 0 0 0 0 0 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0
614+
0 0 0 1 0 1 0 1 0 1 1 1 1 1 1 0 1 0 1 0 1 0 1
615+
0 1 0 1 0 1 1 0 1 1 0 0 0 1 0 0 1 0 0 0 0 0 1
616+
0 0 1 0 0 0 0 0 0 1 1 1 0 0 1 0 0 1 0 0 1 1 1
617+
1 1 0 0 1 1 1 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 1
618+
0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1
619+
1 0 1 0 0 0 1 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1
620+
1 0 1 0 1 0 1 0 1 1 1 1 1 1 0 1 0 1 0 1 0 0 0
621+
0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0
622+
1 1 1 1 1 1 1 0 1 1 0 1 0 1 1 0 1 1 1 0 1 0 1
623+
0 0 0 0 0 0 1 0 0 0 1 1 1 1 0 0 1 1 1 0 1 0 1
624+
1 1 1 1 1 0 1 0 0 0 1 0 0 0 0 0 1 1 1 0 1 0 1
625+
0 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1
626+
1 1 1 0 1 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 0 1
627+
1 1 1 0 1 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1
628+
1 1 1 0 1 0 1 0 0 0 0 1 0 0 0 0 1 1 1 1 1 1 1
629+
] debugIsEqual
630+
631+
{
632+
(12345) (mask=4 dontdraw) hanxin /pixs get
633+
} [
634+
1 1 1 1 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1
635+
1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 1
636+
1 0 1 1 1 1 1 0 0 0 0 0 0 0 1 0 1 1 1 1 1 0 1
637+
1 0 1 0 0 0 0 0 1 1 0 1 1 0 1 0 0 0 0 0 1 0 1
638+
1 0 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 1 1 0 1 0 1
639+
1 0 1 0 1 1 1 0 1 0 0 1 1 1 0 0 1 1 1 0 1 0 1
640+
1 0 1 0 1 1 1 0 1 1 1 0 0 0 1 0 1 1 1 0 1 0 1
641+
0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0
642+
0 0 0 1 0 1 0 1 0 0 0 1 1 1 0 1 0 0 1 0 1 0 1
643+
0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 1 1 0 0 1 1 1 1
644+
1 0 0 1 1 1 1 0 1 0 0 1 1 1 0 0 0 1 1 1 0 0 0
645+
1 1 1 1 0 1 0 1 1 0 1 1 1 0 1 0 0 0 1 1 1 0 0
646+
0 1 0 0 0 1 0 1 1 0 1 1 1 1 1 1 1 0 0 0 1 1 1
647+
0 1 0 0 0 0 0 1 1 0 1 1 0 1 0 0 0 0 1 1 1 0 1
648+
1 0 1 0 1 0 0 1 0 1 0 0 1 0 0 1 0 1 0 1 0 0 0
649+
0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0
650+
1 1 1 1 1 1 1 0 1 0 0 0 1 1 1 0 1 1 1 0 1 0 1
651+
0 0 0 0 0 0 1 0 0 1 1 1 0 1 1 0 1 1 1 0 1 0 1
652+
1 1 1 1 1 0 1 0 0 0 1 1 0 0 1 0 1 1 1 0 1 0 1
653+
0 0 0 0 1 0 1 0 1 0 0 0 1 1 1 0 0 0 0 0 1 0 1
654+
1 1 1 0 1 0 1 0 1 0 0 0 1 0 0 0 1 1 1 1 1 0 1
655+
1 1 1 0 1 0 1 0 0 1 1 0 1 0 1 0 0 0 0 0 0 0 1
656+
1 1 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1 1 1 1 1 1
657+
] debugIsEqual
658+

0 commit comments

Comments
 (0)