LCOV - code coverage report
Current view: top level - ogr - ogrfeaturestyle.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 605 973 62.2 %
Date: 2024-11-21 22:18:42 Functions: 96 123 78.0 %

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

Generated by: LCOV version 1.14