From 71e935520a5d56a5672b2a6c5e5e1e6fe851eee7 Mon Sep 17 00:00:00 2001 From: Markus Peura Date: Fri, 17 Jan 2025 16:59:04 +0200 Subject: [PATCH] v10.4 --- demo/make-tests.sh | 2 +- demo/test-svg.sh | 123 ++++++++++++++++++++++ src/drain/image/AlignSVG.h | 33 ++++-- src/drain/image/TreeUtilsSVG.cpp | 21 ++-- src/drain/image/TreeUtilsSVG.h | 34 +----- src/drain/util/ReferenceMap.h | 10 +- src/drain/util/XML.h | 4 + src/main/graphics.cpp | 174 +++++++++++-------------------- src/main/resources-base.cpp | 1 + 9 files changed, 235 insertions(+), 167 deletions(-) create mode 100755 demo/test-svg.sh diff --git a/demo/make-tests.sh b/demo/make-tests.sh index b444d0532..1854ae111 100755 --- a/demo/make-tests.sh +++ b/demo/make-tests.sh @@ -235,7 +235,7 @@ while (( $line <= iEnd )); do arglast=( $cmd ) argcount=${#arglast[*]} - arglast=${arglast[$(( argpount - 1 ))]} + arglast=${arglast[$(( argcount - 1 ))]} echo "arg last $arglast" output=$arglast diff --git a/demo/test-svg.sh b/demo/test-svg.sh new file mode 100755 index 000000000..aff7ecd85 --- /dev/null +++ b/demo/test-svg.sh @@ -0,0 +1,123 @@ +#!/bin/bash + +DOCFILE=~/eclipse-workspace/rack/src/main/graphics.inc +TMPDIR=out +RACK="rack --outputPrefix \$PWD/$TMPDIR/ --outputConf svg:absolutePaths=true " + +OUTFILES=() + +mkdir -v --parents $TMPDIR + +echo > $DOCFILE + +function WRITE_DOC(){ + + if [ $# == 0 ]; then + # Read stdin + # WARNING: may hang? + cat >> $DOCFILE + else + # Write arguments + echo $* >> $DOCFILE + fi + # echo >> $DOCFILE +} + +NEWLINE=" +" + +function RUN_TEST(){ + + local cmd="$RACK $*" + local args=( $* ) + local argc=${#args[*]} + + # Assume last arg is an output file + local OUTFILE=${args[$(( argc - 1 ))]} + local BASENAME=${OUTFILE%.*} + local FORMAT=${OUTFILE##*.} + + # With original newlines, "\\\n" + # echo -e ${cmd//\/$TMPDIR/} > $TMPDIR/$BASENAME.cmd + # echo "# CMD: $TMPDIR/$BASENAME.cmd" + # rack_cmd=${cmd//\/$TMPDIR/} + rack_cmd=${cmd//\\/\\$NEWLINE } + echo "${rack_cmd}" > $TMPDIR/$BASENAME.cmd + cmd=(`echo -e $cmd | tr -d '\\'`) + #cmd=${cmd//\\/} + cmd="${cmd[*]}" + echo "# $cmd" + eval "${cmd}" + if [ $? != 0 ]; then + echo "# $cmd" + echo "Rack command failed" + exit 1 + fi + + echo "# Format $FORMAT " + + if [ "$FORMAT" == "svg" ]; then + + cmd="xmllint --noout $TMPDIR/$OUTFILE" + eval $cmd + if [ $? == 0 ]; then + echo "# OK: XML syntax" + else + echo $cmd + echo "# FAIL: XML syntax error (xmllint $OUTFILE) " + exit 2 + fi + + local OUTFILE_PNG=$BASENAME.png + cmd="inkscape $TMPDIR/$OUTFILE -o $TMPDIR/$OUTFILE_PNG" + eval $cmd + + if [ $? == 0 ]; then + echo "# OK: created $TMPDIR/$OUTFILE_PNG" + OUTFILES+=($TMPDIR/$OUTFILE_PNG) + cp -v $TMPDIR/$OUTFILE_PNG ../doxygen/ + else + echo $cmd + echo "# FAIL: SVG->PNG conversion " + exit 3 + fi + + CAPTION=${CAPTION:-"SVG output '$OUTFILE_PNG'"} + + WRITE_DOC < inline - void setAlignAnchor(const std::string & pathElem){ - anchorHorz = pathElem; - anchorVert = pathElem; + void setAlignAnchor(const T & pathElem){ + anchorVert = anchorHorz = getElem(pathElem); updateAlign(); } + template inline - void setAlignAnchorHorz(const std::string & pathElem){ - anchorHorz = pathElem; + void setAlignAnchorHorz(const T & pathElem){ + anchorHorz = getElem(pathElem); updateAlign(); } + template inline - void setAlignAnchorVert(const std::string & pathElem){ - anchorVert = pathElem; + void setAlignAnchorVert(const T & pathElem){ + anchorVert = getElem(pathElem); updateAlign(); } @@ -809,6 +811,23 @@ struct AlignAdapterSVG : public AlignSVG { protected: + static inline + const std::string & getElem(const std::string &s){ + return s; + }; + + static inline + const char * getElem(const char *s){ + return s; + }; + + template + static inline + const std::string & getElem(const T & type){ + return EnumDict::dict.getKey(type, false); + } + + virtual inline void updateAlign() override { updateAlignStr(); diff --git a/src/drain/image/TreeUtilsSVG.cpp b/src/drain/image/TreeUtilsSVG.cpp index 7975ec91a..f8d04d41e 100644 --- a/src/drain/image/TreeUtilsSVG.cpp +++ b/src/drain/image/TreeUtilsSVG.cpp @@ -42,7 +42,7 @@ namespace image { PanelConfSVG TreeUtilsSVG::defaultConf; -//const std::set TreeUtilsSVG::abstractTags = { +/* const std::set TreeUtilsSVG::abstractTags = { svg::tag_t::STYLE, svg::tag_t::DESC, @@ -51,11 +51,14 @@ const std::set TreeUtilsSVG::abstractTags = { svg::tag_t::TITLE, svg::tag_t::TSPAN, }; +*/ //bool TreeUtilsSVG::isAbstract(svg::tag_t tag){ +/* bool TreeUtilsSVG::isAbstract(XML::intval_t tag){ return (abstractTags.find((XML::intval_t)tag) != abstractTags.end()); } +*/ @@ -520,7 +523,7 @@ void TreeUtilsSVG::superAlign(TreeSVG & object, AlignBase::Axis orientation, Lay */ // mout.attention("ACCEPT:", object->getTag()); - mout.special(__FUNCTION__, " start: ", object.data); //, object->getId(), " -> ", object->getBoundingBox()); + mout.special(__FUNCTION__, " start: ", object.data); //, object->getId(), " -> ", object->getBoundingBox()); // Depth-first @@ -529,7 +532,7 @@ void TreeUtilsSVG::superAlign(TreeSVG & object, AlignBase::Axis orientation, Lay } // mout.attention("ACCEPT:", object->getTag()); - mout.special(__FUNCTION__, " handle: ", object.data); //, object->getId(), " -> ", object->getBoundingBox()); + mout.special(__FUNCTION__, " handle: ", object.data); //, object->getId(), " -> ", object->getBoundingBox()); /// If main orientation (inside containers) is HORZ, stack containers VERT. And vice versa. @@ -699,7 +702,8 @@ void TreeUtilsSVG::translateAll(TreeSVG & object, const Point2D & */ int TranslatorSVG::visitPrefix(TreeSVG & tree, const TreeSVG::path_t & path) { TreeSVG & node = tree(path); - if (TreeUtilsSVG::isAbstract((svg::tag_t)node->getType())){ // skip TITLE, DESC etc. + //if (TreeUtilsSVG::isAbstract((svg::tag_t)node->getType())){ // skip TITLE, DESC etc. + if (node->isAbstract()){ // skip TITLE, DESC etc. return 1; } else { @@ -723,12 +727,12 @@ bool TreeUtilsSVG::computeBoundingBox(const TreeSVG & elem, Box & // skip, trust others (rect anchor) } else { - if (box.empty()){ + if (box.empty()){ // TODO: check/redefine empty box = elem->getBoundingBox(); } else { // drain::Logger mout(__FILE__, __FUNCTION__); - //mout.pending("Updating bbox ", box, " with ", elem->getBoundingBox()); + // mout.pending("Updating bbox ", box, " with ", elem->getBoundingBox()); box.expand(elem->getBoundingBox()); } } @@ -740,7 +744,7 @@ bool TreeUtilsSVG::computeBoundingBox(const TreeSVG & elem, Box & int BBoxRetrieverSVG::visitPrefix(TreeSVG & tree, const TreeSVG::path_t & path) { TreeSVG & node = tree(path); - if (node->typeIs(svg::SVG) || node->typeIs(svg::GROUP)){ + if (node->typeIs(svg::SVG, svg::GROUP)){ return 0; // continue (traverse children) } else { @@ -793,7 +797,8 @@ int RelativePathSetterSVG::visitPrefix(TreeSVG & tree, const TreeSVG::path_t & p drain::image::TreeSVG & imageNode = tree(path); const std::string imagePath = imageNode->get("xlink:href"); if (drain::StringTools::startsWith(imagePath, dir)){ - imageNode->set("xlink:href", imagePath.substr(dir.size())); // TODO: setURL ? + // imageNode->set("xlink:href", imagePath.substr(dir.size())); // TODO: setURL ? + imageNode->setUrl(imagePath.substr(dir.size())); } else { // mout.attention("could not set relative path: ", p, " href:", imagePath); diff --git a/src/drain/image/TreeUtilsSVG.h b/src/drain/image/TreeUtilsSVG.h index 7b0f80b65..73f174342 100644 --- a/src/drain/image/TreeUtilsSVG.h +++ b/src/drain/image/TreeUtilsSVG.h @@ -74,37 +74,15 @@ class FontSizes : public drain::UniTuple { struct PanelConfSVG { - /* - enum Axis {UNDEFINED_ORIENTATION=0, HORZ, VERT}; - typedef drain::EnumFlagger > AxisFlagger; - AxisFlagger orientation = HORZ; - - enum Direction {UNDEFINED_DIRECTION=0, INCR, DECR}; - typedef drain::EnumFlagger > DirectionFlagger; - DirectionFlagger direction = INCR; - */ - // LayoutSVG layout; - /// SVG file may contain several "modules", for example rows or columns of IMAGE:s. This is the name of the current module, contained in a GROUP. - // Current - // std::string groupName; - // int maxPerGroup = 10; - bool absolutePaths = false; + bool absolutePaths = true; // Currently, applications are recommended to handle "false" and "none". Or "auto"? // std::string title; // FontSizes fontSize; - /* - enum Legend {NO_LEGEND=0, LEFT=1, RIGHT=2, DUPLEX=LEFT|RIGHT, EMBED=4}; - typedef drain::EnumFlagger > LegendFlagger; - LegendFlagger legend; - */ - //typedef drain::EnumFlagger > LegendFlagger; - - inline // maxPerGroup(10), layout(Alignment::HORZ, LayoutSVG::INCR), legend(LEFT, EMBED), - PanelConfSVG() : absolutePaths(false){ + PanelConfSVG() : absolutePaths(true){ } /* @@ -132,18 +110,12 @@ struct TreeUtilsSVG { static PanelConfSVG defaultConf; // Consider separating Rack-specific properties. /* - static - const std::set abstractTags; - - static - bool isAbstract(svg::tag_t tag); - */ - static const std::set abstractTags; static bool isAbstract(XML::intval_t tag); + */ /// Compute bounding box of the whole structure. /** diff --git a/src/drain/util/ReferenceMap.h b/src/drain/util/ReferenceMap.h index f80d6a628..ab1b5f16c 100644 --- a/src/drain/util/ReferenceMap.h +++ b/src/drain/util/ReferenceMap.h @@ -112,15 +112,13 @@ class ReferenceMap2 : public SmartMap { inline void unlink(const std::string & key){ map_t::erase(key); - // std::map - /* - for (std::list::iterator it = keyList.begin(); it != keyList.end(); ++it) + for (std::list::iterator it = this->keyList.begin(); it != this->keyList.end(); ++it){ if (*it == key){ - keyList.erase(it); + this->keyList.erase(it); break; } - unitMap.erase(key); - */ + } + //unitMap.erase(key); } diff --git a/src/drain/util/XML.h b/src/drain/util/XML.h index c268bd402..b832b9fe1 100644 --- a/src/drain/util/XML.h +++ b/src/drain/util/XML.h @@ -194,6 +194,10 @@ class XML : protected ReferenceMap2 { setText(StringBuilder<>(args...).str()); // str() to avoid infinite loop } + inline + void setUrl(const std::string & s){ + url = s; + } // ---------------- Attributes --------------- diff --git a/src/main/graphics.cpp b/src/main/graphics.cpp index 94acd7c75..b2387a194 100644 --- a/src/main/graphics.cpp +++ b/src/main/graphics.cpp @@ -95,7 +95,11 @@ const std::string RackSVG::BACKGROUND_RECT = "bgRect"; * svgConf.link("group", TreeUtilsSVG::defaultGroupName); svgConf.link("orientation", svgConf_Orientation, drain::sprinter(TreeUtilsSVG::defaultOrientation.getDict().getKeys()).str()); svgConf.link("direction", svgConf_Direction, drain::sprinter(TreeUtilsSVG::defaultDirection.getDict().getKeys()).str()); - * + + drain::StyleSelectorXML("Elem"); + drain::StyleSelectorXML(svg::POLYGON); + drain::StyleSelectorXML(svg::POLYGON,GraphicsContext::IMAGE_BORDER); + */ @@ -118,12 +122,8 @@ drain::image::TreeSVG & RackSVG::getStyle(RackContext & ctx){ style->setType(svg::STYLE); - // MODE 2: deprecated: text (CTEXT) of sub-element - note: child elem does not know its parent's type (STYLE) - // style["text"] = "filler:black"; - // style["text"] = ("stroke:white; stroke-width:0.5em; stroke-opacity:0.25; fill:black; paint-order:stroke; stroke-linejoin:round"); - // style["text"].data = "stroker:white"; style[svg::TEXT] = { - {"font-type","arial"} + {"font-family","Helvetica, Arial, sans-serif"} }; // MODE 3: attribs of sub-element @@ -137,9 +137,6 @@ drain::image::TreeSVG & RackSVG::getStyle(RackContext & ctx){ //style["group.imageFrame > rect"].data = { typedef drain::StyleSelectorXML Select; - drain::StyleSelectorXML("Mika"); - drain::StyleSelectorXML(svg::POLYGON); - drain::StyleSelectorXML(svg::POLYGON,GraphicsContext::IMAGE_BORDER); // Text (new) // style["text.TITLE"] = { @@ -171,12 +168,12 @@ drain::image::TreeSVG & RackSVG::getStyle(RackContext & ctx){ }; style["rect.GROUP_TITLE"] = { - {"fill", "darkgreen"}, + {"fill", "gray"}, {"opacity", 0.5}, }; style["text.GROUP_TITLE"] = { - {"fill", "white"}, + {"fill", "black"}, }; style[GraphicsContext::MAIN_TITLE] = { @@ -203,33 +200,17 @@ drain::image::TreeSVG & RackSVG::getStyle(RackContext & ctx){ // style[".imageTitle2"] = "font-size:1.5em; stroke:white; stroke-opacity:0.5; stroke-width:0.3em; fill:darkslateblue; fill-opacity:1; paint-order:stroke; stroke-linejoin:round"; // drain::TreeUtils::dump(ctx.svgTrack); - } - - return style; -} -/* -drain::image::TreeSVG & RackSVG::getMainTitleGroup(RackContext & ctx){ - - drain::Logger mout(ctx.log, __FILE__, __FUNCTION__); - - TreeSVG & group = ctx.svgTrack[MAINTITLE]; - - //if (!ctx.svgTrack.hasChild("style")){ - if (group->isUndefined()){ + // MODE 2: deprecated: text (CTEXT) of sub-element - note: child elem does not know its parent's type (STYLE) + // style["text"] = "filler:black"; + // style["text"] = ("stroke:white; stroke-width:0.5em; stroke-opacity:0.25; fill:black; paint-order:stroke; stroke-linejoin:round"); + // style["text"].data = "stroker:white"; - // mout.debug("initializing style"); - group->setType(svg::GROUP); - group->setId("MAINTITLE"); - group["headerRect"](svg::RECT); - group[GENERAL](svg::TEXT); - group[TIME](svg::TEXT); - group[LOCATION](svg::TEXT); } - return group; + return style; } -*/ + drain::image::TreeSVG & RackSVG::getMainGroup(RackContext & ctx){ // , const std::string & name @@ -242,23 +223,9 @@ drain::image::TreeSVG & RackSVG::getMainGroup(RackContext & ctx){ // , const std drain::image::TreeSVG & main = ctx.svgTrack["rack-outputs"]; if (main -> isUndefined()){ - main->setType(svg::GROUP); - // main->setId(ctx.svgGroupNameSyntax); - // main->setAlign(AlignSVG::RIGHT, AlignSVG::OUTSIDE); // ??? - // main->setAlign(AlignSVG::TOP); - - /* - main["headerRect"](svg::RECT); - main[GENERAL](svg::TEXT); - main[TIME](svg::TEXT); - main[LOCATION](svg::TEXT); - */ } - // Ensure GROUP for main titles - // RackSVG::getMainTitleGroup(ctx); - return main; } @@ -277,33 +244,31 @@ drain::image::TreeSVG & RackSVG::getCurrentAlignedGroup(RackContext & ctx){ // w drain::TreeUtils::dump(mainGroup, mout); mout.end(); */ - //drain::image::NodeSVG::toStream(ostr, tree, defaultTag, indent) - /// - const std::string name = ctx.getFormattedStatus(ctx.svgGroupNameSyntax); // status updated upon last file save + ctx.svgGroupNameFormatted = ctx.getFormattedStatus(ctx.svgGroupNameSyntax); // status updated upon last file save + + drain::image::TreeSVG & alignedGroup = mainGroup[ctx.svgGroupNameFormatted]; + + if (alignedGroup -> isUndefined()){ + alignedGroup->setType(svg::GROUP); + alignedGroup->setId(ctx.svgGroupNameFormatted); + alignedGroup->addClass(drain::image::LayoutSVG::ALIGN_FRAME); + } - //mout.pending("considering group: '", groupName, "' <= ", groupMapper, vmap.get("what:quantity","??")); - mout.pending("Titles: ", ctx.svgTitles); + return alignedGroup; + // mout.pending("considering group: '", groupName, "' <= ", groupMapper, vmap.get("what:quantity","??")); + // mout.pending("Titles: ", ctx.svgTitles); + + /* + const std::string name = ctx.getFormattedStatus(ctx.svgGroupNameSyntax); // status updated upon last file save if (mainGroup.hasChild(name)){ ctx.svgGroupNameFormatted = name; return mainGroup[name]; } else { // NEW Group! Add grouptitles? - //if (ctx.svgTitles.isSet(GraphicsContext::ElemClass::TITLE) && (!FIRST)){ - /* - if (ctx.svgTitles.isSet(GraphicsContext::ElemClass::GROUPTITLE) && !FIRST){ - drain::image::TreeSVG & oldGroup = mainGroup[ctx.svgGroupNameFormatted](svg::GROUP); - addTitles(oldGroup, GraphicsContext::ElemClass::GROUPTITLE); - // oldGroup["mainRect"]->setAlign(AlignSVG::BOTTOM, AlignSVG::INSIDE); - oldGroup[GraphicsContext::ElemClass::GENERAL](svg::TEXT); // undeeded, debugging - oldGroup[GraphicsContext::ElemClass::GENERAL]->setText(ctx.svgGroupNameFormatted); - oldGroup[GraphicsContext::ElemClass::GENERAL]->set("first", "false"); - } - */ - drain::image::TreeSVG & alignedGroup = mainGroup[name](svg::GROUP); alignedGroup->setId(name); alignedGroup->addClass(drain::image::LayoutSVG::ALIGN_FRAME); @@ -311,18 +276,8 @@ drain::image::TreeSVG & RackSVG::getCurrentAlignedGroup(RackContext & ctx){ // w return alignedGroup; } - - // drain::image::TreeSVG & alignedGroup = mainGroup[name]; - - /* - if (alignedGroup->isUndefined()){ - alignedGroup->setType(svg::GROUP); - alignedGroup->setId(name); - alignedGroup->addClass(drain::image::LayoutSVG::ALIGN_FRAME); - } */ - // track[groupName](svg::GROUP); // ctx.svgPanelConf. } @@ -380,15 +335,15 @@ drain::image::TreeSVG & RackSVG::addImage(RackContext & ctx, const drain::image: // TEST // panelGroup->setAlignAnchor("image"); - drain::image::TreeSVG & image = panelGroup["image"](svg::IMAGE); // +EXT! + drain::image::TreeSVG & image = panelGroup[svg::IMAGE](svg::IMAGE); // +EXT! image->setId(filepath.basename); // unneeded, as TITLE also has it: - image["title"](drain::image::svg::TITLE) = filepath.basename; + image[drain::image::svg::TITLE](drain::image::svg::TITLE) = filepath.basename; image->setFrame(src.getGeometry().area); image->set("xlink:href", filepath.str()); // 2025 FIX: without .str() error addImageBorder(panelGroup); //, src.getGeometry().area); - + /* if ( ctx.svgDebug > 0){ // TODO: move to --gDebug etc. image->set("opacity", 0.5); @@ -416,9 +371,8 @@ drain::image::TreeSVG & RackSVG::addImage(RackContext & ctx, const drain::image: //rect2->setAlign(AlignSVG::OBJECT, AlignSVG::CENTER); //rect2->setAlign(AlignSVG::ANCHOR, AlignSVG::BOTTOM); //rect2->setAlign(AlignSVG::OBJECT, AlignSVG::BOTTOM); - } - + */ // Metadata: drain::image::TreeSVG & metadata = panelGroup[svg::METADATA](svg::METADATA); @@ -477,24 +431,26 @@ drain::image::TreeSVG & RackSVG::addImage(RackContext & ctx, const drain::image: drain::image::TreeSVG & group = getCurrentAlignedGroup(ctx); //[filepath.basename+"_Group"](svg::GROUP); drain::image::TreeSVG & image = group[filepath.basename](svg::IMAGE); // +EXT! - image->set("width", svg->get("width", 0)); - image->set("height", svg->get("height", 0)); + image->setFrame(svg->getBoundingBox().getFrame()); + // image->set("width", svg->get("width", 0)); + // image->set("height", svg->get("height", 0)); image->set("xlink:href", filepath.str()); - image["basename"](drain::image::svg::TITLE) = filepath.basename; + // image["basename"](drain::image::svg::TITLE) = filepath.basename; + image[drain::image::svg::TITLE](drain::image::svg::TITLE) = filepath.basename; + + // TODO: align ? + return image; + } /// Add pixel image (PNG) drain::image::TreeSVG & RackSVG::addImage(RackContext & ctx, const drain::FilePath & filepath, const drain::Frame2D & frame){ // what about prefix? drain::image::TreeSVG & group = getCurrentAlignedGroup(ctx); //[filepath.basename+"_Group"](svg::GROUP); - drain::image::TreeSVG & image = group[filepath.basename](svg::IMAGE); // +EXT! + drain::image::TreeSVG & image = group[filepath.basename](svg::IMAGE); // +EXT! image->setFrame(frame); - /* - image->set("width", frame.width); - image->set("height", frame.height); - */ image->set("xlink:href", filepath.str()); image[drain::image::svg::TITLE](drain::image::svg::TITLE) = filepath.basename; @@ -505,13 +461,9 @@ drain::image::TreeSVG & RackSVG::addImageBorder(drain::image::TreeSVG & imagePan // DEBUG: (may be fatal for input.sh etc.) // drain::image::svg::toStream(std::cout, image); drain::image::TreeSVG & imageBorder = imagePanelGroup[GraphicsContext::IMAGE_BORDER](svg::RECT); // +EXT! - imageBorder->addClass(drain::image::LayoutSVG::FLOAT); imageBorder->addClass(GraphicsContext::IMAGE_BORDER); // style + imageBorder->addClass(drain::image::LayoutSVG::FLOAT); imageBorder->setAlign(drain::image::AlignSVG::HORZ_FILL, drain::image::AlignSVG::VERT_FILL); - // image->addClass(drain::image::AlignSVG::ANCHOR); -> setAlignAnchor - // imageBorder->setStyle("stroke", "green"); // Note: without extension - // imageBorder->setStyle("fill", "none"); - // imageBorder->setFrame(frame); return imageBorder; } @@ -831,7 +783,7 @@ int MetaDataPrunerSVG::visitPostfix(TreeSVG & tree, const TreeSVG::path_t & path /** * \param frame - IMAGE or RECT inside which the text will be aligned */ -TreeSVG & getTextElem(const TreeSVG & frame, TreeSVG & current, const std::string key){ +TreeSVG & getTextElemFOO(const TreeSVG & frame, TreeSVG & current, const std::string key){ /* @@ -882,10 +834,10 @@ TreeSVG & getTextElem(const TreeSVG & frame, TreeSVG & current, const std::strin int TitleCreatorSVG::visitPostfix(TreeSVG & root, const TreeSVG::path_t & path){ + drain::Logger mout(__FILE__, __FUNCTION__); TreeSVG & group = root(path); - if (!group->typeIs(svg::GROUP)){ // At least METADATA must be skipped... return 0; } @@ -894,10 +846,8 @@ int TitleCreatorSVG::visitPostfix(TreeSVG & root, const TreeSVG::path_t & path){ if (group->hasClass(LayoutSVG::ALIGN_FRAME)){ // Problem: VERT layout? RackSVG::addTitles(group, GraphicsContext::ElemClass::GROUP_TITLE); - // oldGroup["mainRect"]->setAlign(AlignSVG::BOTTOM, AlignSVG::INSIDE); group[GraphicsContext::ElemClass::GENERAL](svg::TEXT); // undeeded, debugging group[GraphicsContext::ElemClass::GENERAL]->setText(path.back()); - // group[GraphicsContext::ElemClass::LOCATION]->ctext += "HEY!"; } @@ -905,26 +855,20 @@ int TitleCreatorSVG::visitPostfix(TreeSVG & root, const TreeSVG::path_t & path){ return 0; } - /* - if (! group->hasClass(GraphicsContext::IMAGE_PANEL)){ - return 0; - } - */ if (!(group->hasClass(LayoutSVG::ALIGN_FRAME) || group->hasClass(GraphicsContext::IMAGE_PANEL))){ return 0; } - drain::Logger mout(__FILE__, __FUNCTION__); if (group->hasClass(GraphicsContext::IMAGE_PANEL)){ // return 0; - group->setAlignAnchor("image"); + group->setAlignAnchor(svg::IMAGE); } - TreeSVG & metadata = group["metadata"]; + TreeSVG & metadata = group[svg::METADATA]; if (!metadata->getAttributes().empty()){ @@ -933,8 +877,15 @@ int TitleCreatorSVG::visitPostfix(TreeSVG & root, const TreeSVG::path_t & path){ // mout.attention("handle: ", current.data); // Note: these are "subtitles", not the main title + /* + if (group->hasClass(GraphicsContext::IMAGE_PANEL)){ + RackSVG::addTitles(group, GraphicsContext::ElemClass::IMAGE_TITLE); + } + */ + for (const auto & attr: metadata->getAttributes()){ + // This is a weird (old code)? Can metadata have formatting, like time|%Y=201408171845 ?? // Anyway, after split, key contains attrib key. std::string key, format; @@ -949,10 +900,12 @@ int TitleCreatorSVG::visitPostfix(TreeSVG & root, const TreeSVG::path_t & path){ elemClass = GraphicsContext::LOCATION; } + TreeSVG & text = group[elemClass](svg::TEXT); // +"_title" text->addClass(elemClass); //text->set("name", elemClass); + // text->addClass("imageTitle"); // style class (only) if (group->hasClass(GraphicsContext::IMAGE_PANEL)){ text->addClass(GraphicsContext::IMAGE_TITLE); @@ -963,9 +916,7 @@ int TitleCreatorSVG::visitPostfix(TreeSVG & root, const TreeSVG::path_t & path){ //drain::StringTools::split2(attr.second.toStr(), v, format, '|'); if (elemClass == GraphicsContext::TIME){ - // text->addClass(GraphicsContext::TIME); // , alignSvg::BOTTOM, alignSvg::LEFT); // CmdBaseSVG::FLOAT, - text->setAlign(AlignSVG::TOP, AlignSVG::LEFT); //, AlignSVG::INSIDE); - //text->setAlign(AlignSVG::LEFT); //, AlignSVG::INSIDE); + text->setAlign(AlignSVG::TOP, AlignSVG::LEFT); if (format.empty()){ //v = attr.second.toStr(); if (drain::StringTools::endsWith(key, "date")){ @@ -982,15 +933,10 @@ int TitleCreatorSVG::visitPostfix(TreeSVG & root, const TreeSVG::path_t & path){ mout.accept("TIME text format", format); } else if (elemClass == GraphicsContext::LOCATION){ - // text->addClass(GraphicsContext::LOCATION); // , alignSvg::TOP, alignSvg::RIGHT); // CmdBaseSVG::FLOAT, - text->setAlign(AlignSVG::BOTTOM, AlignSVG::RIGHT); //, AlignSVG::INSIDE); // AlignSVG::HorzAlign::RIGHT); // text->setAlignInside(LayoutSVG::Axis::HORZ, AlignSVG::MAX); // = RIGHT - // text->setAlign(AlignSVG::BOTTOM); //, AlignSVG::INSIDE); // AlignSVG::VertAlign::BOTTOM); // text->setAlignInside(LayoutSVG::Axis::VERT, AlignSVG::MAX); // = BOTTOM - // text->set("y", y + 60); // temporary - // text->ctext = " "; + text->setAlign(AlignSVG::BOTTOM, AlignSVG::RIGHT); } else { - text->setAlign(AlignSVG::MIDDLE, AlignSVG::CENTER); //, AlignSVG::INSIDE); // AlignSVG::HorzAlign::RIGHT); // text->setAlignInside(LayoutSVG::Axis::HORZ, AlignSVG::MAX); // = RIGHT - // text->setAlign(AlignSVG::MIDDLE); //, AlignSVG::INSIDE); // AlignSVG::VertAlign::BOTTOM); // text->setAlignInside(LayoutSVG::Axis::VERT, AlignSVG::MAX); // = BOTTOM + text->setAlign(AlignSVG::MIDDLE, AlignSVG::CENTER); text->ctext = drain::StringBuilder<'+'>(attr.first, attr.second); } diff --git a/src/main/resources-base.cpp b/src/main/resources-base.cpp index 133c311f7..8a328cc74 100644 --- a/src/main/resources-base.cpp +++ b/src/main/resources-base.cpp @@ -67,6 +67,7 @@ GraphicsContext::GraphicsContext() { } GraphicsContext::GraphicsContext(const GraphicsContext & ctx) { + svgPanelConf.absolutePaths = ctx.svgPanelConf.absolutePaths; svgGroupNameSyntax = ctx.svgGroupNameSyntax; svgTitles = ctx.svgTitles; }