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

textframe.cc

///
// Copyright (C) 2002 - 2004, Fredrik Arnerup & Rasmus Kaj, See COPYING
///
#include <sstream>
#include <fstream>

#include "textframe.h"
#include "document.h"
#include "pptout/config.h" // Todo
#include "util/tempfile.h"
#include "util/rectboundary.h"
#include "util/xmlwrap.h"
#include "util/filedescriptors.h"
#include <util/warning.h>
#include <util/stringutil.h>
#include <util/filesys.h>
#include <ps/misc.h>

TextFrame::TextFrame(Group *parent, TextStream *stream,
                 float w, float h)
  : CachedFrame(parent, "Text " + (stream ? stream->get_name() : "")),
    truncated(false),
    text_stream(stream),
    num_columns(1), gutter_width(12.0), width(w), height(h)
{
  white_is_transparent = true;
  ps_exists = false;
  parsed_file_lock = false;

  if(text_stream)
    text_stream->add_frame(this);
  signal_end_write_ps.connect
    (slot(*this,  &TextFrame::_end_write_ps));
}

TextFrame::TextFrame(const ElementWrap& xml, Group *parent)
  : CachedFrame(xml, parent),
    truncated(false),
    text_stream(0), 
    num_columns(xml.get_attribute<int>("num_columns", 1)),
    gutter_width(xml.get_attribute<float>("gutter_width", 12.0)),
    width(xml.get_required_attribute<float>("width")),
    height(xml.get_required_attribute<float>("height"))
{
  white_is_transparent = true;
  ps_exists = false;
  parsed_file_lock = false;
  
  if(const xmlpp::Attribute* stream = xml.get_raw_attribute("stream")) {
    set_stream(Document::containing(*this)
             .get_text_stream(stream->get_value()));
    if(!text_stream)
      throw Error::Read("Failed to get text stream \"" + stream->get_value()
                  + "\" for text frame");
  } // If stream is not present text_stream is null. This is ok.
  signal_end_write_ps.connect
    (slot(*this,  &TextFrame::_end_write_ps));
}

TextFrame::~TextFrame() {
  try { 
    if(text_stream)
      text_stream->remove_frame(this);
  }
  catch(const std::exception& err) {
    warning << "Failed to refresh stream: " << err.what() << std::endl;
  }
}

Boundary TextFrame::get_box() const {
  return RectBoundary::create(get_matrix(), width, height);
}

std::string TextFrame::getTypeName() const { return "text"; }

xmlpp::Element *TextFrame::save(xmlpp::Element& parent_node,
                        const FileContext &context) const 
{
  xmlpp::Element *node = CachedFrame::save(parent_node, context);
  node->set_attribute("type", "text");
  node->set_attribute("width", tostr(width));
  node->set_attribute("height", tostr(height));
  
  node->set_attribute("num_columns", tostr(num_columns));
  node->set_attribute("gutter_width", tostr(gutter_width));
  if(text_stream)
    node->set_attribute("stream", text_stream->get_name());
  
  return node;
}

void TextFrame::print(std::ostream &out, bool grayscale) const {
  if(text_stream) {
    out << "% " << name << ", from " << text_stream->get_association() << '\n'
      << "gsave\n"
      << PS::Concat(get_matrix());
    text_stream->outputPageRaw(out, this);
    out << "grestore\n" << std::endl;

  } else {
    out << "% " << name << ", text stream without data\n";
  }
}

void TextFrame::print_pdf(PDF::Content::Ptr pdf) const {
  if(text_stream) {
    const std::string objname = 
      pdf->registerXObj(text_stream->getPagePDF(this));
    
    pdf->data() << "q\n"
             << get_matrix()<< " cm\n"
             << '/' << objname << " Do\n"
             << "Q\n";
  }
}

void TextFrame::set_stream(TextStream *new_stream, 
                     bool remove_from_old) 
{
  if(text_stream == new_stream)
    return;
  
  if(remove_from_old && text_stream)
    text_stream->remove_frame(this);
  
  text_stream = new_stream;
  ps_exists = false;
  if(text_stream) {
    text_stream->add_frame(this);
    text_stream->generate_ps_request(this);
  } else {
    // make sure the viewent notices that something happened
    object_changed_signal(this);
  }
  
  props_changed_signal(this);
  if(text_stream)
    text_stream->generate_ps_request(this);
}

void TextFrame::set_num_columns(unsigned int columns) { 
  if(num_columns != columns) {
    num_columns = columns;
    //content_is_broken = false;    // Assume it's ok until we try it
    props_changed_signal(this);
    if(text_stream)
      text_stream->generate_ps_request(this);
  }
}

void TextFrame::set_gutter(const float& gutter) { 
  if(gutter_width != gutter) {
    gutter_width = gutter; 
    props_changed_signal(this);
    if(text_stream)
      text_stream->generate_ps_request(this);
  }
}

void TextFrame::set_size(float w, float h) {
  if(w != width || h != height) {
    width = w; height = h;
    ps_exists = false;
    geometry_changed_signal(this);
  }
}

void TextFrame::begin_write_ps() {
  parsed_file_lock = true;
}

void TextFrame::end_write_ps(bool _ps_exists, bool _truncated,
                       const std::string &_error) {
  parsed_file_lock = false;
  error = _error;
  ps_exists = _ps_exists;
  if(truncated != _truncated) {
    truncated = _truncated;
    truncated_state_changed_signal(truncated);
  }
  signal_end_write_ps();
}

void TextFrame::_end_write_ps() {
  object_changed_signal(this);
}

void TextFrame::generate_picture(std::ostream& psstream) const {
  if(!text_stream)
    throw GenPicError(ASSOCIATION, "No associated stream");

  if(!error.empty())
    throw GenPicError(GENERATION, error);
  
  if(!ps_exists)
    throw GenPicError(NOTREADY, "No postscript exists yet");
  
  // don't try to start gs if TextStream is writing the file
  if(parsed_file_lock) 
    throw GenPicError(NOTREADY, "Parsed file is locked");
  
  text_stream->outputPageEps(psstream, this);
  // Ugly, but the best way I found to actually close the stream:
  dynamic_cast<filedesc::OutBuf&>(*psstream.rdbuf()).close();
}

Generated by  Doxygen 1.6.0   Back to index