How do I rotate an annotation with custom appearance by 90 degree increments?

Question:

I would like to allow my users to rotate an annotation manually by 90 degree increments. In particular I want to rotate RubberStamp annotations.

Answer:

The following code will rotate the annotations bounding box around its center, and then will add a 90 degree rotation (around the center of the annotation) to the appearance stream.

/////////////////////////////////////////////////////////////////
// Rotate annotation itself
Rect bbox = annot.GetRect();
double cx = bbox.x1 + (bbox.Width() / 2.0);
double cy = bbox.y1 + (bbox.Height() / 2.0);
double w_2 = bbox.Height() / 2.0;
double h_2 = bbox.Width() / 2.0;
bbox = new Rect(cx - w_2, cy - h_2, cx + w_2, cy + h_2);
annot.SetRect(bbox);

SDF.Obj appObj = annot.GetAppearance();
/////////////////////////////////////////////////////////////////
// Find previous matrix if present
Matrix2D original = new Matrix2D();
SDF.Obj mtxObj = appObj.FindObj("Matrix");
if (mtxObj != null)
{
original.m_a = mtxObj.GetAt(0).GetNumber();
original.m_b = mtxObj.GetAt(1).GetNumber();
original.m_c = mtxObj.GetAt(2).GetNumber();
original.m_d = mtxObj.GetAt(3).GetNumber();
original.m_h = mtxObj.GetAt(4).GetNumber();
original.m_v = mtxObj.GetAt(5).GetNumber();
}

/////////////////////////////////////////////////////////////////
// rotatate Appearance Stream
var apBbox = new pdftron.PDF.Rect(appObj.FindObj("BBox"));
cx = apBbox.x1 + (apBbox.Width() / 2.0);
cy = apBbox.y1 + (apBbox.Height() / 2.0);
Matrix2D origin = new Matrix2D(1, 0, 0, 1, -cx, -cy);
Matrix2D rot = Matrix2D.RotationMatrix(Math.PI / 2); // rotation in radians, e.g. 90deg
Matrix2D trans = new Matrix2D(1, 0, 0, 1, cx, cy);
Matrix2D mtx = trans * rot * origin * original;
appObj.PutMatrix("Matrix", mtx);