Share via

SetTransformLocal question.

kasmer 66 Reputation points
2021-08-05T20:35:34.363+00:00

Hello,

I have the following code;

IXpsOMMatrixTransform* rawGeomToPhys;
                            result = xpsObjectFactory->CreateMatrixTransform(&combinedMatrix, &rawGeomToPhys);

                            IXpsOMVisualCollection* pageVisuals;
                            result = page->GetVisuals(&pageVisuals);

                            result = pageVisuals->Append(scaleCanvas);

                            scaleCanvas->SetTransformLocal(rawGeomToPhys);

                            IXpsOMVisual* visual = NULL;
                            XPS_OBJECT_TYPE  visualType;

                            UINT32 count;
                            UINT32 thisVisual;

                            pageVisuals->GetCount(&count);
                            thisVisual = 0;
                            while (thisVisual < count) 
                            {
                                result = pageVisuals->GetAt(thisVisual, &visual);

                                result = visual->GetType(&visualType);

                                if (visualType == XPS_OBJECT_TYPE_CANVAS)
                                {
                                    result = visual->SetTransformLocal(rawGeomToPhys);
                                }

                                if (NULL != visual) { visual->Release(); visual = NULL; }
                                thisVisual++;
                            }

If I remove the following line;

scaleCanvas->SetTransformLocal(rawGeomToPhys);

the scale and translate on the matrix takes effect; however, the pages are produced upside down and content is mirrored.

If I keep the aforementioned line of code, the scale and translate on the matrix has no effect; however, the pages produced come out scaled to the page size and in proper format (upside and not mirrored) (must be using a default value for the scaling and translation)

How can I keep;

scaleCanvas->SetTransformLocal(rawGeomToPhys);

in my code but still apply the matrix scale and translate which is something like;

combinedMatrix.scale(0.5, 0.5);
combinedMatrix.translate(y, x);
Windows development | Windows API - Win32
Developer technologies | C++
Developer technologies | C++

A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.


1 answer

Sort by: Most helpful
  1. Xiaopo Yang - MSFT 12,736 Reputation points Microsoft External Staff
    2021-08-11T05:50:30.783+00:00

    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(&currentVisuals),
             "Could not get current visuals for layer.");
        HRVM(currentVisuals->Append(that->fCurrentXpsCanvas.get()),
             "Could not add layer to current visuals.");
    }
    

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.