1 : /******************************************************************************
2 : * $Id$
3 : *
4 : * Project: DXF and DWG Translators
5 : * Purpose: Implements various generic services shared between autocad related
6 : * drivers.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2011, Frank Warmerdam <warmerdam@pobox.com>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "ogr_autocad_services.h"
32 : #include "cpl_conv.h"
33 :
34 : CPL_CVSID("$Id: ogrdwglayer.cpp 22008 2011-03-22 19:45:20Z warmerdam $");
35 :
36 : #ifndef PI
37 : #define PI 3.14159265358979323846
38 : #endif
39 :
40 : /************************************************************************/
41 : /* ACTextUnescape() */
42 : /* */
43 : /* Unexcape DXF/DWG style escape sequences such as \P for newline */
44 : /* and \~ for space, and do the recoding to UTF8. */
45 : /************************************************************************/
46 :
47 604 : CPLString ACTextUnescape( const char *pszRawInput, const char *pszEncoding )
48 :
49 : {
50 604 : CPLString osResult;
51 604 : CPLString osInput = pszRawInput;
52 :
53 : /* -------------------------------------------------------------------- */
54 : /* Translate text from Win-1252 to UTF8. We approximate this */
55 : /* by treating Win-1252 as Latin-1. Note that we likely ought */
56 : /* to be consulting the $DWGCODEPAGE header variable which */
57 : /* defaults to ANSI_1252 if not set. */
58 : /* -------------------------------------------------------------------- */
59 604 : osInput.Recode( pszEncoding, CPL_ENC_UTF8 );
60 :
61 604 : const char *pszInput = osInput.c_str();
62 :
63 : /* -------------------------------------------------------------------- */
64 : /* Now translate escape sequences. They are all plain ascii */
65 : /* characters and won't have been affected by the UTF8 */
66 : /* recoding. */
67 : /* -------------------------------------------------------------------- */
68 4348 : while( *pszInput != '\0' )
69 : {
70 3144 : if( pszInput[0] == '\\' && pszInput[1] == 'P' )
71 : {
72 4 : osResult += '\n';
73 4 : pszInput++;
74 : }
75 3140 : else if( pszInput[0] == '\\' && pszInput[1] == '~' )
76 : {
77 4 : osResult += ' ';
78 4 : pszInput++;
79 : }
80 3140 : else if( pszInput[0] == '\\' && pszInput[1] == 'U'
81 4 : && pszInput[2] == '+' )
82 : {
83 4 : CPLString osHex;
84 : int iChar;
85 :
86 4 : osHex.assign( pszInput+3, 4 );
87 4 : sscanf( osHex.c_str(), "%x", &iChar );
88 :
89 : wchar_t anWCharString[2];
90 4 : anWCharString[0] = (wchar_t) iChar;
91 4 : anWCharString[1] = 0;
92 :
93 : char *pszUTF8Char = CPLRecodeFromWChar( anWCharString,
94 : CPL_ENC_UCS2,
95 4 : CPL_ENC_UTF8 );
96 :
97 4 : osResult += pszUTF8Char;
98 4 : CPLFree( pszUTF8Char );
99 :
100 4 : pszInput += 6;
101 : }
102 3128 : else if( pszInput[0] == '\\'
103 0 : && (pszInput[1] == 'W'
104 0 : || pszInput[1] == 'T'
105 0 : || pszInput[1] == 'A' ) )
106 : {
107 : // eg. \W1.073172x;\T1.099;Bonneuil de Verrines
108 : // See data/dwg/EP/42002.dwg
109 : // Not sure what \W and \T do, but we skip them.
110 : // According to qcad rs_text.cpp, \A values are vertical
111 : // alignment, 0=bottom, 1=mid, 2=top but we ignore for now.
112 :
113 0 : while( *pszInput != ';' && *pszInput != '\0' )
114 0 : pszInput++;
115 : }
116 3128 : else if( pszInput[0] == '\\' && pszInput[1] == '\\' )
117 : {
118 0 : osResult += '\\';
119 0 : pszInput++;
120 : }
121 3128 : else if( EQUALN(pszInput,"%%c",3)
122 : || EQUALN(pszInput,"%%d",3)
123 : || EQUALN(pszInput,"%%p",3) )
124 : {
125 : wchar_t anWCharString[2];
126 :
127 0 : anWCharString[1] = 0;
128 :
129 : // These are especial symbol representations for autocad.
130 0 : if( EQUALN(pszInput,"%%c",3) )
131 0 : anWCharString[0] = 0x2300; // diameter (0x00F8 is a good approx)
132 0 : else if( EQUALN(pszInput,"%%d",3) )
133 0 : anWCharString[0] = 0x00B0; // degree
134 0 : else if( EQUALN(pszInput,"%%p",3) )
135 0 : anWCharString[0] = 0x00B1; // plus/minus
136 :
137 : char *pszUTF8Char = CPLRecodeFromWChar( anWCharString,
138 : CPL_ENC_UCS2,
139 0 : CPL_ENC_UTF8 );
140 :
141 0 : osResult += pszUTF8Char;
142 0 : CPLFree( pszUTF8Char );
143 :
144 0 : pszInput += 2;
145 : }
146 : else
147 3128 : osResult += *pszInput;
148 :
149 3140 : pszInput++;
150 : }
151 :
152 604 : return osResult;
153 : }
154 :
155 : /************************************************************************/
156 : /* ACGetColorTable() */
157 : /************************************************************************/
158 :
159 170 : const unsigned char *ACGetColorTable()
160 :
161 : {
162 : static const unsigned char abyDXFColors[768] = {
163 : 0, 0, 0, // 0
164 : 255, 0, 0, // 1
165 : 255,255, 0, // 2
166 : 0,255, 0, // 3
167 : 0,255,255, // 4
168 : 0, 0,255, // 5
169 : 255, 0,255, // 6
170 : 0, 0, 0, // 7 - it should be white, but that plots poorly
171 : 127,127,127, // 8
172 : 191,191,191, // 9
173 : 255, 0, 0, // 10
174 : 255,127,127, // 11
175 : 165, 0, 0, // 12
176 : 165, 82, 82, // 13
177 : 127, 0, 0, // 14
178 : 127, 63, 63, // 15
179 : 76, 0, 0, // 16
180 : 76, 38, 38, // 17
181 : 38, 0, 0, // 18
182 : 38, 19, 19, // 19
183 : 255, 63, 0, // 20
184 : 255,159,127, // 21
185 : 165, 41, 0, // 22
186 : 165,103, 82, // 23
187 : 127, 31, 0, // 24
188 : 127, 79, 63, // 25
189 : 76, 19, 0, // 26
190 : 76, 47, 38, // 27
191 : 38, 9, 0, // 28
192 : 38, 23, 19, // 29
193 : 255,127, 0, // 30
194 : 255,191,127, // 31
195 : 165, 82, 0, // 32
196 : 165,124, 82, // 33
197 : 127, 63, 0, // 34
198 : 127, 95, 63, // 35
199 : 76, 38, 0, // 36
200 : 76, 57, 38, // 37
201 : 38, 19, 0, // 38
202 : 38, 28, 19, // 39
203 : 255,191, 0, // 40
204 : 255,223,127, // 41
205 : 165,124, 0, // 42
206 : 165,145, 82, // 43
207 : 127, 95, 0, // 44
208 : 127,111, 63, // 45
209 : 76, 57, 0, // 46
210 : 76, 66, 38, // 47
211 : 38, 28, 0, // 48
212 : 38, 33, 19, // 49
213 : 255,255, 0, // 50
214 : 255,255,127, // 51
215 : 165,165, 0, // 52
216 : 165,165, 82, // 53
217 : 127,127, 0, // 54
218 : 127,127, 63, // 55
219 : 76, 76, 0, // 56
220 : 76, 76, 38, // 57
221 : 38, 38, 0, // 58
222 : 38, 38, 19, // 59
223 : 191,255, 0, // 60
224 : 223,255,127, // 61
225 : 124,165, 0, // 62
226 : 145,165, 82, // 63
227 : 95,127, 0, // 64
228 : 111,127, 63, // 65
229 : 57, 76, 0, // 66
230 : 66, 76, 38, // 67
231 : 28, 38, 0, // 68
232 : 33, 38, 19, // 69
233 : 127,255, 0, // 70
234 : 191,255,127, // 71
235 : 82,165, 0, // 72
236 : 124,165, 82, // 73
237 : 63,127, 0, // 74
238 : 95,127, 63, // 75
239 : 38, 76, 0, // 76
240 : 57, 76, 38, // 77
241 : 19, 38, 0, // 78
242 : 28, 38, 19, // 79
243 : 63,255, 0, // 80
244 : 159,255,127, // 81
245 : 41,165, 0, // 82
246 : 103,165, 82, // 83
247 : 31,127, 0, // 84
248 : 79,127, 63, // 85
249 : 19, 76, 0, // 86
250 : 47, 76, 38, // 87
251 : 9, 38, 0, // 88
252 : 23, 38, 19, // 89
253 : 0,255, 0, // 90
254 : 127,255,127, // 91
255 : 0,165, 0, // 92
256 : 82,165, 82, // 93
257 : 0,127, 0, // 94
258 : 63,127, 63, // 95
259 : 0, 76, 0, // 96
260 : 38, 76, 38, // 97
261 : 0, 38, 0, // 98
262 : 19, 38, 19, // 99
263 : 0,255, 63, // 100
264 : 127,255,159, // 101
265 : 0,165, 41, // 102
266 : 82,165,103, // 103
267 : 0,127, 31, // 104
268 : 63,127, 79, // 105
269 : 0, 76, 19, // 106
270 : 38, 76, 47, // 107
271 : 0, 38, 9, // 108
272 : 19, 38, 23, // 109
273 : 0,255,127, // 110
274 : 127,255,191, // 111
275 : 0,165, 82, // 112
276 : 82,165,124, // 113
277 : 0,127, 63, // 114
278 : 63,127, 95, // 115
279 : 0, 76, 38, // 116
280 : 38, 76, 57, // 117
281 : 0, 38, 19, // 118
282 : 19, 38, 28, // 119
283 : 0,255,191, // 120
284 : 127,255,223, // 121
285 : 0,165,124, // 122
286 : 82,165,145, // 123
287 : 0,127, 95, // 124
288 : 63,127,111, // 125
289 : 0, 76, 57, // 126
290 : 38, 76, 66, // 127
291 : 0, 38, 28, // 128
292 : 19, 38, 33, // 129
293 : 0,255,255, // 130
294 : 127,255,255, // 131
295 : 0,165,165, // 132
296 : 82,165,165, // 133
297 : 0,127,127, // 134
298 : 63,127,127, // 135
299 : 0, 76, 76, // 136
300 : 38, 76, 76, // 137
301 : 0, 38, 38, // 138
302 : 19, 38, 38, // 139
303 : 0,191,255, // 140
304 : 127,223,255, // 141
305 : 0,124,165, // 142
306 : 82,145,165, // 143
307 : 0, 95,127, // 144
308 : 63,111,127, // 145
309 : 0, 57, 76, // 146
310 : 38, 66, 76, // 147
311 : 0, 28, 38, // 148
312 : 19, 33, 38, // 149
313 : 0,127,255, // 150
314 : 127,191,255, // 151
315 : 0, 82,165, // 152
316 : 82,124,165, // 153
317 : 0, 63,127, // 154
318 : 63, 95,127, // 155
319 : 0, 38, 76, // 156
320 : 38, 57, 76, // 157
321 : 0, 19, 38, // 158
322 : 19, 28, 38, // 159
323 : 0, 63,255, // 160
324 : 127,159,255, // 161
325 : 0, 41,165, // 162
326 : 82,103,165, // 163
327 : 0, 31,127, // 164
328 : 63, 79,127, // 165
329 : 0, 19, 76, // 166
330 : 38, 47, 76, // 167
331 : 0, 9, 38, // 168
332 : 19, 23, 38, // 169
333 : 0, 0,255, // 170
334 : 127,127,255, // 171
335 : 0, 0,165, // 172
336 : 82, 82,165, // 173
337 : 0, 0,127, // 174
338 : 63, 63,127, // 175
339 : 0, 0, 76, // 176
340 : 38, 38, 76, // 177
341 : 0, 0, 38, // 178
342 : 19, 19, 38, // 179
343 : 63, 0,255, // 180
344 : 159,127,255, // 181
345 : 41, 0,165, // 182
346 : 103, 82,165, // 183
347 : 31, 0,127, // 184
348 : 79, 63,127, // 185
349 : 19, 0, 76, // 186
350 : 47, 38, 76, // 187
351 : 9, 0, 38, // 188
352 : 23, 19, 38, // 189
353 : 127, 0,255, // 190
354 : 191,127,255, // 191
355 : 82, 0,165, // 192
356 : 124, 82,165, // 193
357 : 63, 0,127, // 194
358 : 95, 63,127, // 195
359 : 38, 0, 76, // 196
360 : 57, 38, 76, // 197
361 : 19, 0, 38, // 198
362 : 28, 19, 38, // 199
363 : 191, 0,255, // 200
364 : 223,127,255, // 201
365 : 124, 0,165, // 202
366 : 145, 82,165, // 203
367 : 95, 0,127, // 204
368 : 111, 63,127, // 205
369 : 57, 0, 76, // 206
370 : 66, 38, 76, // 207
371 : 28, 0, 38, // 208
372 : 33, 19, 38, // 209
373 : 255, 0,255, // 210
374 : 255,127,255, // 211
375 : 165, 0,165, // 212
376 : 165, 82,165, // 213
377 : 127, 0,127, // 214
378 : 127, 63,127, // 215
379 : 76, 0, 76, // 216
380 : 76, 38, 76, // 217
381 : 38, 0, 38, // 218
382 : 38, 19, 38, // 219
383 : 255, 0,191, // 220
384 : 255,127,223, // 221
385 : 165, 0,124, // 222
386 : 165, 82,145, // 223
387 : 127, 0, 95, // 224
388 : 127, 63,111, // 225
389 : 76, 0, 57, // 226
390 : 76, 38, 66, // 227
391 : 38, 0, 28, // 228
392 : 38, 19, 33, // 229
393 : 255, 0,127, // 230
394 : 255,127,191, // 231
395 : 165, 0, 82, // 232
396 : 165, 82,124, // 233
397 : 127, 0, 63, // 234
398 : 127, 63, 95, // 235
399 : 76, 0, 38, // 236
400 : 76, 38, 57, // 237
401 : 38, 0, 19, // 238
402 : 38, 19, 28, // 239
403 : 255, 0, 63, // 240
404 : 255,127,159, // 241
405 : 165, 0, 41, // 242
406 : 165, 82,103, // 243
407 : 127, 0, 31, // 244
408 : 127, 63, 79, // 245
409 : 76, 0, 19, // 246
410 : 76, 38, 47, // 247
411 : 38, 0, 9, // 248
412 : 38, 19, 23, // 249
413 : 84, 84, 84, // 250
414 : 118,118,118, // 251
415 : 152,152,152, // 252
416 : 186,186,186, // 253
417 : 220,220,220, // 254
418 : 255,255,255 // 255
419 : };
420 :
421 170 : return abyDXFColors;
422 : }
423 :
424 : /************************************************************************/
425 : /* ACAdjustText() */
426 : /* */
427 : /* Rotate and scale text features by the designated amount by */
428 : /* adjusting the style string. */
429 : /************************************************************************/
430 :
431 8 : void ACAdjustText( double dfAngle, double dfScale, OGRFeature *poFeature )
432 :
433 : {
434 : /* -------------------------------------------------------------------- */
435 : /* We only try to alter text elements (LABEL styles). */
436 : /* -------------------------------------------------------------------- */
437 8 : if( poFeature->GetStyleString() == NULL )
438 0 : return;
439 :
440 8 : CPLString osOldStyle = poFeature->GetStyleString();
441 :
442 8 : if( strstr(osOldStyle,"LABEL") == NULL )
443 : return;
444 :
445 : /* -------------------------------------------------------------------- */
446 : /* Is there existing angle text? */
447 : /* -------------------------------------------------------------------- */
448 8 : double dfOldAngle = 0.0;
449 8 : CPLString osPreAngle, osPostAngle;
450 8 : size_t nAngleOff = osOldStyle.find( ",a:" );
451 :
452 8 : if( nAngleOff != std::string::npos )
453 : {
454 4 : size_t nEndOfAngleOff = osOldStyle.find( ",", nAngleOff + 1 );
455 :
456 4 : if( nEndOfAngleOff == std::string::npos )
457 0 : nEndOfAngleOff = osOldStyle.find( ")", nAngleOff + 1 );
458 :
459 4 : osPreAngle.assign( osOldStyle, nAngleOff );
460 4 : osPostAngle.assign( osOldStyle.c_str() + nEndOfAngleOff );
461 :
462 4 : dfOldAngle = CPLAtof( osOldStyle.c_str() + nAngleOff + 3 );
463 : }
464 : else
465 : {
466 4 : CPLAssert( osOldStyle[osOldStyle.size()-1] == ')' );
467 4 : osPreAngle.assign( osOldStyle, osOldStyle.size() - 1 );
468 4 : osPostAngle = ")";
469 : }
470 :
471 : /* -------------------------------------------------------------------- */
472 : /* Format with the new angle. */
473 : /* -------------------------------------------------------------------- */
474 8 : CPLString osNewStyle;
475 :
476 : osNewStyle.Printf( "%s,a:%g%s",
477 : osPreAngle.c_str(),
478 : dfOldAngle + dfAngle,
479 8 : osPostAngle.c_str() );
480 :
481 8 : osOldStyle = osNewStyle;
482 :
483 : /* -------------------------------------------------------------------- */
484 : /* Is there existing scale text? */
485 : /* -------------------------------------------------------------------- */
486 8 : double dfOldScale = 1.0;
487 8 : CPLString osPreScale, osPostScale;
488 8 : size_t nScaleOff = osOldStyle.find( ",s:" );
489 :
490 8 : if( nScaleOff != std::string::npos )
491 : {
492 8 : size_t nEndOfScaleOff = osOldStyle.find( ",", nScaleOff + 1 );
493 :
494 8 : if( nEndOfScaleOff == std::string::npos )
495 0 : nEndOfScaleOff = osOldStyle.find( ")", nScaleOff + 1 );
496 :
497 8 : osPreScale.assign( osOldStyle, nScaleOff );
498 8 : osPostScale.assign( osOldStyle.c_str() + nEndOfScaleOff );
499 :
500 8 : dfOldScale = CPLAtof( osOldStyle.c_str() + nScaleOff + 3 );
501 : }
502 : else
503 : {
504 0 : CPLAssert( osOldStyle[osOldStyle.size()-1] == ')' );
505 0 : osPreScale.assign( osOldStyle, osOldStyle.size() - 1 );
506 0 : osPostScale = ")";
507 : }
508 :
509 : /* -------------------------------------------------------------------- */
510 : /* Format with the new scale. */
511 : /* -------------------------------------------------------------------- */
512 : osNewStyle.Printf( "%s,s:%gg%s",
513 : osPreScale.c_str(),
514 : dfOldScale * dfScale,
515 8 : osPostScale.c_str() );
516 :
517 8 : poFeature->SetStyleString( osNewStyle );
518 : }
519 :
|