Use PyObject_CallObject rather than interpreting generated code

Rather than generating Python code and interpreting it, which, in C++, is fraught with issues of creating the correct syntax for a str token when the text contains certain special characters like double-quote and backslash, the modified code makes call(s) to PyObject_CallObject which takes the C++ string and makes the appropriate conversion itself. The steps in building the Position passed to make_text are also done using c++ objects until the final Python Placement object is needed.
This commit is contained in:
Kevin Martin
2023-11-20 09:59:06 -05:00
committed by Yorik van Havre
parent a86ae2790b
commit 4e12621954

View File

@@ -60,6 +60,7 @@
#include <Base/Matrix.h>
#include <Base/Parameter.h>
#include <Base/Vector3D.h>
#include <Base/PlacementPy.h>
#include <Mod/Part/App/PartFeature.h>
#include "ImpExpDxf.h"
@@ -321,16 +322,21 @@ void ImpExpDxfRead::OnReadText(const double* point,
const char* text,
const double rotation)
{
// Note that our parameters do not contain all the information needed to properly orient the text.
// As a result the text will always appear on the XY plane
if (optionImportAnnotations) {
if (LayerName().substr(0, 6) != "BLOCKS") {
Base::Interpreter().runString("import Draft");
Base::Interpreter().runStringArg("p=FreeCAD.Vector(%f,%f,%f)",
point[0] * optionScaling,
point[1] * optionScaling,
point[2] * optionScaling);
Base::Interpreter().runString("a=FreeCAD.Vector(0,0,1)");
Base::Interpreter().runStringArg("pl=FreeCAD.Placement(p,a,%f)", rotation);
Base::Interpreter().runStringArg("Draft.make_text(\"%s\",pl, height=%f)", text, height);
PyObject* draftModule = nullptr;
Base::Vector3d insertionPoint(point[0], point[1], point[2]);
insertionPoint *= optionScaling;
Base::Rotation rot(Base::Vector3d(0, 0, 1), rotation);
PyObject* placement = new Base::PlacementPy(Base::Placement(insertionPoint, rot));
draftModule = PyImport_ImportModule("Draft");
if (draftModule != nullptr)
PyObject_CallMethod(draftModule, "make_text", "sOif", text, placement, 0, height);
// We own all the return values so we must release them.
Py_DECREF(placement);
Py_XDECREF(draftModule);
}
// else std::cout << "skipped text in block: " << LayerName() << std::endl;
}