NiXPS SDK by example: selecting and enumerating objects on an XPS page
The NiXPS SDK provides a an object model of the XPS page content to its users.
This has the nice effect that objects can be refered to by their ID, and all sorts of other nice things become possible like selections etc...
I would like to illustrate some of these aspects via an example that I've sent to a customer the other day.
This customer is looking for ways to get hold of the geometrics of all the objects on an XPS page, and wants to do further calculations based on that.
This is fairly easy to do with our NiXPS SDK v2.5.3, and I'll describe the example and code here (in C++).
First - some housekeeping: opening a file, and getting a handler to page we're interested in:
void test_walk_content(ostream &os)
{
NOPackage *lPackage=NOPackage::readPackageFromFile("../testfiles/Virtual_PC_Technical_Overview_2007.xps");
// first document, first page
NODocument lDoc=lPackage->getDocument(0);
NOPage lPage=lDoc.getPage(0);
I use a test file here that I pulled from the internet.
Next, we need to make sure that the NiXPS library calculates the geometric information for the particular page.
Currently this is a by-product of rendering, so we instruct the library to render to a very small buffer.
(In v2.6 we are going to decouple geometric calculation from rendering.)
// render to calculate bounding boxes
UInt32 lBufferLength = 10 * 10 * 3;
UInt8 *lBuffer = (UInt8 *) malloc(lBufferLength);
memset(lBuffer,0,lBufferLength);
lPage.renderToImage(lBuffer,10,10,true);
free(lBuffer);
Next we select everything on the page, and get hold of the selections list, which is a NOSelection type:
// select all content on the page
lPage.selectAll();
// get selection
NOSelection lSelection = lPage.getCopyOfSelection();
With this NOSelection type, we can now enumerate all objects:
// enumerate the selection, get the boundng box (in XPS document coordinates), and
// print this out, together with the type of object and its ID
UInt32 lNumberOfSelectedObjects = lSelection.getNumberOfSelectedObjects();
UInt32 i=0; for (;i<lNumberOfSelectedObjects;i++)
{
For every selected object, we get the bounding box
NOBase lSelectedObject = lSelection.getSelectedObject(i);
NCommon::doubleRect lRect = lPage.getBoundingBox(lSelectedObject.mID);
And we find out the type, and store that in a string for printing it out later:
std::string lType="unknown";
switch (lSelectedObject.mType)
{
case xPath: lType="Path"; break;
case xGlyphs: lType="Glyphs"; break;
default: lType="SomethingElse"; break;
}
We now summerize everything by printing it out, this is also the end of our loop:
os << i << ": ID:" << lSelectedObject.mID << " Type:" << lType << " bbox [" << lRect.mTop << "," << lRect.mBottom << "," << lRect.mLeft << "," << lRect.mRight << "]" << std::endl;
}
and it also concludes our function
}
There is a lot of powerful functionality like this in our NiXPS SDK, everything is listed in our
api documentation.
But an API reference doesn't really have the same illustrative power, as a real code example holds.
That's why we ship code examples in our SDK, and continue to enhance this by adding more samples to the SDK.