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

Generated by: LCOV version 1.14