/* * Page.cc * * Created on: 28 oct. 2013 * Author: CS */ #include "Page.hh" #include "DefaultPlotConfiguration.hh" #include "ColormapManager.hh" #include #include #include #include "Properties.hh" #include "PlotLogger.hh" #include "AMDA-Kernel_Config.hh" #include "PlPlotUtil.hh" namespace plot { const PLINT Page::A4_X_LENGTH_IN_MM = 297; const PLINT Page::A4_Y_LENGTH_IN_MM = 210; const PLINT Page::LETTER_X_LENGTH_IN_MM = 279; const PLINT Page::LETTER_Y_LENGTH_IN_MM = 216; const PLFLT Page::A4_X_LENGTH_IN_INCHES = 11.69; const PLFLT Page::A4_Y_LENGTH_IN_INCHES = 8.27; const PLFLT Page::LETTER_X_LENGTH_IN_INCHES = 11; const PLFLT Page::LETTER_Y_LENGTH_IN_INCHES = 8.5; const PLINT Page::A4_X_LENGTH_IN_PT = 842; const PLINT Page::A4_Y_LENGTH_IN_PT = 595; const PLINT Page::LETTER_X_LENGTH_IN_PT = 792; const PLINT Page::LETTER_Y_LENGTH_IN_PT = 612; Page::Page() : _format(), _xMargin(-1), _yMargin(-1), _xLoadedMargin(-1), _yLoadedMargin(-1), _orientation(PlotCommon::Orientation::LANDSCAPE), _mode(PlotCommon::Mode::COLOR), _dimension(PlotCommon::Dimension::ISO_A4), _titleAlign(PlotCommon::Align::CENTER), _titlePosition(PlotCommon::Position::POS_TOP), _dpi(300), _layoutProperties(), _fileName(""), _defaultTimePlotWidth(-1), _defaultTimePlotHeight(-1), _defaultTimePlotLeftMargin(-1), _defaultTimePlotRightMargin(-1), _defaultTimePlotTopMargin(-1), _defaultTimePlotBottomMargin(-1), _defaultXYPlotWidth(-1), _defaultXYPlotHeight(-1), _defaultXYPlotLeftMargin(-1), _defaultXYPlotRightMargin(-1), _defaultXYPlotTopMargin(-1), _defaultXYPlotBottomMargin(-1), _superposeMode (false), _font(Font("", 0)), _title(Font("", 0)) { // Initialize colormap ColormapManager::getInstance(); } Page::Page(DefaultPlotConfiguration& defaults) : _format(defaults._defaultPage._format), _xMargin(-1), _yMargin(-1), _xLoadedMargin(-1), _yLoadedMargin(-1), _orientation(defaults._defaultPage._orientation), _mode(defaults._defaultPage._mode), _dimension(defaults._defaultPage._dimension), _titleAlign(defaults._defaultPage._titleAlign), _titlePosition(defaults._defaultPage._titlePosition), _dpi(defaults._defaultPage._dpi), _layoutProperties(defaults._defaultPage._layoutProperties), _fileName(""), _defaultTimePlotWidth(defaults._defaultPage._defaultTimePlotWidth), _defaultTimePlotHeight(defaults._defaultPage._defaultTimePlotHeight), _defaultTimePlotLeftMargin(defaults._defaultPage._defaultTimePlotLeftMargin), _defaultTimePlotRightMargin(defaults._defaultPage._defaultTimePlotRightMargin), _defaultTimePlotTopMargin(defaults._defaultPage._defaultTimePlotTopMargin), _defaultTimePlotBottomMargin(defaults._defaultPage._defaultTimePlotBottomMargin), _defaultXYPlotWidth(defaults._defaultPage._defaultXYPlotWidth), _defaultXYPlotHeight(defaults._defaultPage._defaultXYPlotHeight), _defaultXYPlotLeftMargin(defaults._defaultPage._defaultXYPlotLeftMargin), _defaultXYPlotRightMargin(defaults._defaultPage._defaultXYPlotRightMargin), _defaultXYPlotTopMargin(defaults._defaultPage._defaultXYPlotTopMargin), _defaultXYPlotBottomMargin(defaults._defaultPage._defaultXYPlotBottomMargin), _superposeMode (defaults._defaultPage._superposeMode), _font(defaults._defaultPage.getFont()), _title(_font) { // Initialize colormap ColormapManager::getInstance(); } Page::Page(const Page& page) : _format(page._format), _xMargin(-1), _yMargin(-1), _xLoadedMargin(-1), _yLoadedMargin(-1), _orientation(page._orientation), _mode(page._mode), _dimension(page._dimension), _titleAlign(page._titleAlign), _titlePosition( page._titlePosition), _dpi(page._dpi), _layoutProperties(page._layoutProperties), _fileName(""), _defaultTimePlotWidth(page._defaultTimePlotWidth), _defaultTimePlotHeight(page._defaultTimePlotHeight), _defaultTimePlotLeftMargin(page._defaultTimePlotLeftMargin), _defaultTimePlotRightMargin(page._defaultTimePlotRightMargin), _defaultTimePlotTopMargin(page._defaultTimePlotTopMargin), _defaultTimePlotBottomMargin(page._defaultTimePlotBottomMargin), _defaultXYPlotWidth(page._defaultXYPlotWidth), _defaultXYPlotHeight(page._defaultXYPlotHeight), _defaultXYPlotLeftMargin(page._defaultXYPlotLeftMargin), _defaultXYPlotRightMargin(page._defaultXYPlotRightMargin), _defaultXYPlotTopMargin(page._defaultXYPlotTopMargin), _defaultXYPlotBottomMargin(page._defaultXYPlotBottomMargin), _superposeMode(page._superposeMode), _font(page.getFont()), _title(*page.getTitle()) { // Initialize colormap ColormapManager::getInstance(); } Page::~Page() { } std::tuple Page::getSizeInMm() { float xlengthInMm; float ylengthInMm; switch (_dimension) { case PlotCommon::Dimension::US_letter: if (_orientation == PlotCommon::Orientation::LANDSCAPE) { xlengthInMm = Page::LETTER_X_LENGTH_IN_MM; ylengthInMm = Page::LETTER_Y_LENGTH_IN_MM; } else { xlengthInMm = Page::LETTER_Y_LENGTH_IN_MM; ylengthInMm = Page::LETTER_X_LENGTH_IN_MM; } break; case PlotCommon::Dimension::ISO_A4: default: if (_orientation == PlotCommon::Orientation::LANDSCAPE) { xlengthInMm = Page::A4_X_LENGTH_IN_MM; ylengthInMm = Page::A4_Y_LENGTH_IN_MM; } else { xlengthInMm = Page::A4_Y_LENGTH_IN_MM; ylengthInMm = Page::A4_X_LENGTH_IN_MM; } } return std::tuple(xlengthInMm, ylengthInMm); } std::tuple Page::getSize() { float xlength = getPlDevXLength(_format, _dimension, _dpi); float ylength = getPlDevYLength(_format, _dimension, _dpi); return std::tuple(xlength, ylength); } void Page::setDimension(const std::string& pdimension) { if (pdimension == "US letter") { _dimension = PlotCommon::Dimension::US_letter; } else if (pdimension == "ISO A4") { _dimension = PlotCommon::Dimension::ISO_A4; } // else is default value } void Page::setOrientation(const std::string& porientation) { if (porientation == "portrait") { _orientation = PlotCommon::Orientation::PORTRAIT; } else if (porientation == "landscape") { _orientation = PlotCommon::Orientation::LANDSCAPE; } // else is default value } void Page::setMode(const std::string& pmode) { if (pmode == "color") { _mode = PlotCommon::Mode::COLOR; } else if (pmode == "grayscale") { _mode = PlotCommon::Mode::GRAYSCALE; } // else is default value } void Page::getDrawableBoundsInPlPage(Bounds& pBounds) { //Reserve margins space pBounds._x = _xMargin; pBounds._y = _yMargin; pBounds._width = 1 - 2*_xMargin; pBounds._height = 1 - 2*_yMargin; LabelRowInfo titleRows(Label::getRowNumber(_title)); if (!titleRows.empty()) { //Reserve title space CharSize lCharSizeTitle; Font titleFont(getTitleFont()); PlPlotUtil::setPlFont(titleFont); lCharSizeTitle = PlPlotUtil::getCharacterSizeInPlPage(this); double titleHeight = (titleRows.size() + PlPlotUtil::LINE_SPACE_TITLE * (titleRows.size() + 1)) * lCharSizeTitle.second; switch (_titlePosition) { case PlotCommon::Position::POS_TOP : pBounds._height -= titleHeight; break; case PlotCommon::Position::POS_BOTTOM : pBounds._y += titleHeight; pBounds._height -= titleHeight; break; default : //Not possible - Nothing to do ; } } //Reserve copyright space //Nothing to do - Copyright is drawn in margin } void Page::draw(std::shared_ptr& pls, bool newFile, const char *plotFilePrefix) { if (newFile) { //init page initPageParameters(pls); // Reduce colors in cmap 0 so that cmap 1 is useful on a //16-color display //pls->scmap0n(3); // set color mode (color or grayscale) (not used ?) pls->scolor(getPlColor(_mode)); // set new file std::stringstream plotname; plotname << plotFilePrefix << time(0) << "." << _format; _fileName = plotname.str(); pls->sfnam(_fileName.c_str()); // set output file format pls->sdev(getPlDev(_format).c_str()); pls->scolbg(255, 255, 255); // init plot pls->init(); // load colour palettes according to mode (default colormap for cmap0 is at index 0). pls->spal0( ColormapManager::getInstance().get(_mode, ColormapManager::getInstance().getDefault(_mode)).c_str()); // Default colormap for cmap1 is at index 1. pls->spal1( ColormapManager::getInstance().get(_mode, ColormapManager::DEFAULT_COLORMAP_1).c_str(), true); pls->adv(0); } else { // set white background for page (col 0) pls->scolbg(255, 255, 255); // go to next page pls->adv(0); // reload colour palette pls->spal0( ColormapManager::getInstance().get(_mode, ColormapManager::getInstance().getDefault(_mode)).c_str()); } //Init viewport plvpor(0, 1, 0, 1); // draw title drawTitle(pls); //draw copyright drawCopyright(pls); } void Page::drawCopyright(std::shared_ptr& pls) { // write Created by AMDA(c) on bottom write // write it on bottom right // if HIDE_AMDA_DATE is not defined (used for fitnesse automatic image comparison) if (getenv("HIDE_AMDA_DATE") != NULL) return; // read AMDA version from properties file AMDA::helpers::Properties lProperties("amda.properties"); std::string version = AMDA_Kernel_VERSION; std::string createdby = lProperties["createdby"]; // get and format time as DD/MM/YYYY HH:MM:SS time_t rawtime; struct tm * timeinfo; char buffer[80]; time(&rawtime); timeinfo = localtime(&rawtime); strftime(buffer, 80, "%d/%m/%G %T", timeinfo); //set viewport pls->vpor(0, 1, 0, 1); //set color pls->col0(0); //use page font PlPlotUtil::setPlFont(_font); // write text on right bottom of the page pls->mtex("b", -1., 1, 1, std::string(createdby + " v" + version + " " + std::string(buffer)).c_str()); } void Page::drawTitle(std::shared_ptr& pls) { PLFLT p_xp, p_yp; PLINT p_xleng, p_yleng, p_xoff, p_yoff; plgpage (&p_xp, &p_yp, &p_xleng, &p_yleng, &p_xoff, &p_yoff); LabelRowInfo titleRows(Label::getRowNumber(_title)); if (titleRows.empty()) return; Bounds drawableBounds; getDrawableBoundsInPlPage(drawableBounds); pls->vpor(drawableBounds._x, drawableBounds._x + drawableBounds._width, drawableBounds._y, drawableBounds._y + drawableBounds._height); pls->col0(0); Color lInitialColor = changeColor(pls, _title._color, _mode); // use page font if title font is not set Font titleFont(getTitleFont()); PlPlotUtil::setPlFont(titleFont); pls->mtex(getPlSide(_titlePosition).c_str(), 0.5 + PlPlotUtil::LINE_SPACE_TITLE, getPlPos(_titleAlign), getPlJust(_titleAlign), _title._text.c_str()); // Restore initial color. restoreColor(pls, lInitialColor, _mode); } void Page::initPageParameters(std::shared_ptr& pls) { // get default margin if not set if (_xLoadedMargin == -1) calculateRelativeXMargin(_orientation, _dimension, DefaultPlotConfiguration::getInstance()._defaultPage._xLoadedMargin); else calculateRelativeXMargin(_orientation, _dimension, _xLoadedMargin); if (_yLoadedMargin == -1) calculateRelativeYMargin(_orientation, _dimension, DefaultPlotConfiguration::getInstance()._defaultPage._yLoadedMargin); else calculateRelativeYMargin(_orientation, _dimension, _yLoadedMargin); // set page size according to page format A4 or letter // offset not seams to work pls->spage(0, 0, getPlDevXLength(_format, _dimension, _dpi), getPlDevYLength(_format, _dimension, _dpi), 0, 0); // set page orientation switch (_orientation) { case PlotCommon::Orientation::PORTRAIT: pls->setopt("portrait", ""); pls->sori(1); break; case PlotCommon::Orientation::LANDSCAPE: default: pls->sori(0); } // freeaspect is needed to do portrait mode work on pdf, png and svg pls->setopt("freeaspect", "1"); std::ostringstream dpi; dpi << _dpi << "x" << _dpi; pls->setopt("dpi", dpi.str().c_str()); } void Page::calculateRelativeXMargin(PlotCommon::Orientation& orientation, PlotCommon::Dimension& dimension, float xMarginInMm) { float xlengthInMm; switch (dimension) { case PlotCommon::Dimension::US_letter: if (orientation == PlotCommon::Orientation::LANDSCAPE) { xlengthInMm = Page::LETTER_X_LENGTH_IN_MM; } else { xlengthInMm = Page::LETTER_Y_LENGTH_IN_MM; } break; case PlotCommon::Dimension::ISO_A4: default: if (orientation == PlotCommon::Orientation::LANDSCAPE) { xlengthInMm = Page::A4_X_LENGTH_IN_MM; } else { xlengthInMm = Page::A4_Y_LENGTH_IN_MM; } } _xMargin = xMarginInMm / xlengthInMm; } void Page::calculateRelativeYMargin(PlotCommon::Orientation& orientation, PlotCommon::Dimension& dimension, float yMarginInMm) { float ylengthInMm; switch (dimension) { case PlotCommon::Dimension::US_letter: if (orientation == PlotCommon::Orientation::LANDSCAPE) { ylengthInMm = Page::LETTER_Y_LENGTH_IN_MM; } else { ylengthInMm = Page::LETTER_X_LENGTH_IN_MM; } break; case PlotCommon::Dimension::ISO_A4: default: if (orientation == PlotCommon::Orientation::LANDSCAPE) { ylengthInMm = Page::A4_Y_LENGTH_IN_MM; } else { ylengthInMm = Page::A4_X_LENGTH_IN_MM; } } _yMargin = yMarginInMm / ylengthInMm; } void Page::writeContext(ContextFileWriter& writer) { writer.addAttribute("portrait", (_orientation == PlotCommon::Orientation::PORTRAIT) ? "true": "false"); writer.addAttribute("width", std::to_string(std::get<0>(this->getSize())).c_str()); writer.addAttribute("height", std::to_string(std::get<1>(this->getSize())).c_str()); } std::ostream& operator <<(std::ostream& out, Page& page) { out << "[PAGE]" << std::endl; out << "page.format=" << page._format << std::endl; out << "page.dimension=" << page._dimension << std::endl; out << "page.orientation=" << page._orientation << std::endl; out << "page.mode=" << page._mode << std::endl; out << "page.margin=(" << page._xMargin << "," << page._yMargin << ")" << std::endl; out << "page.title=" << page.getTitle()->_text << std::endl; out << "page.align=" << page._titleAlign << std::endl; out << "page.position=" << page._titlePosition << std::endl; out << "page.dpi=" << page._dpi << std::endl; return out; } std::ostream& operator <<(std::ostream& out, PlotCommon::Dimension& dimension) { switch (dimension) { case PlotCommon::Dimension::US_letter: out << "US letter"; break; case PlotCommon::Dimension::ISO_A4: out << "ISO A4"; } return out; } std::ostream & operator <<(std::ostream & out, PlotCommon::Orientation & orientation) { switch (orientation) { case PlotCommon::Orientation::PORTRAIT: out << "Portrait"; break; case PlotCommon::Orientation::LANDSCAPE: out << "Landscape"; } return out; } std::ostream & operator <<(std::ostream & out, PlotCommon::Mode & mode) { switch (mode) { case PlotCommon::Mode::COLOR: out << "Color"; break; case PlotCommon::Mode::GRAYSCALE: out << "Grayscale"; } return out; } const std::string getPlSide(PlotCommon::Position& position) { switch (position) { case PlotCommon::Position::POS_LEFT: return "l"; case PlotCommon::Position::POS_RIGHT: return "r"; case PlotCommon::Position::POS_BOTTOM: return "b"; case PlotCommon::Position::POS_TOP: default: return "t"; } } PLFLT getPlPos(PlotCommon::Align& align) { switch (align) { case PlotCommon::Align::LEFT: return 0; case PlotCommon::Align::RIGHT: return 1; case PlotCommon::Align::CENTER: default: return 0.5; } } PLFLT getPlJust(PlotCommon::Align& align) { switch (align) { case PlotCommon::Align::LEFT: return 0; case PlotCommon::Align::RIGHT: return 1; case PlotCommon::Align::CENTER: default: return 0.5; } } PLFLT getPlColor(PlotCommon::Mode& mode) { switch (mode) { case PlotCommon::Mode::GRAYSCALE: return 0; case PlotCommon::Mode::COLOR: default: return 1; } } const std::string getPlDev(const std::string& format) { std::string plFormat; if (format == "ps") { plFormat = "pscairo"; } else if (format == "png") { plFormat = "pngcairo"; } else if (format == "pdf") { plFormat = "pdfcairo"; } else if (format == "svg") { plFormat = "svgcairo"; } else { plFormat = format; } return plFormat; } PLINT getPlDevXLength(const std::string& format, PlotCommon::Dimension& dimension, int dpi) { PLINT xPageLength = 0; if (format == "ps" || format == "pdf") { switch (dimension) { case PlotCommon::Dimension::ISO_A4: xPageLength = Page::A4_X_LENGTH_IN_PT; break; case PlotCommon::Dimension::US_letter: default: xPageLength = Page::LETTER_X_LENGTH_IN_PT; break; } } else if (format == "png" || format == "svg") { switch (dimension) { case PlotCommon::Dimension::ISO_A4: xPageLength = dpi * Page::A4_X_LENGTH_IN_INCHES; break; case PlotCommon::Dimension::US_letter: default: xPageLength = dpi* Page::LETTER_X_LENGTH_IN_INCHES; break; } } return xPageLength; } PLINT getPlDevYLength(const std::string& format, PlotCommon::Dimension& dimension, int dpi) { PLINT yPageLength = 0; if (format == "ps" || format == "pdf") { switch (dimension) { case PlotCommon::Dimension::ISO_A4: yPageLength = Page::A4_Y_LENGTH_IN_PT; break; case PlotCommon::Dimension::US_letter: default: yPageLength = Page::LETTER_Y_LENGTH_IN_PT; break; } } else if (format == "png" || format == "svg") { switch (dimension) { case PlotCommon::Dimension::ISO_A4: yPageLength = dpi * Page::A4_Y_LENGTH_IN_INCHES; break; case PlotCommon::Dimension::US_letter: default: yPageLength = dpi * Page::LETTER_Y_LENGTH_IN_INCHES; break; } } return yPageLength; } Color changeColor(std::shared_ptr& pls, Color& color, PlotCommon::Mode mode, int cmap) { Color lInitialColor; if (cmap == 0) { // Change color map. if (color._colorMapIndex != -1) { std::string lFilePath = ColormapManager::getInstance().get(mode, color._colorMapIndex); pls->spal0(lFilePath.c_str()); lInitialColor._colorMapIndex = ColormapManager::DEFAULT_COLORMAP_0; } // Change color index. if (color._colorIndex != -1) { pls->col0(color._colorIndex); } // Set temporary predefined color. else if (color._red != -1 && color._green != -1 && color._blue != -1) { // Store initial color in first index. pls->gcol0(0, lInitialColor._red, lInitialColor._green, lInitialColor._blue); pls->scol0(0, color._red, color._green, color._blue); pls->col0(0); } // Chose first color of color map. else { pls->gcol0(0, lInitialColor._red, lInitialColor._green, lInitialColor._blue); pls->col0(0); } } else { // Change color map. if (color._colorMapIndex != -1) { std::string lFilePath = ColormapManager::getInstance().get(mode, color._colorMapIndex); pls->spal1(lFilePath.c_str()); lInitialColor._colorMapIndex = ColormapManager::DEFAULT_COLORMAP_1; } } return lInitialColor; } void restoreColor(std::shared_ptr& pls, Color& color, PlotCommon::Mode mode, int cmap) { if (cmap == 0) { // Restore color map. if (color._colorMapIndex != -1) { std::string lFilePath = ColormapManager::getInstance().get(mode, color._colorMapIndex); pls->spal0(lFilePath.c_str()); } // Restore color index. if (color._colorIndex != -1) { pls->col0(color._colorIndex); } // Restore color. else if (color._red != -1 && color._green != -1 && color._blue != -1) { // Store initial color in first index. pls->scol0(0, color._red, color._green, color._blue); pls->col0(0); } // Chose first color of color map. else { pls->col0(0); } } else { // Restore color map. if (color._colorMapIndex != -1) { std::string lFilePath = ColormapManager::getInstance().get(mode, color._colorMapIndex); pls->spal1(lFilePath.c_str()); } } } void getDefaultColor(PlotCommon::Mode mode, int& cursor, Color& color) { int nbColors = ColormapManager::getInstance().getDefaultSize(mode); if (nbColors == 0) { color = Color(0,0,0); return; } if (cursor >= nbColors) cursor = cursor%nbColors; color = Color(ColormapManager::getInstance().getDefault(mode), cursor); ++cursor; } } /* namespace plot */