public override void DrawImage(Image actualImage, double left, double top, ICoordTransformer coordTx) { //TODO: implement transformation matrix GLBitmap glBmp = _pcx.ResolveForGLBitmap(actualImage); if (glBmp != null) { if (this.OriginX != 0 || this.OriginY != 0) { //TODO: review here } // coordTx = aff = aff * Affine.NewTranslation(this.OriginX, this.OriginY); Affine aff = coordTx as Affine; if (aff != null) { _pcx.DrawImageToQuad(glBmp, aff); } else { } //_pcx.DrawImage(glBmp, (float)left, (float)top); } }
public override void DrawImage(Image actualImage, double left, double top, ICoordTransformer coordTx) { //draw img with transform coord // MemBitmap memBmp = actualImage as MemBitmap; if (memBmp == null) { //? TODO return; } if (_renderQuality == RenderQuality.Fast) { //todo, review here again //TempMemPtr tmp = ActualBitmap.GetBufferPtr(actualImg); //BitmapBuffer srcBmp = new BitmapBuffer(actualImage.Width, actualImage.Height, tmp.Ptr, tmp.LengthInBytes); //_bxt.BlitRender(srcBmp, false, 1, new BitmapBufferEx.MatrixTransform(affinePlans)); //if (affinePlans != null && affinePlans.Length > 0) //{ // _bxt.BlitRender(srcBmp, false, 1, new BitmapBufferEx.MatrixTransform(affinePlans)); //} //else //{ // //_bxt.BlitRender(srcBmp, false, 1, null); // _bxt.Blit(0, 0, srcBmp.PixelWidth, srcBmp.PixelHeight, srcBmp, 0, 0, srcBmp.PixelWidth, srcBmp.PixelHeight, // ColorInt.FromArgb(255, 255, 255, 255), // BitmapBufferExtensions.BlendMode.Alpha); //} return; } bool useSubPix = UseSubPixelLcdEffect; //save, restore later... //before render an image we turn off vxs subpixel rendering this.UseSubPixelLcdEffect = false; if (coordTx is Affine) { Affine aff = (Affine)coordTx; if (this.OriginX != 0 || this.OriginY != 0) { coordTx = aff = aff * Affine.NewTranslation(this.OriginX, this.OriginY); } } //_aggsx.SetScanlineRasOrigin(OriginX, OriginY); _aggsx.Render(memBmp, coordTx); //_aggsx.SetScanlineRasOrigin(xx, yy); //restore... this.UseSubPixelLcdEffect = useSubPix; }
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); } }
ICoordTransformer ICoordTransformer.MultiplyWith(ICoordTransformer another) { if (another is Affine aff) { return(this * aff); } else if (another is Perspective p2) { return(new Perspective(this) * p2); } else { return(null); } }
/// <summary> /// 坐标转换 /// </summary> /// <param name="trans"></param> /// <returns></returns> public bool Transform(ICoordTransformer trans) { XYZ topRight = new XYZ(this.MaxHorizontal, this.MaxVertical, 0); XYZ leftBottom = new XYZ(this.MinHorizontal, this.MinVertical, 0); topRight = trans.Trans(topRight); leftBottom = trans.Trans(leftBottom); this.MaxHorizontal = topRight[0]; this.MaxVertical = topRight[1]; this.MinHorizontal = leftBottom[0]; this.MinVertical = leftBottom[1]; return(true); }
public static VertexStore MakeVxs(this Ellipse ellipse, ICoordTransformer tx, VertexStore output) { //1. moveto output.AddMoveTo(ellipse.originX + ellipse.radiusX, ellipse.originY, tx);//** //2. // int numSteps = ellipse.NumSteps; double anglePerStep = MathHelper.Tau / numSteps; double angle = 0; double orgX = ellipse.originX; double orgY = ellipse.originY; double radX = ellipse.radiusX; double radY = ellipse.radiusY; if (ellipse._cw) { for (int i = 1; i < numSteps; i++) { angle += anglePerStep; output.AddLineTo( orgX + Math.Cos(MathHelper.Tau - angle) * radX, orgY + Math.Sin(MathHelper.Tau - angle) * radY, tx);//** } } else { for (int i = 1; i < numSteps; i++) { angle += anglePerStep; output.AddLineTo( orgX + Math.Cos(angle) * radX, orgY + Math.Sin(angle) * radY, tx);//** } } //3. output.AddCloseFigure((int)EndVertexOrientation.CCW, 0); //4. output.AddNoMore(); return(output); }
ICoordTransformer ICoordTransformer.MultiplyWith(ICoordTransformer another) { if (another is Affine) { return(this * (Affine)another); } else if (another is Perspective) { Perspective p = new Perspective(this); return(p * (Perspective)another); } else { return(null); } }
public ICoordTransformer MultiplyWith(ICoordTransformer another) { if (another is Affine) { return(this * (Affine)another); } else if (another is Perspective) { Perspective p = new Perspective(this); return(p * (Perspective)another); } else { return(new CoordTransformationChain(this, another)); } }
public void ResolveBrush(RadialGradientBrush radialGrBrush) { //for gradient : PointF p1 = radialGrBrush.StartPoint; PointF p2 = radialGrBrush.EndPoint; if (radialGrBrush.CoordTransformer != null) { _invertCoordTx = radialGrBrush.CoordTransformer.CreateInvert(); } _center_x = (int)Math.Round(p1.X); _center_y = (int)Math.Round(p1.Y); float r = (float)Math.Sqrt((p2.X - _center_x) * (p2.X - _center_x) + (p2.Y - _center_y) * (p2.Y - _center_y)); ColorStop[] colorStops = radialGrBrush.ColorStops; int pairCount = colorStops.Length - 1; _orgList = new LinearGradientPair[pairCount]; _pairList = new LinearGradientPair[_orgList.Length]; ColorStop c1 = ColorStop.Empty; for (int i = 0; i < pairCount; ++i) { ColorStop c0 = colorStops[i]; c1 = colorStops[i + 1]; var pairN = new LinearGradientPair( c0.Offset * r, //to actual pixel c1.Offset * r, //to actual pixel c0.Color, c1.Color); _orgList[i] = pairN; } _endColor = c1.Color; this.SpreadMethod = radialGrBrush.SpreadMethod; Opactiy = 1; }
public void Render(IBitmapSrc source, ICoordTransformer coordtx) { using (VxsTemp.Borrow(out var v1, out var v2)) { BuildOrgImgRectVxs( source.Width, source.Height, v1); //** //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 = coordtx.CreateInvert(); _currentImgSpanGen.BackgroundColor = Color.Transparent; _currentImgSpanGen.SetInterpolator(_spanInterpolator); _currentImgSpanGen.SetSrcBitmap(source); TransformToVxs(coordtx, v1, v2); Render(v2, _currentImgSpanGen); _currentImgSpanGen.ReleaseSrcBitmap(); } }
public void Paint(Painter p, ICoordTransformer tx) { //TODO: implement this... //use prefix command for render vx //------ using (VgPaintArgsPool.Borrow(p, out var paintArgs)) { paintArgs._currentTx = tx; paintArgs.PaintVisitHandler = (vxs, arg) => { //use external painter handler //draw only outline with its fill-color. Drawing.Painter m_painter = arg.P; Drawing.Color prevFillColor = m_painter.FillColor; m_painter.FillColor = m_painter.FillColor; m_painter.Fill(vxs); m_painter.FillColor = prevFillColor; }; _vgVisElem.Paint(paintArgs); } }
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); }
/// <summary> /// serialize coord-transform-chain to specific stream /// </summary> /// <param name="coordTx"></param> /// <param name="writer"></param> public static void Write(ICoordTransformer coordTx, System.IO.BinaryWriter writer) { //write transformation matrix to binary stream CoordTransformerKind txKind = coordTx.Kind; switch (txKind) { case CoordTransformerKind.Unknown: default: throw new System.NotSupportedException(); case CoordTransformerKind.Affine3x2: { Affine aff = (Affine)coordTx; writer.Write((ushort)txKind); //type AffineMat affMat = aff.GetInternalMat(); //write elements writer.Write(affMat.sx); writer.Write(affMat.shy); writer.Write(affMat.shx); writer.Write(affMat.sy); writer.Write(affMat.tx); writer.Write(affMat.ty); } break; case CoordTransformerKind.Bilinear: { Bilinear binTx = (Bilinear)coordTx; writer.Write((ushort)txKind); //write elements BilinearMat binMat = binTx.GetInternalElements(); writer.Write(binMat.rc00); writer.Write(binMat.rc01); writer.Write(binMat.rc10); writer.Write(binMat.rc11); writer.Write(binMat.rc20); writer.Write(binMat.rc21); writer.Write(binMat.rc30); writer.Write(binMat.rc31); } break; case CoordTransformerKind.Perspective: { Perspective perTx = (Perspective)coordTx; writer.Write((ushort)txKind); PerspectiveMat perMat = perTx.GetInternalElements(); writer.Write(perMat.sx); writer.Write(perMat.shx); writer.Write(perMat.w0); writer.Write(perMat.shy); writer.Write(perMat.sy); writer.Write(perMat.w1); writer.Write(perMat.tx); writer.Write(perMat.ty); writer.Write(perMat.w2); //sx, shy, w0, //shx, sy, w1, //tx, ty, w2; } break; case CoordTransformerKind.TransformChain: { CoordTransformationChain chainTx = (CoordTransformationChain)coordTx; writer.Write((ushort)txKind); //*** left, right Write(chainTx.Left, writer); Write(chainTx.Right, writer); } break; } }
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"); //PixelFarm.CpuBlit.RectD org_rectD = _svgRenderVx.GetBounds(); //_svgRenderVx = CreateEllipseVxs(org_rectD); PixelFarm.CpuBlit.RectD 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.InvalidateOuterGraphics(); 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.InvalidateOuterGraphics(); //_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.RectD 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); _rotationUI.SetCenter(svg_bounds.XCenter, svg_bounds.YCenter); _rotationUI.SetRadius(svg_bounds.XCenter + 200, svg_bounds.YCenter); host.AddChild(_rotationUI); _quadController.Drag += ev => { _rotationUI.SetLocation( _rotationUI.Left + ev.XDiff, _rotationUI.Top + ev.YDiff); }; var spriteEvListener = new GeneralEventListener(); _uiSprite.AttachExternalEventListener(spriteEvListener); spriteEvListener.MouseMove += e1 => { if (e1.IsDragging) { //when drag on sprie _uiSprite.InvalidateOuterGraphics(); _uiSprite.SetLocation( _uiSprite.Left + e1.XDiff, _uiSprite.Top + e1.YDiff ); //we also move quadController and _quadPolygonController // _quadController.InvalidateOuterGraphics(); _quadController.SetLocation( _quadController.Left + e1.XDiff, _quadController.Top + e1.YDiff); _quadController.InvalidateOuterGraphics(); // _quadPolygonController.InvalidateOuterGraphics(); _quadPolygonController.SetLocation( _quadPolygonController.Left + e1.XDiff, _quadPolygonController.Top + e1.YDiff ); _quadPolygonController.InvalidateOuterGraphics(); // _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 += 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 ... VgHitInfo hitInfo = _uiSprite.FindRenderElementAtPos(e1.X, e1.Y, true); if (hitInfo.hitElem != null && hitInfo.hitElem.VxsPath != null) { PixelFarm.CpuBlit.RectD bounds = hitInfo.copyOfVxs.GetBoundingRect(); _quadPolygonController.ClearControlPoints(); //clear old control points _quadPolygonController.UpdateControlPoints( //create new control points hitInfo.copyOfVxs, _uiSprite.ActualXOffset, _uiSprite.ActualYOffset); ////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 (VectorToolBox.Borrow(out SimpleRect s)) using (VxsTemp.Borrow(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(); } } }; }
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 CoordTransformationChain(ICoordTransformer left, ICoordTransformer right) { _left = left; _right = right; }
ICoordTransformer ICoordTransformer.MultiplyWith(ICoordTransformer another) { return(new CoordTransformationChain(_left, _right.MultiplyWith(another))); }
ICoordTransformer ICoordTransformer.MultiplyWith(ICoordTransformer another) { return(new CoordTransformationChain(this, another)); }
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 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; }
internal virtual void Reset() { _currentTx = null; Current = null; }
public static void AddLineTo(this VertexStore vxs, double x, double y, ICoordTransformer tx) { tx.Transform(ref x, ref y); vxs.AddLineTo(x, y); }