Color GetColorAt(int x, int y) { double new_x = x; double new_y = y; _transformBackToHorizontal.Transform(ref new_x, ref new_y); if (new_x <= _beginX) { return(_beginColor); } else if (new_x >= _endX) { return(_endColor); } //----------------- //find proper range for (int i = 0; i < _pairList.Length; ++i) { LinearGradientPair p = _pairList[i]; if (new_x >= p._dx1 && new_x < p._dx2) { return(p.GetColor((float)new_x)); } } return(_endColor); }
static void TransformToVxs(ICoordTransformer tx, VertexStore src, VertexStore outputVxs) { int count = src.Count; VertexCmd cmd; double x, y; for (int i = 0; i < count; ++i) { cmd = src.GetVertex(i, out x, out y); tx.Transform(ref x, ref y); outputVxs.AddVertex(x, y, cmd); } }
public void Render(IBitmapSrc source, double destX, double destY) { int inScaleX = 1; int inScaleY = 1; int angleRadians = 0; // exit early if the dest and source bounds don't touch. // TODO: <BUG> make this do rotation and scalling RectInt sourceBounds = new RectInt((int)destX, (int)destY, (int)destX + source.Width, (int)destY + source.Height); //sourceBounds.Offset((int)destX, (int)destY); RectInt destBounds = _destBitmapBlender.GetBounds(); if (!RectInt.DoIntersect(sourceBounds, destBounds)) { //if (inScaleX != 1 || inScaleY != 1 || angleRadians != 0) //{ // throw new NotImplementedException(); //} return; } double scaleX = inScaleX; double scaleY = inScaleY; ICoordTransformer graphicsTransform = this.CurrentTransformMatrix; if (!graphicsTransform.IsIdentity) { if (scaleX != 1 || scaleY != 1 || angleRadians != 0) { throw new NotImplementedException(); } graphicsTransform.Transform(ref destX, ref destY); } #if false // this is an optomization that eliminates the drawing of images that have their alpha set to all 0 (happens with generated images like explosions). MaxAlphaFrameProperty maxAlphaFrameProperty = MaxAlphaFrameProperty::GetMaxAlphaFrameProperty(source); if ((maxAlphaFrameProperty.GetMaxAlpha() * color.A_Byte) / 256 <= ALPHA_CHANNEL_BITS_DIVISOR) { m_OutFinalBlitBounds.SetRect(0, 0, 0, 0); } #endif bool isScale = (scaleX != 1 || scaleY != 1); bool isRotated = false; if (angleRadians != 0 && Math.Abs(angleRadians) >= (0.1 * MathHelper.Tau / 360)) { isRotated = true; } else { angleRadians = 0;//reset very small angle to 0 } //bool IsMipped = false; //double ox, oy; //source.GetOriginOffset(out ox, out oy); bool canUseMipMaps = isScale; if (scaleX > 0.5 || scaleY > 0.5) { canUseMipMaps = false; } bool needSourceResampling = isScale || isRotated;// || destX != (int)destX || destY != (int)destY; //VectorToolBox.GetFreeVxs(out VertexStore imgBoundsPath); // this is the fast drawing path if (needSourceResampling) { #if false // if the scalling is small enough the results can be improved by using mip maps if (CanUseMipMaps) { CMipMapFrameProperty *pMipMapFrameProperty = CMipMapFrameProperty::GetMipMapFrameProperty(source); double OldScaleX = scaleX; double OldScaleY = scaleY; const CFrameInterface *pMippedFrame = pMipMapFrameProperty.GetMipMapFrame(ref scaleX, ref scaleY); if (pMippedFrame != source) { IsMipped = true; source = pMippedFrame; sourceOriginOffsetX *= (OldScaleX / scaleX); sourceOriginOffsetY *= (OldScaleY / scaleY); } HotspotOffsetX *= (inScaleX / scaleX); HotspotOffsetY *= (inScaleY / scaleY); } #endif using (VxsTemp.Borrow(out var imgBoundsPath, out var v1)) { BuildOrgImgRectVxs(source.Width, source.Height, imgBoundsPath); Affine destRectTransform = CreateAffine(destX, destY, _ox, _oy, scaleX, scaleY, angleRadians); //TODO: review reusable span generator an interpolator *** // We invert it because it is the transform to make the image go to the same position as the polygon. LBB [2/24/2004] //spanInterpolator.Transformer = destRectTransform.CreateInvert(); //var imgSpanGen = new ImgSpanGenRGBA_BilinearClip( // Drawing.Color.Black, // spanInterpolator); _spanInterpolator.Transformer = destRectTransform.CreateInvert(); _currentImgSpanGen.SetInterpolator(_spanInterpolator); _currentImgSpanGen.SetSrcBitmap(source); destRectTransform.TransformToVxs(imgBoundsPath, v1); Render(v1, _currentImgSpanGen); _currentImgSpanGen.ReleaseSrcBitmap(); } ////Affine destRectTransform = BuildImageBoundsPath(source.Width, source.Height, //// destX, destY, ox, oy, scaleX, scaleY, angleRadians, imgBoundsPath); //Affine destRectTransform = CreateAffine(destX, destY, ox, oy, scaleX, scaleY, angleRadians); ////TODO: review reusable span generator an interpolator *** //var spanInterpolator = new SpanInterpolatorLinear(); //// We invert it because it is the transform to make the image go to the same position as the polygon. LBB [2/24/2004] //spanInterpolator.Transformer = destRectTransform.CreateInvert(); //var imgSpanGen = new ImgSpanGenRGBA_BilinearClip( // source, // Drawing.Color.Black, // spanInterpolator); //VectorToolBox.GetFreeVxs(out VertexStore v1); //destRectTransform.TransformToVxs(imgBoundsPath, v1); //Render(v1, imgSpanGen); //VectorToolBox.ReleaseVxs(ref v1); #if false // this is some debug you can enable to visualize the dest bounding box LineFloat(BoundingRect.left, BoundingRect.top, BoundingRect.right, BoundingRect.top, WHITE); LineFloat(BoundingRect.right, BoundingRect.top, BoundingRect.right, BoundingRect.bottom, WHITE); LineFloat(BoundingRect.right, BoundingRect.bottom, BoundingRect.left, BoundingRect.bottom, WHITE); LineFloat(BoundingRect.left, BoundingRect.bottom, BoundingRect.left, BoundingRect.top, WHITE); #endif } else // TODO: this can be even faster if we do not use an intermediate buffer { //Affine destRectTransform = BuildImageBoundsPath( // source.Width, source.Height, // destX, destY, imgBoundsPath); using (VxsTemp.Borrow(out var imgBoundsPath, out var v1)) { BuildOrgImgRectVxs(source.Width, source.Height, imgBoundsPath); //... Affine destRectTransform = CreateAffine(destX, destY); //TODO: review reusable span generator an interpolator *** // We invert it because it is the transform to make the image go to the same position as the polygon. LBB [2/24/2004] _spanInterpolator.Transformer = destRectTransform.CreateInvert(); //we generate image by this imagespan generator ImgSpanGen imgSpanGen = null; switch (source.BitDepth) { case 32: if (_imgSpanGenCustom != null) { //use custom span gen _imgSpanGenCustom.SetInterpolator(_spanInterpolator); _imgSpanGenCustom.SetSrcBitmap(source); imgSpanGen = _imgSpanGenCustom; } else { _imgSpanGenNNStepXBy1.SetInterpolator(_spanInterpolator); _imgSpanGenNNStepXBy1.SetSrcBitmap(source); imgSpanGen = _imgSpanGenNNStepXBy1; } break; //case 8: // imgSpanGen = new ImgSpanGenGray_NNStepXby1(source, interpolator); // break; default: throw new NotImplementedException(); } destRectTransform.TransformToVxs(imgBoundsPath, v1); //... Render(v1, imgSpanGen); } // unchecked { _destImageChanged++; }; } }
public static void AddLineTo(this VertexStore vxs, double x, double y, ICoordTransformer tx) { tx.Transform(ref x, ref y); vxs.AddLineTo(x, y); }
public void ResolveBrush(LinearGradientBrush linearGrBrush) { PointF p1 = linearGrBrush.StartPoint; PointF p2 = linearGrBrush.EndPoint; //assume horizontal line _beginX = p1.X; _beginY = p1.Y; _endX = p2.X; _endY = p2.Y; //-------------- //find transformation matrix double angle = Math.Atan2(p2.Y - p1.Y, p2.X - p1.X); ICoordTransformer rotateTx = Affine.NewRotation(angle); if (linearGrBrush.CoordTransformer != null) { //*** IMPORTANT : matrix transform order !** rotateTx = linearGrBrush.CoordTransformer.MultiplyWith(rotateTx); } _transformBackToHorizontal = rotateTx.CreateInvert(); _totalLen = (float)Math.Sqrt((_endX - _beginX) * (_endX - _beginX) + (_endY - _beginY) * (_endY - _beginY)); double tmpX = _beginX; double tmpY = _beginY; _transformBackToHorizontal.Transform(ref tmpX, ref tmpY); _beginX = (float)tmpX; _beginY = (float)tmpY; //-------------- tmpX = _endX; tmpY = _endY; _transformBackToHorizontal.Transform(ref tmpX, ref tmpY); _endX = (float)tmpX; _endY = (float)tmpY; //-------------- ColorStop[] colorStops = linearGrBrush.ColorStops; int pairCount = colorStops.Length - 1; _pairList = new LinearGradientPair[pairCount]; ColorStop c0 = ColorStop.Empty; ColorStop c1 = ColorStop.Empty; for (int i = 0; i < pairCount; ++i) { c0 = colorStops[i]; c1 = colorStops[i + 1]; if (i == 0) { _beginColor = c0.Color; } var pairN = new LinearGradientPair( _beginX + c0.Offset * _totalLen, //to actual pixel _beginX + c1.Offset * _totalLen, //to actual pixel c0.Color, c1.Color); _pairList[i] = pairN; } this.SpreadMethod = linearGrBrush.SpreadMethod; _endColor = c1.Color; }
void ICoordTransformer.Transform(ref double x, ref double y) { _left.Transform(ref x, ref y); _right.Transform(ref x, ref y); }
public void Render(IBitmapSrc source, double destX, double destY, double angleRadians, double inScaleX, double inScaleY) { { // exit early if the dest and source bounds don't touch. // TODO: <BUG> make this do rotation and scalling Q1Rect sourceBounds = source.GetBounds(); Q1Rect destBounds = _destBitmapBlender.GetBounds(); sourceBounds.Offset((int)destX, (int)destY); if (!Q1Rect.DoIntersect(sourceBounds, destBounds)) { if (inScaleX != 1 || inScaleY != 1 || angleRadians != 0) { throw new NotImplementedException(); } return; } } double scaleX = inScaleX; double scaleY = inScaleY; ICoordTransformer graphicsTransform = this.CurrentTransformMatrix; if (!graphicsTransform.IsIdentity) { if (scaleX != 1 || scaleY != 1 || angleRadians != 0) { throw new NotImplementedException(); } graphicsTransform.Transform(ref destX, ref destY); } #if false // this is an optomization that eliminates the drawing of images that have their alpha set to all 0 (happens with generated images like explosions). MaxAlphaFrameProperty maxAlphaFrameProperty = MaxAlphaFrameProperty::GetMaxAlphaFrameProperty(source); if ((maxAlphaFrameProperty.GetMaxAlpha() * color.A_Byte) / 256 <= ALPHA_CHANNEL_BITS_DIVISOR) { m_OutFinalBlitBounds.SetRect(0, 0, 0, 0); } #endif bool isScale = (scaleX != 1 || scaleY != 1); bool isRotated = true; if (Math.Abs(angleRadians) < (0.1 * MathHelper.Tau / 360)) { isRotated = false; angleRadians = 0; } //bool IsMipped = false; //double ox, oy; //source.GetOriginOffset(out ox, out oy); bool canUseMipMaps = isScale; if (scaleX > 0.5 || scaleY > 0.5) { canUseMipMaps = false; } bool renderRequriesSourceSampling = isScale || isRotated || destX != (int)destX || destY != (int)destY; using (VxsTemp.Borrow(out var v1, out var imgBoundsPath)) { // this is the fast drawing path if (renderRequriesSourceSampling) { // if the scalling is small enough the results can be improved by using mip maps //if(CanUseMipMaps) //{ // CMipMapFrameProperty* pMipMapFrameProperty = CMipMapFrameProperty::GetMipMapFrameProperty(source); // double OldScaleX = scaleX; // double OldScaleY = scaleY; // const CFrameInterface* pMippedFrame = pMipMapFrameProperty.GetMipMapFrame(ref scaleX, ref scaleY); // if(pMippedFrame != source) // { // IsMipped = true; // source = pMippedFrame; // sourceOriginOffsetX *= (OldScaleX / scaleX); // sourceOriginOffsetY *= (OldScaleY / scaleY); // } // HotspotOffsetX *= (inScaleX / scaleX); // HotspotOffsetY *= (inScaleY / scaleY); //} //Affine destRectTransform = BuildImageBoundsPath(source.Width, source.Height, // destX, destY, ox, oy, scaleX, scaleY, angleRadians, imgBoundsPath); //1. BuildOrgImgRectVxs(source.Width, source.Height, imgBoundsPath); //2. AffineMat destRectTransform = AffineMat.Iden(); destRectTransform.Translate(-_ox, -_oy); destRectTransform.Scale(scaleX, scaleY); destRectTransform.Rotate(angleRadians); //TODO: review reusable span generator an interpolator *** // We invert it because it is the transform to make the image go to the same position as the polygon. LBB [2/24/2004] _reuseableAffine.SetElements(destRectTransform.CreateInvert()); _spanInterpolator.Transformer = _reuseableAffine; _currentImgSpanGen.BackgroundColor = Drawing.Color.Black; _currentImgSpanGen.SetInterpolator(_spanInterpolator); _currentImgSpanGen.SetSrcBitmap(source); destRectTransform.TransformToVxs(imgBoundsPath, v1); //not inverted version Render(v1, _currentImgSpanGen); _currentImgSpanGen.ReleaseSrcBitmap(); // this is some debug you can enable to visualize the dest bounding box //LineFloat(BoundingRect.left, BoundingRect.top, BoundingRect.right, BoundingRect.top, WHITE); //LineFloat(BoundingRect.right, BoundingRect.top, BoundingRect.right, BoundingRect.bottom, WHITE); //LineFloat(BoundingRect.right, BoundingRect.bottom, BoundingRect.left, BoundingRect.bottom, WHITE); //LineFloat(BoundingRect.left, BoundingRect.bottom, BoundingRect.left, BoundingRect.top, WHITE); } else // TODO: this can be even faster if we do not use an intermediat buffer { //Affine destRectTransform = BuildImageBoundsPath(source.Width, source.Height, destX, destY, imgBoundsPath); BuildOrgImgRectVxs(source.Width, source.Height, imgBoundsPath); // var destRectTransform = new AffineMat(); destRectTransform.Translate(destX, destY); //TODO: review reusable span generator an interpolator *** // We invert it because it is the transform to make the image go to the same position as the polygon. LBB [2/24/2004] _reuseableAffine.SetElements(destRectTransform.CreateInvert()); _spanInterpolator.Transformer = _reuseableAffine; ImgSpanGen imgSpanGen = null; switch (source.BitDepth) { case 32: if (_imgSpanGenCustom != null) { //use custom span gen _imgSpanGenCustom.SetInterpolator(_spanInterpolator); _imgSpanGenCustom.SetSrcBitmap(source); imgSpanGen = _imgSpanGenCustom; } else { _imgSpanGenNNStepXBy1.SetInterpolator(_spanInterpolator); _imgSpanGenNNStepXBy1.SetSrcBitmap(source); imgSpanGen = _imgSpanGenNNStepXBy1; } break; //case 24: // imgSpanGen = new ImgSpanGenRGB_NNStepXby1(source, interpolator); // break; //case 8: // imgSpanGen = new ImgSpanGenGray_NNStepXby1(source, interpolator); // break; default: throw new NotImplementedException(); } TransformToVxs(destRectTransform, imgBoundsPath, v1); Render(v1, imgSpanGen); unchecked { _destImageChanged++; }; } } }
public VertexStore MakeVxs(VertexStore vxs, ICoordTransformer tx, VertexStore output) { _curve3.Reset(); _curve4.Reset(); CurvePointMode latestCurveMode = CurvePointMode.NotCurve; double x, y; VertexCmd cmd; VectorMath.Vector2 c3p2 = new VectorMath.Vector2(); VectorMath.Vector2 c4p2 = new VectorMath.Vector2(); VectorMath.Vector2 c4p3 = new VectorMath.Vector2(); double lastX = 0; double lasty = 0; double lastMoveX = 0; double lastMoveY = 0; int index = 0; bool hasTx = tx != null; while ((cmd = vxs.GetVertex(index++, out x, out y)) != VertexCmd.NoMore) { #if DEBUG if (VertexStore.dbugCheckNANs(x, y)) { } #endif //----------------- if (hasTx) { tx.Transform(ref x, ref y); } //----------------- switch (cmd) { case VertexCmd.C3: { switch (latestCurveMode) { case CurvePointMode.P2: { } break; case CurvePointMode.P3: { } break; case CurvePointMode.NotCurve: { c3p2.x = x; c3p2.y = y; } break; default: { } break; } latestCurveMode = CurvePointMode.P2; } break; case VertexCmd.C4: { //this is p3c switch (latestCurveMode) { case CurvePointMode.P2: { c3p2.x = x; c3p2.y = y; } break; case CurvePointMode.P3: { c4p3.x = x; c4p3.y = y; } break; case CurvePointMode.NotCurve: { c4p2.x = x; c4p2.y = y; } break; } latestCurveMode = CurvePointMode.P3; } break; case VertexCmd.LineTo: { switch (latestCurveMode) { case CurvePointMode.P2: { _curve3.MakeLines(output, lastX, lasty, c3p2.X, c3p2.Y, x, y); } break; case CurvePointMode.P3: { _curve4.MakeLines(output, lastX, lasty, c4p2.x, c4p2.y, c4p3.x, c4p3.y, x, y); } break; default: { output.AddVertex(x, y, cmd); } break; } //----------- latestCurveMode = CurvePointMode.NotCurve; lastX = x; lasty = y; //----------- } break; case VertexCmd.MoveTo: { //move to, and end command output.AddVertex(x, y, cmd); //----------- latestCurveMode = CurvePointMode.NotCurve; lastMoveX = lastX = x; lastMoveY = lasty = y; //----------- } break; case VertexCmd.Close: case VertexCmd.CloseAndEndFigure: { latestCurveMode = CurvePointMode.NotCurve; output.AddVertex(lastMoveX, lastMoveY, cmd); //move to begin lastX = lastMoveX; lasty = lastMoveY; } break; default: { //move to, and end command output.AddVertex(x, y, cmd); //----------- latestCurveMode = CurvePointMode.NotCurve; lastX = x; lasty = y; //----------- } break; } } return(output); }
protected override void OnStart(AppHost host) { _appHost = host;//** //string svgfile = "../Test8_HtmlRenderer.Demo/Samples/Svg/others/cat_simple.svg"; //string svgfile = "../Test8_HtmlRenderer.Demo/Samples/Svg/others/cat_complex.svg"; //string svgfile = "../Test8_HtmlRenderer.Demo/Samples/Svg/others/lion.svg"; string svgfile = "../Test8_HtmlRenderer.Demo/Samples/Svg/others/tiger.svg"; //return VgVisualElemHelper.ReadSvgFile(svgfile); _rotationUI.AngleUpdated += _rotationUI_AngleUpdated; //string svgfile = "../Test8_HtmlRenderer.Demo/Samples/Svg/freepik/dog1.svg"; //string svgfile = "1f30b.svg"; //string svgfile = "../Data/Svg/twemoji/1f30b.svg"; //string svgfile = "../Data/1f30b.svg"; //string svgfile = "../Data/Svg/twemoji/1f370.svg"; //_svgRenderVx = CreateTestRenderVx_FromSvg(); //_svgRenderVx = CreateTestRenderVx_BasicShape(); //_vgVisualElem = CreateTestRenderVx_FromImg("d:\\WImageTest\\alpha1.png"); //string fontfile = "../Test8_HtmlRenderer.Demo/Samples/Fonts/SOV_Thanamas.ttf"; //_vgVisualElem = VgVisualElemHelper.CreateVgVisualElementFromGlyph(fontfile, 256, 'a'); //create from glyph _vgVisualElem = CreateTestRenderVx_FromImg("d:\\WImageTest\\fenec.png"); //_vgVisualElem = VgVisualElemHelper.ReadSvgFile(svgfile); //PixelFarm.CpuBlit.RectD org_rectD = _svgRenderVx.GetBounds(); //_svgRenderVx = CreateEllipseVxs(org_rectD); PixelFarm.CpuBlit.VertexProcessing.Q1RectD org_rectD = _vgVisualElem.GetRectBounds(); org_rectD.Offset(-org_rectD.Left, -org_rectD.Bottom); // _quadController.SetSrcRect(org_rectD.Left, org_rectD.Bottom, org_rectD.Right, org_rectD.Top); _quadController.SetDestQuad( org_rectD.Left, org_rectD.Top, org_rectD.Right, org_rectD.Top, org_rectD.Right, org_rectD.Bottom, org_rectD.Left, org_rectD.Bottom); //create control point _quadController.SetPolygonController(_quadPolygonController); _quadController.BuildControlBoxes(); _quadController.UpdateTransformTarget += (s1, e1) => { //after quadController is updated then //we use the coordTransformer to transform target uiSprite _uiSprite.SetTransformation(_quadController.GetCoordTransformer()); _uiSprite.InvalidateGraphics(); if (_quadController.Left != 0 || _quadController.Top != 0) { float xxdiff = _quadController.Left - _uiSprite.Left; float yydiff = _quadController.Top - _uiSprite.Top; _uiSprite.SetLocation(_quadController.Left, _quadController.Top); _uiSprite.InvalidateGraphics(); //_rotationUI.InvalidateGraphics(); //_rotationUI.SetLocation( // _rotationUI.Left + xxdiff, // _rotationUI.Top + yydiff); //_rotationUI.InvalidateGraphics(); //_rotationControllerPointUI.InvalidateGraphics(); //_rotationControllerPointUI.SetPosition( // (int)(_rotationControllerPointUI.Left + xxdiff), // (int)(_rotationControllerPointUI.Top + yydiff)); //_rotationControllerPointUI.InvalidateGraphics(); } }; //_rectBoundsWidgetBox = new Box2(50, 50); //visual rect box //Color c = KnownColors.FromKnownColor(KnownColor.DeepSkyBlue); //_rectBoundsWidgetBox.BackColor = Color.FromArgb(100, c); //_rectBoundsWidgetBox.SetLocation(10, 10); /////box1.dbugTag = 1; //SetupActiveBoxProperties(_rectBoundsWidgetBox); //host.AddChild(_rectBoundsWidgetBox); //_quadController.Visible = _quadPolygonController.Visible = false; //_rectBoxController.Init(); PixelFarm.CpuBlit.VertexProcessing.Q1RectD svg_bounds = _vgVisualElem.GetRectBounds(); //bounds of graphic shape //ICoordTransformer tx = ((ICoordTransformer)_bilinearTx).MultiplyWith(scaleMat); ICoordTransformer tx = _quadController.GetCoordTransformer(); //svgRenderVx._coordTx = tx; //svgRenderVx._coordTx = ((ICoordTransformer)_bilinearTx).MultiplyWith(scaleMat); //host.AddChild(_quadController); //host.AddChild(_quadPolygonController); //VgRenderVx svgRenderVx = CreateTestRenderVx(); //test transform svgRenderVx _vgVisualElem.DisableBackingImage = true; //----------------------------------------- _uiSprite = new UISprite(10, 10); //init size = (10,10), location=(0,0) _uiSprite.DisableBmpCache = true; _uiSprite.LoadVg(_vgVisualElem); // _uiSprite.SetTransformation(tx); //set transformation host.AddChild(_uiSprite); //----------------------------------------- //host.AddChild(_quadController); host.AddChild(_quadPolygonController); { PointControllerBox center = new PointControllerBox(10, 10); PointControllerBox radius = new PointControllerBox(10, 10); host.AddChild(center); host.AddChild(radius); _rotationUI.AddControlPoints(center, radius); } _rotationUI.SetReferenceOwner(_quadController); double x_center = (svg_bounds.Left + svg_bounds.Right) / 2; double y_center = (svg_bounds.Top + svg_bounds.Bottom) / 2; _rotationUI.SetCenter(x_center, y_center); _rotationUI.SetRadius(x_center + 200, y_center); host.AddChild(_rotationUI); _quadController.Drag += (s1, ev) => { _rotationUI.SetLocation( _rotationUI.Left + ev.XDiff, _rotationUI.Top + ev.YDiff); }; var spriteEvListener = new GeneralEventListener(); _uiSprite.AttachExternalEventListener(spriteEvListener); spriteEvListener.MouseMove += (s1, e1) => { if (e1.IsDragging) { //when drag on sprie _uiSprite.InvalidateGraphics(); _uiSprite.SetLocation( _uiSprite.Left + e1.XDiff, _uiSprite.Top + e1.YDiff ); //we also move quadController and _quadPolygonController // _quadController.InvalidateGraphics(); _quadController.SetLocation( _quadController.Left + e1.XDiff, _quadController.Top + e1.YDiff); _quadController.InvalidateGraphics(); // _quadPolygonController.InvalidateGraphics(); _quadPolygonController.SetLocation( _quadPolygonController.Left + e1.XDiff, _quadPolygonController.Top + e1.YDiff ); _quadPolygonController.InvalidateGraphics(); // _rotationUI.InvalidateGraphics(); _rotationUI.SetLocation( _rotationUI.Left + e1.XDiff, _rotationUI.Top + e1.YDiff); _rotationUI.InvalidateGraphics(); //_rotationControllerPointUI.InvalidateGraphics(); //_rotationControllerPointUI.SetPosition( // _rotationControllerPointUI.Left + e1.XDiff, // _rotationControllerPointUI.Top + e1.YDiff); //_rotationControllerPointUI.InvalidateGraphics(); } }; spriteEvListener.MouseDown += (s1, e1) => { //mousedown on ui sprite //find exact part ... _quadController.BringToTopMost(); _quadController.Visible = true; _quadPolygonController.Visible = true; _quadController.Focus(); // _polygonController.BringToTopMost(); if (_hitTestOnSubPath) { //find which part ... double e1_x = e1.X; double e1_y = e1.Y; ICoordTransformer tx1 = _quadController.GetCoordTransformer(); if (tx1 != null) { //if the sprite is transformed before render //we must invert x,y back to ICoordTransformer tx1_inv = tx1.CreateInvert(); tx1_inv.Transform(ref e1_x, ref e1_y); } VgHitInfo hitInfo = _uiSprite.FindRenderElementAtPos((float)e1_x, (float)e1_y, true); if (hitInfo.hitElem != null && hitInfo.hitElem.VxsPath != null) { PixelFarm.CpuBlit.VertexProcessing.Q1RectD bounds = hitInfo.copyOfVxs.GetBoundingRect(); _quadPolygonController.ClearControlPoints(); //clear old control points _quadPolygonController.UpdateControlPoints( //create new control points hitInfo.copyOfVxs, _uiSprite.ActualXOffset, _uiSprite.ActualYOffset, tx1); ////move redbox and its controller //_rectBoundsWidgetBox.SetLocationAndSize( // (int)(bounds.Left + _uiSprite.ActualXOffset), (int)(bounds.Top - bounds.Height + _uiSprite.ActualYOffset), // (int)bounds.Width, (int)bounds.Height); ////_rectBoxController.UpdateControllerBoxes(_rectBoundsWidgetBox); //_rectBoundsWidgetBox.Visible = true; ////_rectBoxController.Visible = true; //show bounds } else { //_rectBoundsWidgetBox.Visible = false; // _rectBoxController.Visible = false; } } else { //hit on sprite if (e1.Ctrl) { //test*** // _uiSprite.GetElementBounds(out float left, out float top, out float right, out float bottom); // using (Tools.BorrowRect(out SimpleRect s)) using (Tools.BorrowVxs(out var v1)) { s.SetRect(left - _uiSprite.ActualXOffset, bottom - _uiSprite.ActualYOffset, right - _uiSprite.ActualXOffset, top - _uiSprite.ActualYOffset); s.MakeVxs(v1); //_polygonController.UpdateControlPoints(v1.CreateTrim()); } } else { //_rectBoundsWidgetBox.SetTarget(_uiSprite); //_rectBoundsWidgetBox.SetLocationAndSize( //blue // (int)_uiSprite.Left, (int)_uiSprite.Top, // (int)_uiSprite.Width, (int)_uiSprite.Height); ////_rectBoxController.SetTarget(_uiSprite); ////_rectBoxController.UpdateControllerBoxes(_rectBoundsWidgetBox); //control 4 corners //_rectBoundsWidgetBox.Visible = true; ////_rectBoxController.Visible = true; //UpdateTransformedShape2(); } } }; }