DeviceListener: Rejig calculateGestureDelta algorithm

Get rid of the silly precomputed tables, and do More Maths(TM) instead!
Thanks to @zwim for the magic sauce ;).

Minor simplification of the API while I'm in there, and unify the warmth
computations, do everything in the native scale (much like what
effectively happens for intensity) to workaround the silly public API
being an unhelpful PITA, ensuring consistent & effective changes.
reviewable/pr11238/r1
zwim 5 months ago committed by NiLuJe
parent a2e0642998
commit c30c1ff11f

@ -55,68 +55,54 @@ if Device:hasFrontlight() then
local function calculateGestureDelta(ges, direction, min, max)
local delta_int
if type(ges) == "table" then
-- here we are using just two scales
-- big scale is for high dynamic ranges (e.g. brightness from 1..100)
-- original scale maybe tuned by hand
-- small scale is for lower dynamic ranges (e.g. warmth from 1..10)
-- scale entries are calculated by math.round(1*sqrt(2)^n)
--- @fixme: An intermediary scale is probably necessary for Kindle, which goes from 0 to 24...
local steps_fl_big_scale = { 0.1, 0.1, 0.2, 0.4, 0.7, 1.1, 1.6, 2.2, 2.9, 3.7, 4.6, 5.6, 6.7, 7.9, 9.2, 10.6, }
local steps_fl_small_scale = { 1.0, 1.0, 2.0, 3.0, 4.0, 6.0, 8.1, 11.3 }
local steps_fl = steps_fl_big_scale
if (max - min) < 50 then
steps_fl = steps_fl_small_scale
end
local gestureScale
local scale_multiplier
local gesture_multiplier
if ges.ges == "two_finger_swipe" or ges.ges == "swipe" then
scale_multiplier = 0.8
gesture_multiplier = 0.8
else
scale_multiplier = 1
gesture_multiplier = 1
end
local gestureScale
if ges.direction == "south" or ges.direction == "north" then
gestureScale = Screen:getHeight() * scale_multiplier
gestureScale = Screen:getHeight() * gesture_multiplier
elseif ges.direction == "west" or ges.direction == "east" then
gestureScale = Screen:getWidth() * scale_multiplier
gestureScale = Screen:getWidth() * gesture_multiplier
else
local width = Screen:getWidth()
local height = Screen:getHeight()
-- diagonal
gestureScale = math.sqrt(width * width + height * height) * scale_multiplier
end
local steps_tbl = {}
local scale = (max - min) / steps_fl[#steps_fl] / 2 -- full swipe gives half scale
for i = 1, #steps_fl, 1 do
steps_tbl[i] = math.ceil(steps_fl[i] * scale)
gestureScale = math.sqrt(width^2 + height^2) * gesture_multiplier
end
-- In case we're passed a gesture that doesn't imply movement (e.g., tap or hold)
if ges.distance == nil then
ges.distance = 1
end
local step = math.ceil(#steps_tbl * ges.distance / gestureScale)
delta_int = steps_tbl[step] or steps_tbl[#steps_tbl]
-- delta_int is calculated by a function f(x) = coeff * x^2
-- *) f(x) has the boundary condition: f(1) = max/2;
-- *) x is roughly the swipe distance as a fraction of the screen geometry,
-- clamped between 0 and 1
local x = math.min(1, ges.distance / gestureScale)
delta_int = math.ceil(1/2 * max * x^2)
else
-- received amount to change
-- The ges arg passed by our caller wasn't a gesture, but an absolute integer increment
delta_int = ges
end
if direction ~= -1 and direction ~= 1 then
-- set default value (increase frontlight)
-- If the caller didn't specify, opt to *increase* by default
direction = 1
end
return direction, delta_int
return direction * delta_int
end
-- direction +1 - increase frontlight
-- direction -1 - decrease frontlight
function DeviceListener:onChangeFlIntensity(ges, direction)
local powerd = Device:getPowerDevice()
local delta_int
direction, delta_int = calculateGestureDelta(ges, direction, powerd.fl_min, powerd.fl_max)
local delta = calculateGestureDelta(ges, direction, powerd.fl_min, powerd.fl_max)
local new_intensity = powerd:frontlightIntensity() + direction * delta_int
local new_intensity = powerd:frontlightIntensity() + delta
-- when new_intensity <= 0, toggle light off
self:onSetFlIntensity(new_intensity)
self:onShowIntensity()
@ -149,17 +135,13 @@ if Device:hasFrontlight() then
if not Device:hasNaturalLight() then return true end
local powerd = Device:getPowerDevice()
local delta_int
direction, delta_int = calculateGestureDelta(ges, direction, powerd.fl_warmth_min, powerd.fl_warmth_max)
local delta = calculateGestureDelta(ges, direction, powerd.fl_warmth_min, powerd.fl_warmth_max)
local warmth
if type(ges) == "table" then
-- received a gesture, scale the gesture delta to the API range
warmth = powerd:frontlightWarmth() + powerd:fromNativeWarmth(direction * delta_int)
else
-- received an absolute increment, use it as-is in the native scale
warmth = powerd:fromNativeWarmth(powerd:toNativeWarmth(powerd:frontlightWarmth()) + ges)
end
-- Given that the native warmth ranges are usually pretty restrictive (e.g., [0, 10] or [0, 24]),
-- do the computations in the native scale, to ensure we always actually *change* something,
-- in case both the old and new value would round to the same native step,
-- despite being different in the API scale, which is stupidly fixed at [0, 100]...
local warmth = powerd:fromNativeWarmth(powerd:toNativeWarmth(powerd:frontlightWarmth()) + delta)
self:onSetFlWarmth(warmth)
self:onShowWarmth()

Loading…
Cancel
Save