using UnityEngine; using System; using System.Collections.Generic; // TODO: Find a way to break this the hell up. // TODO: Normalize conventions away from Java-style SetX to properties. public class SVGGraphics { private ISVGDevice device; private SVGGraphicsFill graphicsFill; private SVGGraphicsStroke graphicsStroke; public Vector2 Size { set { int width = (int)value.x, height = (int)value.y; device.SetDevice(width, height); graphicsFill.Size = new Vector2(width, height); Clean(); } } public SVGStrokeLineCapMethod StrokeLineCap { get; set; } public SVGStrokeLineJoinMethod StrokeLineJoin { get; set; } public SVGGraphics() { graphicsFill = new SVGGraphicsFill(this); graphicsStroke = new SVGGraphicsStroke(this); } public SVGGraphics(ISVGDevice dev) { device = dev; graphicsFill = new SVGGraphicsFill(this); graphicsStroke = new SVGGraphicsStroke(this); } public void SetColor(Color color) { device.SetColor(color); } public void SetPixel(int x, int y) { device.SetPixel(x, y); } public Texture2D Render() { return device.Render(); } public void Clean() { int width = device.Width; int height = device.Height; SetColor(Color.white); for(int i = 0; i < width; i++) { for(int j = 0; j < height; j++) SetPixel(i, j); } } //Tinh 4 diem 1, 2, 3, 4 cua 1 line voi width public bool GetThickLine(Vector2 p1, Vector2 p2, float width, ref Vector2 rp1, ref Vector2 rp2, ref Vector2 rp3, ref Vector2 rp4) { float cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4; float dtx, dty, temp, _half; int _ihalf1, _ihalf2; _half = width / 2f; _ihalf1 = (int)_half; _ihalf2 = (int)(width - _ihalf1 + 0.5f); dtx = p2.x - p1.x; dty = p2.y - p1.y; temp = dtx * dtx + dty * dty; if(temp == 0f) { rp1.x = p1.x - _ihalf2; rp1.y = p1.y + _ihalf2; rp2.x = p1.x - _ihalf2; rp2.y = p1.y - _ihalf2; rp3.x = p1.x + _ihalf1; rp3.y = p1.y + _ihalf1; rp4.x = p1.x + _ihalf1; rp4.y = p1.y - _ihalf1; return false; } cy1 = _ihalf1 * dtx / (float)Math.Sqrt(temp) + p1.y; if(dtx == 0) { if(dty > 0) cx1 = p1.x - _ihalf1; else cx1 = p1.x + _ihalf1; } else cx1 = (-(cy1 - p1.y) * dty) / dtx + p1.x; cy2 = -(_ihalf2 * dtx / (float)Math.Sqrt(temp)) + p1.y; if(dtx == 0) { if(dty > 0) cx2 = p1.x + _ihalf2; else cx2 = p1.x - _ihalf2; } else cx2 = (-(cy2 - p1.y) * dty) / dtx + p1.x; dtx = p1.x - p2.x; dty = p1.y - p2.y; temp = dtx * dtx + dty * dty; cy3 = _ihalf1 * dtx / (float)Math.Sqrt(temp) + p2.y; if(dtx == 0) { if(dty > 0) cx3 = p2.x - _ihalf1; else cx3 = p2.x + _ihalf1; } else cx3 = (-(cy3 - p2.y) * dty) / dtx + p2.x; cy4 = -(_ihalf2 * dtx / (float)Math.Sqrt(temp)) + p2.y; if(dtx == 0) { if(dty > 0) cx4 = p2.x + _ihalf2; else cx4 = p2.x - _ihalf2; } else cx4 = (-(cy4 - p2.y) * dty) / dtx + p2.x; rp1.x = cx1; rp1.y = cy1; rp2.x = cx2; rp2.y = cy2; float t1, t2; t1 = ((p1.y - cy1) * (p2.x - p1.x)) - ((p1.x - cx1) * (p2.y - p1.y)); t2 = ((p1.y - cy4) * (p2.x - p1.x)) - ((p1.x - cx4) * (p2.y - p1.y)); if(t1 * t2 > 0) { //bi lech if(_ihalf1 != _ihalf2) { cy3 = _ihalf2 * dtx / (float)Math.Sqrt(temp) + p2.y; if(dtx == 0) { if(dty > 0) cx3 = p2.x - _ihalf2; else cx3 = p2.x + _ihalf2; } else cx3 = (-(cy3 - p2.y) * dty) / dtx + p2.x; cy4 = -(_ihalf1 * dtx / (float)Math.Sqrt(temp)) + p2.y; if(dtx == 0) { if(dty > 0) cx4 = p2.x + _ihalf1; else cx4 = p2.x - _ihalf1; } else cx4 = (-(cy4 - p2.y) * dty) / dtx + p2.x; } rp3.x = cx4; rp3.y = cy4; rp4.x = cx3; rp4.y = cy3; } else { rp3.x = cx3; rp3.y = cy3; rp4.x = cx4; rp4.y = cy4; } return true; } //Tinh diem giao nhau giua 2 doan thang public Vector2 GetCrossPoint(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4) { Vector2 _return = new Vector2(0f, 0f); float a1 = 0f, b1 = 0f, a2 = 0f, b2 = 0f; float dx1, dy1, dx2, dy2; dx1 = p1.x - p2.x; dy1 = p1.y - p2.y; dx2 = p3.x - p4.x; dy2 = p3.y - p4.y; if(dx1 != 0f) { a1 = dy1 / dx1; b1 = p1.y - a1 * p1.x; } if(dx2 != 0) { a2 = dy2 / dx2; b2 = p3.y - a2 * p3.x; } float tx = 0f, ty = 0f; //truong hop nam tren duong thang if((a1 == a2) && (b1 == b2)) { Vector2 t_p1 = p1; Vector2 t_p2 = p1; if(dx1 == 0f) { if(p2.y < t_p1.y) t_p1 = p2; if(p3.y < t_p1.y) t_p1 = p3; if(p4.y < t_p1.y) t_p1 = p4; if(p2.y > t_p2.y) t_p2 = p2; if(p3.y > t_p2.y) t_p2 = p3; if(p4.y > t_p2.y) t_p2 = p4; } else { if(p2.x < t_p1.x) t_p1 = p2; if(p3.x < t_p1.x) t_p1 = p3; if(p4.x < t_p1.x) t_p1 = p4; if(p2.x > t_p2.x) t_p2 = p2; if(p3.x > t_p2.x) t_p2 = p3; if(p4.x > t_p2.x) t_p2 = p4; } tx = (t_p1.x - t_p2.x) / 2f; tx = t_p2.x + tx; ty = (t_p1.y - t_p2.y) / 2f; ty = t_p2.y + ty; _return.x = tx; _return.y = ty; return _return; } if((dx1 != 0) && (dx2 != 0)) { tx = -(b1 - b2) / (a1 - a2); ty = a1 * tx + b1; } else if((dx1 == 0) && (dx2 != 0)) { tx = p1.x; ty = a2 * tx + b2; } else if((dx1 != 0) && (dx2 == 0)) { tx = p3.x; ty = a1 * tx + b1; } _return.x = tx; _return.y = ty; return _return; } public float AngleBetween2Vector(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4) { Vector2 vt1, vt2; vt1 = new Vector2(p2.x - p1.x, p2.y - p1.y); vt2 = new Vector2(p4.x - p3.x, p4.y - p3.y); float t1 = vt1.x * vt2.x + vt1.y * vt2.y; float gtvt1 = (float)Math.Sqrt(vt1.x * vt1.x + vt1.y * vt1.y); float gtvt2 = (float)Math.Sqrt(vt2.x * vt2.x + vt2.y * vt2.y); float t2 = gtvt1 * gtvt2; float cosAngle = t1 / t2; return ((float)Math.Acos(cosAngle)); } public void Line(Vector2 p1, Vector2 p2) { graphicsStroke.Line(p1, p2); } public void Line(Vector2 p1, Vector2 p2, SVGColor? strokeColor) { if(strokeColor != null) SetColor(strokeColor.Value.color); Line(p1, p2); } public void Line(Vector2 p1, Vector2 p2, float width) { graphicsStroke.Line(p1, p2, width); } public void Line(Vector2 p1, Vector2 p2, SVGColor? strokeColor, float width) { if(strokeColor != null) SetColor(strokeColor.Value.color); Line(p1, p2, width); } public void Rect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4) { graphicsStroke.Rect(p1, p2, p3, p4); } public void Rect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, SVGColor? strokeColor) { if(strokeColor != null) SetColor(strokeColor.Value.color); Rect(p1, p2, p3, p4); } public void Rect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float width) { graphicsStroke.Rect(p1, p2, p3, p4, width); } public void Rect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, SVGColor? strokeColor, float width) { if(strokeColor != null) SetColor(strokeColor.Value.color); Rect(p1, p2, p3, p4, width); } public void RoundedRect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, Vector2 p5, Vector2 p6, Vector2 p7, Vector2 p8, float r1, float r2, float angle) { graphicsStroke.RoundedRect(p1, p2, p3, p4, p5, p6, p7, p8, r1, r2, angle); } public void RoundedRect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, Vector2 p5, Vector2 p6, Vector2 p7, Vector2 p8, float r1, float r2, float angle, SVGColor? strokeColor) { if(strokeColor != null) SetColor(strokeColor.Value.color); RoundedRect(p1, p2, p3, p4, p5, p6, p7, p8, r1, r2, angle); } public void RoundedRect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, Vector2 p5, Vector2 p6, Vector2 p7, Vector2 p8, float r1, float r2, float angle, float width) { if((int)width == 1) { RoundedRect(p1, p2, p3, p4, p5, p6, p7, p8, r1, r2, angle); return; } graphicsStroke.RoundedRect(p1, p2, p3, p4, p5, p6, p7, p8, r1, r2, angle, width); } public void RoundedRect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, Vector2 p5, Vector2 p6, Vector2 p7, Vector2 p8, float r1, float r2, float angle, SVGColor? strokeColor, float width) { if(strokeColor != null) SetColor(strokeColor.Value.color); RoundedRect(p1, p2, p3, p4, p5, p6, p7, p8, r1, r2, angle, width); } public void FillRect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4) { graphicsFill.Rect(p1, p2, p3, p4); } public void FillRect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, SVGColor? strokeColor) { graphicsFill.Rect(p1, p2, p3, p4, strokeColor); } public void FillRect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, SVGColor fillColor, SVGColor? strokeColor) { graphicsFill.Rect(p1, p2, p3, p4, fillColor, strokeColor); } public void FillRect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, SVGColor? strokeColor, float width) { if((int)width == 1) { FillRect(p1, p2, p3, p4, strokeColor); return; } FillRect(p1, p2, p3, p4); if(strokeColor == null) return; SetColor(strokeColor.Value.color); Rect(p1, p2, p3, p4, strokeColor, width); } public void FillRect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, SVGColor fillColor, SVGColor? strokeColor, float width) { if((int)width == 1) { FillRect(p1, p2, p3, p4, fillColor, strokeColor); return; } SetColor(fillColor.color); FillRect(p1, p2, p3, p4); if(strokeColor == null) return; SetColor(strokeColor.Value.color); Rect(p1, p2, p3, p4, strokeColor, width); } public void FillRoundedRect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, Vector2 p5, Vector2 p6, Vector2 p7, Vector2 p8, float r1, float r2, float angle) { graphicsFill.RoundedRect(p1, p2, p3, p4, p5, p6, p7, p8, r1, r2, angle); } public void FillRoundedRect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, Vector2 p5, Vector2 p6, Vector2 p7, Vector2 p8, float r1, float r2, float angle, SVGColor? strokeColor) { graphicsFill.RoundedRect(p1, p2, p3, p4, p5, p6, p7, p8, r1, r2, angle, strokeColor); } public void FillRoundedRect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, Vector2 p5, Vector2 p6, Vector2 p7, Vector2 p8, float r1, float r2, float angle, SVGColor fillColor, SVGColor? strokeColor) { graphicsFill.RoundedRect(p1, p2, p3, p4, p5, p6, p7, p8, r1, r2, angle, fillColor, strokeColor); } public void FillRoundedRect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, Vector2 p5, Vector2 p6, Vector2 p7, Vector2 p8, float r1, float r2, float angle, SVGColor? strokeColor, float width) { if((int)width == 1) { FillRoundedRect(p1, p2, p3, p4, p5, p6, p7, p8, r1, r2, angle, strokeColor); return; } graphicsFill.RoundedRect(p1, p2, p3, p4, p5, p6, p7, p8, r1, r2, angle); if(strokeColor == null) return; SetColor(strokeColor.Value.color); RoundedRect(p1, p2, p3, p4, p5, p6, p7, p8, r1, r2, angle, strokeColor); } public void FillRoundedRect(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, Vector2 p5, Vector2 p6, Vector2 p7, Vector2 p8, float r1, float r2, float angle, SVGColor fillColor, SVGColor? strokeColor, float width) { if((int)width == 1) { FillRoundedRect(p1, p2, p3, p4, p5, p6, p7, p8, r1, r2, angle, strokeColor); return; } SetColor(fillColor.color); graphicsFill.RoundedRect(p1, p2, p3, p4, p5, p6, p7, p8, r1, r2, angle); if(strokeColor == null) return; SetColor(strokeColor.Value.color); RoundedRect(p1, p2, p3, p4, p5, p6, p7, p8, r1, r2, angle, strokeColor); } public void Circle(Vector2 p, float r) { graphicsStroke.Circle(p, r); } public void Circle(Vector2 p, float r, SVGColor? strokeColor) { if(strokeColor != null) SetColor(strokeColor.Value.color); Circle(p, r); } public void Circle(Vector2 p, float r, float width) { graphicsStroke.Circle(p, r, width); } public void Circle(Vector2 p, float r, SVGColor? strokeColor, float width) { if(strokeColor != null) SetColor(strokeColor.Value.color); Circle(p, r, width); } public void FillCircle(Vector2 p, float r) { graphicsFill.Circle(p, r); } public void FillCircle(Vector2 p, float r, SVGColor? strokeColor) { graphicsFill.Circle(p, r, strokeColor); } public void FillCircle(Vector2 p, float r, SVGColor fillColor, SVGColor? strokeColor) { graphicsFill.Circle(p, r, fillColor, strokeColor); } public void FillCircle(Vector2 p, float r, SVGColor? strokeColor, float width) { if((int)width == 1) { FillCircle(p, r, strokeColor); return; } FillCircle(p, r); if(strokeColor == null) return; SetColor(strokeColor.Value.color); Circle(p, r, strokeColor, width); } public void FillCircle(Vector2 p, float r, SVGColor fillColor, SVGColor? strokeColor, float width) { if((int)width == 1) { FillCircle(p, r, strokeColor); return; } SetColor(fillColor.color); FillCircle(p, r); if(strokeColor == null) return; SetColor(strokeColor.Value.color); Circle(p, r, strokeColor, width); } public void Ellipse(Vector2 p, float rx, float ry, float angle) { graphicsStroke.Ellipse(p, rx, ry, angle); } public void Ellipse(Vector2 p, float rx, float ry, float angle, SVGColor? strokeColor) { if(strokeColor != null) SetColor(strokeColor.Value.color); Ellipse(p, rx, ry, angle); } public void Ellipse(Vector2 p, float rx, float ry, float angle, float width) { graphicsStroke.Ellipse(p, rx, ry, angle, width); } public void Ellipse(Vector2 p, float rx, float ry, float angle, SVGColor? strokeColor, float width) { if(strokeColor != null) SetColor(strokeColor.Value.color); Ellipse(p, rx, ry, angle, width); } public void FillEllipse(Vector2 p, float rx, float ry, float angle) { graphicsFill.Ellipse(p, rx, ry, angle); } public void FillEllipse(Vector2 p, float rx, float ry, float angle, SVGColor? strokeColor) { graphicsFill.Ellipse(p, rx, ry, angle, strokeColor); } public void FillEllipse(Vector2 p, float rx, float ry, float angle, SVGColor fillColor, SVGColor? strokeColor) { graphicsFill.Ellipse(p, rx, ry, angle, fillColor, strokeColor); } public void FillEllipse(Vector2 p, float rx, float ry, float angle, SVGColor? strokeColor, float width) { if((int)width == 1) { FillEllipse(p, rx, ry, angle, strokeColor); return; } FillEllipse(p, rx, ry, angle); if(strokeColor == null) return; SetColor(strokeColor.Value.color); Ellipse(p, rx, ry, angle, width); } public void FillEllipse(Vector2 p, float rx, float ry, float angle, SVGColor fillColor, SVGColor? strokeColor, float width) { if((int)width == 1) { FillEllipse(p, rx, ry, angle, strokeColor); return; } SetColor(fillColor.color); FillEllipse(p, rx, ry, angle); if(strokeColor == null) return; SetColor(strokeColor.Value.color); Ellipse(p, rx, ry, angle, width); } public void Polygon(Vector2[] points) { graphicsStroke.Polygon(points); } public void Polygon(Vector2[] points, SVGColor? strokeColor) { if(strokeColor != null) SetColor(strokeColor.Value.color); Polygon(points); } public void Polygon(Vector2[] points, float width) { graphicsStroke.Polygon(points, width); } public void Polygon(Vector2[] points, SVGColor? strokeColor, float width) { if(strokeColor != null) SetColor(strokeColor.Value.color); Polygon(points, width); } public void FillPolygon(Vector2[] points) { graphicsFill.Polygon(points); } public void FillPolygon(Vector2[] points, SVGColor? strokeColor) { graphicsFill.Polygon(points, strokeColor); } public void FillPolygon(Vector2[] points, SVGColor fillColor, SVGColor? strokeColor) { graphicsFill.Polygon(points, fillColor, strokeColor); } public void FillPolygon(Vector2[] points, SVGColor? strokeColor, float width) { if((int)width == 1) { FillPolygon(points, strokeColor); return; } FillPolygon(points); if(strokeColor == null) return; SetColor(strokeColor.Value.color); Polygon(points, width); } public void FillPolygon(Vector2[] points, SVGColor fillColor, SVGColor? strokeColor, float width) { if((int)width == 1) { FillPolygon(points, strokeColor); return; } SetColor(fillColor.color); FillPolygon(points); if(strokeColor == null) return; SetColor(strokeColor.Value.color); Polygon(points, width); } //Fill khong to Stroke public void FillPath(SVGLinearGradientBrush linearGradientBrush, SVGGraphicsPath graphicsPath) { graphicsFill.FillPath(linearGradientBrush, graphicsPath); } //Fill co Stroke trong do luon public void FillPath(SVGLinearGradientBrush linearGradientBrush, SVGColor? strokePathColor, SVGGraphicsPath graphicsPath) { graphicsFill.FillPath(linearGradientBrush, strokePathColor, graphicsPath); } //Fill khong co Stroke, va ve stroke sau public void FillPath(SVGLinearGradientBrush linearGradientBrush, SVGColor? strokePathColor, float width, SVGGraphicsPath graphicsPath) { graphicsFill.FillPath(linearGradientBrush, strokePathColor, graphicsPath); if((int)width == 1) graphicsFill.FillPath(linearGradientBrush, strokePathColor, graphicsPath); else graphicsFill.FillPath(linearGradientBrush, graphicsPath); if(strokePathColor == null) return; SetColor(strokePathColor.Value.color); } //Fill khong to Stroke public void FillPath(SVGRadialGradientBrush radialGradientBrush, SVGGraphicsPath graphicsPath) { graphicsFill.FillPath(radialGradientBrush, graphicsPath); } //Fill co Stroke trong do luon public void FillPath(SVGRadialGradientBrush radialGradientBrush, SVGColor? strokePathColor, SVGGraphicsPath graphicsPath) { graphicsFill.FillPath(radialGradientBrush, strokePathColor, graphicsPath); } //Fill khong co Stroke, va ve stroke sau public void FillPath(SVGRadialGradientBrush radialGradientBrush, SVGColor? strokePathColor, float width, SVGGraphicsPath graphicsPath) { graphicsFill.FillPath(radialGradientBrush, strokePathColor, graphicsPath); if((int)width == 1) graphicsFill.FillPath(radialGradientBrush, strokePathColor, graphicsPath); else graphicsFill.FillPath(radialGradientBrush, graphicsPath); if(strokePathColor == null) return; SetColor(strokePathColor.Value.color); //graphicsPath.RenderPath(this, width, false); } //Fill khong to Stroke public void FillPath(SVGGraphicsPath graphicsPath) { graphicsFill.FillPath(graphicsPath); } //Fill khong to Stroke public void FillPath(SVGColor fillColor, SVGGraphicsPath graphicsPath) { graphicsFill.FillPath(fillColor, graphicsPath); } //Fill co Stroke trong do luon public void FillPath(SVGColor fillColor, SVGColor? strokePathColor, SVGGraphicsPath graphicsPath) { graphicsFill.FillPath(fillColor, strokePathColor, graphicsPath); } //Fill khong co Stroke, va ve stroke sau public void FillPath(SVGColor fillColor, SVGColor? strokePathColor, float width, SVGGraphicsPath graphicsPath) { graphicsFill.FillPath(fillColor, strokePathColor, graphicsPath); if((int)width == 1) graphicsFill.FillPath(fillColor, strokePathColor, graphicsPath); else graphicsFill.FillPath(fillColor, graphicsPath); if(strokePathColor == null) return; SetColor(strokePathColor.Value.color); } public void FillPath(SVGGraphicsPath graphicsPath, Vector2[] points) { graphicsFill.FillPath(graphicsPath, points); } public void FillPath(SVGGraphicsPath graphicsPath, Vector2 point) { graphicsFill.FillPath(graphicsPath, point); } public void DrawPath(SVGGraphicsPath graphicsPath) { graphicsStroke.DrawPath(graphicsPath); } //Fill co Stroke trong do luon public void DrawPath(SVGGraphicsPath graphicsPath, float width) { graphicsStroke.DrawPath(graphicsPath, width); } //Fill khong co Stroke, va ve stroke sau public void DrawPath(SVGGraphicsPath graphicsPath, float width, SVGColor? strokePathColor) { if(strokePathColor == null) return; SetColor(strokePathColor.Value.color); graphicsStroke.DrawPath(graphicsPath, width); } }