@@ -97,7 +97,7 @@ function hanxinSize(version: number): number {
9797 *
9898 * Total modules minus function patterns:
9999 * - 4 finder patterns (7×7 each = 196 modules)
100- * - 4 timing strips along edges (between finders)
100+ * - Separator bands around finders
101101 * - Version/format info areas
102102 *
103103 * Returns the total number of data codewords (bytes) available
@@ -110,15 +110,13 @@ function hanxinTotalCodewords(version: number): number {
110110 // 4 finder patterns — 7×7 each
111111 const finderModules = 4 * 7 * 7 ;
112112
113- // Timing patterns along all 4 edges (between finders)
114- // Each edge has (size - 14) modules in the timing strip
115- const timingModules = 4 * ( size - 14 ) ;
113+ // Separator bands around finders: 4 L-shaped bands, ~8 modules each
114+ const separatorModules = 4 * ( 8 + 7 ) ;
116115
117- // Format/version info: Han Xin uses structural regions
118- // along finder edges — approximate as 36 modules per version
116+ // Format/version info regions around finders
119117 const formatModules = Math . min ( 36 + version * 2 , size * 4 ) ;
120118
121- const usableModules = totalModules - finderModules - timingModules - formatModules ;
119+ const usableModules = totalModules - finderModules - separatorModules - formatModules ;
122120
123121 return Math . floor ( usableModules / 8 ) ;
124122}
@@ -331,12 +329,21 @@ export function encodeHanXin(text: string, options: HanXinOptions = {}): boolean
331329 placeFinderHX ( matrix , size - 7 , 0 , FINDER_BL , size ) ;
332330 placeFinderHX ( matrix , size - 7 , size - 7 , FINDER_BR , size ) ;
333331
334- // Timing patterns along all 4 edges
335- for ( let i = 7 ; i < size - 7 ; i ++ ) {
336- if ( matrix [ 0 ] ! [ i ] === null ) matrix [ 0 ] ! [ i ] = i % 2 === 0 ;
337- if ( matrix [ i ] ! [ 0 ] === null ) matrix [ i ] ! [ 0 ] = i % 2 === 0 ;
338- if ( matrix [ size - 1 ] ! [ i ] === null ) matrix [ size - 1 ] ! [ i ] = i % 2 === 0 ;
339- if ( matrix [ i ] ! [ size - 1 ] === null ) matrix [ i ] ! [ size - 1 ] = i % 2 === 0 ;
332+ // Han Xin has NO timing patterns — only separator bands around finders
333+ // 1-module white separator around each 7x7 finder
334+ for ( let i = - 1 ; i <= 7 ; i ++ ) {
335+ // Top-left separator
336+ setSafeNull ( matrix , 7 , i , size ) ;
337+ setSafeNull ( matrix , i , 7 , size ) ;
338+ // Top-right separator
339+ setSafeNull ( matrix , 7 , size - 8 + i , size ) ;
340+ setSafeNull ( matrix , i , size - 8 , size ) ;
341+ // Bottom-left separator
342+ setSafeNull ( matrix , size - 8 , i , size ) ;
343+ setSafeNull ( matrix , size - 8 + i , 7 , size ) ;
344+ // Bottom-right separator
345+ setSafeNull ( matrix , size - 8 , size - 8 + i , size ) ;
346+ setSafeNull ( matrix , size - 8 + i , size - 8 , size ) ;
340347 }
341348
342349 // Place data bits into available modules
@@ -360,6 +367,12 @@ export function encodeHanXin(text: string, options: HanXinOptions = {}): boolean
360367 return matrix . map ( ( row ) => row . map ( ( cell ) => cell === true ) ) ;
361368}
362369
370+ function setSafeNull ( matrix : ( boolean | null ) [ ] [ ] , r : number , c : number , size : number ) : void {
371+ if ( r >= 0 && r < size && c >= 0 && c < size && matrix [ r ] ! [ c ] === null ) {
372+ matrix [ r ] ! [ c ] = false ;
373+ }
374+ }
375+
363376function placeFinderHX (
364377 matrix : ( boolean | null ) [ ] [ ] ,
365378 row : number ,
0 commit comments