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

line.cc

///
// Copyright (C) 2002 - 2004, Fredrik Arnerup & Rasmus Kaj, See COPYING
///
#include "line.hh"

xml2ps::Line::Line(const Element& elem, Canvas& o,
               float line_h, bool span,
               float margin_left, float margin_right)
  : out(o), hbox(out.hbox(span, margin_left, margin_right,
                    elem.getFont().getAscender()*line_h, 
                    elem.getFont().getDescender()*line_h)),
    text_width(0), space_width(0),
    element(elem), first_node(0), last_node(0),
    line_height(line_h), spancolumns(span),
    m_left(margin_left), m_right(margin_right)
{}

xml2ps::Line::~Line() {}

bool
xml2ps::Line::add(xml2ps::Node* node) {
  // Container Elements must be split into pieces, or the
  // width calculations might go wrong:
  if(const Element* element = dynamic_cast<const Element*>(node))
    if(element->begin() != element->end())
      return false; 

  if(dynamic_cast<const LineBreak*>(last_node)) {
    // kill whitespace after line break
    return dynamic_cast<const WhiteSpaceNode*>(node);
  }

  bool force = !first_node;
  if(force) 
    first_node = node;
  
  float twidth = node->getWidth();
  if(dynamic_cast<const WhiteSpaceNode*>(node)) {
    last_node = node;
    space_width += twidth;
    return true;
  } else {
    // This is a factor, not a width in points or something ...
    const float max_wordspace = 4.0; /// \todo read this number somewhere!
    const float min_wordspace = 0.5; /// \todo Also configurable ...
    const float sw(((hbox.room() - text_width) / space_width) > max_wordspace
               ? space_width * min_wordspace
               : space_width);
    if (force || text_width + sw + twidth <= hbox.room()) {
      last_node = node;
      text_width += twidth;
      return true;
    } else return false;
  }
}

void xml2ps::Line::flush(bool is_last) {
  TextNode* hyphen = 0;
  bool is_linebreak = dynamic_cast<const LineBreak*>(last_node);
  if(last_node && dynamic_cast<const BreakPoint*>(last_node)) {
    // hex 2D is a hyphen or minus according to unicode
    // and is a hyphen in the Adobe standard encoding
    // other unicode hyphenoids (hex):
    // 2010 - hyphen
    // 2011 - non-breaking hyphen
    // 2012 - figure dash
    // 2013 - en dash
    // 2212 - minus sign
    hyphen = new TextNode(last_node->getParent(), 
                    Glib::ustring(Glib::ustring::size_type(1), 
                              gunichar(0x2D)));
    text_width += hyphen->getWidth();
  }
  while(last_node && last_node != first_node &&
      dynamic_cast<const WhiteSpaceNode*>(last_node)) {
    space_width -= last_node->getWidth();
    last_node = last_node->nodeBefore();
  }
  Element::Align align = element.getAlign();
  const float hpos = ((align == Element::center)
                  ? ((hbox.right()+hbox.left())/2 -
                   (text_width+space_width)/2)
                  :((align == Element::right)
                  ? hbox.right() - text_width - space_width
                  : hbox.left()));
  const float max_wsw = 3;    /// \todo Get from attribute
  float wsw = ((!is_last && !is_linebreak && align == Element::justify)
             ? (space_width > 0
              ? ((hbox.room() - text_width) / space_width)
              : max_wsw + 1) // or maxfloat, or whatever ...
             : 1);

  // increase character spacing if necessary:
  float charw = 0;
  if(wsw > max_wsw) {
    Element::CharSpaceCount count = element.countChars(first_node, last_node);
    
    wsw = max_wsw;
    float desired_text_width = hbox.room() - space_width * wsw;
    if(count.first > 1)
      charw = (desired_text_width - text_width)
      / (count.first - 1 + count.second * wsw);
  }

  out.moveto(hpos, hbox.baseline());

  element.printPart(out, first_node, last_node, wsw, charw);
  
  first_node = last_node = 0;
  text_width = space_width = 0;
  
  if(hyphen) {
    out.show(hyphen->getContent());
    delete hyphen;
  }

  if(!is_last)
    hbox = out.hbox(spancolumns, m_left, m_right, 
                element.getFont().getAscender() * line_height,
                element.getFont().getDescender() * line_height);
}

Generated by  Doxygen 1.6.0   Back to index