img_to_script 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +25 -0
  3. data/.vscode/launch.json +21 -0
  4. data/CHANGELOG.md +7 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +271 -0
  7. data/Rakefile +16 -0
  8. data/img_to_script.gemspec +41 -0
  9. data/lib/img_to_script/abs_token_type.rb +33 -0
  10. data/lib/img_to_script/abstract_token/abs_func.rb +19 -0
  11. data/lib/img_to_script/abstract_token/abstract_token.rb +23 -0
  12. data/lib/img_to_script/abstract_token/assign_value.rb +20 -0
  13. data/lib/img_to_script/abstract_token/clear_screen.rb +16 -0
  14. data/lib/img_to_script/abstract_token/data_read.rb +19 -0
  15. data/lib/img_to_script/abstract_token/data_store.rb +19 -0
  16. data/lib/img_to_script/abstract_token/draw_chunk_by_hex_value.rb +19 -0
  17. data/lib/img_to_script/abstract_token/draw_line_by_abs_coords.rb +22 -0
  18. data/lib/img_to_script/abstract_token/draw_pixel_by_abs_coords.rb +20 -0
  19. data/lib/img_to_script/abstract_token/go_to.rb +19 -0
  20. data/lib/img_to_script/abstract_token/if_condition.rb +20 -0
  21. data/lib/img_to_script/abstract_token/loop_begin.rb +21 -0
  22. data/lib/img_to_script/abstract_token/loop_end.rb +19 -0
  23. data/lib/img_to_script/abstract_token/math_add.rb +20 -0
  24. data/lib/img_to_script/abstract_token/math_greater_than.rb +20 -0
  25. data/lib/img_to_script/abstract_token/math_mult.rb +20 -0
  26. data/lib/img_to_script/abstract_token/math_sub.rb +20 -0
  27. data/lib/img_to_script/abstract_token/move_point_to_abs_coords.rb +20 -0
  28. data/lib/img_to_script/abstract_token/parentheses.rb +19 -0
  29. data/lib/img_to_script/abstract_token/program_begin.rb +16 -0
  30. data/lib/img_to_script/abstract_token/program_end.rb +16 -0
  31. data/lib/img_to_script/abstract_token/remark.rb +19 -0
  32. data/lib/img_to_script/abstract_token/sign_func.rb +19 -0
  33. data/lib/img_to_script/abstract_token/wait.rb +19 -0
  34. data/lib/img_to_script/abstract_token.rb +8 -0
  35. data/lib/img_to_script/container.rb +26 -0
  36. data/lib/img_to_script/current_line_placeholder.rb +40 -0
  37. data/lib/img_to_script/formatter.rb +34 -0
  38. data/lib/img_to_script/generators/generator.rb +134 -0
  39. data/lib/img_to_script/generators/hex_mask/default.rb +24 -0
  40. data/lib/img_to_script/generators/hex_mask/enhanced.rb +220 -0
  41. data/lib/img_to_script/generators/hex_mask/hex_mask.rb +100 -0
  42. data/lib/img_to_script/generators/hex_mask.rb +13 -0
  43. data/lib/img_to_script/generators/run_length_encoding/horizontal.rb +78 -0
  44. data/lib/img_to_script/generators/run_length_encoding/run_length_encoding.rb +304 -0
  45. data/lib/img_to_script/generators/run_length_encoding/vertical.rb +79 -0
  46. data/lib/img_to_script/generators/run_length_encoding.rb +10 -0
  47. data/lib/img_to_script/generators/segmental/data_read_draw/data_read_draw.rb +70 -0
  48. data/lib/img_to_script/generators/segmental/data_read_draw/horizontal.rb +54 -0
  49. data/lib/img_to_script/generators/segmental/data_read_draw/vertical.rb +54 -0
  50. data/lib/img_to_script/generators/segmental/data_read_draw.rb +18 -0
  51. data/lib/img_to_script/generators/segmental/direct_draw/direct_draw.rb +62 -0
  52. data/lib/img_to_script/generators/segmental/direct_draw/horizontal.rb +16 -0
  53. data/lib/img_to_script/generators/segmental/direct_draw/vertical.rb +16 -0
  54. data/lib/img_to_script/generators/segmental/direct_draw.rb +12 -0
  55. data/lib/img_to_script/generators/segmental/horizontal_mixin.rb +32 -0
  56. data/lib/img_to_script/generators/segmental/segmental.rb +101 -0
  57. data/lib/img_to_script/generators/segmental/vertical_mixin.rb +38 -0
  58. data/lib/img_to_script/generators/segmental.rb +10 -0
  59. data/lib/img_to_script/generators.rb +27 -0
  60. data/lib/img_to_script/import.rb +5 -0
  61. data/lib/img_to_script/language_token.rb +8 -0
  62. data/lib/img_to_script/languages/mk90_basic/formatters/formatter.rb +49 -0
  63. data/lib/img_to_script/languages/mk90_basic/formatters/minificator.rb +316 -0
  64. data/lib/img_to_script/languages/mk90_basic/formatters/sliceable_tokens_mixin.rb +15 -0
  65. data/lib/img_to_script/languages/mk90_basic/formatters.rb +13 -0
  66. data/lib/img_to_script/languages/mk90_basic/mk90_basic_token.rb +59 -0
  67. data/lib/img_to_script/languages/mk90_basic/translators/mixin.rb +205 -0
  68. data/lib/img_to_script/languages/mk90_basic/translators/mk90_basic_10.rb +27 -0
  69. data/lib/img_to_script/languages/mk90_basic/translators/mk90_basic_20.rb +27 -0
  70. data/lib/img_to_script/languages/mk90_basic/translators/translator.rb +205 -0
  71. data/lib/img_to_script/languages/mk90_basic/translators.rb +13 -0
  72. data/lib/img_to_script/languages/mk90_basic.rb +17 -0
  73. data/lib/img_to_script/languages.rb +10 -0
  74. data/lib/img_to_script/task.rb +26 -0
  75. data/lib/img_to_script/translator.rb +31 -0
  76. data/lib/img_to_script/version.rb +5 -0
  77. data/lib/img_to_script.rb +19 -0
  78. data/sig/img_to_script.rbs +4 -0
  79. metadata +204 -0
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module AbstractToken
5
+ #
6
+ # Begin a loop.
7
+ #
8
+ class LoopBegin < AbstractToken
9
+ attr_reader :var_name, :start_value, :end_value
10
+
11
+ def initialize(var_name:, start_value:, end_value:, **)
12
+ @type = AbsTokenType::LOOP_BEGIN
13
+ @var_name = var_name
14
+ @start_value = start_value
15
+ @end_value = end_value
16
+
17
+ super
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module AbstractToken
5
+ #
6
+ # Marks loop end.
7
+ #
8
+ class LoopEnd < AbstractToken
9
+ attr_reader :var_name
10
+
11
+ def initialize(var_name:, **)
12
+ @var_name = var_name
13
+ @type = AbsTokenType::LOOP_END
14
+
15
+ super
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module AbstractToken
5
+ #
6
+ # Addition arithmetical operation.
7
+ #
8
+ class MathAdd < AbstractToken
9
+ attr_reader :left, :right
10
+
11
+ def initialize(left:, right:, **)
12
+ @type = AbsTokenType::MATH_ADD
13
+ @left = left
14
+ @right = right
15
+
16
+ super
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module AbstractToken
5
+ #
6
+ # left > right.
7
+ #
8
+ class MathGreaterThan < AbstractToken
9
+ attr_reader :left, :right
10
+
11
+ def initialize(left:, right:, **)
12
+ @type = AbsTokenType::MATH_GREATER_THAN
13
+ @left = left
14
+ @right = right
15
+
16
+ super
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module AbstractToken
5
+ #
6
+ # Multiplication arithmetical operation.
7
+ #
8
+ class MathMult < AbstractToken
9
+ attr_reader :left, :right
10
+
11
+ def initialize(left:, right:, **)
12
+ @type = AbsTokenType::MATH_MULT
13
+ @left = left
14
+ @right = right
15
+
16
+ super
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module AbstractToken
5
+ #
6
+ # Subtraction arithmetical operation.
7
+ #
8
+ class MathSub < AbstractToken
9
+ attr_reader :left, :right
10
+
11
+ def initialize(left:, right:, **)
12
+ @type = AbsTokenType::MATH_SUB
13
+ @left = left
14
+ @right = right
15
+
16
+ super
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module AbstractToken
5
+ #
6
+ # Move point to the (x, y) position (in the absolute coordinates).
7
+ #
8
+ class MovePointToAbsCoords < AbstractToken
9
+ attr_reader :x, :y
10
+
11
+ def initialize(x:, y:, **)
12
+ @x = x
13
+ @y = y
14
+ @type = AbsTokenType::MOVE_POINT_TO_ABS_COORDS
15
+
16
+ super
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module AbstractToken
5
+ #
6
+ # Wrap an expression into parentheses.
7
+ #
8
+ class Parentheses < AbstractToken
9
+ attr_reader :expression
10
+
11
+ def initialize(expression:, **)
12
+ @type = AbsTokenType::PARENTHESES
13
+ @expression = expression
14
+
15
+ super
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module AbstractToken
5
+ #
6
+ # Marks begin of the program.
7
+ #
8
+ class ProgramBegin < AbstractToken
9
+ def initialize(**)
10
+ @type = AbsTokenType::PROGRAM_BEGIN
11
+
12
+ super
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module AbstractToken
5
+ #
6
+ # Marks end of the program.
7
+ #
8
+ class ProgramEnd < AbstractToken
9
+ def initialize(**)
10
+ @type = AbsTokenType::PROGRAM_END_LBL
11
+
12
+ super
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module AbstractToken
5
+ #
6
+ # Remark - a comment.
7
+ #
8
+ class Remark < AbstractToken
9
+ attr_reader :text
10
+
11
+ def initialize(text:, **)
12
+ @type = AbsTokenType::REMARK
13
+ @text = text
14
+
15
+ super
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module AbstractToken
5
+ #
6
+ # Sign function.
7
+ #
8
+ class SignFunc < AbstractToken
9
+ attr_reader :expression
10
+
11
+ def initialize(expression:, **)
12
+ @type = AbsTokenType::SIGN_FUNC
13
+ @expression = expression
14
+
15
+ super
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module AbstractToken
5
+ #
6
+ # Pause a program run.
7
+ #
8
+ class Wait < AbstractToken
9
+ attr_reader :time
10
+
11
+ def initialize(time:, **)
12
+ @type = AbsTokenType::WAIT
13
+ @time = time
14
+
15
+ super
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ #
5
+ # Namespace for abstact tokens.
6
+ #
7
+ module AbstractToken; end
8
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ #
5
+ # See https://dry-rb.org/gems/dry-system/main/container/
6
+ #
7
+ class Container < Dry::System::Container
8
+ configure do |config|
9
+ use :zeitwerk
10
+
11
+ config.root = Pathname(__dir__).join("../../")
12
+
13
+ config.component_dirs.add "lib" do |dir|
14
+ dir.namespaces.add "img_to_script", key: nil
15
+ end
16
+
17
+ config.inflector = Dry::Inflector.new do |inflections|
18
+ inflections.acronym("MK90")
19
+ end
20
+ end
21
+
22
+ register("utils.logger", Logger.new($stdout, level: Logger::ERROR))
23
+
24
+ add_to_load_path! "lib"
25
+ end
26
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ #
5
+ # BASIC known by its widely usage of the GOTO construction.
6
+ # It is a common practice to use statements like N GOTO N + m
7
+ # (i.e. jump m lines away from the current line N).
8
+ #
9
+ # When a generator generates an abstract token, it doesn't know
10
+ # anything about the current line or its number yet. It is only
11
+ # when a formatter starts to format the code, this values can be
12
+ # calculated.
13
+ #
14
+ # Thus, at the generation step a placeholder is being used to mark
15
+ # the current line number.
16
+ #
17
+ # Placeholder's job is to tell a formatter that the argument should
18
+ # be replaced with the actual line number value.
19
+ #
20
+ # The optional attribute 'shift' allows to make a relative jump
21
+ # from the current line to a line that is above (a negative value)
22
+ # or to a line that's behind (a positive value) of the current line.
23
+ #
24
+ # Shift value is in line steps, i.e. works as a coefficient, so the
25
+ # full form of the expression is: N GOTO N + m * line_step.
26
+ #
27
+ class CurrentLinePlaceholder
28
+ attr_reader :shift
29
+
30
+ #
31
+ # Initialize a placeholder.
32
+ #
33
+ # @param [Integer] shift
34
+ # A relative shift of the current line number.
35
+ #
36
+ def initialize(shift = 0)
37
+ @shift = shift
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ #
5
+ # Base class.
6
+ #
7
+ # Formatters format array of target language tokens to an
8
+ # executable script.
9
+ #
10
+ # A formatter's responsibility is to label BASIC lines, put
11
+ # separators between the statements' and their arguments, etc.
12
+ #
13
+ class Formatter
14
+ attr_reader :script
15
+
16
+ include Dry::Configurable
17
+
18
+ #
19
+ # Format an array of the language tokens to an executable script.
20
+ #
21
+ # @param [Array<Object>] tokens
22
+ # Translator's output.
23
+ #
24
+ # @param [Hash{ Symbol => Object }] **kwargs
25
+ # Options.
26
+ #
27
+ # @return [Array<String>]
28
+ # Formatted script.
29
+ #
30
+ def format(tokens, **kwargs)
31
+ _format(tokens, **kwargs)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module Generators
5
+ #
6
+ # Base class.
7
+ #
8
+ class Generator
9
+ include Dry::Configurable
10
+
11
+ setting :x_offset, default: X_OFFSET
12
+ setting :y_offset, default: Y_OFFSET
13
+ setting :clear_screen, default: CLEAR_SCREEN
14
+ setting :pause_program, default: PAUSE_PROGRAM
15
+ setting :program_begin_lbl, default: PRORGAM_BEGIN_LBL
16
+ setting :program_end_lbl, default: PROGRAM_END_LBL
17
+
18
+ #
19
+ # Generate abstract tokens that represent the image.
20
+ #
21
+ # @param [Magick::BinMagick::Image] image
22
+ # Binary image.
23
+ #
24
+ # @param [Integer] scr_width
25
+ # Target device horizontal screen resolution.
26
+ #
27
+ # @param [Integer] scr_height
28
+ # Target device vertical screen resolution.
29
+ #
30
+ # @return [Array<AbstractToken>] @tokens
31
+ #
32
+ def generate(image:, scr_width:, scr_height:)
33
+ @image = image
34
+ @scr_width = scr_width
35
+ @scr_height = scr_height
36
+ @x_offset = config.x_offset
37
+ @y_offset = config.y_offset
38
+
39
+ _generate_tokens
40
+
41
+ @tokens
42
+ end
43
+
44
+ private
45
+
46
+ def _generate_tokens
47
+ @tokens = [] # append new tokens here
48
+
49
+ _program_begin if config.program_begin_lbl
50
+ _clear_screen if config.clear_screen
51
+ _generate
52
+ _program_pause if config.pause_program
53
+ _program_end if config.program_end_lbl
54
+ end
55
+
56
+ #
57
+ # Transpose image for vertical scanning.
58
+ #
59
+ def _transpose
60
+ @image.rotate!(90)
61
+ @image.flop!
62
+ end
63
+
64
+ #
65
+ # Append a token to clear screen.
66
+ #
67
+ def _clear_screen
68
+ @tokens.append(
69
+ AbstractToken::ClearScreen.new(
70
+ require_nl: true
71
+ )
72
+ )
73
+ end
74
+
75
+ #
76
+ # Append a token to mark end of the program.
77
+ #
78
+ def _program_end
79
+ @tokens.append(
80
+ AbstractToken::ProgramEnd.new(
81
+ require_nl: true
82
+ )
83
+ )
84
+ end
85
+
86
+ #
87
+ # Append a token to mark begin of the program.
88
+ #
89
+ def _program_begin
90
+ @tokens.append(
91
+ AbstractToken::ProgramBegin.new(
92
+ require_nl: true
93
+ )
94
+ )
95
+ end
96
+
97
+ #
98
+ # Append a sub-routine to pause the program.
99
+ #
100
+ def _program_pause
101
+ _loop_begin
102
+ _wait
103
+ _loop_end
104
+ end
105
+
106
+ def _loop_begin
107
+ @tokens.append(
108
+ AbstractToken::LoopBegin.new(
109
+ start_value: 1,
110
+ end_value: WAIT_LOOP_COUNT,
111
+ var_name: LOOP_VAR,
112
+ require_nl: true
113
+ )
114
+ )
115
+ end
116
+
117
+ def _wait
118
+ @tokens.append(
119
+ AbstractToken::Wait.new(
120
+ time: WAIT_TIME
121
+ )
122
+ )
123
+ end
124
+
125
+ def _loop_end
126
+ @tokens.append(
127
+ AbstractToken::LoopEnd.new(
128
+ var_name: LOOP_VAR
129
+ )
130
+ )
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ImgToScript
4
+ module Generators
5
+ module HexMask
6
+ #
7
+ # Generates image rendering script with the DRAM/M statements only
8
+ # (without 'enhacements').
9
+ #
10
+ class Default < HexMask
11
+ private
12
+
13
+ def _generate
14
+ @tokens.append(
15
+ AbstractToken::DrawChunkByHexValue.new(
16
+ hex_values: _encode_img,
17
+ require_nl: true
18
+ )
19
+ )
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end