1 /******************************************************************************
2  *
3  * Project:  OpenGIS Simple Features Reference Implementation
4  * Purpose:  Feature Representation string API
5  * Author:   Stephane Villeneuve, stephane.v@videotron.ca
6  *
7  ******************************************************************************
8  * Copyright (c) 2000-2001, Stephane Villeneuve
9  * Copyright (c) 2008-2010, Even Rouault <even dot rouault at spatialys.com>
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 "cpl_port.h"
31 #include "ogr_featurestyle.h"
32 
33 #include <cstddef>
34 #include <cstdio>
35 #include <cstdlib>
36 #include <cstring>
37 
38 #include <string>
39 
40 #include "cpl_conv.h"
41 #include "cpl_error.h"
42 #include "cpl_string.h"
43 #include "cpl_vsi.h"
44 #include "ogr_api.h"
45 #include "ogr_core.h"
46 #include "ogr_feature.h"
47 
48 CPL_CVSID("$Id: ogrfeaturestyle.cpp 2d686cadda65aebe1463aa2b7aaf7bfbcf992cdc 2020-10-03 17:16:57 -0400 Dylan Sutton $")
49 
50 /****************************************************************************/
51 /*                Class Parameter (used in the String)                      */
52 /*                                                                          */
53 /*      The order of all parameter MUST be the same than in the definition. */
54 /****************************************************************************/
55 static const OGRStyleParamId asStylePen[] =
56 {
57     {OGRSTPenColor, "c", FALSE, OGRSTypeString},
58     {OGRSTPenWidth, "w", TRUE, OGRSTypeDouble},
59     // Georefed, but multiple times.
60     {OGRSTPenPattern, "p", FALSE, OGRSTypeString},
61     {OGRSTPenId, "id", FALSE, OGRSTypeString},
62     {OGRSTPenPerOffset, "dp", TRUE, OGRSTypeDouble},
63     {OGRSTPenCap, "cap", FALSE, OGRSTypeString},
64     {OGRSTPenJoin, "j", FALSE, OGRSTypeString},
65     {OGRSTPenPriority,  "l",  FALSE,  OGRSTypeInteger}
66 };
67 
68 static const OGRStyleParamId asStyleBrush[] =
69 {
70     {OGRSTBrushFColor, "fc", FALSE, OGRSTypeString},
71     {OGRSTBrushBColor, "bc", FALSE, OGRSTypeString},
72     {OGRSTBrushId, "id", FALSE, OGRSTypeString},
73     {OGRSTBrushAngle, "a", FALSE, OGRSTypeDouble},
74     {OGRSTBrushSize, "s", TRUE, OGRSTypeDouble},
75     {OGRSTBrushDx, "dx", TRUE, OGRSTypeDouble},
76     {OGRSTBrushDy, "dy", TRUE, OGRSTypeDouble},
77     {OGRSTBrushPriority, "l", FALSE, OGRSTypeInteger}
78 };
79 
80 static const OGRStyleParamId asStyleSymbol[] =
81 {
82     {OGRSTSymbolId, "id", FALSE, OGRSTypeString},
83     {OGRSTSymbolAngle, "a", FALSE, OGRSTypeDouble},
84     {OGRSTSymbolColor, "c", FALSE, OGRSTypeString},
85     {OGRSTSymbolSize, "s", TRUE, OGRSTypeDouble},
86     {OGRSTSymbolDx, "dx", TRUE, OGRSTypeDouble},
87     {OGRSTSymbolDy, "dy", TRUE, OGRSTypeDouble},
88     {OGRSTSymbolStep, "ds", TRUE, OGRSTypeDouble},
89     {OGRSTSymbolPerp, "dp", TRUE, OGRSTypeDouble},
90     {OGRSTSymbolOffset, "di", TRUE, OGRSTypeDouble},
91     {OGRSTSymbolPriority, "l", FALSE, OGRSTypeInteger},
92     {OGRSTSymbolFontName, "f", FALSE, OGRSTypeString},
93     {OGRSTSymbolOColor, "o", FALSE, OGRSTypeString}
94 };
95 
96 static const OGRStyleParamId asStyleLabel[] =
97 {
98     {OGRSTLabelFontName, "f", FALSE, OGRSTypeString},
99     {OGRSTLabelSize, "s", TRUE, OGRSTypeDouble},
100     {OGRSTLabelTextString, "t", FALSE, OGRSTypeString},
101     {OGRSTLabelAngle, "a", FALSE, OGRSTypeDouble},
102     {OGRSTLabelFColor, "c", FALSE, OGRSTypeString},
103     {OGRSTLabelBColor, "b", FALSE, OGRSTypeString},
104     {OGRSTLabelPlacement, "m", FALSE, OGRSTypeString},
105     {OGRSTLabelAnchor, "p", FALSE, OGRSTypeInteger},
106     {OGRSTLabelDx, "dx", TRUE, OGRSTypeDouble},
107     {OGRSTLabelDy, "dy", TRUE, OGRSTypeDouble},
108     {OGRSTLabelPerp, "dp", TRUE, OGRSTypeDouble},
109     {OGRSTLabelBold, "bo", FALSE, OGRSTypeBoolean},
110     {OGRSTLabelItalic, "it", FALSE, OGRSTypeBoolean},
111     {OGRSTLabelUnderline, "un", FALSE, OGRSTypeBoolean},
112     {OGRSTLabelPriority, "l", FALSE, OGRSTypeInteger},
113     {OGRSTLabelStrikeout, "st", FALSE, OGRSTypeBoolean},
114     {OGRSTLabelStretch, "w", FALSE, OGRSTypeDouble},
115     {-1, nullptr, FALSE, OGRSTypeUnused}, // was OGRSTLabelAdjHor
116     {-1, nullptr, FALSE, OGRSTypeUnused}, // was OGRSTLabelAdjVert
117     {OGRSTLabelHColor, "h", FALSE, OGRSTypeString},
118     {OGRSTLabelOColor, "o", FALSE, OGRSTypeString}
119 };
120 
121 /* ======================================================================== */
122 /* OGRStyleMgr                                                              */
123 /* ======================================================================== */
124 
125 /****************************************************************************/
126 /*             OGRStyleMgr::OGRStyleMgr(OGRStyleTable *poDataSetStyleTable) */
127 /*                                                                          */
128 /****************************************************************************/
129 /**
130  * \brief Constructor.
131  *
132  * This method is the same as the C function OGR_SM_Create()
133  *
134  * @param poDataSetStyleTable (currently unused, reserved for future use),
135  * pointer to OGRStyleTable. Pass NULL for now.
136  */
OGRStyleMgr(OGRStyleTable * poDataSetStyleTable)137 OGRStyleMgr::OGRStyleMgr( OGRStyleTable *poDataSetStyleTable ):
138     m_poDataSetStyleTable( poDataSetStyleTable )
139 {
140 }
141 
142 /************************************************************************/
143 /*                            OGR_SM_Create()                           */
144 /************************************************************************/
145 /**
146  * \brief OGRStyleMgr factory.
147  *
148  * This function is the same as the C++ method OGRStyleMgr::OGRStyleMgr().
149  *
150  * @param hStyleTable pointer to OGRStyleTable or NULL if not working with
151  *  a style table.
152  *
153  * @return a handle to the new style manager object.
154  */
155 
OGR_SM_Create(OGRStyleTableH hStyleTable)156 OGRStyleMgrH OGR_SM_Create( OGRStyleTableH hStyleTable )
157 
158 {
159     return reinterpret_cast<OGRStyleMgrH>(
160         new OGRStyleMgr(reinterpret_cast<OGRStyleTable *>(hStyleTable)));
161 }
162 
163 /****************************************************************************/
164 /*             OGRStyleMgr::~OGRStyleMgr()                                  */
165 /*                                                                          */
166 /****************************************************************************/
167 /**
168  * \brief Destructor.
169  *
170  * This method is the same as the C function OGR_SM_Destroy()
171  */
~OGRStyleMgr()172 OGRStyleMgr::~OGRStyleMgr()
173 {
174     CPLFree(m_pszStyleString);
175 }
176 
177 /************************************************************************/
178 /*                           OGR_SM_Destroy()                            */
179 /************************************************************************/
180 /**
181  * \brief Destroy Style Manager
182  *
183  * This function is the same as the C++ method OGRStyleMgr::~OGRStyleMgr().
184  *
185  * @param hSM handle to the style manager to destroy.
186  */
187 
OGR_SM_Destroy(OGRStyleMgrH hSM)188 void OGR_SM_Destroy( OGRStyleMgrH hSM )
189 
190 {
191     delete reinterpret_cast<OGRStyleMgr *>(hSM);
192 }
193 
194 /****************************************************************************/
195 /*      GBool OGRStyleMgr::SetFeatureStyleString(OGRFeature *poFeature,     */
196 /*                                       char *pszStyleString,              */
197 /*                                       GBool bNoMatching)                 */
198 /*      Set the given representation to the feature,                        */
199 /*      if bNoMatching == TRUE, don't try to find it in the styletable      */
200 /*      otherwise, we will use the name defined in the styletable.          */
201 /****************************************************************************/
202 
203 /**
204  * \brief Set a style in a feature
205  *
206  * @param poFeature       the feature object to store the style in
207  * @param pszStyleString  the style to store
208  * @param bNoMatching     TRUE to lookup the style in the style table and
209  *  add the name to the feature
210  *
211  * @return TRUE on success, FALSE on error.
212  */
213 
SetFeatureStyleString(OGRFeature * poFeature,const char * pszStyleString,GBool bNoMatching)214 GBool OGRStyleMgr::SetFeatureStyleString( OGRFeature *poFeature,
215                                           const char *pszStyleString,
216                                           GBool bNoMatching )
217 {
218     if( poFeature == nullptr )
219         return FALSE;
220 
221     const char *pszName = nullptr;
222 
223     if( pszStyleString == nullptr )
224         poFeature->SetStyleString("");
225     else if( bNoMatching == TRUE )
226         poFeature->SetStyleString(pszStyleString);
227     else if( (pszName = GetStyleName(pszStyleString)) != nullptr )
228         poFeature->SetStyleString(pszName);
229     else
230         poFeature->SetStyleString(pszStyleString);
231 
232     return TRUE;
233 }
234 
235 /****************************************************************************/
236 /*            const char *OGRStyleMgr::InitFromFeature(OGRFeature *)        */
237 /*                                                                          */
238 /****************************************************************************/
239 
240 /**
241  * \brief Initialize style manager from the style string of a feature.
242  *
243  * This method is the same as the C function OGR_SM_InitFromFeature().
244  *
245  * @param poFeature feature object from which to read the style.
246  *
247  * @return a reference to the style string read from the feature, or NULL
248  * in case of error..
249  */
250 
InitFromFeature(OGRFeature * poFeature)251 const char *OGRStyleMgr::InitFromFeature( OGRFeature *poFeature )
252 {
253     CPLFree(m_pszStyleString);
254     m_pszStyleString = nullptr;
255 
256     if( poFeature )
257         InitStyleString(poFeature->GetStyleString());
258     else
259         m_pszStyleString = nullptr;
260 
261     return m_pszStyleString;
262 }
263 
264 /************************************************************************/
265 /*                     OGR_SM_InitFromFeature()                         */
266 /************************************************************************/
267 
268 /**
269  * \brief Initialize style manager from the style string of a feature.
270  *
271  * This function is the same as the C++ method
272  * OGRStyleMgr::InitFromFeature().
273  *
274  * @param hSM handle to the style manager.
275  * @param hFeat handle to the new feature from which to read the style.
276  *
277  * @return a reference to the style string read from the feature, or NULL
278  * in case of error.
279  */
280 
OGR_SM_InitFromFeature(OGRStyleMgrH hSM,OGRFeatureH hFeat)281 const char *OGR_SM_InitFromFeature( OGRStyleMgrH hSM, OGRFeatureH hFeat )
282 
283 {
284     VALIDATE_POINTER1( hSM, "OGR_SM_InitFromFeature", nullptr );
285     VALIDATE_POINTER1( hFeat, "OGR_SM_InitFromFeature", nullptr );
286 
287     return reinterpret_cast<OGRStyleMgr *>(hSM)->
288         InitFromFeature(reinterpret_cast<OGRFeature *>(hFeat));
289 }
290 
291 /****************************************************************************/
292 /*            GBool OGRStyleMgr::InitStyleString(char *pszStyleString)      */
293 /*                                                                          */
294 /****************************************************************************/
295 
296 /**
297  * \brief Initialize style manager from the style string.
298  *
299  * This method is the same as the C function OGR_SM_InitStyleString().
300  *
301  * @param pszStyleString the style string to use (can be NULL).
302  *
303  * @return TRUE on success, FALSE on errors.
304  */
InitStyleString(const char * pszStyleString)305 GBool OGRStyleMgr::InitStyleString( const char *pszStyleString )
306 {
307     CPLFree(m_pszStyleString);
308     m_pszStyleString = nullptr;
309 
310     if( pszStyleString && pszStyleString[0] == '@' )
311         m_pszStyleString = CPLStrdup(GetStyleByName(pszStyleString));
312     else
313         m_pszStyleString = nullptr;
314 
315     if( m_pszStyleString == nullptr && pszStyleString )
316         m_pszStyleString = CPLStrdup(pszStyleString);
317 
318     return TRUE;
319 }
320 
321 /************************************************************************/
322 /*                     OGR_SM_InitStyleString()                         */
323 /************************************************************************/
324 
325 /**
326  * \brief Initialize style manager from the style string.
327  *
328  * This function is the same as the C++ method OGRStyleMgr::InitStyleString().
329  *
330  * @param hSM handle to the style manager.
331  * @param pszStyleString the style string to use (can be NULL).
332  *
333  * @return TRUE on success, FALSE on errors.
334  */
335 
OGR_SM_InitStyleString(OGRStyleMgrH hSM,const char * pszStyleString)336 int OGR_SM_InitStyleString( OGRStyleMgrH hSM, const char *pszStyleString )
337 
338 {
339     VALIDATE_POINTER1( hSM, "OGR_SM_InitStyleString", FALSE );
340 
341     return reinterpret_cast<OGRStyleMgr *>(hSM)->
342         InitStyleString(pszStyleString);
343 }
344 
345 /****************************************************************************/
346 /*      const char *OGRStyleMgr::GetStyleName(const char *pszStyleString)   */
347 /****************************************************************************/
348 
349 /**
350  * \brief Get the name of a style from the style table.
351  *
352  * @param pszStyleString the style to search for, or NULL to use the style
353  *   currently stored in the manager.
354  *
355  * @return The name if found, or NULL on error.
356  */
357 
GetStyleName(const char * pszStyleString)358 const char *OGRStyleMgr::GetStyleName( const char *pszStyleString )
359 {
360     // SECURITY: The unit and the value for all parameter should be the same,
361     // a text comparison is executed.
362 
363     const char *pszStyle = pszStyleString ? pszStyleString : m_pszStyleString;
364 
365     if( pszStyle )
366     {
367         if( m_poDataSetStyleTable )
368             return m_poDataSetStyleTable->GetStyleName(pszStyle);
369     }
370     return nullptr;
371 }
372 /****************************************************************************/
373 /*      const char *OGRStyleMgr::GetStyleByName(const char *pszStyleName)   */
374 /*                                                                          */
375 /****************************************************************************/
376 
377 /**
378  * \brief find a style in the current style table.
379  *
380  *
381  * @param pszStyleName the name of the style to add.
382  *
383  * @return the style string matching the name or NULL if not found or error.
384  */
GetStyleByName(const char * pszStyleName)385 const char *OGRStyleMgr::GetStyleByName( const char *pszStyleName )
386 {
387     if( m_poDataSetStyleTable )
388     {
389         return m_poDataSetStyleTable->Find(pszStyleName);
390     }
391     return nullptr;
392 }
393 
394 /****************************************************************************/
395 /*            GBool OGRStyleMgr::AddStyle(char *pszStyleName,               */
396 /*                                   char *pszStyleString)                  */
397 /*                                                                          */
398 /****************************************************************************/
399 
400 /**
401  * \brief Add a style to the current style table.
402  *
403  * This method is the same as the C function OGR_SM_AddStyle().
404  *
405  * @param pszStyleName the name of the style to add.
406  * @param pszStyleString the style string to use, or NULL to use the style
407  *                       stored in the manager.
408  *
409  * @return TRUE on success, FALSE on errors.
410  */
411 
AddStyle(const char * pszStyleName,const char * pszStyleString)412 GBool OGRStyleMgr::AddStyle( const char *pszStyleName,
413                              const char *pszStyleString )
414 {
415     const char *pszStyle = pszStyleString ? pszStyleString : m_pszStyleString;
416 
417     if( m_poDataSetStyleTable )
418     {
419         return m_poDataSetStyleTable->AddStyle(pszStyleName, pszStyle);
420     }
421     return FALSE;
422 }
423 
424 /************************************************************************/
425 /*                     OGR_SM_AddStyle()                         */
426 /************************************************************************/
427 
428 /**
429  * \brief Add a style to the current style table.
430  *
431  * This function is the same as the C++ method OGRStyleMgr::AddStyle().
432  *
433  * @param hSM handle to the style manager.
434  * @param pszStyleName the name of the style to add.
435  * @param pszStyleString the style string to use, or NULL to use the style
436  *                       stored in the manager.
437  *
438  * @return TRUE on success, FALSE on errors.
439  */
440 
OGR_SM_AddStyle(OGRStyleMgrH hSM,const char * pszStyleName,const char * pszStyleString)441 int OGR_SM_AddStyle( OGRStyleMgrH hSM, const char *pszStyleName,
442                      const char *pszStyleString )
443 {
444     VALIDATE_POINTER1( hSM, "OGR_SM_AddStyle", FALSE );
445     VALIDATE_POINTER1( pszStyleName, "OGR_SM_AddStyle", FALSE );
446 
447     return reinterpret_cast<OGRStyleMgr *>(hSM)->
448         AddStyle( pszStyleName, pszStyleString);
449 }
450 
451 /****************************************************************************/
452 /*            const char *OGRStyleMgr::GetStyleString(OGRFeature *)         */
453 /*                                                                          */
454 /****************************************************************************/
455 
456 /**
457  * \brief Get the style string from the style manager.
458  *
459  * @param poFeature feature object from which to read the style or NULL to
460  *                  get the style string stored in the manager.
461  *
462  * @return the style string stored in the feature or the style string stored
463  *          in the style manager if poFeature is NULL
464  *
465  * NOTE: this method will call OGRStyleMgr::InitFromFeature() if poFeature is
466  *       not NULL and replace the style string stored in the style manager
467  */
468 
GetStyleString(OGRFeature * poFeature)469 const char *OGRStyleMgr::GetStyleString( OGRFeature *poFeature )
470 {
471     if( poFeature == nullptr )
472         return m_pszStyleString;
473 
474     return InitFromFeature(poFeature);
475 }
476 
477 /****************************************************************************/
478 /*            GBool OGRStyleMgr::AddPart(const char *pszPart)               */
479 /*            Add a new part in the current style                           */
480 /****************************************************************************/
481 
482 /**
483  * \brief Add a part (style string) to the current style.
484  *
485  * @param pszPart the style string defining the part to add.
486  *
487  * @return TRUE on success, FALSE on errors.
488  */
489 
AddPart(const char * pszPart)490 GBool OGRStyleMgr::AddPart( const char *pszPart )
491 {
492     if( pszPart == nullptr )
493         return FALSE;
494 
495     if( m_pszStyleString )
496     {
497         char *pszTmp =
498             CPLStrdup(CPLString().Printf("%s;%s", m_pszStyleString, pszPart));
499         CPLFree(m_pszStyleString);
500         m_pszStyleString = pszTmp;
501     }
502     else
503     {
504         char *pszTmp = CPLStrdup(CPLString().Printf("%s", pszPart));
505         CPLFree(m_pszStyleString);
506         m_pszStyleString = pszTmp;
507     }
508     return TRUE;
509 }
510 
511 /****************************************************************************/
512 /*            GBool OGRStyleMgr::AddPart(OGRStyleTool *)                    */
513 /*            Add a new part in the current style                           */
514 /****************************************************************************/
515 
516 /**
517  * \brief Add a part (style tool) to the current style.
518  *
519  * This method is the same as the C function OGR_SM_AddPart().
520  *
521  * @param poStyleTool the style tool defining the part to add.
522  *
523  * @return TRUE on success, FALSE on errors.
524  */
525 
AddPart(OGRStyleTool * poStyleTool)526 GBool OGRStyleMgr::AddPart( OGRStyleTool *poStyleTool )
527 {
528     if( poStyleTool == nullptr || !poStyleTool->GetStyleString() )
529         return FALSE;
530 
531     if( m_pszStyleString )
532     {
533         char *pszTmp =
534             CPLStrdup(CPLString().Printf("%s;%s", m_pszStyleString,
535                                          poStyleTool->GetStyleString()));
536         CPLFree(m_pszStyleString);
537         m_pszStyleString = pszTmp;
538     }
539     else
540     {
541         char *pszTmp =
542             CPLStrdup(CPLString().Printf("%s",
543                                          poStyleTool->GetStyleString()));
544           CPLFree(m_pszStyleString);
545           m_pszStyleString = pszTmp;
546     }
547     return TRUE;
548 }
549 
550 /************************************************************************/
551 /*                     OGR_SM_AddPart()                                 */
552 /************************************************************************/
553 
554 /**
555  * \brief Add a part (style tool) to the current style.
556  *
557  * This function is the same as the C++ method OGRStyleMgr::AddPart().
558  *
559  * @param hSM handle to the style manager.
560  * @param hST the style tool defining the part to add.
561  *
562  * @return TRUE on success, FALSE on errors.
563  */
564 
OGR_SM_AddPart(OGRStyleMgrH hSM,OGRStyleToolH hST)565 int OGR_SM_AddPart( OGRStyleMgrH hSM, OGRStyleToolH hST )
566 
567 {
568     VALIDATE_POINTER1( hSM, "OGR_SM_InitStyleString", FALSE );
569     VALIDATE_POINTER1( hST, "OGR_SM_InitStyleString", FALSE );
570 
571     return reinterpret_cast<OGRStyleMgr *>(hSM)->
572         AddPart(reinterpret_cast<OGRStyleTool *>(hST));
573 }
574 
575 /****************************************************************************/
576 /*            int OGRStyleMgr::GetPartCount(const char *pszStyleString)     */
577 /*            return the number of part in the stylestring                  */
578 /* FIXME: this function should actually parse style string instead of simple*/
579 /*        semicolon counting, we should not count broken and empty parts.   */
580 /****************************************************************************/
581 
582 /**
583  * \brief Get the number of parts in a style.
584  *
585  * This method is the same as the C function OGR_SM_GetPartCount().
586  *
587  * @param pszStyleString (optional) the style string on which to operate.
588  * If NULL then the current style string stored in the style manager is used.
589  *
590  * @return the number of parts (style tools) in the style.
591  */
592 
GetPartCount(const char * pszStyleString)593 int OGRStyleMgr::GetPartCount( const char *pszStyleString )
594 {
595     const char *pszString = pszStyleString != nullptr
596         ? pszStyleString
597         : m_pszStyleString;
598 
599     if( pszString == nullptr )
600       return 0;
601 
602     int nPartCount = 1;
603     const char *pszStrTmp = pszString;
604     // Search for parts separated by semicolons not counting the possible
605     // semicolon at the and of string.
606     const char *pszPart = nullptr;
607     while( (pszPart = strstr(pszStrTmp, ";")) != nullptr && pszPart[1] != '\0' )
608     {
609         pszStrTmp = &pszPart[1];
610         nPartCount++;
611     }
612     return nPartCount;
613 }
614 
615 /************************************************************************/
616 /*                     OGR_SM_GetPartCount()                            */
617 /************************************************************************/
618 
619 /**
620  * \brief Get the number of parts in a style.
621  *
622  * This function is the same as the C++ method OGRStyleMgr::GetPartCount().
623  *
624  * @param hSM handle to the style manager.
625  * @param pszStyleString (optional) the style string on which to operate.
626  * If NULL then the current style string stored in the style manager is used.
627  *
628  * @return the number of parts (style tools) in the style.
629  */
630 
OGR_SM_GetPartCount(OGRStyleMgrH hSM,const char * pszStyleString)631 int OGR_SM_GetPartCount( OGRStyleMgrH hSM, const char *pszStyleString )
632 
633 {
634     VALIDATE_POINTER1( hSM, "OGR_SM_InitStyleString", FALSE );
635 
636     return reinterpret_cast<OGRStyleMgr *>(hSM)->GetPartCount(pszStyleString);
637 }
638 
639 /****************************************************************************/
640 /*            OGRStyleTool *OGRStyleMgr::GetPart(int nPartId,               */
641 /*                                 const char *pszStyleString)              */
642 /*                                                                          */
643 /*     Return a StyleTool of the type of the wanted part, could return NULL */
644 /****************************************************************************/
645 
646 /**
647  * \brief Fetch a part (style tool) from the current style.
648  *
649  * This method is the same as the C function OGR_SM_GetPart().
650  *
651  * This method instantiates a new object that should be freed with
652  * OGR_ST_Destroy().
653  *
654  * @param nPartId the part number (0-based index).
655  * @param pszStyleString (optional) the style string on which to operate.
656  * If NULL then the current style string stored in the style manager is used.
657  *
658  * @return OGRStyleTool of the requested part (style tools) or NULL on error.
659  */
660 
GetPart(int nPartId,const char * pszStyleString)661 OGRStyleTool *OGRStyleMgr::GetPart( int nPartId,
662                                     const char *pszStyleString )
663 {
664     const char *pszStyle = pszStyleString ? pszStyleString : m_pszStyleString;
665 
666     if( pszStyle == nullptr )
667       return nullptr;
668 
669     char **papszStyleString =
670         CSLTokenizeString2(pszStyle, ";",
671                            CSLT_HONOURSTRINGS
672                            | CSLT_PRESERVEQUOTES
673                            | CSLT_PRESERVEESCAPES );
674 
675     const char *pszString = CSLGetField( papszStyleString, nPartId );
676 
677     OGRStyleTool *poStyleTool = nullptr;
678     if( strlen(pszString) > 0 )
679     {
680         poStyleTool = CreateStyleToolFromStyleString(pszString);
681         if( poStyleTool )
682             poStyleTool->SetStyleString(pszString);
683     }
684 
685     CSLDestroy( papszStyleString );
686 
687     return poStyleTool;
688 }
689 
690 /************************************************************************/
691 /*                     OGR_SM_GetPart()                                 */
692 /************************************************************************/
693 
694 /**
695  * \brief Fetch a part (style tool) from the current style.
696  *
697  * This function is the same as the C++ method OGRStyleMgr::GetPart().
698  *
699  * This function instantiates a new object that should be freed with
700  * OGR_ST_Destroy().
701  *
702  * @param hSM handle to the style manager.
703  * @param nPartId the part number (0-based index).
704  * @param pszStyleString (optional) the style string on which to operate.
705  * If NULL then the current style string stored in the style manager is used.
706  *
707  * @return OGRStyleToolH of the requested part (style tools) or NULL on error.
708  */
709 
OGR_SM_GetPart(OGRStyleMgrH hSM,int nPartId,const char * pszStyleString)710 OGRStyleToolH OGR_SM_GetPart( OGRStyleMgrH hSM, int nPartId,
711                               const char *pszStyleString )
712 
713 {
714     VALIDATE_POINTER1( hSM, "OGR_SM_InitStyleString", nullptr );
715 
716     return
717         reinterpret_cast<OGRStyleToolH>(
718             reinterpret_cast<OGRStyleMgr *>(hSM)->
719                 GetPart(nPartId, pszStyleString));
720 }
721 
722 /****************************************************************************/
723 /* OGRStyleTool *CreateStyleToolFromStyleString(const char *pszStyleString) */
724 /*                                                                          */
725 /* create a Style tool from the given StyleString, it should contain only a */
726 /* part of a StyleString.                                                    */
727 /****************************************************************************/
728 
729 //! @cond Doxygen_Suppress
730 OGRStyleTool *
CreateStyleToolFromStyleString(const char * pszStyleString)731 OGRStyleMgr::CreateStyleToolFromStyleString( const char *pszStyleString )
732 {
733     char **papszToken = CSLTokenizeString2(pszStyleString, "();",
734                                            CSLT_HONOURSTRINGS
735                                            | CSLT_PRESERVEQUOTES
736                                            | CSLT_PRESERVEESCAPES );
737     OGRStyleTool *poStyleTool = nullptr;
738 
739     if( CSLCount(papszToken) < 2 )
740         poStyleTool = nullptr;
741     else if( EQUAL(papszToken[0], "PEN") )
742         poStyleTool = new OGRStylePen();
743     else if( EQUAL(papszToken[0], "BRUSH") )
744         poStyleTool = new OGRStyleBrush();
745     else if( EQUAL(papszToken[0], "SYMBOL") )
746         poStyleTool = new OGRStyleSymbol();
747     else if( EQUAL(papszToken[0], "LABEL") )
748         poStyleTool = new OGRStyleLabel();
749     else
750         poStyleTool = nullptr;
751 
752     CSLDestroy( papszToken );
753 
754     return poStyleTool;
755 }
756 //! @endcond
757 
758 /* ======================================================================== */
759 /*                OGRStyleTable                                             */
760 /*     Object Used to manage and store a styletable                         */
761 /* ======================================================================== */
762 
763 /****************************************************************************/
764 /*              OGRStyleTable::OGRStyleTable()                              */
765 /*                                                                          */
766 /****************************************************************************/
OGRStyleTable()767 OGRStyleTable::OGRStyleTable()
768 {
769     m_papszStyleTable = nullptr;
770     iNextStyle = 0;
771 }
772 
773 /************************************************************************/
774 /*                            OGR_STBL_Create()                           */
775 /************************************************************************/
776 /**
777  * \brief OGRStyleTable factory.
778  *
779  * This function is the same as the C++ method OGRStyleTable::OGRStyleTable().
780  *
781  *
782  * @return a handle to the new style table object.
783  */
784 
OGR_STBL_Create(void)785 OGRStyleTableH OGR_STBL_Create( void )
786 
787 {
788     return reinterpret_cast<OGRStyleTableH>(new OGRStyleTable());
789 }
790 
791 /****************************************************************************/
792 /*                void OGRStyleTable::Clear()                               */
793 /*                                                                          */
794 /****************************************************************************/
795 
796 /**
797  * \brief Clear a style table.
798  *
799  */
800 
Clear()801 void OGRStyleTable::Clear()
802 {
803     if( m_papszStyleTable )
804       CSLDestroy(m_papszStyleTable);
805     m_papszStyleTable = nullptr;
806 }
807 
808 /****************************************************************************/
809 /*          OGRStyleTable::~OGRStyleTable()                                 */
810 /*                                                                          */
811 /****************************************************************************/
~OGRStyleTable()812 OGRStyleTable::~OGRStyleTable()
813 {
814     Clear();
815 }
816 
817 /************************************************************************/
818 /*                           OGR_STBL_Destroy()                            */
819 /************************************************************************/
820 /**
821  * \brief Destroy Style Table
822  *
823  * @param hSTBL handle to the style table to destroy.
824  */
825 
OGR_STBL_Destroy(OGRStyleTableH hSTBL)826 void OGR_STBL_Destroy( OGRStyleTableH hSTBL )
827 
828 {
829     delete reinterpret_cast<OGRStyleTable *>(hSTBL);
830 }
831 
832 /****************************************************************************/
833 /*    const char *OGRStyleTable::GetStyleName(const char *pszStyleString)   */
834 /*                                                                          */
835 /*    return the Name of a given stylestring otherwise NULL.                */
836 /****************************************************************************/
837 
838 /**
839  * \brief Get style name by style string.
840  *
841  * @param pszStyleString the style string to look up.
842  *
843  * @return the Name of the matching style string or NULL on error.
844  */
845 
GetStyleName(const char * pszStyleString)846 const char *OGRStyleTable::GetStyleName( const char *pszStyleString )
847 {
848     for( int i = 0; i < CSLCount(m_papszStyleTable); i++ )
849     {
850         const char *pszStyleStringBegin =
851             strstr(m_papszStyleTable[i], ":");
852 
853         if( pszStyleStringBegin && EQUAL(&pszStyleStringBegin[1],
854                                          pszStyleString) )
855         {
856             osLastRequestedStyleName = m_papszStyleTable[i];
857             const size_t nColon = osLastRequestedStyleName.find( ':' );
858             if( nColon != std::string::npos )
859                 osLastRequestedStyleName =
860                     osLastRequestedStyleName.substr(0, nColon);
861 
862             return osLastRequestedStyleName;
863         }
864     }
865 
866     return nullptr;
867 }
868 
869 /****************************************************************************/
870 /*            GBool OGRStyleTable::AddStyle(char *pszName,                  */
871 /*                                          char *pszStyleString)           */
872 /*                                                                          */
873 /*   Add a new style in the table, no comparison will be done on the        */
874 /*   Style string, only on the name, TRUE success, FALSE error              */
875 /****************************************************************************/
876 
877 /**
878  * \brief Add a new style in the table.
879  * No comparison will be done on the
880  * Style string, only on the name.
881  *
882  * @param pszName the name the style to add.
883  * @param pszStyleString the style string to add.
884  *
885  * @return TRUE on success, FALSE on error
886  */
887 
AddStyle(const char * pszName,const char * pszStyleString)888 GBool OGRStyleTable::AddStyle( const char *pszName, const char *pszStyleString )
889 {
890     if( pszName == nullptr || pszStyleString == nullptr )
891         return FALSE;
892 
893     const int nPos = IsExist(pszName);
894     if( nPos != -1 )
895       return FALSE;
896 
897     m_papszStyleTable =
898         CSLAddString(m_papszStyleTable,
899                      CPLString().Printf("%s:%s", pszName, pszStyleString));
900     return TRUE;
901 }
902 
903 /************************************************************************/
904 /*                       OGR_STBL_AddStyle()                            */
905 /************************************************************************/
906 
907 /**
908  * \brief Add a new style in the table.
909  * No comparison will be done on the
910  * Style string, only on the name.
911  * This function is the same as the C++ method OGRStyleTable::AddStyle().
912  *
913  * @param hStyleTable handle to the style table.
914  * @param pszName the name the style to add.
915  * @param pszStyleString the style string to add.
916  *
917  * @return TRUE on success, FALSE on error
918  */
919 
OGR_STBL_AddStyle(OGRStyleTableH hStyleTable,const char * pszName,const char * pszStyleString)920 int OGR_STBL_AddStyle( OGRStyleTableH hStyleTable,
921                        const char *pszName, const char *pszStyleString )
922 {
923     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_AddStyle", FALSE );
924 
925     return reinterpret_cast<OGRStyleTable *>(hStyleTable)->
926         AddStyle(pszName, pszStyleString);
927 }
928 
929 /****************************************************************************/
930 /*            GBool OGRStyleTable::RemoveStyle(char *pszName)               */
931 /*                                                                          */
932 /*    Remove the given style in the table based on the name, return TRUE    */
933 /*    on success otherwise FALSE.                                           */
934 /****************************************************************************/
935 
936 /**
937  * \brief Remove a style in the table by its name.
938  *
939  * @param pszName the name of the style to remove.
940  *
941  * @return TRUE on success, FALSE on error
942  */
943 
RemoveStyle(const char * pszName)944 GBool OGRStyleTable::RemoveStyle( const char *pszName )
945 {
946     const int nPos = IsExist(pszName);
947     if( nPos == -1 )
948         return FALSE;
949 
950     m_papszStyleTable = CSLRemoveStrings(m_papszStyleTable, nPos, 1, nullptr);
951     return TRUE;
952 }
953 
954 /****************************************************************************/
955 /*            GBool OGRStyleTable::ModifyStyle(char *pszName,               */
956 /*                                             char *pszStyleString)        */
957 /*                                                                          */
958 /*    Modify the given style, if the style doesn't exist, it will be added  */
959 /*    return TRUE on success otherwise return FALSE.                        */
960 /****************************************************************************/
961 
962 /**
963  * \brief Modify a style in the table by its name
964  * If the style does not exist, it will be added.
965  *
966  * @param pszName the name of the style to modify.
967  * @param pszStyleString the style string.
968  *
969  * @return TRUE on success, FALSE on error
970  */
971 
ModifyStyle(const char * pszName,const char * pszStyleString)972 GBool OGRStyleTable::ModifyStyle( const char *pszName,
973                                   const char * pszStyleString )
974 {
975     if( pszName == nullptr || pszStyleString == nullptr )
976       return FALSE;
977 
978     RemoveStyle(pszName);
979     return AddStyle(pszName, pszStyleString);
980 }
981 
982 /****************************************************************************/
983 /*            GBool OGRStyleTable::SaveStyleTable(char *)                   */
984 /*                                                                          */
985 /*    Save the StyleTable in the given file, return TRUE on success         */
986 /*    otherwise return FALSE.                                               */
987 /****************************************************************************/
988 
989 /**
990  * \brief Save a style table to a file.
991  *
992  * @param pszFilename the name of the file to save to.
993  *
994  * @return TRUE on success, FALSE on error
995  */
996 
SaveStyleTable(const char * pszFilename)997 GBool OGRStyleTable::SaveStyleTable( const char *pszFilename )
998 {
999     if( pszFilename == nullptr )
1000       return FALSE;
1001 
1002     if( CSLSave(m_papszStyleTable, pszFilename) == 0 )
1003       return FALSE;
1004 
1005     return TRUE;
1006 }
1007 
1008 /************************************************************************/
1009 /*                     OGR_STBL_SaveStyleTable()                        */
1010 /************************************************************************/
1011 
1012 /**
1013  * \brief Save a style table to a file.
1014  *
1015  * This function is the same as the C++ method OGRStyleTable::SaveStyleTable().
1016  *
1017  * @param hStyleTable handle to the style table.
1018  * @param pszFilename the name of the file to save to.
1019  *
1020  * @return TRUE on success, FALSE on error
1021  */
1022 
OGR_STBL_SaveStyleTable(OGRStyleTableH hStyleTable,const char * pszFilename)1023 int OGR_STBL_SaveStyleTable( OGRStyleTableH hStyleTable,
1024                              const char *pszFilename )
1025 {
1026     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_SaveStyleTable", FALSE );
1027     VALIDATE_POINTER1( pszFilename, "OGR_STBL_SaveStyleTable", FALSE );
1028 
1029     return reinterpret_cast<OGRStyleTable *>(hStyleTable)->
1030         SaveStyleTable( pszFilename );
1031 }
1032 
1033 /****************************************************************************/
1034 /*            GBool OGRStyleTable::LoadStyleTable(char *)                   */
1035 /*                                                                          */
1036 /*            Read the Style table from a file, return TRUE on success      */
1037 /*            otherwise return FALSE                                        */
1038 /****************************************************************************/
1039 
1040 /**
1041  * \brief Load a style table from a file.
1042  *
1043  * @param pszFilename the name of the file to load from.
1044  *
1045  * @return TRUE on success, FALSE on error
1046  */
1047 
LoadStyleTable(const char * pszFilename)1048 GBool OGRStyleTable::LoadStyleTable( const char *pszFilename )
1049 {
1050     if( pszFilename == nullptr )
1051       return FALSE;
1052 
1053     CSLDestroy(m_papszStyleTable);
1054 
1055     m_papszStyleTable = CSLLoad(pszFilename);
1056 
1057     return m_papszStyleTable != nullptr;
1058 }
1059 
1060 /************************************************************************/
1061 /*                     OGR_STBL_LoadStyleTable()                        */
1062 /************************************************************************/
1063 
1064 /**
1065  * \brief Load a style table from a file.
1066  *
1067  * This function is the same as the C++ method OGRStyleTable::LoadStyleTable().
1068  *
1069  * @param hStyleTable handle to the style table.
1070  * @param pszFilename the name of the file to load from.
1071  *
1072  * @return TRUE on success, FALSE on error
1073  */
1074 
OGR_STBL_LoadStyleTable(OGRStyleTableH hStyleTable,const char * pszFilename)1075 int OGR_STBL_LoadStyleTable( OGRStyleTableH hStyleTable,
1076                              const char *pszFilename )
1077 {
1078     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_LoadStyleTable", FALSE );
1079     VALIDATE_POINTER1( pszFilename, "OGR_STBL_LoadStyleTable", FALSE );
1080 
1081     return reinterpret_cast<OGRStyleTable *>(hStyleTable)->
1082         LoadStyleTable( pszFilename );
1083 }
1084 
1085 /****************************************************************************/
1086 /*             const char *OGRStyleTable::Find(const char *pszName)         */
1087 /*                                                                          */
1088 /*             return the StyleString based on the given name,              */
1089 /*             otherwise return NULL.                                       */
1090 /****************************************************************************/
1091 
1092 /**
1093  * \brief Get a style string by name.
1094  *
1095  * @param pszName the name of the style string to find.
1096  *
1097  * @return the style string matching the name, NULL if not found or error.
1098  */
1099 
Find(const char * pszName)1100 const char *OGRStyleTable::Find(const char *pszName)
1101 {
1102     const int nPos = IsExist(pszName);
1103     if( nPos == -1 )
1104         return nullptr;
1105 
1106     const char *pszOutput = CSLGetField(m_papszStyleTable, nPos);
1107 
1108     const char *pszDash = strstr(pszOutput, ":");
1109 
1110     if( pszDash == nullptr )
1111         return nullptr;
1112 
1113     return &pszDash[1];
1114 }
1115 
1116 /************************************************************************/
1117 /*                     OGR_STBL_Find()                                  */
1118 /************************************************************************/
1119 
1120 /**
1121  * \brief Get a style string by name.
1122  *
1123  * This function is the same as the C++ method OGRStyleTable::Find().
1124  *
1125  * @param hStyleTable handle to the style table.
1126  * @param pszName the name of the style string to find.
1127  *
1128  * @return the style string matching the name or NULL if not found or error.
1129  */
1130 
OGR_STBL_Find(OGRStyleTableH hStyleTable,const char * pszName)1131 const char *OGR_STBL_Find( OGRStyleTableH hStyleTable, const char *pszName )
1132 {
1133     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_Find", nullptr );
1134     VALIDATE_POINTER1( pszName, "OGR_STBL_Find", nullptr );
1135 
1136     return reinterpret_cast<OGRStyleTable *>(hStyleTable)->Find(pszName);
1137 }
1138 
1139 /****************************************************************************/
1140 /*              OGRStyleTable::Print(FILE *fpOut)                           */
1141 /*                                                                          */
1142 /****************************************************************************/
1143 
1144 /**
1145  * \brief Print a style table to a FILE pointer.
1146  *
1147  * @param fpOut the FILE pointer to print to.
1148  *
1149  */
1150 
Print(FILE * fpOut)1151 void OGRStyleTable::Print( FILE *fpOut )
1152 {
1153 
1154     CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut, "#OFS-Version: 1.0\n"));
1155     CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut, "#StyleField: style\n"));
1156     if( m_papszStyleTable )
1157     {
1158         CSLPrint(m_papszStyleTable, fpOut);
1159     }
1160 }
1161 
1162 /****************************************************************************/
1163 /*             int OGRStyleTable::IsExist(const char *pszName)              */
1164 /*                                                                          */
1165 /*   return a index of the style in the table otherwise return -1           */
1166 /****************************************************************************/
1167 
1168 /**
1169  * \brief Get the index of a style in the table by its name.
1170  *
1171  * @param pszName the name to look for.
1172  *
1173  * @return The index of the style if found, -1 if not found or error.
1174  */
1175 
IsExist(const char * pszName)1176 int OGRStyleTable::IsExist( const char *pszName )
1177 {
1178     if( pszName == nullptr )
1179       return -1;
1180 
1181     const int nCount = CSLCount(m_papszStyleTable);
1182     const char *pszNewString = CPLSPrintf("%s:", pszName);
1183 
1184     for( int i = 0; i < nCount; i++ )
1185     {
1186         if( strstr(m_papszStyleTable[i], pszNewString) != nullptr )
1187         {
1188             return i;
1189         }
1190     }
1191 
1192     return -1;
1193 }
1194 
1195 /************************************************************************/
1196 /*                               Clone()                                */
1197 /************************************************************************/
1198 
1199 /**
1200  * \brief Duplicate style table.
1201  *
1202  * The newly created style table is owned by the caller, and will have its
1203  * own reference to the OGRStyleTable.
1204  *
1205  * @return new style table, exactly matching this style table.
1206  */
1207 
Clone()1208 OGRStyleTable *OGRStyleTable::Clone()
1209 
1210 {
1211     OGRStyleTable *poNew = new OGRStyleTable();
1212 
1213     poNew->m_papszStyleTable = CSLDuplicate( m_papszStyleTable );
1214 
1215     return poNew;
1216 }
1217 
1218 /************************************************************************/
1219 /*                            ResetStyleStringReading()                 */
1220 /************************************************************************/
1221 
1222 /** Reset the next style pointer to 0 */
ResetStyleStringReading()1223 void OGRStyleTable::ResetStyleStringReading()
1224 
1225 {
1226     iNextStyle = 0;
1227 }
1228 
1229 /************************************************************************/
1230 /*                     OGR_STBL_ResetStyleStringReading()               */
1231 /************************************************************************/
1232 
1233 /**
1234  * \brief Reset the next style pointer to 0
1235  *
1236  * This function is the same as the C++ method
1237  * OGRStyleTable::ResetStyleStringReading().
1238  *
1239  * @param hStyleTable handle to the style table.
1240  *
1241  */
1242 
OGR_STBL_ResetStyleStringReading(OGRStyleTableH hStyleTable)1243 void OGR_STBL_ResetStyleStringReading( OGRStyleTableH hStyleTable )
1244 {
1245     VALIDATE_POINTER0( hStyleTable, "OGR_STBL_ResetStyleStringReading" );
1246 
1247     reinterpret_cast<OGRStyleTable *>(hStyleTable)->ResetStyleStringReading();
1248 }
1249 
1250 /************************************************************************/
1251 /*                           GetNextStyle()                             */
1252 /************************************************************************/
1253 
1254 /**
1255  * \brief Get the next style string from the table.
1256  *
1257  * @return the next style string or NULL on error.
1258  */
1259 
GetNextStyle()1260 const char *OGRStyleTable::GetNextStyle()
1261 {
1262     while( iNextStyle < CSLCount(m_papszStyleTable) )
1263     {
1264         const char *pszOutput = CSLGetField(m_papszStyleTable, iNextStyle++);
1265         if( pszOutput == nullptr )
1266             continue;
1267 
1268         const char *pszDash = strstr(pszOutput, ":");
1269 
1270         osLastRequestedStyleName = pszOutput;
1271         const size_t nColon = osLastRequestedStyleName.find( ':' );
1272         if( nColon != std::string::npos )
1273             osLastRequestedStyleName =
1274                 osLastRequestedStyleName.substr(0, nColon);
1275 
1276         if( pszDash )
1277             return pszDash + 1;
1278     }
1279     return nullptr;
1280 }
1281 
1282 /************************************************************************/
1283 /*                     OGR_STBL_GetNextStyle()                          */
1284 /************************************************************************/
1285 
1286 /**
1287  * \brief Get the next style string from the table.
1288  *
1289  * This function is the same as the C++ method OGRStyleTable::GetNextStyle().
1290  *
1291  * @param hStyleTable handle to the style table.
1292  *
1293  * @return the next style string or NULL on error.
1294  */
1295 
OGR_STBL_GetNextStyle(OGRStyleTableH hStyleTable)1296 const char *OGR_STBL_GetNextStyle( OGRStyleTableH hStyleTable)
1297 {
1298     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_GetNextStyle", nullptr );
1299 
1300     return reinterpret_cast<OGRStyleTable *>(hStyleTable)->GetNextStyle();
1301 }
1302 
1303 /************************************************************************/
1304 /*                           GetLastStyleName()                         */
1305 /************************************************************************/
1306 
1307 /**
1308  * Get the style name of the last style string fetched with
1309  * OGR_STBL_GetNextStyle.
1310  *
1311  * @return the Name of the last style string or NULL on error.
1312  */
1313 
GetLastStyleName()1314 const char *OGRStyleTable::GetLastStyleName()
1315 {
1316     return osLastRequestedStyleName;
1317 }
1318 
1319 /************************************************************************/
1320 /*                     OGR_STBL_GetLastStyleName()                      */
1321 /************************************************************************/
1322 
1323 /**
1324  * Get the style name of the last style string fetched with
1325  * OGR_STBL_GetNextStyle.
1326  *
1327  * This function is the same as the C++ method OGRStyleTable::GetStyleName().
1328  *
1329  * @param hStyleTable handle to the style table.
1330  *
1331  * @return the Name of the last style string or NULL on error.
1332  */
1333 
OGR_STBL_GetLastStyleName(OGRStyleTableH hStyleTable)1334 const char *OGR_STBL_GetLastStyleName( OGRStyleTableH hStyleTable)
1335 {
1336     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_GetLastStyleName", nullptr );
1337 
1338     return reinterpret_cast<OGRStyleTable *>(hStyleTable)->GetLastStyleName();
1339 }
1340 
1341 /****************************************************************************/
1342 /*                          OGRStyleTool::OGRStyleTool()                    */
1343 /*                                                                          */
1344 /****************************************************************************/
1345 
1346 /** Constructor */
OGRStyleTool(OGRSTClassId eClassId)1347 OGRStyleTool::OGRStyleTool( OGRSTClassId eClassId ) :
1348     m_eClassId(eClassId)
1349 {
1350 }
1351 
1352 /************************************************************************/
1353 /*                            OGR_ST_Create()                           */
1354 /************************************************************************/
1355 /**
1356  * \brief OGRStyleTool factory.
1357  *
1358  * This function is a constructor for OGRStyleTool derived classes.
1359  *
1360  * @param eClassId subclass of style tool to create. One of OGRSTCPen (1),
1361  * OGRSTCBrush (2), OGRSTCSymbol (3) or OGRSTCLabel (4).
1362  *
1363  * @return a handle to the new style tool object or NULL if the creation
1364  * failed.
1365  */
1366 
OGR_ST_Create(OGRSTClassId eClassId)1367 OGRStyleToolH OGR_ST_Create( OGRSTClassId eClassId )
1368 
1369 {
1370     switch( eClassId )
1371     {
1372       case OGRSTCPen:
1373         return reinterpret_cast<OGRStyleToolH>(new OGRStylePen());
1374       case OGRSTCBrush:
1375         return reinterpret_cast<OGRStyleToolH>(new OGRStyleBrush());
1376       case OGRSTCSymbol:
1377         return reinterpret_cast<OGRStyleToolH>(new OGRStyleSymbol());
1378       case OGRSTCLabel:
1379         return reinterpret_cast<OGRStyleToolH>(new OGRStyleLabel());
1380       default:
1381         return nullptr;
1382     }
1383 }
1384 
1385 /****************************************************************************/
1386 /*                       OGRStyleTool::~OGRStyleTool()                      */
1387 /*                                                                          */
1388 /****************************************************************************/
~OGRStyleTool()1389 OGRStyleTool::~OGRStyleTool()
1390 {
1391     CPLFree(m_pszStyleString);
1392 }
1393 
1394 /************************************************************************/
1395 /*                           OGR_ST_Destroy()                            */
1396 /************************************************************************/
1397 /**
1398  * \brief Destroy Style Tool
1399  *
1400  * @param hST handle to the style tool to destroy.
1401  */
1402 
OGR_ST_Destroy(OGRStyleToolH hST)1403 void OGR_ST_Destroy( OGRStyleToolH hST )
1404 
1405 {
1406     delete reinterpret_cast<OGRStyleTool *>(hST);
1407 }
1408 
1409 /****************************************************************************/
1410 /*      void OGRStyleTool::SetStyleString(const char *pszStyleString)       */
1411 /*                                                                          */
1412 /****************************************************************************/
1413 
1414 /** Undocumented
1415  * @param pszStyleString undocumented.
1416  */
SetStyleString(const char * pszStyleString)1417 void OGRStyleTool::SetStyleString( const char *pszStyleString )
1418 {
1419     m_pszStyleString = CPLStrdup(pszStyleString);
1420 }
1421 
1422 /****************************************************************************/
1423 /*const char *OGRStyleTool::GetStyleString( OGRStyleParamId *pasStyleParam, */
1424 /*                          OGRStyleValue *pasStyleValue, int nSize)        */
1425 /*                                                                          */
1426 /****************************************************************************/
1427 
1428 /** Undocumented
1429  * @param pasStyleParam undocumented.
1430  * @param pasStyleValue undocumented.
1431  * @param nSize undocumented.
1432  * @return undocumented.
1433  */
GetStyleString(const OGRStyleParamId * pasStyleParam,OGRStyleValue * pasStyleValue,int nSize)1434 const char *OGRStyleTool::GetStyleString( const OGRStyleParamId *pasStyleParam,
1435                                           OGRStyleValue *pasStyleValue,
1436                                           int nSize )
1437 {
1438     if( IsStyleModified() )
1439     {
1440         CPLFree(m_pszStyleString);
1441 
1442         const char *pszClass = nullptr;
1443         switch( GetType() )
1444         {
1445           case OGRSTCPen:
1446             pszClass = "PEN(";
1447             break;
1448           case OGRSTCBrush:
1449             pszClass = "BRUSH(";
1450             break;
1451           case OGRSTCSymbol:
1452             pszClass = "SYMBOL(";
1453             break;
1454           case OGRSTCLabel:
1455             pszClass = "LABEL(";
1456             break;
1457           default:
1458             pszClass = "UNKNOWN(";
1459         }
1460 
1461         CPLString osCurrent = pszClass;
1462 
1463         bool bFound = false;
1464         for( int i = 0; i < nSize; i++ )
1465         {
1466             if( !pasStyleValue[i].bValid ||
1467                 pasStyleParam[i].eType == OGRSTypeUnused )
1468             {
1469                 continue;
1470             }
1471 
1472             if( bFound )
1473                 osCurrent += ",";
1474             bFound = true;
1475 
1476             osCurrent += pasStyleParam[i].pszToken;
1477             switch( pasStyleParam[i].eType )
1478             {
1479               case OGRSTypeString:
1480                 osCurrent += ":";
1481                 osCurrent += pasStyleValue[i].pszValue;
1482                 break;
1483               case OGRSTypeDouble:
1484                 osCurrent +=
1485                     CPLString().Printf(":%f", pasStyleValue[i].dfValue);
1486                 break;
1487               case OGRSTypeInteger:
1488                 osCurrent += CPLString().Printf(":%d", pasStyleValue[i].nValue);
1489                 break;
1490               case OGRSTypeBoolean:
1491                 osCurrent += CPLString().Printf(":%d",
1492                     pasStyleValue[i].nValue != 0);
1493                 break;
1494               default:
1495                 break;
1496             }
1497             if( pasStyleParam[i].bGeoref )
1498               switch( pasStyleValue[i].eUnit )
1499               {
1500                 case OGRSTUGround:
1501                   osCurrent += "g";
1502                   break;
1503                 case OGRSTUPixel:
1504                   osCurrent += "px";
1505                   break;
1506                 case OGRSTUPoints:
1507                   osCurrent += "pt";
1508                   break;
1509                 case OGRSTUCM:
1510                   osCurrent += "cm";
1511                   break;
1512                 case OGRSTUInches:
1513                   osCurrent += "in";
1514                   break;
1515                 case OGRSTUMM:
1516                   //osCurrent += "mm";
1517                 default:
1518                   break;    //imp
1519               }
1520         }
1521         osCurrent += ")";
1522 
1523         m_pszStyleString = CPLStrdup(osCurrent);
1524 
1525         m_bModified = FALSE;
1526     }
1527 
1528     return m_pszStyleString;
1529 }
1530 
1531 /************************************************************************/
1532 /*                          GetRGBFromString()                          */
1533 /************************************************************************/
1534 /**
1535  * \brief Return the r,g,b,a components of a color encoded in \#RRGGBB[AA]
1536  * format.
1537  *
1538  * Maps to OGRStyleTool::GetRGBFromString().
1539  *
1540  * @param pszColor the color to parse
1541  * @param nRed reference to an int in which the red value will be returned.
1542  * @param nGreen reference to an int in which the green value will be returned.
1543  * @param nBlue reference to an int in which the blue value will be returned.
1544  * @param nTransparance reference to an int in which the (optional) alpha value
1545  * will be returned.
1546  *
1547  * @return TRUE if the color could be successfully parsed, or FALSE in case of
1548  * errors.
1549  */
GetRGBFromString(const char * pszColor,int & nRed,int & nGreen,int & nBlue,int & nTransparance)1550 GBool OGRStyleTool::GetRGBFromString( const char *pszColor, int &nRed,
1551                                       int &nGreen, int &nBlue,
1552                                       int &nTransparance )
1553 {
1554    int nCount = 0;
1555 
1556    nTransparance = 255;
1557 
1558    // FIXME: should we really use sscanf here?
1559    unsigned int unRed = 0;
1560    unsigned int unGreen = 0;
1561    unsigned int unBlue = 0;
1562    unsigned int unTransparance = 0;
1563    if( pszColor )
1564        nCount = sscanf(pszColor, "#%2x%2x%2x%2x",
1565                        &unRed, &unGreen, &unBlue, &unTransparance);
1566    nRed = static_cast<int>(unRed);
1567    nGreen = static_cast<int>(unGreen);
1568    nBlue = static_cast<int>(unBlue);
1569    if( nCount == 4 )
1570         nTransparance = static_cast<int>(unTransparance);
1571    return nCount >= 3;
1572 }
1573 
1574 /************************************************************************/
1575 /*                           GetSpecificId()                            */
1576 /*                                                                      */
1577 /*      return -1, if the wanted type is not found, ex:                 */
1578 /*      if you want ogr-pen value, pszWanted should be ogr-pen(case     */
1579 /*      sensitive)                                                      */
1580 /************************************************************************/
1581 
1582 /** Undocumented
1583  * @param pszId Undocumented
1584  * @param pszWanted Undocumented
1585  * @return Undocumented
1586  */
GetSpecificId(const char * pszId,const char * pszWanted)1587 int OGRStyleTool::GetSpecificId( const char *pszId, const char *pszWanted )
1588 {
1589     const char *pszRealWanted = pszWanted;
1590 
1591     if( pszWanted == nullptr || strlen(pszWanted) == 0 )
1592         pszRealWanted = "ogr-pen";
1593 
1594     if( pszId == nullptr )
1595         return -1;
1596 
1597     int nValue = -1;
1598     const char *pszFound = strstr(pszId, pszRealWanted);
1599     if( pszFound != nullptr )
1600     {
1601         // We found the string, it could be no value after it, use default one.
1602         nValue = 0;
1603 
1604         if( pszFound[strlen(pszRealWanted)] == '-' )
1605             nValue =atoi(&pszFound[strlen(pszRealWanted)+1]);
1606     }
1607 
1608     return nValue;
1609 }
1610 
1611 /************************************************************************/
1612 /*                              GetType()                               */
1613 /************************************************************************/
1614 
1615 /**
1616  * \brief Determine type of Style Tool
1617  *
1618  * @return the style tool type, one of OGRSTCPen (1), OGRSTCBrush (2),
1619  * OGRSTCSymbol (3) or OGRSTCLabel (4). Returns OGRSTCNone (0) if the
1620  * OGRStyleToolH is invalid.
1621  */
GetType()1622 OGRSTClassId OGRStyleTool::GetType()
1623 {
1624     return m_eClassId;
1625 }
1626 
1627 /************************************************************************/
1628 /*                           OGR_ST_GetType()                           */
1629 /************************************************************************/
1630 /**
1631  * \brief Determine type of Style Tool
1632  *
1633  * @param hST handle to the style tool.
1634  *
1635  * @return the style tool type, one of OGRSTCPen (1), OGRSTCBrush (2),
1636  * OGRSTCSymbol (3) or OGRSTCLabel (4). Returns OGRSTCNone (0) if the
1637  * OGRStyleToolH is invalid.
1638  */
1639 
OGR_ST_GetType(OGRStyleToolH hST)1640 OGRSTClassId OGR_ST_GetType( OGRStyleToolH hST )
1641 
1642 {
1643     VALIDATE_POINTER1( hST, "OGR_ST_GetType", OGRSTCNone );
1644     return reinterpret_cast<OGRStyleTool *>(hST)->GetType();
1645 }
1646 
1647 /************************************************************************/
1648 /*                           OGR_ST_GetUnit()                           */
1649 /************************************************************************/
1650 
1651 /**
1652  * \fn OGRStyleTool::GetUnit()
1653  * \brief Get Style Tool units
1654  *
1655  * @return the style tool units.
1656  */
1657 
1658 /**
1659  * \brief Get Style Tool units
1660  *
1661  * @param hST handle to the style tool.
1662  *
1663  * @return the style tool units.
1664  */
1665 
OGR_ST_GetUnit(OGRStyleToolH hST)1666 OGRSTUnitId OGR_ST_GetUnit( OGRStyleToolH hST )
1667 
1668 {
1669     VALIDATE_POINTER1( hST, "OGR_ST_GetUnit", OGRSTUGround );
1670     return reinterpret_cast<OGRStyleTool *>(hST)->GetUnit();
1671 }
1672 
1673 /************************************************************************/
1674 /*                              SetUnit()                               */
1675 /************************************************************************/
1676 
1677 /**
1678  * \brief Set Style Tool units
1679  *
1680  * @param eUnit the new unit.
1681  * @param dfGroundPaperScale ground to paper scale factor.
1682  *
1683  */
SetUnit(OGRSTUnitId eUnit,double dfGroundPaperScale)1684 void OGRStyleTool::SetUnit( OGRSTUnitId eUnit, double dfGroundPaperScale )
1685 {
1686     m_eUnit = eUnit;
1687     m_dfScale = dfGroundPaperScale;
1688 }
1689 
1690 /************************************************************************/
1691 /*                           OGR_ST_SetUnit()                           */
1692 /************************************************************************/
1693 /**
1694  * \brief Set Style Tool units
1695  *
1696  * This function is the same as OGRStyleTool::SetUnit()
1697  *
1698  * @param hST handle to the style tool.
1699  * @param eUnit the new unit.
1700  * @param dfGroundPaperScale ground to paper scale factor.
1701  *
1702  */
1703 
OGR_ST_SetUnit(OGRStyleToolH hST,OGRSTUnitId eUnit,double dfGroundPaperScale)1704 void OGR_ST_SetUnit( OGRStyleToolH hST, OGRSTUnitId eUnit,
1705                      double dfGroundPaperScale )
1706 
1707 {
1708     VALIDATE_POINTER0( hST, "OGR_ST_SetUnit" );
1709     reinterpret_cast<OGRStyleTool *>(hST)->SetUnit(eUnit, dfGroundPaperScale);
1710 }
1711 
1712 /************************************************************************/
1713 /*                               Parse()                                */
1714 /************************************************************************/
1715 
1716 //! @cond Doxygen_Suppress
Parse(const OGRStyleParamId * pasStyle,OGRStyleValue * pasValue,int nCount)1717 GBool OGRStyleTool::Parse( const OGRStyleParamId *pasStyle,
1718                            OGRStyleValue *pasValue,
1719                            int nCount )
1720 {
1721     if( IsStyleParsed() )
1722         return TRUE;
1723 
1724     StyleParsed();
1725 
1726     if( m_pszStyleString == nullptr )
1727         return FALSE;
1728 
1729     // Token to contains StyleString Type and content.
1730     // Tokenize the String to get the Type and the content
1731     // Example: Type(elem1:val2,elem2:val2)
1732     char **papszToken =
1733         CSLTokenizeString2(m_pszStyleString, "()",
1734                            CSLT_HONOURSTRINGS
1735                            | CSLT_PRESERVEQUOTES
1736                            | CSLT_PRESERVEESCAPES );
1737 
1738     if( CSLCount(papszToken) > 2 || CSLCount(papszToken) == 0 )
1739     {
1740         CSLDestroy( papszToken );
1741         CPLError(CE_Failure, CPLE_AppDefined,
1742                  "Error in the format of the StyleTool %s", m_pszStyleString);
1743         return FALSE;
1744     }
1745 
1746     // Token that will contains StyleString elements.
1747     // Tokenize the content of the StyleString to get paired components in it.
1748     char **papszToken2 =
1749         CSLTokenizeString2( papszToken[1], ",",
1750                             CSLT_HONOURSTRINGS
1751                             | CSLT_PRESERVEQUOTES
1752                             | CSLT_PRESERVEESCAPES );
1753 
1754     // Valid that we have the right StyleString for this feature type.
1755     switch( GetType() )
1756     {
1757       case OGRSTCPen:
1758         if( !EQUAL(papszToken[0],"PEN") )
1759         {
1760             CPLError(CE_Failure, CPLE_AppDefined,
1761                      "Error in the Type of StyleTool %s should be a PEN Type",
1762                      papszToken[0]);
1763             CSLDestroy( papszToken );
1764             CSLDestroy( papszToken2 );
1765             return FALSE;
1766         }
1767         break;
1768       case OGRSTCBrush:
1769         if( !EQUAL(papszToken[0], "BRUSH") )
1770         {
1771             CPLError(CE_Failure, CPLE_AppDefined,
1772                      "Error in the Type of StyleTool %s should be a BRUSH Type",
1773                      papszToken[0]);
1774             CSLDestroy( papszToken );
1775             CSLDestroy( papszToken2 );
1776             return FALSE;
1777         }
1778         break;
1779       case OGRSTCSymbol:
1780         if( !EQUAL(papszToken[0], "SYMBOL") )
1781         {
1782             CPLError(CE_Failure, CPLE_AppDefined,
1783                      "Error in the Type of StyleTool %s should be "
1784                      "a SYMBOL Type",
1785                      papszToken[0]);
1786             CSLDestroy( papszToken );
1787             CSLDestroy( papszToken2 );
1788             return FALSE;
1789         }
1790         break;
1791       case OGRSTCLabel:
1792         if( !EQUAL(papszToken[0], "LABEL") )
1793         {
1794             CPLError(CE_Failure, CPLE_AppDefined,
1795                      "Error in the Type of StyleTool %s should be a LABEL Type",
1796                      papszToken[0]);
1797             CSLDestroy( papszToken );
1798             CSLDestroy( papszToken2 );
1799             return FALSE;
1800         }
1801         break;
1802       default:
1803         CPLError(CE_Failure, CPLE_AppDefined,
1804                  "Error in the Type of StyleTool, Type undetermined");
1805         CSLDestroy( papszToken );
1806         CSLDestroy( papszToken2 );
1807         return FALSE;
1808         break;
1809     }
1810 
1811     ////////////////////////////////////////////////////////////////////////
1812     // Here we will loop on each element in the StyleString. If it is
1813     // a valid element, we will add it in the StyleTool with
1814     // SetParamStr().
1815     //
1816     // It is important to note that the SetInternalUnit...() is use to update
1817     // the unit of the StyleTool param (m_eUnit).
1818     // See OGRStyleTool::SetParamStr().
1819     // There's a StyleTool unit (m_eUnit), which is the output unit, and each
1820     // parameter of the style have its own unit value (the input unit). Here we
1821     // set m_eUnit to the input unit and in SetParamStr(), we will use this
1822     // value to set the input unit. Then after the loop we will reset m_eUnit
1823     // to its original value. (Yes it is a side effect / black magic)
1824     //
1825     // The pasStyle variable is a global variable passed in argument to the
1826     // function. See at the top of this file the four OGRStyleParamId
1827     // variable. They are used to register the valid parameter of each
1828     // StyleTool.
1829     ////////////////////////////////////////////////////////////////////////
1830 
1831     // Save Scale and output Units because the parsing code will alter
1832     // the values.
1833     OGRSTUnitId eLastUnit = m_eUnit;
1834     double dSavedScale = m_dfScale;
1835     const int nElements = CSLCount(papszToken2);
1836 
1837     for( int i = 0; i < nElements; i++ )
1838     {
1839         char **papszStylePair =
1840             CSLTokenizeString2( papszToken2[i], ":",
1841                                 CSLT_HONOURSTRINGS
1842                                 | CSLT_STRIPLEADSPACES
1843                                 | CSLT_STRIPENDSPACES
1844                                 | CSLT_ALLOWEMPTYTOKENS );
1845 
1846         const int nTokens = CSLCount(papszStylePair);
1847 
1848         if( nTokens < 1 || nTokens > 2 )
1849         {
1850             CPLError( CE_Warning, CPLE_AppDefined,
1851                       "Error in the StyleTool String %s", m_pszStyleString );
1852             CPLError( CE_Warning, CPLE_AppDefined,
1853                       "Malformed element #%d (\"%s\") skipped",
1854                       i, papszToken2[i] );
1855             CSLDestroy(papszStylePair);
1856             continue;
1857         }
1858 
1859         for( int j = 0; j < nCount; j++ )
1860         {
1861             if( pasStyle[j].pszToken &&
1862                 EQUAL(pasStyle[j].pszToken, papszStylePair[0]) )
1863             {
1864                 if( papszStylePair[1] != nullptr && pasStyle[j].bGeoref == TRUE )
1865                     SetInternalInputUnitFromParam(papszStylePair[1]);
1866 
1867                 // Set either the actual value of style parameter or "1"
1868                 // for boolean parameters which do not have values (legacy
1869                 // behavior).
1870                 OGRStyleTool::SetParamStr(
1871                     pasStyle[j], pasValue[j],
1872                     papszStylePair[1] != nullptr ? papszStylePair[1] : "1" );
1873 
1874                 break;
1875             }
1876         }
1877 
1878         CSLDestroy( papszStylePair );
1879     }
1880 
1881     m_eUnit = eLastUnit;
1882     m_dfScale = dSavedScale;
1883 
1884     CSLDestroy(papszToken2);
1885     CSLDestroy(papszToken);
1886 
1887     return TRUE;
1888 }
1889 //! @endcond
1890 
1891 /************************************************************************/
1892 /*                   SetInternalInputUnitFromParam()                    */
1893 /************************************************************************/
1894 
1895 //! @cond Doxygen_Suppress
SetInternalInputUnitFromParam(char * pszString)1896 void OGRStyleTool::SetInternalInputUnitFromParam( char *pszString )
1897 {
1898     if( pszString == nullptr )
1899         return;
1900 
1901     char *pszUnit = strstr(pszString, "g");
1902     if( pszUnit )
1903     {
1904         SetUnit(OGRSTUGround);
1905         pszUnit[0]= '\0';
1906         return;
1907     }
1908     pszUnit = strstr(pszString, "px");
1909     if( pszUnit )
1910     {
1911         SetUnit(OGRSTUPixel);
1912         pszUnit[0]= '\0';
1913         return;
1914     }
1915     pszUnit = strstr(pszString, "pt");
1916     if( pszUnit )
1917     {
1918         SetUnit(OGRSTUPoints);
1919         pszUnit[0]= '\0';
1920         return;
1921     }
1922     pszUnit = strstr(pszString, "mm");
1923     if( pszUnit )
1924     {
1925         SetUnit(OGRSTUMM);
1926         pszUnit[0]= '\0';
1927         return;
1928     }
1929     pszUnit = strstr(pszString, "cm");
1930     if( pszUnit )
1931     {
1932         SetUnit(OGRSTUCM);
1933         pszUnit[0]= '\0';
1934         return;
1935     }
1936     pszUnit = strstr(pszString, "in");
1937     if( pszUnit )
1938     {
1939         SetUnit(OGRSTUInches);
1940         pszUnit[0]= '\0';
1941         return;
1942     }
1943 
1944     SetUnit(OGRSTUMM);
1945 }
1946 
1947 /************************************************************************/
1948 /*                          ComputeWithUnit()                           */
1949 /************************************************************************/
ComputeWithUnit(double dfValue,OGRSTUnitId eInputUnit)1950 double OGRStyleTool::ComputeWithUnit( double dfValue, OGRSTUnitId eInputUnit )
1951 {
1952     OGRSTUnitId eOutputUnit = GetUnit();
1953 
1954     double dfNewValue = dfValue;  // dfValue in meters;
1955 
1956     if( eOutputUnit == eInputUnit )
1957         return dfValue;
1958 
1959     switch( eInputUnit )
1960     {
1961       case OGRSTUGround:
1962         dfNewValue = dfValue / m_dfScale;
1963         break;
1964       case OGRSTUPixel:
1965         dfNewValue = dfValue / (72.0 * 39.37);
1966         break;
1967       case OGRSTUPoints:
1968         dfNewValue =dfValue / (72.0 * 39.37);
1969         break;
1970       case OGRSTUMM:
1971         dfNewValue = 0.001 * dfValue;
1972         break;
1973       case OGRSTUCM:
1974         dfNewValue = 0.01 * dfValue;
1975         break;
1976       case OGRSTUInches:
1977         dfNewValue = dfValue / 39.37;
1978         break;
1979       default:
1980         break;  // imp.
1981     }
1982 
1983     switch( eOutputUnit )
1984     {
1985       case OGRSTUGround:
1986         dfNewValue *= m_dfScale;
1987         break;
1988       case OGRSTUPixel:
1989         dfNewValue *= 72.0 * 39.37;
1990         break;
1991       case OGRSTUPoints:
1992         dfNewValue *= 72.0 * 39.37;
1993         break;
1994       case OGRSTUMM:
1995         dfNewValue *= 1000.0;
1996         break;
1997       case OGRSTUCM:
1998         dfNewValue *= 100.0;
1999         break;
2000       case OGRSTUInches:
2001         dfNewValue *= 39.37;
2002         break;
2003       default:
2004         break;  // imp.
2005     }
2006     return dfNewValue;
2007 }
2008 
2009 /************************************************************************/
2010 /*                          ComputeWithUnit()                           */
2011 /************************************************************************/
ComputeWithUnit(int nValue,OGRSTUnitId eUnit)2012 int OGRStyleTool::ComputeWithUnit( int nValue, OGRSTUnitId eUnit )
2013 {
2014     return
2015         static_cast<int>(ComputeWithUnit(static_cast<double>(nValue), eUnit));
2016 }
2017 //! @endcond
2018 
2019 /************************************************************************/
2020 /*                            GetParamStr()                             */
2021 /************************************************************************/
2022 
2023 /** Undocumented
2024  * @param sStyleParam undocumented.
2025  * @param sStyleValue undocumented.
2026  * @param bValueIsNull undocumented.
2027  * @return Undocumented.
2028  */
GetParamStr(const OGRStyleParamId & sStyleParam,OGRStyleValue & sStyleValue,GBool & bValueIsNull)2029 const char *OGRStyleTool::GetParamStr( const OGRStyleParamId &sStyleParam ,
2030                                        OGRStyleValue &sStyleValue,
2031                                        GBool &bValueIsNull )
2032 {
2033     if( !Parse() )
2034     {
2035         bValueIsNull = TRUE;
2036         return nullptr;
2037     }
2038 
2039     bValueIsNull = !sStyleValue.bValid;
2040 
2041     if( bValueIsNull == TRUE )
2042         return nullptr;
2043 
2044     switch( sStyleParam.eType )
2045     {
2046       // If sStyleParam.bGeoref == TRUE, need to convert to output value.
2047       case OGRSTypeString:
2048         return sStyleValue.pszValue;
2049       case OGRSTypeDouble:
2050         if( sStyleParam.bGeoref )
2051           return CPLSPrintf("%f", ComputeWithUnit(sStyleValue.dfValue,
2052                                                   sStyleValue.eUnit));
2053         else
2054           return CPLSPrintf("%f", sStyleValue.dfValue);
2055 
2056       case OGRSTypeInteger:
2057         if( sStyleParam.bGeoref )
2058           return CPLSPrintf("%d", ComputeWithUnit(sStyleValue.nValue,
2059                                                   sStyleValue.eUnit));
2060         else
2061           return CPLSPrintf("%d", sStyleValue.nValue);
2062       case OGRSTypeBoolean:
2063         return CPLSPrintf("%d", sStyleValue.nValue != 0);
2064       default:
2065         bValueIsNull = TRUE;
2066         return nullptr;
2067     }
2068 }
2069 
2070 /****************************************************************************/
2071 /*    int OGRStyleTool::GetParamNum(OGRStyleParamId sStyleParam ,           */
2072 /*                               OGRStyleValue sStyleValue,                 */
2073 /*                               GBool &bValueIsNull)                       */
2074 /*                                                                          */
2075 /****************************************************************************/
2076 
2077 /** Undocumented
2078  * @param sStyleParam undocumented.
2079  * @param sStyleValue undocumented.
2080  * @param bValueIsNull undocumented.
2081  * @return Undocumented.
2082  */
GetParamNum(const OGRStyleParamId & sStyleParam,OGRStyleValue & sStyleValue,GBool & bValueIsNull)2083 int OGRStyleTool::GetParamNum( const OGRStyleParamId &sStyleParam ,
2084                                OGRStyleValue &sStyleValue,
2085                                GBool &bValueIsNull )
2086 {
2087     return
2088         static_cast<int>(GetParamDbl(sStyleParam, sStyleValue, bValueIsNull));
2089 }
2090 
2091 /****************************************************************************/
2092 /*       double OGRStyleTool::GetParamDbl(OGRStyleParamId sStyleParam ,     */
2093 /*                               OGRStyleValue sStyleValue,                 */
2094 /*                               GBool &bValueIsNull)                       */
2095 /*                                                                          */
2096 /****************************************************************************/
2097 
2098 /** Undocumented
2099  * @param sStyleParam undocumented.
2100  * @param sStyleValue undocumented.
2101  * @param bValueIsNull undocumented.
2102  * @return Undocumented.
2103  */
GetParamDbl(const OGRStyleParamId & sStyleParam,OGRStyleValue & sStyleValue,GBool & bValueIsNull)2104 double OGRStyleTool::GetParamDbl( const OGRStyleParamId &sStyleParam ,
2105                                   OGRStyleValue &sStyleValue,
2106                                   GBool &bValueIsNull )
2107 {
2108     if( !Parse() )
2109     {
2110         bValueIsNull = TRUE;
2111         return 0.0;
2112     }
2113 
2114     bValueIsNull = !sStyleValue.bValid;
2115 
2116     if( bValueIsNull == TRUE )
2117         return 0.0;
2118 
2119     switch( sStyleParam.eType )
2120     {
2121       // if sStyleParam.bGeoref == TRUE, need to convert to output value.
2122       case OGRSTypeString:
2123         if( sStyleParam.bGeoref )
2124           return ComputeWithUnit(CPLAtof(sStyleValue.pszValue),
2125                                  sStyleValue.eUnit);
2126         else
2127           return CPLAtof(sStyleValue.pszValue);
2128       case OGRSTypeDouble:
2129         if( sStyleParam.bGeoref )
2130           return ComputeWithUnit(sStyleValue.dfValue,
2131                                  sStyleValue.eUnit);
2132         else
2133           return sStyleValue.dfValue;
2134       case OGRSTypeInteger:
2135         if( sStyleParam.bGeoref )
2136           return static_cast<double>(
2137               ComputeWithUnit(sStyleValue.nValue,
2138                               sStyleValue.eUnit));
2139         else
2140           return static_cast<double>(sStyleValue.nValue);
2141       case OGRSTypeBoolean:
2142         return static_cast<double>(sStyleValue.nValue != 0);
2143       default:
2144         bValueIsNull = TRUE;
2145         return 0.0;
2146     }
2147 }
2148 
2149 /****************************************************************************/
2150 /*      void OGRStyleTool::SetParamStr(OGRStyleParamId &sStyleParam ,       */
2151 /*                             OGRStyleValue &sStyleValue,                  */
2152 /*                             const char *pszParamString)                  */
2153 /*                                                                          */
2154 /****************************************************************************/
2155 
2156 /** Undocumented
2157  * @param sStyleParam undocumented.
2158  * @param sStyleValue undocumented.
2159  * @param pszParamString undocumented.
2160  */
SetParamStr(const OGRStyleParamId & sStyleParam,OGRStyleValue & sStyleValue,const char * pszParamString)2161 void OGRStyleTool::SetParamStr( const OGRStyleParamId &sStyleParam ,
2162                                 OGRStyleValue &sStyleValue,
2163                                 const char *pszParamString )
2164 {
2165     Parse();
2166     StyleModified();
2167     sStyleValue.bValid = TRUE;
2168     sStyleValue.eUnit = GetUnit();
2169     switch( sStyleParam.eType )
2170     {
2171       // If sStyleParam.bGeoref == TRUE, need to convert to output value;
2172       case OGRSTypeString:
2173         sStyleValue.pszValue = CPLStrdup(pszParamString);
2174         break;
2175       case OGRSTypeDouble:
2176         sStyleValue.dfValue = CPLAtof(pszParamString);
2177         break;
2178       case OGRSTypeInteger:
2179         sStyleValue.nValue = atoi(pszParamString);
2180         break;
2181       case OGRSTypeBoolean:
2182         sStyleValue.nValue = atoi(pszParamString) != 0;
2183         break;
2184       default:
2185         sStyleValue.bValid = FALSE;
2186         break;
2187     }
2188 }
2189 
2190 /****************************************************************************/
2191 /*    void OGRStyleTool::SetParamNum(OGRStyleParamId &sStyleParam ,         */
2192 /*                             OGRStyleValue &sStyleValue,                  */
2193 /*                             int nParam)                                  */
2194 /*                                                                          */
2195 /****************************************************************************/
2196 
2197 /** Undocumented
2198  * @param sStyleParam undocumented.
2199  * @param sStyleValue undocumented.
2200  * @param nParam undocumented.
2201  */
SetParamNum(const OGRStyleParamId & sStyleParam,OGRStyleValue & sStyleValue,int nParam)2202 void OGRStyleTool::SetParamNum( const OGRStyleParamId &sStyleParam ,
2203                                 OGRStyleValue &sStyleValue,
2204                                 int nParam )
2205 {
2206     Parse();
2207     StyleModified();
2208     sStyleValue.bValid = TRUE;
2209     sStyleValue.eUnit = GetUnit();
2210     switch( sStyleParam.eType )
2211     {
2212 
2213       // If sStyleParam.bGeoref == TRUE, need to convert to output value;
2214       case OGRSTypeString:
2215         sStyleValue.pszValue = CPLStrdup(CPLString().Printf("%d", nParam));
2216         break;
2217       case OGRSTypeDouble:
2218         sStyleValue.dfValue = static_cast<double>(nParam);
2219         break;
2220       case OGRSTypeInteger:
2221         sStyleValue.nValue = nParam;
2222         break;
2223       case OGRSTypeBoolean:
2224         sStyleValue.nValue = nParam != 0;
2225         break;
2226       default:
2227         sStyleValue.bValid = FALSE;
2228         break;
2229     }
2230 }
2231 
2232 /****************************************************************************/
2233 /*      void OGRStyleTool::SetParamDbl(OGRStyleParamId &sStyleParam ,       */
2234 /*                             OGRStyleValue &sStyleValue,                  */
2235 /*                             double dfParam)                              */
2236 /*                                                                          */
2237 /****************************************************************************/
2238 
2239 /** Undocumented
2240  * @param sStyleParam undocumented.
2241  * @param sStyleValue undocumented.
2242  * @param dfParam undocumented.
2243  */
SetParamDbl(const OGRStyleParamId & sStyleParam,OGRStyleValue & sStyleValue,double dfParam)2244 void OGRStyleTool::SetParamDbl( const OGRStyleParamId &sStyleParam,
2245                                 OGRStyleValue &sStyleValue,
2246                                 double dfParam )
2247 {
2248     Parse();
2249     StyleModified();
2250     sStyleValue.bValid = TRUE;
2251     sStyleValue.eUnit = GetUnit();
2252     switch( sStyleParam.eType )
2253     {
2254       // If sStyleParam.bGeoref == TRUE, need to convert to output value;
2255       case OGRSTypeString:
2256         sStyleValue.pszValue = CPLStrdup(CPLString().Printf("%f", dfParam));
2257         break;
2258       case OGRSTypeDouble:
2259         sStyleValue.dfValue = dfParam;
2260         break;
2261       case OGRSTypeInteger:
2262         sStyleValue.nValue = static_cast<int>(dfParam);
2263         break;
2264       case OGRSTypeBoolean:
2265         sStyleValue.nValue = static_cast<int>(dfParam) != 0;
2266         break;
2267       default:
2268         sStyleValue.bValid = FALSE;
2269         break;
2270     }
2271 }
2272 
2273 /************************************************************************/
2274 /*                           OGR_ST_GetParamStr()                       */
2275 /************************************************************************/
2276 /**
2277  * \brief Get Style Tool parameter value as string
2278  *
2279  * Maps to the OGRStyleTool subclasses' GetParamStr() methods.
2280  *
2281  * @param hST handle to the style tool.
2282  * @param eParam the parameter id from the enumeration corresponding to the
2283  * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam,
2284  * OGRSTSymbolParam or OGRSTLabelParam enumerations)
2285  * @param bValueIsNull pointer to an integer that will be set to TRUE or FALSE
2286  * to indicate whether the parameter value is NULL.
2287  *
2288  * @return the parameter value as string and sets bValueIsNull.
2289  */
2290 
OGR_ST_GetParamStr(OGRStyleToolH hST,int eParam,int * bValueIsNull)2291 const char *OGR_ST_GetParamStr( OGRStyleToolH hST, int eParam,
2292                                 int *bValueIsNull )
2293 {
2294     VALIDATE_POINTER1( hST, "OGR_ST_GetParamStr", "" );
2295     VALIDATE_POINTER1( bValueIsNull, "OGR_ST_GetParamStr", "" );
2296 
2297     GBool bIsNull = TRUE;
2298     const char *pszVal = "";
2299 
2300     switch( reinterpret_cast<OGRStyleTool *>(hST)->GetType() )
2301     {
2302     case OGRSTCPen:
2303         pszVal = reinterpret_cast<OGRStylePen *>(hST)->
2304             GetParamStr(static_cast<OGRSTPenParam>(eParam), bIsNull);
2305         break;
2306     case OGRSTCBrush:
2307         pszVal = reinterpret_cast<OGRStyleBrush *>(hST)->
2308             GetParamStr(static_cast<OGRSTBrushParam>(eParam), bIsNull);
2309         break;
2310     case OGRSTCSymbol:
2311         pszVal = reinterpret_cast<OGRStyleSymbol *>(hST)->
2312             GetParamStr(static_cast<OGRSTSymbolParam>(eParam), bIsNull);
2313         break;
2314     case OGRSTCLabel:
2315         pszVal = reinterpret_cast<OGRStyleLabel *>(hST)->
2316             GetParamStr(static_cast<OGRSTLabelParam>(eParam), bIsNull);
2317         break;
2318     default:
2319         break;
2320     }
2321 
2322     *bValueIsNull = bIsNull;
2323     return pszVal;
2324 }
2325 
2326 /************************************************************************/
2327 /*                           OGR_ST_GetParamNum()                       */
2328 /************************************************************************/
2329 /**
2330  * \brief Get Style Tool parameter value as an integer
2331  *
2332  * Maps to the OGRStyleTool subclasses' GetParamNum() methods.
2333  *
2334  * @param hST handle to the style tool.
2335  * @param eParam the parameter id from the enumeration corresponding to the
2336  * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam,
2337  * OGRSTSymbolParam or OGRSTLabelParam enumerations)
2338  * @param bValueIsNull pointer to an integer that will be set to TRUE or FALSE
2339  * to indicate whether the parameter value is NULL.
2340  *
2341  * @return the parameter value as integer and sets bValueIsNull.
2342  */
2343 
OGR_ST_GetParamNum(OGRStyleToolH hST,int eParam,int * bValueIsNull)2344 int OGR_ST_GetParamNum( OGRStyleToolH hST, int eParam, int *bValueIsNull )
2345 {
2346     VALIDATE_POINTER1( hST, "OGR_ST_GetParamNum", 0 );
2347     VALIDATE_POINTER1( bValueIsNull, "OGR_ST_GetParamNum", 0 );
2348 
2349     GBool bIsNull = TRUE;
2350     int nVal = 0;
2351 
2352     switch( reinterpret_cast<OGRStyleTool *>(hST)->GetType() )
2353     {
2354     case OGRSTCPen:
2355         nVal = reinterpret_cast<OGRStylePen *>(hST)->
2356             GetParamNum(static_cast<OGRSTPenParam>(eParam), bIsNull);
2357         break;
2358     case OGRSTCBrush:
2359         nVal = reinterpret_cast<OGRStyleBrush *>(hST)->
2360             GetParamNum(static_cast<OGRSTBrushParam>(eParam), bIsNull);
2361         break;
2362     case OGRSTCSymbol:
2363         nVal = reinterpret_cast<OGRStyleSymbol *>(hST)->
2364             GetParamNum(static_cast<OGRSTSymbolParam>(eParam), bIsNull);
2365         break;
2366     case OGRSTCLabel:
2367         nVal = reinterpret_cast<OGRStyleLabel *>(hST)->
2368             GetParamNum(static_cast<OGRSTLabelParam>(eParam), bIsNull);
2369         break;
2370     default:
2371         break;
2372     }
2373 
2374     *bValueIsNull = bIsNull;
2375     return nVal;
2376 }
2377 
2378 /************************************************************************/
2379 /*                           OGR_ST_GetParamDbl()                       */
2380 /************************************************************************/
2381 /**
2382  * \brief Get Style Tool parameter value as a double
2383  *
2384  * Maps to the OGRStyleTool subclasses' GetParamDbl() methods.
2385  *
2386  * @param hST handle to the style tool.
2387  * @param eParam the parameter id from the enumeration corresponding to the
2388  * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam,
2389  * OGRSTSymbolParam or OGRSTLabelParam enumerations)
2390  * @param bValueIsNull pointer to an integer that will be set to TRUE or FALSE
2391  * to indicate whether the parameter value is NULL.
2392  *
2393  * @return the parameter value as double and sets bValueIsNull.
2394  */
2395 
OGR_ST_GetParamDbl(OGRStyleToolH hST,int eParam,int * bValueIsNull)2396 double OGR_ST_GetParamDbl( OGRStyleToolH hST, int eParam, int *bValueIsNull )
2397 {
2398     VALIDATE_POINTER1( hST, "OGR_ST_GetParamDbl", 0.0 );
2399     VALIDATE_POINTER1( bValueIsNull, "OGR_ST_GetParamDbl", 0.0 );
2400 
2401     GBool bIsNull = TRUE;
2402     double dfVal = 0.0;
2403 
2404     switch( reinterpret_cast<OGRStyleTool *>(hST)->GetType() )
2405     {
2406     case OGRSTCPen:
2407         dfVal = reinterpret_cast<OGRStylePen *>(hST)->
2408             GetParamDbl(static_cast<OGRSTPenParam>(eParam), bIsNull);
2409         break;
2410     case OGRSTCBrush:
2411         dfVal = reinterpret_cast<OGRStyleBrush *>(hST)->
2412             GetParamDbl(static_cast<OGRSTBrushParam>(eParam), bIsNull);
2413         break;
2414     case OGRSTCSymbol:
2415         dfVal = reinterpret_cast<OGRStyleSymbol *>(hST)->
2416             GetParamDbl(static_cast<OGRSTSymbolParam>(eParam), bIsNull);
2417         break;
2418     case OGRSTCLabel:
2419         dfVal = reinterpret_cast<OGRStyleLabel *>(hST)->
2420             GetParamDbl(static_cast<OGRSTLabelParam>(eParam), bIsNull);
2421         break;
2422     default:
2423         break;
2424     }
2425 
2426     *bValueIsNull = bIsNull;
2427     return dfVal;
2428 }
2429 
2430 /************************************************************************/
2431 /*                           OGR_ST_SetParamStr()                       */
2432 /************************************************************************/
2433 /**
2434  * \brief Set Style Tool parameter value from a string
2435  *
2436  * Maps to the OGRStyleTool subclasses' SetParamStr() methods.
2437  *
2438  * @param hST handle to the style tool.
2439  * @param eParam the parameter id from the enumeration corresponding to the
2440  * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam,
2441  * OGRSTSymbolParam or OGRSTLabelParam enumerations)
2442  * @param pszValue the new parameter value
2443  *
2444  */
2445 
OGR_ST_SetParamStr(OGRStyleToolH hST,int eParam,const char * pszValue)2446 void OGR_ST_SetParamStr( OGRStyleToolH hST, int eParam, const char *pszValue )
2447 {
2448     VALIDATE_POINTER0( hST, "OGR_ST_SetParamStr" );
2449     VALIDATE_POINTER0( pszValue, "OGR_ST_SetParamStr" );
2450 
2451     switch( reinterpret_cast<OGRStyleTool *>(hST)->GetType() )
2452     {
2453     case OGRSTCPen:
2454         reinterpret_cast<OGRStylePen *>(hST)->
2455             SetParamStr(static_cast<OGRSTPenParam>(eParam), pszValue);
2456         break;
2457     case OGRSTCBrush:
2458         reinterpret_cast<OGRStyleBrush *>(hST)->
2459             SetParamStr(static_cast<OGRSTBrushParam>(eParam), pszValue);
2460         break;
2461     case OGRSTCSymbol:
2462         reinterpret_cast<OGRStyleSymbol *>(hST)->
2463             SetParamStr(static_cast<OGRSTSymbolParam>(eParam), pszValue);
2464         break;
2465     case OGRSTCLabel:
2466         reinterpret_cast<OGRStyleLabel *>(hST)->
2467             SetParamStr(static_cast<OGRSTLabelParam>(eParam), pszValue);
2468         break;
2469     default:
2470         break;
2471     }
2472 }
2473 
2474 /************************************************************************/
2475 /*                           OGR_ST_SetParamNum()                       */
2476 /************************************************************************/
2477 /**
2478  * \brief Set Style Tool parameter value from an integer
2479  *
2480  * Maps to the OGRStyleTool subclasses' SetParamNum() methods.
2481  *
2482  * @param hST handle to the style tool.
2483  * @param eParam the parameter id from the enumeration corresponding to the
2484  * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam,
2485  * OGRSTSymbolParam or OGRSTLabelParam enumerations)
2486  * @param nValue the new parameter value
2487  *
2488  */
2489 
OGR_ST_SetParamNum(OGRStyleToolH hST,int eParam,int nValue)2490 void OGR_ST_SetParamNum( OGRStyleToolH hST, int eParam, int nValue )
2491 {
2492     VALIDATE_POINTER0( hST, "OGR_ST_SetParamNum" );
2493 
2494     switch( reinterpret_cast<OGRStyleTool *>(hST)->GetType() )
2495     {
2496     case OGRSTCPen:
2497         reinterpret_cast<OGRStylePen *>(hST)->
2498             SetParamNum(static_cast<OGRSTPenParam>(eParam), nValue);
2499         break;
2500     case OGRSTCBrush:
2501         reinterpret_cast<OGRStyleBrush *>(hST)->
2502             SetParamNum(static_cast<OGRSTBrushParam>(eParam), nValue);
2503         break;
2504     case OGRSTCSymbol:
2505         reinterpret_cast<OGRStyleSymbol *>(hST)->
2506             SetParamNum(static_cast<OGRSTSymbolParam>(eParam), nValue);
2507         break;
2508     case OGRSTCLabel:
2509         reinterpret_cast<OGRStyleLabel *>(hST)->
2510             SetParamNum(static_cast<OGRSTLabelParam>(eParam), nValue);
2511         break;
2512     default:
2513         break;
2514     }
2515 }
2516 
2517 /************************************************************************/
2518 /*                           OGR_ST_SetParamDbl()                       */
2519 /************************************************************************/
2520 /**
2521  * \brief Set Style Tool parameter value from a double
2522  *
2523  * Maps to the OGRStyleTool subclasses' SetParamDbl() methods.
2524  *
2525  * @param hST handle to the style tool.
2526  * @param eParam the parameter id from the enumeration corresponding to the
2527  * type of this style tool (one of the OGRSTPenParam, OGRSTBrushParam,
2528  * OGRSTSymbolParam or OGRSTLabelParam enumerations)
2529  * @param dfValue the new parameter value
2530  *
2531  */
2532 
OGR_ST_SetParamDbl(OGRStyleToolH hST,int eParam,double dfValue)2533 void OGR_ST_SetParamDbl( OGRStyleToolH hST, int eParam, double dfValue )
2534 {
2535     VALIDATE_POINTER0( hST, "OGR_ST_SetParamDbl" );
2536 
2537     switch( reinterpret_cast<OGRStyleTool *>(hST)->GetType() )
2538     {
2539     case OGRSTCPen:
2540         reinterpret_cast<OGRStylePen *>(hST)->
2541             SetParamDbl(static_cast<OGRSTPenParam>(eParam), dfValue);
2542         break;
2543     case OGRSTCBrush:
2544         reinterpret_cast<OGRStyleBrush *>(hST)->
2545             SetParamDbl(static_cast<OGRSTBrushParam>(eParam), dfValue);
2546         break;
2547     case OGRSTCSymbol:
2548         reinterpret_cast<OGRStyleSymbol *>(hST)->
2549             SetParamDbl(static_cast<OGRSTSymbolParam>(eParam), dfValue);
2550         break;
2551     case OGRSTCLabel:
2552         reinterpret_cast<OGRStyleLabel *>(hST)->
2553             SetParamDbl(static_cast<OGRSTLabelParam>(eParam), dfValue);
2554         break;
2555     default:
2556         break;
2557     }
2558 }
2559 
2560 /************************************************************************/
2561 /*                           OGR_ST_GetStyleString()                    */
2562 /************************************************************************/
2563 
2564 /**
2565  * \fn OGRStyleTool::GetStyleString()
2566  * \brief Get the style string for this Style Tool
2567  *
2568  * Maps to the OGRStyleTool subclasses' GetStyleString() methods.
2569  *
2570  * @return the style string for this style tool or "" if the hST is invalid.
2571  */
2572 
2573 /**
2574  * \brief Get the style string for this Style Tool
2575  *
2576  * Maps to the OGRStyleTool subclasses' GetStyleString() methods.
2577  *
2578  * @param hST handle to the style tool.
2579  *
2580  * @return the style string for this style tool or "" if the hST is invalid.
2581  */
2582 
OGR_ST_GetStyleString(OGRStyleToolH hST)2583 const char *OGR_ST_GetStyleString( OGRStyleToolH hST )
2584 {
2585     const char *pszVal = "";
2586 
2587     VALIDATE_POINTER1( hST, "OGR_ST_GetStyleString", "" );
2588 
2589     switch( reinterpret_cast<OGRStyleTool *>(hST)->GetType() )
2590     {
2591       case OGRSTCPen:
2592         pszVal = reinterpret_cast<OGRStylePen *>(hST)->GetStyleString();
2593         break;
2594       case OGRSTCBrush:
2595         pszVal = reinterpret_cast<OGRStyleBrush *>(hST)->GetStyleString();
2596         break;
2597       case OGRSTCSymbol:
2598         pszVal = reinterpret_cast<OGRStyleSymbol *>(hST)->GetStyleString();
2599         break;
2600       case OGRSTCLabel:
2601         pszVal = reinterpret_cast<OGRStyleLabel *>(hST)->GetStyleString();
2602         break;
2603       default:
2604         break;
2605     }
2606 
2607     return pszVal;
2608 }
2609 
2610 /************************************************************************/
2611 /*                           OGR_ST_GetRGBFromString()                  */
2612 /************************************************************************/
2613 /**
2614  * \brief Return the r,g,b,a components of a color encoded in \#RRGGBB[AA]
2615  * format.
2616  *
2617  * Maps to OGRStyleTool::GetRGBFromString().
2618  *
2619  * @param hST handle to the style tool.
2620  * @param pszColor the color to parse
2621  * @param pnRed pointer to an int in which the red value will be returned
2622  * @param pnGreen pointer to an int in which the green value will be returned
2623  * @param pnBlue pointer to an int in which the blue value will be returned
2624  * @param pnAlpha pointer to an int in which the (optional) alpha value will
2625  * be returned
2626  *
2627  * @return TRUE if the color could be successfully parsed, or FALSE in case of
2628  * errors.
2629  */
2630 
OGR_ST_GetRGBFromString(OGRStyleToolH hST,const char * pszColor,int * pnRed,int * pnGreen,int * pnBlue,int * pnAlpha)2631 int OGR_ST_GetRGBFromString( OGRStyleToolH hST, const char *pszColor,
2632                              int *pnRed, int *pnGreen, int *pnBlue,
2633                              int *pnAlpha )
2634 {
2635 
2636     VALIDATE_POINTER1( hST, "OGR_ST_GetRGBFromString", FALSE );
2637     VALIDATE_POINTER1( pnRed, "OGR_ST_GetRGBFromString", FALSE );
2638     VALIDATE_POINTER1( pnGreen, "OGR_ST_GetRGBFromString", FALSE );
2639     VALIDATE_POINTER1( pnBlue, "OGR_ST_GetRGBFromString", FALSE );
2640     VALIDATE_POINTER1( pnAlpha, "OGR_ST_GetRGBFromString", FALSE );
2641 
2642     return reinterpret_cast<OGRStyleTool *>(hST)->
2643         GetRGBFromString(pszColor, *pnRed, *pnGreen,
2644                          *pnBlue, *pnAlpha );
2645 }
2646 
2647 //! @cond Doxygen_Suppress
2648 /* ======================================================================== */
2649 /*                OGRStylePen                                               */
2650 /*       Specific parameter (Set/Get) for the StylePen                      */
2651 /* ======================================================================== */
2652 
2653 /****************************************************************************/
2654 /*                      OGRStylePen::OGRStylePen()                          */
2655 /*                                                                          */
2656 /****************************************************************************/
OGRStylePen()2657 OGRStylePen::OGRStylePen() :
2658     OGRStyleTool(OGRSTCPen),
2659     m_pasStyleValue( static_cast<OGRStyleValue *>(
2660         CPLCalloc(OGRSTPenLast, sizeof(OGRStyleValue))))
2661 {
2662 }
2663 
2664 /****************************************************************************/
2665 /*                      OGRStylePen::~OGRStylePen()                         */
2666 /*                                                                          */
2667 /****************************************************************************/
~OGRStylePen()2668 OGRStylePen::~OGRStylePen()
2669 {
2670     for( int i = 0; i < OGRSTPenLast; i++ )
2671     {
2672         if( m_pasStyleValue[i].pszValue != nullptr )
2673         {
2674             CPLFree(m_pasStyleValue[i].pszValue);
2675             m_pasStyleValue[i].pszValue = nullptr;
2676         }
2677     }
2678 
2679     CPLFree(m_pasStyleValue);
2680 }
2681 
2682 /************************************************************************/
2683 /*                         OGRStylePen::Parse()                         */
2684 /************************************************************************/
Parse()2685 GBool OGRStylePen::Parse()
2686 
2687 {
2688     return OGRStyleTool::Parse(asStylePen, m_pasStyleValue,
2689                                static_cast<int>(OGRSTPenLast));
2690 }
2691 
2692 /************************************************************************/
2693 /*                            GetParamStr()                             */
2694 /************************************************************************/
GetParamStr(OGRSTPenParam eParam,GBool & bValueIsNull)2695 const char *OGRStylePen::GetParamStr( OGRSTPenParam eParam,
2696                                       GBool &bValueIsNull )
2697 {
2698     return OGRStyleTool::GetParamStr(asStylePen[eParam],
2699                                      m_pasStyleValue[eParam],
2700                                      bValueIsNull);
2701 }
2702 
2703 /************************************************************************/
2704 /*                            GetParamNum()                             */
2705 /************************************************************************/
GetParamNum(OGRSTPenParam eParam,GBool & bValueIsNull)2706 int OGRStylePen::GetParamNum( OGRSTPenParam eParam, GBool &bValueIsNull )
2707 {
2708     return OGRStyleTool::GetParamNum(asStylePen[eParam],
2709                                      m_pasStyleValue[eParam], bValueIsNull);
2710 }
2711 
2712 /************************************************************************/
2713 /*                            GetParamDbl()                             */
2714 /************************************************************************/
GetParamDbl(OGRSTPenParam eParam,GBool & bValueIsNull)2715 double OGRStylePen::GetParamDbl( OGRSTPenParam eParam, GBool &bValueIsNull )
2716 {
2717     return OGRStyleTool::GetParamDbl(asStylePen[eParam],
2718                                      m_pasStyleValue[eParam], bValueIsNull);
2719 }
2720 
2721 /************************************************************************/
2722 /*                            SetParamStr()                             */
2723 /************************************************************************/
2724 
SetParamStr(OGRSTPenParam eParam,const char * pszParamString)2725 void OGRStylePen::SetParamStr( OGRSTPenParam eParam,
2726                                const char *pszParamString )
2727 {
2728     OGRStyleTool::SetParamStr(asStylePen[eParam], m_pasStyleValue[eParam],
2729                               pszParamString);
2730 }
2731 
2732 /************************************************************************/
2733 /*                            SetParamNum()                             */
2734 /************************************************************************/
SetParamNum(OGRSTPenParam eParam,int nParam)2735 void OGRStylePen::SetParamNum( OGRSTPenParam eParam, int nParam )
2736 {
2737     OGRStyleTool::SetParamNum(asStylePen[eParam],
2738                               m_pasStyleValue[eParam], nParam);
2739 }
2740 
2741 /************************************************************************/
2742 /*                            SetParamDbl()                             */
2743 /************************************************************************/
SetParamDbl(OGRSTPenParam eParam,double dfParam)2744 void OGRStylePen::SetParamDbl( OGRSTPenParam eParam, double dfParam )
2745 {
2746     OGRStyleTool::SetParamDbl(asStylePen[eParam],
2747                               m_pasStyleValue[eParam], dfParam);
2748 }
2749 
2750 /************************************************************************/
2751 /*                           GetStyleString()                           */
2752 /************************************************************************/
GetStyleString()2753 const char *OGRStylePen::GetStyleString()
2754 {
2755     return OGRStyleTool::GetStyleString(asStylePen, m_pasStyleValue,
2756                                         static_cast<int>(OGRSTPenLast));
2757 }
2758 
2759 /****************************************************************************/
2760 /*                      OGRStyleBrush::OGRStyleBrush()                      */
2761 /*                                                                          */
2762 /****************************************************************************/
OGRStyleBrush()2763 OGRStyleBrush::OGRStyleBrush() :
2764     OGRStyleTool(OGRSTCBrush),
2765     m_pasStyleValue( static_cast<OGRStyleValue *>(
2766         CPLCalloc(OGRSTBrushLast, sizeof(OGRStyleValue))))
2767 {
2768 }
2769 
2770 /****************************************************************************/
2771 /*                      OGRStyleBrush::~OGRStyleBrush()                     */
2772 /*                                                                          */
2773 /****************************************************************************/
~OGRStyleBrush()2774 OGRStyleBrush::~OGRStyleBrush()
2775 {
2776     for( int i = 0; i < OGRSTBrushLast; i++ )
2777     {
2778         if( m_pasStyleValue[i].pszValue != nullptr )
2779         {
2780             CPLFree(m_pasStyleValue[i].pszValue);
2781             m_pasStyleValue[i].pszValue = nullptr;
2782         }
2783     }
2784 
2785     CPLFree(m_pasStyleValue);
2786 }
2787 
2788 /************************************************************************/
2789 /*                               Parse()                                */
2790 /************************************************************************/
Parse()2791 GBool OGRStyleBrush::Parse()
2792 {
2793     return OGRStyleTool::Parse(asStyleBrush, m_pasStyleValue,
2794                                static_cast<int>(OGRSTBrushLast));
2795 }
2796 
2797 /************************************************************************/
2798 /*                            GetParamStr()                             */
2799 /************************************************************************/
GetParamStr(OGRSTBrushParam eParam,GBool & bValueIsNull)2800 const char *OGRStyleBrush::GetParamStr( OGRSTBrushParam eParam,
2801                                         GBool &bValueIsNull )
2802 {
2803     return OGRStyleTool::GetParamStr(asStyleBrush[eParam],
2804                                      m_pasStyleValue[eParam],
2805                                      bValueIsNull);
2806 }
2807 
2808 /************************************************************************/
2809 /*                            GetParamNum()                             */
2810 /************************************************************************/
GetParamNum(OGRSTBrushParam eParam,GBool & bValueIsNull)2811 int OGRStyleBrush::GetParamNum( OGRSTBrushParam eParam, GBool &bValueIsNull )
2812 {
2813     return OGRStyleTool::GetParamNum(asStyleBrush[eParam],
2814                                      m_pasStyleValue[eParam], bValueIsNull);
2815 }
2816 
2817 /************************************************************************/
2818 /*                            GetParamDbl()                             */
2819 /************************************************************************/
GetParamDbl(OGRSTBrushParam eParam,GBool & bValueIsNull)2820 double OGRStyleBrush::GetParamDbl( OGRSTBrushParam eParam, GBool &bValueIsNull )
2821 {
2822     return OGRStyleTool::GetParamDbl(asStyleBrush[eParam],
2823                                      m_pasStyleValue[eParam], bValueIsNull);
2824 }
2825 
2826 /************************************************************************/
2827 /*                            SetParamStr()                             */
2828 /************************************************************************/
SetParamStr(OGRSTBrushParam eParam,const char * pszParamString)2829 void OGRStyleBrush::SetParamStr( OGRSTBrushParam eParam,
2830                                  const char *pszParamString )
2831 {
2832     OGRStyleTool::SetParamStr(asStyleBrush[eParam], m_pasStyleValue[eParam],
2833                               pszParamString);
2834 }
2835 
2836 /************************************************************************/
2837 /*                            SetParamNum()                             */
2838 /************************************************************************/
SetParamNum(OGRSTBrushParam eParam,int nParam)2839 void OGRStyleBrush::SetParamNum( OGRSTBrushParam eParam, int nParam )
2840 {
2841     OGRStyleTool::SetParamNum(asStyleBrush[eParam],
2842                               m_pasStyleValue[eParam], nParam);
2843 }
2844 
2845 /************************************************************************/
2846 /*                            SetParamDbl()                             */
2847 /************************************************************************/
SetParamDbl(OGRSTBrushParam eParam,double dfParam)2848 void OGRStyleBrush::SetParamDbl( OGRSTBrushParam eParam, double dfParam )
2849 {
2850     OGRStyleTool::SetParamDbl(asStyleBrush[eParam],
2851                               m_pasStyleValue[eParam], dfParam);
2852 }
2853 
2854 /************************************************************************/
2855 /*                           GetStyleString()                           */
2856 /************************************************************************/
GetStyleString()2857 const char *OGRStyleBrush::GetStyleString()
2858 {
2859     return OGRStyleTool::GetStyleString(asStyleBrush, m_pasStyleValue,
2860                                         static_cast<int>(OGRSTBrushLast));
2861 }
2862 
2863 /****************************************************************************/
2864 /*                      OGRStyleSymbol::OGRStyleSymbol()                    */
2865 /****************************************************************************/
OGRStyleSymbol()2866 OGRStyleSymbol::OGRStyleSymbol() :
2867     OGRStyleTool(OGRSTCSymbol),
2868     m_pasStyleValue( static_cast<OGRStyleValue *>(
2869         CPLCalloc(OGRSTSymbolLast, sizeof(OGRStyleValue))))
2870 {
2871 }
2872 
2873 /****************************************************************************/
2874 /*                      OGRStyleSymbol::~OGRStyleSymbol()                   */
2875 /*                                                                          */
2876 /****************************************************************************/
~OGRStyleSymbol()2877 OGRStyleSymbol::~OGRStyleSymbol()
2878 {
2879     for( int i = 0; i < OGRSTSymbolLast; i++ )
2880     {
2881         if( m_pasStyleValue[i].pszValue != nullptr )
2882         {
2883             CPLFree(m_pasStyleValue[i].pszValue);
2884             m_pasStyleValue[i].pszValue = nullptr;
2885         }
2886     }
2887 
2888     CPLFree(m_pasStyleValue);
2889 }
2890 
2891 /************************************************************************/
2892 /*                               Parse()                                */
2893 /************************************************************************/
Parse()2894 GBool OGRStyleSymbol::Parse()
2895 {
2896     return OGRStyleTool::Parse(asStyleSymbol, m_pasStyleValue,
2897                                static_cast<int>(OGRSTSymbolLast));
2898 }
2899 
2900 /************************************************************************/
2901 /*                            GetParamStr()                             */
2902 /************************************************************************/
GetParamStr(OGRSTSymbolParam eParam,GBool & bValueIsNull)2903 const char *OGRStyleSymbol::GetParamStr( OGRSTSymbolParam eParam,
2904                                          GBool &bValueIsNull )
2905 {
2906     return OGRStyleTool::GetParamStr(asStyleSymbol[eParam],
2907                                      m_pasStyleValue[eParam],
2908                                      bValueIsNull);
2909 }
2910 /************************************************************************/
2911 /*                            GetParamNum()                             */
2912 /************************************************************************/
GetParamNum(OGRSTSymbolParam eParam,GBool & bValueIsNull)2913 int OGRStyleSymbol::GetParamNum( OGRSTSymbolParam eParam, GBool &bValueIsNull )
2914 {
2915     return OGRStyleTool::GetParamNum(asStyleSymbol[eParam],
2916                                      m_pasStyleValue[eParam], bValueIsNull);
2917 }
2918 /************************************************************************/
2919 /*                            GetParamDbl()                             */
2920 /************************************************************************/
GetParamDbl(OGRSTSymbolParam eParam,GBool & bValueIsNull)2921 double OGRStyleSymbol::GetParamDbl( OGRSTSymbolParam eParam,
2922                                     GBool &bValueIsNull )
2923 {
2924     return OGRStyleTool::GetParamDbl(asStyleSymbol[eParam],
2925                                      m_pasStyleValue[eParam], bValueIsNull);
2926 }
2927 
2928 /************************************************************************/
2929 /*                            SetParamStr()                             */
2930 /************************************************************************/
SetParamStr(OGRSTSymbolParam eParam,const char * pszParamString)2931 void OGRStyleSymbol::SetParamStr( OGRSTSymbolParam eParam,
2932                                   const char *pszParamString )
2933 {
2934     OGRStyleTool::SetParamStr(asStyleSymbol[eParam], m_pasStyleValue[eParam],
2935                               pszParamString);
2936 }
2937 
2938 /************************************************************************/
2939 /*                            SetParamNum()                             */
2940 /************************************************************************/
SetParamNum(OGRSTSymbolParam eParam,int nParam)2941 void OGRStyleSymbol::SetParamNum( OGRSTSymbolParam eParam, int nParam )
2942 {
2943     OGRStyleTool::SetParamNum(asStyleSymbol[eParam],
2944                               m_pasStyleValue[eParam], nParam);
2945 }
2946 
2947 /************************************************************************/
2948 /*                            SetParamDbl()                             */
2949 /************************************************************************/
SetParamDbl(OGRSTSymbolParam eParam,double dfParam)2950 void OGRStyleSymbol::SetParamDbl( OGRSTSymbolParam eParam, double dfParam )
2951 {
2952     OGRStyleTool::SetParamDbl(asStyleSymbol[eParam],
2953                               m_pasStyleValue[eParam], dfParam);
2954 }
2955 /************************************************************************/
2956 /*                           GetStyleString()                           */
2957 /************************************************************************/
GetStyleString()2958 const char *OGRStyleSymbol::GetStyleString()
2959 {
2960     return OGRStyleTool::GetStyleString(asStyleSymbol, m_pasStyleValue,
2961                                         static_cast<int>(OGRSTSymbolLast));
2962 }
2963 
2964 /****************************************************************************/
2965 /*                      OGRStyleLabel::OGRStyleLabel()                      */
2966 /*                                                                          */
2967 /****************************************************************************/
OGRStyleLabel()2968 OGRStyleLabel::OGRStyleLabel() :
2969     OGRStyleTool(OGRSTCLabel),
2970     m_pasStyleValue( static_cast<OGRStyleValue *>(
2971         CPLCalloc(OGRSTLabelLast, sizeof(OGRStyleValue))))
2972 {
2973 }
2974 
2975 /****************************************************************************/
2976 /*                      OGRStyleLabel::~OGRStyleLabel()                     */
2977 /*                                                                          */
2978 /****************************************************************************/
~OGRStyleLabel()2979 OGRStyleLabel::~OGRStyleLabel()
2980 {
2981     for( int i = 0; i < OGRSTLabelLast; i++ )
2982     {
2983         if( m_pasStyleValue[i].pszValue != nullptr )
2984         {
2985             CPLFree(m_pasStyleValue[i].pszValue);
2986             m_pasStyleValue[i].pszValue = nullptr;
2987         }
2988     }
2989 
2990     CPLFree(m_pasStyleValue);
2991 }
2992 
2993 /************************************************************************/
2994 /*                               Parse()                                */
2995 /************************************************************************/
Parse()2996 GBool OGRStyleLabel::Parse()
2997 {
2998     return OGRStyleTool::Parse(asStyleLabel, m_pasStyleValue,
2999                                static_cast<int>(OGRSTLabelLast));
3000 }
3001 
3002 /************************************************************************/
3003 /*                            GetParamStr()                             */
3004 /************************************************************************/
GetParamStr(OGRSTLabelParam eParam,GBool & bValueIsNull)3005 const char *OGRStyleLabel::GetParamStr( OGRSTLabelParam eParam,
3006                                         GBool &bValueIsNull )
3007 {
3008     return OGRStyleTool::GetParamStr(asStyleLabel[eParam],
3009                                      m_pasStyleValue[eParam],
3010                                      bValueIsNull);
3011 }
3012 /************************************************************************/
3013 /*                            GetParamNum()                             */
3014 /************************************************************************/
GetParamNum(OGRSTLabelParam eParam,GBool & bValueIsNull)3015 int OGRStyleLabel::GetParamNum( OGRSTLabelParam eParam,
3016                                 GBool &bValueIsNull )
3017 {
3018     return OGRStyleTool::GetParamNum(asStyleLabel[eParam],
3019                                      m_pasStyleValue[eParam], bValueIsNull);
3020 }
3021 /************************************************************************/
3022 /*                            GetParamDbl()                             */
3023 /************************************************************************/
GetParamDbl(OGRSTLabelParam eParam,GBool & bValueIsNull)3024 double OGRStyleLabel::GetParamDbl( OGRSTLabelParam eParam,
3025                                    GBool &bValueIsNull )
3026 {
3027     return OGRStyleTool::GetParamDbl(asStyleLabel[eParam],
3028                                      m_pasStyleValue[eParam], bValueIsNull);
3029 }
3030 /************************************************************************/
3031 /*                            SetParamStr()                             */
3032 /************************************************************************/
SetParamStr(OGRSTLabelParam eParam,const char * pszParamString)3033 void OGRStyleLabel::SetParamStr( OGRSTLabelParam eParam,
3034                                  const char *pszParamString )
3035 {
3036     OGRStyleTool::SetParamStr(asStyleLabel[eParam], m_pasStyleValue[eParam],
3037                               pszParamString);
3038 }
3039 /************************************************************************/
3040 /*                            SetParamNum()                             */
3041 /************************************************************************/
SetParamNum(OGRSTLabelParam eParam,int nParam)3042 void OGRStyleLabel::SetParamNum( OGRSTLabelParam eParam, int nParam )
3043 {
3044     OGRStyleTool::SetParamNum(asStyleLabel[eParam],
3045                               m_pasStyleValue[eParam], nParam);
3046 }
3047 
3048 /************************************************************************/
3049 /*                            SetParamDbl()                             */
3050 /************************************************************************/
SetParamDbl(OGRSTLabelParam eParam,double dfParam)3051 void OGRStyleLabel::SetParamDbl( OGRSTLabelParam eParam, double dfParam )
3052 {
3053     OGRStyleTool::SetParamDbl(asStyleLabel[eParam],
3054                               m_pasStyleValue[eParam], dfParam);
3055 }
3056 /************************************************************************/
3057 /*                           GetStyleString()                           */
3058 /************************************************************************/
GetStyleString()3059 const char *OGRStyleLabel::GetStyleString()
3060 {
3061     return OGRStyleTool::GetStyleString(asStyleLabel, m_pasStyleValue,
3062                                         static_cast<int>(OGRSTLabelLast));
3063 }
3064 //! @endcond
3065