clockworkcomicpdf 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 983d2f02eac2ae6b01baf045ccae832effa3ae3a
4
+ data.tar.gz: 565431e7815bcfd34301b89b45b3b6873cb8a0a6
5
+ SHA512:
6
+ metadata.gz: 034150b51ff58647e31ba36f77a0916bd3290984e153fffcaca1b8c3acac180a4f2b4f57d3abc29d961efd9dd356d77220b3cd2e877d8cf42a3971a4a9e1502a
7
+ data.tar.gz: 0a6aefc0b8080189f0b6a9e57c12b5a3126d1c398531e1805856717f2a0589821760d613a95553b4e795a5005d047caf58e8ccd4fb40c062ebbe3a232e2aab22
@@ -0,0 +1,102 @@
1
+ require_relative 'to_points'
2
+ require_relative 'page_header'
3
+ require_relative 'errors'
4
+ require_relative 'cover'
5
+ require_relative 'version'
6
+ require_relative 'option_validation'
7
+ require_relative 'book_validation'
8
+ require_relative 'book_init'
9
+
10
+ module ClockworkComicPDF
11
+ # variable storage for the book class
12
+ class Book
13
+ include OptionValidation, BookValidation, BookInit
14
+ def font
15
+ @font ||= 'Helvetica'
16
+ end
17
+ attr_writer :font
18
+
19
+ def font_size
20
+ @font_size ||= 12
21
+ end
22
+
23
+ def font_size=(font_size)
24
+ @font_size = font_size.to_points unless font_size.nil?
25
+ end
26
+
27
+ attr_accessor :base_file_name
28
+
29
+ def info
30
+ @info ||= {}
31
+ end
32
+
33
+ def info=(info)
34
+ if info.is_a? Hash
35
+ info[:CreationDate] = Time.now
36
+ info[:Creator] = 'Clockwork Comic PDF Engine'
37
+ info[:Producer] = 'Prawn'
38
+ else
39
+ fail InvalidValueError, 'Information must be set as a Hash value'
40
+ end
41
+ @info = info
42
+ end
43
+
44
+ def page_size
45
+ @page_size ||= [{ val: 8.5, type: :in },
46
+ { val: 11, type: :in }]
47
+ end
48
+
49
+ def page_size=(page_size)
50
+ page_size = page_size.to_a
51
+ page_size.each do |dim|
52
+ page_size[page_size.find_index dim] = dim.to_points
53
+ end
54
+ @page_size = page_size
55
+ end
56
+
57
+ def margin
58
+ @margin ||= { val: 0.25, type: :in }
59
+ end
60
+
61
+ def margin=(margin)
62
+ @margin = []
63
+ margin = [margin] unless margin.is_a? Array
64
+ unless margin.count == 4 || margin.count == 1
65
+ fail InvalidValueError 'Margin must contain 1 or 4 values'
66
+ end
67
+ margin.each_index do |i|
68
+ @margin[i] = margin[i].to_points
69
+ end
70
+ @margin
71
+ end
72
+
73
+ def offset_from_spine
74
+ @offset_from_spine ||= 0
75
+ end
76
+
77
+ def offset_from_spine=(offset_from_spine)
78
+ @offset_from_spine = offset_from_spine.to_points
79
+ end
80
+
81
+ def print_toc
82
+ @print_toc = true if @print_toc.nil?
83
+ @print_toc
84
+ end
85
+ attr_writer :print_toc
86
+
87
+ def print_pagenum
88
+ @print_pagenum = true if @print_toc.nil?
89
+ @print_pagenum
90
+ end
91
+ attr_writer :print_pagenum
92
+ attr_accessor :page_header
93
+ attr_accessor :cover
94
+
95
+ def versions
96
+ @versions ||= []
97
+ end
98
+ attr_writer :versions
99
+
100
+ attr_accessor :sections
101
+ end
102
+ end
@@ -0,0 +1,37 @@
1
+ module ClockworkComicPDF
2
+ # initalization blocks for the book class
3
+ module BookInit
4
+ def valid_options
5
+ [:font, :info, :base_file_name, :page_size, :margin,
6
+ :offset_from_spine, :print_toc, :print_pagenum, :page_header,
7
+ :versions, :sections, :font_size, :cover]
8
+ end
9
+
10
+ def initialize(options = {})
11
+ check_options(options.keys, valid_options)
12
+ initialize_options(options)
13
+ initialize_content(options)
14
+ end
15
+
16
+ private
17
+
18
+ def initialize_options(options = {})
19
+ self.font = options[:font]
20
+ self.base_file_name = options[:base_file_name]
21
+ self.info = options[:info]
22
+ self.page_size = options[:page_size]
23
+ self.margin = options[:margin]
24
+ self.offset_from_spine = options[:offset_from_spine]
25
+ self.print_toc = options[:print_toc]
26
+ self.print_pagenum = options[:print_pagenum]
27
+ end
28
+
29
+ def initialize_content(options = {})
30
+ self.page_header = PageHeader.new(options[:page_header])
31
+ self.cover = Cover.new(options[:cover])
32
+ self.versions = Versions.new(options[:versions])
33
+ self.sections = Sections.new(options[:sections])
34
+ self.font_size = options[:font_size]
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,79 @@
1
+ module ClockworkComicPDF
2
+ # Validation Module for Book Class
3
+ module BookValidation
4
+ def validate
5
+ fail MissingValueError, 'base_file_name required' unless @base_file_name
6
+ cover.validate if cover
7
+ sections.validate
8
+ versions.validate
9
+ miss = image_mismatch
10
+ if miss.count > 0
11
+ fail_s = "Image directories do no match: #{miss.join(', ')}"
12
+ fail MissingValueError, fail_s
13
+ end
14
+ end
15
+
16
+ def image_mismatch
17
+ mismatch = []
18
+ files = version_files
19
+ files.each_pair do |key_v, sec|
20
+ mismatch.concat(scan_version(key_v, sec, files))
21
+ end
22
+ mismatch.flatten
23
+ end
24
+
25
+ def scan_version(key_v, sec, files)
26
+ mismatch = []
27
+ files.each_pair do |c_ver, c_sec|
28
+ unless key_v == c_ver
29
+ mismatch << scan_section(key_v.name, sec, c_ver.name, c_sec)
30
+ end
31
+ end
32
+ mismatch
33
+ end
34
+
35
+ def scan_section(v_name, sec_v, c_name, sec_c)
36
+ mismatch = []
37
+ sec_v.each_pair do |ss_key, ss_v|
38
+ ss_v.each do |f|
39
+ unless sec_c[ss_key].include? f
40
+ mismatch << "#{f} in section #{ss_key.name} exists " <<
41
+ "in #{v_name} but not #{c_name}"
42
+ end
43
+ end
44
+ end
45
+ mismatch
46
+ end
47
+
48
+ def version_files
49
+ files = {}
50
+ versions.each do |version|
51
+ files[version] = section_files(version)
52
+ end
53
+ files
54
+ end
55
+
56
+ def section_files(check_ver)
57
+ s_files = {}
58
+ [sections.front_matter, sections.body,
59
+ sections.end_matter].flatten.each do |sub|
60
+ if sub.is_a? SectionComicPages
61
+ s_files[sub] = get_comic_files(check_ver, sub)
62
+ end
63
+ end
64
+ s_files
65
+ end
66
+
67
+ def get_comic_files(check_ver, sub)
68
+ current_dir = "./#{check_ver.name}/#{sub.directory}/"
69
+ unless File.exist?(current_dir)
70
+ fail InvalidValueError, "#{File.path(current_dir)} does not exist"
71
+ end
72
+ c_files = []
73
+ Dir["#{current_dir}*.*"].each do |file|
74
+ c_files << File.basename(file, '.*')
75
+ end
76
+ c_files
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,42 @@
1
+ require_relative 'to_points'
2
+ require_relative 'errors'
3
+ require_relative 'option_validation'
4
+
5
+ module ClockworkComicPDF
6
+ # this contains the size, file path, and size of the cover
7
+ class Cover
8
+ include OptionValidation
9
+ attr_reader :size
10
+ def size=(size)
11
+ unless size.is_a?(Array) && size.count == 2
12
+ throw InvalidValueError.new 'Cover size must contain exactly 2 values'
13
+ end
14
+ size[0] = size[0].to_points
15
+ size[1] = size[1].to_points
16
+ @size = size
17
+ end
18
+
19
+ attr_reader :path
20
+ def path=(path)
21
+ @path = path.to_s
22
+ end
23
+
24
+ attr_reader :file
25
+ def file=(file)
26
+ @file = file.to_s
27
+ end
28
+
29
+ def validate
30
+ fail InvalidValueError, 'Cover Must specify a file' unless file
31
+ fail InvalidValueError, 'Cover must specify a size' unless size
32
+ fail InvalidValueError, 'Cover must specify a path' unless path
33
+ end
34
+
35
+ def initialize(options = {})
36
+ check_options(options.keys, [:size, :path, :file])
37
+ self.path = options[:path]
38
+ self.size = options[:size]
39
+ self.file = options[:file]
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,13 @@
1
+ module ClockworkComicPDF
2
+ class MissingValueError < StandardError
3
+ end
4
+
5
+ class InvalidValueError < ArgumentError
6
+ end
7
+
8
+ class UndefinedKeyError < ArgumentError
9
+ end
10
+
11
+ class ArgumentError < ArgumentError
12
+ end
13
+ end
@@ -0,0 +1,83 @@
1
+ module ClockworkComicPDF
2
+ # stores the option parsing logic for PDFMaker
3
+ module MeasurementParser
4
+ def parse_options(pdf, opt_in)
5
+ out = {}
6
+ opt_in.each_pair do |key, val|
7
+ case key
8
+ when :height_ratio then out[:height] = pdf.bounds.height * val.to_r
9
+ when :width_ratio then out[:width] = pdf.bounds.width * val.to_r
10
+ else out[key] = convert_val(pdf, val, opt_in)
11
+ end
12
+ end
13
+ out
14
+ end
15
+
16
+ def convert_val(pdf, val, opt_in)
17
+ if val.is_a? Array
18
+ val = Array.new(val)
19
+ val.each_index do |i|
20
+ val[i] = convert_val(pdf, val[i], opt_in)
21
+ end
22
+ else
23
+ val = convert_position(pdf, val)
24
+ val = convert_size(pdf, val, opt_in)
25
+ end
26
+ val
27
+ end
28
+
29
+ def convert_position(pdf, val)
30
+ val = convert_complex_position(pdf, val)
31
+ val = convert_simple_position(pdf, val)
32
+ val
33
+ end
34
+
35
+ def convert_complex_position(pdf, val)
36
+ case val
37
+ when :bounds_top_left then return pdf.bounds.top_left
38
+ when :bounds_top_right then return pdf.bounds.top_right
39
+ when :bounds_bottom_left then return pdf.bounds.bottom_left
40
+ when :bounds_bottom_right then return pdf.bounds.bottom_right
41
+ else return val
42
+ end
43
+ end
44
+
45
+ def convert_simple_position(pdf, val)
46
+ case val
47
+ when :bounds_top then return pdf.bounds.top
48
+ when :bounds_bottom then return pdf.bounds.bottom
49
+ when :bounds_left then return pdf.bounds.left
50
+ when :bounds_right then return pdf.bounds.right
51
+ else return val
52
+ end
53
+ end
54
+
55
+ def convert_size(pdf, val, opt_in)
56
+ case val
57
+ when :bounds_width then return pdf.bounds.width
58
+ when :bounds_height then return pdf.bounds.height
59
+ when :bounds_center_width then return get_h_center(pdf, opt_in)
60
+ when :bounds_center_height then return get_v_center(pdf, opt_in)
61
+ else return val
62
+ end
63
+ end
64
+
65
+ def get_h_center(pdf, opt_in)
66
+ if !opt_in[:width_ratio].nil?
67
+ box_width = opt_in[:width_ratio].to_r * pdf.bounds.width
68
+ else
69
+ box_width = opt_in[:width]
70
+ end
71
+ pdf.bounds.width / 2 - box_width / 2
72
+ end
73
+
74
+ def get_v_center(pdf, options)
75
+ if !opt_in[:height_ratio].nil?
76
+ box_height = opt_in[:height_ratio].to_r * pdf.bounds.height
77
+ else
78
+ box_height = opt_in[:height]
79
+ end
80
+ pdf.bounds.height / 2 - box_height / 2
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,23 @@
1
+ require_relative 'errors'
2
+
3
+ # Module-level parameter checker
4
+ module ClockworkComicPDF
5
+ # provides option validation and requirements vaildaiton
6
+ module OptionValidation
7
+ def check_options(options, valid_options)
8
+ options.each do |key|
9
+ unless valid_options.include? key
10
+ fail UndefinedKeyError, "Unsupported key '#{key}' " <<
11
+ "for '#{self.class}'"
12
+ end
13
+ end
14
+ end
15
+
16
+ def check_required(options = {})
17
+ options.each_pair do |key, val|
18
+ fail UndefinedKeyError, "'#{self.class}' requires " <<
19
+ "key '#{key}'" if val.nil?
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,59 @@
1
+ require_relative 'errors'
2
+ require_relative 'option_validation'
3
+
4
+ module ClockworkComicPDF
5
+ # storage class for the page header
6
+ # includes alignment, left and right side text, and size
7
+ class PageHeader
8
+ include OptionValidation
9
+ def align
10
+ @align = :center unless @align
11
+ @align
12
+ end
13
+ attr_writer :align
14
+
15
+ def text=(text)
16
+ self.left_text = text
17
+ self.right_text = text
18
+ end
19
+
20
+ def text
21
+ { left: left_text, right: right_text }
22
+ end
23
+
24
+ def left_text
25
+ @left_text ||= ''
26
+ end
27
+
28
+ def left_text=(left_text)
29
+ @left_text = left_text.to_s
30
+ end
31
+
32
+ def right_text
33
+ @right_text ||= ''
34
+ end
35
+
36
+ def right_text=(right_text)
37
+ @right_text = right_text.to_s
38
+ end
39
+
40
+ def size
41
+ @size = 8 unless @size
42
+ @size
43
+ end
44
+
45
+ def size=(size)
46
+ @size = size.to_points
47
+ end
48
+
49
+ def initialize(options = {})
50
+ valid_options = [:size, :text, :left_text, :right_text, :align]
51
+ check_options(options.keys, valid_options)
52
+ self.size = options[:size]
53
+ self.text = options[:text]
54
+ self.left_text = options[:left_text]
55
+ self.right_text = options[:right_text]
56
+ self.align = options[:align]
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,116 @@
1
+ require_relative 'book'
2
+ require_relative 'version'
3
+ require_relative 'measurement_parser'
4
+ require_relative 'pdf_section_maker'
5
+ require_relative 'pdf_toc_maker'
6
+ require 'prawn'
7
+
8
+ module ClockworkComicPDF
9
+ # this parses the sections of a book into a pdf file
10
+ class PDFMaker
11
+ include MeasurementParser, PDFSectionMaker, PDFTocMaker
12
+ attr_accessor :book, :content_start, :debug, :printing_body, :current_page,
13
+ :trim_offset
14
+
15
+ attr_writer :page_index
16
+ def page_index
17
+ @page_index ||= []
18
+ end
19
+
20
+ def initialize(book)
21
+ self.book = book
22
+ end
23
+
24
+ def print
25
+ book.validate
26
+ book.versions.each do |version|
27
+ self.content_start = nil
28
+ self.printing_body = false
29
+ self.current_page = nil
30
+ self.page_index = nil
31
+ self.debug = false
32
+ print_version(version)
33
+ end
34
+ end
35
+
36
+ def print_version(version)
37
+ self.trim_offset = version.trim_offset
38
+ pdf = Prawn::Document.new(info: book.info, font_size: book.font_size,
39
+ skip_page_creation: true)
40
+ print_sections(pdf, version)
41
+ print_cover(pdf, version) if version.print_cover
42
+ pdf.render_file "#{book.base_file_name} - #{version.name}.pdf"
43
+ end
44
+
45
+ def print_cover(pdf, version)
46
+ pdf.go_to_page 0
47
+ return if book.cover.nil?
48
+ cover = book.cover
49
+ pdf.start_new_page(size: cover.size, margin: 0)
50
+ pdf.image("#{cover.path}/#{version.name}/#{cover.file}",
51
+ at: pdf.bounds.top_left, scale: 72.0 / version.dpi.to_f)
52
+ end
53
+
54
+ def new_page(pdf)
55
+ if trim_offset then make_trim_page(pdf)
56
+ else make_offset_page(pdf)
57
+ end
58
+ pdf.font(book.font)
59
+ print_body_page(pdf) if printing_body
60
+ debug_stroke(pdf) if debug
61
+ end
62
+
63
+ def make_offset_page(pdf)
64
+ margin = Array.new(book.margin)
65
+ if pdf.page_number.odd? then margin[1] += book.offset_from_spine
66
+ else margin[3] += book.offset_from_spine
67
+ end
68
+ pdf.start_new_page(size: book.page_size, margin: margin)
69
+ end
70
+
71
+ def make_trim_page(pdf)
72
+ margin = Array.new(book.margin)
73
+ pdf.start_new_page(size: [book.page_size[0] - book.offset_from_spine,
74
+ book.page_size[1]],
75
+ margin: margin)
76
+ end
77
+
78
+ def print_body_page(pdf)
79
+ self.current_page += 1
80
+ print_header(pdf) unless book.page_header.nil?
81
+ print_page_num(pdf) if book.print_pagenum
82
+ end
83
+
84
+ def print_header(pdf)
85
+ head = book.page_header
86
+ options = { size: head.size, align: head.align, width: pdf.bounds.width }
87
+ text = pdf.page_number.even? ? head.left_text : head.right_text
88
+ options[:at] = [pdf.bounds.left, pdf.bounds.top + 0.25.in]
89
+ options[:valign] = :center
90
+ options[:height] = 0.25.in
91
+ if options[:align] == :alternating
92
+ options[:align] = even_page ? :left : :right
93
+ end
94
+ pdf.text_box(text, options)
95
+ end
96
+
97
+ def print_page_num(pdf)
98
+ options = { at: pdf.bounds.bottom_left,
99
+ width: pdf.bounds.width,
100
+ align: :center,
101
+ size: 8 }
102
+ options[:height] = 0.25.in
103
+ pdf.text_box("#{self.current_page}", options)
104
+ end
105
+
106
+ def debug_stroke(pdf)
107
+ pdf.stroke_bounds
108
+ pdf.stroke do
109
+ pdf.line [0, 0], [pdf.bounds.width, pdf.bounds.height]
110
+ pdf.line [pdf.bounds.width, 0], [0, pdf.bounds.height]
111
+ pdf.line [pdf.bounds.width / 2,
112
+ pdf.bounds.height], [pdf.bounds.width / 2, 0]
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,82 @@
1
+ module ClockworkComicPDF
2
+ # this parses the sections of a book into a pdf file
3
+ module PDFSectionMaker
4
+ def print_sections(pdf, version)
5
+ print_section(pdf, version, book.sections.front_matter)
6
+ self.printing_body = true
7
+ self.current_page = 0
8
+ self.content_start = pdf.page_number + 1
9
+ print_section(pdf, version, book.sections.body)
10
+ self.printing_body = false
11
+ print_section(pdf, version, book.sections.end_matter)
12
+ new_page(pdf) if pdf.page_number.odd?
13
+ print_toc(pdf) if book.print_toc
14
+ end
15
+
16
+ def print_section(pdf, version, section)
17
+ section.each do |item|
18
+ case item.type
19
+ when :text_box
20
+ print_text_box(pdf, version, item)
21
+ when :formatted_text_box
22
+ print_formatted_text_box(pdf, version, item)
23
+ when :comic_pages
24
+ print_comic_pages(pdf, version, item)
25
+ end
26
+ end
27
+ end
28
+
29
+ def print_comic_pages(pdf, version, comic_pages)
30
+ puts comic_pages.name
31
+ if comic_pages.print_section_intro
32
+ print_section_break(pdf, comic_pages.name)
33
+ end
34
+ section_dir = "./#{version.name}/#{comic_pages.directory}/"
35
+ Dir["#{section_dir}*.*"].each do |image|
36
+ print_comic_image(pdf, version, image)
37
+ end
38
+ end
39
+
40
+ def print_section_break(pdf, text)
41
+ new_page(pdf)
42
+ pdf.move_cursor_to pdf.bounds.top
43
+ options = { valign: :center, align: :center, width: pdf.bounds.width,
44
+ height: pdf.bounds.height, size: 18,
45
+ at: pdf.bounds.top_left }
46
+ page_index << { page: current_page, name: text } if printing_body
47
+ pdf.text_box(text, options)
48
+ end
49
+
50
+ def print_comic_image(pdf, version, image)
51
+ new_page(pdf)
52
+ name = make_name(image)
53
+ page_index << { page: current_page, name: "#{name}" } if printing_body
54
+ content = [[name], [{ image: image, scale: 72.0 / version.dpi }]]
55
+ table = Prawn::Table.new(content, pdf, cell_style: { borders: [] },
56
+ position: :center)
57
+ pdf.move_down((pdf.bounds.height - table.height) / 2.0)
58
+ table.draw
59
+ end
60
+
61
+ def make_name(file_path)
62
+ File.basename(file_path, '.*').split(' ').slice(1..-1).join(' ')
63
+ end
64
+
65
+ def print_text_box(pdf, version, content)
66
+ text = File.new(content.file).read
67
+ make_text_box(pdf, [{ text: text }], content)
68
+ end
69
+
70
+ def print_formatted_text_box(pdf, version, content)
71
+ text = YAML.load_file(content.file)
72
+ make_text_box(pdf, text, content)
73
+ end
74
+
75
+ def make_text_box(pdf, text, content)
76
+ new_page(pdf)
77
+ page_index << { page: current_page, name: content.name } if printing_body
78
+ options = parse_options(pdf, content.options)
79
+ pdf.formatted_text_box(text, options)
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,27 @@
1
+ module ClockworkComicPDF
2
+ # stores the PDF printing methods for making the table of contents
3
+ module PDFTocMaker
4
+ def print_toc(pdf)
5
+ pdf.go_to_page(content_start - 1)
6
+ toc_start = pdf.page_number
7
+ new_page(pdf)
8
+ pdf.text 'Table of Contents', size: 18, align: :left
9
+ pdf.move_down(25)
10
+ page_index.each { |toc_item| make_toc_item(pdf, toc_item) }
11
+ new_page(pdf) unless (toc_start - pdf.page_number).even?
12
+ self.content_start += (toc_start - pdf.page_number)
13
+ end
14
+
15
+ def make_toc_item(pdf, toc_item)
16
+ content = [["#{toc_item[:name]}", "#{toc_item[:page]}"]]
17
+ options = { width: pdf.bounds.width / 2, position: :center,
18
+ cell_style: { borders: [], size: 8,
19
+ padding: 1 } }
20
+ table = Prawn::Table.new(content, pdf, options) do
21
+ cells.style { |c| c.align = c.column.zero? ? :left : :right }
22
+ end
23
+ new_page(pdf) if table.height >= pdf.cursor
24
+ table.draw
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,144 @@
1
+ require_relative 'option_validation'
2
+
3
+ module ClockworkComicPDF
4
+ # this stores the data for each section of the book
5
+ class Sections
6
+ include OptionValidation
7
+ def front_matter
8
+ @front_matter ||= []
9
+ end
10
+ attr_writer :front_matter
11
+
12
+ def body
13
+ @body ||= []
14
+ @body
15
+ end
16
+ attr_writer :body
17
+
18
+ def end_matter
19
+ @end_matter ||= []
20
+ @end_matter
21
+ end
22
+ attr_writer :end_matter
23
+
24
+ def parse_sections(sections)
25
+ parsed_sections = []
26
+ sections.each do |section|
27
+ parsed_sections << section_by_type(section)
28
+ end
29
+ parsed_sections
30
+ end
31
+
32
+ def section_by_type(section)
33
+ case section[:type]
34
+ when :comic_pages
35
+ return SectionComicPages.new(section)
36
+ when :text_box
37
+ return SectionTextBox.new(section)
38
+ when :formatted_text_box
39
+ return SectionFormattedTextBox.new(section)
40
+ else
41
+ fail InvalidKeyError, "#{section[:type]} is not a valid section type"
42
+ end
43
+ end
44
+
45
+ def validate
46
+ [front_matter, body, end_matter].each do |chunk|
47
+ chunk.each { |sec| sec.validate }
48
+ end
49
+ end
50
+
51
+ def print_pdf(options = {})
52
+ [front_matter, body, end_matter].each do |chunk|
53
+ chunk.each { |sec| sec.print_pdf(options) }
54
+ end
55
+ end
56
+
57
+ def initialize(options = {})
58
+ check_options(options.keys, [:front_matter, :body, :end_matter])
59
+ self.front_matter = parse_sections(options[:front_matter])
60
+ self.body = parse_sections(options[:body])
61
+ self.end_matter = parse_sections(options[:end_matter])
62
+ end
63
+ end
64
+
65
+ # this is the base class for sections data that stores common section info
66
+ class Section
67
+ include OptionValidation
68
+ attr_writer :print_section_intro
69
+ def print_section_intro
70
+ @print_section_intro = false if @print_section_intro.nil?
71
+ @print_section_intro
72
+ end
73
+
74
+ attr_accessor :type
75
+ attr_accessor :name
76
+
77
+ def valid_options
78
+ @valid_options = [:print_section_intro, :type, :name]
79
+ end
80
+
81
+ def req_keys
82
+ @required_keys = { name: @name }
83
+ end
84
+
85
+ def validate
86
+ check_required(req_keys)
87
+ end
88
+
89
+ def initialize(options = {})
90
+ self.name = options[:name]
91
+ self.type = options[:type]
92
+ self.print_section_intro = options[:print_section_intro]
93
+ end
94
+ end
95
+
96
+ # Comic Pages section
97
+ class SectionComicPages < Section
98
+ def valid_options
99
+ super
100
+ @valid_options << :directory
101
+ end
102
+
103
+ def req_keys
104
+ super
105
+ @required_keys[:directory] = @directory
106
+ @required_keys
107
+ end
108
+
109
+ attr_accessor :directory
110
+
111
+ def initialize(options = {})
112
+ super
113
+ self.directory = options[:directory]
114
+ end
115
+ end
116
+
117
+ # text box method
118
+ class SectionTextBox < Section
119
+ attr_accessor :file, :options
120
+
121
+ def valid_options
122
+ super
123
+ @valid_options << :file
124
+ @valid_options << :options
125
+ end
126
+
127
+ def req_keys
128
+ super
129
+ @required_keys[:file] = @file
130
+ @required_keys[:options] = @options
131
+ @required_keys
132
+ end
133
+
134
+ def initialize(options = {})
135
+ super
136
+ self.options = options[:options]
137
+ self.file = options[:file]
138
+ end
139
+ end
140
+
141
+ # formatted text box method
142
+ class SectionFormattedTextBox < SectionTextBox
143
+ end
144
+ end
@@ -0,0 +1,27 @@
1
+ require 'prawn/measurement_extensions'
2
+
3
+ # adds point conversion function for hash values
4
+ class Hash
5
+ def to_points
6
+ if size == 2 && self[:val] && self[:type]
7
+ return self[:val].to_f.send(self[:type])
8
+ end
9
+ puts self
10
+ fail ClockworkComicPDF::UndefinedKeyError,
11
+ 'measurement must contain only :val and :type'
12
+ end
13
+ end
14
+
15
+ # returns itself as is for fixnum
16
+ class Fixnum
17
+ def to_points
18
+ self
19
+ end
20
+ end
21
+
22
+ # returns itself as is for Float
23
+ class Float
24
+ def to_points
25
+ self
26
+ end
27
+ end
@@ -0,0 +1,59 @@
1
+ require_relative 'option_validation'
2
+
3
+ module ClockworkComicPDF
4
+ # convienience class for parsing and holding version objects
5
+ class Versions < Array
6
+ def initialize(options)
7
+ options.each do |param|
8
+ self << Version.new(param)
9
+ end
10
+ end
11
+
12
+ def validate
13
+ each { |version| version.validate }
14
+ end
15
+ end
16
+
17
+ # stores version information for PDF generation
18
+ # includes name, length, dpi and a toggle for printing the cover
19
+ class Version
20
+ include OptionValidation
21
+ attr_reader :name
22
+ def name=(name)
23
+ @name = name.to_s
24
+ end
25
+
26
+ attr_reader :dpi
27
+ def dpi=(dpi)
28
+ @dpi = dpi.to_i
29
+ end
30
+
31
+ def print_cover
32
+ @print_cover = false if @print_cover.nil?
33
+ @print_cover
34
+ end
35
+ attr_writer :print_cover
36
+
37
+ def trim_offset
38
+ @trim_offset = false if @trim_offset.nil?
39
+ @trim_offset
40
+ end
41
+ attr_writer :trim_offset
42
+
43
+ def validate
44
+ fail InvalidValueError, 'Each version must contain a name' unless name
45
+ fail InvalidValueError,
46
+ 'Each version must contain a name' if name.length == 0
47
+ fail InvalidValueError,
48
+ 'each version must specify a dpi value' unless dpi
49
+ end
50
+
51
+ def initialize(options = {})
52
+ check_options(options.keys, [:name, :dpi, :print_cover, :trim_offset])
53
+ self.name = options[:name]
54
+ self.dpi = options[:dpi]
55
+ self.trim_offset = options[:trim_offset]
56
+ self.print_cover = options[:print_cover]
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,21 @@
1
+ require 'prawn'
2
+ require 'yaml'
3
+
4
+ require_relative 'clockwork_comic_pdf/book'
5
+ require_relative 'clockwork_comic_pdf/errors'
6
+ require_relative 'clockwork_comic_pdf/page_header'
7
+ require_relative 'clockwork_comic_pdf/cover'
8
+ require_relative 'clockwork_comic_pdf/version'
9
+ require_relative 'clockwork_comic_pdf/section'
10
+ require_relative 'clockwork_comic_pdf/option_validation'
11
+ require_relative 'clockwork_comic_pdf/pdf_maker'
12
+
13
+ # the base module for ClockworkComicPDF
14
+ module ClockworkComicPDF
15
+ # VERSION "0.1.0"
16
+ def book_from_yaml(book)
17
+ parsed_book = Book.new(YAML.load_file(book))
18
+ PDFMaker.new(parsed_book).print
19
+ end
20
+ module_function :book_from_yaml
21
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clockworkcomicpdf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Michael Skiba
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: prawn
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.15.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.15.0
27
+ description: A Simple(ish) Ruby System for creating print and web ready PDF files.
28
+ email: mike.skiba@atelierclockwork.net
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - lib/clockwork_comic_pdf/book.rb
34
+ - lib/clockwork_comic_pdf/book_init.rb
35
+ - lib/clockwork_comic_pdf/book_validation.rb
36
+ - lib/clockwork_comic_pdf/cover.rb
37
+ - lib/clockwork_comic_pdf/errors.rb
38
+ - lib/clockwork_comic_pdf/measurement_parser.rb
39
+ - lib/clockwork_comic_pdf/option_validation.rb
40
+ - lib/clockwork_comic_pdf/page_header.rb
41
+ - lib/clockwork_comic_pdf/pdf_maker.rb
42
+ - lib/clockwork_comic_pdf/pdf_section_maker.rb
43
+ - lib/clockwork_comic_pdf/pdf_toc_maker.rb
44
+ - lib/clockwork_comic_pdf/section.rb
45
+ - lib/clockwork_comic_pdf/to_points.rb
46
+ - lib/clockwork_comic_pdf/version.rb
47
+ - lib/clockworkcomicpdf.rb
48
+ homepage: http://www.atelierclockwork.net/ccpdf/
49
+ licenses:
50
+ - MIT
51
+ metadata: {}
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '>='
59
+ - !ruby/object:Gem::Version
60
+ version: 1.9.3
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - '>='
64
+ - !ruby/object:Gem::Version
65
+ version: 1.3.6
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 2.0.3
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: Clockwork Comic PDF
72
+ test_files: []