182182 ] ;
183183
184184 // ===== EFFICIENT COLOR SYSTEM =====
185- // Pre-calculated color tables for animations using typed arrays
185+ // Pre-calculated color tables for animations
186186 let colorOn = null , colorOff = null ;
187187
188188 const initColorTables = ( ) => {
189- // Use Uint32Array for maximum performance
190- colorOn = new Uint32Array ( FRAC_STEPS + 1 ) ;
191- colorOff = new Uint32Array ( FRAC_STEPS + 1 ) ;
189+ // Use Uint16Array since Bangle uses RGB565 (16-bit) colors
190+ colorOn = new Uint16Array ( FRAC_STEPS + 1 ) ;
191+ colorOff = new Uint16Array ( FRAC_STEPS + 1 ) ;
192192
193193 const bgColor = g . theme . bg ;
194194 const fgColor = g . theme . fg ;
195195
196- // Calculate all color transitions
196+ // Simple linear interpolation between color values
197197 for ( let i = 0 ; i <= FRAC_STEPS ; i ++ ) {
198198 const frac = i / FRAC_STEPS ;
199- const invFrac = 1 - frac ;
200199
201- // Direct calculation for better performance
202- const rOn = ( ( ( bgColor >> 16 ) & 0xFF ) * invFrac + ( ( fgColor >> 16 ) & 0xFF ) * frac ) | 0 ;
203- const gOn = ( ( ( bgColor >> 8 ) & 0xFF ) * invFrac + ( ( fgColor >> 8 ) & 0xFF ) * frac ) | 0 ;
204- const bOn = ( ( bgColor & 0xFF ) * invFrac + ( fgColor & 0xFF ) * frac ) | 0 ;
205- const rOff = ( ( ( fgColor >> 16 ) & 0xFF ) * invFrac + ( ( bgColor >> 16 ) & 0xFF ) * frac ) | 0 ;
206- const gOff = ( ( ( fgColor >> 8 ) & 0xFF ) * invFrac + ( ( bgColor >> 8 ) & 0xFF ) * frac ) | 0 ;
207- const bOff = ( ( fgColor & 0xFF ) * invFrac + ( bgColor & 0xFF ) * frac ) | 0 ;
208- colorOn [ i ] = ( rOn << 16 ) | ( gOn << 8 ) | bOn ;
209- colorOff [ i ] = ( rOff << 16 ) | ( gOff << 8 ) | bOff ;
200+ // Direct interpolation of RGB565 values
201+ colorOn [ i ] = ( bgColor + ( fgColor - bgColor ) * frac + 0.5 ) | 0 ;
202+ colorOff [ i ] = ( fgColor + ( bgColor - fgColor ) * frac + 0.5 ) | 0 ;
210203 }
211204 }
212- // ===== BORDER DRAWING =====
213- const drawBorder = ( x , y , s , thickness ) => {
214- if ( ! showBorders || thickness <= 0 ) return ;
205+
206+ // ===== CONSOLIDATED BORDER DRAWING =====
207+ const drawBorder = ( x , y , s , isMainDigit ) => {
208+ if ( ! showBorders ) return ;
209+
210+ // Direct variable lookup is faster than object property access
211+ const thickness = isMainDigit ? MAIN_BORDER_THICKNESS : SEC_BORDER_THICKNESS ;
212+ if ( thickness <= 0 ) return ;
213+
215214 g . setColor ( borderColor ) ;
216215 for ( let i = 0 ; i < thickness ; i ++ ) {
217216 g . drawRect ( x + i , y + i , x + s - 1 - i , y + s - 1 - i ) ;
226225 function transition ( ) {
227226 if ( ! isDrawing || ( pendingSwitch && isSeconds ) ) return ;
228227
229- // Use pre-calculated color instead of interpColor()
228+ // Use pre-calculated color
230229 g . setColor ( colors [ step ] ) ;
231230 g . fillRect ( x , y , x + s - 1 , y + s - 1 ) ;
232231
248247 }
249248
250249 function animateTileOn ( x , y , s , callback , isMainDigit ) {
251- const thickness = isMainDigit ? MAIN_BORDER_THICKNESS : SEC_BORDER_THICKNESS ;
252- const borderFunc = ( showBorders && thickness > 0 ) ?
253- ( ) => drawBorder ( x , y , s , thickness ) : null ;
250+ const borderFunc = showBorders ? ( ) => drawBorder ( x , y , s , isMainDigit ) : null ;
254251 animateTransition ( x , y , s , g . theme . bg , g . theme . fg , borderFunc , callback ) ;
255252 }
256253
257254 function animateTileOff ( x , y , s , callback ) {
258255 animateTransition ( x , y , s , g . theme . fg , g . theme . bg , null , callback ) ;
259256 }
257+
260258 // ===== TILE CALCULATION =====
261259 const calculateTilesToUpdate = ( x , y , s , currentDigit , prevDigit ) => {
262260 const currentPacked = digitBitmaps [ getDigitIndex ( currentDigit ) ] ;
281279
282280 return tiles ;
283281 }
282+
284283 // ===== TILE UPDATE =====
285284 function updateTile ( tile , s , skipAnimation , isMainDigit , isClearing ) {
286- const thickness = isMainDigit ? MAIN_BORDER_THICKNESS : SEC_BORDER_THICKNESS ;
287-
288285 if ( tile . state ) {
289286 if ( skipAnimation ) {
290287 g . setColor ( g . theme . fg ) ;
291288 g . fillRect ( tile . x , tile . y , tile . x + s - 1 , tile . y + s - 1 ) ;
292- drawBorder ( tile . x , tile . y , s , thickness ) ;
289+ drawBorder ( tile . x , tile . y , s , isMainDigit ) ;
293290 } else {
294291 animateTileOn ( tile . x , tile . y , s , null , isMainDigit ) ;
295292 }
315312 animationTimeouts [ animationTimeoutCount ++ ] = timeout ;
316313 }
317314 }
315+
318316 // ===== DIGIT DRAWING =====
319317 function drawDigit ( x , y , s , num , prevNum , callback , skipAnimation , isMainDigit ) {
320318 if ( num === prevNum ) {
344342 } , true ) ;
345343 } , true ) ;
346344 }
345+
347346 // ===== TIME UPDATE SCHEDULING =====
348347 function scheduleNextUpdate ( ) {
349348 if ( drawTimeout ) clearTimeout ( drawTimeout ) ;
352351
353352 drawTimeout = setTimeout ( updateAndAnimTime , msUntilNextMinute ) ;
354353 }
354+
355355 // ===== CLEARING FUNCTIONS (Direct callback approach for performance) =====
356356 function clearColon ( callback ) {
357357 if ( ! isColonDrawn ) {
417417 } ) ;
418418 }
419419
420- // ===== MAIN TIME UPDATE =====
420+ // ===== MAIN TIME UPDATE (OPTIMIZED) =====
421421 function updateAndAnimTime ( ) {
422422 if ( ! isDrawing ) return ;
423423
426426 const minutesNum = now . getMinutes ( ) ;
427427 const currentTime = hoursNum * 100 + minutesNum ;
428428
429- // Extract digits only for layout decision
430- const isCurrentThreeDigit = is12Hour && hoursNum < 10 ;
431- const wasLastThreeDigit = is12Hour && lastTime !== null && lastTime < 1000 ;
432-
433- function drawTime ( ) {
434- // Extract current digits using cached lookups for maximum performance
435- let h1 , h2 , m1 , m2 ;
436-
429+ // Extract current digits ONCE
430+ const currentDigits = ( ( ) => {
437431 if ( timeCache && timeCache . minuteDigits ) {
438432 const hourCache = is12Hour ? timeCache . hourDigits12 : timeCache . hourDigits24 ;
439433 const minuteCache = timeCache . minuteDigits ;
440434
441- h1 = hourCache [ hoursNum * 2 ] ;
442- h2 = hourCache [ hoursNum * 2 + 1 ] ;
443- m1 = minuteCache [ minutesNum * 2 ] ;
444- m2 = minuteCache [ minutesNum * 2 + 1 ] ;
435+ return {
436+ h1 : hourCache [ hoursNum * 2 ] ,
437+ h2 : hourCache [ hoursNum * 2 + 1 ] ,
438+ m1 : minuteCache [ minutesNum * 2 ] ,
439+ m2 : minuteCache [ minutesNum * 2 + 1 ]
440+ } ;
445441 } else {
446- // Fallback to direct calculation
447- h1 = ( hoursNum / 10 ) | 0 ;
448- h2 = hoursNum % 10 ;
449- m1 = ( minutesNum / 10 ) | 0 ;
450- m2 = minutesNum % 10 ;
442+ return {
443+ h1 : ( hoursNum / 10 ) | 0 ,
444+ h2 : hoursNum % 10 ,
445+ m1 : ( minutesNum / 10 ) | 0 ,
446+ m2 : minutesNum % 10
447+ } ;
451448 }
452-
453- const digitMap = { h1 : h1 , h2 : h2 , m1 : m1 , m2 : m2 } ;
454-
449+ } ) ( ) ;
450+
451+ // Determine layout based on extracted digits
452+ const isCurrentThreeDigit = is12Hour && currentDigits . h1 === 0 ;
453+ const wasLastThreeDigit = is12Hour && lastTime !== null && lastTime < 1000 ;
454+
455+ function drawTime ( ) {
455456 // Extract previous digits (or null for blank)
456457 const previousDigits = ( isCurrentThreeDigit !== wasLastThreeDigit && lastTime !== null ) ?
457458 { h1 : null , h2 : null , m1 : null , m2 : null } :
470471 const next = ( ) => drawLayout ( items , onComplete ) ;
471472
472473 if ( item . type === 'digit' ) {
473- drawDigit ( item . x , item . y , item . scale , digitMap [ item . value ] , previousDigits [ item . value ] , next , false , true ) ;
474+ drawDigit ( item . x , item . y , item . scale , currentDigits [ item . value ] , previousDigits [ item . value ] , next , false , true ) ;
474475 } else if ( item . type === 'colon' ) {
475476 drawColon ( item . x , item . y , next ) ;
476477 }
996997
997998 // ===== START CLOCK =====
998999 drawClock ( ) ;
999- } ) ( ) ;
1000+ } ) ( ) ;
0 commit comments