LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/dxf - ogr_autocad_services.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 203 213 95.3 %
Date: 2024-11-21 22:18:42 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  DXF and DWG Translators
       4             :  * Purpose:  Implements various generic services shared between autocad related
       5             :  *           drivers.
       6             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2011, Frank Warmerdam <warmerdam@pobox.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "ogr_autocad_services.h"
      15             : #include "cpl_conv.h"
      16             : 
      17             : /************************************************************************/
      18             : /*                           ACTextUnescape()                           */
      19             : /*                                                                      */
      20             : /*      Unexcape DXF/DWG style escape sequences such as %%d for the     */
      21             : /*      degree sign, and do the recoding to UTF8.  Set bIsMText to      */
      22             : /*      true to translate MTEXT-specific sequences like \P and \~.      */
      23             : /************************************************************************/
      24             : 
      25         147 : CPLString ACTextUnescape(const char *pszRawInput, const char *pszEncoding,
      26             :                          bool bIsMText)
      27             : 
      28             : {
      29         294 :     CPLString osResult;
      30         294 :     CPLString osInput = pszRawInput;
      31             : 
      32             :     /* -------------------------------------------------------------------- */
      33             :     /*      Translate text from Win-1252 to UTF8.  We approximate this      */
      34             :     /*      by treating Win-1252 as Latin-1.  Note that we likely ought     */
      35             :     /*      to be consulting the $DWGCODEPAGE header variable which         */
      36             :     /*      defaults to ANSI_1252 if not set.                               */
      37             :     /* -------------------------------------------------------------------- */
      38         147 :     osInput.Recode(pszEncoding, CPL_ENC_UTF8);
      39             : 
      40         147 :     const char *pszInput = osInput.c_str();
      41             : 
      42             :     /* -------------------------------------------------------------------- */
      43             :     /*      Now translate low-level escape sequences.  They are all plain   */
      44             :     /*      ASCII characters and won't have been affected by the UTF8       */
      45             :     /*      recoding.                                                       */
      46             :     /* -------------------------------------------------------------------- */
      47        3060 :     while (*pszInput != '\0')
      48             :     {
      49        2913 :         if (pszInput[0] == '^' && pszInput[1] != '\0')
      50             :         {
      51           5 :             if (pszInput[1] == ' ')
      52           3 :                 osResult += '^';
      53             :             else
      54           4 :                 osResult += static_cast<char>(CPLToupper(
      55           2 :                                 static_cast<unsigned char>(pszInput[1]))) ^
      56           2 :                             0x40;
      57           5 :             pszInput++;
      58             :         }
      59        2908 :         else if (STARTS_WITH_CI(pszInput, "%%c") ||
      60        2908 :                  STARTS_WITH_CI(pszInput, "%%d") ||
      61        2908 :                  STARTS_WITH_CI(pszInput, "%%p"))
      62             :         {
      63             :             wchar_t anWCharString[2];
      64             : 
      65           6 :             anWCharString[1] = 0;
      66             : 
      67             :             // These are special symbol representations for AutoCAD.
      68           6 :             if (STARTS_WITH_CI(pszInput, "%%c"))
      69           0 :                 anWCharString[0] =
      70             :                     0x2300;  // diameter (0x00F8 is a good approx)
      71           6 :             else if (STARTS_WITH_CI(pszInput, "%%d"))
      72           0 :                 anWCharString[0] = 0x00B0;  // degree
      73           6 :             else if (STARTS_WITH_CI(pszInput, "%%p"))
      74           6 :                 anWCharString[0] = 0x00B1;  // plus/minus
      75             : 
      76             :             char *pszUTF8Char =
      77           6 :                 CPLRecodeFromWChar(anWCharString, CPL_ENC_UCS2, CPL_ENC_UTF8);
      78             : 
      79           6 :             osResult += pszUTF8Char;
      80           6 :             CPLFree(pszUTF8Char);
      81             : 
      82           6 :             pszInput += 2;
      83             :         }
      84        2902 :         else if (!bIsMText && (STARTS_WITH_CI(pszInput, "%%u") ||
      85         512 :                                STARTS_WITH_CI(pszInput, "%%o") ||
      86         512 :                                STARTS_WITH_CI(pszInput, "%%k")))
      87             :         {
      88             :             // Underline, overline, and strikethrough markers.
      89             :             // These have no effect in MTEXT
      90           7 :             pszInput += 2;
      91             :         }
      92             :         else
      93             :         {
      94        2895 :             osResult += pszInput[0];
      95             :         }
      96             : 
      97        2913 :         pszInput++;
      98             :     }
      99             : 
     100         147 :     if (!bIsMText)
     101          62 :         return osResult;
     102             : 
     103             :     /* -------------------------------------------------------------------- */
     104             :     /*      If this is MTEXT, or something similar (e.g. DIMENSION text),   */
     105             :     /*      do a second pass to strip additional MTEXT format codes.        */
     106             :     /* -------------------------------------------------------------------- */
     107          85 :     pszInput = osResult.c_str();
     108         170 :     CPLString osMtextResult;
     109             : 
     110        2336 :     while (*pszInput != '\0')
     111             :     {
     112        2251 :         if (pszInput[0] == '\\' && pszInput[1] == 'P')
     113             :         {
     114          19 :             osMtextResult += '\n';
     115          19 :             pszInput++;
     116             :         }
     117        2232 :         else if (pszInput[0] == '\\' && pszInput[1] == '~')
     118             :         {
     119          16 :             osMtextResult += ' ';
     120          16 :             pszInput++;
     121             :         }
     122          23 :         else if (pszInput[0] == '\\' && pszInput[1] == 'U' &&
     123        2239 :                  pszInput[2] == '+' && CPLStrnlen(pszInput, 7) >= 7)
     124             :         {
     125          10 :             CPLString osHex;
     126          10 :             unsigned int iChar = 0;
     127             : 
     128          10 :             osHex.assign(pszInput + 3, 4);
     129          10 :             sscanf(osHex.c_str(), "%x", &iChar);
     130             : 
     131             :             wchar_t anWCharString[2];
     132          10 :             anWCharString[0] = (wchar_t)iChar;
     133          10 :             anWCharString[1] = 0;
     134             : 
     135             :             char *pszUTF8Char =
     136          10 :                 CPLRecodeFromWChar(anWCharString, CPL_ENC_UCS2, CPL_ENC_UTF8);
     137             : 
     138          10 :             osMtextResult += pszUTF8Char;
     139          10 :             CPLFree(pszUTF8Char);
     140             : 
     141          10 :             pszInput += 6;
     142             :         }
     143        2206 :         else if (pszInput[0] == '{' || pszInput[0] == '}')
     144             :         {
     145             :             // Skip braces, which are used for grouping
     146             :         }
     147        2203 :         else if (pszInput[0] == '\\' &&
     148          13 :                  strchr("WTAHFfCcQp", pszInput[1]) != nullptr)
     149             :         {
     150             :             // eg. \W1.073172x;\T1.099;Bonneuil de Verrines
     151             :             // See data/dwg/EP/42002.dwg
     152             :             // These are all inline formatting codes which take an argument
     153             :             // up to the first semicolon (\W for width, \f for font, etc)
     154             : 
     155          30 :             while (*pszInput != ';' && *pszInput != '\0')
     156          24 :                 pszInput++;
     157           6 :             if (*pszInput == '\0')
     158           0 :                 break;
     159             :         }
     160        2197 :         else if (pszInput[0] == '\\' &&
     161           7 :                  strchr("KkLlOo", pszInput[1]) != nullptr)
     162             :         {
     163             :             // Inline formatting codes that don't take an argument
     164             : 
     165           3 :             pszInput++;
     166             :         }
     167        2194 :         else if (pszInput[0] == '\\' && pszInput[1] == 'S')
     168             :         {
     169             :             // Stacked text. Normal escapes don't work inside a stack
     170             : 
     171           1 :             pszInput += 2;
     172          18 :             while (*pszInput != ';' && *pszInput != '\0')
     173             :             {
     174          17 :                 if (pszInput[0] == '\\' &&
     175           4 :                     strchr("^/#~", pszInput[1]) != nullptr)
     176             :                 {
     177           4 :                     osMtextResult += pszInput[1];
     178           4 :                     pszInput++;
     179           4 :                     if (pszInput[0] == '\0')
     180           0 :                         break;
     181             :                 }
     182          13 :                 else if (strchr("^/#~", pszInput[0]) == nullptr)
     183             :                 {
     184          12 :                     osMtextResult += pszInput[0];
     185             :                 }
     186          17 :                 pszInput++;
     187             :             }
     188           1 :             if (pszInput[0] == ';')
     189           1 :                 pszInput++;
     190           1 :             if (pszInput[0] == '\0')
     191           0 :                 break;
     192             :         }
     193        2193 :         else if (pszInput[0] == '\\' && strchr("\\{}", pszInput[1]) != nullptr)
     194             :         {
     195             :             // MTEXT character escapes
     196             : 
     197           3 :             osMtextResult += pszInput[1];
     198           3 :             pszInput++;
     199           3 :             if (pszInput[0] == '\0')
     200           0 :                 break;
     201             :         }
     202             :         else
     203             :         {
     204        2190 :             osMtextResult += *pszInput;
     205             :         }
     206             : 
     207        2251 :         pszInput++;
     208             :     }
     209             : 
     210          85 :     return osMtextResult;
     211             : }
     212             : 
     213             : /************************************************************************/
     214             : /*                          ACGetColorTable()                           */
     215             : /************************************************************************/
     216             : 
     217        1260 : const unsigned char *ACGetColorTable()
     218             : 
     219             : {
     220             :     static const unsigned char abyDXFColors[768] = {
     221             :         0,   0,   0,    // 0
     222             :         255, 0,   0,    // 1
     223             :         255, 255, 0,    // 2
     224             :         0,   255, 0,    // 3
     225             :         0,   255, 255,  // 4
     226             :         0,   0,   255,  // 5
     227             :         255, 0,   255,  // 6
     228             :         0,   0,   0,    // 7 - it should be white, but that plots poorly
     229             :         127, 127, 127,  // 8
     230             :         191, 191, 191,  // 9
     231             :         255, 0,   0,    // 10
     232             :         255, 127, 127,  // 11
     233             :         165, 0,   0,    // 12
     234             :         165, 82,  82,   // 13
     235             :         127, 0,   0,    // 14
     236             :         127, 63,  63,   // 15
     237             :         76,  0,   0,    // 16
     238             :         76,  38,  38,   // 17
     239             :         38,  0,   0,    // 18
     240             :         38,  19,  19,   // 19
     241             :         255, 63,  0,    // 20
     242             :         255, 159, 127,  // 21
     243             :         165, 41,  0,    // 22
     244             :         165, 103, 82,   // 23
     245             :         127, 31,  0,    // 24
     246             :         127, 79,  63,   // 25
     247             :         76,  19,  0,    // 26
     248             :         76,  47,  38,   // 27
     249             :         38,  9,   0,    // 28
     250             :         38,  23,  19,   // 29
     251             :         255, 127, 0,    // 30
     252             :         255, 191, 127,  // 31
     253             :         165, 82,  0,    // 32
     254             :         165, 124, 82,   // 33
     255             :         127, 63,  0,    // 34
     256             :         127, 95,  63,   // 35
     257             :         76,  38,  0,    // 36
     258             :         76,  57,  38,   // 37
     259             :         38,  19,  0,    // 38
     260             :         38,  28,  19,   // 39
     261             :         255, 191, 0,    // 40
     262             :         255, 223, 127,  // 41
     263             :         165, 124, 0,    // 42
     264             :         165, 145, 82,   // 43
     265             :         127, 95,  0,    // 44
     266             :         127, 111, 63,   // 45
     267             :         76,  57,  0,    // 46
     268             :         76,  66,  38,   // 47
     269             :         38,  28,  0,    // 48
     270             :         38,  33,  19,   // 49
     271             :         255, 255, 0,    // 50
     272             :         255, 255, 127,  // 51
     273             :         165, 165, 0,    // 52
     274             :         165, 165, 82,   // 53
     275             :         127, 127, 0,    // 54
     276             :         127, 127, 63,   // 55
     277             :         76,  76,  0,    // 56
     278             :         76,  76,  38,   // 57
     279             :         38,  38,  0,    // 58
     280             :         38,  38,  19,   // 59
     281             :         191, 255, 0,    // 60
     282             :         223, 255, 127,  // 61
     283             :         124, 165, 0,    // 62
     284             :         145, 165, 82,   // 63
     285             :         95,  127, 0,    // 64
     286             :         111, 127, 63,   // 65
     287             :         57,  76,  0,    // 66
     288             :         66,  76,  38,   // 67
     289             :         28,  38,  0,    // 68
     290             :         33,  38,  19,   // 69
     291             :         127, 255, 0,    // 70
     292             :         191, 255, 127,  // 71
     293             :         82,  165, 0,    // 72
     294             :         124, 165, 82,   // 73
     295             :         63,  127, 0,    // 74
     296             :         95,  127, 63,   // 75
     297             :         38,  76,  0,    // 76
     298             :         57,  76,  38,   // 77
     299             :         19,  38,  0,    // 78
     300             :         28,  38,  19,   // 79
     301             :         63,  255, 0,    // 80
     302             :         159, 255, 127,  // 81
     303             :         41,  165, 0,    // 82
     304             :         103, 165, 82,   // 83
     305             :         31,  127, 0,    // 84
     306             :         79,  127, 63,   // 85
     307             :         19,  76,  0,    // 86
     308             :         47,  76,  38,   // 87
     309             :         9,   38,  0,    // 88
     310             :         23,  38,  19,   // 89
     311             :         0,   255, 0,    // 90
     312             :         127, 255, 127,  // 91
     313             :         0,   165, 0,    // 92
     314             :         82,  165, 82,   // 93
     315             :         0,   127, 0,    // 94
     316             :         63,  127, 63,   // 95
     317             :         0,   76,  0,    // 96
     318             :         38,  76,  38,   // 97
     319             :         0,   38,  0,    // 98
     320             :         19,  38,  19,   // 99
     321             :         0,   255, 63,   // 100
     322             :         127, 255, 159,  // 101
     323             :         0,   165, 41,   // 102
     324             :         82,  165, 103,  // 103
     325             :         0,   127, 31,   // 104
     326             :         63,  127, 79,   // 105
     327             :         0,   76,  19,   // 106
     328             :         38,  76,  47,   // 107
     329             :         0,   38,  9,    // 108
     330             :         19,  38,  23,   // 109
     331             :         0,   255, 127,  // 110
     332             :         127, 255, 191,  // 111
     333             :         0,   165, 82,   // 112
     334             :         82,  165, 124,  // 113
     335             :         0,   127, 63,   // 114
     336             :         63,  127, 95,   // 115
     337             :         0,   76,  38,   // 116
     338             :         38,  76,  57,   // 117
     339             :         0,   38,  19,   // 118
     340             :         19,  38,  28,   // 119
     341             :         0,   255, 191,  // 120
     342             :         127, 255, 223,  // 121
     343             :         0,   165, 124,  // 122
     344             :         82,  165, 145,  // 123
     345             :         0,   127, 95,   // 124
     346             :         63,  127, 111,  // 125
     347             :         0,   76,  57,   // 126
     348             :         38,  76,  66,   // 127
     349             :         0,   38,  28,   // 128
     350             :         19,  38,  33,   // 129
     351             :         0,   255, 255,  // 130
     352             :         127, 255, 255,  // 131
     353             :         0,   165, 165,  // 132
     354             :         82,  165, 165,  // 133
     355             :         0,   127, 127,  // 134
     356             :         63,  127, 127,  // 135
     357             :         0,   76,  76,   // 136
     358             :         38,  76,  76,   // 137
     359             :         0,   38,  38,   // 138
     360             :         19,  38,  38,   // 139
     361             :         0,   191, 255,  // 140
     362             :         127, 223, 255,  // 141
     363             :         0,   124, 165,  // 142
     364             :         82,  145, 165,  // 143
     365             :         0,   95,  127,  // 144
     366             :         63,  111, 127,  // 145
     367             :         0,   57,  76,   // 146
     368             :         38,  66,  76,   // 147
     369             :         0,   28,  38,   // 148
     370             :         19,  33,  38,   // 149
     371             :         0,   127, 255,  // 150
     372             :         127, 191, 255,  // 151
     373             :         0,   82,  165,  // 152
     374             :         82,  124, 165,  // 153
     375             :         0,   63,  127,  // 154
     376             :         63,  95,  127,  // 155
     377             :         0,   38,  76,   // 156
     378             :         38,  57,  76,   // 157
     379             :         0,   19,  38,   // 158
     380             :         19,  28,  38,   // 159
     381             :         0,   63,  255,  // 160
     382             :         127, 159, 255,  // 161
     383             :         0,   41,  165,  // 162
     384             :         82,  103, 165,  // 163
     385             :         0,   31,  127,  // 164
     386             :         63,  79,  127,  // 165
     387             :         0,   19,  76,   // 166
     388             :         38,  47,  76,   // 167
     389             :         0,   9,   38,   // 168
     390             :         19,  23,  38,   // 169
     391             :         0,   0,   255,  // 170
     392             :         127, 127, 255,  // 171
     393             :         0,   0,   165,  // 172
     394             :         82,  82,  165,  // 173
     395             :         0,   0,   127,  // 174
     396             :         63,  63,  127,  // 175
     397             :         0,   0,   76,   // 176
     398             :         38,  38,  76,   // 177
     399             :         0,   0,   38,   // 178
     400             :         19,  19,  38,   // 179
     401             :         63,  0,   255,  // 180
     402             :         159, 127, 255,  // 181
     403             :         41,  0,   165,  // 182
     404             :         103, 82,  165,  // 183
     405             :         31,  0,   127,  // 184
     406             :         79,  63,  127,  // 185
     407             :         19,  0,   76,   // 186
     408             :         47,  38,  76,   // 187
     409             :         9,   0,   38,   // 188
     410             :         23,  19,  38,   // 189
     411             :         127, 0,   255,  // 190
     412             :         191, 127, 255,  // 191
     413             :         82,  0,   165,  // 192
     414             :         124, 82,  165,  // 193
     415             :         63,  0,   127,  // 194
     416             :         95,  63,  127,  // 195
     417             :         38,  0,   76,   // 196
     418             :         57,  38,  76,   // 197
     419             :         19,  0,   38,   // 198
     420             :         28,  19,  38,   // 199
     421             :         191, 0,   255,  // 200
     422             :         223, 127, 255,  // 201
     423             :         124, 0,   165,  // 202
     424             :         145, 82,  165,  // 203
     425             :         95,  0,   127,  // 204
     426             :         111, 63,  127,  // 205
     427             :         57,  0,   76,   // 206
     428             :         66,  38,  76,   // 207
     429             :         28,  0,   38,   // 208
     430             :         33,  19,  38,   // 209
     431             :         255, 0,   255,  // 210
     432             :         255, 127, 255,  // 211
     433             :         165, 0,   165,  // 212
     434             :         165, 82,  165,  // 213
     435             :         127, 0,   127,  // 214
     436             :         127, 63,  127,  // 215
     437             :         76,  0,   76,   // 216
     438             :         76,  38,  76,   // 217
     439             :         38,  0,   38,   // 218
     440             :         38,  19,  38,   // 219
     441             :         255, 0,   191,  // 220
     442             :         255, 127, 223,  // 221
     443             :         165, 0,   124,  // 222
     444             :         165, 82,  145,  // 223
     445             :         127, 0,   95,   // 224
     446             :         127, 63,  111,  // 225
     447             :         76,  0,   57,   // 226
     448             :         76,  38,  66,   // 227
     449             :         38,  0,   28,   // 228
     450             :         38,  19,  33,   // 229
     451             :         255, 0,   127,  // 230
     452             :         255, 127, 191,  // 231
     453             :         165, 0,   82,   // 232
     454             :         165, 82,  124,  // 233
     455             :         127, 0,   63,   // 234
     456             :         127, 63,  95,   // 235
     457             :         76,  0,   38,   // 236
     458             :         76,  38,  57,   // 237
     459             :         38,  0,   19,   // 238
     460             :         38,  19,  28,   // 239
     461             :         255, 0,   63,   // 240
     462             :         255, 127, 159,  // 241
     463             :         165, 0,   41,   // 242
     464             :         165, 82,  103,  // 243
     465             :         127, 0,   31,   // 244
     466             :         127, 63,  79,   // 245
     467             :         76,  0,   19,   // 246
     468             :         76,  38,  47,   // 247
     469             :         38,  0,   9,    // 248
     470             :         38,  19,  23,   // 249
     471             :         84,  84,  84,   // 250
     472             :         118, 118, 118,  // 251
     473             :         152, 152, 152,  // 252
     474             :         186, 186, 186,  // 253
     475             :         220, 220, 220,  // 254
     476             :         255, 255, 255   // 255
     477             :     };
     478             : 
     479        1260 :     return abyDXFColors;
     480             : }
     481             : 
     482             : /************************************************************************/
     483             : /*                       ACGetKnownDimStyleCodes()                      */
     484             : /*                                                                      */
     485             : /*      Gets a list of the DIMSTYLE codes that we care about. Array     */
     486             : /*      terminates with a zero value.                                   */
     487             : /************************************************************************/
     488             : 
     489         182 : const int *ACGetKnownDimStyleCodes()
     490             : {
     491             :     static const int aiKnownCodes[] = {40,  41,  42,  44,  75,  76,  77,
     492             :                                        140, 147, 176, 178, 271, 341, 0};
     493             : 
     494         182 :     return aiKnownCodes;
     495             : }
     496             : 
     497             : /************************************************************************/
     498             : /*                      ACGetDimStylePropertyName()                     */
     499             : /************************************************************************/
     500             : 
     501        3751 : const char *ACGetDimStylePropertyName(const int iDimStyleCode)
     502             : 
     503             : {
     504             :     // We are only interested in properties required by the DIMENSION
     505             :     // and LEADER code. Return NULL for other properties.
     506        3751 :     switch (iDimStyleCode)
     507             :     {
     508         207 :         case 40:
     509         207 :             return "DIMSCALE";
     510         222 :         case 41:
     511         222 :             return "DIMASZ";
     512         203 :         case 42:
     513         203 :             return "DIMEXO";
     514         203 :         case 44:
     515         203 :             return "DIMEXE";
     516         188 :         case 75:
     517         188 :             return "DIMSE1";
     518         188 :         case 76:
     519         188 :             return "DIMSE2";
     520         205 :         case 77:
     521         205 :             return "DIMTAD";
     522         216 :         case 140:
     523         216 :             return "DIMTXT";
     524         201 :         case 147:
     525         201 :             return "DIMGAP";
     526         204 :         case 176:
     527         204 :             return "DIMCLRD";
     528         188 :         case 178:
     529         188 :             return "DIMCLRT";
     530         210 :         case 271:
     531         210 :             return "DIMDEC";
     532         190 :         case 341:
     533         190 :             return "DIMLDRBLK";
     534        1126 :         default:
     535        1126 :             return nullptr;
     536             :     }
     537             : }
     538             : 
     539             : /************************************************************************/
     540             : /*                    ACGetDimStylePropertyDefault()                    */
     541             : /************************************************************************/
     542             : 
     543        2366 : const char *ACGetDimStylePropertyDefault(const int iDimStyleCode)
     544             : 
     545             : {
     546             :     // We are only interested in properties required by the DIMENSION
     547             :     // and LEADER code. Return "0" for other, unknown properties.
     548             :     // These defaults were obtained from the Express\defaults.scr file
     549             :     // in an AutoCAD installation.
     550        2366 :     switch (iDimStyleCode)
     551             :     {
     552         182 :         case 40:
     553         182 :             return "1.0";
     554         182 :         case 41:
     555         182 :             return "0.18";
     556         182 :         case 42:
     557         182 :             return "0.0625";
     558         182 :         case 44:
     559         182 :             return "0.18";
     560         182 :         case 75:
     561         182 :             return "0";
     562         182 :         case 76:
     563         182 :             return "0";
     564         182 :         case 77:
     565         182 :             return "0";
     566         182 :         case 140:
     567         182 :             return "0.18";
     568         182 :         case 147:
     569         182 :             return "0.09";
     570         182 :         case 176:
     571         182 :             return "0";
     572         182 :         case 178:
     573         182 :             return "0";
     574         182 :         case 271:
     575         182 :             return "4";
     576         182 :         case 341:
     577         182 :             return "";
     578           0 :         default:
     579           0 :             return "0";
     580             :     }
     581             : }
     582             : 
     583             : /************************************************************************/
     584             : /*                            ACAdjustText()                            */
     585             : /*                                                                      */
     586             : /*      Rotate and scale text features by the designated amount by      */
     587             : /*      adjusting the style string.                                     */
     588             : /************************************************************************/
     589             : 
     590         568 : void ACAdjustText(const double dfAngle, const double dfScaleX,
     591             :                   const double dfScaleY, OGRFeature *const poFeature)
     592             : 
     593             : {
     594             :     /* -------------------------------------------------------------------- */
     595             :     /*      We only try to alter text elements (LABEL styles).              */
     596             :     /* -------------------------------------------------------------------- */
     597         568 :     if (poFeature->GetStyleString() == nullptr)
     598         504 :         return;
     599             : 
     600         568 :     CPLString osOldStyle = poFeature->GetStyleString();
     601             : 
     602         568 :     if (!STARTS_WITH(osOldStyle, "LABEL("))
     603         504 :         return;
     604             : 
     605             :     // Split the style string up into its parts
     606          64 :     osOldStyle.erase(0, 6);
     607          64 :     osOldStyle.erase(osOldStyle.size() - 1);
     608          64 :     char **papszTokens = CSLTokenizeString2(
     609             :         osOldStyle, ",",
     610             :         CSLT_HONOURSTRINGS | CSLT_PRESERVEQUOTES | CSLT_PRESERVEESCAPES);
     611             : 
     612             :     /* -------------------------------------------------------------------- */
     613             :     /*      Update the text angle.                                          */
     614             :     /* -------------------------------------------------------------------- */
     615             :     char szBuffer[64];
     616             : 
     617          64 :     if (dfAngle != 0.0)
     618             :     {
     619           4 :         double dfOldAngle = 0.0;
     620             : 
     621           4 :         const char *pszAngle = CSLFetchNameValue(papszTokens, "a");
     622           4 :         if (pszAngle)
     623           0 :             dfOldAngle = CPLAtof(pszAngle);
     624             : 
     625           4 :         CPLsnprintf(szBuffer, sizeof(szBuffer), "%.3g", dfOldAngle + dfAngle);
     626           4 :         papszTokens = CSLSetNameValue(papszTokens, "a", szBuffer);
     627             :     }
     628             : 
     629             :     /* -------------------------------------------------------------------- */
     630             :     /*      Update the text width and height.                               */
     631             :     /* -------------------------------------------------------------------- */
     632             : 
     633          64 :     if (dfScaleY != 1.0)
     634             :     {
     635           4 :         const char *pszHeight = CSLFetchNameValue(papszTokens, "s");
     636           4 :         if (pszHeight)
     637             :         {
     638           4 :             const double dfOldHeight = CPLAtof(pszHeight);
     639             : 
     640           4 :             CPLsnprintf(szBuffer, sizeof(szBuffer), "%.3gg",
     641             :                         dfOldHeight * dfScaleY);
     642           4 :             papszTokens = CSLSetNameValue(papszTokens, "s", szBuffer);
     643             :         }
     644             :     }
     645             : 
     646          64 :     if (dfScaleX != dfScaleY && dfScaleY != 0.0)
     647             :     {
     648           4 :         const double dfWidthFactor = dfScaleX / dfScaleY;
     649           4 :         double dfOldWidth = 100.0;
     650             : 
     651           4 :         const char *pszWidth = CSLFetchNameValue(papszTokens, "w");
     652           4 :         if (pszWidth)
     653           3 :             dfOldWidth = CPLAtof(pszWidth);
     654             : 
     655           4 :         CPLsnprintf(szBuffer, sizeof(szBuffer), "%.4g",
     656             :                     dfOldWidth * dfWidthFactor);
     657           4 :         papszTokens = CSLSetNameValue(papszTokens, "w", szBuffer);
     658             :     }
     659             : 
     660             :     /* -------------------------------------------------------------------- */
     661             :     /*      Update the text offsets.                                        */
     662             :     /* -------------------------------------------------------------------- */
     663             : 
     664          64 :     if (dfScaleX != 1.0 || dfScaleY != 1.0 || dfAngle != 0.0)
     665             :     {
     666           6 :         double dfOldDx = 0.0;
     667           6 :         double dfOldDy = 0.0;
     668             : 
     669           6 :         const char *pszDx = CSLFetchNameValue(papszTokens, "dx");
     670           6 :         if (pszDx)
     671           2 :             dfOldDx = CPLAtof(pszDx);
     672           6 :         const char *pszDy = CSLFetchNameValue(papszTokens, "dy");
     673           6 :         if (pszDy)
     674           0 :             dfOldDy = CPLAtof(pszDy);
     675             : 
     676           6 :         if (dfOldDx != 0.0 || dfOldDy != 0.0)
     677             :         {
     678           2 :             const double dfAngleRadians = dfAngle * M_PI / 180.0;
     679             : 
     680           2 :             CPLsnprintf(szBuffer, sizeof(szBuffer), "%.6gg",
     681           2 :                         dfScaleX * dfOldDx * cos(dfAngleRadians) +
     682           2 :                             dfScaleY * dfOldDy * -sin(dfAngleRadians));
     683           2 :             papszTokens = CSLSetNameValue(papszTokens, "dx", szBuffer);
     684             : 
     685           2 :             CPLsnprintf(szBuffer, sizeof(szBuffer), "%.6gg",
     686           2 :                         dfScaleX * dfOldDx * sin(dfAngleRadians) +
     687           2 :                             dfScaleY * dfOldDy * cos(dfAngleRadians));
     688           2 :             papszTokens = CSLSetNameValue(papszTokens, "dy", szBuffer);
     689             :         }
     690             :     }
     691             : 
     692          64 :     CSLSetNameValueSeparator(papszTokens, ":");
     693             : 
     694         128 :     CPLString osNewStyle = "LABEL(";
     695          64 :     int iIndex = 0;
     696         497 :     while (papszTokens[iIndex])
     697             :     {
     698         433 :         if (iIndex > 0)
     699         369 :             osNewStyle += ",";
     700         433 :         osNewStyle += papszTokens[iIndex++];
     701             :     }
     702          64 :     osNewStyle += ")";
     703             : 
     704          64 :     poFeature->SetStyleString(osNewStyle);
     705             : 
     706          64 :     CSLDestroy(papszTokens);
     707             : }

Generated by: LCOV version 1.14