diff --git a/Filtering/vtkCellType.h b/Filtering/vtkCellType.h
index 4633f74..0661685 100644
--- a/Filtering/vtkCellType.h
+++ b/Filtering/vtkCellType.h
@@ -29,7 +29,8 @@
 // GetCell() and vtkGenericCell::SetCellType(). Also, to do the job right,
 // you'll also have to modify some filters (vtkGeometryFilter...) and
 // regression tests (example scripts) to reflect the new cell addition.
-// Also, make sure to update vtkCellTypesStrings in vtkCellTypes.cxx.
+// Also, make sure to update vtkCellTypesStrings in vtkCellTypes.cxx
+// and the vtkCellTypes::IsLinear method in vtkCellTypes.h.
 
 // .SECTION Caveats
 // An unstructured grid stores the types of its cells as a
diff --git a/Filtering/vtkCellTypes.h b/Filtering/vtkCellTypes.h
index 08015d2..b56132c 100644
--- a/Filtering/vtkCellTypes.h
+++ b/Filtering/vtkCellTypes.h
@@ -118,6 +118,13 @@ public:
   // defined in vtkCellType.h)
   static int GetTypeIdFromClassName(const char* classname);
 
+  // Description:
+  // This convenience method is a fast check to determine if a cell type
+  // represents a linear or nonlinear cell.  This is generally much more
+  // efficient than getting the appropriate vtkCell and checking its IsLinear
+  // method.
+  static int IsLinear(unsigned char type);
+
 protected:
   vtkCellTypes();
   ~vtkCellTypes();
@@ -148,5 +155,11 @@ inline int vtkCellTypes::IsType(unsigned char type)
   return 0;
 }
 
+//-----------------------------------------------------------------------------
+inline int vtkCellTypes::IsLinear(unsigned char type)
+{
+  return ((type <= 20) || (type == VTK_CONVEX_POINT_SET));
+}
+
 
 #endif
diff --git a/Filtering/vtkDataSetAttributes.cxx b/Filtering/vtkDataSetAttributes.cxx
index d5739b0..67505f7 100644
--- a/Filtering/vtkDataSetAttributes.cxx
+++ b/Filtering/vtkDataSetAttributes.cxx
@@ -51,7 +51,9 @@ const char vtkDataSetAttributes
   "TCoords",
   "Tensors",
   "GlobalIds",
-  "PedigreeIds" };
+  "PedigreeIds",
+  "EdgeFlag"
+};
 
 const char vtkDataSetAttributes
 ::LongAttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][35] =
@@ -61,7 +63,9 @@ const char vtkDataSetAttributes
   "vtkDataSetAttributes::TCOORDS",
   "vtkDataSetAttributes::TENSORS",
   "vtkDataSetAttributes::GLOBALIDS",
-  "vtkDataSetAttributes::PEDIGREEIDS" };
+  "vtkDataSetAttributes::PEDIGREEIDS",
+  "vtkDataSetAttributes::EDGEFLAG"
+};
 
 //--------------------------------------------------------------------------
 // Construct object with copying turned on for all data.
@@ -1073,6 +1077,7 @@ const int vtkDataSetAttributes
   3,
   9,
   1,
+  1,
   1};
 
 //--------------------------------------------------------------------------
@@ -1085,6 +1090,7 @@ const int vtkDataSetAttributes
   MAX,
   EXACT,
   EXACT,
+  EXACT,
   EXACT};
 
 //--------------------------------------------------------------------------
diff --git a/Filtering/vtkDataSetAttributes.h b/Filtering/vtkDataSetAttributes.h
index 33051cc..187fe54 100644
--- a/Filtering/vtkDataSetAttributes.h
+++ b/Filtering/vtkDataSetAttributes.h
@@ -90,6 +90,7 @@ public:
     TENSORS=4,
     GLOBALIDS=5,
     PEDIGREEIDS=6,
+    EDGEFLAG=7,
     NUM_ATTRIBUTES
   };
 
@@ -165,6 +166,7 @@ public:
   //  vtkDataSetAttributes::TENSORS = 4
   //  vtkDataSetAttributes::GLOBALIDS = 5
   //  vtkDataSetAttributes::PEDIGREEIDS = 6
+  //  vtkDataSetAttributes::EDGEFLAG = 7
   // Returns the index of the array if succesful, -1 if the array 
   // is not in the list of arrays.
   int SetActiveAttribute(const char* name, int attributeType);
diff --git a/Graphics/vtkDataSetSurfaceFilter.cxx b/Graphics/vtkDataSetSurfaceFilter.cxx
index 18c7c0a..d4f189d 100644
--- a/Graphics/vtkDataSetSurfaceFilter.cxx
+++ b/Graphics/vtkDataSetSurfaceFilter.cxx
@@ -16,8 +16,10 @@
 
 #include "vtkCellArray.h"
 #include "vtkCellData.h"
+#include "vtkDoubleArray.h"
 #include "vtkGenericCell.h"
 #include "vtkHexahedron.h"
+#include "vtkIdTypeArray.h"
 #include "vtkInformation.h"
 #include "vtkInformationVector.h"
 #include "vtkMergePoints.h"
@@ -26,18 +28,19 @@
 #include "vtkPolyData.h"
 #include "vtkPyramid.h"
 #include "vtkRectilinearGrid.h"
-#include "vtkStructuredGrid.h"
-#include "vtkUniformGrid.h"
 #include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkStructuredGrid.h"
 #include "vtkStructuredGridGeometryFilter.h"
 #include "vtkStructuredPoints.h"
 #include "vtkTetra.h"
+#include "vtkUniformGrid.h"
 #include "vtkUnsignedCharArray.h"
 #include "vtkUnstructuredGrid.h"
 #include "vtkVoxel.h"
 #include "vtkWedge.h"
-#include "vtkIdTypeArray.h"
 
+#include <vtkstd/algorithm>
+#include <vtksys/hash_map.hxx>
 
 static int sizeofFastQuad(int numPts)
 {
@@ -45,6 +48,40 @@ static int sizeofFastQuad(int numPts)
   return static_cast<int>(sizeof(vtkFastGeomQuad)+(numPts-4)*sizeof(vtkIdType));
 }
 
+
+class vtkDataSetSurfaceFilter::vtkEdgeInterpolationMap
+{
+public:
+  void AddEdge(vtkIdType endpoint1, vtkIdType endpoint2, vtkIdType midpoint) {
+    if (endpoint1 > endpoint2) vtkstd::swap(endpoint1, endpoint2);
+    Map.insert(vtkstd::make_pair(vtkstd::make_pair(endpoint1, endpoint2),
+                                 midpoint));
+  }
+  vtkIdType FindEdge(vtkIdType endpoint1, vtkIdType endpoint2) {
+    if (endpoint1 > endpoint2) vtkstd::swap(endpoint1, endpoint2);
+    MapType::iterator iter = Map.find(vtkstd::make_pair(endpoint1, endpoint2));
+    if (iter != Map.end())
+      {
+      return iter->second;
+      }
+    else
+      {
+      return -1;
+      }
+  }
+
+protected:
+  struct HashFunction {
+  public:
+    size_t operator()(vtkstd::pair<vtkIdType,vtkIdType> edge) const {
+      return static_cast<size_t>(edge.first + edge.second);
+    }
+  };
+  typedef vtksys::hash_map<vtkstd::pair<vtkIdType, vtkIdType>, vtkIdType,
+                           HashFunction> MapType;
+  MapType Map;
+};
+
 vtkCxxRevisionMacro(vtkDataSetSurfaceFilter, "1.75");
 vtkStandardNewMacro(vtkDataSetSurfaceFilter);
 
@@ -53,6 +90,7 @@ vtkDataSetSurfaceFilter::vtkDataSetSurfaceFilter()
 {
   this->QuadHash = NULL;
   this->PointMap = NULL;
+  this->EdgeMap = NULL;
   this->QuadHashLength = 0;
   this->UseStrips = 0;
   this->NumberOfNewCells = 0;
@@ -70,6 +108,10 @@ vtkDataSetSurfaceFilter::vtkDataSetSurfaceFilter()
   this->PassThroughPointIds = 0;
   this->OriginalCellIds = NULL;
   this->OriginalPointIds = NULL;
+  this->OriginalCellIdsName = NULL;
+  this->OriginalPointIdsName = NULL;
+
+  this->NonlinearSubdivisionLevel = 1;
 }
 
 //----------------------------------------------------------------------------
@@ -84,6 +126,8 @@ vtkDataSetSurfaceFilter::~vtkDataSetSurfaceFilter()
     this->OriginalCellIds->Delete();
     this->OriginalCellIds = NULL;
     }
+  this->SetOriginalCellIdsName(NULL);
+  this->SetOriginalPointIdsName(NULL);
 }
 
 //----------------------------------------------------------------------------
@@ -175,7 +219,7 @@ int vtkDataSetSurfaceFilter::RequestData(
         {
         //make a 1:1 mapping
         this->OriginalCellIds = vtkIdTypeArray::New();
-        this->OriginalCellIds->SetName("vtkOriginalCellIds");
+        this->OriginalCellIds->SetName(this->GetOriginalCellIdsName());
         this->OriginalCellIds->SetNumberOfComponents(1);
         vtkCellData *outputCD = output->GetCellData();
         outputCD->AddArray(this->OriginalCellIds);        
@@ -192,7 +236,7 @@ int vtkDataSetSurfaceFilter::RequestData(
         {
         //make a 1:1 mapping
         this->OriginalPointIds = vtkIdTypeArray::New();
-        this->OriginalPointIds->SetName("vtkOriginalPointIds");
+        this->OriginalPointIds->SetName(this->GetOriginalPointIdsName());
         this->OriginalPointIds->SetNumberOfComponents(1);
         vtkPointData *outputPD = output->GetPointData();
         outputPD->AddArray(this->OriginalPointIds);        
@@ -335,14 +379,14 @@ int vtkDataSetSurfaceFilter::StructuredExecute(vtkDataSet *input,
   if (this->PassThroughCellIds)
     {
     this->OriginalCellIds = vtkIdTypeArray::New();
-    this->OriginalCellIds->SetName("vtkOriginalCellIds");
+    this->OriginalCellIds->SetName(this->GetOriginalCellIdsName());
     this->OriginalCellIds->SetNumberOfComponents(1);
     output->GetCellData()->AddArray(this->OriginalCellIds);
     }
   if (this->PassThroughPointIds)
     {
     this->OriginalPointIds = vtkIdTypeArray::New();
-    this->OriginalPointIds->SetName("vtkOriginalPointIds");
+    this->OriginalPointIds->SetName(this->GetOriginalPointIdsName());
     this->OriginalPointIds->SetNumberOfComponents(1);
     output->GetPointData()->AddArray(this->OriginalPointIds);
     }
@@ -894,6 +938,11 @@ void vtkDataSetSurfaceFilter::PrintSelf(ostream& os, vtkIndent indent)
   os << indent << "PassThroughCellIds: " << (this->PassThroughCellIds ? "On\n" : "Off\n");
   os << indent << "PassThroughPointIds: " << (this->PassThroughPointIds ? "On\n" : "Off\n");
 
+  os << indent << "OriginalCellIdsName: " << this->GetOriginalCellIdsName() << endl;
+  os << indent << "OriginalPointIdsName: " << this->GetOriginalPointIdsName() << endl;
+
+  os << indent << "NonlinearSubdivisionLevel: "
+     << this->NonlinearSubdivisionLevel << endl;
 }
 
 //========================================================================
@@ -927,7 +976,6 @@ int vtkDataSetSurfaceFilter::UnstructuredGridExecute(vtkDataSet *dataSetInput,
   vtkCellData *cd = input->GetCellData();
   vtkPointData *outputPD = output->GetPointData();
   vtkCellData *outputCD = output->GetCellData();
-  vtkIdType outPts[6];
   vtkFastGeomQuad *q;
   unsigned char* cellTypes = input->GetCellTypesArray()->GetPointer(0);
 
@@ -936,9 +984,19 @@ int vtkDataSetSurfaceFilter::UnstructuredGridExecute(vtkDataSet *dataSetInput,
   vtkPoints *coords;
   vtkCell *face;
   int flag2D = 0;
+
+  // These are for subdividing quadratic cells
+  vtkDoubleArray *parametricCoords;
+  vtkDoubleArray *parametricCoords2;
+  vtkIdList *outPts;
+  vtkIdList *outPts2;
   
   pts = vtkIdList::New();  
   coords = vtkPoints::New();
+  parametricCoords = vtkDoubleArray::New();
+  parametricCoords2 = vtkDoubleArray::New();
+  outPts = vtkIdList::New();
+  outPts2 = vtkIdList::New();
   // might not be necessary to set the data type for coords
   // but certainly safer to do so
   coords->SetDataType(input->GetPoints()->GetData()->GetDataType());
@@ -957,21 +1015,28 @@ int vtkDataSetSurfaceFilter::UnstructuredGridExecute(vtkDataSet *dataSetInput,
   newVerts = vtkCellArray::New();
   newLines = vtkCellArray::New();
 
-  outputPD->CopyGlobalIdsOn();
-  outputPD->CopyAllocate(inputPD, numPts, numPts/2);
+  if (this->NonlinearSubdivisionLevel <= 1)
+    {
+    outputPD->CopyGlobalIdsOn();
+    outputPD->CopyAllocate(inputPD, numPts, numPts/2);
+    }
+  else
+    {
+    outputPD->InterpolateAllocate(inputPD, numPts, numPts/2);
+    }
   outputCD->CopyGlobalIdsOn();
   outputCD->CopyAllocate(inputCD, numCells, numCells/2);
 
   if (this->PassThroughCellIds)
     {
     this->OriginalCellIds = vtkIdTypeArray::New();
-    this->OriginalCellIds->SetName("vtkOriginalCellIds");
+    this->OriginalCellIds->SetName(this->GetOriginalCellIdsName());
     this->OriginalCellIds->SetNumberOfComponents(1);
     }
   if (this->PassThroughPointIds)
     {
     this->OriginalPointIds = vtkIdTypeArray::New();
-    this->OriginalPointIds->SetName("vtkOriginalPointIds");
+    this->OriginalPointIds->SetName(this->GetOriginalPointIdsName());
     this->OriginalPointIds->SetNumberOfComponents(1);
     }
 
@@ -1180,14 +1245,40 @@ int vtkDataSetSurfaceFilter::UnstructuredGridExecute(vtkDataSet *dataSetInput,
             if ( cellIds->GetNumberOfIds() <= 0)
               {
               // FIXME: Face could not be consistent. vtkOrderedTriangulator is a better option
-              face->Triangulate(0,pts,coords);
-              for (i=0; i < pts->GetNumberOfIds(); i+=3)
+              if (this->NonlinearSubdivisionLevel >= 1)
                 {
-                this->InsertTriInHash(pts->GetId(i), pts->GetId(i+1),
-                                      pts->GetId(i+2), cellId);
+                // TODO: Handle NonlinearSubdivisionLevel > 1 correctly.
+                face->Triangulate(0,pts,coords);
+                for (i=0; i < pts->GetNumberOfIds(); i+=3)
+                  {
+                  this->InsertTriInHash(pts->GetId(i), pts->GetId(i+1),
+                                        pts->GetId(i+2), cellId);
+                  }
                 }
-              }
-            }
+              else
+                {
+                switch (face->GetCellType())
+                  {
+                  case VTK_QUADRATIC_TRIANGLE:
+                    this->InsertTriInHash(face->PointIds->GetId(0),
+                                          face->PointIds->GetId(1),
+                                          face->PointIds->GetId(2), cellId);
+                    break;
+                  case VTK_QUADRATIC_QUAD:
+                  case VTK_BIQUADRATIC_QUAD:
+                  case VTK_QUADRATIC_LINEAR_QUAD:
+                    this->InsertQuadInHash(face->PointIds->GetId(0),
+                                           face->PointIds->GetId(1),
+                                           face->PointIds->GetId(2),
+                                           face->PointIds->GetId(3), cellId);
+                    break;
+                  default:
+                    vtkWarningMacro(<< "Encountered unknown nonlinear face.");
+                    break;
+                  } // switch cell type
+                } // subdivision level
+              } // cell has ids
+            } // for faces
           cellIds->Delete();
           } //3d cell
         } //nonlinear cell
@@ -1211,6 +1302,25 @@ int vtkDataSetSurfaceFilter::UnstructuredGridExecute(vtkDataSet *dataSetInput,
     // Move to the next cell.
     cellPointer += (1 + *cellPointer);
 
+    // If we have a quadratic face and our subdivision level is zero, just treat
+    // it as a linear cell.  This should work so long as the first points of the
+    // quadratic cell correspond to all those of the equivalent linear cell
+    // (which all the current definitions do).
+    if (this->NonlinearSubdivisionLevel < 1)
+      {
+      switch (cellType)
+        {
+        case VTK_QUADRATIC_TRIANGLE:
+          cellType = VTK_TRIANGLE;  numCellPts = 3;
+          break;
+        case VTK_QUADRATIC_QUAD:
+        case VTK_BIQUADRATIC_QUAD:
+        case VTK_QUADRATIC_LINEAR_QUAD:
+          cellType = VTK_POLYGON;  numCellPts = 4;
+          break;
+        }
+      }
+
     // A couple of common cases to see if things go faster.
     if (cellType == VTK_PIXEL)
       { // Do we really want to insert the 2D cells into a hash?
@@ -1263,14 +1373,99 @@ int vtkDataSetSurfaceFilter::UnstructuredGridExecute(vtkDataSet *dataSetInput,
            || cellType == VTK_BIQUADRATIC_QUAD
            || cellType == VTK_QUADRATIC_LINEAR_QUAD)
       {
+      // Note: we should not be here if this->NonlinearSubdivisionLevel is less
+      // than 1.  See the check above.
       input->GetCell( cellId, cell );
       cell->Triangulate( 0, pts, coords );
-      for ( i=0; i < pts->GetNumberOfIds(); i+=3 )
+      // Copy the level 1 subdivision points (which also exist in the input and
+      // can therefore just be copied over.  Note that the output of Triangulate
+      // records triangles in pts where each 3 points defines a triangle.  We
+      // will keep this invariant and also keep the same invariant in
+      // parametericCoords and outPts later.
+      outPts->Reset();
+      for ( i=0; i < pts->GetNumberOfIds(); i++ )
+        {
+        vtkIdType op;
+        op = this->GetOutputPointId(pts->GetId(i), input, newPts, outputPD);
+        outPts->InsertNextId(op);
+        }
+      // Do any further subdivision if necessary.
+      if (this->NonlinearSubdivisionLevel > 1)
+        {
+        // We are going to need parametric coordinates to further subdivide.
+        double *pc = cell->GetParametricCoords();
+        parametricCoords->Reset();
+        parametricCoords->SetNumberOfComponents(3);
+        for (i = 0; i < pts->GetNumberOfIds(); i++)
+          {
+          vtkIdType ptId = pts->GetId(i);
+          vtkIdType cellPtId;
+          for (cellPtId = 0; cell->GetPointId(cellPtId) != ptId; cellPtId++);
+          parametricCoords->InsertNextTupleValue(pc + 3*cellPtId);
+          }
+        // Subdivide these triangles as many more times as necessary.  Remember
+        // that we have already done the first subdivision.
+        for (j = 1; j < this->NonlinearSubdivisionLevel; j++)
+          {
+          parametricCoords2->Reset();
+          parametricCoords2->SetNumberOfComponents(3);
+          outPts2->Reset();
+          // Each triangle will be split into 4 triangles.
+          for (i = 0; i < outPts->GetNumberOfIds(); i += 3)
+            {
+            // Hold the input point ids and parametric coordinates.  First 3
+            // indices are the original points.  Second three are the midpoints
+            // in the edges (0,1), (1,2) and (2,0), respectively (see comment
+            // below).
+            vtkIdType inPts[6];
+            double inParamCoords[6][3];
+            int k;
+            for (k = 0; k < 3; k++)
+              {
+              inPts[k] = outPts->GetId(i+k);
+              parametricCoords->GetTupleValue(i+k, inParamCoords[k]);
+              }
+            for (k = 3; k < 6; k++)
+              {
+              int pt1 = k-3;
+              int pt2 = (pt1 < 2) ? (pt1 + 1) : 0;
+              inParamCoords[k][0] = 0.5*(inParamCoords[pt1][0] + inParamCoords[pt2][0]);
+              inParamCoords[k][1] = 0.5*(inParamCoords[pt1][1] + inParamCoords[pt2][1]);
+              inParamCoords[k][2] = 0.5*(inParamCoords[pt1][2] + inParamCoords[pt2][2]);
+              inPts[k] = GetInterpolatedPointId(inPts[pt1], inPts[pt2],
+                                                input, cell,
+                                                inParamCoords[k], newPts,
+                                                outputPD);
+              }
+            //       * 0
+            //      / \        Use the 6 points recorded
+            //     /   \       in inPts and inParamCoords
+            //  3 *-----* 5    to create the 4 triangles
+            //   / \   / \     shown here.
+            //  /   \ /   \    .
+            // *-----*-----*
+            // 1     4     2
+            const int subtriangles[12] = {0,3,5,   3,1,4,   3,4,5,   5,4,2};
+            for (k = 0; k < 12; k++)
+              {
+              int localId = subtriangles[k];
+              outPts2->InsertNextId(inPts[localId]);
+              parametricCoords2->InsertNextTupleValue(inParamCoords[localId]);
+              }
+            } // Iterate over triangles
+          // Now that we have recorded the subdivided triangles in outPts2 and
+          // parametricCoords2, swap them with outPts and parametricCoords to
+          // make them the current ones.
+          vtkstd::swap(outPts, outPts2);
+          vtkstd::swap(parametricCoords, parametricCoords2);
+          } // Iterate over subdivision levels
+        } // If further subdivision
+
+      // Now that we have done all the subdivisions and created all of the
+      // points, record the triangles.
+      for (i = 0; i < outPts->GetNumberOfIds(); i += 3)
         {
-        outPts[0] = this->GetOutputPointId( pts->GetId(i),   input, newPts, outputPD );
-        outPts[1] = this->GetOutputPointId( pts->GetId(i+1), input, newPts, outputPD );
-        outPts[2] = this->GetOutputPointId( pts->GetId(i+2), input, newPts, outputPD );
-        newPolys->InsertNextCell( 3, outPts );
+        newPolys->InsertNextCell(3, outPts->GetPointer(i));
         this->RecordOrigCellId(this->NumberOfNewCells, cellId);
         outputCD->CopyData(cd, cellId, this->NumberOfNewCells++);
         }
@@ -1306,6 +1501,10 @@ int vtkDataSetSurfaceFilter::UnstructuredGridExecute(vtkDataSet *dataSetInput,
   cell->Delete();
   coords->Delete();
   pts->Delete();
+  parametricCoords->Delete();
+  parametricCoords2->Delete();
+  outPts->Delete();
+  outPts2->Delete();
 
   output->SetPoints(newPts);
   newPts->Delete();
@@ -1367,6 +1566,7 @@ void vtkDataSetSurfaceFilter::InitializeQuadHash(vtkIdType numPoints)
     this->QuadHash[i] = NULL;
     this->PointMap[i] = -1;
     }
+  this->EdgeMap = new vtkEdgeInterpolationMap;
 }
 
 //----------------------------------------------------------------------------
@@ -1386,6 +1586,8 @@ void vtkDataSetSurfaceFilter::DeleteQuadHash()
   this->QuadHashLength = 0;
   delete [] this->PointMap;
   this->PointMap = NULL;
+  delete this->EdgeMap;
+  this->EdgeMap = NULL;
 }
 
 //----------------------------------------------------------------------------
@@ -1781,6 +1983,34 @@ vtkIdType vtkDataSetSurfaceFilter::GetOutputPointId(vtkIdType inPtId,
   return outPtId;
 }
 
+//-----------------------------------------------------------------------------
+vtkIdType vtkDataSetSurfaceFilter::GetInterpolatedPointId(vtkIdType edgePtA,
+                                                          vtkIdType edgePtB,
+                                                          vtkDataSet *input,
+                                                          vtkCell *cell,
+                                                          double pcoords[3],
+                                                          vtkPoints *outPts,
+                                                          vtkPointData *outPD)
+{
+  vtkIdType outPtId;
+
+  outPtId = this->EdgeMap->FindEdge(edgePtA, edgePtB);
+  if (outPtId == -1)
+    {
+    int subId = -1;
+    double wcoords[3];
+    double weights[100];  // Any reason to need more?
+    cell->EvaluateLocation(subId, pcoords, wcoords, weights);
+    outPtId = outPts->InsertNextPoint(wcoords);
+    outPD->InterpolatePoint(input->GetPointData(), outPtId,
+                            cell->GetPointIds(), weights);
+    this->RecordOrigPointId(outPtId, -1);
+    this->EdgeMap->AddEdge(edgePtA, edgePtB, outPtId);
+    }
+
+  return outPtId;
+}
+
 //----------------------------------------------------------------------------
 void vtkDataSetSurfaceFilter::RecordOrigCellId(vtkIdType destIndex, 
                                                vtkIdType originalId)
diff --git a/Graphics/vtkDataSetSurfaceFilter.h b/Graphics/vtkDataSetSurfaceFilter.h
index f089c97..80a41c4 100644
--- a/Graphics/vtkDataSetSurfaceFilter.h
+++ b/Graphics/vtkDataSetSurfaceFilter.h
@@ -80,6 +80,34 @@ public:
   vtkGetMacro(PassThroughPointIds,int);
   vtkBooleanMacro(PassThroughPointIds,int);
 
+  // Description:
+  // If PassThroughCellIds or PassThroughPointIds is on, then these ivars
+  // control the name given to the field in which the ids are written into.  If
+  // set to NULL, then vtkOriginalCellIds or vtkOriginalPointIds (the default)
+  // is used, respectively.
+  vtkSetStringMacro(OriginalCellIdsName);
+  virtual const char *GetOriginalCellIdsName() {
+    return (  this->OriginalCellIdsName
+            ? this->OriginalCellIdsName : "vtkOriginalCellIds");
+  }
+  vtkSetStringMacro(OriginalPointIdsName);
+  virtual const char *GetOriginalPointIdsName() {
+    return (  this->OriginalPointIdsName
+            ? this->OriginalPointIdsName : "vtkOriginalPointIds");
+  }
+
+  // Description:
+  // If the input is an unstructured grid with nonlinear faces, this parameter
+  // determines how many times the face is subdivided into linear faces.  If 0,
+  // the output is the equivalent of its linear couterpart (and the midpoints
+  // determining the nonlinear interpolation are discarded).  If 1 (the
+  // default), the nonlinear face is triangulated based on the midpoints.  If
+  // greater than 1, the triangulated pieces are recursively subdivided to reach
+  // the desired subdivision.  Setting the value to greater than 1 may cause
+  // some point data to not be passed even if no nonlinear faces exist.  This
+  // option has no effect if the input is not an unstructured grid.
+  vtkSetMacro(NonlinearSubdivisionLevel, int);
+  vtkGetMacro(NonlinearSubdivisionLevel, int);
 
   // Description:
   // Direct access methods that can be used to use the this class as an
@@ -143,6 +171,14 @@ protected:
   vtkIdType *PointMap;
   vtkIdType GetOutputPointId(vtkIdType inPtId, vtkDataSet *input, 
                              vtkPoints *outPts, vtkPointData *outPD);
+//BTX
+  class vtkEdgeInterpolationMap;
+//ETX
+  vtkEdgeInterpolationMap *EdgeMap;
+  vtkIdType GetInterpolatedPointId(vtkIdType edgePtA, vtkIdType edgePtB,
+                                   vtkDataSet *input, vtkCell *cell,
+                                   double pcoords[3], vtkPoints *outPts,
+                                   vtkPointData *outPD);
   
   vtkIdType NumberOfNewCells;
   
@@ -164,10 +200,14 @@ protected:
   void RecordOrigCellId(vtkIdType newIndex, vtkIdType origId);
   virtual void RecordOrigCellId(vtkIdType newIndex, vtkFastGeomQuad *quad);
   vtkIdTypeArray *OriginalCellIds;
+  char *OriginalCellIdsName;
 
   int PassThroughPointIds;
   void RecordOrigPointId(vtkIdType newIndex, vtkIdType origId);
   vtkIdTypeArray *OriginalPointIds;
+  char *OriginalPointIdsName;
+
+  int NonlinearSubdivisionLevel;
 
 private:
   vtkDataSetSurfaceFilter(const vtkDataSetSurfaceFilter&);  // Not implemented.
diff --git a/Graphics/vtkUnstructuredGridGeometryFilter.cxx b/Graphics/vtkUnstructuredGridGeometryFilter.cxx
index d6ffb0a..7065491 100644
--- a/Graphics/vtkUnstructuredGridGeometryFilter.cxx
+++ b/Graphics/vtkUnstructuredGridGeometryFilter.cxx
@@ -27,6 +27,7 @@
 #include "vtkPolyData.h"
 #include "vtkPyramid.h"
 #include "vtkPentagonalPrism.h"
+#include "vtkSmartPointer.h"
 #include "vtkStreamingDemandDrivenPipeline.h"
 #include "vtkStructuredGrid.h"
 #include "vtkTetra.h"
@@ -718,6 +719,11 @@ vtkUnstructuredGridGeometryFilter::vtkUnstructuredGridGeometryFilter()
   this->CellClipping = 0;
   this->ExtentClipping = 0;
 
+  this->PassThroughCellIds = 0;
+  this->PassThroughPointIds = 0;
+  this->OriginalCellIdsName = NULL;
+  this->OriginalPointIdsName = NULL;
+
   this->Merging = 1;
   this->Locator = NULL;
   
@@ -732,6 +738,9 @@ vtkUnstructuredGridGeometryFilter::~vtkUnstructuredGridGeometryFilter()
     this->Locator->UnRegister(this);
     this->Locator = NULL;
     }
+
+  this->SetOriginalCellIdsName(NULL);
+  this->SetOriginalPointIdsName(NULL);
 }
 
 //-----------------------------------------------------------------------------
@@ -905,8 +914,24 @@ int vtkUnstructuredGridGeometryFilter::RequestData(
   newPts->Allocate(numPts);
   output->Allocate(numCells);
   outputPD->CopyAllocate(pd,numPts,numPts/2);
+  vtkSmartPointer<vtkIdTypeArray> originalPointIds;
+  if (this->PassThroughPointIds)
+    {
+    originalPointIds = vtkSmartPointer<vtkIdTypeArray>::New();
+    originalPointIds->SetName(this->GetOriginalPointIdsName());
+    originalPointIds->SetNumberOfComponents(1);
+    originalPointIds->Allocate(numPts, numPts/2);
+    }
  
   outputCD->CopyAllocate(cd,numCells,numCells/2);
+  vtkSmartPointer<vtkIdTypeArray> originalCellIds;
+  if (this->PassThroughCellIds)
+    {
+    originalCellIds = vtkSmartPointer<vtkIdTypeArray>::New();
+    originalCellIds->SetName(this->GetOriginalCellIdsName());
+    originalCellIds->SetNumberOfComponents(1);
+    originalCellIds->Allocate(numCells, numCells/2);
+    }
 
   vtkIdType *pointMap=0;
   
@@ -979,6 +1004,10 @@ int vtkUnstructuredGridGeometryFilter::RequestData(
             if ( this->Locator->InsertUniquePoint(x, newPtId) )
               {
               outputPD->CopyData(pd,ptId,newPtId);
+              if (this->PassThroughPointIds)
+                {
+                originalPointIds->InsertValue(newPtId, ptId);
+                }
               }
             cellIds->InsertNextId(newPtId);
             }
@@ -993,6 +1022,10 @@ int vtkUnstructuredGridGeometryFilter::RequestData(
               newPtId=newPts->InsertNextPoint(inPts->GetPoint(ptId));
               pointMap[ptId]=newPtId;
               outputPD->CopyData(pd, ptId, newPtId);
+              if (this->PassThroughPointIds)
+                {
+                originalPointIds->InsertValue(newPtId, ptId);
+                }
               }
             cellIds->InsertNextId(pointMap[ptId]);
             }
@@ -1000,6 +1033,10 @@ int vtkUnstructuredGridGeometryFilter::RequestData(
         
         newCellId = output->InsertNextCell(cellType,cellIds);
         outputCD->CopyData(cd, cellId, newCellId);
+        if (this->PassThroughCellIds)
+          {
+          originalCellIds->InsertValue(newCellId, cellId);
+          }
         }
       else // added the faces to the hashtable
         {
@@ -1378,6 +1415,10 @@ int vtkUnstructuredGridGeometryFilter::RequestData(
           if ( this->Locator->InsertUniquePoint(x, newPtId) )
             {
             outputPD->CopyData(pd,ptId,newPtId);
+            if (this->PassThroughPointIds)
+              {
+              originalPointIds->InsertValue(newPtId, ptId);
+              }
             }
           cellIds->InsertNextId(newPtId);
           }
@@ -1392,6 +1433,10 @@ int vtkUnstructuredGridGeometryFilter::RequestData(
             newPtId=newPts->InsertNextPoint(inPts->GetPoint(ptId));
             pointMap[ptId]=newPtId;
             outputPD->CopyData(pd, ptId, newPtId);
+            if (this->PassThroughPointIds)
+              {
+              originalPointIds->InsertValue(newPtId, ptId);
+              }
             }
           cellIds->InsertNextId(pointMap[ptId]);
           }
@@ -1399,6 +1444,10 @@ int vtkUnstructuredGridGeometryFilter::RequestData(
       
       newCellId = output->InsertNextCell(cellType,cellIds);
       outputCD->CopyData(cd, cellId, newCellId);
+      if (this->PassThroughCellIds)
+        {
+        originalCellIds->InsertValue(newCellId, cellId);
+        }
       }
     cursor.Next();
     }
@@ -1416,6 +1465,15 @@ int vtkUnstructuredGridGeometryFilter::RequestData(
   newPts->Delete();
   
 //  output->SetCells(types,locs,conn);
+
+  if (this->PassThroughPointIds)
+    {
+    outputPD->AddArray(originalPointIds);
+    }
+  if (this->PassThroughCellIds)
+    {
+    outputCD->AddArray(originalCellIds);
+    }
   
   if(!this->Merging && this->Locator)
     {
@@ -1491,6 +1549,12 @@ void vtkUnstructuredGridGeometryFilter::PrintSelf(ostream& os,
   os << indent << "CellClipping: " << (this->CellClipping ? "On\n" : "Off\n");
   os << indent << "ExtentClipping: " << (this->ExtentClipping ? "On\n" : "Off\n");
 
+  os << indent << "PassThroughCellIds: " << this->PassThroughCellIds << endl;
+  os << indent << "PassThroughPointIds: " << this->PassThroughPointIds << endl;
+
+  os << indent << "OriginalCellIdsName: " << this->GetOriginalCellIdsName() << endl;
+  os << indent << "OriginalPointIdsName: " << this->GetOriginalPointIdsName() << endl;
+
   os << indent << "Merging: " << (this->Merging ? "On\n" : "Off\n");
   if ( this->Locator )
     {
diff --git a/Graphics/vtkUnstructuredGridGeometryFilter.h b/Graphics/vtkUnstructuredGridGeometryFilter.h
index 66b28d8..4d73db9 100644
--- a/Graphics/vtkUnstructuredGridGeometryFilter.h
+++ b/Graphics/vtkUnstructuredGridGeometryFilter.h
@@ -107,6 +107,36 @@ public:
   vtkBooleanMacro(Merging,int);
 
   // Description:
+  // If on, the output polygonal dataset will have a celldata array that
+  // holds the cell index of the original 3D cell that produced each output
+  // cell. This is useful for cell picking. The default is off to conserve
+  // memory. Note that PassThroughCellIds will be ignored if UseStrips is on,
+  // since in that case each tringle strip can represent more than on of the
+  // input cells.
+  vtkSetMacro(PassThroughCellIds,int);
+  vtkGetMacro(PassThroughCellIds,int);
+  vtkBooleanMacro(PassThroughCellIds,int);
+  vtkSetMacro(PassThroughPointIds,int);
+  vtkGetMacro(PassThroughPointIds,int);
+  vtkBooleanMacro(PassThroughPointIds,int);
+
+  // Description:
+  // If PassThroughCellIds or PassThroughPointIds is on, then these ivars
+  // control the name given to the field in which the ids are written into.  If
+  // set to NULL, then vtkOriginalCellIds or vtkOriginalPointIds (the default)
+  // is used, respectively.
+  vtkSetStringMacro(OriginalCellIdsName);
+  virtual const char *GetOriginalCellIdsName() {
+    return (  this->OriginalCellIdsName
+            ? this->OriginalCellIdsName : "vtkOriginalCellIds");
+  }
+  vtkSetStringMacro(OriginalPointIdsName);
+  virtual const char *GetOriginalPointIdsName() {
+    return (  this->OriginalPointIdsName
+            ? this->OriginalPointIdsName : "vtkOriginalPointIds");
+  }
+
+  // Description:
   // Set / get a spatial locator for merging points. By
   // default an instance of vtkMergePoints is used.
   void SetLocator(vtkIncrementalPointLocator *locator);
@@ -138,6 +168,11 @@ protected:
   int CellClipping;
   int ExtentClipping;
 
+  int PassThroughCellIds;
+  int PassThroughPointIds;
+  char *OriginalCellIdsName;
+  char *OriginalPointIdsName;
+
   int Merging;
   vtkIncrementalPointLocator *Locator;
   
diff --git a/IO/vtkSLACReader.cxx b/IO/vtkSLACReader.cxx
index 68ec746..4db8a03 100644
--- a/IO/vtkSLACReader.cxx
+++ b/IO/vtkSLACReader.cxx
@@ -1315,13 +1315,6 @@ int vtkSLACReader::ReadMidpointCoordinates(
 int vtkSLACReader::ReadMidpointData(int meshFD, vtkMultiBlockDataSet *output,
                                     MidpointIdMap &midpointIds)
 {
-  static bool GaveMidpointWarning = false;
-  if (!GaveMidpointWarning)
-    {
-    vtkWarningMacro(<< "Quadratic elements not displayed entirely correctly yet.  Quadratic triangles are drawn as 4 linear triangles.");
-    GaveMidpointWarning = true;
-    }
-
   // Get the point information from the data.
   vtkPoints *points = vtkPoints::SafeDownCast(
                         output->GetInformation()->Get(vtkSLACReader::POINTS()));
diff --git a/IO/vtkXMLReader.h b/IO/vtkXMLReader.h
index 1a262fc..c910902 100644
--- a/IO/vtkXMLReader.h
+++ b/IO/vtkXMLReader.h
@@ -95,6 +95,10 @@ public:
   vtkGetVector2Macro(TimeStepRange, int);
   vtkSetVector2Macro(TimeStepRange, int);
 
+  virtual int ProcessRequest(vtkInformation *request,
+                             vtkInformationVector **inputVector,
+                             vtkInformationVector *outputVector);
+  
 protected:
   vtkXMLReader();
   ~vtkXMLReader();
@@ -218,10 +222,7 @@ protected:
   virtual void SetProgressRange(float* range, int curStep, float* fractions);
   virtual void UpdateProgressDiscrete(float progress);
   float ProgressRange[2];
-
-  virtual int ProcessRequest(vtkInformation *request,
-                             vtkInformationVector **inputVector,
-                             vtkInformationVector *outputVector);
+  
   virtual int RequestData(vtkInformation *request,
                           vtkInformationVector **inputVector,
                           vtkInformationVector *outputVector);
diff --git a/Infovis/vtkTreeLayoutStrategy.cxx b/Infovis/vtkTreeLayoutStrategy.cxx
index bc9621f..d1a0aac 100644
--- a/Infovis/vtkTreeLayoutStrategy.cxx
+++ b/Infovis/vtkTreeLayoutStrategy.cxx
@@ -33,6 +33,7 @@
 #include "vtkPointData.h"
 #include "vtkPoints.h"
 #include "vtkSmartPointer.h"
+#include "vtkTransform.h"
 #include "vtkTree.h"
 #include "vtkTreeDFSIterator.h"
 
@@ -46,6 +47,7 @@ vtkTreeLayoutStrategy::vtkTreeLayoutStrategy()
   this->LogSpacingValue = 1.0;
   this->LeafSpacing = 0.9;
   this->DistanceArrayName = NULL;
+  this->Rotation = 0.0;
 }
 
 vtkTreeLayoutStrategy::~vtkTreeLayoutStrategy()
@@ -336,6 +338,21 @@ void vtkTreeLayoutStrategy::Layout()
       }
     newPoints->SetPoint(vertex, x, y, 0.0);
     }
+
+  // Rotate coordinates
+  if (this->Rotation != 0.0)
+    {
+    vtkSmartPointer<vtkTransform> t = vtkSmartPointer<vtkTransform>::New();
+    t->RotateZ(this->Rotation);
+    double x[3];
+    double y[3];
+    for (vtkIdType p = 0; p < newPoints->GetNumberOfPoints(); ++p)
+      {
+      newPoints->GetPoint(p, x);
+      t->MultiplyPoint(x, y);
+      newPoints->SetPoint(p, y);
+      }
+    }
   
   // Copy coordinates back into the original graph
   if (vtkTree::SafeDownCast(this->Graph))
@@ -377,7 +394,8 @@ void vtkTreeLayoutStrategy::PrintSelf(ostream& os, vtkIndent indent)
   os << indent << "Radial: " << (this->Radial ? "true" : "false") << endl;
   os << indent << "LogSpacingValue: " << this->LogSpacingValue << endl;
   os << indent << "LeafSpacing: " << this->LeafSpacing << endl;
-  os << indent << "DistanceArrayName: " 
+  os << indent << "Rotation: " << this->Rotation << endl;
+  os << indent << "DistanceArrayName: "
      << (this->DistanceArrayName ? this->DistanceArrayName : "(null)") << endl;
 }
 
diff --git a/Infovis/vtkTreeLayoutStrategy.h b/Infovis/vtkTreeLayoutStrategy.h
index fb98dcc..2c3a437 100644
--- a/Infovis/vtkTreeLayoutStrategy.h
+++ b/Infovis/vtkTreeLayoutStrategy.h
@@ -87,6 +87,12 @@ public:
   vtkSetStringMacro(DistanceArrayName);
   vtkGetStringMacro(DistanceArrayName);
 
+  // Description:
+  // The amount of counter-clockwise rotation to apply after the
+  // layout.
+  vtkSetMacro(Rotation, double);
+  vtkGetMacro(Rotation, double);
+
 protected:
   vtkTreeLayoutStrategy();
   ~vtkTreeLayoutStrategy();
@@ -96,6 +102,7 @@ protected:
   double LogSpacingValue;
   double LeafSpacing;
   char *DistanceArrayName;
+  double Rotation;
 
 private:
 
diff --git a/Rendering/vtkChooserPainter.cxx b/Rendering/vtkChooserPainter.cxx
index a215b0f..11bcbe2 100644
--- a/Rendering/vtkChooserPainter.cxx
+++ b/Rendering/vtkChooserPainter.cxx
@@ -20,6 +20,7 @@
 #include "vtkInformation.h"
 #include "vtkLinesPainter.h"
 #include "vtkObjectFactory.h"
+#include "vtkPointData.h"
 #include "vtkPointsPainter.h"
 #include "vtkPolyData.h"
 #include "vtkPolygonsPainter.h"
@@ -338,7 +339,9 @@ void vtkChooserPainter::RenderInternal(vtkRenderer* renderer, vtkActor* actor,
     if (   this->UseLinesPainterForWireframes
         && (actor->GetProperty()->GetRepresentation() == VTK_WIREFRAME)
         && !actor->GetProperty()->GetBackfaceCulling()
-        && !actor->GetProperty()->GetFrontfaceCulling() )
+        && !actor->GetProperty()->GetFrontfaceCulling()
+        && !this->GetInputAsPolyData()->GetPointData()->GetAttribute(
+                                               vtkDataSetAttributes::EDGEFLAG) )
       {
       this->LinePainter->Render(renderer, actor, vtkPainter::POLYS,
         forceCompileOnly);
diff --git a/Rendering/vtkLinesPainter.cxx b/Rendering/vtkLinesPainter.cxx
index ca9fc8a..877e075 100644
--- a/Rendering/vtkLinesPainter.cxx
+++ b/Rendering/vtkLinesPainter.cxx
@@ -131,6 +131,9 @@ int vtkLinesPainter::RenderPrimitive(unsigned long idx, vtkDataArray* n,
   // we just ignore the flag.
   idx &= (~VTK_PDM_FIELD_COLORS);
 
+  // Also ignore edge flags.
+  idx &= (~VTK_PDM_EDGEFLAGS);
+
   // draw all the elements, use fast path if available
   switch (idx)
     {
diff --git a/Rendering/vtkOpenGLPainterDeviceAdapter.cxx b/Rendering/vtkOpenGLPainterDeviceAdapter.cxx
index 0c0eb91..9328a3c 100644
--- a/Rendering/vtkOpenGLPainterDeviceAdapter.cxx
+++ b/Rendering/vtkOpenGLPainterDeviceAdapter.cxx
@@ -259,6 +259,7 @@ int vtkOpenGLPainterDeviceAdapter::IsAttributesSupported(int attribute)
   case vtkDataSetAttributes::NORMALS:
   case vtkDataSetAttributes::SCALARS:
   case vtkDataSetAttributes::TCOORDS:
+  case vtkDataSetAttributes::EDGEFLAG:
     return 1;
     }
   return 0;
@@ -534,6 +535,18 @@ void vtkOpenGLPainterDeviceAdapter::SendAttribute(int index, int numcomp,
           return;
         }
       break;
+    case vtkDataSetAttributes::EDGEFLAG:        // Edge Flag
+      if (numcomp != 1)
+        {
+        vtkErrorMacro("Bad number of components.");
+        return;
+        }
+       switch (type)
+        {
+        vtkTemplateMacro(glEdgeFlag(static_cast<GLboolean>(
+                          reinterpret_cast<const VTK_TT*>(attribute)[offset])));
+        }
+      break;
     default:
       vtkErrorMacro("Unsupported attribute index: " << index);
       return;
@@ -715,6 +728,33 @@ void vtkOpenGLPainterDeviceAdapter::SetAttributePointer(int index,
         }
       glTexCoordPointer(numcomponents, gltype, stride, pointer);
       break;
+    case vtkDataSetAttributes::EDGEFLAG:        // Edge flag
+      if (numcomponents != 1)
+        {
+        vtkErrorMacro("Edge flag must have one component.");
+        return;
+        }
+      // Flag must be conformant to GLboolean
+      if ((type == VTK_FLOAT) || (type == GL_DOUBLE))
+        {
+        vtkErrorMacro("Unsupported type for edge flag: " << type);
+        return;
+        }
+      // Thus is an unfriendly way to force the array to be conformant to
+      // a GLboolean array.  At the very least there should be some indication
+      // in VTK outside of OpenGL to determine which VTK type to use.
+      switch (type)
+        {
+        vtkTemplateMacro(if (sizeof(VTK_TT) != sizeof(GLboolean))
+                           {
+                           vtkErrorMacro(<< "Unsupported tyep for edge flag: "
+                                         << type);
+                           return;
+                           }
+                         );
+        }
+      glEdgeFlagPointer(stride, pointer);
+      break;
     default:
       vtkErrorMacro("Unsupported attribute index: " << index);
       return;
@@ -735,6 +775,8 @@ void vtkOpenGLPainterDeviceAdapter::EnableAttributeArray(int index)
       glEnableClientState(GL_COLOR_ARRAY);  break;
   case vtkDataSetAttributes::TCOORDS:
       glEnableClientState(GL_TEXTURE_COORD_ARRAY);  break;
+  case vtkDataSetAttributes::EDGEFLAG:
+      glEnableClientState(GL_EDGE_FLAG_ARRAY);  break;
     default:
       vtkErrorMacro("Unsupported attribute index: " << index);
       return;
@@ -753,6 +795,8 @@ void vtkOpenGLPainterDeviceAdapter::DisableAttributeArray(int index)
       glDisableClientState(GL_COLOR_ARRAY);  break;
   case vtkDataSetAttributes::TCOORDS:
       glDisableClientState(GL_TEXTURE_COORD_ARRAY);  break;
+  case vtkDataSetAttributes::EDGEFLAG:
+      glDisableClientState(GL_EDGE_FLAG_ARRAY);  break;
     default:
       vtkErrorMacro("Unsupported attribute index: " << index);
       return;
diff --git a/Rendering/vtkPointsPainter.cxx b/Rendering/vtkPointsPainter.cxx
index 97d1613..ce64eb6 100644
--- a/Rendering/vtkPointsPainter.cxx
+++ b/Rendering/vtkPointsPainter.cxx
@@ -107,6 +107,10 @@ int vtkPointsPainter::RenderPrimitive(unsigned long idx, vtkDataArray* n,
   // since this painter does not deal with field colors specially,
   // we just ignore the flag.
   idx &= (~VTK_PDM_FIELD_COLORS);
+
+  // Also ignore edge flags.
+  idx &= (~VTK_PDM_EDGEFLAGS);
+
   switch (idx)
     {
   case 0://no cell/point attribs are present. 
diff --git a/Rendering/vtkPolygonsPainter.cxx b/Rendering/vtkPolygonsPainter.cxx
index 62ed003..3f02deb 100644
--- a/Rendering/vtkPolygonsPainter.cxx
+++ b/Rendering/vtkPolygonsPainter.cxx
@@ -181,6 +181,8 @@ int vtkPolygonsPainter::RenderPrimitive(unsigned long idx, vtkDataArray* n,
     pd->GetLines()->GetNumberOfCells();
   vtkIdType cellNumStart = cellNum;
   vtkIdType totalCells = ca->GetNumberOfCells();
+  vtkUnsignedCharArray *ef = vtkUnsignedCharArray::SafeDownCast(
+              pd->GetPointData()->GetAttribute(vtkDataSetAttributes::EDGEFLAG));
   
   vtkPainterDeviceAdapter* device = ren->GetRenderWindow()->
     GetPainterDeviceAdapter();
@@ -188,6 +190,7 @@ int vtkPolygonsPainter::RenderPrimitive(unsigned long idx, vtkDataArray* n,
   void *normals = 0;
   void *tcoords = 0;
   unsigned char *colors = 0;
+  unsigned char *edgeflags = 0;
   int primitive = VTK_POLYGON;
 
   if (ca->GetNumberOfCells() == 0)
@@ -211,12 +214,17 @@ int vtkPolygonsPainter::RenderPrimitive(unsigned long idx, vtkDataArray* n,
     {
     tcoords = t->GetVoidPointer(0);
     }
+  if (ef)
+    {
+    edgeflags = ef->GetPointer(0);
+    }
   vtkIdType *ptIds = ca->GetPointer();
   vtkIdType *endPtIds = ptIds + ca->GetNumberOfConnectivityEntries();
   int ptype = p->GetDataType();
   int ntype = (n)? n->GetDataType() : 0;
   int ttype = (t)? t->GetDataType() : 0;
   int tcomps = (t)? t->GetNumberOfComponents() : 0;
+  int eftype = (ef)? ef->GetDataType() : 0;
   int celloffset = 0;
   
   // since this painter does not deal with field colors specially,
@@ -412,9 +420,266 @@ int vtkPolygonsPainter::RenderPrimitive(unsigned long idx, vtkDataArray* n,
           VTK_UNSIGNED_CHAR, colors); colors += 4;,
         celloffset = cellNum;);
       break;
+
+    case VTK_PDM_EDGEFLAGS:
+      if (this->BuildNormals)
+        {
+        vtkDrawPolysMacro(primitive,
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);,
+                          PolyNormal,;);
+        }
+      else
+        {
+        vtkDrawPolysMacro(primitive,
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);, ;,;);
+        }
+      break;
+
+    case VTK_PDM_NORMALS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,;,;);
+      break;
+
+    case VTK_PDM_COLORS | VTK_PDM_EDGEFLAGS:
+      if (this->BuildNormals)
+        {
+        vtkDrawPolysMacro(primitive,
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::SCALARS, 4,
+                                                VTK_UNSIGNED_CHAR,
+                                                colors + 4**ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);,
+                          PolyNormal,;);
+        }
+      else
+        {
+        vtkDrawPolysMacro(primitive,
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::SCALARS, 4,
+                                                VTK_UNSIGNED_CHAR,
+                                                colors + 4**ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);,
+                          ;,;);
+        }
+      break;
+    case VTK_PDM_COLORS  | VTK_PDM_OPAQUE_COLORS | VTK_PDM_EDGEFLAGS:
+      if (this->BuildNormals)
+        {
+        vtkDrawPolysMacro(primitive,
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::SCALARS, 3,
+                                                VTK_UNSIGNED_CHAR,
+                                                colors + 4**ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);,
+                          PolyNormal,;);
+        }
+      else
+        {
+        vtkDrawPolysMacro(primitive,
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::SCALARS, 3,
+                                                VTK_UNSIGNED_CHAR,
+                                                colors + 4**ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);,
+                          ;,;);
+        }
+      break;
+    case VTK_PDM_NORMALS | VTK_PDM_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3**ptIds);
+                        device->SendAttribute(vtkPointData::SCALARS, 4,
+                                              VTK_UNSIGNED_CHAR,
+                                              colors + 4**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,;,;);
+      break;
+    case VTK_PDM_NORMALS | VTK_PDM_COLORS  | VTK_PDM_OPAQUE_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3**ptIds);
+                        device->SendAttribute(vtkPointData::SCALARS, 3,
+                                              VTK_UNSIGNED_CHAR,
+                                              colors + 4**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,;,;);
+      break;
+    case VTK_PDM_NORMALS | VTK_PDM_TCOORDS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3**ptIds);
+                        device->SendAttribute(vtkPointData::TCOORDS, tcomps,
+                                              ttype, tcoords, tcomps**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,;,;);
+      break;
+    case VTK_PDM_CELL_NORMALS | VTK_PDM_TCOORDS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::TCOORDS, tcomps,
+                                              ttype, tcoords, tcomps**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3*celloffset);
+                        celloffset++;,
+                        celloffset = cellNum;);
+      break;
+    case VTK_PDM_TCOORDS | VTK_PDM_EDGEFLAGS:
+      if (this->BuildNormals)
+        {
+        vtkDrawPolysMacro(primitive,
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::TCOORDS, tcomps,
+                                                ttype, tcoords, tcomps**ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);,
+                          PolyNormal,;);
+        }
+      else
+        {
+        vtkDrawPolysMacro(primitive,
+                          device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                                eftype, edgeflags, *ptIds);
+                          device->SendAttribute(vtkPointData::TCOORDS, 1,
+                                                ttype, tcoords, *ptIds);
+                          device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                                ptype, points, 3**ptIds);,
+                          ;,;);
+        }
+      break;
+    case VTK_PDM_CELL_NORMALS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3*celloffset);
+                        celloffset++;,
+                        celloffset = cellNum;);
+      break;
+    case VTK_PDM_CELL_NORMALS | VTK_PDM_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::SCALARS, 4,
+                                              VTK_UNSIGNED_CHAR,
+                                              colors + 4**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3*celloffset);
+                        celloffset++;,
+                        celloffset = cellNum;);
+      break;
+    case VTK_PDM_CELL_NORMALS | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::SCALARS, 3,
+                                              VTK_UNSIGNED_CHAR,
+                                              colors + 4**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3*celloffset);
+                        celloffset++;,
+                        celloffset = cellNum;);
+      break;
+    case VTK_PDM_NORMALS | VTK_PDM_COLORS | VTK_PDM_CELL_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::SCALARS, 4,
+                                              VTK_UNSIGNED_CHAR, colors);
+                        colors += 4;,;);
+      break;
+    case VTK_PDM_NORMALS | VTK_PDM_COLORS  | VTK_PDM_OPAQUE_COLORS | VTK_PDM_CELL_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3**ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::SCALARS, 3,
+                                              VTK_UNSIGNED_CHAR, colors);
+                        colors += 4;,;);
+      break;
+    case VTK_PDM_CELL_NORMALS | VTK_PDM_COLORS | VTK_PDM_CELL_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3*celloffset);
+                        celloffset++;
+                        device->SendAttribute(vtkPointData::SCALARS, 4,
+                                              VTK_UNSIGNED_CHAR, colors);
+                        colors += 4;,
+                        celloffset = cellNum;);
+      break;
+    case VTK_PDM_CELL_NORMALS | VTK_PDM_COLORS  | VTK_PDM_OPAQUE_COLORS | VTK_PDM_CELL_COLORS | VTK_PDM_EDGEFLAGS:
+      vtkDrawPolysMacro(primitive,
+                        device->SendAttribute(vtkPointData::EDGEFLAG, 1,
+                                              eftype, edgeflags, *ptIds);
+                        device->SendAttribute(vtkPointData::NUM_ATTRIBUTES, 3,
+                                              ptype, points, 3**ptIds);,
+                        device->SendAttribute(vtkPointData::NORMALS, 3,
+                                              ntype, normals, 3*celloffset);
+                        celloffset++;
+                        device->SendAttribute(vtkPointData::SCALARS, 3,
+                                              VTK_UNSIGNED_CHAR, colors);
+                        colors += 4;,
+                        celloffset = cellNum;);
+      break;
+
     default:
       return 0; // let the delegate painter handle it.
     }
+
+  if (idx & VTK_PDM_EDGEFLAGS)
+    {
+    // Reset the edge flag to 1 so that if the next thing rendered does not
+    // have an edge flag, it will have all edges on.
+    unsigned char edgeflag = 1;
+    device->SendAttribute(vtkPointData::EDGEFLAG, 1, VTK_UNSIGNED_CHAR,
+                          &edgeflag, 0);
+    }
+
   return 1;
 }
 
diff --git a/Rendering/vtkPrimitivePainter.cxx b/Rendering/vtkPrimitivePainter.cxx
index df859e9..d6253cd 100644
--- a/Rendering/vtkPrimitivePainter.cxx
+++ b/Rendering/vtkPrimitivePainter.cxx
@@ -159,6 +159,7 @@ void vtkPrimitivePainter::RenderInternal(vtkRenderer* renderer,
   vtkUnsignedCharArray *c=NULL;
   vtkDataArray *n;
   vtkDataArray *t;
+  vtkDataArray *ef;
   int tDim;
   vtkPolyData *input = this->GetInputAsPolyData();
   int cellNormals;
@@ -269,6 +270,28 @@ void vtkPrimitivePainter::RenderInternal(vtkRenderer* renderer,
     idx |= VTK_PDM_TCOORDS;
     }
 
+  // Edge flag
+  ef = input->GetPointData()->GetAttribute(vtkDataSetAttributes::EDGEFLAG);
+  if (ef)
+    {
+    if (ef->GetNumberOfComponents() != 1)
+      {
+      vtkDebugMacro(<< "Currently only 1d edge flags are supported.");
+      ef = NULL;
+      }
+    if (!ef->IsA("vtkUnsignedCharArray"))
+      {
+      vtkDebugMacro(<< "Currently only unsigned char edge flags are suported.");
+      ef = NULL;
+      }
+    }
+
+  // Set the flags
+  if (ef)
+    {
+    idx |= VTK_PDM_EDGEFLAGS;
+    }
+
   if (!act)
     {
     vtkErrorMacro("No actor");
diff --git a/Rendering/vtkPrimitivePainter.h b/Rendering/vtkPrimitivePainter.h
index 100cc22..2ca46a7 100644
--- a/Rendering/vtkPrimitivePainter.h
+++ b/Rendering/vtkPrimitivePainter.h
@@ -49,14 +49,15 @@ protected:
 
   //BTX
   enum {
-    VTK_PDM_NORMALS = 0x01,
-    VTK_PDM_COLORS = 0x02,
-    VTK_PDM_TCOORDS = 0x04,
-    VTK_PDM_CELL_COLORS = 0x08,
-    VTK_PDM_CELL_NORMALS = 0x10,
-    VTK_PDM_OPAQUE_COLORS = 0x20,
-    VTK_PDM_FIELD_COLORS = 0x40,
-    VTK_PDM_GENERIC_VERTEX_ATTRIBUTES =0x80
+    VTK_PDM_NORMALS = 0x001,
+    VTK_PDM_COLORS = 0x002,
+    VTK_PDM_TCOORDS = 0x004,
+    VTK_PDM_CELL_COLORS = 0x008,
+    VTK_PDM_CELL_NORMALS = 0x010,
+    VTK_PDM_OPAQUE_COLORS = 0x020,
+    VTK_PDM_FIELD_COLORS = 0x040,
+    VTK_PDM_EDGEFLAGS = 0x080,
+    VTK_PDM_GENERIC_VERTEX_ATTRIBUTES = 0x100
   };
   //ETX
 
diff --git a/Rendering/vtkTStripsPainter.cxx b/Rendering/vtkTStripsPainter.cxx
index 101070f..f326981 100644
--- a/Rendering/vtkTStripsPainter.cxx
+++ b/Rendering/vtkTStripsPainter.cxx
@@ -189,6 +189,9 @@ int vtkTStripsPainter::RenderPrimitive(unsigned long idx, vtkDataArray* n,
   int ttype = (t)? t->GetDataType() : 0;
   int tcomps = (t)? t->GetNumberOfComponents() : 0;
 
+  // Ignore edge flags.
+  idx &= (~VTK_PDM_EDGEFLAGS);
+
   // draw all the elements, use fast path if available
   switch (idx)
     {
diff --git a/Utilities/kwsys/ProcessUNIX.c b/Utilities/kwsys/ProcessUNIX.c
index 57f7b16..b368901 100644
--- a/Utilities/kwsys/ProcessUNIX.c
+++ b/Utilities/kwsys/ProcessUNIX.c
@@ -2374,7 +2374,7 @@ static pid_t kwsysProcessFork(kwsysProcess* cp,
    corresponding parsing format string.  The parsing format should
    have two integers to store: the pid and then the ppid.  */
 #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) \
-   || defined(__FreeBSD_kernel__)
+   || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
 # define KWSYSPE_PS_COMMAND "ps axo pid,ppid"
 # define KWSYSPE_PS_FORMAT  "%d %d\n"
 #elif defined(__hpux) || defined(__sun__) || defined(__sgi) || defined(_AIX) \
diff --git a/Utilities/kwsys/SharedForward.h.in b/Utilities/kwsys/SharedForward.h.in
index da62d84..8521099 100644
--- a/Utilities/kwsys/SharedForward.h.in
+++ b/Utilities/kwsys/SharedForward.h.in
@@ -201,6 +201,12 @@ static const char kwsys_shared_forward_path_slash[2] = {KWSYS_SHARED_FORWARD_PAT
 # define KWSYS_SHARED_FORWARD_LDD_N 1
 # define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
 
+/* OpenBSD */
+#elif defined(__OpenBSD__)
+# define KWSYS_SHARED_FORWARD_LDD "ldd"
+# define KWSYS_SHARED_FORWARD_LDD_N 1
+# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
+
 /* OSX */
 #elif defined(__APPLE__)
 # define KWSYS_SHARED_FORWARD_LDD "otool", "-L"
diff --git a/Utilities/kwsys/kwsysDateStamp.cmake b/Utilities/kwsys/kwsysDateStamp.cmake
index 9a5e9e9..9ccf63d 100644
--- a/Utilities/kwsys/kwsysDateStamp.cmake
+++ b/Utilities/kwsys/kwsysDateStamp.cmake
@@ -18,4 +18,4 @@ SET(KWSYS_DATE_STAMP_YEAR  2010)
 SET(KWSYS_DATE_STAMP_MONTH 04)
 
 # KWSys version date day component.  Format is DD.
-SET(KWSYS_DATE_STAMP_DAY   19)
+SET(KWSYS_DATE_STAMP_DAY   21)
