tileclk: Optimize digit extraction, simplify RGB565 color interpolation, and streamline border drawing with direct boolean flags
parent
1e9c001725
commit
b28a3116f9
|
|
@ -182,36 +182,35 @@
|
||||||
];
|
];
|
||||||
|
|
||||||
// ===== EFFICIENT COLOR SYSTEM =====
|
// ===== EFFICIENT COLOR SYSTEM =====
|
||||||
// Pre-calculated color tables for animations using typed arrays
|
// Pre-calculated color tables for animations
|
||||||
let colorOn = null, colorOff = null;
|
let colorOn = null, colorOff = null;
|
||||||
|
|
||||||
const initColorTables = () => {
|
const initColorTables = () => {
|
||||||
// Use Uint32Array for maximum performance
|
// Use Uint16Array since Bangle uses RGB565 (16-bit) colors
|
||||||
colorOn = new Uint32Array(FRAC_STEPS + 1);
|
colorOn = new Uint16Array(FRAC_STEPS + 1);
|
||||||
colorOff = new Uint32Array(FRAC_STEPS + 1);
|
colorOff = new Uint16Array(FRAC_STEPS + 1);
|
||||||
|
|
||||||
const bgColor = g.theme.bg;
|
const bgColor = g.theme.bg;
|
||||||
const fgColor = g.theme.fg;
|
const fgColor = g.theme.fg;
|
||||||
|
|
||||||
// Calculate all color transitions
|
// Simple linear interpolation between color values
|
||||||
for (let i = 0; i <= FRAC_STEPS; i++) {
|
for (let i = 0; i <= FRAC_STEPS; i++) {
|
||||||
const frac = i / FRAC_STEPS;
|
const frac = i / FRAC_STEPS;
|
||||||
const invFrac = 1 - frac;
|
|
||||||
|
|
||||||
// Direct calculation for better performance
|
// Direct interpolation of RGB565 values
|
||||||
const rOn = (((bgColor >> 16) & 0xFF) * invFrac + ((fgColor >> 16) & 0xFF) * frac) | 0;
|
colorOn[i] = (bgColor + (fgColor - bgColor) * frac + 0.5) | 0;
|
||||||
const gOn = (((bgColor >> 8) & 0xFF) * invFrac + ((fgColor >> 8) & 0xFF) * frac) | 0;
|
colorOff[i] = (fgColor + (bgColor - fgColor) * frac + 0.5) | 0;
|
||||||
const bOn = ((bgColor & 0xFF) * invFrac + (fgColor & 0xFF) * frac) | 0;
|
|
||||||
const rOff = (((fgColor >> 16) & 0xFF) * invFrac + ((bgColor >> 16) & 0xFF) * frac) | 0;
|
|
||||||
const gOff = (((fgColor >> 8) & 0xFF) * invFrac + ((bgColor >> 8) & 0xFF) * frac) | 0;
|
|
||||||
const bOff = ((fgColor & 0xFF) * invFrac + (bgColor & 0xFF) * frac) | 0;
|
|
||||||
colorOn[i] = (rOn << 16) | (gOn << 8) | bOn;
|
|
||||||
colorOff[i] = (rOff << 16) | (gOff << 8) | bOff;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ===== BORDER DRAWING =====
|
|
||||||
const drawBorder = (x, y, s, thickness) => {
|
// ===== CONSOLIDATED BORDER DRAWING =====
|
||||||
if (!showBorders || thickness <= 0) return;
|
const drawBorder = (x, y, s, isMainDigit) => {
|
||||||
|
if (!showBorders) return;
|
||||||
|
|
||||||
|
// Direct variable lookup is faster than object property access
|
||||||
|
const thickness = isMainDigit ? MAIN_BORDER_THICKNESS : SEC_BORDER_THICKNESS;
|
||||||
|
if (thickness <= 0) return;
|
||||||
|
|
||||||
g.setColor(borderColor);
|
g.setColor(borderColor);
|
||||||
for (let i = 0; i < thickness; i++) {
|
for (let i = 0; i < thickness; i++) {
|
||||||
g.drawRect(x + i, y + i, x + s - 1 - i, y + s - 1 - i);
|
g.drawRect(x + i, y + i, x + s - 1 - i, y + s - 1 - i);
|
||||||
|
|
@ -226,7 +225,7 @@
|
||||||
function transition() {
|
function transition() {
|
||||||
if (!isDrawing || (pendingSwitch && isSeconds)) return;
|
if (!isDrawing || (pendingSwitch && isSeconds)) return;
|
||||||
|
|
||||||
// Use pre-calculated color instead of interpColor()
|
// Use pre-calculated color
|
||||||
g.setColor(colors[step]);
|
g.setColor(colors[step]);
|
||||||
g.fillRect(x, y, x + s - 1, y + s - 1);
|
g.fillRect(x, y, x + s - 1, y + s - 1);
|
||||||
|
|
||||||
|
|
@ -248,15 +247,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function animateTileOn(x, y, s, callback, isMainDigit) {
|
function animateTileOn(x, y, s, callback, isMainDigit) {
|
||||||
const thickness = isMainDigit ? MAIN_BORDER_THICKNESS : SEC_BORDER_THICKNESS;
|
const borderFunc = showBorders ? () => drawBorder(x, y, s, isMainDigit) : null;
|
||||||
const borderFunc = (showBorders && thickness > 0) ?
|
|
||||||
() => drawBorder(x, y, s, thickness) : null;
|
|
||||||
animateTransition(x, y, s, g.theme.bg, g.theme.fg, borderFunc, callback);
|
animateTransition(x, y, s, g.theme.bg, g.theme.fg, borderFunc, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
function animateTileOff(x, y, s, callback) {
|
function animateTileOff(x, y, s, callback) {
|
||||||
animateTransition(x, y, s, g.theme.fg, g.theme.bg, null, callback);
|
animateTransition(x, y, s, g.theme.fg, g.theme.bg, null, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== TILE CALCULATION =====
|
// ===== TILE CALCULATION =====
|
||||||
const calculateTilesToUpdate = (x, y, s, currentDigit, prevDigit) => {
|
const calculateTilesToUpdate = (x, y, s, currentDigit, prevDigit) => {
|
||||||
const currentPacked = digitBitmaps[getDigitIndex(currentDigit)];
|
const currentPacked = digitBitmaps[getDigitIndex(currentDigit)];
|
||||||
|
|
@ -281,15 +279,14 @@
|
||||||
|
|
||||||
return tiles;
|
return tiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== TILE UPDATE =====
|
// ===== TILE UPDATE =====
|
||||||
function updateTile(tile, s, skipAnimation, isMainDigit, isClearing) {
|
function updateTile(tile, s, skipAnimation, isMainDigit, isClearing) {
|
||||||
const thickness = isMainDigit ? MAIN_BORDER_THICKNESS : SEC_BORDER_THICKNESS;
|
|
||||||
|
|
||||||
if (tile.state) {
|
if (tile.state) {
|
||||||
if (skipAnimation) {
|
if (skipAnimation) {
|
||||||
g.setColor(g.theme.fg);
|
g.setColor(g.theme.fg);
|
||||||
g.fillRect(tile.x, tile.y, tile.x + s - 1, tile.y + s - 1);
|
g.fillRect(tile.x, tile.y, tile.x + s - 1, tile.y + s - 1);
|
||||||
drawBorder(tile.x, tile.y, s, thickness);
|
drawBorder(tile.x, tile.y, s, isMainDigit);
|
||||||
} else {
|
} else {
|
||||||
animateTileOn(tile.x, tile.y, s, null, isMainDigit);
|
animateTileOn(tile.x, tile.y, s, null, isMainDigit);
|
||||||
}
|
}
|
||||||
|
|
@ -315,6 +312,7 @@
|
||||||
animationTimeouts[animationTimeoutCount++] = timeout;
|
animationTimeouts[animationTimeoutCount++] = timeout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== DIGIT DRAWING =====
|
// ===== DIGIT DRAWING =====
|
||||||
function drawDigit(x, y, s, num, prevNum, callback, skipAnimation, isMainDigit) {
|
function drawDigit(x, y, s, num, prevNum, callback, skipAnimation, isMainDigit) {
|
||||||
if (num === prevNum) {
|
if (num === prevNum) {
|
||||||
|
|
@ -344,6 +342,7 @@
|
||||||
}, true);
|
}, true);
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== TIME UPDATE SCHEDULING =====
|
// ===== TIME UPDATE SCHEDULING =====
|
||||||
function scheduleNextUpdate() {
|
function scheduleNextUpdate() {
|
||||||
if (drawTimeout) clearTimeout(drawTimeout);
|
if (drawTimeout) clearTimeout(drawTimeout);
|
||||||
|
|
@ -352,6 +351,7 @@
|
||||||
|
|
||||||
drawTimeout = setTimeout(updateAndAnimTime, msUntilNextMinute);
|
drawTimeout = setTimeout(updateAndAnimTime, msUntilNextMinute);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== CLEARING FUNCTIONS (Direct callback approach for performance) =====
|
// ===== CLEARING FUNCTIONS (Direct callback approach for performance) =====
|
||||||
function clearColon(callback) {
|
function clearColon(callback) {
|
||||||
if (!isColonDrawn) {
|
if (!isColonDrawn) {
|
||||||
|
|
@ -417,7 +417,7 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== MAIN TIME UPDATE =====
|
// ===== MAIN TIME UPDATE (OPTIMIZED) =====
|
||||||
function updateAndAnimTime() {
|
function updateAndAnimTime() {
|
||||||
if (!isDrawing) return;
|
if (!isDrawing) return;
|
||||||
|
|
||||||
|
|
@ -426,32 +426,33 @@
|
||||||
const minutesNum = now.getMinutes();
|
const minutesNum = now.getMinutes();
|
||||||
const currentTime = hoursNum * 100 + minutesNum;
|
const currentTime = hoursNum * 100 + minutesNum;
|
||||||
|
|
||||||
// Extract digits only for layout decision
|
// Extract current digits ONCE
|
||||||
const isCurrentThreeDigit = is12Hour && hoursNum < 10;
|
const currentDigits = (() => {
|
||||||
const wasLastThreeDigit = is12Hour && lastTime !== null && lastTime < 1000;
|
|
||||||
|
|
||||||
function drawTime() {
|
|
||||||
// Extract current digits using cached lookups for maximum performance
|
|
||||||
let h1, h2, m1, m2;
|
|
||||||
|
|
||||||
if (timeCache && timeCache.minuteDigits) {
|
if (timeCache && timeCache.minuteDigits) {
|
||||||
const hourCache = is12Hour ? timeCache.hourDigits12 : timeCache.hourDigits24;
|
const hourCache = is12Hour ? timeCache.hourDigits12 : timeCache.hourDigits24;
|
||||||
const minuteCache = timeCache.minuteDigits;
|
const minuteCache = timeCache.minuteDigits;
|
||||||
|
|
||||||
h1 = hourCache[hoursNum * 2];
|
return {
|
||||||
h2 = hourCache[hoursNum * 2 + 1];
|
h1: hourCache[hoursNum * 2],
|
||||||
m1 = minuteCache[minutesNum * 2];
|
h2: hourCache[hoursNum * 2 + 1],
|
||||||
m2 = minuteCache[minutesNum * 2 + 1];
|
m1: minuteCache[minutesNum * 2],
|
||||||
|
m2: minuteCache[minutesNum * 2 + 1]
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
// Fallback to direct calculation
|
return {
|
||||||
h1 = (hoursNum / 10) | 0;
|
h1: (hoursNum / 10) | 0,
|
||||||
h2 = hoursNum % 10;
|
h2: hoursNum % 10,
|
||||||
m1 = (minutesNum / 10) | 0;
|
m1: (minutesNum / 10) | 0,
|
||||||
m2 = minutesNum % 10;
|
m2: minutesNum % 10
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
const digitMap = { h1: h1, h2: h2, m1: m1, m2: m2 };
|
// Determine layout based on extracted digits
|
||||||
|
const isCurrentThreeDigit = is12Hour && currentDigits.h1 === 0;
|
||||||
|
const wasLastThreeDigit = is12Hour && lastTime !== null && lastTime < 1000;
|
||||||
|
|
||||||
|
function drawTime() {
|
||||||
// Extract previous digits (or null for blank)
|
// Extract previous digits (or null for blank)
|
||||||
const previousDigits = (isCurrentThreeDigit !== wasLastThreeDigit && lastTime !== null) ?
|
const previousDigits = (isCurrentThreeDigit !== wasLastThreeDigit && lastTime !== null) ?
|
||||||
{ h1: null, h2: null, m1: null, m2: null } :
|
{ h1: null, h2: null, m1: null, m2: null } :
|
||||||
|
|
@ -470,7 +471,7 @@
|
||||||
const next = () => drawLayout(items, onComplete);
|
const next = () => drawLayout(items, onComplete);
|
||||||
|
|
||||||
if (item.type === 'digit') {
|
if (item.type === 'digit') {
|
||||||
drawDigit(item.x, item.y, item.scale, digitMap[item.value], previousDigits[item.value], next, false, true);
|
drawDigit(item.x, item.y, item.scale, currentDigits[item.value], previousDigits[item.value], next, false, true);
|
||||||
} else if (item.type === 'colon') {
|
} else if (item.type === 'colon') {
|
||||||
drawColon(item.x, item.y, next);
|
drawColon(item.x, item.y, next);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue