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