I think I find a way to avoid most of the version dependant P/Invoke in the extension methods by building the ResultBuffer from the text properties.
// inspired by: https://adndevblog.typepad.com/autocad/2013/10/mirroring-a-dbtext-entity.html
public static class Extension
{
/// <summary>
/// Gets the points of the text bounding box.
/// </summary>
/// <param name="dbText">Instance of DBText the method applies to.</param>
/// <returns>The bounding box points in counterclockwise sense.</returns>
public static Point3d[] GetTextBoxCorners(this DBText dbText)
{
if (dbText == null)
throw new ArgumentNullException("dbText");
int mirrored = dbText.IsMirroredInX ? 2 : 0;
mirrored |= dbText.IsMirroredInY ? 4 : 0;
var rb = new ResultBuffer(
new TypedValue(1, dbText.TextString),
new TypedValue(40, dbText.Height),
new TypedValue(41, dbText.WidthFactor),
new TypedValue(51, dbText.Oblique),
new TypedValue(7, dbText.TextStyleName),
new TypedValue(71, mirrored),
new TypedValue(72, (int)dbText.HorizontalMode),
new TypedValue(73, (int)dbText.VerticalMode));
var point1 = new double[3];
var point2 = new double[3];
acedTextBox(rb.UnmanagedObject, point1, point2);
var xform =
Matrix3d.Displacement(dbText.Position.GetAsVector()) *
Matrix3d.Rotation(dbText.Rotation, dbText.Normal, Point3d.Origin) *
Matrix3d.WorldToPlane(new Plane(Point3d.Origin, dbText.Normal));
return new[]
{
new Point3d(point1).TransformBy(xform),
new Point3d(point2[0], point1[1], 0.0).TransformBy(xform),
new Point3d(point2).TransformBy(xform),
new Point3d(point1[0], point2[1], 0.0).TransformBy(xform)
};
}
/// <summary>
/// Mirrors the block reference.
/// </summary>
/// <param name="source">Instance of BlockReference the method applies to.</param>
/// <param name="axis">Mirror axis line.</param>
/// <param name="eraseSource">Value indicating if the source object have to be erased</param>
public static void Mirror(this BlockReference source, Line3d axis, bool eraseSource)
{
if (source == null)
throw new ArgumentNullException("source");
if (axis == null)
throw new ArgumentNullException("axis");
var db = source.Database;
var tr = db.TransactionManager.TopTransaction;
if (tr == null)
throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NoActiveTransactions);
BlockReference mirrored;
if (eraseSource)
{
mirrored = source;
if (!mirrored.IsWriteEnabled)
{
tr.GetObject(mirrored.ObjectId, OpenMode.ForWrite);
}
}
else
{
var ids = new ObjectIdCollection(new[] { source.ObjectId });
var mapping = new IdMapping();
db.DeepCloneObjects(ids, db.CurrentSpaceId, mapping, false);
mirrored = (BlockReference)tr.GetObject(mapping[source.ObjectId].Value, OpenMode.ForWrite);
}
mirrored.TransformBy(Matrix3d.Mirroring(axis));
foreach (ObjectId id in mirrored.AttributeCollection)
{
var attRef = (AttributeReference)tr.GetObject(id, OpenMode.ForWrite);
var pts = attRef.GetTextBoxCorners();
attRef.TransformBy(Matrix3d.Rotation(Math.PI, pts[0].GetVectorTo(pts[3]), pts[0] + pts[0].GetVectorTo(pts[2]) / 2.0));
}
}
/// <summary>
/// Mirrors the DBText.
/// </summary>
/// <param name="source">Instance of BlockReference the method applies to.</param>
/// <param name="axis">Mirror axis line.</param>
/// <param name="eraseSource">Value indicating if the source object have to be erased.</param>
public static void Mirror(this DBText source, Line3d axis, bool eraseSource)
{
if (source == null)
throw new ArgumentNullException("source");
if (axis == null)
throw new ArgumentNullException("axis");
var db = source.Database;
var tr = db.TransactionManager.TopTransaction;
if (tr == null)
throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NoActiveTransactions);
DBText mirrored;
if (eraseSource)
{
mirrored = source;
if (!mirrored.IsWriteEnabled)
{
tr.GetObject(mirrored.ObjectId, OpenMode.ForWrite);
}
}
else
{
var ids = new ObjectIdCollection(new[] { source.ObjectId });
var mapping = new IdMapping();
db.DeepCloneObjects(ids, db.CurrentSpaceId, mapping, false);
mirrored = (DBText)tr.GetObject(mapping[source.ObjectId].Value, OpenMode.ForWrite);
}
mirrored.TransformBy(Matrix3d.Mirroring(axis));
var pts = mirrored.GetTextBoxCorners();
mirrored.TransformBy(Matrix3d.Rotation(Math.PI, pts[0].GetVectorTo(pts[3]), pts[0] + pts[0].GetVectorTo(pts[2]) / 2.0));
}
[DllImport("accore.dll", CharSet = CharSet.Unicode,
CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedTextBox")]
static extern System.IntPtr acedTextBox(IntPtr rb, double[] point1, double[] point2);
}