The issue of incorrect positioning of text coordinates from SVG in C++ using the GDI+ library

68 Views Asked by At

Lately i have been working on a small project that reads information from SVG file and then using GDI+ to draw, but im having trouble with text drawing position, because what i draw is not the same as what SVG draw, im pretty sure that i read the information correctly. I guess there is a difference between the coordinate system of GDI+ and SVG, below is the code i use to draw text. can anyone suggest me a way to fix this ? Thanks a lot!

Picture of wrong drawing of text

<svg xmlns="http://www.w3.org/2000/svg">
    <g transform="translate(100, 100) rotate(45)">
      <line x1="10" y1="10" x2="85" y2="10" stroke="rgb(255,0,0)"/>
      <rect x="10" y="20" height="50" width="75"
            stroke="rgb(0,255,0)" fill="rgb(0,255,0)"/>
      <text x="10" y="120" stroke="rgb(255,0,0)" fill="rgb(0,0,255)" font-size ="50">
        Text grouped with shapes</text>
    </g>
</svg>

class TextSVG : public ShapeSVG {
private:
    PointSVG p;
    double fontSize = 0;
    int fontWeight1 = 0;
    string fontWeight2 = "";
    string fontStyle = "";
    string fontFamily = "Times New Roman";
    string textAnchor = "";
    string textDecoration = "";
    string textTransform = "";
    string textContent = "";
    bool checkStroke = 0;
 
    
public:;
    void parseShapeSVG(const SVGElement& element) override;
    void drawSVG(Graphics& graphics) override;

    void TranslateText(Graphics& graphics, float dx, float dy) {
        graphics.TranslateTransform(dx, dy);
    }
    void ScaleText(Graphics& graphics, float x, float y) {
        
        graphics.ScaleTransform(x, y);

    }
    void RotateText(Graphics& graphics, float angleDegrees) {

        //graphics.TranslateTransform(0, 0);
        graphics.RotateTransform(angleDegrees);

    }

    void getPointMINMAX(pointMinMax&) override;
};
void TextSVG::drawSVG(Graphics& graphics) {
    graphics.SetSmoothingMode(SmoothingModeAntiAlias);
    //graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
    GraphicsState state = graphics.Save();
    bool checkScale = 0;
    for (const auto& tf : tfSVG) {
        if (tf.transformType == "translate") {
            this->TranslateText(graphics, tf.translateX, tf.translateY);
        }
        else if (tf.transformType == "scale") {
            this->ScaleText(graphics, tf.scaleX, tf.scaleY);
            checkScale = 1;
        }
        else if (tf.transformType == "rotate") {
            this->RotateText(graphics, tf.rotateAngle);
        }
    }
    
    int font1 = FontStyleRegular;
    if (fontWeight2 == "bold" || fontWeight2 == "Bold" || fontWeight1 >= 550) {
        font1 = FontStyleBold;
    }
    else if (fontStyle == "italic" || fontStyle == "Italic") {
        font1 = FontStyleItalic;
    }
    else if ((fontWeight2 == "bold" || fontWeight2 == "Bold" || fontWeight1 >= 550) && (fontStyle == "italic" || fontStyle == "Italic")) {
        font1 = FontStyleBoldItalic;
    }
    else if (textDecoration == "underline" || textDecoration == "Underline") {
        font1 = FontStyleUnderline;
    }
    else if (textDecoration == "line-through") {
        font1 = FontStyleStrikeout;
    }


    unordered_map <string, float>offset_map= {
        {"start", -0.15 * fontSize},
        {"middle", 0.0f},
        {"end", 0.15 * fontSize}
    };
    unordered_map <string, Gdiplus::StringAlignment> text_anchor_map = {
     { "start", Gdiplus::StringAlignment::StringAlignmentNear },
     { "middle", Gdiplus::StringAlignment::StringAlignmentCenter },
     { "end", Gdiplus::StringAlignment::StringAlignmentFar }
    };


    wstring wstr = wstring(textContent.begin(), textContent.end());
    std::wstring ws = wstring(fontFamily.begin(), fontFamily.end());
    FontFamily fontFamily1(ws.c_str());

   
    Gdiplus::PointF origin(p.x, p.y - 0.9 * fontSize);
    origin.X += offset_map[textAnchor];
    Gdiplus::StringFormat format(Gdiplus::StringFormat::GenericDefault());
    format.SetAlignment(text_anchor_map[textAnchor]);

    GraphicsPath path; 
    path.AddString(wstr.c_str(), -1, &fontFamily1, font1, fontSize, origin, &format);

    SolidBrush brush(Color(fillOpacity * 255, fill.R, fill.G, fill.B));
    graphics.FillPath(&brush, &path);

    if (checkStroke == 1) {
        Pen pen(Color(strokeOpacity * 255, stroke.R, stroke.G, stroke.B), strokeWidth);
        graphics.DrawPath(&pen, &path);
    }

    graphics.Restore(state);
}

UPDATE: i know what is wrong, that is i forgot to add more cases to read text, when the text content is on a new line, it represents the same drawing. My code just works correct when it is like this:

<svg xmlns="http://www.w3.org/2000/svg">
    <g transform="translate(100, 100) rotate(45)">
      <line x1="10" y1="10" x2="85" y2="10" stroke="rgb(255,0,0)"/>
      <rect x="10" y="20" height="50" width="75"
            stroke="rgb(0,255,0)" fill="rgb(0,255,0)"/>
      <text x="10" y="120" stroke="rgb(255,0,0)" fill="rgb(0,0,255)" font-size ="50">Text grouped with shapes</text>
    </g>
</svg>

Instead of the original version. Many thanks to all that have helped me so far on this post :DD.

0

There are 0 best solutions below