From 043b20d1c068d216764fb37420ad17ebdab19456 Mon Sep 17 00:00:00 2001 From: Keith Fahlgren Date: Wed, 9 Jul 2008 18:58:32 +0000 Subject: [PATCH] Adding primitive support for embedding a single font --- xsl/epub/bin/dbtoepub | 5 +++- xsl/epub/bin/lib/docbook.rb | 30 +++++++++++++++++-- xsl/epub/bin/spec/epub_spec.rb | 38 +++++++++++++++++++++++-- xsl/epub/bin/spec/files/DejaVuSerif.otf | 0 xsl/epub/bin/spec/files/test.css | 7 +++++ xsl/epub/docbook.xsl | 22 ++++++++++++++ 6 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 xsl/epub/bin/spec/files/DejaVuSerif.otf diff --git a/xsl/epub/bin/dbtoepub b/xsl/epub/bin/dbtoepub index abe176def..a6a431659 100755 --- a/xsl/epub/bin/dbtoepub +++ b/xsl/epub/bin/dbtoepub @@ -11,6 +11,7 @@ # Specific options: # -c, --css [FILE] Use FILE for CSS on generated XHTML. # -d, --debug Show debugging output. +# -f, --font [OTF FILE] Embed OTF FILE in .epub. # -h, --help Display usage info. # -s, --stylesheet [XSL FILE] Use XSL FILE as a customization # layer (imports epub/docbook.xsl). @@ -27,6 +28,7 @@ require 'docbook' verbose = false debug = false css_file = nil +otf_files = [] customization_layer = nil # Set up the OptionParser @@ -43,6 +45,7 @@ opts.banner = "Usage: #{File.basename($0)} [OPTIONS] [DocBook Files] Specific options:" opts.on("-c", "--css [FILE]", "Use FILE for CSS on generated XHTML.") {|f| css_file = f} opts.on("-d", "--debug", "Show debugging output.") {debug = true; verbose = true} +opts.on("-f", "--font [OTF FILE]", "Embed OTF FILE in .epub.") {|f| otf_files << f} opts.on("-h", "--help", "Display usage info.") {puts opts.to_s; exit 0} opts.on("-s", "--stylesheet [XSL FILE]", "Use XSL FILE as a customization layer (imports epub/docbook.xsl).") {|f| customization_layer = f} opts.on("-v", "--verbose", "Make output verbose.") {verbose = true} @@ -55,7 +58,7 @@ end db_files.each {|docbook_file| dir = File.expand_path(File.join(Dir.tmpdir, ".epubtmp#{Time.now.to_f.to_s}")) - e = DocBook::Epub.new(docbook_file, dir, css_file, customization_layer) + e = DocBook::Epub.new(docbook_file, dir, css_file, customization_layer, otf_files) epub_file = File.basename(docbook_file, ".xml") + ".epub" puts "Rendering DocBook file #{docbook_file} to #{epub_file}" if verbose e.render_to_file(epub_file) diff --git a/xsl/epub/bin/lib/docbook.rb b/xsl/epub/bin/lib/docbook.rb index 96ed0cf40..3b622ae37 100755 --- a/xsl/epub/bin/lib/docbook.rb +++ b/xsl/epub/bin/lib/docbook.rb @@ -19,12 +19,14 @@ module DocBook attr_reader :output_dir - def initialize(docbook_file, output_dir=OUTPUT_DIR, css_file=nil, customization_layer=nil) + def initialize(docbook_file, output_dir=OUTPUT_DIR, css_file=nil, customization_layer=nil, embedded_fonts=[]) @docbook_file = docbook_file @output_dir = output_dir @meta_dir = File.join(@output_dir, META_DIR) @oebps_dir = File.join(@output_dir, OEBPS_DIR) @css_file = css_file ? File.expand_path(css_file) : css_file + @embedded_fonts = embedded_fonts + raise NotImplementedError if @embedded_fonts.length > 1 @to_delete = [] if customization_layer @@ -65,9 +67,22 @@ module DocBook callout_ext = "--stringparam callout.graphics.extension #{CALLOUT_EXT}" html_stylesheet = "--stringparam html.stylesheet #{File.basename(@css_file)}" if @css_file base = "--stringparam base.dir #{@oebps_dir}/" + unless @embedded_fonts.empty? + font = "--stringparam epub.embedded.font \"#{File.basename(@embedded_fonts.first)}\"" + end meta = "--stringparam epub.metainf.dir #{@meta_dir}/" oebps = "--stringparam epub.oebps.dir #{@oebps_dir}/" - options = "--xinclude #{chunk_quietly} #{callout_path} #{callout_limit} #{callout_ext} #{base} #{meta} #{oebps} #{html_stylesheet}" + options = ["--xinclude", + chunk_quietly, + callout_path, + callout_limit, + callout_ext, + base, + font, + meta, + oebps, + html_stylesheet, + ].join(" ") # Double-quote stylesheet & file to help Windows cmd.exe db2epub_cmd = "#{XSLT_PROCESSOR} #{options} \"#{@stylesheet}\" \"#{@docbook_file}\"" STDERR.puts db2epub_cmd if $DEBUG @@ -84,6 +99,7 @@ module DocBook oebps = File.basename(@oebps_dir) images = copy_images() csses = copy_csses() + fonts = copy_fonts() callouts = copy_callouts() # zip -X -r ../book.epub mimetype META-INF OEBPS # Double-quote stylesheet & file to help Windows cmd.exe @@ -110,6 +126,16 @@ module DocBook return new_callout_images end + def copy_fonts + new_fonts = [] + @embedded_fonts.each {|font_file| + font_new_filename = File.join(@oebps_dir, File.basename(font_file)) + FileUtils.cp(font_file, font_new_filename) + new_fonts << font_file + } + return new_fonts + end + def copy_csses if @css_file css_new_filename = File.join(@oebps_dir, File.basename(@css_file)) diff --git a/xsl/epub/bin/spec/epub_spec.rb b/xsl/epub/bin/spec/epub_spec.rb index 17b62a572..08c8bedac 100755 --- a/xsl/epub/bin/spec/epub_spec.rb +++ b/xsl/epub/bin/spec/epub_spec.rb @@ -36,7 +36,10 @@ describe DocBook::Epub do @css_file_base = "test.css" @css_file = File.join(@filedir, @css_file_base) - @css_epub = DocBook::Epub.new(File.join(@testdocsdir, "book.002.xml"), @tmpdir, @css_file) + customization_layer = nil + @embedded_font_file_base = "DejaVuSerif.otf" + embedded_fonts = [File.join(@filedir, @embedded_font_file_base)] + @css_epub = DocBook::Epub.new(File.join(@testdocsdir, "book.002.xml"), @tmpdir, @css_file, customization_layer, embedded_fonts) @css_epubfile = File.join(@tmpdir, "css.epub") @css_epub.render_to_file(@css_epubfile, $DEBUG) @@ -180,7 +183,7 @@ describe DocBook::Epub do end end - it "should include a CSS link in OPF file when a CSS file has been provided" do + it "should include a reference in the OPF manifest to the provided CSS file" do begin tmpdir = File.join(Dir::tmpdir(), "epubcsshtmltest"); Dir.mkdir(tmpdir) rescue Errno::EEXIST @@ -196,6 +199,37 @@ describe DocBook::Epub do end end + it "should include a reference in the OPF manifest to the embedded font" do + begin + tmpdir = File.join(Dir::tmpdir(), "epubfontman"); Dir.mkdir(tmpdir) rescue Errno::EEXIST + + success = system("unzip -q -d #{File.expand_path(tmpdir)} -o #{@css_epubfile}") + raise "Could not unzip #{@css_epubfile}" unless success + opf_files = Dir.glob(File.join(tmpdir, "**", "*.opf")) + opf_links = opf_files.find_all {|opf_file| File.open(opf_file).readlines.to_s =~ /]*#{@embedded_font_file_base}/} + opf_links.should_not be_empty + rescue => e + raise e + ensure + FileUtils.rm_r(tmpdir, :force => true) + end + end + + it "should include the embedded font file in the bundle" do + begin + tmpdir = File.join(Dir::tmpdir(), "epubfontbundle"); Dir.mkdir(tmpdir) rescue Errno::EEXIST + + success = system("unzip -q -d #{File.expand_path(tmpdir)} -o #{@css_epubfile}") + raise "Could not unzip #{@css_epubfile}" unless success + font_files = Dir.glob(File.join(tmpdir, "**", @embedded_font_file_base)) + font_files.should_not be_empty + rescue => e + raise e + ensure + FileUtils.rm_r(tmpdir, :force => true) + end + end + it "should include a TOC link in rendered epub files for s" do begin tmpdir = File.join(Dir::tmpdir(), "epubtoctest"); Dir.mkdir(tmpdir) rescue Errno::EEXIST diff --git a/xsl/epub/bin/spec/files/DejaVuSerif.otf b/xsl/epub/bin/spec/files/DejaVuSerif.otf new file mode 100644 index 000000000..e69de29bb diff --git a/xsl/epub/bin/spec/files/test.css b/xsl/epub/bin/spec/files/test.css index 2301cef9f..cd70946dc 100644 --- a/xsl/epub/bin/spec/files/test.css +++ b/xsl/epub/bin/spec/files/test.css @@ -1,4 +1,11 @@ +@font-face { + font-family: "DejaVu Serif"; + font-style: normal; + font-weight: normal; + src:url(DejaVuSerif.otf); +} h2 { + font-family: "DejaVu Serif"; text-align: center; color: #dda0dd; } diff --git a/xsl/epub/docbook.xsl b/xsl/epub/docbook.xsl index ab850115a..b2d324967 100644 --- a/xsl/epub/docbook.xsl +++ b/xsl/epub/docbook.xsl @@ -41,6 +41,8 @@ htmltoc + +