/// <summary> /// Translates and scales all rings and invisible polygons as specified. /// </summary> /// <param name="from"></param> /// <param name="to"></param> public void Shift(RectangleF from, RectangleF to) { PointF fromOrigin = new PointF(from.X + (from.Width / 2), from.Y + (from.Height / 2)); PointF toOrigin = new PointF(to.X + (to.Width / 2), to.Y + (to.Height / 2)); PointF offset = new PointF(toOrigin.X - fromOrigin.X, toOrigin.Y - fromOrigin.Y); double xd = to.Width / from.Width; double yd = to.Height / from.Height; //Offset points foreach (PointSet ps in ringList) { if (ps.flags != PointFlags.Ignored) { ps.points = PolygonMath.MovePoly(ps.points, offset); } } //Scale points foreach (PointSet ps in ringList) { if (ps.flags != PointFlags.Ignored) { ps.points = PolygonMath.ScalePoints(ps.points, xd, yd, toOrigin); } } }
/// <summary> /// Normalizes all rings and invisible polygons so that the outermost ring's bounding box starts at the specified orign. /// </summary> /// <param name="origin"></param> /// <returns></returns> public void Normalize(PointF origin) { PointF offset = GetBoundingBox().Location; offset.X *= -1; offset.Y *= -1; foreach (PointSet ps in ringList) { if (ps.flags != PointFlags.Ignored) { ps.points = PolygonMath.MovePoly(ps.points, offset); } } }
protected override RequestedAction LayoutEffects(ImageState s) { float shadowWidth = s.settings.Get <float>("shadowWidth", 0); if (shadowWidth != 0) { var offset = s.settings.GetList <float>("shadowOffset", 0, 2); PointF shadowOffset = offset == null ? new PointF(0, 0) : new PointF(offset[0], offset[1]); //Clone last ring, then offset it - provides the inner bounds of the shadow later s.layout.AddInvisiblePolygon("shadowInner", PolygonMath.MovePoly(s.layout.LastRing.points, shadowOffset)); //Determine the outer bound of the shadow s.layout.AddRing("shadow", PolygonMath.InflatePoly(s.layout.LastRing.points, new float[] { Math.Max(0, shadowWidth - shadowOffset.Y), Math.Max(0, shadowWidth + shadowOffset.X), Math.Max(0, shadowWidth + shadowOffset.Y), Math.Max(0, shadowWidth - shadowOffset.X) })); } return(RequestedAction.None); }
public LayoutInformation(ImageState state) { this.instructions = new NameValueCollection(state.settings); this.sourceRect = new SizeOnly(state.originalSize); this.finalRect = new SizeOnly(state.destSize); this.imageSourcePoly = new PolyRect(state.copyRect); if (state.layout.ContainsRing("image")) { this.imageDestPoly = new PolyRect(state.layout["image"]); } if (state.layout.ContainsRing("imageArea")) { this.imageDestAreaPoly = new PolyRect(state.layout["imageArea"]); } // Check to see if sFlip/sRotate has altered the original raw image // rectangle. The check must be the same as in // ImageBuilder.PrepareSourceBitmap(). Note that the adjustment // happens only when there's an actual bitmap, regardless of the // sFlip/sRotate settings. if (state.sourceBitmap != null && (state.settings.SourceFlip != RotateFlipType.RotateNoneFlipNone || !string.IsNullOrEmpty(state.settings["sRotate"]))) { // We need to calculate the original rect/poly by *reversing* the // requested sFlip/sRotate. We determine what the requested change // was, then calculate the reverse. var angle = state.settings.Get <double>("sRotate", 0); var flipRotate = (int)PolygonMath.CombineFlipAndRotate(state.settings.SourceFlip, angle); var copyPoly = PolygonMath.ToPoly(state.copyRect); var trueOriginalSize = state.originalSize; // The RotateFlipType values are ordered such that odd values // transpose the size of the rectangle, %4 gives the rotation // and /4 (=> 0 or 1) whether there's been an x-flip. We can // use this to streamline our calculations. if (flipRotate % 2 == 1) { trueOriginalSize = new Size(state.originalSize.Height, state.originalSize.Width); } this.preAdjustedSourceRect = new SizeOnly(trueOriginalSize); // Remember that the sFlip/sRotate change performed the rotation // first and then the flip, so we have to do the opposite to go // backwards. if (flipRotate / 4 == 1) { copyPoly = PolygonMath.ScalePoints(copyPoly, -1, 1, PointF.Empty); copyPoly = PolygonMath.MovePoly(copyPoly, new PointF(trueOriginalSize.Width, 0)); } // It's possible to calculate a rotation-origin that will place // the original pre-sRotate (0,0) point back at (0,0) again... // but since it involves sqrt(), there would be rounding errors // that we should be able to avoid. (We might, in fact, want to // avoid using PolygonMath entirely, and hand-map the points // backwards for accuracy.) switch (flipRotate % 4) { case 0: // no rotation // no-op! break; case 1: // 90 degrees, clockwise copyPoly = PolygonMath.RotatePoly(copyPoly, -90); copyPoly = PolygonMath.MovePoly(copyPoly, new PointF(0, trueOriginalSize.Height)); break; case 2: // 180 degrees, clockwise copyPoly = PolygonMath.RotatePoly(copyPoly, -180); copyPoly = PolygonMath.MovePoly(copyPoly, new PointF(trueOriginalSize.Width, trueOriginalSize.Height)); break; case 3: // 270 degrees, clockwise copyPoly = PolygonMath.RotatePoly(copyPoly, -270); copyPoly = PolygonMath.MovePoly(copyPoly, new PointF(trueOriginalSize.Width, 0)); break; } this.preAdjustedImageSourcePoly = new PolyRect(copyPoly); } }