Line data Source code
1 : /**********************************************************************
2 : *
3 : * Name: mitab_tooldef.cpp
4 : * Project: MapInfo TAB Read/Write library
5 : * Language: C++
6 : * Purpose: Implementation of the TABToolDefTable class used to handle
7 : * a dataset's table of drawing tool blocks
8 : * Author: Daniel Morissette, dmorissette@dmsolutions.ca
9 : *
10 : **********************************************************************
11 : * Copyright (c) 1999, 2000, Daniel Morissette
12 : *
13 : * Permission is hereby granted, free of charge, to any person obtaining a
14 : * copy of this software and associated documentation files (the "Software"),
15 : * to deal in the Software without restriction, including without limitation
16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 : * and/or sell copies of the Software, and to permit persons to whom the
18 : * Software is furnished to do so, subject to the following conditions:
19 : *
20 : * The above copyright notice and this permission notice shall be included
21 : * in all copies or substantial portions of the Software.
22 : *
23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 : * DEALINGS IN THE SOFTWARE.
30 : **********************************************************************/
31 :
32 : #include "cpl_port.h"
33 : #include "mitab.h"
34 :
35 : #include <cstddef>
36 : #include <algorithm>
37 :
38 : #include "cpl_conv.h"
39 : #include "cpl_error.h"
40 : #include "mitab_priv.h"
41 : #include "mitab_utils.h"
42 :
43 : /*=====================================================================
44 : * class TABToolDefTable
45 : *====================================================================*/
46 :
47 : /**********************************************************************
48 : * TABToolDefTable::TABToolDefTable()
49 : *
50 : * Constructor.
51 : **********************************************************************/
52 1316 : TABToolDefTable::TABToolDefTable()
53 : : m_papsPen(nullptr), m_numPen(0), m_numAllocatedPen(0),
54 : m_papsBrush(nullptr), m_numBrushes(0), m_numAllocatedBrushes(0),
55 : m_papsFont(nullptr), m_numFonts(0), m_numAllocatedFonts(0),
56 1316 : m_papsSymbol(nullptr), m_numSymbols(0), m_numAllocatedSymbols(0)
57 : {
58 1316 : }
59 :
60 : /**********************************************************************
61 : * TABToolDefTable::~TABToolDefTable()
62 : *
63 : * Destructor.
64 : **********************************************************************/
65 2632 : TABToolDefTable::~TABToolDefTable()
66 : {
67 1401 : for (int i = 0; m_papsPen && i < m_numPen; i++)
68 85 : CPLFree(m_papsPen[i]);
69 1316 : CPLFree(m_papsPen);
70 :
71 1377 : for (int i = 0; m_papsBrush && i < m_numBrushes; i++)
72 61 : CPLFree(m_papsBrush[i]);
73 1316 : CPLFree(m_papsBrush);
74 :
75 1335 : for (int i = 0; m_papsFont && i < m_numFonts; i++)
76 19 : CPLFree(m_papsFont[i]);
77 1316 : CPLFree(m_papsFont);
78 :
79 2573 : for (int i = 0; m_papsSymbol && i < m_numSymbols; i++)
80 1257 : CPLFree(m_papsSymbol[i]);
81 1316 : CPLFree(m_papsSymbol);
82 1316 : }
83 :
84 : /**********************************************************************
85 : * TABToolDefTable::ReadAllToolDefs()
86 : *
87 : * Read all tool definition blocks until we reach the end of the chain.
88 : * This function will be called only once per dataset, after that
89 : * we keep all the tool definitions in memory.
90 : *
91 : * Returns 0 on success, -1 on error.
92 : **********************************************************************/
93 1208 : int TABToolDefTable::ReadAllToolDefs(TABMAPToolBlock *poBlock)
94 : {
95 1208 : int nStatus = 0;
96 :
97 : /*-----------------------------------------------------------------
98 : * Loop until we reach the end of the chain of blocks... we assume
99 : * that the first block of data is already pre-loaded.
100 : *----------------------------------------------------------------*/
101 2489 : while (!poBlock->EndOfChain())
102 : {
103 1281 : const int nDefType = poBlock->ReadByte();
104 1281 : switch (nDefType)
105 : {
106 43 : case TABMAP_TOOL_PEN: // PEN
107 43 : if (m_numPen >= m_numAllocatedPen)
108 : {
109 : // Realloc array by blocks of 20 items
110 37 : m_numAllocatedPen += 20;
111 37 : m_papsPen = static_cast<TABPenDef **>(CPLRealloc(
112 37 : m_papsPen, m_numAllocatedPen * sizeof(TABPenDef *)));
113 : }
114 86 : m_papsPen[m_numPen] =
115 43 : static_cast<TABPenDef *>(CPLCalloc(1, sizeof(TABPenDef)));
116 :
117 43 : m_papsPen[m_numPen]->nRefCount = poBlock->ReadInt32();
118 43 : m_papsPen[m_numPen]->nPixelWidth = poBlock->ReadByte();
119 43 : m_papsPen[m_numPen]->nLinePattern = poBlock->ReadByte();
120 43 : m_papsPen[m_numPen]->nPointWidth = poBlock->ReadByte();
121 43 : m_papsPen[m_numPen]->rgbColor =
122 43 : poBlock->ReadByte() * 256 * 256 +
123 43 : poBlock->ReadByte() * 256 + poBlock->ReadByte();
124 :
125 : // Adjust width value...
126 : // High bits for point width values > 255 are stored in the
127 : // pixel width byte
128 43 : if (m_papsPen[m_numPen]->nPixelWidth > 7)
129 : {
130 0 : m_papsPen[m_numPen]->nPointWidth +=
131 0 : (m_papsPen[m_numPen]->nPixelWidth - 8) * 0x100;
132 0 : m_papsPen[m_numPen]->nPixelWidth = 1;
133 : }
134 :
135 43 : m_numPen++;
136 :
137 43 : break;
138 32 : case TABMAP_TOOL_BRUSH: // BRUSH
139 32 : if (m_numBrushes >= m_numAllocatedBrushes)
140 : {
141 : // Realloc array by blocks of 20 items
142 26 : m_numAllocatedBrushes += 20;
143 26 : m_papsBrush = static_cast<TABBrushDef **>(
144 26 : CPLRealloc(m_papsBrush, m_numAllocatedBrushes *
145 : sizeof(TABBrushDef *)));
146 : }
147 64 : m_papsBrush[m_numBrushes] = static_cast<TABBrushDef *>(
148 32 : CPLCalloc(1, sizeof(TABBrushDef)));
149 :
150 32 : m_papsBrush[m_numBrushes]->nRefCount = poBlock->ReadInt32();
151 32 : m_papsBrush[m_numBrushes]->nFillPattern = poBlock->ReadByte();
152 64 : m_papsBrush[m_numBrushes]->bTransparentFill =
153 32 : poBlock->ReadByte();
154 32 : m_papsBrush[m_numBrushes]->rgbFGColor =
155 32 : poBlock->ReadByte() * 256 * 256 +
156 32 : poBlock->ReadByte() * 256 + poBlock->ReadByte();
157 32 : m_papsBrush[m_numBrushes]->rgbBGColor =
158 32 : poBlock->ReadByte() * 256 * 256 +
159 32 : poBlock->ReadByte() * 256 + poBlock->ReadByte();
160 :
161 32 : m_numBrushes++;
162 :
163 32 : break;
164 13 : case TABMAP_TOOL_FONT: // FONT NAME
165 13 : if (m_numFonts >= m_numAllocatedFonts)
166 : {
167 : // Realloc array by blocks of 20 items
168 7 : m_numAllocatedFonts += 20;
169 7 : m_papsFont = static_cast<TABFontDef **>(
170 7 : CPLRealloc(m_papsFont,
171 7 : m_numAllocatedFonts * sizeof(TABFontDef *)));
172 : }
173 26 : m_papsFont[m_numFonts] =
174 13 : static_cast<TABFontDef *>(CPLCalloc(1, sizeof(TABFontDef)));
175 :
176 13 : m_papsFont[m_numFonts]->nRefCount = poBlock->ReadInt32();
177 13 : poBlock->ReadBytes(32, reinterpret_cast<GByte *>(
178 13 : m_papsFont[m_numFonts]->szFontName));
179 13 : m_papsFont[m_numFonts]->szFontName[32] = '\0';
180 :
181 13 : m_numFonts++;
182 :
183 13 : break;
184 1193 : case TABMAP_TOOL_SYMBOL: // SYMBOL
185 1193 : if (m_numSymbols >= m_numAllocatedSymbols)
186 : {
187 : // Realloc array by blocks of 20 items
188 1187 : m_numAllocatedSymbols += 20;
189 1187 : m_papsSymbol = static_cast<TABSymbolDef **>(
190 1187 : CPLRealloc(m_papsSymbol, m_numAllocatedSymbols *
191 : sizeof(TABSymbolDef *)));
192 : }
193 2386 : m_papsSymbol[m_numSymbols] = static_cast<TABSymbolDef *>(
194 1193 : CPLCalloc(1, sizeof(TABSymbolDef)));
195 :
196 1193 : m_papsSymbol[m_numSymbols]->nRefCount = poBlock->ReadInt32();
197 1193 : m_papsSymbol[m_numSymbols]->nSymbolNo = poBlock->ReadInt16();
198 1193 : m_papsSymbol[m_numSymbols]->nPointSize = poBlock->ReadInt16();
199 2386 : m_papsSymbol[m_numSymbols]->_nUnknownValue_ =
200 1193 : poBlock->ReadByte();
201 1193 : m_papsSymbol[m_numSymbols]->rgbColor =
202 1193 : poBlock->ReadByte() * 256 * 256 +
203 1193 : poBlock->ReadByte() * 256 + poBlock->ReadByte();
204 :
205 1193 : m_numSymbols++;
206 :
207 1193 : break;
208 0 : default:
209 : /* Unsupported Tool type!!! */
210 0 : CPLError(CE_Failure, CPLE_NotSupported,
211 : "Unsupported drawing tool type: `%d'", nDefType);
212 0 : nStatus = -1;
213 : }
214 :
215 1281 : if (CPLGetLastErrorType() == CE_Failure)
216 : {
217 : // An error happened reading this tool definition... stop now.
218 0 : nStatus = -1;
219 0 : break;
220 : }
221 : }
222 :
223 1208 : return nStatus;
224 : }
225 :
226 : /**********************************************************************
227 : * TABToolDefTable::WriteAllToolDefs()
228 : *
229 : * Write all tool definition structures to the TABMAPToolBlock.
230 : *
231 : * Note that at the end of this call, poBlock->CommitToFile() will have
232 : * been called.
233 : *
234 : * Returns 0 on success, -1 on error.
235 : **********************************************************************/
236 1161 : int TABToolDefTable::WriteAllToolDefs(TABMAPToolBlock *poBlock)
237 : {
238 1161 : int nStatus = 0;
239 :
240 : /*-----------------------------------------------------------------
241 : * Write Pen Defs
242 : *----------------------------------------------------------------*/
243 1206 : for (int i = 0; nStatus == 0 && i < m_numPen; i++)
244 : {
245 : // The pen width is encoded over 2 bytes
246 45 : GByte byPixelWidth = 1;
247 45 : GByte byPointWidth = 0;
248 45 : if (m_papsPen[i]->nPointWidth > 0)
249 : {
250 0 : byPointWidth = static_cast<GByte>(m_papsPen[i]->nPointWidth & 0xff);
251 0 : if (m_papsPen[i]->nPointWidth > 255)
252 0 : byPixelWidth =
253 0 : 8 + static_cast<GByte>(m_papsPen[i]->nPointWidth / 0x100);
254 : }
255 : else
256 : {
257 45 : const GByte nMinWidth = 1;
258 45 : const GByte nMaxWidth = 7;
259 45 : byPixelWidth = std::min(
260 45 : std::max(m_papsPen[i]->nPixelWidth, nMinWidth), nMaxWidth);
261 : }
262 :
263 45 : poBlock->CheckAvailableSpace(TABMAP_TOOL_PEN);
264 45 : poBlock->WriteByte(TABMAP_TOOL_PEN); // Def Type = Pen
265 45 : poBlock->WriteInt32(m_papsPen[i]->nRefCount);
266 :
267 45 : poBlock->WriteByte(byPixelWidth);
268 45 : poBlock->WriteByte(m_papsPen[i]->nLinePattern);
269 45 : poBlock->WriteByte(byPointWidth);
270 45 : poBlock->WriteByte(static_cast<GByte>(COLOR_R(m_papsPen[i]->rgbColor)));
271 45 : poBlock->WriteByte(static_cast<GByte>(COLOR_G(m_papsPen[i]->rgbColor)));
272 45 : poBlock->WriteByte(static_cast<GByte>(COLOR_B(m_papsPen[i]->rgbColor)));
273 :
274 45 : if (CPLGetLastErrorType() == CE_Failure)
275 : {
276 : // An error happened reading this tool definition... stop now.
277 0 : nStatus = -1;
278 : }
279 : }
280 :
281 : /*-----------------------------------------------------------------
282 : * Write Brush Defs
283 : *----------------------------------------------------------------*/
284 1191 : for (int i = 0; nStatus == 0 && i < m_numBrushes; i++)
285 : {
286 30 : poBlock->CheckAvailableSpace(TABMAP_TOOL_BRUSH);
287 :
288 30 : poBlock->WriteByte(TABMAP_TOOL_BRUSH); // Def Type = Brush
289 30 : poBlock->WriteInt32(m_papsBrush[i]->nRefCount);
290 :
291 30 : poBlock->WriteByte(m_papsBrush[i]->nFillPattern);
292 30 : poBlock->WriteByte(m_papsBrush[i]->bTransparentFill);
293 30 : poBlock->WriteByte(
294 30 : static_cast<GByte>(COLOR_R(m_papsBrush[i]->rgbFGColor)));
295 30 : poBlock->WriteByte(
296 30 : static_cast<GByte>(COLOR_G(m_papsBrush[i]->rgbFGColor)));
297 30 : poBlock->WriteByte(
298 30 : static_cast<GByte>(COLOR_B(m_papsBrush[i]->rgbFGColor)));
299 30 : poBlock->WriteByte(
300 30 : static_cast<GByte>(COLOR_R(m_papsBrush[i]->rgbBGColor)));
301 30 : poBlock->WriteByte(
302 30 : static_cast<GByte>(COLOR_G(m_papsBrush[i]->rgbBGColor)));
303 30 : poBlock->WriteByte(
304 30 : static_cast<GByte>(COLOR_B(m_papsBrush[i]->rgbBGColor)));
305 :
306 30 : if (CPLGetLastErrorType() == CE_Failure)
307 : {
308 : // An error happened reading this tool definition... stop now.
309 0 : nStatus = -1;
310 : }
311 : }
312 :
313 : /*-----------------------------------------------------------------
314 : * Write Font Defs
315 : *----------------------------------------------------------------*/
316 1167 : for (int i = 0; nStatus == 0 && i < m_numFonts; i++)
317 : {
318 6 : poBlock->CheckAvailableSpace(TABMAP_TOOL_FONT);
319 :
320 6 : poBlock->WriteByte(TABMAP_TOOL_FONT); // Def Type = Font name
321 6 : poBlock->WriteInt32(m_papsFont[i]->nRefCount);
322 :
323 6 : poBlock->WriteBytes(
324 6 : 32, reinterpret_cast<GByte *>(m_papsFont[i]->szFontName));
325 :
326 6 : if (CPLGetLastErrorType() == CE_Failure)
327 : {
328 : // An error happened reading this tool definition... stop now.
329 0 : nStatus = -1;
330 : }
331 : }
332 :
333 : /*-----------------------------------------------------------------
334 : * Write Symbol Defs
335 : *----------------------------------------------------------------*/
336 2297 : for (int i = 0; nStatus == 0 && i < m_numSymbols; i++)
337 : {
338 1136 : poBlock->CheckAvailableSpace(TABMAP_TOOL_SYMBOL);
339 :
340 1136 : poBlock->WriteByte(TABMAP_TOOL_SYMBOL); // Def Type = Symbol
341 1136 : poBlock->WriteInt32(m_papsSymbol[i]->nRefCount);
342 :
343 1136 : poBlock->WriteInt16(m_papsSymbol[i]->nSymbolNo);
344 1136 : poBlock->WriteInt16(m_papsSymbol[i]->nPointSize);
345 1136 : poBlock->WriteByte(m_papsSymbol[i]->_nUnknownValue_);
346 1136 : poBlock->WriteByte(
347 1136 : static_cast<GByte>(COLOR_R(m_papsSymbol[i]->rgbColor)));
348 1136 : poBlock->WriteByte(
349 1136 : static_cast<GByte>(COLOR_G(m_papsSymbol[i]->rgbColor)));
350 1136 : poBlock->WriteByte(
351 1136 : static_cast<GByte>(COLOR_B(m_papsSymbol[i]->rgbColor)));
352 :
353 1136 : if (CPLGetLastErrorType() == CE_Failure)
354 : {
355 : // An error happened reading this tool definition... stop now.
356 0 : nStatus = -1;
357 : }
358 : }
359 :
360 1161 : if (nStatus == 0)
361 1161 : nStatus = poBlock->CommitToFile();
362 :
363 1161 : return nStatus;
364 : }
365 :
366 : /**********************************************************************
367 : * TABToolDefTable::GetNumPen()
368 : *
369 : * Return the number of valid pen indexes for this .MAP file
370 : **********************************************************************/
371 2322 : int TABToolDefTable::GetNumPen()
372 : {
373 2322 : return m_numPen;
374 : }
375 :
376 : /**********************************************************************
377 : * TABToolDefTable::GetPenDefRef()
378 : *
379 : * Return a reference to the specified Pen tool definition, or NULL if
380 : * specified index is invalid.
381 : *
382 : * Note that nIndex is a 1-based index. A value of 0 indicates "none"
383 : * in MapInfo.
384 : **********************************************************************/
385 1792 : TABPenDef *TABToolDefTable::GetPenDefRef(int nIndex)
386 : {
387 1792 : if (nIndex > 0 && nIndex <= m_numPen)
388 1790 : return m_papsPen[nIndex - 1];
389 :
390 2 : return nullptr;
391 : }
392 :
393 : /**********************************************************************
394 : * TABToolDefTable::AddPenDefRef()
395 : *
396 : * Either create a new PenDefRef or add a reference to an existing one.
397 : *
398 : * Return the pen index that has been attributed to this Pen tool
399 : * definition, or -1 if something went wrong
400 : *
401 : * Note that nIndex is a 1-based index. A value of 0 indicates "none"
402 : * in MapInfo.
403 : **********************************************************************/
404 330 : int TABToolDefTable::AddPenDefRef(TABPenDef *poNewPenDef)
405 : {
406 330 : if (poNewPenDef == nullptr)
407 0 : return -1;
408 :
409 : /*-----------------------------------------------------------------
410 : * Check for "none" case: pattern = 0 (pattern 0 does not exist!)
411 : *----------------------------------------------------------------*/
412 330 : if (poNewPenDef->nLinePattern < 1)
413 0 : return 0;
414 :
415 : /*-----------------------------------------------------------------
416 : * Start by searching the list of existing pens
417 : *----------------------------------------------------------------*/
418 330 : int nNewPenIndex = 0;
419 630 : for (int i = 0; nNewPenIndex == 0 && i < m_numPen; i++)
420 : {
421 300 : TABPenDef *poDef = m_papsPen[i];
422 300 : if (poDef->nPixelWidth == poNewPenDef->nPixelWidth &&
423 300 : poDef->nLinePattern == poNewPenDef->nLinePattern &&
424 300 : poDef->nPointWidth == poNewPenDef->nPointWidth &&
425 300 : poDef->rgbColor == poNewPenDef->rgbColor)
426 : {
427 288 : nNewPenIndex = i + 1; // Fount it!
428 288 : poDef->nRefCount++;
429 : }
430 : }
431 :
432 : /*-----------------------------------------------------------------
433 : * OK, we did not find a match, then create a new entry
434 : *----------------------------------------------------------------*/
435 330 : if (nNewPenIndex == 0)
436 : {
437 42 : if (m_numPen >= m_numAllocatedPen)
438 : {
439 : // Realloc array by blocks of 20 items
440 39 : m_numAllocatedPen += 20;
441 39 : m_papsPen = static_cast<TABPenDef **>(
442 39 : CPLRealloc(m_papsPen, m_numAllocatedPen * sizeof(TABPenDef *)));
443 : }
444 84 : m_papsPen[m_numPen] =
445 42 : static_cast<TABPenDef *>(CPLCalloc(1, sizeof(TABPenDef)));
446 :
447 42 : *m_papsPen[m_numPen] = *poNewPenDef;
448 42 : m_papsPen[m_numPen]->nRefCount = 1;
449 42 : nNewPenIndex = ++m_numPen;
450 : }
451 :
452 330 : return nNewPenIndex;
453 : }
454 :
455 : /**********************************************************************
456 : * TABToolDefTable::GetNumBrushes()
457 : *
458 : * Return the number of valid Brush indexes for this .MAP file
459 : **********************************************************************/
460 2322 : int TABToolDefTable::GetNumBrushes()
461 : {
462 2322 : return m_numBrushes;
463 : }
464 :
465 : /**********************************************************************
466 : * TABToolDefTable::GetBrushDefRef()
467 : *
468 : * Return a reference to the specified Brush tool definition, or NULL if
469 : * specified index is invalid.
470 : *
471 : * Note that nIndex is a 1-based index. A value of 0 indicates "none"
472 : * in MapInfo.
473 : **********************************************************************/
474 515 : TABBrushDef *TABToolDefTable::GetBrushDefRef(int nIndex)
475 : {
476 515 : if (nIndex > 0 && nIndex <= m_numBrushes)
477 510 : return m_papsBrush[nIndex - 1];
478 :
479 5 : return nullptr;
480 : }
481 :
482 : /**********************************************************************
483 : * TABToolDefTable::AddBrushDefRef()
484 : *
485 : * Either create a new BrushDefRef or add a reference to an existing one.
486 : *
487 : * Return the Brush index that has been attributed to this Brush tool
488 : * definition, or -1 if something went wrong
489 : *
490 : * Note that nIndex is a 1-based index. A value of 0 indicates "none"
491 : * in MapInfo.
492 : **********************************************************************/
493 88 : int TABToolDefTable::AddBrushDefRef(TABBrushDef *poNewBrushDef)
494 : {
495 88 : if (poNewBrushDef == nullptr)
496 0 : return -1;
497 :
498 : /*-----------------------------------------------------------------
499 : * Check for "none" case: pattern = 0 (pattern 0 does not exist!)
500 : *----------------------------------------------------------------*/
501 88 : if (poNewBrushDef->nFillPattern < 1)
502 0 : return 0;
503 :
504 : /*-----------------------------------------------------------------
505 : * Start by searching the list of existing Brushs
506 : *----------------------------------------------------------------*/
507 88 : int nNewBrushIndex = 0;
508 153 : for (int i = 0; nNewBrushIndex == 0 && i < m_numBrushes; i++)
509 : {
510 65 : TABBrushDef *poDef = m_papsBrush[i];
511 65 : if (poDef->nFillPattern == poNewBrushDef->nFillPattern &&
512 63 : poDef->bTransparentFill == poNewBrushDef->bTransparentFill &&
513 63 : poDef->rgbFGColor == poNewBrushDef->rgbFGColor &&
514 59 : poDef->rgbBGColor == poNewBrushDef->rgbBGColor)
515 : {
516 59 : nNewBrushIndex = i + 1; // Fount it!
517 59 : poDef->nRefCount++;
518 : }
519 : }
520 :
521 : /*-----------------------------------------------------------------
522 : * OK, we did not find a match, then create a new entry
523 : *----------------------------------------------------------------*/
524 88 : if (nNewBrushIndex == 0)
525 : {
526 29 : if (m_numBrushes >= m_numAllocatedBrushes)
527 : {
528 : // Realloc array by blocks of 20 items
529 26 : m_numAllocatedBrushes += 20;
530 26 : m_papsBrush = static_cast<TABBrushDef **>(CPLRealloc(
531 26 : m_papsBrush, m_numAllocatedBrushes * sizeof(TABBrushDef *)));
532 : }
533 58 : m_papsBrush[m_numBrushes] =
534 29 : static_cast<TABBrushDef *>(CPLCalloc(1, sizeof(TABBrushDef)));
535 :
536 29 : *m_papsBrush[m_numBrushes] = *poNewBrushDef;
537 29 : m_papsBrush[m_numBrushes]->nRefCount = 1;
538 29 : nNewBrushIndex = ++m_numBrushes;
539 : }
540 :
541 88 : return nNewBrushIndex;
542 : }
543 :
544 : /**********************************************************************
545 : * TABToolDefTable::GetNumFonts()
546 : *
547 : * Return the number of valid Font indexes for this .MAP file
548 : **********************************************************************/
549 2322 : int TABToolDefTable::GetNumFonts()
550 : {
551 2322 : return m_numFonts;
552 : }
553 :
554 : /**********************************************************************
555 : * TABToolDefTable::GetFontDefRef()
556 : *
557 : * Return a reference to the specified Font tool definition, or NULL if
558 : * specified index is invalid.
559 : *
560 : * Note that nIndex is a 1-based index. A value of 0 indicates "none"
561 : * in MapInfo.
562 : **********************************************************************/
563 20 : TABFontDef *TABToolDefTable::GetFontDefRef(int nIndex)
564 : {
565 20 : if (nIndex > 0 && nIndex <= m_numFonts)
566 20 : return m_papsFont[nIndex - 1];
567 :
568 0 : return nullptr;
569 : }
570 :
571 : /**********************************************************************
572 : * TABToolDefTable::AddFontDefRef()
573 : *
574 : * Either create a new FontDefRef or add a reference to an existing one.
575 : *
576 : * Return the Font index that has been attributed to this Font tool
577 : * definition, or -1 if something went wrong
578 : *
579 : * Note that nIndex is a 1-based index. A value of 0 indicates "none"
580 : * in MapInfo.
581 : **********************************************************************/
582 8 : int TABToolDefTable::AddFontDefRef(TABFontDef *poNewFontDef)
583 : {
584 8 : if (poNewFontDef == nullptr)
585 0 : return -1;
586 :
587 : /*-----------------------------------------------------------------
588 : * Start by searching the list of existing Fonts
589 : *----------------------------------------------------------------*/
590 8 : int nNewFontIndex = 0;
591 12 : for (int i = 0; nNewFontIndex == 0 && i < m_numFonts; i++)
592 : {
593 4 : TABFontDef *poDef = m_papsFont[i];
594 4 : if (EQUAL(poDef->szFontName, poNewFontDef->szFontName))
595 : {
596 2 : nNewFontIndex = i + 1; // Fount it!
597 2 : poDef->nRefCount++;
598 : }
599 : }
600 :
601 : /*-----------------------------------------------------------------
602 : * OK, we did not find a match, then create a new entry
603 : *----------------------------------------------------------------*/
604 8 : if (nNewFontIndex == 0)
605 : {
606 6 : if (m_numFonts >= m_numAllocatedFonts)
607 : {
608 : // Realloc array by blocks of 20 items
609 4 : m_numAllocatedFonts += 20;
610 4 : m_papsFont = static_cast<TABFontDef **>(CPLRealloc(
611 4 : m_papsFont, m_numAllocatedFonts * sizeof(TABFontDef *)));
612 : }
613 12 : m_papsFont[m_numFonts] =
614 6 : static_cast<TABFontDef *>(CPLCalloc(1, sizeof(TABFontDef)));
615 :
616 6 : *m_papsFont[m_numFonts] = *poNewFontDef;
617 6 : m_papsFont[m_numFonts]->nRefCount = 1;
618 6 : nNewFontIndex = ++m_numFonts;
619 : }
620 :
621 8 : return nNewFontIndex;
622 : }
623 :
624 : /**********************************************************************
625 : * TABToolDefTable::GetNumSymbols()
626 : *
627 : * Return the number of valid Symbol indexes for this .MAP file
628 : **********************************************************************/
629 2322 : int TABToolDefTable::GetNumSymbols()
630 : {
631 2322 : return m_numSymbols;
632 : }
633 :
634 : /**********************************************************************
635 : * TABToolDefTable::GetSymbolDefRef()
636 : *
637 : * Return a reference to the specified Symbol tool definition, or NULL if
638 : * specified index is invalid.
639 : *
640 : * Note that nIndex is a 1-based index. A value of 0 indicates "none"
641 : * in MapInfo.
642 : **********************************************************************/
643 514741 : TABSymbolDef *TABToolDefTable::GetSymbolDefRef(int nIndex)
644 : {
645 514741 : if (nIndex > 0 && nIndex <= m_numSymbols)
646 514741 : return m_papsSymbol[nIndex - 1];
647 :
648 0 : return nullptr;
649 : }
650 :
651 : /**********************************************************************
652 : * TABToolDefTable::AddSymbolDefRef()
653 : *
654 : * Either create a new SymbolDefRef or add a reference to an existing one.
655 : *
656 : * Return the Symbol index that has been attributed to this Symbol tool
657 : * definition, or -1 if something went wrong
658 : *
659 : * Note that nIndex is a 1-based index. A value of 0 indicates "none"
660 : * in MapInfo.
661 : **********************************************************************/
662 14685 : int TABToolDefTable::AddSymbolDefRef(TABSymbolDef *poNewSymbolDef)
663 : {
664 14685 : if (poNewSymbolDef == nullptr)
665 0 : return -1;
666 :
667 : /*-----------------------------------------------------------------
668 : * Start by searching the list of existing Symbols
669 : *----------------------------------------------------------------*/
670 14685 : int nNewSymbolIndex = 0;
671 29308 : for (int i = 0; nNewSymbolIndex == 0 && i < m_numSymbols; i++)
672 : {
673 14623 : TABSymbolDef *poDef = m_papsSymbol[i];
674 14623 : if (poDef->nSymbolNo == poNewSymbolDef->nSymbolNo &&
675 14623 : poDef->nPointSize == poNewSymbolDef->nPointSize &&
676 14621 : poDef->_nUnknownValue_ == poNewSymbolDef->_nUnknownValue_ &&
677 14621 : poDef->rgbColor == poNewSymbolDef->rgbColor)
678 : {
679 14621 : nNewSymbolIndex = i + 1; // Fount it!
680 14621 : poDef->nRefCount++;
681 : }
682 : }
683 :
684 : /*-----------------------------------------------------------------
685 : * OK, we did not find a match, then create a new entry
686 : *----------------------------------------------------------------*/
687 14685 : if (nNewSymbolIndex == 0)
688 : {
689 64 : if (m_numSymbols >= m_numAllocatedSymbols)
690 : {
691 : // Realloc array by blocks of 20 items
692 62 : m_numAllocatedSymbols += 20;
693 62 : m_papsSymbol = static_cast<TABSymbolDef **>(CPLRealloc(
694 62 : m_papsSymbol, m_numAllocatedSymbols * sizeof(TABSymbolDef *)));
695 : }
696 128 : m_papsSymbol[m_numSymbols] =
697 64 : static_cast<TABSymbolDef *>(CPLCalloc(1, sizeof(TABSymbolDef)));
698 :
699 64 : *m_papsSymbol[m_numSymbols] = *poNewSymbolDef;
700 64 : m_papsSymbol[m_numSymbols]->nRefCount = 1;
701 64 : nNewSymbolIndex = ++m_numSymbols;
702 : }
703 :
704 14685 : return nNewSymbolIndex;
705 : }
706 :
707 : /**********************************************************************
708 : * TABToolDefTable::GetMinVersionNumber()
709 : *
710 : * Returns the minimum file version number that can accept all the
711 : * tool objects currently defined.
712 : *
713 : * Default is 300, and currently 450 can be returned if file contains
714 : * pen widths defined in points.
715 : **********************************************************************/
716 102 : int TABToolDefTable::GetMinVersionNumber()
717 : {
718 102 : int i, nVersion = 300;
719 :
720 : /*-----------------------------------------------------------------
721 : * Scan Pen Defs
722 : *----------------------------------------------------------------*/
723 143 : for (i = 0; i < m_numPen; i++)
724 : {
725 41 : if (m_papsPen[i]->nPointWidth > 0)
726 : {
727 0 : nVersion = std::max(nVersion, 450); // Raise version to 450
728 : }
729 : }
730 :
731 102 : return nVersion;
732 : }
|