Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 17 additions & 33 deletions packages/barcodes/code128.rip
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ codewords =! (text, gs1) ->
fail 'Code 128 text is empty' unless n
cost = Int32Array.new(3 * (n + 1))
move = Uint8Array.new(3 * (n + 1))
i = n - 1
while i >= 0
for i in [n - 1..0] by -1
c = text.charCodeAt i
fnc = c is GS
pair = i + 1 < n and isDigit(c) and isDigit(text.charCodeAt(i + 1))
Expand All @@ -89,14 +88,14 @@ codewords =! (text, gs1) ->
best = 2 + cost[next + 1]
pick = 3
else
inside = if s is 0 then a else b
own = if s is 0 then a else b
other = if s is 0 then b else a
if fnc or inside
if fnc or own
best = 1 + cost[next + s]
if pair and 2 + cost[skip + 2] < best
best = 2 + cost[skip + 2]
pick = 4
if other and not inside and 2 + cost[next + s] < best
if other and not own and 2 + cost[next + s] < best
best = 2 + cost[next + s]
pick = 5
if other and 2 + cost[next + 1 - s] < best
Expand All @@ -105,7 +104,6 @@ codewords =! (text, gs1) ->
fail "Code 128 cannot encode #{JSON.stringify text[i]}" if best is 0x7fffffff
cost[3 * i + s] = best
move[3 * i + s] = pick
i--
s = 1
s = 2 if cost[2] < cost[s]
s = 0 if cost[0] < cost[s]
Expand Down Expand Up @@ -137,8 +135,7 @@ codewords =! (text, gs1) ->
codes.push SHIFT, charValue(c, 1 - s)
i++
sum = codes[0]
for k in [1...codes.length]
sum += k * codes[k]
sum += k * codes[k] for k in [1...codes.length]
codes.push sum % 103, STOP
codes

Expand Down Expand Up @@ -187,31 +184,25 @@ raster =! (mods, scale, border, height) ->

pixelRow =! (r) ->
row = Uint8Array.new(r.W)
for k in [0...r.bars.length] by 2
row.fill 1, r.bars[k], r.bars[k] + r.bars[k + 1]
row.fill 1, r.bars[k], r.bars[k] + r.bars[k + 1] for k in [0...r.bars.length] by 2
row

renderRaw =! (r) ->
row = pixelRow r
out = Array.new(r.W)
for x in [0...r.W]
out[x] = row[x] is 1
out
(row[x] is 1 for x in [0...r.W])

renderAscii =! (r) ->
row = pixelRow r
out = ''
for x in [0...r.W]
out += (if row[x] then ' ' else '█')
out += (if row[x] then ' ' else '█') for x in [0...r.W]
out + '\n'

renderTerm =! (r) ->
row = pixelRow r
black = '\x1b[40m \x1b[0m'
white = '\x1b[1;47m \x1b[0m'
out = ''
for x in [0...r.W]
out += (if row[x] then black else white)
out += (if row[x] then black else white) for x in [0...r.W]
out + '\n'

renderSvg =! (r, optimize) ->
Expand Down Expand Up @@ -256,8 +247,7 @@ export encodeCode128 =! (text, output = 'raw', opts = {}) ->
WIDTHS =! do ->
out = Uint8Array.new(7 * PATTERNS.length)
for pattern, code in PATTERNS
for k in [0...pattern.length]
out[7 * code + k] = pattern.charCodeAt(k) - 48
out[7 * code + k] = pattern.charCodeAt(k) - 48 for k in [0...pattern.length]
out

# Nearest value in lo..hi to the six runs at `at`, or -1: every run within
Expand Down Expand Up @@ -316,9 +306,7 @@ runLengths =! (luma, start, step, count, runs) ->
reverseRuns =! (runs, n, out) ->
m = 0
out[m++] = 0 if (n & 1) is 0
k = n - 1
while k >= 0
out[m++] = runs[k--]
out[m++] = runs[k] for k in [n - 1..0] by -1
m

# Codewords from a start at `at` through stop, check verified; the count, or 0.
Expand All @@ -340,23 +328,20 @@ readFrom =! (runs, n, at, start, codes) ->
at += 6
return 0 if len < 4
sum = codes[0]
for k in [1...len - 2]
sum += k * codes[k]
sum += k * codes[k] for k in [1...len - 2]
return 0 unless sum % 103 is codes[len - 2]
len

# Every start code behind a quiet zone, left to right; `first` is the slot
# of the first dark run, 1 as recorded and 0 to read the line inverted.
readRuns =! (runs, n, codes, first) ->
at = first
while at + 5 < n
for at in [first...n - 5] by 2
start = nearest runs, at, START_A, STOP - 1
if start >= 0
width = runs[at] + runs[at + 1] + runs[at + 2] + runs[at + 3] + runs[at + 4] + runs[at + 5]
if at is first or 2 * runs[at - 1] >= width
len = readFrom runs, n, at, start, codes
return len if len
at += 2
0

# Text from verified codewords, tracking latches, shifts, FNC1 and FNC4.
Expand All @@ -368,9 +353,8 @@ decodeText =! (codes, len) ->
lastFnc4 = false
gs1 = false
out = ''
k = 1
while k < len - 2
code = codes[k++]
for k in [1...len - 2]
code = codes[k]
current = if shifted >= 0 then shifted else subset
shifted = -1
fnc4 = false
Expand All @@ -379,7 +363,7 @@ decodeText =! (codes, len) ->
out += (if code < 10 then '0' else '') + code
else if code is CODE_B then subset = 1
else if code is CODE_A then subset = 0
else if k is 2 then gs1 = true
else if k is 1 then gs1 = true
else out += '\x1d'
else if code < 96
c = if code < 64 then code + 32 else if current is 0 then code - 64 else code + 32
Expand All @@ -395,7 +379,7 @@ decodeText =! (codes, len) ->
when CODE_A
if current is 1 then subset = 0 else fnc4 = true
when FNC1
if k is 2 then gs1 = true else out += '\x1d'
if k is 1 then gs1 = true else out += '\x1d'
if fnc4
if lastFnc4
high = not high
Expand Down
36 changes: 13 additions & 23 deletions packages/barcodes/dom.rip
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ clearCanvas =! (cc) ->
traceQuad =! (context, points) ->
context.beginPath()
context.moveTo points[0].x, points[0].y
for i in [1...points.length]
context.lineTo points[i].x, points[i].y
context.lineTo points[i].x, points[i].y for i in [1...points.length]
context.closePath()

fillQuad =! (context, points) ->
Expand Down Expand Up @@ -97,11 +96,9 @@ sameOverlays = (left, right) ->
[right[i], right[match]] = [right[match], right[i]] if match isnt i
true

copyOverlays =! (target, source) ->
copyOverlays! =! (target, source) ->
target.length = source.length
for i in [0...source.length]
target[i] = source[i]
return
target[i] = source[i] for i in [0...source.length]

# Drawing and decode options, with defaults.
canvasDefaults = ->
Expand Down Expand Up @@ -167,20 +164,18 @@ export class QRCanvas
@drawBitmap img
@scanner = Scanner.new(decoder)
@reader =
clean: =>
clean!: =>
@generation++
@task?.abort()
@task = undefined
if @pending then @cleanPending = true else @scanner.clean()
return
crop: @opts.cropToSquare
luma: @scanner.luma
frame: @opts.onVideoFrame
source: (source) =>
source!: (source) =>
return if source is @frameSource
@frameSource = source
@opts.onFrameSource source if @opts.onFrameSource
return
read: (frame) =>
@rotate = frame.rotate
@sourceHeight = frame.sourceHeight
Expand Down Expand Up @@ -208,7 +203,7 @@ export class QRCanvas
onPoints!: (points, result) ->
@resetOverlay() if Date.now() - @lastDetect > @opts.overlayTimeout
if @rotate or @sourceX or @sourceY
move = (point) =>
move! = (point) =>
x = point.x + @sourceX
y = point.y + @sourceY
if @rotate
Expand All @@ -217,7 +212,6 @@ export class QRCanvas
else
point.x = x
point.y = y
return
move point for point in [points.tl, points.tr, points.br, points.bl, ...points.aligners]
for marker in [points.tl, points.tr, points.bl, ...points.aligners]
move point for point in marker.corners
Expand Down Expand Up @@ -336,8 +330,7 @@ export class QRCanvas
for x in [0...width]
src = 4 * (y * width + x)
dst = 4 * (x * height + height - 1 - y)
for k in [0...4]
out[dst + k] = data[src + k]
out[dst + k] = data[src + k] for k in [0...4]
[width, height] = [height, width]
else
out = Uint8ClampedArray.from data
Expand Down Expand Up @@ -448,13 +441,12 @@ export class QRCanvas
return if generation isnt @generation
@endDecode()
@finish()
settle = =>
settle! = =>
@pending = undefined if @pending is pending
@task = undefined if @task is task
if @cleanPending
@cleanPending = false
@scanner.clean()
return
pending = work.then(onDone, onFail).finally(settle)
@pending = pending
pending
Expand Down Expand Up @@ -647,7 +639,7 @@ export class QRCamera

# Stop first so constrained camera hardware is released before the
# replacement stream is requested.
setDevice: (deviceId) ->
setDevice!: (deviceId) ->
@stop()
source = @source
stream = navigator.mediaDevices.getUserMedia! video: { deviceId: { exact: deviceId } }
Expand All @@ -656,7 +648,6 @@ export class QRCamera
track.stop() for track in stream.getTracks()
return
@setStream stream
return

draw: (canvas, fullSize) ->
player = @player
Expand Down Expand Up @@ -715,14 +706,14 @@ export class QRCamera
return if @player.videoWidth isnt videoWidth or @player.videoHeight isnt videoHeight
@videoFrame = true
reader.source 'VideoFrame'
return reader.read(scanned)
reader.read scanned
catch
@resetFrame()
return if source isnt @source
# A constructor can exist while copyTo support does not; only the
# first frame of a source pays for finding out.
@videoFrame = false
return @draw(canvas, fullSize)
@draw canvas, fullSize
finally
frame.close()
@reading = false
Expand Down Expand Up @@ -753,11 +744,10 @@ export frameLoop =! (cb, video) ->
useVideo = !!video and typeof video.requestVideoFrameCallback is 'function' and typeof video.cancelVideoFrameCallback is 'function'
active = true
handle = undefined
loopFn = (ts) ->
loopFn! = (ts) ->
# Check active after the callback: it may cancel the loop from inside.
cb ts
handle = request() if active
return
request = -> if useVideo then video.requestVideoFrameCallback(loopFn) else requestAnimationFrame(loopFn)
cancel = (id) -> if useVideo then video.cancelVideoFrameCallback(id) else cancelAnimationFrame(id)
handle = request()
Expand Down Expand Up @@ -804,7 +794,7 @@ export gifToPng =! (gifBytes) ->
ctx = canvas.getContext 'bitmaprenderer', { alpha: false }
throw Error.new 'was not able to create bitmaprenderer context' unless ctx
ctx.transferFromImageBitmap bitmap
return canvas.convertToBlob!({ type: 'image/png' })
canvas.convertToBlob!({ type: 'image/png' })
finally
bitmap.close()

Expand Down
8 changes: 2 additions & 6 deletions packages/barcodes/gif.rip
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ export writeGif =! (W, H, rowFor) ->
tail = pixels % N
out = Uint8Array.new(408 + fullChunks * (N + 2) + 2 + tail + 4)
pos = 0
u16 = (v) ->
u16! = (v) ->
out[pos++] = v & 0xff
out[pos++] = v >>> 8
return
for b in [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]
out[pos++] = b
u16 W
Expand Down Expand Up @@ -63,9 +62,6 @@ export gifDataUrl =! (gif) ->
gif.toBase64()
else
bin = ''
i = 0
while i < gif.length
bin += String.fromCharCode(...gif.subarray(i, i + 8192))
i += 8192
bin += String.fromCharCode(...gif.subarray(i, i + 8192)) for i in [0...gif.length] by 8192
btoa bin
'data:image/gif;base64,' + b64
20 changes: 7 additions & 13 deletions packages/barcodes/image.rip
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,9 @@ export LITTLE_ENDIAN =! Uint8Array.new(Uint32Array.new([1]).buffer)[0] is 1
# three, unrolled four wide, the same (r + 2g + b) / 4 luma. Alpha and the X
# byte fall out of the mask, and the weights are symmetric in r and b, so
# every RGBA/BGRA/X layout takes this path.
copyWords =! (out, data, byteStart, n) ->
copyWords! =! (out, data, byteStart, n) ->
words = Uint32Array.new(data.buffer, byteStart, n)
i = 0
end = n - 3
while i < end
for i in [0...n - 3] by 4
p = words[i]
q = words[i + 1]
r = words[i + 2]
Expand All @@ -72,28 +70,25 @@ copyWords =! (out, data, byteStart, n) ->
out[i + 1] = ((q & 255) + ((q >>> 7) & 510) + ((q >>> 16) & 255)) >> 2
out[i + 2] = ((r & 255) + ((r >>> 7) & 510) + ((r >>> 16) & 255)) >> 2
out[i + 3] = ((s & 255) + ((s >>> 7) & 510) + ((s >>> 16) & 255)) >> 2
i += 4
while i < n
for i in [n - (n & 3)...n]
p = words[i]
out[i] = ((p & 255) + ((p >>> 7) & 510) + ((p >>> 16) & 255)) >> 2
i++
return

# Convert any input into the tight native luma plane.
export copyLuma =! (out, maxSize, img, named, layout) ->
export copyLuma! =! (out, maxSize, img, named, layout) ->
{step, bits} = validateImage img, named, layout, maxSize
{width, height, data} = img
stride = layout?.stride or width * step
offset = layout?.offset or 0
return if data is out and not offset and stride is width and step is 1
if step is 4 and LITTLE_ENDIAN and stride is width * 4 and ((data.byteOffset + offset) & 3) is 0
return copyWords out, data, data.byteOffset + offset, width * height
copyWords out, data, data.byteOffset + offset, width * height
return
for y in [0...height]
src = offset + y * stride
dst = y * width
if step is 1
for x in [0...width]
out[dst++] = data[src++]
out[dst++] = data[src++] for x in [0...width]
else if step is 2
for x in [0...width]
out[dst++] = (data[src] | (data[src + 1] << 8)) >>> (bits - 8)
Expand All @@ -102,7 +97,6 @@ export copyLuma =! (out, maxSize, img, named, layout) ->
for x in [0...width]
out[dst++] = (data[src] + 2 * data[src + 1] + data[src + 2]) >> 2
src += step
return

# RGBA image from a per-pixel dark predicate.
export darkToImage =! (width, height, isDark) ->
Expand Down
Loading