From: ishmal Date: Thu, 20 Apr 2006 21:49:49 +0000 (+0000) Subject: Use dual maps to remove duplicates in style table X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=1bc7ff4868e64da17954b8545c9510ae6165ae7a;p=inkscape.git Use dual maps to remove duplicates in style table --- diff --git a/src/extension/internal/odf.cpp b/src/extension/internal/odf.cpp index bfb38656a..704d388fd 100644 --- a/src/extension/internal/odf.cpp +++ b/src/extension/internal/odf.cpp @@ -120,6 +120,21 @@ static std::string getExtension(const std::string &fname) return ext; } + +static std::string formatTransform(NR::Matrix &tf) +{ + std::string str; + if (!tf.test_identity()) + { + char buf[128]; + snprintf(buf, 127, "matrix(%.3f %.3f %.3f %.3f %.3f %.3f)", + tf[0], tf[1], tf[2], tf[3], tf[4], tf[5]); + str = buf; + } + return str; +} + + /** * Method descends into the repr tree, converting image and style info * into forms compatible in ODF. @@ -205,7 +220,30 @@ OdfOutput::preprocess(ZipFile &zf, Inkscape::XML::Node *node) si.stroke = "solid"; } - styleTable[id] = si; + //Look for existing identical style; + bool styleMatch = false; + std::map::iterator iter; + for (iter=styleTable.begin() ; iter!=styleTable.end() ; iter++) + { + if (si.equals(iter->second)) + { + //map to existing styleTable entry + std::string styleName = iter->first; + g_message("found duplicate style:%s", styleName.c_str()); + styleLookupTable[id] = styleName; + styleMatch = true; + break; + } + } + //None found, make a new pair or entries + if (!styleMatch) + { + char buf[16]; + snprintf(buf, 15, "style%d", styleTable.size()); + std::string styleName = buf; + styleTable[styleName] = si; + styleLookupTable[id] = styleName; + } } /* @@ -399,14 +437,14 @@ bool OdfOutput::writeStyle(Writer &outs) StyleInfo s(iter->second); outs.printf(" style:family=\"graphic\" style:parent-style-name=\"standard\">\n"); outs.printf(" \n"); outs.printf("\n"); @@ -482,19 +520,19 @@ bool OdfOutput::writeTree(Writer &outs, Inkscape::XML::Node *node) } SPItem *item = SP_ITEM(reprobj); + std::string nodeName = node->name(); std::string id = getAttribute(node, "id"); - NR::Matrix tf = sp_item_i2d_affine(item); + NR::Matrix tf = sp_item_i2d_affine(item); NR::Rect bbox = sp_item_bbox_desktop(item); //Flip Y into document coordinates - double svgHeight = sp_document_height(SP_ACTIVE_DOCUMENT); - double doc_height = svgHeight; // * pxToCm; + double doc_height = sp_document_height(SP_ACTIVE_DOCUMENT); NR::Matrix doc2dt_tf = NR::Matrix(NR::scale(1, -1)); doc2dt_tf = doc2dt_tf * NR::Matrix(NR::translate(0, doc_height)); - tf = tf * doc2dt_tf; - bbox = bbox * doc2dt_tf; + //tf = tf * doc2dt_tf; + //bbox = bbox * doc2dt_tf; double x = pxToCm * bbox.min()[NR::X]; double y = pxToCm * bbox.min()[NR::Y]; @@ -534,6 +572,27 @@ bool OdfOutput::writeTree(Writer &outs, Inkscape::XML::Node *node) } else if (nodeName == "image" || nodeName == "svg:image") { + if (!SP_IS_IMAGE(item)) + { + g_warning(" is not an SPImage. Why? ;-)"); + return false; + } + + SPImage *img = SP_IMAGE(item); + double ix = img->x.computed; + double iy = img->y.computed; + double iwidth = img->width.computed; + double iheight = img->height.computed; + + NR::Rect ibbox(NR::Point(ix, iy), NR::Point(iwidth, iheight)); + ix = pxToCm * ibbox.min()[NR::X]; + iy = pxToCm * ibbox.min()[NR::Y]; + iwidth = pxToCm * ( ibbox.max()[NR::X] - ibbox.min()[NR::X] ); + iheight = pxToCm * ( ibbox.max()[NR::Y] - ibbox.min()[NR::Y] ); + + + std::string itemTransformString = formatTransform(item->transform); + std::string href = getAttribute(node, "xlink:href"); std::map::iterator iter = imageTable.find(href); if (iter == imageTable.end()) @@ -543,15 +602,19 @@ bool OdfOutput::writeTree(Writer &outs, Inkscape::XML::Node *node) } std::string newName = iter->second; + outs.printf(" 0) outs.printf("id=\"%s\" ", id.c_str()); outs.printf("draw:style-name=\"gr1\" draw:text-style-name=\"P1\" draw:layer=\"layout\" "); outs.printf("svg:x=\"%.3fcm\" svg:y=\"%.3fcm\" ", - x, y, width); - outs.printf("svg:width=\"%.3fcm\" svg:height=\"%.3fcm\">\n", - width, height); + ix, iy); + outs.printf("svg:width=\"%.3fcm\" svg:height=\"%.3fcm\" ", + iwidth, iheight); + if (itemTransformString.size() > 0) + outs.printf("draw:transform=\"%s\" ", itemTransformString.c_str()); + outs.printf(">\n"); outs.printf(" \n"); @@ -586,10 +649,13 @@ bool OdfOutput::writeTree(Writer &outs, Inkscape::XML::Node *node) if (id.size()>0) outs.printf("id=\"%s\" ", id.c_str()); - std::map::iterator iter; - iter = styleTable.find(id); - if (iter != styleTable.end()) - outs.printf("draw:style-name=\"%s\" ", id.c_str()); + std::map::iterator iter; + iter = styleLookupTable.find(id); + if (iter != styleLookupTable.end()) + { + std::string styleName = iter->second; + outs.printf("draw:style-name=\"%s\" ", styleName.c_str()); + } outs.printf("draw:layer=\"layout\" svg:x=\"%.3fcm\" svg:y=\"%.3fcm\" ", x, y); @@ -708,6 +774,7 @@ bool OdfOutput::writeContent(ZipFile &zf, Inkscape::XML::Node *node) outs.printf("\n"); outs.printf("\n"); + outs.printf("\n"); outs.printf("\n"); if (!writeTree(outs, node)) @@ -717,6 +784,7 @@ bool OdfOutput::writeContent(ZipFile &zf, Inkscape::XML::Node *node) } outs.printf("\n"); + outs.printf("\n"); outs.printf("\n"); outs.printf("\n"); @@ -763,6 +831,7 @@ OdfOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const * { ZipFile zf; styleTable.clear(); + styleLookupTable.clear(); imageTable.clear(); preprocess(zf, doc->rroot); diff --git a/src/extension/internal/odf.h b/src/extension/internal/odf.h index e1cf133db..5b6a2bdde 100644 --- a/src/extension/internal/odf.h +++ b/src/extension/internal/odf.h @@ -67,13 +67,6 @@ public: init(); } - StyleInfo(const std::string &nameArg, const std::string &styleArg) - { - init(); - name = nameArg; - style = styleArg; - } - StyleInfo(const StyleInfo &other) { assign(other); @@ -87,75 +80,52 @@ public: void assign(const StyleInfo &other) { - name = other.name; - style = other.style; - cssStyle = other.cssStyle; - stroke = other.stroke; - strokeColor = other.strokeColor; - strokeWidth = other.strokeWidth; - fill = other.fill; - fillColor = other.fillColor; + stroke = other.stroke; + strokeColor = other.strokeColor; + strokeWidth = other.strokeWidth; + strokeOpacity = other.strokeOpacity; + fill = other.fill; + fillColor = other.fillColor; + fillOpacity = other.fillOpacity; } void init() { - name = "none"; - style = "none"; - cssStyle = "none"; - stroke = "none"; - strokeColor = "none"; - strokeWidth = "none"; - fill = "none"; - fillColor = "none"; + stroke = "none"; + strokeColor = "none"; + strokeWidth = "none"; + strokeOpacity = "none"; + fill = "none"; + fillColor = "none"; + fillOpacity = "none"; } virtual ~StyleInfo() {} - std::string getName() - { - return name; - } - - std::string getCssStyle() - { - return cssStyle; - } - - std::string getStroke() - { - return stroke; - } - - std::string getStrokeColor() - { - return strokeColor; - } - - std::string getStrokeWidth() - { - return strokeWidth; - } - - - std::string getFill() - { - return fill; - } - - std::string getFillColor() + //used for eliminating duplicates in the styleTable + bool equals(const StyleInfo &other) { - return fillColor; + if ( + stroke != other.stroke || + strokeColor != other.strokeColor || + strokeWidth != other.strokeWidth || + strokeOpacity != other.strokeOpacity || + fill != other.fill || + fillColor != other.fillColor || + fillOpacity != other.fillOpacity + ) + return false; + return true; } - std::string name; - std::string style; - std::string cssStyle; std::string stroke; std::string strokeColor; std::string strokeWidth; + std::string strokeOpacity; std::string fill; std::string fillColor; + std::string fillOpacity; }; @@ -176,6 +146,15 @@ public: private: + /* Style table + Uses a two-stage lookup to avoid style duplication. + Use like: + StyleInfo si = styleTable[styleLookupTable[id]]; + but check for errors, of course + */ + //element id -> style entry name + std::map styleLookupTable; + //style entry name -> style info std::map styleTable; //for renaming image file names