Logo Search packages:      
Sourcecode: bibledit version File versions  Download package

xmlfo-utils.cpp

/*
** Copyright (C) 2003-2006 Teus Benschop.
**  
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**  
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**  
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**  
*/


#include "libraries.h"
#include "utilities.h"
#include <libgen.h>
#include <glib.h>
#include <config.h>
#include "constants.h"
#include "xmlfo-utils.h"
#include "date_time_utils.h"
#include "fonts.h"
#include "gwrappers.h"
#include "generalconfig.h"
#include "projectconfig.h"


void insert_empty_lines (vector<ustring> * lines)
{
  lines->push_back ("");
  lines->push_back ("");
}


XmlFoRoot::XmlFoRoot (vector<ustring> * lines)
/*
Add the root data for the xslfo file.

In XEP, you can specify multiple font-families in font-family property and if 
font-selection-strategy is set to character-by-character value, XEP can 
substitute glyphs missing in the first specified font with characters from other 
fonts in the list.
*/
{
  // Config and font data.
  GeneralConfiguration genconfig (0);
  ProjectConfiguration projectconfig ("");
  PrintingFonts printingfonts (genconfig.project());
  // Depending on the amount of fonts used, get the font and the font selection.
  ustring font;
  ustring font_selection_strategy;
  if (printingfonts.printing_families.size() > 1) {
    font = printingfonts.printing_families_comma_separated ();
    font_selection_strategy = " font-selection-strategy=\"character-by-character\"";
  } else {
    font = printingfonts.printing_families[0]; 
  }
  int lineheight = projectconfig.printing_line_height ();
  // Assemble the lines to put in the xslfo file.
  mylines = lines;
  mylines->push_back ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
  ustring line;
  line = "<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\" font-family=\"" + font + "\"" + font_selection_strategy + " font-size=\"" + convert_to_string (projectconfig.printing_font_size()) + "pt\" text-align=\"justify\" line-height=\"" + convert_to_string (lineheight) + "%\">";
  mylines->push_back (line);  
  insert_empty_lines (mylines);
}


XmlFoRoot::~XmlFoRoot ()
{
  insert_empty_lines (mylines);
  mylines->push_back ("</fo:root>");
}


XmlFoLayoutMasterSet::XmlFoLayoutMasterSet (vector<ustring> * lines, bool twocolumns)
{
  GeneralConfiguration genconfig (0);
  insert_empty_lines (lines);
  ustring line;
  // Ensure a blank page does not print any headers.
  lines->push_back ("  <fo:layout-master-set>");
  line = "    <fo:simple-page-master master-name=\"blank-page\" page-width=\"21cm\" page-height=\"29.7cm\">";
  replace_text (line, "21", convert_to_string (genconfig.paper_width()));
  replace_text (line, "29.7", convert_to_string (genconfig.paper_height()));
  lines->push_back (line);
  // XEP 4 only validates if the region-body is empty, but counts white-space
  // as non-empty space. Strange behaviour, but solved so:
  lines->push_back ("      <fo:region-body></fo:region-body>");
  lines->push_back ("      <fo:region-before region-name=\"header-blank\" extent=\"0cm\"/>");
  lines->push_back ("    </fo:simple-page-master>");
  // Fill in paper size, margins.
  line = "    <fo:simple-page-master master-name=\"odd-page\" page-width=\""
       + convert_to_string (genconfig.paper_width()) + "cm\" page-height=\""
       + convert_to_string (genconfig.paper_height()) + "cm\">";
  lines->push_back (line);
  line = "      <fo:region-body margin-top=\""
       + convert_to_string (genconfig.paper_top_margin()) + "cm\" margin-bottom=\""
       + convert_to_string (genconfig.paper_bottom_margin()) + "cm\" margin-left=\""
       + convert_to_string (genconfig.paper_left_margin()) + "cm\" margin-right=\"" 
       + convert_to_string (genconfig.paper_right_margin()) + "cm\"";
  if (twocolumns)
    line.append (" column-count=\"2\"");
  line.append("></fo:region-body>");
  lines->push_back (line);
  line = "      <fo:region-before region-name=\"header-odd\" extent=\"2cm\"/>";
  replace_text (line, "2", convert_to_string (genconfig.paper_top_margin()));
  lines->push_back (line);
  lines->push_back ("    </fo:simple-page-master>");
  line = "    <fo:simple-page-master master-name=\"even-page\" page-width=\""
       + convert_to_string (genconfig.paper_width()) + "cm\" page-height=\""
       + convert_to_string (genconfig.paper_height()) + "cm\">";
  lines->push_back (line);
  // Mirrored paper : swap left/right margins on even pages.
  line = "      <fo:region-body margin-top=\""
       + convert_to_string (genconfig.paper_top_margin()) + "cm\" margin-bottom=\""
       + convert_to_string (genconfig.paper_bottom_margin()) + "cm\" margin-left=\""
       + convert_to_string (genconfig.paper_right_margin()) + "cm\" margin-right=\""
       + convert_to_string (genconfig.paper_left_margin()) + "cm\"";
  if (twocolumns)
    line.append (" column-count=\"2\"");
  line.append("></fo:region-body>");
  lines->push_back (line);
  line = "      <fo:region-before region-name=\"header-even\" extent=\"2cm\"/>";
  replace_text (line, "2", convert_to_string (genconfig.paper_top_margin()));
  lines->push_back (line);
  lines->push_back ("    </fo:simple-page-master>");
  lines->push_back ("    <fo:page-sequence-master master-name=\"text\">");
  lines->push_back ("      <fo:repeatable-page-master-alternatives>");
  lines->push_back ("        <fo:conditional-page-master-reference blank-or-not-blank=\"blank\" master-reference=\"blank-page\"/>");
  lines->push_back ("        <fo:conditional-page-master-reference odd-or-even=\"odd\" master-reference=\"odd-page\"/>");
  lines->push_back ("        <fo:conditional-page-master-reference odd-or-even=\"even\" master-reference=\"even-page\"/>");
  lines->push_back ("      </fo:repeatable-page-master-alternatives>");
  lines->push_back ("    </fo:page-sequence-master>");
  lines->push_back ("  </fo:layout-master-set>");
  insert_empty_lines (lines);
}


XmlFoLayoutMasterSet::~XmlFoLayoutMasterSet ()
{
}


XmlFoPageSequence::XmlFoPageSequence (vector<ustring> * lines, bool force_even_page_count)
{
  mylines = lines;
  insert_empty_lines (mylines);
  ustring line;
  line = "  <fo:page-sequence master-reference=\"text\"";
  if (force_even_page_count)
    line.append (" force-page-count=\"end-on-even\"");
  line.append (">");
  mylines->push_back (line);
  insert_empty_lines (mylines);
}


XmlFoPageSequence::~XmlFoPageSequence ()
{
  insert_empty_lines (mylines);
  mylines->push_back ("  </fo:page-sequence>");
  insert_empty_lines (mylines);
}


XmlFoStaticContent::XmlFoStaticContent (vector<ustring> * lines)
{
  GeneralConfiguration genconfig (0);
  insert_empty_lines (lines);
  ustring date;
  date = date_time_julian_human_readable (date_time_julian_day_get_current (), false);
  ustring line;
  // Allow for blank pages.
  lines->push_back ("    <fo:static-content flow-name=\"header-blank\">");
  lines->push_back ("    </fo:static-content>");
  lines->push_back ("    <fo:static-content flow-name=\"header-odd\">");
  lines->push_back ("      <fo:table table-layout=\"fixed\" width=\"100%\">");
  line = "        <fo:table-column column-width=\"2cm\"/>";
  replace_text (line, "2", convert_to_string (genconfig.paper_left_margin()));
  lines->push_back (line);
  lines->push_back ("        <fo:table-column column-width=\"proportional-column-width(1)\"/>");
  lines->push_back ("        <fo:table-column column-width=\"proportional-column-width(1)\"/>");
  lines->push_back ("        <fo:table-column column-width=\"proportional-column-width(1)\"/>");
  line = "        <fo:table-column column-width=\"1cm\"/>";
  replace_text (line, "1", convert_to_string (genconfig.paper_right_margin()));
  lines->push_back (line);
  lines->push_back ("        <fo:table-body>");
  line = "          <fo:table-row height=\"1.8cm\">";
  double table_height;
  table_height = genconfig.paper_top_margin() - 0.2;
  replace_text (line, "1.8", convert_to_string (table_height));  
  lines->push_back (line);
  lines->push_back ("            <fo:table-cell/>");
  lines->push_back ("            <fo:table-cell/>");
  lines->push_back ("            <fo:table-cell display-align=\"after\">");
  lines->push_back ("              <fo:block text-align=\"center\">");
  lines->push_back ("                <fo:retrieve-marker retrieve-class-name=\"book\"/>");
  lines->push_back ("                <fo:retrieve-marker retrieve-class-name=\"chapter\"/>");
  lines->push_back ("              </fo:block>");
  lines->push_back ("            </fo:table-cell>");
  lines->push_back ("            <fo:table-cell display-align=\"after\">");
  lines->push_back ("              <fo:block text-align-last=\"end\">");
  if (genconfig.printdate()) {
    lines->push_back (date);
  }
  lines->push_back ("                <fo:leader leader-length=\"1cm\"/>");
  lines->push_back ("                <fo:page-number/>");
  lines->push_back ("              </fo:block>");
  lines->push_back ("            </fo:table-cell>");
  lines->push_back ("            <fo:table-cell/>");
  lines->push_back ("          </fo:table-row>");
  lines->push_back ("        </fo:table-body>");
  lines->push_back ("      </fo:table>");
  lines->push_back ("    </fo:static-content>");
  lines->push_back ("    <fo:static-content flow-name=\"header-even\">");
  lines->push_back ("      <fo:table table-layout=\"fixed\" width=\"100%\">");
  line = "        <fo:table-column column-width=\"1cm\"/>";
  replace_text (line, "1", convert_to_string (genconfig.paper_right_margin()));
  lines->push_back (line);
  lines->push_back ("        <fo:table-column column-width=\"proportional-column-width(1)\"/>");
  lines->push_back ("        <fo:table-column column-width=\"proportional-column-width(1)\"/>");
  lines->push_back ("        <fo:table-column column-width=\"proportional-column-width(1)\"/>");
  line = "        <fo:table-column column-width=\"2cm\"/>";
  replace_text (line, "2", convert_to_string (genconfig.paper_left_margin()));
  lines->push_back (line);
  lines->push_back ("        <fo:table-body>");
  line = "          <fo:table-row height=\"1.8cm\">";
  replace_text (line, "1.8", convert_to_string (table_height));
  lines->push_back (line);
  lines->push_back ("            <fo:table-cell/>");
  lines->push_back ("            <fo:table-cell display-align=\"after\">");
  lines->push_back ("              <fo:block text-align=\"start\">");
  lines->push_back ("                <fo:page-number/>");
  lines->push_back ("                <fo:leader leader-length=\"1cm\"/>");
  if (genconfig.printdate()) {
    lines->push_back (date);
  }
  lines->push_back ("              </fo:block>");
  lines->push_back ("            </fo:table-cell>");
  lines->push_back ("            <fo:table-cell display-align=\"after\">");
  lines->push_back ("              <fo:block text-align=\"center\">");
  lines->push_back ("                <fo:retrieve-marker retrieve-class-name=\"book\"/>");
  lines->push_back ("                <fo:retrieve-marker retrieve-class-name=\"chapter\"/>");
  lines->push_back ("              </fo:block>");
  lines->push_back ("            </fo:table-cell>");
  lines->push_back ("            <fo:table-cell/>");
  lines->push_back ("            <fo:table-cell/>");
  lines->push_back ("          </fo:table-row>");
  lines->push_back ("        </fo:table-body>");
  lines->push_back ("      </fo:table>");
  lines->push_back ("    </fo:static-content>");
  insert_empty_lines (lines);
}


XmlFoStaticContent::~XmlFoStaticContent ()
{
}


XmlFoFlow::XmlFoFlow (vector<ustring> * lines)
{
  mylines = lines;
  insert_empty_lines (mylines);
  mylines->push_back ("    <fo:flow flow-name=\"xsl-region-body\">");
  insert_empty_lines (mylines);
}


XmlFoFlow::~XmlFoFlow ()
{
  insert_empty_lines (mylines);
  mylines->push_back ("    </fo:flow>");
  insert_empty_lines (mylines);
}


XmlFoBlock::XmlFoBlock (vector<ustring> * lines, double fontsize,
                        const ustring& italic_in, const ustring& bold_in, 
                        const ustring& underline_in, const ustring& smallcaps_in,
                        ustring justification,
                        double spacebefore, double spaceafter,
                        double leftmargin, double rightmargin,
                        double firstlineindent, bool spancolumns)
{
  mylines = lines;
  insert_empty_lines (mylines);
  ustring line;
  line = "      <fo:block";
  // Fontsize
  line.append (" font-size=\"");
  line.append (convert_to_string (fontsize));
  line.append ("pt\"");
  // Italic
  italic = false;
  if (italic_in == ON) {
    line.append (" font-style=\"italic\"");
    italic = true;
  }
  // Bold
  bold = false;
  if (bold_in == ON) {
    line.append (" font-weight=\"bold\"");
    bold = true;
  }
  // Underline
  underline = false;
  if (underline_in == ON) {
    line.append (" text-decoration=\"underline\"");
    underline = true;
  }
  // Smallcaps
  smallcaps = false;
  if (smallcaps_in == ON) {
    line.append (" font-variant=\"small-caps\"");
    smallcaps = true;
  }
  // Justification
  if (justification == "last-justify")
    line.append (" text-align-last=\"justify\"");
  else {
    if (!justification.empty()) {
      line.append (" text-align=\"");
      line.append (justification);
      line.append ("\"");
    }
  }
  // Space before
  line.append (" space-before=\"");
  line.append (convert_to_string (spacebefore));
  line.append ("mm\"");
  // Space after
  line.append (" space-after=\"");
  line.append (convert_to_string (spaceafter));
  line.append ("mm\"");
  // Left margin
  line.append (" start-indent=\"");
  line.append (convert_to_string (leftmargin));
  line.append ("mm\"");
  // Right margin
  line.append (" end-indent=\"");
  line.append (convert_to_string (rightmargin));
  line.append ("mm\"");
  // First line indent
  line.append (" text-indent=\"");
  line.append (convert_to_string (firstlineindent));
  line.append ("mm\"");
  // Spanning of columns.
  if (spancolumns)
    line.append (" span=\"all\"");
  line.append (">");
  mylines->push_back (line);
}


XmlFoBlock::~XmlFoBlock ()
{
  mylines->push_back ("      </fo:block>");
  insert_empty_lines (mylines);
}


ustring XmlFoInlineText (const ustring& line, XmlFoBlock * xmlfoblock, double fontpercentage, const ustring& italic, const ustring& bold, const ustring& underline, const ustring& smallcaps, bool superscript)
{
  ustring result;
  result = "<fo:inline font-size=\"FontSize%\"";
  replace_text (result, "FontSize", convert_to_string (fontpercentage));
  // Deal with italics.
  if (italic == ON)
    result.append (" font-style=\"italic\"");
  else if (italic == OFF)
    result.append (" font-style=\"normal\"");
  else if (italic == INHERIT)
    result.append (" font-style=\"inherit\"");
  else if (italic == TOGGLE)
    if (xmlfoblock) {
      if (xmlfoblock->italic)
        result.append (" font-style=\"normal\"");
      else 
        result.append (" font-style=\"italic\"");
    }
  // Deal with bold.
  if (bold == ON)
    result.append (" font-weight=\"bold\"");
  else if (bold == OFF)
    result.append (" font-weight=\"normal\"");
  else if (bold == INHERIT)
    result.append (" font-weight=\"inherit\"");
  else if (bold == TOGGLE)
    if (xmlfoblock) {
      if (xmlfoblock->bold)
        result.append (" font-weight=\"normal\"");
      else
        result.append (" font-weight=\"bold\"");
    }
  // Deal with underline.
  if (underline == ON)
    result.append (" text-decoration=\"underline\"");
  else if (underline == INHERIT)
    result.append (" text-decoration=\"inherit\"");
  else if (underline == OFF)
    result.append (" text-decoration=\"none\"");
  else if (underline == TOGGLE)
    if (xmlfoblock) {
      if (xmlfoblock->underline)
        result.append (" text-decoration=\"none\"");
      else
        result.append (" text-decoration=\"underline\"");
    }
  // Deal with smallcaps.
  if (smallcaps == ON)
    result.append (" font-variant=\"small-caps\"");
  else if (smallcaps == OFF)
    result.append (" font-variant=\"normal\"");
  else if (smallcaps == INHERIT)
    result.append (" font-variant=\"inherit\"");
  else if (smallcaps == TOGGLE) {
    if (xmlfoblock) {
      if (xmlfoblock->smallcaps)
        result.append (" font-variant=\"normal\"");
      else
        result.append (" font-variant=\"small-caps\"");
    }
  }
 
  if (superscript) {
    result.append (" vertical-align=\"super\"");
  }
  result.append (">");
  result.append (line);
  result.append ("</fo:inline>");
  return result;
}

Generated by  Doxygen 1.6.0   Back to index