# 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).
verbose = false
debug = false
css_file = nil
+otf_files = []
customization_layer = nil
# Set up the OptionParser
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}
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)
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
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
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
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))
@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)
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
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 =~ /<item [^>]*#{@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 <book>s" do
begin
tmpdir = File.join(Dir::tmpdir(), "epubtoctest"); Dir.mkdir(tmpdir) rescue Errno::EEXIST
+@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;
}
<xsl:param name="epub.html.toc.id">htmltoc</xsl:param>
<xsl:param name="epub.metainf.dir" select="'META-INF/'"/>
+ <xsl:param name="epub.embedded.font"></xsl:param>
+
<!-- Per Bob Stayton:
"""Process your documents with the css.decoration parameter set to zero.
That will avoid the use of style attributes in XHTML elements where they are not permitted."""
</xsl:element>
</xsl:if>
+ <xsl:if test="$epub.embedded.font != ''">
+ <xsl:element name="item">
+ <xsl:attribute name="xmlns">http://www.idpf.org/2007/opf</xsl:attribute>
+ <xsl:attribute name="id">epub.embedded.font</xsl:attribute>
+ <xsl:attribute name="href"><xsl:value-of select="$epub.embedded.font"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="contains($epub.embedded.font, 'otf')">
+ <xsl:attribute name="media-type">font/opentype</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">
+ <xsl:text>ERROR: Only OpenType fonts are supported in .epub! (</xsl:text>
+ <xsl:value-of select="$epub.embedded.font"/>
+ <xsl:text>)</xsl:text>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+
<!-- TODO: be nice to have a id="titlepage" here -->
<xsl:apply-templates select="//part|
//book[*[last()][self::bookinfo]]|