-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Erik Corry
committed
Nov 28, 2023
1 parent
43451b5
commit 082021d
Showing
9 changed files
with
269 additions
and
153 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// Copyright (C) 2023 Toitware ApS. All rights reserved. | ||
// Use of this source code is governed by an MIT-style license that can be | ||
// found in the LICENSE file. | ||
import font show Font | ||
|
||
import .common | ||
import .element show CustomElement | ||
import .style | ||
|
||
EAN_13_QUIET_ZONE_WIDTH ::= 9 | ||
EAN_13_START_WIDTH ::= 3 | ||
EAN_13_MIDDLE_WIDTH ::= 5 | ||
EAN_13_DIGIT_WIDTH ::= 7 | ||
EAN_13_BOTTOM_SPACE ::= 5 | ||
EAN_13_WIDTH ::= 2 * EAN_13_QUIET_ZONE_WIDTH + 2 * EAN_13_START_WIDTH + EAN_13_MIDDLE_WIDTH + 12 * EAN_13_DIGIT_WIDTH | ||
EAN_13_HEIGHT ::= 83 | ||
// Encoding of L digits. R digits are the bitwise-not of this and G digits are | ||
// the R digits in reverse order. | ||
EAN_13_L_CODES_ ::= [0x0d, 0x19, 0x13, 0x3d, 0x23, 0x31, 0x2f, 0x3b, 0x37, 0x0b] | ||
EAN_13_G_CODES_ ::= [0x27, 0x33, 0x1b, 0x21, 0x1d, 0x39, 0x05, 0x11, 0x09, 0x17] | ||
// Encoding of the first (invisible) digit. | ||
EAN_13_FIRST_CODES_ ::= [0x00, 0x0b, 0x0d, 0x0e, 0x13, 0x19, 0x1c, 0x15, 0x16, 0x1a] | ||
|
||
// Element that draws a standard EAN-13 bar code. TODO: Other scales. | ||
class BarCodeEanElement extends CustomElement: | ||
color_/int? := 0 | ||
background_ := 0xff | ||
sans10_ ::= Font.get "sans10" | ||
number_height_ := EAN_13_BOTTOM_SPACE | ||
|
||
type -> string: return "bar-code-ean" | ||
|
||
set_attribute key/string value -> none: | ||
if key == "color": | ||
if color_ != value: | ||
invalidate | ||
color_ = value | ||
else: | ||
super key value | ||
|
||
code_ := ? // 13 digit code as a string. | ||
code= value/string -> none: | ||
if value != code_: invalidate | ||
code_ = value | ||
|
||
code -> string: return code_ | ||
|
||
/** | ||
$code_: The 13 digit product code. | ||
$x: The left edge of the barcode in the coordinate system of the transform. | ||
$y: The top edge of the barcode in the coordinate system of the transform. | ||
Use $set_styles to set the background to white and the color to black. | ||
*/ | ||
constructor .code_/string --x/int?=null --y/int?=null: | ||
// The numbers go below the bar code in a way that depends on the size | ||
// of the digits, so we need to take that into account when calculating | ||
// the bounding box. | ||
number_height_ = (sans10_.text_extent "8")[1] | ||
height := EAN_13_HEIGHT + number_height_ - EAN_13_BOTTOM_SPACE | ||
w := EAN_13_WIDTH | ||
h := height + 1 | ||
super --x=x --y=y --w=w --h=h | ||
|
||
l_ digit: | ||
return EAN_13_L_CODES_[digit & 0xf] | ||
|
||
g_ digit: | ||
return EAN_13_G_CODES_[digit & 0xf] | ||
|
||
r_ digit: | ||
return (l_ digit) ^ 0x7f | ||
|
||
// Make a white background behind the bar code and draw the digits along the bottom. | ||
draw_background_ canvas/Canvas: | ||
if not (x and y): return | ||
Background.draw background_ canvas x_ y_ w h | ||
|
||
// Bar code coordinates. | ||
text_x := x + EAN_13_QUIET_ZONE_WIDTH + EAN_13_START_WIDTH | ||
text_y := y + EAN_13_HEIGHT + number_height_ - EAN_13_BOTTOM_SPACE + 1 | ||
|
||
canvas.text (x + 1) text_y --text=code_[..1] --color=color_ --font=sans10_ | ||
|
||
code_[1..7].split "": | ||
if it != "": | ||
canvas.text text_x text_y --text=it --color=color_ --font=sans10_ | ||
text_x += EAN_13_DIGIT_WIDTH | ||
text_x += EAN_13_MIDDLE_WIDTH - 1 | ||
code_[7..13].split "": | ||
if it != "": | ||
canvas.text text_x text_y --text=it --color=color_ --font=sans10_ | ||
text_x += EAN_13_DIGIT_WIDTH | ||
marker_width := (sans10_.text_extent ">")[0] | ||
text_x += EAN_13_START_WIDTH + EAN_13_QUIET_ZONE_WIDTH - marker_width | ||
canvas.text text_x text_y --text=">" --color=color_ --font=sans10_ | ||
|
||
// Redraw routine. | ||
draw canvas/Canvas: | ||
if not (x and y): return | ||
if (canvas.bounds_analysis x y w h) == Canvas.ALL_OUTSIDE: return | ||
draw_background_ canvas | ||
|
||
x := x_ + EAN_13_QUIET_ZONE_WIDTH | ||
top := y_ | ||
long_height := EAN_13_HEIGHT | ||
short_height := EAN_13_HEIGHT - EAN_13_BOTTOM_SPACE | ||
// Start bars: 101. | ||
canvas.rectangle x top --w=1 --h=long_height --color=color_ | ||
canvas.rectangle x + 2 top --w=1 --h=long_height --color=color_ | ||
x += 3 | ||
first_code := EAN_13_FIRST_CODES_[code_[0] & 0xf] | ||
// Left digits using the L or G mapping. | ||
for i := 1; i < 7; i++: | ||
digit := code_[i] | ||
code := ((first_code >> (6 - i)) & 1) == 0 ? (l_ digit) : (g_ digit) | ||
for b := 6; b >= 0; b--: | ||
if ((1 << b) & code) != 0: | ||
canvas.rectangle x top --w=1 --h=short_height --color=color_ | ||
x++ | ||
// Middle bars: 01010 | ||
canvas.rectangle x + 1 top --w=1 --h=long_height --color=color_ | ||
canvas.rectangle x + 3 top --w=1 --h=long_height --color=color_ | ||
x += 5 | ||
// Left digits using the R mapping. | ||
for i := 7; i < 13; i++: | ||
digit := code_[i] | ||
code := r_ digit | ||
for b := 6; b >= 0; b--: | ||
if ((1 << b) & code) != 0: | ||
canvas.rectangle x top --w=1 --h=short_height --color=color_ | ||
x++ | ||
// End bars: 101. | ||
canvas.rectangle x top --w=1 --h=long_height --color=color_ | ||
canvas.rectangle x + 2 top --w=1 --h=long_height --color=color_ |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.