4

I am trying to add a watermark in a XOD file (XOD is very similar to XPS files as far as I know). Inside XODs, there are XAML files with content like that:

<?xml version="1.0" encoding="UTF-8"?>
<FixedPage xmlns="http://schemas.microsoft.com/xps/2005/06" xmlns:x="http://schemas.microsoft.com/xps/2005/06/resourcedictionary-key" xml:lang="EN" Width="725.66667" Height="990.236">
<Canvas RenderTransform="1.3333333,0,0,-1.3333333,0,990.236">
....
</Canvas>
</FixedPage>

I want to insert my watermark inside the Canvas, but I want to place it in the same page position for each document. The thing is that the RenderTransform is changing from document to document, so I should probably calculate the inverse transform to do this (I have also thought of wrapping the old Canvas element into a new Canvas without RenderTransform but I don't really like this).

I have found some related documentation and questions for these:

http://msdn.microsoft.com/en-us/library/ms750596(v=vs.110).aspx

Default RenderTransform Converter syntax

 <Canvas RenderTransform="m11, m12, m21, m22, offsetX, offsetY">

 m11   m12    0           a  b  0
 m21   m22    0     or    c  d  0
 offx  offy   1           tx ty 1

...and I have calculated what I thought was the inverse matrix:

        float det = a * d - b * c;
        float ia, ib, ic, id, itx, ity;
        ia = d / det;
        ib = -b / det;
        ic = -c / det;
        id = a / det;
        itx = (c * ty - d * tx) / det;
        ity = -(a * ty - b * tx) / det;

...and multiplied it with my desired transform, p ([f] = [i] * [p]):

        float pa = 60, pb = -60, pc = 60, pd = 60, ptx = 20, pty = 20;
        float fa, fb, fc, fd, ftx, fty;
        fa = ia * pa + ib * pc;
        fb = ia * pb + ib * pd;
        fc = ic * pa + id * pc;
        fd = ic * pb + id * pd;
        ftx = itx * pa + ity * pc + ptx;
        fty = itx * pb + ity * pd + pty;

Then my element inside the Canvas would be:

<Glyphs RenderTransform="fa, fb, fc, fd, ftx, fty" .... />

But this doesn't seem to work for the Offset coefficients. They seem to get too big values and go outside the page. The M** coefficients seem to come out correct though. Am I missing something here? Are the translation coefficients supposed to be calculated in another way?

Using :

        ftx = ptx - tx;
        fty = pty + pageHeight - ty;

..seemed to provide similar results for most of the RenderTransforms, but not all.

EDIT: I try to avoid using any of the WPF assemblies because I don't need any other functionality from there.

Community
  • 1
  • 1
NoOne
  • 3,851
  • 1
  • 40
  • 47
  • Are your documents a different size each time? Do you need to scale the watermark as well as applying the translation? – Chris May 05 '14 at 10:48
  • @Chris Yes, the page size varies. As far as I see, my watermark scales quite fine on different documents without me playing much with the `RenderTransform` property. This is probably because I specify the `FontRenderingEmSize` property on the `Glyphs` element. I have tried lowering the `pa,pb,pc,pd` values and raising `FontRenderingEmSize` but again the result doesn't seem so reasonable/predictable (I still can't manage to bring it inside the page... I have to do some brute forcing on the 'ptx,pty' values for that...). – NoOne May 05 '14 at 18:33
  • I just wonder where is the math error. I have also tried multiplying the matrices the other way around ([f] = [p]*[i]) and this doesn't seem to be correct either. Anyway... perhaps will I add the whole page content in a new Canvas that has no transform specified. This will definitely solve the problem. – NoOne May 05 '14 at 18:33
  • Ah, I was just wondering if you could get away without the scaling, I might have a crack at the Math if I get a chance. – Chris May 05 '14 at 18:43
  • 1
    Turns out that the way I used to parse the values here was affected in a bad way by the local culture... Once I used invariant culture, things made sense. – NoOne Sep 07 '19 at 17:43

1 Answers1

3

if i understand you correctly and you just want to compute the inverse of a RenderTransform then why don't you use the Invert() function of the RenderTransforms underlying matrix?

Transform t = elem.RenderTransform;
if(t.Value.HasInverse) {
    t.Value = t.Value.Invert();
    elem.RenderTransform = t;
}

Where elem is your UIElement.

MrToast
  • 1,159
  • 13
  • 41