Perhaps you should code according to the following code from chromium, especially the order of SetTransformLocal and Append, etc. I suppose there is no trick about SetTransformLocal.:
bool SkXPSDevice::endSheet() {
//XPS is fixed at 96dpi (XPS Spec 11.1).
static const float xpsDPI = 96.0f;
static const float inchesPerMeter = 10000.0f / 254.0f;
static const float targetUnitsPerMeter = xpsDPI * inchesPerMeter;
const float scaleX = targetUnitsPerMeter
/ SkScalarToFLOAT(this->fCurrentUnitsPerMeter.fX);
const float scaleY = targetUnitsPerMeter
/ SkScalarToFLOAT(this->fCurrentUnitsPerMeter.fY);
//Create the scale canvas.
SkTScopedComPtr<IXpsOMCanvas> scaleCanvas;
HRBM(this->fXpsFactory->CreateCanvas(&scaleCanvas),
"Could not create scale canvas.");
SkTScopedComPtr<IXpsOMVisualCollection> scaleCanvasVisuals;
HRBM(scaleCanvas->GetVisuals(&scaleCanvasVisuals),
"Could not get scale canvas visuals.");
SkTScopedComPtr<IXpsOMMatrixTransform> geomToPhys;
XPS_MATRIX rawGeomToPhys = { scaleX, 0, 0, scaleY, 0, 0, };
HRBM(this->fXpsFactory->CreateMatrixTransform(&rawGeomToPhys, &geomToPhys),
"Could not create geometry to physical transform.");
HRBM(scaleCanvas->SetTransformLocal(geomToPhys.get()),
"Could not set transform on scale canvas.");
//Add the content canvas to the scale canvas.
HRBM(scaleCanvasVisuals->Append(this->fCurrentXpsCanvas.get()),
"Could not add base canvas to scale canvas.");
//Create the page.
XPS_SIZE pageSize = {
SkScalarToFLOAT(this->fCurrentCanvasSize.width()) * scaleX,
SkScalarToFLOAT(this->fCurrentCanvasSize.height()) * scaleY,
};
SkTScopedComPtr<IXpsOMPage> page;
HRB(this->createXpsPage(pageSize, &page));
SkTScopedComPtr<IXpsOMVisualCollection> pageVisuals;
HRBM(page->GetVisuals(&pageVisuals), "Could not get page visuals.");
//Add the scale canvas to the page.
HRBM(pageVisuals->Append(scaleCanvas.get()),
"Could not add scale canvas to page.");
//Create the package writer if it hasn't been created yet.
if (NULL == this->fPackageWriter.get()) {
SkTScopedComPtr<IXpsOMImageResource> image;
//Ignore return, thumbnail is completely optional.
this->createXpsThumbnail(page.get(), 0, &image);
HRB(this->initXpsDocumentWriter(image.get()));
}
HRBM(this->fPackageWriter->AddPage(page.get(),
&pageSize,
NULL,
NULL,
NULL,
NULL),
"Could not write the page.");
this->fCurrentXpsCanvas.reset();
return true;
}
and
void SkXPSDevice::drawDevice(const SkDraw& d, SkBaseDevice* dev,
int x, int y,
const SkPaint&) {
SkXPSDevice* that = static_cast<SkXPSDevice*>(dev);
SkTScopedComPtr<IXpsOMMatrixTransform> xpsTransform;
XPS_MATRIX rawTransform = {
1.0f,
0.0f,
0.0f,
1.0f,
static_cast<FLOAT>(x),
static_cast<FLOAT>(y),
};
HRVM(this->fXpsFactory->CreateMatrixTransform(&rawTransform, &xpsTransform),
"Could not create layer transform.");
HRVM(that->fCurrentXpsCanvas->SetTransformLocal(xpsTransform.get()),
"Could not set layer transform.");
//Get the current visual collection and add the layer to it.
SkTScopedComPtr<IXpsOMVisualCollection> currentVisuals;
HRVM(this->fCurrentXpsCanvas->GetVisuals(¤tVisuals),
"Could not get current visuals for layer.");
HRVM(currentVisuals->Append(that->fCurrentXpsCanvas.get()),
"Could not add layer to current visuals.");
}