LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/svg - ogrsvglayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 375 312 83.2 %
Date: 2012-12-26 Functions: 27 22 81.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrsvglayer.cpp 22111 2011-04-03 19:28:18Z rouault $
       3                 :  *
       4                 :  * Project:  SVG Translator
       5                 :  * Purpose:  Implements OGRSVGLayer class.
       6                 :  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2011, Even Rouault
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "ogr_svg.h"
      31                 : #include "cpl_conv.h"
      32                 : 
      33                 : CPL_CVSID("$Id: ogrsvglayer.cpp 22111 2011-04-03 19:28:18Z rouault $");
      34                 : 
      35                 : /************************************************************************/
      36                 : /*                            OGRSVGLayer()                             */
      37                 : /************************************************************************/
      38                 : 
      39               3 : OGRSVGLayer::OGRSVGLayer( const char* pszFilename,
      40                 :                           const char* pszLayerName,
      41                 :                           SVGGeometryType svgGeomType,
      42               3 :                           OGRSVGDataSource* poDS)
      43                 : 
      44                 : {
      45               3 :     nNextFID = 0;
      46                 : 
      47               3 :     this->poDS = poDS;
      48               3 :     this->svgGeomType = svgGeomType;
      49               3 :     osLayerName = pszLayerName;
      50                 : 
      51               3 :     poFeatureDefn = NULL;
      52                 : 
      53               3 :     nTotalFeatures = 0;
      54                 : 
      55               3 :     ppoFeatureTab = NULL;
      56               3 :     nFeatureTabIndex = 0;
      57               3 :     nFeatureTabLength = 0;
      58               3 :     pszSubElementValue = NULL;
      59               3 :     nSubElementValueLen = 0;
      60               3 :     bStopParsing = FALSE;
      61                 : 
      62                 :     poSRS = new OGRSpatialReference("PROJCS[\"WGS 84 / Pseudo-Mercator\","
      63                 :     "GEOGCS[\"WGS 84\","
      64                 :     "    DATUM[\"WGS_1984\","
      65                 :     "        SPHEROID[\"WGS 84\",6378137,298.257223563,"
      66                 :     "            AUTHORITY[\"EPSG\",\"7030\"]],"
      67                 :     "        AUTHORITY[\"EPSG\",\"6326\"]],"
      68                 :     "    PRIMEM[\"Greenwich\",0,"
      69                 :     "        AUTHORITY[\"EPSG\",\"8901\"]],"
      70                 :     "    UNIT[\"degree\",0.0174532925199433,"
      71                 :     "        AUTHORITY[\"EPSG\",\"9122\"]],"
      72                 :     "    AUTHORITY[\"EPSG\",\"4326\"]],"
      73                 :     "UNIT[\"metre\",1,"
      74                 :     "    AUTHORITY[\"EPSG\",\"9001\"]],"
      75                 :     "PROJECTION[\"Mercator_1SP\"],"
      76                 :     "PARAMETER[\"central_meridian\",0],"
      77                 :     "PARAMETER[\"scale_factor\",1],"
      78                 :     "PARAMETER[\"false_easting\",0],"
      79                 :     "PARAMETER[\"false_northing\",0],"
      80                 :     "EXTENSION[\"PROJ4\",\"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs\"],"
      81                 :     "AUTHORITY[\"EPSG\",\"3857\"],"
      82                 :     "AXIS[\"X\",EAST],"
      83               3 :     "AXIS[\"Y\",NORTH]]");
      84                 : 
      85               3 :     poFeature = NULL;
      86                 : 
      87                 : #ifdef HAVE_EXPAT
      88               3 :     oParser = NULL;
      89                 : #endif
      90                 : 
      91               6 :     fpSVG = VSIFOpenL( pszFilename, "r" );
      92               3 :     if( fpSVG == NULL )
      93                 :     {
      94               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s", pszFilename);
      95               0 :         return;
      96                 :     }
      97                 : 
      98               3 :     ResetReading();
      99               0 : }
     100                 : 
     101                 : /************************************************************************/
     102                 : /*                            ~OGRSVGLayer()                            */
     103                 : /************************************************************************/
     104                 : 
     105               3 : OGRSVGLayer::~OGRSVGLayer()
     106                 : 
     107                 : {
     108                 : #ifdef HAVE_EXPAT
     109               3 :     if (oParser)
     110               3 :         XML_ParserFree(oParser);
     111                 : #endif
     112               3 :     if (poFeatureDefn)
     113               3 :         poFeatureDefn->Release();
     114                 :     
     115               3 :     if( poSRS != NULL )
     116               3 :         poSRS->Release();
     117                 : 
     118               3 :     CPLFree(pszSubElementValue);
     119                 : 
     120                 :     int i;
     121               3 :     for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
     122               0 :         delete ppoFeatureTab[i];
     123               3 :     CPLFree(ppoFeatureTab);
     124                 : 
     125               3 :     if (poFeature)
     126               0 :         delete poFeature;
     127                 : 
     128               3 :     if (fpSVG)
     129               3 :         VSIFCloseL( fpSVG );
     130               3 : }
     131                 : 
     132                 : #ifdef HAVE_EXPAT
     133                 : 
     134              54 : static void XMLCALL startElementCbk(void *pUserData,
     135                 :                                     const char *pszName, const char **ppszAttr)
     136                 : {
     137              54 :     ((OGRSVGLayer*)pUserData)->startElementCbk(pszName, ppszAttr);
     138              54 : }
     139                 : 
     140              54 : static void XMLCALL endElementCbk(void *pUserData, const char *pszName)
     141                 : {
     142              54 :     ((OGRSVGLayer*)pUserData)->endElementCbk(pszName);
     143              54 : }
     144                 : 
     145             168 : static void XMLCALL dataHandlerCbk(void *pUserData, const char *data, int nLen)
     146                 : {
     147             168 :     ((OGRSVGLayer*)pUserData)->dataHandlerCbk(data, nLen);
     148             168 : }
     149                 : 
     150                 : #endif
     151                 : 
     152                 : /************************************************************************/
     153                 : /*                            ResetReading()                            */
     154                 : /************************************************************************/
     155                 : 
     156               3 : void OGRSVGLayer::ResetReading()
     157                 : 
     158                 : {
     159               3 :     nNextFID = 0;
     160               3 :     if (fpSVG)
     161                 :     {
     162               3 :         VSIFSeekL( fpSVG, 0, SEEK_SET );
     163                 : #ifdef HAVE_EXPAT
     164               3 :         if (oParser)
     165               0 :             XML_ParserFree(oParser);
     166                 : 
     167               3 :         oParser = OGRCreateExpatXMLParser();
     168               3 :         XML_SetElementHandler(oParser, ::startElementCbk, ::endElementCbk);
     169               3 :         XML_SetCharacterDataHandler(oParser, ::dataHandlerCbk);
     170               3 :         XML_SetUserData(oParser, this);
     171                 : #endif
     172                 :     }
     173                 : 
     174               3 :     CPLFree(pszSubElementValue);
     175               3 :     pszSubElementValue = NULL;
     176               3 :     nSubElementValueLen = 0;
     177               3 :     iCurrentField = -1;
     178                 : 
     179                 :     int i;
     180               3 :     for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
     181               0 :         delete ppoFeatureTab[i];
     182               3 :     CPLFree(ppoFeatureTab);
     183               3 :     nFeatureTabIndex = 0;
     184               3 :     nFeatureTabLength = 0;
     185               3 :     ppoFeatureTab = NULL;
     186               3 :     if (poFeature)
     187               0 :         delete poFeature;
     188               3 :     poFeature = NULL;
     189                 : 
     190               3 :     depthLevel = 0;
     191               3 :     interestingDepthLevel = 0;
     192               3 :     inInterestingElement = FALSE;
     193               3 : }
     194                 : 
     195                 : #ifdef HAVE_EXPAT
     196                 : 
     197                 : /************************************************************************/
     198                 : /*                         OGRSVGGetClass()                             */
     199                 : /************************************************************************/
     200                 : 
     201               9 : static const char* OGRSVGGetClass(const char **ppszAttr)
     202                 : {
     203               9 :     const char** ppszIter = ppszAttr;
     204              28 :     while(*ppszIter)
     205                 :     {
     206              19 :         if (strcmp(ppszIter[0], "class") == 0)
     207               9 :             return ppszIter[1];
     208              10 :         ppszIter += 2;
     209                 :     }
     210               0 :     return "";
     211                 : }
     212                 : 
     213                 : /************************************************************************/
     214                 : /*                          OGRSVGParseD()                              */
     215                 : /************************************************************************/
     216                 : 
     217               2 : static void OGRSVGParseD(OGRLineString* poLS, const char* pszD)
     218                 : {
     219                 :     char szBuffer[32];
     220               2 :     int iBuffer = 0;
     221               2 :     const char* pszIter = pszD;
     222                 :     char ch;
     223               2 :     int iNumber = 0;
     224               2 :     double dfPrevNumber = 0;
     225               2 :     int bRelativeLineto = FALSE;
     226               2 :     double dfX = 0, dfY = 0;
     227               2 :     int nPointCount = 0;
     228            8999 :     while(TRUE)
     229                 :     {
     230            9001 :         ch = *(pszIter ++);
     231                 : 
     232            9003 :         if (ch == 'M' || ch == 'm')
     233                 :         {
     234               2 :             if (nPointCount != 0)
     235                 :             {
     236               0 :                 CPLDebug("SVG", "Not ready to handle M/m not at the beginning");
     237               0 :                 return;
     238                 :             }
     239                 :         }
     240            8999 :         else if (ch == 'L')
     241                 :         {
     242               2 :             bRelativeLineto = FALSE;
     243                 :         }
     244            8997 :         else if (ch == 'l')
     245                 :         {
     246               0 :             if (nPointCount == 0)
     247                 :             {
     248               0 :                 CPLDebug("SVG", "Relative lineto at the beginning of the line");
     249               0 :                 return;
     250                 :             }
     251               0 :             bRelativeLineto = TRUE;
     252                 :         }
     253            8997 :         else if (ch == 'z' || ch == 'Z')
     254                 :         {
     255               1 :             poLS->closeRings();
     256               1 :             return;
     257                 :         }
     258           17628 :         else if (ch == '+' || ch == '-' || ch == '.' ||
     259                 :                  (ch >= '0' && ch <= '9'))
     260                 :         {
     261            8632 :             if (iBuffer == 30)
     262                 :             {
     263               0 :                 CPLDebug("SVG", "Too big number");
     264               0 :                 return;
     265                 :             }
     266            8632 :             szBuffer[iBuffer ++] = ch;
     267                 :         }
     268             364 :         else if (ch == ' ' || ch == 0)
     269                 :         {
     270             364 :             if (iBuffer > 0)
     271                 :             {
     272             360 :                 szBuffer[iBuffer] = 0;
     273             360 :                 if (iNumber == 1)
     274                 :                 {
     275                 :                     /* Cloudmade --> negate y */
     276             180 :                     double dfNumber = -CPLAtof(szBuffer);
     277                 : 
     278             180 :                     if (bRelativeLineto)
     279                 :                     {
     280               0 :                         dfX += dfPrevNumber;
     281               0 :                         dfY += dfNumber;
     282                 :                     }
     283                 :                     else
     284                 :                     {
     285             180 :                         dfX = dfPrevNumber;
     286             180 :                         dfY = dfNumber;
     287                 :                     }
     288             180 :                     poLS->addPoint(dfX, dfY);
     289             180 :                     nPointCount ++;
     290                 : 
     291             180 :                     iNumber = 0;
     292                 :                 }
     293                 :                 else
     294                 :                 {
     295             180 :                     iNumber = 1;
     296             180 :                     dfPrevNumber = CPLAtof(szBuffer);
     297                 :                 }
     298                 : 
     299             360 :                 iBuffer = 0;
     300                 :             }
     301             364 :             if (ch == 0)
     302               1 :                 break;
     303                 :         }
     304                 :     }
     305                 : }
     306                 : 
     307                 : /************************************************************************/
     308                 : /*                        startElementCbk()                            */
     309                 : /************************************************************************/
     310                 : 
     311              54 : void OGRSVGLayer::startElementCbk(const char *pszName, const char **ppszAttr)
     312                 : {
     313                 :     int i;
     314                 : 
     315              54 :     if (bStopParsing) return;
     316                 : 
     317              54 :     nWithoutEventCounter = 0;
     318                 : 
     319              54 :     if (svgGeomType == SVG_POINTS &&
     320                 :         strcmp(pszName, "circle") == 0 &&
     321                 :         strcmp(OGRSVGGetClass(ppszAttr), "point") == 0)
     322                 :     {
     323               1 :         int bHasFoundX = FALSE, bHasFoundY = FALSE;
     324               1 :         double dfX = 0, dfY = 0;
     325               6 :         for (i = 0; ppszAttr[i]; i += 2)
     326                 :         {
     327               5 :             if (strcmp(ppszAttr[i], "cx") == 0)
     328                 :             {
     329               1 :                 bHasFoundX = TRUE;
     330               1 :                 dfX = CPLAtof(ppszAttr[i + 1]);
     331                 :             }
     332               4 :             else if (strcmp(ppszAttr[i], "cy") == 0)
     333                 :             {
     334               1 :                 bHasFoundY = TRUE;
     335                 :                 /* Cloudmade --> negate y */
     336               1 :                 dfY = - CPLAtof(ppszAttr[i + 1]);
     337                 :             }
     338                 :         }
     339               1 :         if (bHasFoundX && bHasFoundY)
     340                 :         {
     341               1 :             interestingDepthLevel = depthLevel;
     342               1 :             inInterestingElement = TRUE;
     343                 : 
     344               1 :             if (poFeature)
     345               0 :                 delete poFeature;
     346                 : 
     347               1 :             poFeature = new OGRFeature( poFeatureDefn );
     348                 : 
     349               1 :             poFeature->SetFID( nNextFID++ );
     350               2 :             OGRPoint* poPoint = new OGRPoint( dfX, dfY );
     351               1 :             poPoint->assignSpatialReference(poSRS);
     352               1 :             poFeature->SetGeometryDirectly( poPoint );
     353                 :         }
     354                 :     }
     355              53 :     else if (svgGeomType == SVG_LINES &&
     356                 :              strcmp(pszName, "path") == 0 &&
     357                 :              strcmp(OGRSVGGetClass(ppszAttr), "line") == 0)
     358                 :     {
     359               1 :         const char* pszD = NULL;
     360               1 :         for (i = 0; ppszAttr[i]; i += 2)
     361                 :         {
     362               1 :             if (strcmp(ppszAttr[i], "d") == 0)
     363                 :             {
     364               1 :                 pszD = ppszAttr[i + 1];
     365               1 :                 break;
     366                 :             }
     367                 :         }
     368               1 :         if (pszD)
     369                 :         {
     370               1 :             interestingDepthLevel = depthLevel;
     371               1 :             inInterestingElement = TRUE;
     372                 : 
     373               1 :             if (poFeature)
     374               0 :                 delete poFeature;
     375                 : 
     376               1 :             poFeature = new OGRFeature( poFeatureDefn );
     377                 : 
     378               1 :             poFeature->SetFID( nNextFID++ );
     379               2 :             OGRLineString* poLS = new OGRLineString();
     380               1 :             OGRSVGParseD(poLS, pszD);
     381               1 :             poLS->assignSpatialReference(poSRS);
     382               1 :             poFeature->SetGeometryDirectly( poLS );
     383                 :         }
     384                 :     }
     385              52 :     else if (svgGeomType == SVG_POLYGONS &&
     386                 :              strcmp(pszName, "path") == 0 &&
     387                 :              strcmp(OGRSVGGetClass(ppszAttr), "polygon") == 0)
     388                 :     {
     389               1 :         const char* pszD = NULL;
     390               1 :         for (i = 0; ppszAttr[i]; i += 2)
     391                 :         {
     392               1 :             if (strcmp(ppszAttr[i], "d") == 0)
     393                 :             {
     394               1 :                 pszD = ppszAttr[i + 1];
     395               1 :                 break;
     396                 :             }
     397                 :         }
     398               1 :         if (pszD)
     399                 :         {
     400               1 :             interestingDepthLevel = depthLevel;
     401               1 :             inInterestingElement = TRUE;
     402                 : 
     403               1 :             if (poFeature)
     404               0 :                 delete poFeature;
     405                 : 
     406               1 :             poFeature = new OGRFeature( poFeatureDefn );
     407                 : 
     408               1 :             poFeature->SetFID( nNextFID++ );
     409               2 :             OGRPolygon* poPolygon = new OGRPolygon();
     410               2 :             OGRLinearRing* poLS = new OGRLinearRing();
     411               1 :             OGRSVGParseD(poLS, pszD);
     412               1 :             poPolygon->addRingDirectly(poLS);
     413               1 :             poPolygon->assignSpatialReference(poSRS);
     414               1 :             poFeature->SetGeometryDirectly( poPolygon );
     415                 :         }
     416                 :     }
     417              51 :     else if (inInterestingElement &&
     418                 :              depthLevel == interestingDepthLevel + 1 &&
     419                 :              strncmp(pszName, "cm:", 3) == 0)
     420                 :     {
     421              11 :         iCurrentField = poFeatureDefn->GetFieldIndex(pszName + 3);
     422                 :     }
     423                 : 
     424              54 :     depthLevel++;
     425                 : }
     426                 : 
     427                 : /************************************************************************/
     428                 : /*                           endElementCbk()                            */
     429                 : /************************************************************************/
     430                 : 
     431              54 : void OGRSVGLayer::endElementCbk(const char *pszName)
     432                 : {
     433              54 :     if (bStopParsing) return;
     434                 : 
     435              54 :     nWithoutEventCounter = 0;
     436                 : 
     437              54 :     depthLevel--;
     438                 : 
     439              54 :     if (inInterestingElement)
     440                 :     {
     441              14 :         if (depthLevel == interestingDepthLevel)
     442                 :         {
     443               3 :             inInterestingElement = FALSE;
     444                 : 
     445               3 :             if( (m_poFilterGeom == NULL
     446                 :                     || FilterGeometry( poFeature->GetGeometryRef() ) )
     447                 :                 && (m_poAttrQuery == NULL
     448                 :                     || m_poAttrQuery->Evaluate( poFeature )) )
     449                 :             {
     450                 :                 ppoFeatureTab = (OGRFeature**)
     451                 :                         CPLRealloc(ppoFeatureTab,
     452               3 :                                     sizeof(OGRFeature*) * (nFeatureTabLength + 1));
     453               3 :                 ppoFeatureTab[nFeatureTabLength] = poFeature;
     454               3 :                 nFeatureTabLength++;
     455                 :             }
     456                 :             else
     457                 :             {
     458               0 :                 delete poFeature;
     459                 :             }
     460               3 :             poFeature = NULL;
     461                 :         }
     462              11 :         else if (depthLevel == interestingDepthLevel + 1)
     463                 :         {
     464              11 :             if (poFeature && iCurrentField >= 0 && nSubElementValueLen)
     465                 :             {
     466              11 :                 pszSubElementValue[nSubElementValueLen] = 0;
     467              11 :                 poFeature->SetField( iCurrentField, pszSubElementValue);
     468                 :             }
     469                 : 
     470              11 :             CPLFree(pszSubElementValue);
     471              11 :             pszSubElementValue = NULL;
     472              11 :             nSubElementValueLen = 0;
     473              11 :             iCurrentField = -1;
     474                 :         }
     475                 :     }
     476                 : }
     477                 : 
     478                 : /************************************************************************/
     479                 : /*                          dataHandlerCbk()                            */
     480                 : /************************************************************************/
     481                 : 
     482             168 : void OGRSVGLayer::dataHandlerCbk(const char *data, int nLen)
     483                 : {
     484             168 :     if (bStopParsing) return;
     485                 : 
     486             168 :     nDataHandlerCounter ++;
     487             168 :     if (nDataHandlerCounter >= BUFSIZ)
     488                 :     {
     489                 :         CPLError(CE_Failure, CPLE_AppDefined,
     490               0 :                  "File probably corrupted (million laugh pattern)");
     491               0 :         XML_StopParser(oParser, XML_FALSE);
     492               0 :         bStopParsing = TRUE;
     493               0 :         return;
     494                 :     }
     495                 : 
     496             168 :     nWithoutEventCounter = 0;
     497                 : 
     498             168 :     if (iCurrentField >= 0)
     499                 :     {
     500                 :         char* pszNewSubElementValue = (char*) VSIRealloc(pszSubElementValue,
     501              11 :                                            nSubElementValueLen + nLen + 1);
     502              11 :         if (pszNewSubElementValue == NULL)
     503                 :         {
     504               0 :             CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
     505               0 :             XML_StopParser(oParser, XML_FALSE);
     506               0 :             bStopParsing = TRUE;
     507               0 :             return;
     508                 :         }
     509              11 :         pszSubElementValue = pszNewSubElementValue;
     510              11 :         memcpy(pszSubElementValue + nSubElementValueLen, data, nLen);
     511              11 :         nSubElementValueLen += nLen;
     512              11 :         if (nSubElementValueLen > 100000)
     513                 :         {
     514                 :             CPLError(CE_Failure, CPLE_AppDefined,
     515               0 :                      "Too much data inside one element. File probably corrupted");
     516               0 :             XML_StopParser(oParser, XML_FALSE);
     517               0 :             bStopParsing = TRUE;
     518                 :         }
     519                 :     }
     520                 : }
     521                 : #endif
     522                 : 
     523                 : /************************************************************************/
     524                 : /*                           GetNextFeature()                           */
     525                 : /************************************************************************/
     526                 : 
     527               3 : OGRFeature *OGRSVGLayer::GetNextFeature()
     528                 : {
     529               3 :     GetLayerDefn();
     530                 : 
     531               3 :     if (fpSVG == NULL)
     532               0 :         return NULL;
     533                 : 
     534               3 :     if (bStopParsing)
     535               0 :         return NULL;
     536                 : 
     537                 : #ifdef HAVE_EXPAT
     538               3 :     if (nFeatureTabIndex < nFeatureTabLength)
     539                 :     {
     540               0 :         return ppoFeatureTab[nFeatureTabIndex++];
     541                 :     }
     542                 :     
     543               3 :     if (VSIFEofL(fpSVG))
     544               0 :         return NULL;
     545                 :     
     546                 :     char aBuf[BUFSIZ];
     547                 :     
     548               3 :     CPLFree(ppoFeatureTab);
     549               3 :     ppoFeatureTab = NULL;
     550               3 :     nFeatureTabLength = 0;
     551               3 :     nFeatureTabIndex = 0;
     552               3 :     nWithoutEventCounter = 0;
     553               3 :     iCurrentField = -1;
     554                 : 
     555                 :     int nDone;
     556               6 :     do
     557                 :     {
     558               6 :         nDataHandlerCounter = 0;
     559                 :         unsigned int nLen = (unsigned int)
     560               6 :                     VSIFReadL( aBuf, 1, sizeof(aBuf), fpSVG );
     561               6 :         nDone = VSIFEofL(fpSVG);
     562               6 :         if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
     563                 :         {
     564                 :             CPLError(CE_Failure, CPLE_AppDefined,
     565                 :                      "XML parsing of SVG file failed : %s at line %d, column %d",
     566                 :                      XML_ErrorString(XML_GetErrorCode(oParser)),
     567                 :                      (int)XML_GetCurrentLineNumber(oParser),
     568               0 :                      (int)XML_GetCurrentColumnNumber(oParser));
     569               0 :             bStopParsing = TRUE;
     570               0 :             break;
     571                 :         }
     572               6 :         nWithoutEventCounter ++;
     573                 :     } while (!nDone && nFeatureTabLength == 0 && !bStopParsing &&
     574                 :              nWithoutEventCounter < 1000);
     575                 : 
     576               3 :     if (nWithoutEventCounter == 1000)
     577                 :     {
     578                 :         CPLError(CE_Failure, CPLE_AppDefined,
     579               0 :                  "Too much data inside one element. File probably corrupted");
     580               0 :         bStopParsing = TRUE;
     581                 :     }
     582                 : 
     583               3 :     return (nFeatureTabLength) ? ppoFeatureTab[nFeatureTabIndex++] : NULL;
     584                 : #else
     585                 :     return NULL;
     586                 : #endif
     587                 : }
     588                 : 
     589                 : /************************************************************************/
     590                 : /*                           GetSpatialRef()                            */
     591                 : /************************************************************************/
     592                 : 
     593               0 : OGRSpatialReference *OGRSVGLayer::GetSpatialRef()
     594                 : 
     595                 : {
     596               0 :     return poSRS;
     597                 : }
     598                 : 
     599                 : /************************************************************************/
     600                 : /*                           TestCapability()                           */
     601                 : /************************************************************************/
     602                 : 
     603               0 : int OGRSVGLayer::TestCapability( const char * pszCap )
     604                 : 
     605                 : {
     606               0 :     if( EQUAL(pszCap,OLCFastFeatureCount) )
     607                 :         return m_poAttrQuery == NULL && m_poFilterGeom == NULL &&
     608               0 :                nTotalFeatures > 0;
     609                 : 
     610               0 :     else if( EQUAL(pszCap,OLCStringsAsUTF8) )
     611               0 :         return TRUE;
     612                 : 
     613                 :     else
     614               0 :         return FALSE;
     615                 : }
     616                 : 
     617                 : 
     618                 : /************************************************************************/
     619                 : /*                       LoadSchema()                         */
     620                 : /************************************************************************/
     621                 : 
     622                 : #ifdef HAVE_EXPAT
     623                 : 
     624              18 : static void XMLCALL startElementLoadSchemaCbk(void *pUserData,
     625                 :                                               const char *pszName,
     626                 :                                               const char **ppszAttr)
     627                 : {
     628              18 :     ((OGRSVGLayer*)pUserData)->startElementLoadSchemaCbk(pszName, ppszAttr);
     629              18 : }
     630                 : 
     631              18 : static void XMLCALL endElementLoadSchemaCbk(void *pUserData, const char *pszName)
     632                 : {
     633              18 :     ((OGRSVGLayer*)pUserData)->endElementLoadSchemaCbk(pszName);
     634              18 : }
     635                 : 
     636              56 : static void XMLCALL dataHandlerLoadSchemaCbk(void *pUserData,
     637                 :                                              const char *data, int nLen)
     638                 : {
     639              56 :     ((OGRSVGLayer*)pUserData)->dataHandlerLoadSchemaCbk(data, nLen);
     640              56 : }
     641                 : 
     642                 : 
     643                 : /** This function parses the whole file to build the schema */
     644               1 : void OGRSVGLayer::LoadSchema()
     645                 : {
     646               1 :     CPLAssert(poFeatureDefn == NULL);
     647                 : 
     648               8 :     for(int i=0;i<poDS->GetLayerCount();i++)
     649                 :     {
     650               3 :         OGRSVGLayer* poLayer = (OGRSVGLayer*)poDS->GetLayer(i);
     651               3 :         poLayer->poFeatureDefn = new OGRFeatureDefn( poLayer->osLayerName );
     652               3 :         poLayer->poFeatureDefn->Reference();
     653               3 :         poLayer->poFeatureDefn->SetGeomType(poLayer->GetGeomType());
     654                 :     }
     655                 : 
     656               1 :     oSchemaParser = OGRCreateExpatXMLParser();
     657                 :     XML_SetElementHandler(oSchemaParser, ::startElementLoadSchemaCbk,
     658               1 :                                          ::endElementLoadSchemaCbk);
     659               1 :     XML_SetCharacterDataHandler(oSchemaParser, ::dataHandlerLoadSchemaCbk);
     660               1 :     XML_SetUserData(oSchemaParser, this);
     661                 : 
     662               1 :     if (fpSVG == NULL)
     663               0 :         return;
     664                 : 
     665               1 :     VSIFSeekL( fpSVG, 0, SEEK_SET );
     666                 : 
     667               1 :     inInterestingElement = FALSE;
     668               1 :     depthLevel = 0;
     669               1 :     nWithoutEventCounter = 0;
     670               1 :     bStopParsing = FALSE;
     671                 : 
     672                 :     char aBuf[BUFSIZ];
     673                 :     int nDone;
     674               2 :     do
     675                 :     {
     676               2 :         nDataHandlerCounter = 0;
     677                 :         unsigned int nLen =
     678               2 :             (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fpSVG );
     679               2 :         nDone = VSIFEofL(fpSVG);
     680               2 :         if (XML_Parse(oSchemaParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
     681                 :         {
     682                 :             CPLError(CE_Failure, CPLE_AppDefined,
     683                 :                      "XML parsing of SVG file failed : %s at line %d, column %d",
     684                 :                      XML_ErrorString(XML_GetErrorCode(oSchemaParser)),
     685                 :                      (int)XML_GetCurrentLineNumber(oSchemaParser),
     686               0 :                      (int)XML_GetCurrentColumnNumber(oSchemaParser));
     687               0 :             bStopParsing = TRUE;
     688               0 :             break;
     689                 :         }
     690               2 :         nWithoutEventCounter ++;
     691                 :     } while (!nDone && !bStopParsing && nWithoutEventCounter < 1000);
     692                 : 
     693               1 :     if (nWithoutEventCounter == 1000)
     694                 :     {
     695                 :         CPLError(CE_Failure, CPLE_AppDefined,
     696               0 :                  "Too much data inside one element. File probably corrupted");
     697               0 :         bStopParsing = TRUE;
     698                 :     }
     699                 : 
     700               1 :     XML_ParserFree(oSchemaParser);
     701               1 :     oSchemaParser = NULL;
     702                 : 
     703               1 :     VSIFSeekL( fpSVG, 0, SEEK_SET );
     704                 : }
     705                 : 
     706                 : 
     707                 : /************************************************************************/
     708                 : /*                  startElementLoadSchemaCbk()                         */
     709                 : /************************************************************************/
     710                 : 
     711              18 : void OGRSVGLayer::startElementLoadSchemaCbk(const char *pszName,
     712                 :                                             const char **ppszAttr)
     713                 : {
     714              18 :     if (bStopParsing) return;
     715                 : 
     716              18 :     nWithoutEventCounter = 0;
     717                 : 
     718              18 :     if (strcmp(pszName, "circle") == 0 &&
     719                 :         strcmp(OGRSVGGetClass(ppszAttr), "point") == 0)
     720                 :     {
     721               1 :         poCurLayer = (OGRSVGLayer*)poDS->GetLayer(0);
     722               1 :         poCurLayer->nTotalFeatures ++;
     723               1 :         inInterestingElement = TRUE;
     724               1 :         interestingDepthLevel = depthLevel;
     725                 :     }
     726              17 :     else if (strcmp(pszName, "path") == 0 &&
     727                 :              strcmp(OGRSVGGetClass(ppszAttr), "line") == 0)
     728                 :     {
     729               1 :         poCurLayer = (OGRSVGLayer*)poDS->GetLayer(1);
     730               1 :         poCurLayer->nTotalFeatures ++;
     731               1 :         inInterestingElement = TRUE;
     732               1 :         interestingDepthLevel = depthLevel;
     733                 :     }
     734              16 :     else if (strcmp(pszName, "path") == 0 &&
     735                 :              strcmp(OGRSVGGetClass(ppszAttr), "polygon") == 0)
     736                 :     {
     737               1 :         poCurLayer = (OGRSVGLayer*)poDS->GetLayer(2);
     738               1 :         poCurLayer->nTotalFeatures ++;
     739               1 :         inInterestingElement = TRUE;
     740               1 :         interestingDepthLevel = depthLevel;
     741                 :     }
     742              15 :     else if (inInterestingElement)
     743                 :     {
     744              11 :         if (depthLevel == interestingDepthLevel + 1 &&
     745                 :             strncmp(pszName, "cm:", 3) == 0)
     746                 :         {
     747              11 :             pszName += 3;
     748              11 :             if (poCurLayer->poFeatureDefn->GetFieldIndex(pszName) < 0)
     749                 :             {
     750              11 :                 OGRFieldDefn oFieldDefn(pszName, OFTString);
     751              11 :                 if (strcmp(pszName, "timestamp") == 0)
     752               3 :                     oFieldDefn.SetType(OFTDateTime);
     753               9 :                 else if (strcmp(pszName, "way_area") == 0 ||
     754                 :                          strcmp(pszName, "area") == 0)
     755               1 :                     oFieldDefn.SetType(OFTReal);
     756               7 :                 else if (strcmp(pszName, "z_order") == 0)
     757               0 :                     oFieldDefn.SetType(OFTInteger);
     758              11 :                 poCurLayer->poFeatureDefn->AddFieldDefn(&oFieldDefn);
     759                 :             }
     760                 :         }
     761                 :     }
     762                 : 
     763              18 :     depthLevel++;
     764                 : }
     765                 : 
     766                 : /************************************************************************/
     767                 : /*                   endElementLoadSchemaCbk()                           */
     768                 : /************************************************************************/
     769                 : 
     770              18 : void OGRSVGLayer::endElementLoadSchemaCbk(const char *pszName)
     771                 : {
     772              18 :     if (bStopParsing) return;
     773                 : 
     774              18 :     nWithoutEventCounter = 0;
     775                 : 
     776              18 :     depthLevel--;
     777                 : 
     778              18 :     if (inInterestingElement &&
     779                 :         depthLevel == interestingDepthLevel)
     780                 :     {
     781               3 :         inInterestingElement = FALSE;
     782                 :     }
     783                 : }
     784                 : 
     785                 : /************************************************************************/
     786                 : /*                   dataHandlerLoadSchemaCbk()                         */
     787                 : /************************************************************************/
     788                 : 
     789              56 : void OGRSVGLayer::dataHandlerLoadSchemaCbk(const char *data, int nLen)
     790                 : {
     791              56 :     if (bStopParsing) return;
     792                 : 
     793              56 :     nDataHandlerCounter ++;
     794              56 :     if (nDataHandlerCounter >= BUFSIZ)
     795                 :     {
     796                 :         CPLError(CE_Failure, CPLE_AppDefined,
     797               0 :                  "File probably corrupted (million laugh pattern)");
     798               0 :         XML_StopParser(oSchemaParser, XML_FALSE);
     799               0 :         bStopParsing = TRUE;
     800               0 :         return;
     801                 :     }
     802                 : 
     803              56 :     nWithoutEventCounter = 0;
     804                 : }
     805                 : #else
     806                 : void OGRSVGLayer::LoadSchema()
     807                 : {
     808                 : }
     809                 : #endif
     810                 : 
     811                 : /************************************************************************/
     812                 : /*                          GetLayerDefn()                              */
     813                 : /************************************************************************/
     814                 : 
     815               6 : OGRFeatureDefn * OGRSVGLayer::GetLayerDefn()
     816                 : {
     817               6 :     if (poFeatureDefn == NULL)
     818                 :     {
     819               1 :         LoadSchema();
     820                 :     }
     821                 : 
     822               6 :     return poFeatureDefn;
     823                 : }
     824                 : 
     825                 : /************************************************************************/
     826                 : /*                           GetGeomType()                              */
     827                 : /************************************************************************/
     828                 : 
     829               3 : OGRwkbGeometryType OGRSVGLayer::GetGeomType()
     830                 : {
     831               3 :     if (svgGeomType == SVG_POINTS)
     832               1 :         return wkbPoint;
     833               2 :     else if (svgGeomType == SVG_LINES)
     834               1 :         return wkbLineString;
     835                 :     else
     836               1 :         return wkbPolygon;
     837                 : }
     838                 : 
     839                 : /************************************************************************/
     840                 : /*                           GetGeomType()                              */
     841                 : /************************************************************************/
     842                 : 
     843               3 : int OGRSVGLayer::GetFeatureCount( int bForce )
     844                 : {
     845               3 :     if (m_poAttrQuery != NULL || m_poFilterGeom != NULL)
     846               0 :         return OGRLayer::GetFeatureCount(bForce);
     847                 : 
     848               3 :     GetLayerDefn();
     849                 : 
     850               3 :     return nTotalFeatures;
     851                 : }

Generated by: LCOV version 1.7