public void Update(RotateZoomEffectConfigToken token)
            {
                Transform(token, 0, 0, out startX, out startY, out startZ);
                Transform(token, 1, 0, out dsxdx, out dsydx, out dszdx);
                Transform(token, 0, 1, out dsxdy, out dsydy, out dszdy);

                dsxdx -= startX; dsydx -= startY; dszdx -= startZ;
                dsxdy -= startX; dsydy -= startY; dszdy -= startZ;
            }
         public void Update(RotateZoomEffectConfigToken token)
         {
             Transform(token, 0, 0, out startX, out startY, out startZ);
             Transform(token, 1, 0, out dsxdx, out dsydx, out dszdx);
             Transform(token, 0, 1, out dsxdy, out dsydy, out dszdy);
 
             dsxdx -= startX; dsydx -= startY; dszdx -= startZ;
             dsxdy -= startX; dsydy -= startY; dszdy -= startZ;
         }
 protected RotateZoomEffectConfigToken(RotateZoomEffectConfigToken copyMe)
 {
     this.highQuality = copyMe.highQuality;
     this.preRotateZ = copyMe.preRotateZ;
     this.postRotateZ = copyMe.postRotateZ;
     this.tilt = copyMe.tilt;
     this.zoom = copyMe.zoom;
     this.offset = copyMe.offset;
     this.sourceAsBackground = copyMe.sourceAsBackground;
     this.tile = copyMe.tile;
     UpdateRzInfo();
 }
 protected RotateZoomEffectConfigToken(RotateZoomEffectConfigToken copyMe)
 {
     this.highQuality        = copyMe.highQuality;
     this.preRotateZ         = copyMe.preRotateZ;
     this.postRotateZ        = copyMe.postRotateZ;
     this.tilt               = copyMe.tilt;
     this.zoom               = copyMe.zoom;
     this.offset             = copyMe.offset;
     this.sourceAsBackground = copyMe.sourceAsBackground;
     this.tile               = copyMe.tile;
     UpdateRzInfo();
 }
        protected override void InitDialogFromToken(EffectConfigToken effectToken)
        {
            RotateZoomEffectConfigToken token = (RotateZoomEffectConfigToken)effectToken;
            double r = Math.Sin(token.Tilt) * 90;
            double t = -token.PreRotateZ;

            panControl.Position            = token.Offset;
            rollControl.Angle              = (token.PostRotateZ - t) * 180 / Math.PI;
            rollControl.RollDirection      = 180 * t / Math.PI;
            rollControl.RollAmount         = r;
            keepBackgroundCheckBox.Checked = token.SourceAsBackground;
            tileSourceCheckBox.Checked     = token.Tile;
            trackBarZoom.Value             = (int)Math.Round(512 + 128 * Math.Log(token.Zoom, 2.0));

            TrackBarZoom_ValueChanged(this, EventArgs.Empty);
        }
        protected override void InitTokenFromDialog()
        {
            RotateZoomEffectConfigToken token = (RotateZoomEffectConfigToken)theEffectToken;
            double angle = rollControl.RollDirection * Math.PI / 180;
            double dist  = rollControl.RollAmount;

            if (double.IsNaN(angle))
            {
                angle = 0;
                dist  = 0;
            }

            token.Offset             = panControl.Position;
            token.PreRotateZ         = (float)(angle);
            token.PostRotateZ        = (float)(-angle - rollControl.Angle * Math.PI / 180);
            token.Tilt               = (float)Math.Asin(dist / 90);
            token.SourceAsBackground = keepBackgroundCheckBox.Checked;
            token.Tile               = tileSourceCheckBox.Checked;
            token.Zoom               = (float)Math.Pow(2.0, (trackBarZoom.Value - 512) / 128.0);
        }
            private void Transform(RotateZoomEffectConfigToken token, int x, int y, out float sx, out float sy, out float sz)
            {
                float rb = token.preRotateZ;
                float ra = token.postRotateZ;
                float r = -token.tilt;
                float crb = (float)Math.Cos(rb);
                float cr = (float)Math.Cos(r);
                float cra = (float)Math.Cos(ra);
                float srb = (float)Math.Sin(rb);
                float sr = (float)Math.Sin(r);
                float sra = (float)Math.Sin(ra);
                float ox = x, oy = y, oz = 0;
            
                sx = (ox * crb + oy * srb) / cr;
                sy = -ox * srb + oy * crb;

                sz = sx * sr;
                sx = sx / cr;
                ox = sx; oy = sy; oz = sz;
            
                sx =  ox * cra + oy * sra;
                sy = -ox * sra + oy * cra;
            }
            private void Transform(RotateZoomEffectConfigToken token, int x, int y, out float sx, out float sy, out float sz)
            {
                float rb = token.preRotateZ;
                float ra = token.postRotateZ;
                float r = -token.tilt;
                float crb = (float)Math.Cos(rb);
                float cr = (float)Math.Cos(r);
                float cra = (float)Math.Cos(ra);
                float srb = (float)Math.Sin(rb);
                float sr = (float)Math.Sin(r);
                float sra = (float)Math.Sin(ra);
                float ox = x, oy = y, oz = 0;

                sx = (ox * crb + oy * srb) / cr;
                sy = -ox * srb + oy * crb;

                sz = sx * sr;
                sx = sx / cr;
                ox = sx; oy = sy; oz = sz;

                sx = ox * cra + oy * sra;
                sy = -ox * sra + oy * cra;
            }
 protected override void InitialInitToken()
 {
     theEffectToken = new RotateZoomEffectConfigToken(true, 0, 0, 0, 1.0f, PointF.Empty, false, false);
 }
        public unsafe override void Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, int startIndex, int length)
        {
            RotateZoomEffectConfigToken token = (RotateZoomEffectConfigToken)parameters;

            RotateZoomEffectConfigToken.RzInfo rzInfo = token.ComputedOnce;
            Rectangle bounds = this.EnvironmentParameters.GetSelection(dstArgs.Bounds).GetBoundsInt();

            bounds.Intersect(dstArgs.Bounds);
            Surface   src       = srcArgs.Surface;
            Surface   dst       = dstArgs.Surface;
            PdnRegion selection = this.EnvironmentParameters.GetSelection(src.Bounds);
            Rectangle srcBounds = src.Bounds;
            int       srcMaxX   = srcBounds.Width - 1;
            int       srcMaxY   = srcBounds.Height - 1;

            float dsxdx   = rzInfo.dsxdx;
            float dsydx   = rzInfo.dsydx;
            float dszdx   = rzInfo.dszdx;
            float dsxdy   = rzInfo.dsxdy;
            float dsydy   = rzInfo.dsydy;
            float dszdy   = rzInfo.dszdy;
            float zoom    = token.Zoom;
            uint  srcMask = token.SourceAsBackground ? 0xffffffff : 0;

            bool  tile    = token.Tile;
            float divZ    = 0.5f * (float)Math.Sqrt(dst.Width * dst.Width + dst.Height * dst.Height);
            float centerX = (float)dst.Width / 2.0f;
            float centerY = (float)dst.Height / 2.0f;
            float tx      = (token.Offset.X) * dst.Width / 2.0f;
            float ty      = (token.Offset.Y) * dst.Height / 2.0f;

            uint tilingMask = tile ? 0xffffffff : 0;

            for (int i = startIndex; i < startIndex + length; ++i)
            {
                Rectangle rect = rois[i];

                float cx = rzInfo.startX;
                float cy = rzInfo.startY;
                float cz = rzInfo.startZ;

                float mcl = ((rect.Left - tx) - dst.Width / 2.0f);
                cx += dsxdx * mcl;
                cy += dsydx * mcl;
                cz += dszdx * mcl;

                float mct = ((rect.Top - ty) - dst.Height / 2.0f);
                cx += dsxdy * mct;
                cy += dsydy * mct;
                cz += dszdy * mct;

                for (int y = rect.Top; y < rect.Bottom; ++y)
                {
                    ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y);
                    ColorBgra *srcPtr = src.GetPointAddressUnchecked(rect.Left, y);

                    float rx = cx;
                    float ry = cy;
                    float rz = cz;

                    for (int x = rect.Left; x < rect.Right; ++x)
                    {
                        if (rz > -divZ)
                        {
                            float div = divZ / (zoom * (divZ + rz));
                            float u   = (rx * div) + centerX;
                            float v   = (ry * div) + centerY;

                            if (tile || (u >= -1 && v >= -1 && u <= srcBounds.Width && v <= srcBounds.Height))
                            {
                                unchecked
                                {
                                    int  iu        = (int)Math.Floor(u);
                                    uint sxfrac    = (uint)(256 * (u - (float)iu));
                                    uint sxfracinv = 256 - sxfrac;

                                    int  iv        = (int)Math.Floor(v);
                                    uint syfrac    = (uint)(256 * (v - (float)iv));
                                    uint syfracinv = 256 - syfrac;

                                    uint wul = (uint)(sxfracinv * syfracinv);
                                    uint wur = (uint)(sxfrac * syfracinv);
                                    uint wll = (uint)(sxfracinv * syfrac);
                                    uint wlr = (uint)(sxfrac * syfrac);

                                    uint inBoundsMaskLeft   = tilingMask;
                                    uint inBoundsMaskTop    = tilingMask;
                                    uint inBoundsMaskRight  = tilingMask;
                                    uint inBoundsMaskBottom = tilingMask;

                                    int sx = iu;
                                    if (sx < 0)
                                    {
                                        sx = srcMaxX + ((sx + 1) % srcBounds.Width);
                                    }
                                    else if (sx > srcMaxX)
                                    {
                                        sx = sx % srcBounds.Width;
                                    }
                                    else
                                    {
                                        inBoundsMaskLeft = 0xffffffff;
                                    }

                                    int sy = iv;
                                    if (sy < 0)
                                    {
                                        sy = srcMaxY + ((sy + 1) % srcBounds.Height);
                                    }
                                    else if (sy > srcMaxY)
                                    {
                                        sy = sy % srcBounds.Height;
                                    }
                                    else
                                    {
                                        inBoundsMaskTop = 0xffffffff;
                                    }

                                    int sleft = sx;
                                    int sright;

                                    if (sleft == srcMaxX)
                                    {
                                        sright            = 0;
                                        inBoundsMaskRight = (iu == -1) ? 0xffffffff : tilingMask;
                                    }
                                    else
                                    {
                                        sright            = sleft + 1;
                                        inBoundsMaskRight = inBoundsMaskLeft & 0xffffffff;
                                    }

                                    int stop = sy;
                                    int sbottom;

                                    if (stop == srcMaxY)
                                    {
                                        sbottom            = 0;
                                        inBoundsMaskBottom = (iv == -1) ? 0xffffffff : tilingMask;
                                    }
                                    else
                                    {
                                        sbottom            = stop + 1;
                                        inBoundsMaskBottom = inBoundsMaskTop & 0xffffffff;
                                    }

                                    uint      maskUL = inBoundsMaskLeft & inBoundsMaskTop;
                                    ColorBgra cul    = ColorBgra.FromUInt32(src.GetPointUnchecked(sleft, stop).Bgra & maskUL);

                                    uint      maskUR = inBoundsMaskRight & inBoundsMaskTop;
                                    ColorBgra cur    = ColorBgra.FromUInt32(src.GetPointUnchecked(sright, stop).Bgra & maskUR);

                                    uint      maskLL = inBoundsMaskLeft & inBoundsMaskBottom;
                                    ColorBgra cll    = ColorBgra.FromUInt32(src.GetPointUnchecked(sleft, sbottom).Bgra & maskLL);

                                    uint      maskLR = inBoundsMaskRight & inBoundsMaskBottom;
                                    ColorBgra clr    = ColorBgra.FromUInt32(src.GetPointUnchecked(sright, sbottom).Bgra & maskLR);

                                    ColorBgra c = ColorBgra.BlendColors4W16IP(cul, wul, cur, wur, cll, wll, clr, wlr);

                                    if (c.A == 255 || !token.SourceAsBackground)
                                    {
                                        dstPtr->Bgra = c.Bgra;
                                    }
                                    else
                                    {
                                        *dstPtr = PaintDotNet.UserBlendOps.NormalBlendOp.ApplyStatic(*srcPtr, c);
                                    }
                                }
                            }
                            else
                            {
                                if (srcMask != 0)
                                {
                                    dstPtr->Bgra = srcPtr->Bgra;
                                }
                                else
                                {
                                    dstPtr->Bgra = 0;
                                }
                            }
                        }
                        else
                        {
                            if (srcMask != 0)
                            {
                                dstPtr->Bgra = srcPtr->Bgra;
                            }
                            else
                            {
                                dstPtr->Bgra = 0;
                            }
                        }

                        rx += dsxdx;
                        ry += dsydx;
                        rz += dszdx;

                        ++dstPtr;
                        ++srcPtr;
                    }

                    cx += dsxdy;
                    cy += dsydy;
                    cz += dszdy;
                }
            }
        }
 protected override void InitialInitToken()
 {
     theEffectToken = new RotateZoomEffectConfigToken(true, 0, 0, 0, 1.0f, PointF.Empty, false, false);
 }