C++使用GDI+解析SVG绘制文本时坐标定位错误的解决求助
SVG文本绘制位置异常问题排查与解决
近期开发一个读取SVG文件并使用GDI+绘制的小型项目,遇到文本绘制位置与SVG显示效果不一致的问题。已确认SVG信息读取正确,最初推测是GDI+与SVG坐标系存在差异,相关代码及SVG示例如下:

SVG示例代码
<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>
C++类定义代码
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; };
C++文本绘制代码
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); }
更新说明:已找到问题根源——未处理文本内容换行的解析场景。SVG中<text>标签文本内容不换行时代码可正常工作,换行则绘制出错。感谢各位帮助!
内容的提问来源于stack exchange,提问作者Tran_Duc_Tung_HCMUS
相关产品推荐
相关产品推荐

