@@ -15,6 +15,129 @@ namespace helper {
1515 return v < minv ? minv : (v > maxv ? maxv : v);
1616 } */
1717
18+ // ใน fximg.utils.ts หรือไฟล์ blit-related
19+ export function fximgBlitRow (
20+ dst : Buffer ,
21+ xDst : number ,
22+ yDst : number ,
23+ wDst : number , // ความกว้าง dst (ใช้เช็คขอบเขตเท่านั้น)
24+ hDst : number , // ความสูง dst (ใช้เช็คขอบเขต)
25+ src : Buffer ,
26+ xSrc : number ,
27+ hSrc : number // ความสูงที่จะ copy (จำนวน pixel ใน column)
28+ ) : void {
29+ if ( fximgRoCheck ( dst ) ) return ;
30+
31+ const dstW = fximgWidthOf ( dst ) ;
32+ const dstFullH = fximgHeightOf ( dst ) ;
33+ const srcW = fximgWidthOf ( src ) ;
34+ const srcFullH = fximgHeightOf ( src ) ;
35+
36+ // Clip ง่าย ๆ
37+ if ( xDst < 0 || xDst >= dstW || xSrc < 0 || xSrc >= srcW ) return ;
38+ if ( yDst < 0 ) {
39+ hSrc += yDst ;
40+ yDst = 0 ;
41+ }
42+ if ( yDst + hSrc > dstFullH ) hSrc = dstFullH - yDst ;
43+ if ( hSrc <= 0 ) return ;
44+
45+ // ใช้ buffer ชั่วคราวขนาด hSrc เพื่อ optimize (ไม่ต้อง buffer เต็ม dstH)
46+ const buf = pins . createBuffer ( hSrc ) ;
47+
48+ // ดึง column จาก src (เริ่มจาก y=0 ของ buf)
49+ fximgGetRows ( src , xSrc , buf , hSrc ) ;
50+
51+ if ( yDst === 0 ) {
52+ // Fast path: วางตรงหัว column
53+ fximgSetRows ( dst , xDst , buf , hSrc ) ;
54+ } else {
55+ // Slow path: merge กับข้อมูลเดิมที่ yDst
56+ const dstBuf = pins . createBuffer ( dstFullH ) ;
57+ fximgGetRows ( dst , xDst , dstBuf , dstFullH ) ;
58+
59+ // copy เข้าไปที่ offset yDst
60+ for ( let i = 0 ; i < hSrc ; i ++ ) {
61+ dstBuf [ yDst + i ] = buf [ i ] ;
62+ }
63+
64+ fximgSetRows ( dst , xDst , dstBuf , dstFullH ) ;
65+ }
66+ }
67+
68+ export function fximgBlit (
69+ dst : Buffer ,
70+ xDst : number , yDst : number ,
71+ wDst : number , hDst : number ,
72+ src : Buffer ,
73+ xSrc : number , ySrc : number ,
74+ wSrc : number , hSrc : number ,
75+ transparent ?: boolean ,
76+ check ?: boolean
77+ ) : boolean {
78+ if ( fximgRoCheck ( dst ) ) return false ;
79+
80+ const dstW = fximgWidthOf ( dst ) ;
81+ const dstH = fximgHeightOf ( dst ) ;
82+ const srcW = fximgWidthOf ( src ) ;
83+ const srcH = fximgHeightOf ( src ) ;
84+
85+ // Clip rectangle ทั้ง src และ dst (เหมือนมาตรฐาน)
86+ let clipWDst = wDst ;
87+ let clipHDst = hDst ;
88+ let clipWSrc = wSrc ;
89+ let clipHSrc = hSrc ;
90+
91+ if ( xDst < 0 ) { clipWDst += xDst ; clipWSrc += xDst ; xSrc -= xDst ; xDst = 0 ; }
92+ if ( yDst < 0 ) { clipHDst += yDst ; clipHSrc += yDst ; ySrc -= yDst ; yDst = 0 ; }
93+ if ( xDst + clipWDst > dstW ) clipWDst = dstW - xDst ;
94+ if ( yDst + clipHDst > dstH ) clipHDst = dstH - yDst ;
95+
96+ if ( xSrc < 0 ) { clipWDst += xSrc ; clipWSrc += xSrc ; xSrc = 0 ; }
97+ if ( ySrc < 0 ) { clipHDst += ySrc ; clipHSrc += ySrc ; ySrc = 0 ; }
98+ if ( xSrc + clipWSrc > srcW ) clipWSrc = srcW - xSrc ;
99+ if ( ySrc + clipHSrc > srcH ) clipHSrc = srcH - ySrc ;
100+
101+ if ( clipWDst <= 0 || clipHDst <= 0 || clipWSrc <= 0 || clipHSrc <= 0 ) return false ;
102+
103+ // ถ้า transparent=false และ check=false → อาจ optimize เร็วขึ้น แต่เวอร์ชันนี้ทำแบบ general ก่อน
104+
105+ const rowBuf = pins . createBuffer ( clipHDst ) ; // buffer ขนาดสูงสุดที่ copy จริง
106+ const dstRow = pins . createBuffer ( dstH ) ; // buffer เต็ม column ของ dst
107+
108+ let anyChange = false ;
109+
110+ for ( let dx = 0 ; dx < clipWDst ; dx ++ ) {
111+ const sx = xSrc + dx ;
112+ const tx = xDst + dx ;
113+
114+ // ดึง column ส่วนที่ต้องการจาก src (offset ySrc)
115+ fximgGetRows ( src , sx , rowBuf , clipHSrc ) ;
116+
117+ fximgGetRows ( dst , tx , dstRow , dstH ) ;
118+
119+ let colChanged = false ;
120+
121+ for ( let dy = 0 ; dy < clipHDst ; dy ++ ) {
122+ const syPixel = rowBuf [ dy ] ; // pixel จาก src (หลัง shift ySrc แล้ว)
123+
124+ if ( transparent && syPixel < 1 ) continue ;
125+
126+ const oldPixel = dstRow [ yDst + dy ] ;
127+ if ( oldPixel === syPixel ) continue ;
128+ dstRow [ yDst + dy ] = syPixel ;
129+ colChanged = true , anyChange = true ;
130+ }
131+
132+ if ( ! ( colChanged || ! check ) ) continue ;
133+ fximgSetRows ( dst , tx , dstRow , dstH ) ;
134+
135+ // ถ้า check=true และยังไม่มี change เลย → สามารถ break ได้เร็ว แต่เวอร์ชันนี้ scan หมดก่อน
136+ }
137+
138+ return check ? anyChange : true ;
139+ }
140+
18141 // 1. drawLine (Bresenham ปรับปรุงตามที่ภัทรแนะนำ - ใช้ sx/sy ตรวจทิศทาง ไม่เช็คจุดเริ่ม=จุดจบ)
19142 export function fximgDrawLine ( fxpic : Buffer , x0 : number , y0 : number , x1 : number , y1 : number , color : number , idx ?: number ) {
20143 if ( fximgRoCheck ( fxpic ) ) return ;
0 commit comments