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