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 : }
|