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 6 : OGRSVGLayer::OGRSVGLayer( const char* pszFilename,
40 : const char* pszLayerName,
41 : SVGGeometryType svgGeomType,
42 6 : OGRSVGDataSource* poDS)
43 :
44 : {
45 6 : nNextFID = 0;
46 :
47 6 : this->poDS = poDS;
48 6 : this->svgGeomType = svgGeomType;
49 6 : osLayerName = pszLayerName;
50 :
51 6 : poFeatureDefn = NULL;
52 :
53 6 : nTotalFeatures = 0;
54 :
55 6 : ppoFeatureTab = NULL;
56 6 : nFeatureTabIndex = 0;
57 6 : nFeatureTabLength = 0;
58 6 : pszSubElementValue = NULL;
59 6 : nSubElementValueLen = 0;
60 6 : 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 6 : "AXIS[\"Y\",NORTH]]");
84 :
85 6 : poFeature = NULL;
86 :
87 : #ifdef HAVE_EXPAT
88 6 : oParser = NULL;
89 : #endif
90 :
91 12 : fpSVG = VSIFOpenL( pszFilename, "r" );
92 6 : if( fpSVG == NULL )
93 : {
94 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s", pszFilename);
95 0 : return;
96 : }
97 :
98 6 : ResetReading();
99 0 : }
100 :
101 : /************************************************************************/
102 : /* ~OGRSVGLayer() */
103 : /************************************************************************/
104 :
105 6 : OGRSVGLayer::~OGRSVGLayer()
106 :
107 : {
108 : #ifdef HAVE_EXPAT
109 6 : if (oParser)
110 6 : XML_ParserFree(oParser);
111 : #endif
112 6 : if (poFeatureDefn)
113 6 : poFeatureDefn->Release();
114 :
115 6 : if( poSRS != NULL )
116 6 : poSRS->Release();
117 :
118 6 : CPLFree(pszSubElementValue);
119 :
120 : int i;
121 6 : for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
122 0 : delete ppoFeatureTab[i];
123 6 : CPLFree(ppoFeatureTab);
124 :
125 6 : if (poFeature)
126 0 : delete poFeature;
127 :
128 6 : if (fpSVG)
129 6 : VSIFCloseL( fpSVG );
130 6 : }
131 :
132 : #ifdef HAVE_EXPAT
133 :
134 108 : static void XMLCALL startElementCbk(void *pUserData,
135 : const char *pszName, const char **ppszAttr)
136 : {
137 108 : ((OGRSVGLayer*)pUserData)->startElementCbk(pszName, ppszAttr);
138 108 : }
139 :
140 108 : static void XMLCALL endElementCbk(void *pUserData, const char *pszName)
141 : {
142 108 : ((OGRSVGLayer*)pUserData)->endElementCbk(pszName);
143 108 : }
144 :
145 336 : static void XMLCALL dataHandlerCbk(void *pUserData, const char *data, int nLen)
146 : {
147 336 : ((OGRSVGLayer*)pUserData)->dataHandlerCbk(data, nLen);
148 336 : }
149 :
150 : #endif
151 :
152 : /************************************************************************/
153 : /* ResetReading() */
154 : /************************************************************************/
155 :
156 6 : void OGRSVGLayer::ResetReading()
157 :
158 : {
159 6 : nNextFID = 0;
160 6 : if (fpSVG)
161 : {
162 6 : VSIFSeekL( fpSVG, 0, SEEK_SET );
163 : #ifdef HAVE_EXPAT
164 6 : if (oParser)
165 0 : XML_ParserFree(oParser);
166 :
167 6 : oParser = OGRCreateExpatXMLParser();
168 6 : XML_SetElementHandler(oParser, ::startElementCbk, ::endElementCbk);
169 6 : XML_SetCharacterDataHandler(oParser, ::dataHandlerCbk);
170 6 : XML_SetUserData(oParser, this);
171 : #endif
172 : }
173 :
174 6 : CPLFree(pszSubElementValue);
175 6 : pszSubElementValue = NULL;
176 6 : nSubElementValueLen = 0;
177 6 : iCurrentField = -1;
178 :
179 : int i;
180 6 : for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
181 0 : delete ppoFeatureTab[i];
182 6 : CPLFree(ppoFeatureTab);
183 6 : nFeatureTabIndex = 0;
184 6 : nFeatureTabLength = 0;
185 6 : ppoFeatureTab = NULL;
186 6 : if (poFeature)
187 0 : delete poFeature;
188 6 : poFeature = NULL;
189 :
190 6 : depthLevel = 0;
191 6 : interestingDepthLevel = 0;
192 6 : inInterestingElement = FALSE;
193 6 : }
194 :
195 : #ifdef HAVE_EXPAT
196 :
197 : /************************************************************************/
198 : /* OGRSVGGetClass() */
199 : /************************************************************************/
200 :
201 18 : static const char* OGRSVGGetClass(const char **ppszAttr)
202 : {
203 18 : const char** ppszIter = ppszAttr;
204 56 : while(*ppszIter)
205 : {
206 38 : if (strcmp(ppszIter[0], "class") == 0)
207 18 : return ppszIter[1];
208 20 : ppszIter += 2;
209 : }
210 0 : return "";
211 : }
212 :
213 : /************************************************************************/
214 : /* OGRSVGParseD() */
215 : /************************************************************************/
216 :
217 4 : static void OGRSVGParseD(OGRLineString* poLS, const char* pszD)
218 : {
219 : char szBuffer[32];
220 4 : int iBuffer = 0;
221 4 : const char* pszIter = pszD;
222 : char ch;
223 4 : int iNumber = 0;
224 4 : double dfPrevNumber = 0;
225 4 : int bRelativeLineto = FALSE;
226 4 : double dfX = 0, dfY = 0;
227 4 : int nPointCount = 0;
228 17998 : while(TRUE)
229 : {
230 18002 : ch = *(pszIter ++);
231 :
232 18006 : if (ch == 'M' || ch == 'm')
233 : {
234 4 : if (nPointCount != 0)
235 : {
236 0 : CPLDebug("SVG", "Not ready to handle M/m not at the beginning");
237 0 : return;
238 : }
239 : }
240 17998 : else if (ch == 'L')
241 : {
242 4 : bRelativeLineto = FALSE;
243 : }
244 17994 : 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 17994 : else if (ch == 'z' || ch == 'Z')
254 : {
255 2 : poLS->closeRings();
256 2 : return;
257 : }
258 35256 : else if (ch == '+' || ch == '-' || ch == '.' ||
259 : (ch >= '0' && ch <= '9'))
260 : {
261 17264 : if (iBuffer == 30)
262 : {
263 0 : CPLDebug("SVG", "Too big number");
264 0 : return;
265 : }
266 17264 : szBuffer[iBuffer ++] = ch;
267 : }
268 728 : else if (ch == ' ' || ch == 0)
269 : {
270 728 : if (iBuffer > 0)
271 : {
272 720 : szBuffer[iBuffer] = 0;
273 720 : if (iNumber == 1)
274 : {
275 : /* Cloudmade --> negate y */
276 360 : double dfNumber = -CPLAtof(szBuffer);
277 :
278 360 : if (bRelativeLineto)
279 : {
280 0 : dfX += dfPrevNumber;
281 0 : dfY += dfNumber;
282 : }
283 : else
284 : {
285 360 : dfX = dfPrevNumber;
286 360 : dfY = dfNumber;
287 : }
288 360 : poLS->addPoint(dfX, dfY);
289 360 : nPointCount ++;
290 :
291 360 : iNumber = 0;
292 : }
293 : else
294 : {
295 360 : iNumber = 1;
296 360 : dfPrevNumber = CPLAtof(szBuffer);
297 : }
298 :
299 720 : iBuffer = 0;
300 : }
301 728 : if (ch == 0)
302 2 : break;
303 : }
304 : }
305 : }
306 :
307 : /************************************************************************/
308 : /* startElementCbk() */
309 : /************************************************************************/
310 :
311 108 : void OGRSVGLayer::startElementCbk(const char *pszName, const char **ppszAttr)
312 : {
313 : int i;
314 :
315 108 : if (bStopParsing) return;
316 :
317 108 : nWithoutEventCounter = 0;
318 :
319 108 : if (svgGeomType == SVG_POINTS &&
320 : strcmp(pszName, "circle") == 0 &&
321 : strcmp(OGRSVGGetClass(ppszAttr), "point") == 0)
322 : {
323 2 : int bHasFoundX = FALSE, bHasFoundY = FALSE;
324 2 : double dfX = 0, dfY = 0;
325 12 : for (i = 0; ppszAttr[i]; i += 2)
326 : {
327 10 : if (strcmp(ppszAttr[i], "cx") == 0)
328 : {
329 2 : bHasFoundX = TRUE;
330 2 : dfX = CPLAtof(ppszAttr[i + 1]);
331 : }
332 8 : else if (strcmp(ppszAttr[i], "cy") == 0)
333 : {
334 2 : bHasFoundY = TRUE;
335 : /* Cloudmade --> negate y */
336 2 : dfY = - CPLAtof(ppszAttr[i + 1]);
337 : }
338 : }
339 2 : if (bHasFoundX && bHasFoundY)
340 : {
341 2 : interestingDepthLevel = depthLevel;
342 2 : inInterestingElement = TRUE;
343 :
344 2 : if (poFeature)
345 0 : delete poFeature;
346 :
347 2 : poFeature = new OGRFeature( poFeatureDefn );
348 :
349 2 : poFeature->SetFID( nNextFID++ );
350 4 : OGRPoint* poPoint = new OGRPoint( dfX, dfY );
351 2 : poPoint->assignSpatialReference(poSRS);
352 2 : poFeature->SetGeometryDirectly( poPoint );
353 : }
354 : }
355 106 : else if (svgGeomType == SVG_LINES &&
356 : strcmp(pszName, "path") == 0 &&
357 : strcmp(OGRSVGGetClass(ppszAttr), "line") == 0)
358 : {
359 2 : const char* pszD = NULL;
360 2 : for (i = 0; ppszAttr[i]; i += 2)
361 : {
362 2 : if (strcmp(ppszAttr[i], "d") == 0)
363 : {
364 2 : pszD = ppszAttr[i + 1];
365 2 : break;
366 : }
367 : }
368 2 : if (pszD)
369 : {
370 2 : interestingDepthLevel = depthLevel;
371 2 : inInterestingElement = TRUE;
372 :
373 2 : if (poFeature)
374 0 : delete poFeature;
375 :
376 2 : poFeature = new OGRFeature( poFeatureDefn );
377 :
378 2 : poFeature->SetFID( nNextFID++ );
379 4 : OGRLineString* poLS = new OGRLineString();
380 2 : OGRSVGParseD(poLS, pszD);
381 2 : poLS->assignSpatialReference(poSRS);
382 2 : poFeature->SetGeometryDirectly( poLS );
383 : }
384 : }
385 104 : else if (svgGeomType == SVG_POLYGONS &&
386 : strcmp(pszName, "path") == 0 &&
387 : strcmp(OGRSVGGetClass(ppszAttr), "polygon") == 0)
388 : {
389 2 : const char* pszD = NULL;
390 2 : for (i = 0; ppszAttr[i]; i += 2)
391 : {
392 2 : if (strcmp(ppszAttr[i], "d") == 0)
393 : {
394 2 : pszD = ppszAttr[i + 1];
395 2 : break;
396 : }
397 : }
398 2 : if (pszD)
399 : {
400 2 : interestingDepthLevel = depthLevel;
401 2 : inInterestingElement = TRUE;
402 :
403 2 : if (poFeature)
404 0 : delete poFeature;
405 :
406 2 : poFeature = new OGRFeature( poFeatureDefn );
407 :
408 2 : poFeature->SetFID( nNextFID++ );
409 4 : OGRPolygon* poPolygon = new OGRPolygon();
410 4 : OGRLinearRing* poLS = new OGRLinearRing();
411 2 : OGRSVGParseD(poLS, pszD);
412 2 : poPolygon->addRingDirectly(poLS);
413 2 : poPolygon->assignSpatialReference(poSRS);
414 2 : poFeature->SetGeometryDirectly( poPolygon );
415 : }
416 : }
417 102 : else if (inInterestingElement &&
418 : depthLevel == interestingDepthLevel + 1 &&
419 : strncmp(pszName, "cm:", 3) == 0)
420 : {
421 22 : iCurrentField = poFeatureDefn->GetFieldIndex(pszName + 3);
422 : }
423 :
424 108 : depthLevel++;
425 : }
426 :
427 : /************************************************************************/
428 : /* endElementCbk() */
429 : /************************************************************************/
430 :
431 108 : void OGRSVGLayer::endElementCbk(const char *pszName)
432 : {
433 108 : if (bStopParsing) return;
434 :
435 108 : nWithoutEventCounter = 0;
436 :
437 108 : depthLevel--;
438 :
439 108 : if (inInterestingElement)
440 : {
441 28 : if (depthLevel == interestingDepthLevel)
442 : {
443 6 : inInterestingElement = FALSE;
444 :
445 6 : 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 6 : sizeof(OGRFeature*) * (nFeatureTabLength + 1));
453 6 : ppoFeatureTab[nFeatureTabLength] = poFeature;
454 6 : nFeatureTabLength++;
455 : }
456 : else
457 : {
458 0 : delete poFeature;
459 : }
460 6 : poFeature = NULL;
461 : }
462 22 : else if (depthLevel == interestingDepthLevel + 1)
463 : {
464 22 : if (poFeature && iCurrentField >= 0 && nSubElementValueLen)
465 : {
466 22 : pszSubElementValue[nSubElementValueLen] = 0;
467 22 : poFeature->SetField( iCurrentField, pszSubElementValue);
468 : }
469 :
470 22 : CPLFree(pszSubElementValue);
471 22 : pszSubElementValue = NULL;
472 22 : nSubElementValueLen = 0;
473 22 : iCurrentField = -1;
474 : }
475 : }
476 : }
477 :
478 : /************************************************************************/
479 : /* dataHandlerCbk() */
480 : /************************************************************************/
481 :
482 336 : void OGRSVGLayer::dataHandlerCbk(const char *data, int nLen)
483 : {
484 336 : if (bStopParsing) return;
485 :
486 336 : nDataHandlerCounter ++;
487 336 : 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 336 : nWithoutEventCounter = 0;
497 :
498 336 : if (iCurrentField >= 0)
499 : {
500 : char* pszNewSubElementValue = (char*) VSIRealloc(pszSubElementValue,
501 22 : nSubElementValueLen + nLen + 1);
502 22 : 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 22 : pszSubElementValue = pszNewSubElementValue;
510 22 : memcpy(pszSubElementValue + nSubElementValueLen, data, nLen);
511 22 : nSubElementValueLen += nLen;
512 22 : 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 6 : OGRFeature *OGRSVGLayer::GetNextFeature()
528 : {
529 6 : GetLayerDefn();
530 :
531 6 : if (fpSVG == NULL)
532 0 : return NULL;
533 :
534 6 : if (bStopParsing)
535 0 : return NULL;
536 :
537 : #ifdef HAVE_EXPAT
538 6 : if (nFeatureTabIndex < nFeatureTabLength)
539 : {
540 0 : return ppoFeatureTab[nFeatureTabIndex++];
541 : }
542 :
543 6 : if (VSIFEofL(fpSVG))
544 0 : return NULL;
545 :
546 : char aBuf[BUFSIZ];
547 :
548 6 : CPLFree(ppoFeatureTab);
549 6 : ppoFeatureTab = NULL;
550 6 : nFeatureTabLength = 0;
551 6 : nFeatureTabIndex = 0;
552 6 : nWithoutEventCounter = 0;
553 6 : iCurrentField = -1;
554 :
555 : int nDone;
556 12 : do
557 : {
558 12 : nDataHandlerCounter = 0;
559 : unsigned int nLen = (unsigned int)
560 12 : VSIFReadL( aBuf, 1, sizeof(aBuf), fpSVG );
561 12 : nDone = VSIFEofL(fpSVG);
562 12 : 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 12 : nWithoutEventCounter ++;
573 : } while (!nDone && nFeatureTabLength == 0 && !bStopParsing &&
574 : nWithoutEventCounter < 1000);
575 :
576 6 : 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 6 : 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 36 : static void XMLCALL startElementLoadSchemaCbk(void *pUserData,
625 : const char *pszName,
626 : const char **ppszAttr)
627 : {
628 36 : ((OGRSVGLayer*)pUserData)->startElementLoadSchemaCbk(pszName, ppszAttr);
629 36 : }
630 :
631 36 : static void XMLCALL endElementLoadSchemaCbk(void *pUserData, const char *pszName)
632 : {
633 36 : ((OGRSVGLayer*)pUserData)->endElementLoadSchemaCbk(pszName);
634 36 : }
635 :
636 112 : static void XMLCALL dataHandlerLoadSchemaCbk(void *pUserData,
637 : const char *data, int nLen)
638 : {
639 112 : ((OGRSVGLayer*)pUserData)->dataHandlerLoadSchemaCbk(data, nLen);
640 112 : }
641 :
642 :
643 : /** This function parses the whole file to build the schema */
644 2 : void OGRSVGLayer::LoadSchema()
645 : {
646 2 : CPLAssert(poFeatureDefn == NULL);
647 :
648 16 : for(int i=0;i<poDS->GetLayerCount();i++)
649 : {
650 6 : OGRSVGLayer* poLayer = (OGRSVGLayer*)poDS->GetLayer(i);
651 6 : poLayer->poFeatureDefn = new OGRFeatureDefn( poLayer->osLayerName );
652 6 : poLayer->poFeatureDefn->Reference();
653 6 : poLayer->poFeatureDefn->SetGeomType(poLayer->GetGeomType());
654 : }
655 :
656 2 : oSchemaParser = OGRCreateExpatXMLParser();
657 : XML_SetElementHandler(oSchemaParser, ::startElementLoadSchemaCbk,
658 2 : ::endElementLoadSchemaCbk);
659 2 : XML_SetCharacterDataHandler(oSchemaParser, ::dataHandlerLoadSchemaCbk);
660 2 : XML_SetUserData(oSchemaParser, this);
661 :
662 2 : if (fpSVG == NULL)
663 0 : return;
664 :
665 2 : VSIFSeekL( fpSVG, 0, SEEK_SET );
666 :
667 2 : inInterestingElement = FALSE;
668 2 : depthLevel = 0;
669 2 : nWithoutEventCounter = 0;
670 2 : bStopParsing = FALSE;
671 :
672 : char aBuf[BUFSIZ];
673 : int nDone;
674 4 : do
675 : {
676 4 : nDataHandlerCounter = 0;
677 : unsigned int nLen =
678 4 : (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fpSVG );
679 4 : nDone = VSIFEofL(fpSVG);
680 4 : 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 4 : nWithoutEventCounter ++;
691 : } while (!nDone && !bStopParsing && nWithoutEventCounter < 1000);
692 :
693 2 : 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 2 : XML_ParserFree(oSchemaParser);
701 2 : oSchemaParser = NULL;
702 :
703 2 : VSIFSeekL( fpSVG, 0, SEEK_SET );
704 : }
705 :
706 :
707 : /************************************************************************/
708 : /* startElementLoadSchemaCbk() */
709 : /************************************************************************/
710 :
711 36 : void OGRSVGLayer::startElementLoadSchemaCbk(const char *pszName,
712 : const char **ppszAttr)
713 : {
714 36 : if (bStopParsing) return;
715 :
716 36 : nWithoutEventCounter = 0;
717 :
718 36 : if (strcmp(pszName, "circle") == 0 &&
719 : strcmp(OGRSVGGetClass(ppszAttr), "point") == 0)
720 : {
721 2 : poCurLayer = (OGRSVGLayer*)poDS->GetLayer(0);
722 2 : poCurLayer->nTotalFeatures ++;
723 2 : inInterestingElement = TRUE;
724 2 : interestingDepthLevel = depthLevel;
725 : }
726 34 : else if (strcmp(pszName, "path") == 0 &&
727 : strcmp(OGRSVGGetClass(ppszAttr), "line") == 0)
728 : {
729 2 : poCurLayer = (OGRSVGLayer*)poDS->GetLayer(1);
730 2 : poCurLayer->nTotalFeatures ++;
731 2 : inInterestingElement = TRUE;
732 2 : interestingDepthLevel = depthLevel;
733 : }
734 32 : else if (strcmp(pszName, "path") == 0 &&
735 : strcmp(OGRSVGGetClass(ppszAttr), "polygon") == 0)
736 : {
737 2 : poCurLayer = (OGRSVGLayer*)poDS->GetLayer(2);
738 2 : poCurLayer->nTotalFeatures ++;
739 2 : inInterestingElement = TRUE;
740 2 : interestingDepthLevel = depthLevel;
741 : }
742 30 : else if (inInterestingElement)
743 : {
744 22 : if (depthLevel == interestingDepthLevel + 1 &&
745 : strncmp(pszName, "cm:", 3) == 0)
746 : {
747 22 : pszName += 3;
748 22 : if (poCurLayer->poFeatureDefn->GetFieldIndex(pszName) < 0)
749 : {
750 22 : OGRFieldDefn oFieldDefn(pszName, OFTString);
751 22 : if (strcmp(pszName, "timestamp") == 0)
752 6 : oFieldDefn.SetType(OFTDateTime);
753 18 : else if (strcmp(pszName, "way_area") == 0 ||
754 : strcmp(pszName, "area") == 0)
755 2 : oFieldDefn.SetType(OFTReal);
756 14 : else if (strcmp(pszName, "z_order") == 0)
757 0 : oFieldDefn.SetType(OFTInteger);
758 22 : poCurLayer->poFeatureDefn->AddFieldDefn(&oFieldDefn);
759 : }
760 : }
761 : }
762 :
763 36 : depthLevel++;
764 : }
765 :
766 : /************************************************************************/
767 : /* endElementLoadSchemaCbk() */
768 : /************************************************************************/
769 :
770 36 : void OGRSVGLayer::endElementLoadSchemaCbk(const char *pszName)
771 : {
772 36 : if (bStopParsing) return;
773 :
774 36 : nWithoutEventCounter = 0;
775 :
776 36 : depthLevel--;
777 :
778 36 : if (inInterestingElement &&
779 : depthLevel == interestingDepthLevel)
780 : {
781 6 : inInterestingElement = FALSE;
782 : }
783 : }
784 :
785 : /************************************************************************/
786 : /* dataHandlerLoadSchemaCbk() */
787 : /************************************************************************/
788 :
789 112 : void OGRSVGLayer::dataHandlerLoadSchemaCbk(const char *data, int nLen)
790 : {
791 112 : if (bStopParsing) return;
792 :
793 112 : nDataHandlerCounter ++;
794 112 : 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 112 : nWithoutEventCounter = 0;
804 : }
805 : #else
806 : void OGRSVGLayer::LoadSchema()
807 : {
808 : }
809 : #endif
810 :
811 : /************************************************************************/
812 : /* GetLayerDefn() */
813 : /************************************************************************/
814 :
815 12 : OGRFeatureDefn * OGRSVGLayer::GetLayerDefn()
816 : {
817 12 : if (poFeatureDefn == NULL)
818 : {
819 2 : LoadSchema();
820 : }
821 :
822 12 : return poFeatureDefn;
823 : }
824 :
825 : /************************************************************************/
826 : /* GetGeomType() */
827 : /************************************************************************/
828 :
829 6 : OGRwkbGeometryType OGRSVGLayer::GetGeomType()
830 : {
831 6 : if (svgGeomType == SVG_POINTS)
832 2 : return wkbPoint;
833 4 : else if (svgGeomType == SVG_LINES)
834 2 : return wkbLineString;
835 : else
836 2 : return wkbPolygon;
837 : }
838 :
839 : /************************************************************************/
840 : /* GetGeomType() */
841 : /************************************************************************/
842 :
843 6 : int OGRSVGLayer::GetFeatureCount( int bForce )
844 : {
845 6 : if (m_poAttrQuery != NULL || m_poFilterGeom != NULL)
846 0 : return OGRLayer::GetFeatureCount(bForce);
847 :
848 6 : GetLayerDefn();
849 :
850 6 : return nTotalFeatures;
851 : }
|