예제 #1
0
        public GradientPaintContext(ColorModel cm, Point2D p1, Point2D p2, AffineTransform xform, Color c1, Color c2, bool cyclic)
        {
            // First calculate the distance moved in user space when
            // we move a single unit along the X & Y axes in device space.
            Point2D xvec = new Point2D.Double(1, 0);
            Point2D yvec = new Point2D.Double(0, 1);

            try
            {
                AffineTransform inverse = xform.CreateInverse();
                inverse.DeltaTransform(xvec, xvec);
                inverse.DeltaTransform(yvec, yvec);
            }
            catch (NoninvertibleTransformException)
            {
                xvec.SetLocation(0, 0);
                yvec.SetLocation(0, 0);
            }

            // Now calculate the (square of the) user space distance
            // between the anchor points. This value equals:
            //     (UserVec . UserVec)
            double udx    = p2.X - p1.X;
            double udy    = p2.Y - p1.Y;
            double ulenSq = udx * udx + udy * udy;

            if (ulenSq <= Double.Epsilon)
            {
                Dx = 0;
                Dy = 0;
            }
            else
            {
                // Now calculate the proportional distance moved along the
                // vector from p1 to p2 when we move a unit along X & Y in
                // device space.
                //
                // The length of the projection of the Device Axis Vector is
                // its dot product with the Unit User Vector:
                //     (DevAxisVec . (UserVec / Len(UserVec))
                //
                // The "proportional" length is that length divided again
                // by the length of the User Vector:
                //     (DevAxisVec . (UserVec / Len(UserVec))) / Len(UserVec)
                // which simplifies to:
                //     ((DevAxisVec . UserVec) / Len(UserVec)) / Len(UserVec)
                // which simplifies to:
                //     (DevAxisVec . UserVec) / LenSquared(UserVec)
                Dx = (xvec.X * udx + xvec.Y * udy) / ulenSq;
                Dy = (yvec.X * udx + yvec.Y * udy) / ulenSq;

                if (cyclic)
                {
                    Dx = Dx % 1.0;
                    Dy = Dy % 1.0;
                }
                else
                {
                    // We are acyclic
                    if (Dx < 0)
                    {
                        // If we are using the acyclic form below, we need
                        // dx to be non-negative for simplicity of scanning
                        // across the scan lines for the transition points.
                        // To ensure that constraint, we negate the dx/dy
                        // values and swap the points and colors.
                        Point2D p = p1;
                        p1 = p2;
                        p2 = p;
                        Color c = c1;
                        c1 = c2;
                        c2 = c;
                        Dx = -Dx;
                        Dy = -Dy;
                    }
                }
            }

            Point2D dp1 = xform.Transform(p1, null);

            this.X1 = dp1.X;
            this.Y1 = dp1.Y;

            this.Cyclic = cyclic;
            int rgb1 = c1.RGB;
            int rgb2 = c2.RGB;
            int a1   = (rgb1 >> 24) & 0xff;
            int r1   = (rgb1 >> 16) & 0xff;
            int g1   = (rgb1 >> 8) & 0xff;
            int b1   = (rgb1) & 0xff;
            int da   = ((rgb2 >> 24) & 0xff) - a1;
            int dr   = ((rgb2 >> 16) & 0xff) - r1;
            int dg   = ((rgb2 >> 8) & 0xff) - g1;
            int db   = ((rgb2) & 0xff) - b1;

            if (a1 == 0xff && da == 0)
            {
                Model = Xrgbmodel;
                if (cm is DirectColorModel)
                {
                    DirectColorModel dcm = (DirectColorModel)cm;
                    int tmp = dcm.AlphaMask;
                    if ((tmp == 0 || tmp == 0xff) && dcm.RedMask == 0xff && dcm.GreenMask == 0xff00 && dcm.BlueMask == 0xff0000)
                    {
                        Model = Xbgrmodel;
                        tmp   = r1;
                        r1    = b1;
                        b1    = tmp;
                        tmp   = dr;
                        dr    = db;
                        db    = tmp;
                    }
                }
            }
            else
            {
                Model = ColorModel.RGBdefault;
            }
            Interp = new int[cyclic ? 513 : 257];
            for (int i = 0; i <= 256; i++)
            {
                float rel = i / 256.0f;
                int   rgb = (((int)(a1 + da * rel)) << 24) | (((int)(r1 + dr * rel)) << 16) | (((int)(g1 + dg * rel)) << 8) | (((int)(b1 + db * rel)));
                Interp[i] = rgb;
                if (cyclic)
                {
                    Interp[512 - i] = rgb;
                }
            }
        }