Index: ogr/ogr_geometry.h
===================================================================
--- ogr/ogr_geometry.h	(revision 11766)
+++ ogr/ogr_geometry.h	(working copy)
@@ -333,6 +333,7 @@
     virtual const char *getGeometryName() const;
     virtual OGRGeometry *clone() const;
     virtual int isClockwise() const;
+    virtual void reverseWindingOrder();
     virtual void closeRings();
     virtual double get_Area() const;
     OGRBoolean isPointInRing(const OGRPoint* pt) const;
Index: ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp
===================================================================
--- ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp	(revision 11766)
+++ ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp	(working copy)
@@ -235,12 +235,23 @@
         AppendString( ppszText, pnLength, pnMaxLength,
                       "<Polygon>" );
 
-        if( poPolygon->getExteriorRing() != NULL )
+        OGRLinearRing *poExteriorRing = poPolygon->getExteriorRing();
+        if( poExteriorRing != NULL )
         {
+            // Test if we need to reverse the winding order. KML defines the
+            // front of a face as a LinearRing with an anti-clockwise winding
+            // order. Full 3D implementations of KML, such as Google Earth,
+            // will light the front of the face, not the rear. For the present
+            // case it's safe to assume that all faces exported from OGR
+            // should have anti-clockwise winding orders.
+            if ( poExteriorRing->isClockwise() ) {
+                poExteriorRing->reverseWindingOrder();
+            }
+
             AppendString( ppszText, pnLength, pnMaxLength,
                           "<outerBoundaryIs>" );
 
-            if( !OGR2KMLGeometryAppend( poPolygon->getExteriorRing(), 
+            if( !OGR2KMLGeometryAppend( poExteriorRing, 
                                         ppszText, pnLength, pnMaxLength ) )
                 return FALSE;
             
@@ -252,6 +263,12 @@
         {
             OGRLinearRing *poRing = poPolygon->getInteriorRing(iRing);
 
+            // Perform the winding test again.
+            if( poRing->isClockwise() )
+            {
+                poRing->reverseWindingOrder();
+            }
+
             AppendString( ppszText, pnLength, pnMaxLength,
                           "<innerBoundaryIs>" );
             
Index: ogr/ogrlinearring.cpp
===================================================================
--- ogr/ogrlinearring.cpp	(revision 11766)
+++ ogr/ogrlinearring.cpp	(working copy)
@@ -357,7 +357,27 @@
     return dfSum < 0.0;
 }
 
+
 /************************************************************************/
+/*                             reverseWindingOrder()                    */
+/************************************************************************/
+
+void OGRLinearRing::reverseWindingOrder()
+
+{
+    OGRPoint tempPoint;
+    int pos;
+    for( int i = 0; i < nPointCount / 2; i++ )
+    {
+        getPoint( i, &tempPoint );
+        pos = nPointCount - i - 1;
+        setPoint( i, getX(pos), getY(pos), getZ(pos) );
+        setPoint( pos, tempPoint.getX(), tempPoint.getY(), tempPoint.getZ() );
+    }
+}
+
+
+/************************************************************************/
 /*                             closeRing()                              */
 /************************************************************************/
 

