How do I move just certain Path elements?

Question:
I want to move certain path elements around the page, but whenever I try it affects other things in the document, or even breaks the whole thing so the page is very messed up.

Answer:
Since path elements cannot have children, it is easy to isolate them and just apply a custom transformation to that element.

The following code will shift the elements down 100 units (assuming no page rotation). You can place this code in the ElementEdit sample to see in effect.

// convert PDFNet Matrix to raw PDF operators
static string Mtx2String(Matrix2D mtx)
{
return String.Format("{0} {1} {2} {3} {4} {5} cm", mtx.m_a, mtx.m_b, mtx.m_c, mtx.m_d, mtx.m_h, mtx.m_v);
}

static void ProcessElements(ElementReader reader, ElementWriter writer, ElementBuilder builder, XSet visited, Matrix2D page_shift_mtx)
{

Element element;
while ((element = reader.Next()) != null)
{
Element.Type type = element.GetType();
Matrix2D trans = element.GetGState().GetTransform();
switch (type)
{
case Element.Type.e_path:
--skip;
bool shift = skip == 0;
if(shift)
{
skip = 3;
Matrix2D ctm = element.GetCTM().Inverse();
writer.WriteString(Mtx2String(element.GetGState().GetTransform()) + "\n");
// figure out shift taking into account current transformation matrix
Matrix2D mtx = ctm * page_shift_mtx;
mtx.m_a = mtx.m_d = 1.0;
mtx.m_b = mtx.m_c = 0.0;
element.GetGState().SetTransform(mtx);
writer.WritePlacedElement(element);
}
else
{
writer.WriteElement(element);
}
break;
case Element.Type.e_form:
{
writer.WriteElement(element); // write Form XObject reference to current stream

Obj form_obj = element.GetXObject();
if (!visited.Contains(form_obj.GetObjNum())) // if this XObject has not been processed
{
// recursively process the Form XObject
visited.Add(form_obj.GetObjNum());
ElementWriter new_writer = new ElementWriter();

reader.FormBegin();
new_writer.Begin(form_obj, true);
ProcessElements(reader, new_writer, builder, visited, page_shift_mtx);
new_writer.End();
reader.End();
}
break;
}
default:
writer.WriteElement(element);
break;
}
}

}

void ProcessDoc(PDFDoc doc)
{
ElementWriter writer = new ElementWriter();
ElementReader reader = new ElementReader();
ElementBuilder builder = new ElementBuilder();
XSet visited = new XSet();

PageIterator itr = doc.GetPageIterator();

// dx,dy are the desired shift/displacement, where up is +y and right is +x
double dx = 0;
double dy = -360; // shift down 5 inches (5 * 72)

while (itr.HasNext())
{
Page page = itr.Current();
Matrix2D pg_mtx = page.GetDefaultMatrix().Inverse();
pg_mtx.m_h = pg_mtx.m_v = 0.0; // remove page translation
pg_mtx.Mult(ref dx, ref dy);
Matrix2D page_shift_mtx = new Matrix2D(1, 0, 0, 1, dx, dy);

visited.Add(page.GetSDFObj().GetObjNum());

reader.Begin(page);
writer.Begin(page, ElementWriter.WriteMode.e_replacement, false);
ProcessElements(reader, writer, builder, visited, page_shift_mtx);
writer.End();
reader.End();

itr.Next();
}
}