/// // Copyright (C) 2002 - 2004, Fredrik Arnerup & Rasmus Kaj, See COPYING /// #include #include #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 #include #include #include 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) { ps_exists = false; parsed_file_lock = false; if(text_stream) text_stream->add_frame(this); } TextFrame::TextFrame(const ElementWrap& xml, Group *parent) : CachedFrame(xml, parent), truncated(false), text_stream(0), num_columns(xml.get_attribute("num_columns", 1)), gutter_width(xml.get_attribute("gutter_width", 12.0)), width(xml.get_required_attribute("width")), height(xml.get_required_attribute("height")) { 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. } 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); } else { // make sure the viewent notices that something happened object_changed_signal(); } props_changed_signal(); } 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(); } } void TextFrame::set_gutter(const float& gutter) { if(gutter_width != gutter) { gutter_width = gutter; props_changed_signal(); } } void TextFrame::set_size(float w, float h) { if(w != width || h != height) { width = w; height = h; ps_exists = false; geometry_changed_signal(); } } void TextFrame::begin_write_ps() { parsed_file_lock = true; } void TextFrame::end_write_ps(bool _ps_exists, bool _truncated, const std::string &_error) { debug << "*** END_WRITE_PS ***" << std::endl; parsed_file_lock = false; error = _error; ps_exists = _ps_exists; if(truncated != _truncated) { truncated = _truncated; truncated_state_changed_signal(truncated); } object_changed_signal(); } 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(*psstream.rdbuf()).close(); }