diff options
Diffstat (limited to 'source/codes/Codes.mc')
| -rw-r--r-- | source/codes/Codes.mc | 72 |
1 files changed, 69 insertions, 3 deletions
diff --git a/source/codes/Codes.mc b/source/codes/Codes.mc index 247acfa..9527a75 100644 --- a/source/codes/Codes.mc +++ b/source/codes/Codes.mc @@ -7,6 +7,7 @@ // come back as a CodeError with a message for the user, never an exception. import Toybox.Lang; +import Toybox.System; module Codes { @@ -174,6 +175,12 @@ module Codes { result[6] = matrix.rowHeight; } + // Progress 0-99 through the bytes. + function percent() as Number { + var full = _matrix.modules.size() / 8; + return full > 0 ? 99 * _i / full : 0; + } + function step(budget as Number) as Boolean { var m = _matrix.modules; var n = m.size(); @@ -235,6 +242,11 @@ module Codes { result = new Runs(packed); } + // Progress 0-99 through the rows. + function percent() as Number { + return 99 * _row / _packed.height; + } + function step(budget as Number) as Boolean { var p = _packed; var w = p.width; @@ -276,31 +288,63 @@ module Codes { // A 2D code from the cache or a fresh encoding to Runs: encode (unless // cached), pack (`cache` then holds the bytes to store), find the runs. + // percent() follows the work: the encoder's share of 0-100 comes from + // its stageEnds(), then the packer's, then the run finder's; a cached + // code only runs the finder, over the whole range. class DisplayJob extends Jobs.Job { var error as String? = null; var cache as ByteArray? = null; var runs as Runs? = null; + // Milliseconds spent in each stage's steps (encode, pack, runs), for + // the debug log. + var stageMs as Array<Number> = [0, 0, 0]; private var _encoder as MatrixJob?; private var _packer as Packer? = null; private var _finder as RunFinder? = null; + private var _encodeEnd as Number = 0; + private var _packEnd as Number = 0; // Either an encoder (fresh) or the cached bytes. function initialize(encoder as MatrixJob?, packed as Packed?) { Job.initialize(); _encoder = encoder; + if (encoder != null) { + var ends = encoder.stageEnds(); + _encodeEnd = ends[0]; + _packEnd = ends[1]; + } if (packed != null) { _finder = new RunFinder(packed); } } - // Progress 0-100: encoding is most of it. + // Progress 0-99 (100 is never shown: the code replaces this screen), + // never going back: each stage starts where the one before ended. function percent() as Number { var e = _encoder; - return e != null ? e.percent() * 9 / 10 : 90; + var p = _packer; + var f = _finder; + var done = 0; + if (e != null) { + done = e.percent() * _encodeEnd / 100; + } else if (p != null) { + done = _encodeEnd + (_packEnd - _encodeEnd) * p.percent() / 100; + } else if (f != null) { + done = _packEnd + (100 - _packEnd) * f.percent() / 100; + } + return done < 99 ? done : 99; } function step(budget as Number) as Boolean { + var started = System.getTimer(); + var stage = _finder != null ? 2 : (_packer != null ? 1 : 0); + var done = advance(budget); + stageMs[stage] += System.getTimer() - started; + return done; + } + + private function advance(budget as Number) as Boolean { var finder = _finder; if (finder != null) { if (!finder.step(budget)) { @@ -344,11 +388,20 @@ module Codes { Job.initialize(); } - // Progress 0-100 for the UI. + // Progress 0-100 for the UI, following the work done so far. function percent() as Number { return 0; } + // Where the pack and the run stages begin in a display job's 0-100 + // (the encoding is [0, ends[0]], packing [ends[0], ends[1]], the + // runs the rest), weighted by their time in the simulator's + // benchmark: encoding takes by far the most, except for PDF417, + // whose wide matrices make the runs a third. + function stageEnds() as Array<Number> { + return [90, 92]; + } + function matrix() as Matrix? { return null; } @@ -379,6 +432,19 @@ module Codes { return isLinear(symbology) || symbology == PDF417 ? 1 : 2; } + // Progress 0-100 through phases: ends[i] is the percent at the end of + // phase i; `done` of `total` is how far the current phase has got (it + // may be a flat 0 for a phase that reports no progress). A finished job + // (phase past the last) is 100. Never goes back while `done` doesn't. + function phased(ends as Array<Number>, phase as Number, done as Number, total as Number) as Number { + if (phase >= ends.size()) { + return 100; + } + var from = phase > 0 ? ends[phase - 1] : 0; + var inside = total > 0 && done > 0 ? (done < total ? done : total) : 0; + return from + (ends[phase] - from) * inside / (total > 0 ? total : 1); + } + // True when a code of w x h modules (quiet zone included) at px pixels // per module fits the screen: inside the circle (less a 4 px margin) on // round screens; elsewhere the full width and the height less room for |
