ExtendedGeneralPath.jvm.cs :  » 2.6.4-mono-.net-core » System.Drawing » System » Drawing » Drawing2D » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Drawing 
System.Drawing » System » Drawing » Drawing2D » ExtendedGeneralPath.jvm.cs
//
// System.Drawing.Drawing2D.ExtendedGeneralPath.cs
//
// Author:
// Bors Kirzner <boris@mainsoft.com>  
//
// Copyright (C) 2005 Mainsoft Corporation, (http://www.mainsoft.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System;

using java.awt;
using java.awt.geom;
using java.lang;

namespace System.Drawing.Drawing2D{
  internal class ExtendedGeneralPath : Shape, ICloneable
  {
    #region Fields

    public const int WIND_EVEN_ODD = 0; //PathIterator__Finals.WIND_EVEN_ODD;
    public const int WIND_NON_ZERO = 1; //PathIterator__Finals.WIND_NON_ZERO;
    
    public const sbyte SEG_MOVETO  = 0; //(byte) PathIterator__Finals.SEG_MOVETO;
    public const sbyte SEG_LINETO  = 1; //(byte) PathIterator__Finals.SEG_LINETO;
    public const sbyte SEG_QUADTO  = 2; //(byte) PathIterator__Finals.SEG_QUADTO;
    public const sbyte SEG_CUBICTO = 3; //(byte) PathIterator__Finals.SEG_CUBICTO;
    public const sbyte SEG_CLOSE   = 4; //(byte) PathIterator__Finals.SEG_CLOSE;
    
    public const sbyte SEG_START    = 16; // segment start

    public const sbyte SEG_MASK    = SEG_MOVETO | SEG_LINETO | SEG_QUADTO | SEG_CUBICTO | SEG_CLOSE; // mask to eliminate SEG_CLOSE and SEG_MARKER

    private const sbyte SEG_MARKER = 32; // path marker
    

    private sbyte [] _types;
    private float [] _coords;
    private int _typesCount;
    private int _coordsCount;
    private int _windingRule;

    private PathData _pathData;
    private GeneralPath _generalPath;

    const int INIT_SIZE = 20;
    const int EXPAND_MAX = 500;

    #endregion // Fileds

    #region Constructors

      public ExtendedGeneralPath() : this (WIND_NON_ZERO, INIT_SIZE, INIT_SIZE)
    {
    }

    public ExtendedGeneralPath(int rule) : this (rule, INIT_SIZE, INIT_SIZE)
    {
    }

    public ExtendedGeneralPath(int rule, int initialCapacity) : this (rule, initialCapacity, initialCapacity)
    {
    }

    public ExtendedGeneralPath(Shape s) : this(WIND_NON_ZERO, INIT_SIZE, INIT_SIZE)
    {
      PathIterator pi = s.getPathIterator (null);
      setWindingRule (pi.getWindingRule ());
      append (pi, false);
    }

    private ExtendedGeneralPath(int rule, int initialTypes, int initialCoords) 
    {
      setWindingRule(rule);
      Reset (initialTypes, initialCoords);
    }

    #endregion // Constructors

    #region Properties

    private GeneralPath GeneralPath
    {
      get {
        if (_generalPath == null) {        
          _generalPath = GetGeneralPath ();
        }
        return _generalPath;
      }
    }

    public sbyte [] Types
    {
      get { return _types; }
    }

    public float [] Coords
    {
      get { return _coords; }
    }

    public int TypesCount
    {
      get { return _typesCount; }
    }

    public int CoordsCount
    {
      get { return _coordsCount; }
    }

    public bool LastFigureClosed
    {
      get { 
        return ((TypesCount == 0) || 
          ((Types [TypesCount - 1] & ExtendedGeneralPath.SEG_CLOSE) != 0) ||
          ((Types [TypesCount - 1] & ExtendedGeneralPath.SEG_START) != 0));
      }
    }

    public int PointCount
    {
      get {
        return CoordsCount / 2;
      }
    }

    public PathData PathData 
    {
      get 
      {
        if (_pathData == null)
          _pathData = GetPathData ();
        
        return _pathData;
      }
    }

    #endregion // Properties

    #region Methods

    #region CachedData

    private void ClearCache ()
    {
      _pathData = null;
      _generalPath = null;
    }

    private GeneralPath GetGeneralPath ()
    {
      PathIterator iter = getPathIterator (null);
      GeneralPath path = new GeneralPath ();
      path.append (iter, false);
      return path;
    }

    private PathData GetPathData ()
    {
      PathData pathData = new PathData();
      int nPts = PointCount;
      for (int i = 0; i < TypesCount; i++)
        if ((Types [i] & SEG_MASK) == SEG_QUADTO)
          nPts++;

      pathData.Types = new byte [nPts];
      pathData.Points = new PointF [nPts];
      int tpos = 0;
      int ppos = 0;
      int cpos = 0;
      byte marker;
      bool start;
      for (int i = 0; i < TypesCount; i++) {
        sbyte segmentType = (sbyte)(Types [i] & SEG_MASK);

        // set the masks and the markers
        marker = ((Types [i] & SEG_MARKER) != 0) ? (byte)PathPointType.PathMarker : (byte)0;
        start = ((Types [i] & SEG_START) != 0);
        
        switch (segmentType) {
          case SEG_CLOSE:
            pathData.Types [tpos - 1] = (byte) (pathData.Types [tpos - 1] | (byte) PathPointType.CloseSubpath | marker);
            break;
          case SEG_MOVETO:
            pathData.Types [tpos++] = (byte)((byte) PathPointType.Start | marker);
            pathData.Points [ppos++] = new PointF (Coords [cpos++], Coords [cpos++]);
            break;
          case SEG_LINETO:
            pathData.Types [tpos++] = (byte) ((byte) PathPointType.Line | marker);
            pathData.Points [ppos++] = new PointF (Coords [cpos++], Coords [cpos++]);
            break;
          case SEG_QUADTO:
            /*
              .net does not support Quadratic curves, so convert to Cubic according to http://pfaedit.sourceforge.net/bezier.html
                
              The end points of the cubic will be the same as the quadratic's.
              CP0 = QP0
              CP3 = QP2 

              The two control points for the cubic are:

              CP1 = QP0 + 2/3 *(QP1-QP0)
              CP2 = CP1 + 1/3 *(QP2-QP0) 
            */

            float x0 = Coords[cpos-2]; //QP0
            float y0 = Coords[cpos-1]; //QP0
      
            float x1 = x0 + (2/3 * (Coords [cpos++]-x0));
            float y1 = y0 + (2/3 * (Coords [cpos++]-y0));

            float x3 = Coords [cpos++]; //QP2
            float y3 = Coords [cpos++]; //QP2
            
            float x2 = x1 + (1/3 * (x3-x0));
            float y2 = y1 + (1/3 * (y3-y0));

            pathData.Types [tpos++] = (byte)(byte) PathPointType.Bezier;
            pathData.Points [ppos++] = new PointF (x1, y1);
            pathData.Types [tpos++] = (byte)(byte) PathPointType.Bezier;
            pathData.Points [ppos++] = new PointF (x2, y2);
            pathData.Types [tpos++] = (byte) ((byte)PathPointType.Bezier | marker);
            pathData.Points [ppos++] = new PointF (x3, y3);
            break;
          case SEG_CUBICTO:
            pathData.Types [tpos++] = (byte)(byte) PathPointType.Bezier3;
            pathData.Points [ppos++] = new PointF (Coords [cpos++], Coords [cpos++]);
            pathData.Types [tpos++] = (byte) PathPointType.Bezier3;
            pathData.Points [ppos++] = new PointF (Coords [cpos++], Coords [cpos++]);
            pathData.Types [tpos++] = (byte) ((byte)PathPointType.Bezier3 | marker);
            pathData.Points [ppos++] = new PointF (Coords [cpos++], Coords [cpos++]);
            break;
        }
      }
      return pathData;
    }

    #endregion // CachedData

    public void append(Shape s)
    {
      append (s, !LastFigureClosed);
    }

    #region GeneralPath

    public void append(PathIterator pi, bool connect) 
    {
      ClearCache ();
      float [] coords = new float [6];
      while (!pi.isDone ()) {
        switch (pi.currentSegment (coords)) {
          case SEG_MOVETO:
            if (!connect || _typesCount < 1 || _coordsCount < 2) {
              moveTo (coords [0], coords [1]);
              break;
            }
            if (_types [_typesCount - 1] != SEG_CLOSE &&
              _coords [_coordsCount - 2] == coords [0] &&
              _coords [_coordsCount - 1] == coords [1])
              break;  
            goto case SEG_LINETO;
          case SEG_LINETO:
            lineTo (coords [0], coords [1]);
            break;
          case SEG_QUADTO:
            quadTo (coords [0], coords [1], coords [2], coords [3]);
            break;
          case SEG_CUBICTO:
            curveTo (coords [0], coords [1], coords [2], coords [3], coords [4], coords [5]);
            break;
          case SEG_CLOSE:
            closePath ();
          break;
        }
        pi.next  ();
        connect = false;
      }
    }

    public void append(Shape s, bool connect) 
    {
      PathIterator pi = s.getPathIterator (null);
      append (pi,connect);
    }

    public object Clone() 
    {
      ExtendedGeneralPath copy = (ExtendedGeneralPath)MemberwiseClone ();
      copy._types = (sbyte []) _types.Clone ();
      copy._coords = (float []) _coords.Clone ();
      return copy;
    }

    public void closePath() 
    {
      ClearCache ();
      if (_typesCount == 0 || _types[_typesCount - 1] != SEG_CLOSE) {
        needRoom (1, 0, true);
        _types [_typesCount++] = SEG_CLOSE;
      }
    }

    public bool contains(double x, double y) 
    {      
      return GeneralPath.contains (x, y);
    }

    public bool contains(double x, double y, double w, double h) 
    {
      return GeneralPath.contains (x, y, w, h);
    }

    public bool contains(Point2D p) 
    {
      return contains (p.getX (), p.getY ());
    }

    public bool contains(Rectangle2D r) 
    {
      return contains (r.getX (), r.getY (), r.getWidth (), r.getHeight ());
    }

    public Shape createTransformedShape(AffineTransform at) 
    {
      ExtendedGeneralPath gp = (ExtendedGeneralPath) Clone ();
      if (at != null) {
        gp.transform (at);
      }
      return gp;
    }

    public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) 
    {
      ClearCache ();
      needRoom (1, 6, true);
      _types [_typesCount++] = SEG_CUBICTO;
      _coords [_coordsCount++] = x1;
      _coords [_coordsCount++] = y1;
      _coords [_coordsCount++] = x2;
      _coords [_coordsCount++] = y2;
      _coords [_coordsCount++] = x3;
      _coords [_coordsCount++] = y3;
    }

    public java.awt.Rectangle getBounds() 
    {
      return getBounds2D ().getBounds ();
    }

    public Rectangle2D getBounds2D() 
    {
      float x1, y1, x2, y2;
      int i = _coordsCount;
      if (i > 0) {
        y1 = y2 = _coords [--i];
        x1 = x2 = _coords [--i];
        while (i > 0) {
          float y = _coords [--i];
          float x = _coords [--i];
          if (x < x1) x1 = x;
          if (y < y1) y1 = y;
          if (x > x2) x2 = x;
          if (y > y2) y2 = y;
        }
      } 
      else {
        x1 = y1 = x2 = y2 = 0f;
      }
      return new Rectangle2D.Float (x1, y1, x2 - x1, y2 - y1);
    }

    public Point2D getCurrentPoint() 
    {
      if (_typesCount < 1 || _coordsCount < 2)
        return null;
      
      int index = _coordsCount;
      if (_types [_typesCount - 1] == SEG_CLOSE)
        for (int i = _typesCount - 2; i > 0; i--) {
          switch (_types [i]) {
            case SEG_MOVETO:
              //break loop;
              goto loopend;
            case SEG_LINETO:
              index -= 2;
              break;
            case SEG_QUADTO:
              index -= 4;
              break;
            case SEG_CUBICTO:
              index -= 6;
              break;
            case SEG_CLOSE:
              break;
          }
        }
      loopend:

      return new Point2D.Float (_coords [index - 2], _coords [index - 1]);
    }

    public PathIterator getPathIterator(AffineTransform at) {
      return new GeneralPathIterator (this, at);
    }

    public PathIterator getPathIterator(AffineTransform at, double flatness) {
      return new FlatteningPathIterator (getPathIterator (at), flatness);
    }

    public int getWindingRule() 
    {
      return _windingRule;
    }

    public bool intersects(double x, double y, double w, double h) 
    {
      return GeneralPath.intersects (x, y, w, h);
    }

    public bool intersects(Rectangle2D r) 
    {
      return intersects (r.getX (), r.getY (), r.getWidth (), r.getHeight ());
    }

    public void lineTo(float x, float y) 
    {
      ClearCache ();
      needRoom (1, 2, true);
      _types [_typesCount++] = SEG_LINETO;
      _coords [_coordsCount++] = x;
      _coords [_coordsCount++] = y;
    }

    public void moveTo(float x, float y) 
    {
      ClearCache ();
      if (_typesCount > 0 && _types [_typesCount - 1] == SEG_MOVETO) {
        _coords [_coordsCount - 2] = x;
        _coords [_coordsCount - 1] = y;
      } 
      else {
        needRoom (1, 2, false);
        _types [_typesCount++] = SEG_MOVETO;
        _coords [_coordsCount++] = x;
        _coords [_coordsCount++] = y;
      }
    }

    public void quadTo(float x1, float y1, float x2, float y2) 
    {
      // restore quadTo as cubic affects quality
      ClearCache ();
      needRoom (1, 4, true);
      _types [_typesCount++] = SEG_QUADTO;
      _coords [_coordsCount++] = x1;
      _coords [_coordsCount++] = y1;
      _coords [_coordsCount++] = x2;
      _coords [_coordsCount++] = y2;
    }

    public void reset() 
    {
      ClearCache ();
      _typesCount = 0;
      _coordsCount = 0;
    }

    public void setWindingRule(int rule) 
    {
      if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) {
        throw new IllegalArgumentException ("winding rule must be WIND_EVEN_ODD or WIND_NON_ZERO");
      }
      _windingRule = rule;
    }

    public void transform(AffineTransform at) 
    {
      transform(at, 0, CoordsCount);
    }

    public void transform(AffineTransform at, int startCoord, int numCoords) {
      ClearCache ();
      at.transform (_coords, startCoord, _coords, startCoord, numCoords/2);
    }

    private void needRoom(int newTypes, int newCoords, bool needMove) 
    {
      if (needMove && _typesCount == 0)
        throw new IllegalPathStateException ("missing initial moveto in path definition");
      
      int size = _coords.Length;
      if (_coordsCount + newCoords > size) {
        int grow = size;
        if (grow > EXPAND_MAX * 2)
          grow = EXPAND_MAX * 2;
        
        if (grow < newCoords)
          grow = newCoords;
        
        float [] arr = new float [size + grow];
        Array.Copy (_coords, 0, arr, 0, _coordsCount);
        _coords = arr;
      }
      size = _types.Length;
      if (_typesCount + newTypes > size) {
        int grow = size;
        if (grow > EXPAND_MAX)
          grow = EXPAND_MAX;
        
        if (grow < newTypes)
          grow = newTypes;
        
        sbyte [] arr = new sbyte [size + grow];
        Array.Copy (_types, 0, arr, 0, _typesCount);
        _types = arr;
      }
    }

    #endregion // GeneralPath

    public void SetMarkers()
    {
      ClearCache ();
      if (TypesCount > 0)
        Types [ TypesCount - 1] |= SEG_MARKER;
    }

    public void ClearMarkers()
    {
      ClearCache ();
      for (int i = 0; i < TypesCount; i++)
        Types [i] &= ~SEG_MARKER;
    }

    public void StartFigure ()
    {
      ClearCache ();
      if (TypesCount > 0)
        Types [TypesCount - 1] |= ExtendedGeneralPath.SEG_START;
    }

    private void Reset (int initialTypes, int initialCoords)
    {
      ClearCache ();
      _types = new sbyte [initialTypes];
      _coords = new float [initialCoords * 2];
      _typesCount = 0;
      _coordsCount = 0;
    }

    internal void Clear ()
    {
      Reset (INIT_SIZE, INIT_SIZE);
    }

    internal void Reverse ()
    {
      ClearCache ();
      // revert coordinates
      for (int i=0, max = CoordsCount / 2; i < max;) {
        int ix = i++;
        int iy = i++;
        int rix = CoordsCount - i;
        int riy = rix + 1;
        float tmpx = Coords [ix];
        float tmpy = Coords [iy];
        Coords [ix] = Coords [rix];
        Coords [iy] = Coords [riy];
        Coords [rix] = tmpx;
        Coords [riy] = tmpy;
      }

      // revert types
      sbyte [] newTypes = new sbyte [TypesCount];
      int oldIdx = 0;
      int newIdx = TypesCount - 1;
      int copyStart;
      int copyEnd;
      sbyte mask1 = 0;
      sbyte mask2 = 0;
      sbyte closeMask = 0;
      bool closedFigure = false;
      
      while (oldIdx < TypesCount) {
        // start copying after moveto
        copyStart = ++oldIdx;
        // continue to the next figure start
        while ((Types [oldIdx] != SEG_MOVETO) && (oldIdx < TypesCount))
          oldIdx++;

        copyEnd = oldIdx - 1;
        // check whenever current figure is closed
        if ((Types [oldIdx - 1] & SEG_CLOSE) != 0) {
          closedFigure = true;
          // close figure
          newTypes [newIdx--] = (sbyte)(SEG_CLOSE | mask1);
          mask1 = 0;
          mask2 = 0;
          // end copy one cell earlier
          copyEnd--;
          closeMask = (sbyte)(Types [oldIdx - 1] & (sbyte)SEG_MARKER);
        }
        else {
          mask2 = mask1;
          mask1 = 0;
        }

        // copy reverted "inner" types
        for(int i = copyStart; i <= copyEnd; i++) {
          newTypes [newIdx--] = (sbyte)((Types [i] & SEG_MASK) | mask2);
          mask2 = mask1;
          mask1 = (sbyte)(Types [i] & (sbyte)SEG_MARKER);
        }

        // copy moveto
        newTypes [newIdx--] = SEG_MOVETO;

        // pass close mask to the nex figure
        if (closedFigure) {
          mask1 = closeMask;
          closedFigure = false;
        }
      }

      _types = newTypes;
    }

    public PointF GetLastPoint ()
    {
      if (CoordsCount == 0)
        throw new System.ArgumentException ("Invalid parameter used.");

      return new PointF (Coords [CoordsCount - 2], Coords [CoordsCount - 1]);
    }

    #endregion //Methods

    #region Private helpers

#if DEBUG
    private void Print()
    {
      Console.WriteLine ("\n\n");
      float [] fpoints = _coords;
      int cpos = 0;
      for (int i=0; i < _typesCount; i++) {
        sbyte type = _types [i];
        string marker = String.Empty;
        if ((type & SEG_MARKER) != 0)
          marker = " | MARKER";

        switch (type & SEG_MASK) {
          case SEG_CLOSE:
            Console.WriteLine ("CLOSE {0}",marker);
            break;
          case SEG_MOVETO:
            Console.WriteLine("{0}{3} ({1},{2})","MOVETO", fpoints[cpos++], fpoints[cpos++], marker);
            break;
          case SEG_LINETO:
            Console.WriteLine("{0}{3} ({1},{2})","LINETO", fpoints[cpos++], fpoints[cpos++], marker);
            break;
          case SEG_QUADTO:
            Console.WriteLine("{0}{3} ({1},{2})","QUADTO", fpoints[cpos++], fpoints[cpos++], marker);
            Console.WriteLine("       ({1},{2})","QUADTO", fpoints[cpos++], fpoints[cpos++]);
            break;
          case SEG_CUBICTO:
            Console.WriteLine("{0}{3} ({1},{2})","CUBICTO", fpoints[cpos++], fpoints[cpos++], marker);
            Console.WriteLine("        ({1},{2})","CUBICTO", fpoints[cpos++], fpoints[cpos++]);
            Console.WriteLine("        ({1},{2})","CUBICTO", fpoints[cpos++], fpoints[cpos++]);
            break;
        }
      }
    }
#endif
    #endregion // Private helpers
     
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.