oshpark-rqrcode 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,93 @@
1
+ module RQRCode
2
+ module Export
3
+ module Gerber
4
+ attr_accessor :positive, :precision, :pixel_width, :x_origin, :y_origin, :quiet_zone_size, :mirrored
5
+ ##
6
+ # Returns a string of the QR code as
7
+ # characters writen with ANSI background set.
8
+ #
9
+ # Options:
10
+ # light: Foreground ("\033[47m")
11
+ # dark: Background ANSI code. ("\033[47m")
12
+ # fill_character: The written character. (' ')
13
+ # quiet_zone_size: (4)
14
+ #
15
+ def flash(x,y)
16
+ top_y = (@y_origin + @module_count + (@quiet_zone_size *2 )) * @pixel_width
17
+ y = top_y - (y * @pixel_width)
18
+ if @mirrored then
19
+ right_x = (@x_origin + @module_count + (@quiet_zone_size*2)) * @pixel_width
20
+ x = right_x - (x * @pixel_width)
21
+ else
22
+ x = @x_origin + x * @pixel_width
23
+ end
24
+ #puts "FLASH #{x} #{y}"
25
+ y = (y * @p_mult).to_i
26
+ x = (x * @p_mult).to_i
27
+ return "G01X#{x}Y#{y}D03*\n"
28
+ end
29
+
30
+ def is_light(x,y)
31
+ ! is_dark(x,y)
32
+ end
33
+
34
+ def as_gerber(options={})
35
+ options = {
36
+ precision: 6,
37
+ pixel_width: 0.010, # inches
38
+ x_origin: 0.000, # inches
39
+ y_origin: 0.000, # inches
40
+ quiet_zone_size: 1,
41
+ mirrored: false
42
+ }.merge(options)
43
+ @x_origin = options.fetch(:x_origin)
44
+ @y_origin = options.fetch(:y_origin)
45
+ @precision = options.fetch(:precision)
46
+ @pixel_width = options.fetch(:pixel_width)
47
+ @quiet_zone_size = options.fetch(:quiet_zone_size)
48
+ @mirrored = options.fetch(:mirrored)
49
+
50
+ @p_mult = 10**options[:precision]
51
+
52
+ output=<<-EOF
53
+ G04 This is an RQRCode Generated gerber file.*
54
+ G04 --End of header info--*
55
+ %MOIN*%
56
+ %FSLAX3#{options[:precision]}Y3#{options[:precision]}*%
57
+ %IPPOS*%
58
+ %ADD10R,#{options[:pixel_width]}X#{options[:pixel_width]}*%
59
+ G04 --Start main section--*
60
+ G54D10*
61
+ EOF
62
+
63
+ quiet_zone_size = options.fetch(:quiet_zone_size)
64
+
65
+ width = quiet_zone_size + @module_count + quiet_zone_size
66
+
67
+ quiet_zone_size.times do |r|
68
+ width.times do |c|
69
+ output << flash(c,r) ## Top Quiet Zone
70
+ output << flash(r,c) ## Left Quiet Zone
71
+ output << flash(r+quiet_zone_size+@module_count,c)
72
+ output << flash(c,r+quiet_zone_size+@module_count)
73
+ end
74
+ end
75
+
76
+
77
+ @modules.each_index do |r|
78
+ @modules[r].each_index do |c|
79
+ if is_light(r, c)
80
+ output << flash(quiet_zone_size+c,quiet_zone_size+r)
81
+ end
82
+ end
83
+ end
84
+
85
+ output << "M02*\n"
86
+
87
+ return output
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ RQRCode::QRCode.send :include, RQRCode::Export::Gerber
@@ -0,0 +1,53 @@
1
+ # Use this module to HTML-ify the QR code if you just want the default HTML
2
+ module RQRCode
3
+ module Export
4
+ module HTML
5
+
6
+ def as_html
7
+ ['<table>', rows.as_html, '</table>'].join
8
+ end
9
+
10
+ private
11
+
12
+ def rows
13
+ Rows.new(self)
14
+ end
15
+
16
+ class Rows < Struct.new(:qr)
17
+ def as_html
18
+ rows.map(&:as_html).join
19
+ end
20
+
21
+ def rows
22
+ qr.modules.each_with_index.map { |qr_module, row_index| Row.new(qr, qr_module, row_index) }
23
+ end
24
+ end
25
+
26
+ class Row < Struct.new(:qr, :qr_module, :row_index)
27
+ def as_html
28
+ ['<tr>', cells.map(&:as_html).join, '</tr>'].join
29
+ end
30
+
31
+ def cells
32
+ qr.modules.each_with_index.map { |qr_module, col_index| Cell.new(qr, col_index, row_index) }
33
+ end
34
+ end
35
+
36
+ class Cell < Struct.new(:qr, :col_index, :row_index)
37
+ def as_html
38
+ "<td class=\"#{html_class}\"></td>"
39
+ end
40
+
41
+ def html_class
42
+ dark? ? 'black' : 'white'
43
+ end
44
+
45
+ def dark?
46
+ qr.dark?(row_index, col_index)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ RQRCode::QRCode.send :include, RQRCode::Export::HTML
@@ -0,0 +1,117 @@
1
+ require 'chunky_png'
2
+
3
+ # This class creates PNG files.
4
+ # Code from: https://github.com/DCarper/rqrcode
5
+ module RQRCode
6
+ module Export
7
+ module PNG
8
+
9
+ # Render the PNG from the Qrcode.
10
+ #
11
+ # There are two sizing algoritams.
12
+ #
13
+ # - Original that can result in blurry and hard to scan images
14
+ # - Google's Chart API inspired sizing that resizes the module size to fit within the given image size.
15
+ #
16
+ # The Googleis one will be used when no options are given or when the new size option is used.
17
+ #
18
+ # Options:
19
+ # fill - Background ChunkyPNG::Color, defaults to 'white'
20
+ # color - Foreground ChunkyPNG::Color, defaults to 'black'
21
+ #
22
+ # *Googleis*
23
+ # size - Total size of PNG in pixels. The module size is calculated so it fits. (defaults to 90)
24
+ # border_modules - Width of white border around in modules. (defaults to 4).
25
+ #
26
+ # -- DONT USE border_modules OPTION UNLESS YOU KNOW ABOUT THE QUIET ZONE NEEDS OF QR CODES --
27
+ #
28
+ # *Original*
29
+ # module_px_size - Image size, in pixels.
30
+ # border - Border thickness, in pixels
31
+ #
32
+ # It first creates an image where 1px = 1 module, then resizes.
33
+ # Defaults to 90x90 pixels, customizable by option.
34
+ #
35
+ def as_png(options = {})
36
+
37
+ default_img_options = {
38
+ :resize_gte_to => false,
39
+ :resize_exactly_to => false,
40
+ :fill => 'white',
41
+ :color => 'black',
42
+ :size => 120,
43
+ :border_modules => 4,
44
+ :file => false,
45
+ :module_px_size => 6
46
+ }
47
+
48
+ googleis = options.length == 0 || (options[:size] != nil)
49
+
50
+ options = default_img_options.merge(options) # reverse_merge
51
+
52
+ fill = ChunkyPNG::Color(options[:fill])
53
+ color = ChunkyPNG::Color(options[:color])
54
+ output_file = options[:file]
55
+
56
+ module_px_size = nil
57
+ border_px = nil
58
+ png = nil
59
+
60
+ if googleis
61
+ total_image_size = options[:size]
62
+ border_modules = options[:border_modules]
63
+
64
+ module_px_size = (total_image_size.to_f / (self.module_count + 2 * border_modules).to_f).floor.to_i
65
+
66
+ img_size = module_px_size * self.module_count
67
+
68
+ remaining = total_image_size - img_size
69
+ border_px = (remaining / 2.0).floor.to_i
70
+
71
+ png = ChunkyPNG::Image.new(total_image_size, total_image_size, fill)
72
+ else
73
+ border = options[:border_modules]
74
+ total_border = border * 2
75
+ module_px_size = if options[:resize_gte_to]
76
+ (options[:resize_gte_to].to_f / (self.module_count + total_border).to_f).ceil.to_i
77
+ else
78
+ options[:module_px_size]
79
+ end
80
+ border_px = border * module_px_size
81
+ total_border_px = border_px * 2
82
+ resize_to = options[:resize_exactly_to]
83
+
84
+ img_size = module_px_size * self.module_count
85
+ total_img_size = img_size + total_border_px
86
+
87
+ png = ChunkyPNG::Image.new(total_img_size, total_img_size, fill)
88
+ end
89
+
90
+ self.modules.each_index do |x|
91
+ self.modules.each_index do |y|
92
+ if self.dark?(x, y)
93
+ (0...module_px_size).each do |i|
94
+ (0...module_px_size).each do |j|
95
+ png[(y * module_px_size) + border_px + j , (x * module_px_size) + border_px + i] = color
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ if !googleis && resize_to
103
+ png = png.resize(resize_to, resize_to)
104
+ end
105
+
106
+
107
+ if output_file
108
+ png.save(output_file,{ :color_mode => ChunkyPNG::COLOR_GRAYSCALE, :bit_depth =>1})
109
+ end
110
+ png
111
+ end
112
+
113
+ end
114
+ end
115
+ end
116
+
117
+ RQRCode::QRCode.send :include, RQRCode::Export::PNG
@@ -0,0 +1,53 @@
1
+ # This class creates a SVG files.
2
+ # Code from: https://github.com/samvincent/rqrcode-rails3
3
+ module RQRCode
4
+ module Export
5
+
6
+ module SVG
7
+
8
+ # Render the SVG from the Qrcode.
9
+ #
10
+ # Options:
11
+ # offset - Padding around the QR Code (e.g. 10)
12
+ # fill - Background color (e.g "ffffff" or :white)
13
+ # color - Foreground color for the code (e.g. "000000" or :black)
14
+ # module_size - The Pixel size of each module (e.g. 11)
15
+ # shape_rendering - Defaults to crispEdges
16
+ #
17
+ def as_svg(options={})
18
+ offset = options[:offset].to_i || 0
19
+ color = options[:color] || "000"
20
+ shape_rendering = options[:shape_rendering] || "crispEdges"
21
+ module_size = options[:module_size] || 11
22
+
23
+ # height and width dependent on offset and QR complexity
24
+ dimension = (self.module_count*module_size) + (2*offset)
25
+
26
+ xml_tag = %{<?xml version="1.0" standalone="yes"?>}
27
+ open_tag = %{<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" width="#{dimension}" height="#{dimension}" shape-rendering="#{shape_rendering}">}
28
+ close_tag = "</svg>"
29
+
30
+ result = []
31
+ self.modules.each_index do |c|
32
+ tmp = []
33
+ self.modules.each_index do |r|
34
+ y = c*module_size + offset
35
+ x = r*module_size + offset
36
+
37
+ next unless self.is_dark(c, r)
38
+ tmp << %{<rect width="#{module_size}" height="#{module_size}" x="#{x}" y="#{y}" style="fill:##{color}"/>}
39
+ end
40
+ result << tmp.join
41
+ end
42
+
43
+ if options[:fill]
44
+ result.unshift %{<rect width="#{dimension}" height="#{dimension}" x="0" y="0" style="fill:##{options[:fill]}"/>}
45
+ end
46
+
47
+ [xml_tag, open_tag, result, close_tag].flatten.join("\n")
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ RQRCode::QRCode.send :include, RQRCode::Export::SVG
@@ -0,0 +1,4 @@
1
+ Dir[File.dirname(__FILE__) + "/qrcode/*.rb"].sort.each do |path|
2
+ filename = File.basename(path)
3
+ require "rqrcode/qrcode/#{filename}"
4
+ end
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #--
4
+ # Copyright 2004 by Duncan Robertson (duncan@whomwah.com).
5
+ # All rights reserved.
6
+
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #++
11
+
12
+ module RQRCode
13
+
14
+ class QR8bitByte
15
+ attr_reader :mode
16
+
17
+ def initialize( data )
18
+ @mode = QRMODE[:mode_8bit_byte]
19
+ @data = data;
20
+ end
21
+
22
+
23
+ def get_length
24
+ @data.bytesize
25
+ end
26
+
27
+
28
+ def write( buffer)
29
+ buffer.byte_encoding_start(get_length)
30
+ @data.each_byte do |b|
31
+ buffer.put(b, 8)
32
+ end
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,47 @@
1
+ module RQRCode
2
+
3
+ ALPHANUMERIC = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',' ','$','%','*','+','-','.','/',':']
4
+
5
+ class QRAlphanumeric
6
+ attr_reader :mode
7
+
8
+ def initialize( data )
9
+ @mode = QRMODE[:mode_alpha_numk]
10
+
11
+ raise QRCodeArgumentError, "Not a alpha numeric uppercase string `#{data}`" unless QRAlphanumeric.valid_data?(data)
12
+
13
+ @data = data;
14
+ end
15
+
16
+
17
+ def get_length
18
+ @data.size
19
+ end
20
+
21
+ def self.valid_data? data
22
+ data.each_char do |s|
23
+ return false if ALPHANUMERIC.index(s).nil?
24
+ end
25
+ true
26
+ end
27
+
28
+
29
+ def write( buffer)
30
+ buffer.alphanumeric_encoding_start(get_length)
31
+
32
+ (@data.size).times do |i|
33
+ if i % 2 == 0
34
+ if i == (@data.size - 1)
35
+ value = ALPHANUMERIC.index(@data[i])
36
+ buffer.put( value, 6 )
37
+ else
38
+ value = (ALPHANUMERIC.index(@data[i]) * 45) + ALPHANUMERIC.index(@data[i+1])
39
+ buffer.put( value, 11 )
40
+ end
41
+ end
42
+ end
43
+
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #--
4
+ # Copyright 2004 by Duncan Robertson (duncan@whomwah.com).
5
+ # All rights reserved.
6
+
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #++
11
+
12
+ module RQRCode
13
+
14
+ class QRBitBuffer
15
+ attr_reader :buffer
16
+
17
+ PAD0 = 0xEC
18
+ PAD1 = 0x11
19
+
20
+ def initialize(version)
21
+ @version = version
22
+ @buffer = []
23
+ @length = 0
24
+ end
25
+
26
+
27
+ def get( index )
28
+ buf_index = (index / 8).floor
29
+ (( (@buffer[buf_index]).rszf(7 - index % 8)) & 1) == 1
30
+ end
31
+
32
+
33
+ def put( num, length )
34
+ ( 0...length ).each do |i|
35
+ put_bit((((num).rszf(length - i - 1)) & 1) == 1)
36
+ end
37
+ end
38
+
39
+
40
+ def get_length_in_bits
41
+ @length
42
+ end
43
+
44
+
45
+ def put_bit( bit )
46
+ buf_index = ( @length / 8 ).floor
47
+ if @buffer.size <= buf_index
48
+ @buffer << 0
49
+ end
50
+
51
+ if bit
52
+ @buffer[buf_index] |= ((0x80).rszf(@length % 8))
53
+ end
54
+
55
+ @length += 1
56
+ end
57
+
58
+ def byte_encoding_start(length)
59
+
60
+ put( QRMODE[:mode_8bit_byte], 4 )
61
+ put(length, QRUtil.get_length_in_bits(QRMODE[:mode_8bit_byte], @version))
62
+
63
+ end
64
+
65
+ def alphanumeric_encoding_start(length)
66
+
67
+ put( QRMODE[:mode_alpha_numk], 4 )
68
+ put(length, QRUtil.get_length_in_bits(QRMODE[:mode_alpha_numk], @version))
69
+
70
+ end
71
+
72
+ def numeric_encoding_start(length)
73
+
74
+ put( QRMODE[:mode_number], 4 )
75
+ put(length, QRUtil.get_length_in_bits(QRMODE[:mode_number], @version))
76
+
77
+ end
78
+
79
+ def pad_until(prefered_size)
80
+ # Align on byte
81
+ while get_length_in_bits % 8 != 0
82
+ put_bit( false )
83
+ end
84
+
85
+ # Pad with padding code words
86
+ while get_length_in_bits < prefered_size
87
+ put( QRBitBuffer::PAD0, 8 )
88
+ put( QRBitBuffer::PAD1, 8 ) if get_length_in_bits < prefered_size
89
+ end
90
+ end
91
+
92
+ def end_of_message(max_data_bits)
93
+ put( 0, 4 ) unless get_length_in_bits+4 > max_data_bits
94
+ end
95
+
96
+
97
+ end
98
+
99
+ end