[Git][debian-gis-team/mkgmap][upstream] New upstream version 0.0.0+svn4885

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Tue Feb 1 17:23:22 GMT 2022



Bas Couwenberg pushed to branch upstream at Debian GIS Project / mkgmap


Commits:
021c85ed by Bas Couwenberg at 2022-02-01T18:09:08+01:00
New upstream version 0.0.0+svn4885
- - - - -


21 changed files:

- doc/index.txt
- doc/options.txt
- doc/styles/internal-tags.txt
- doc/styles/rules-filters.txt
- doc/styles/rules.txt
- resources/help/en/options
- resources/mkgmap-version.properties
- src/uk/me/parabola/imgfmt/app/BufferedImgFileReader.java
- src/uk/me/parabola/imgfmt/app/CommonHeader.java
- src/uk/me/parabola/imgfmt/app/ImgFileReader.java
- src/uk/me/parabola/imgfmt/app/lbl/LBLFileReader.java
- src/uk/me/parabola/imgfmt/app/lbl/PlacesHeader.java
- src/uk/me/parabola/imgfmt/app/net/NODHeader.java
- src/uk/me/parabola/imgfmt/app/trergn/RGNFile.java
- src/uk/me/parabola/imgfmt/app/trergn/RGNFileReader.java
- src/uk/me/parabola/imgfmt/app/trergn/Subdivision.java
- src/uk/me/parabola/imgfmt/app/trergn/TREFileReader.java
- src/uk/me/parabola/imgfmt/app/trergn/TREHeader.java
- src/uk/me/parabola/imgfmt/sys/ImgHeader.java
- src/uk/me/parabola/mkgmap/build/MapSplitter.java
- src/uk/me/parabola/mkgmap/combiners/FileInfo.java


Changes:

=====================================
doc/index.txt
=====================================
@@ -28,6 +28,9 @@ in the template.args file generated by splitter, produces a .img
 file for each tile, then merges all the tiles together into a
 single gmapsupp.img file.
 
+Regional extracts of OpenStreetMap data can be obtained from
+[https://download.geofabrik.de/ '''download.geofabrik.de'''].
+
 == Documentation ==
 The documentation that is currently available on this site is listed
 below.
@@ -50,6 +53,3 @@ they are written.
 
 [/doc/tuning '''Tuning''']
 Instructions on how to minimise execution time and avoid running out of memory.
-
-Further information can be found in the
-[http://wiki.openstreetmap.org/wiki/Mkgmap '''Open Street Map wiki''']


=====================================
doc/options.txt
=====================================
@@ -220,17 +220,19 @@ It may list 'Rueben Brookins Road' if that is in the map.
 ;--mdr7-excl=name[,name...]
 :	Specify words which should be omitted from the road index. 
 It was developed before option --road-name-config and is probably no longer needed.
-Matching is done case insensitive.
+Matching is case insensitive.
 :	Example usage: --mdr7-excl="Road, Street, Weg"
 
 ;--mdr7-del=name[,name...]
 :	Use this option if your style adds strings to the labels of roads which you
 want to see in the map but which should not appear in the result list
-of a road name / address search. The list is used like this:
-For each road label, mkgmap searches for the last blank. If one is found, it checks
-whether the word after it appears in the given list. If so, the word is removed
-and the search is repeated. The remaining string is used to create the index.
-The search is done case insensitive.
+of a road name / address search.
+When creating the index, words in the given list are removed from the end of road labels.
+Any word not found in the given list is considerered to be a valid label; words
+before the last valid label are not removed.
+If the label consists of a single word in the given list, or all the words in the
+label are contained in the given list, then the label is omitted from the index.
+The comparison is case insensitive and words are separated by a space.
 :	Example: Assume your style adds surface attributes like 'pav.' or 'unp.' to a road
 label. You can use --mdr7-del="pav.,unp." to remove these suffixes from the index.
 


=====================================
doc/styles/internal-tags.txt
=====================================
@@ -20,7 +20,7 @@ This rule defines that the road cannot be used by bicycles.
 // see [[Mkgmap/help/Tags]]
 
 .Tags for routable roads
-[options="header"]
+[cols="4,6,3,7",options="header"]
 |=========================================================
 | Attribute   | mkgmap tag     | Example | Notes
 | Labels      | +mkgmap:label:1+ + 
@@ -56,7 +56,7 @@ A112 | Usually only the first label is displayed. On some units the second label
 |=========================================================
 
 .Tags that control the treatment of roads
-[options="header"]
+[cols="8,7,5",options="header"]
 |=========================================================
 | Tag | Description     | Required mkgmap option
 | +mkgmap:way-has-pois+  | +true+ for ways that have at least one point with a tag +access=\*+, +barrier=\*+, or +highway=*+ | 'link-pois-to-ways'


=====================================
doc/styles/rules-filters.txt
=====================================
@@ -2,7 +2,7 @@
 // This is the list of variable filters.
 //
 .List of all substitution filters
-[width="100%",grid="rows",cols="<1,<1,3a",options="header"]
+[width="100%",grid="rows",cols="<1,<1,4a",options="header"]
 |=======
 | Name | Arguments | Description
 | def | `default` |
@@ -10,7 +10,7 @@ If the variable is not set, then use the argument as a default value.
 This means that the variable will never be `unset' in places where that
 matters. 
 
-`${oneway\|def:no}`
+`${oneway\|def:"no"}`
 
 | conv | `m=>ft` |
 Use for conversions between units.
@@ -49,7 +49,7 @@ Example, if name ="Queen Street"
 | part | `separator operator partnumber` |
 Split a value in parts and returns one or more part(s) of it. If +partnumber+ is negative, the part returned is counted from the end of the split
 
-If not specified, the default separator is ';' and the first part is returned (i.e. `${name\|part:}`=`${name\|part:;:1}`).
+If not specified, the default separator is ';' and the first part is returned (i.e. `${name\|part:""}`=`${name\|part:";:1"}`).
 
 If the operator is `:` the part specified by +partnumber+ is returned.
 
@@ -80,8 +80,7 @@ example if value is "word1 word2 ... wordN-1 wordN"
 Prepares the value as a highway reference such as "A21" "I-80" and so
 on.
 A code is added to the front of the string so that a highway shield is
-displayed, spaces are removed and the text is truncated so as not to overflow the
-symbol.
+displayed, any ";" are replaced by "/" and spaces are removed.
 
 `${ref\|highway-symbol:"box:4:8"}`
 
@@ -91,6 +90,10 @@ The first number is the maximum number of characters to allow for
 references that contain numbers and letters.
 The second is the maximum length of references that do not contain numbers.
 If there is just the one number then it is used in both cases.
+If no numbers are given, the default value 8 is used.
+
+If the reference, after spaces have been removed, is longer than the maximum length
+then the filter passes the string onwards unchanged; the highway-symbol is not prepended.
 
 | height | `m=>ft` |
 This is exactly the same as the +conv+ filter, except that it prepends a special
@@ -104,7 +107,7 @@ must be ft (foot).
 | country-ISO |  |
 Use to normalize country names to the 3 character ISO 1366 code.
 The filter has no arguments. It uses the list in LocatorConfig.xml.
-Possible arguments are country names, or ISO codes in 2 or 3 characters,
+Possible inputs are country names, or ISO codes in 2 or 3 characters,
 for example "Deutschland", "Germany", "Bundesrepublik Deutschland", or "DE" 
 will all return "DEU", also different cases like "GERMANY" or "   germany " 
 will work.
@@ -118,7 +121,7 @@ of this tag is set to undefined.
 
 ....
 place=* {
-   name '${name} (${int_name\|not-equal:name})'
+   name '${name} (${int_name\|not-equal:"name"})'
        \| '${name}'
    }
 ....
@@ -130,11 +133,11 @@ in parenthesis after the name. Otherwise there will just be the name as given in
 Extract part of the string. The start and end positions
 are counted starting from zero and the end position is not included.
 
-`${name\|substring:2:5}`
+`${name\|substring:"2:5"}`
 If the "name" was "Dorset Lane", then the result is "rse".  If there is just the one number,
 then the substring starts from that character until the end of the string.
 
-| not-contained | `separator tag` |
+| not-contained | `separator:tag` |
 Used to check for duplicate values. If the value of this tag is contained in the list being
 the value of the tag named as the argument to +not-contained+, then value
 of this tag is set to undefined.
@@ -142,7 +145,9 @@ of this tag is set to undefined.
 ....
 type=route & route=bus & ref=* {
    apply {
-      set route_ref='$(route_ref),${ref\|not-contained:,:route_ref}' \| '$(route_ref)' \| '${ref}';
+      set route_ref=
+         '$(route_ref),${ref\|not-contained:",:route_ref"}'
+             \| '$(route_ref)' \| '${ref}';
    }
 }
 ....


=====================================
doc/styles/rules.txt
=====================================
@@ -578,18 +578,14 @@ by the filter name, then a colon ":" and an argument. If there is more than
 one argument required then they are usually separated by colons too, but
 that is not a rule.
 
-+${tagname|filter:arg1:arg2}+
++${tagname|filter:"arg1:arg2"}+
 
 You can apply as many filter expressions to a substitution as you like.
 
 
-+${tagname|filter1:arg|filter2:arg}+
++${tagname|filter1:"f1Args"|filter2:"f2Args"}+
 
-If the argument contains spaces or symbols it should be quoted.
-
-+${tagname|filter1:"arg with spaces"}+
-
-For backward compatibility, most cases where you have spaces or symbols
+For backward compatibility, most argument strings
 do not actually need to be quoted, however we would recommend that you
 do for clarity.  If you need a pipe symbol or a closing curly backet,
 then you must use quotes.
@@ -714,8 +710,10 @@ connect different parts of the country, class 3 is used for roads that
 connect different regions, down to class 0 which is used for residential
 streets and other roads that you would only use for local travel.
 
-It is important for routing to work well that most roads are class 0 and
+It is important for routing to work well that most roads have lower classes and
 there are fewer and fewer roads in each of the higher classes.
+Also, the class of connector roads (links, roundabouts, ramps) matches
+the class of the highest class of roads being connected.  
 
 .Road classes
 [width="40%",frame="topbot",grid="rows",cols="<1,<4",options="header"]
@@ -724,7 +722,7 @@ there are fewer and fewer roads in each of the higher classes.
 | 4 | Major HW/Ramp
 | 3 | Principal HW
 | 2 | Arterial St / Other HW
-| 1 | Roundabout / Collector
+| 1 | Minor or Service road
 | 0 | Residential Street / Unpaved road / Trail
 |=====
 


=====================================
resources/help/en/options
=====================================
@@ -219,17 +219,19 @@ filename
 --mdr7-excl=name[,name...]
     Specify words which should be omitted from the road index. It was developed
     before option --road-name-config and is probably no longer needed. Matching
-    is done case insensitive.
+    is case insensitive.
     Example usage: --mdr7-excl="Road, Street, Weg"
 
 --mdr7-del=name[,name...]
     Use this option if your style adds strings to the labels of roads which you
     want to see in the map but which should not appear in the result list of a
-    road name / address search. The list is used like this: For each road
-    label, mkgmap searches for the last blank. If one is found, it checks
-    whether the word after it appears in the given list. If so, the word is
-    removed and the search is repeated. The remaining string is used to create
-    the index. The search is done case insensitive.
+    road name / address search. When creating the index, words in the given
+    list are removed from the end of road labels. Any word not found in the
+    given list is considerered to be a valid label; words before the last valid
+    label are not removed. If the label consists of a single word in the given
+    list, or all the words in the label are contained in the given list, then
+    the label is omitted from the index. The comparison is case insensitive and
+    words are separated by a space.
     Example: Assume your style adds surface attributes like 'pav.' or 'unp.' to
     a road label. You can use --mdr7-del="pav.,unp." to remove these suffixes
     from the index.


=====================================
resources/mkgmap-version.properties
=====================================
@@ -1,2 +1,2 @@
-svn.version: 4839
-build.timestamp: 2021-12-30T15:30:14+0000
+svn.version: 4885
+build.timestamp: 2022-01-30T08:18:40+0000


=====================================
src/uk/me/parabola/imgfmt/app/BufferedImgFileReader.java
=====================================
@@ -45,13 +45,25 @@ public class BufferedImgFileReader implements ImgFileReader {
 
 	// We keep our own idea of the file position.
 	private long position;
+	// the position of the header, normally 0, but not in GMP format
+	private final int gmpOffset;
 
 	public BufferedImgFileReader(ImgChannel chan) {
+		this(chan, 0);
+	}
+
+	public BufferedImgFileReader(ImgChannel chan, int gmpOffset) {
 		this.chan = chan;
+		this.gmpOffset = gmpOffset;
 //		buf.order(ByteOrder.LITTLE_ENDIAN);
 // could use getShort/getChar/getInt if sure buffer loaded		
 	}
 
+	@Override
+	public int getGMPOffset() {
+		return gmpOffset;
+	}
+
 	/**
 	 * Called when the stream is closed.  Any resources can be freed.
 	 *


=====================================
src/uk/me/parabola/imgfmt/app/CommonHeader.java
=====================================
@@ -41,7 +41,7 @@ public abstract class CommonHeader {
 
 	// Set to 0x80 on locked maps.  We are not interested in creating locked
 	// maps, but may be useful to recognise them for completeness.
-	//	private byte lockFlag;
+	private byte lockFlag;
 
 	// A date of creation.
 	private Date creationDate;
@@ -78,12 +78,12 @@ public abstract class CommonHeader {
 	 * @param reader Used to read the header.
 	 */
 	public final void readHeader(ImgFileReader reader) throws ReadFailedException {
-		reader.position(0);
+		reader.position(reader.getGMPOffset());
 		headerLength = reader.get2u();
 		byte[] bytes = reader.get(TYPE_LEN);
 		type = new String(bytes, StandardCharsets.US_ASCII);
 		reader.get(); // ignore
-		reader.get(); // ignore
+		this.lockFlag = reader.get(); // 0x80 if locked
 
 		byte[] date = reader.get(7);
 		creationDate = Utils.makeCreationTime(date);
@@ -116,4 +116,11 @@ public abstract class CommonHeader {
 		if (creationDate == null)
 			creationDate = new Date();
 	}
+
+	/**
+	 * @return the lockFlag
+	 */
+	public byte getLockFlag() {
+		return lockFlag;
+	}
 }


=====================================
src/uk/me/parabola/imgfmt/app/ImgFileReader.java
=====================================
@@ -17,6 +17,7 @@
 package uk.me.parabola.imgfmt.app;
 
 import java.io.Closeable;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import uk.me.parabola.imgfmt.ReadFailedException;
 
@@ -109,4 +110,35 @@ public interface ImgFileReader extends Closeable {
 	 * @return A phone number possibly containing the delimiter character.
 	 */
 	public String getBase11str(byte firstChar, char delimiter);
+
+	/**
+	 * Get the offset in the GMP file.
+	 * @return the offset, 0 if not a GMP file  
+	 */
+	default int getGMPOffset() {
+		return 0;
+	}
+
+	/**
+	 * Read varying length integer where first byte also gives number of following bytes.
+	 * See also imgfmt/app/mdr/MdrUtils.writeVarLength() and ./MdrDisplay.printSect17()
+	 *
+	 * @return the length
+	 */
+	default int readVarLength(AtomicInteger varLength) {
+		int peek = get1u();
+		if ((peek & 0x1) == 0x1) {
+			varLength.set(1);
+			return peek >> 1;
+		} else if ((peek & 0x3) == 0x2) {
+			varLength.set(2);
+			return peek >> 2 | get1u() << 6;
+		} else if ((peek & 0x7) == 0x4) {
+			varLength.set(3);
+			return peek >> 3 | get2u() << 5;
+		}  else { // bottom 3 bits clear so assume:
+			varLength.set(4);
+			return peek >> 4 | get3u() << 4; // mkgmap writeVarLength does this
+		}
+	}
 }


=====================================
src/uk/me/parabola/imgfmt/app/lbl/LBLFileReader.java
=====================================
@@ -12,6 +12,8 @@
  */
 package uk.me.parabola.imgfmt.app.lbl;
 
+import static uk.me.parabola.imgfmt.app.Label.NULL_LABEL;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -24,6 +26,7 @@ import uk.me.parabola.imgfmt.app.BufferedImgFileReader;
 import uk.me.parabola.imgfmt.app.ImgFile;
 import uk.me.parabola.imgfmt.app.ImgFileReader;
 import uk.me.parabola.imgfmt.app.Label;
+import uk.me.parabola.imgfmt.app.Section;
 import uk.me.parabola.imgfmt.app.labelenc.CharacterDecoder;
 import uk.me.parabola.imgfmt.app.labelenc.CodeFunctions;
 import uk.me.parabola.imgfmt.app.labelenc.DecodedText;
@@ -31,8 +34,6 @@ import uk.me.parabola.imgfmt.app.trergn.Subdivision;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
 import uk.me.parabola.log.Logger;
 
-import static uk.me.parabola.imgfmt.app.Label.NULL_LABEL;
-
 /**
  * The file that holds all the labels for the map.
  *
@@ -59,13 +60,13 @@ public class LBLFileReader extends ImgFile {
 	private final List<City> cities = new ArrayList<>();
 
 	public LBLFileReader(ImgChannel chan) {
-		this(chan, true);
+		this(chan, true, 0);
 	}
 	
-	public LBLFileReader(ImgChannel chan, boolean fullData) {
+	public LBLFileReader(ImgChannel chan, boolean fullData, int gmpOffset) {
 		setHeader(header);
 
-		setReader(new BufferedImgFileReader(chan));
+		setReader(new BufferedImgFileReader(chan, gmpOffset));
 		header.readHeader(getReader());
 		if (!fullData)
 			return;
@@ -140,15 +141,18 @@ public class LBLFileReader extends ImgFile {
 		PlacesHeader placeHeader = header.getPlaceHeader();
 
 		countries.add(null); // 1 based indexes
-
-		int start = placeHeader.getCountriesStart();
-		int end = placeHeader.getCountriesEnd();
-
+		Section s = placeHeader.getCountrySection();
+		int start = s.getPosition();
+		int end = s.getEndPos();
+		int recSize = s.getItemSize();
+		int unkSize = recSize - 3;   // new maps may have extra data
 		reader.position(start);
 		int index = 1;
 		while (reader.position() < end) {
 			int offset = reader.get3u();
-			Label label = fetchLabel(offset);
+			Label label = fetchLabel(offset & 0x3fffff);
+			if (unkSize > 0)
+				reader.get(unkSize);
 
 			if (label != null) {
 				Country country = new Country(index, label);
@@ -165,9 +169,11 @@ public class LBLFileReader extends ImgFile {
 		ImgFileReader reader = getReader();
 
 		PlacesHeader placeHeader = header.getPlaceHeader();
-
-		int start = placeHeader.getRegionsStart();
-		int end = placeHeader.getRegionsEnd();
+		Section s = placeHeader.getRegionSection();
+		int start = s.getPosition();
+		int end = s.getEndPos();
+		int recSize = s.getItemSize();
+		int unkSize = recSize - 5;   // new maps may have extra data
 
 		regions.add(null);
 
@@ -176,7 +182,9 @@ public class LBLFileReader extends ImgFile {
 		while (reader.position() < end) {
 			int country = reader.get2u();
 			int offset = reader.get3u();
-			Label label = fetchLabel(offset);
+			if (unkSize > 0)
+				reader.get(unkSize);
+			Label label = fetchLabel(offset & 0x3fffff);
 			if (label != null) {
 				Region region = new Region(countries.get(country), label);
 				region.setIndex(index);
@@ -194,9 +202,11 @@ public class LBLFileReader extends ImgFile {
 	 */
 	private void readCities() {
 		PlacesHeader placeHeader = header.getPlaceHeader();
-		int start = placeHeader.getCitiesStart();
-		int end = placeHeader.getCitiesEnd();
-
+		Section s = placeHeader.getCitySection();
+		int start = s.getPosition();
+		int end = s.getEndPos();
+		int recSize = s.getItemSize();
+		int unkSize = recSize - 5;   // new maps may have extra data
 		ImgFileReader reader = getReader();
 
 		// Since cities are indexed starting from 1, we add a null one at index 0
@@ -208,6 +218,8 @@ public class LBLFileReader extends ImgFile {
 			// don't know until we have read further
 			int label = reader.get3u();
 			int info = reader.get2u();
+			if (unkSize > 0)
+				reader.get(unkSize);
 
 			City city;
 			if ((info & 0x4000) == 0) {
@@ -221,7 +233,7 @@ public class LBLFileReader extends ImgFile {
 			city.setIndex(index);
 			if ((info & 0x8000) == 0) {
 				city.setSubdivision(Subdivision.createEmptySubdivision(1));
-				Label label1 = labels.get(label & 0x3fffff);
+				Label label1 = fetchLabel(label & 0x3fffff);
 				city.setLabel(label1);
 			} else {
 				// Has subdiv/point index
@@ -310,16 +322,21 @@ public class LBLFileReader extends ImgFile {
 		ImgFileReader reader = getReader();
 
 		PlacesHeader placeHeader = header.getPlaceHeader();
-		int start = placeHeader.getZipsStart();
-		int end = placeHeader.getZipsEnd();
+		Section s = placeHeader.getZipSection();
+		int start = s.getPosition();
+		int end = s.getEndPos();
+		int recSize = s.getItemSize();
+		int unkSize = recSize - 3;   // new maps may have extra data
 
 		reader.position(start);
 
 		int zipIndex = 1;
 		while (reader.position() < end) {
 			int lblOffset = reader.get3u();
-			
-			Zip zip = new Zip(fetchLabel(lblOffset));
+			if (unkSize > 0)
+				reader.get(unkSize);
+
+			Zip zip = new Zip(fetchLabel(lblOffset & 0x3fffff));
 			zip.setIndex(zipIndex);
 			
 			zips.put(zip.getIndex(), zip);


=====================================
src/uk/me/parabola/imgfmt/app/lbl/PlacesHeader.java
=====================================
@@ -122,7 +122,7 @@ public class PlacesHeader {
 	}
 
 	void readFileHeader(ImgFileReader reader) {
-		reader.position(0x1f);
+		reader.position(0x1fL + reader.getGMPOffset());
 
 		country.readSectionInfo(reader, true);
 		reader.get4();
@@ -223,42 +223,26 @@ public class PlacesHeader {
 		return poiProperties.getEndPos();
 	}
 
-	public int getCitiesStart() {
-		return city.getPosition();
+	public Section getCitySection() {
+		return city;
 	}
-	public int getCitiesEnd() {
-		return city.getEndPos();
-	}
-	
 	public int getNumExits() {
 		return exitFacility.getNumItems();
 	}
 
-	public int getCountriesStart() {
-		return country.getPosition();
-	}
-
-	public int getCountriesEnd() {
-		return country.getEndPos();
+	public Section getCountrySection() {
+		return country;
 	}
 
-	public int getRegionsStart() {
-		return region.getPosition();
-	}
-
-	public int getRegionsEnd() {
-		return region.getEndPos();
+	public Section getRegionSection() {
+		return region;
 	}
 
 	public int getNumHighways() {
 		return highway.getNumItems();
 	}
 	
-	public int getZipsStart() {
-		return zip.getPosition();
+	public Section getZipSection() {
+		return zip;
 	}
-	
-	public int getZipsEnd() {
-		return zip.getEndPos();
-	}	
 }


=====================================
src/uk/me/parabola/imgfmt/app/net/NODHeader.java
=====================================
@@ -18,6 +18,7 @@ package uk.me.parabola.imgfmt.app.net;
 
 import java.util.Arrays;
 
+import uk.me.parabola.imgfmt.Utils;
 import uk.me.parabola.imgfmt.app.CommonHeader;
 import uk.me.parabola.imgfmt.app.ImgFileReader;
 import uk.me.parabola.imgfmt.app.ImgFileWriter;
@@ -41,6 +42,8 @@ public class NODHeader extends CommonHeader {
 	private final Section boundary = new Section(roads, BOUNDARY_ITEM_SIZE);
 	private final Section highClassBoundary = new Section(boundary);
 	private final int[] classBoundaries = new int[5];
+	private final Section nod5 = new Section();
+	private final Section nod6 = new Section();
 
     private int flags;
     private int align;
@@ -48,6 +51,8 @@ public class NODHeader extends CommonHeader {
 	private int tableARecordLen;
 	private boolean driveOnLeft;
 
+	private int indexIdSize;
+
 	public NODHeader() {
 		super(HEADER_LEN, "GARMIN NOD");
 		Arrays.fill(classBoundaries, Integer.MAX_VALUE);
@@ -80,6 +85,14 @@ public class NODHeader extends CommonHeader {
 			classBoundaries[3] = classBoundaries[2] + reader.get4();
 			classBoundaries[4] = classBoundaries[3] + reader.get4();
 		}
+		if (getHeaderLength() >= 0x7f) {
+			reader.position(reader.getGMPOffset() + 0x67);
+			nod5.readSectionInfo(reader, false);
+			reader.get2u();
+			nod6.readSectionInfo(reader, true);
+			indexIdSize = Utils.numberToPointerSize(nod6.getNumItems());
+		}
+
 	}
 
 	/**
@@ -199,4 +212,11 @@ public class NODHeader extends CommonHeader {
 	public int getTableARecordLen() {
 		return tableARecordLen;
 	}
+
+	/**
+	 * @return the indexIdSize
+	 */
+	public int getIndexIdSize() {
+		return indexIdSize;
+	}
 }


=====================================
src/uk/me/parabola/imgfmt/app/trergn/RGNFile.java
=====================================
@@ -50,9 +50,9 @@ public class RGNFile extends ImgFile {
 	private int indPointPtrOff;
 	private int polylinePtrOff;
 	private int polygonPtrOff;
-	private ByteArrayOutputStream extTypePointsData;
-	private ByteArrayOutputStream extTypeLinesData;
-	private ByteArrayOutputStream extTypeAreasData;
+	private final ByteArrayOutputStream extTypePointsData = new ByteArrayOutputStream();
+	private final ByteArrayOutputStream extTypeLinesData = new ByteArrayOutputStream();
+	private final ByteArrayOutputStream extTypeAreasData = new ByteArrayOutputStream();
 
 	public RGNFile(ImgChannel chan) {
 		setHeader(header);
@@ -69,15 +69,15 @@ public class RGNFile extends ImgFile {
 
 		header.setDataSize(position() - HEADER_LEN);
 
-		if(extTypeAreasData != null) {
+		if(extTypeAreasData.size() > 0) {
 			header.setExtTypeAreasInfo(position(), extTypeAreasData.size());
 			getWriter().put(extTypeAreasData.toByteArray());
 		}
-		if(extTypeLinesData != null) {
+		if(extTypeLinesData.size() > 0) {
 			header.setExtTypeLinesInfo(position(), extTypeLinesData.size());
 			getWriter().put(extTypeLinesData.toByteArray());
 		}
-		if(extTypePointsData != null) {
+		if(extTypePointsData.size() > 0) {
 			header.setExtTypePointsInfo(position(), extTypePointsData.size());
 			getWriter().put(extTypePointsData.toByteArray());
 		}
@@ -95,48 +95,37 @@ public class RGNFile extends ImgFile {
 		// needed as it will always be first if present.
 		if (sd.needsIndPointPtr()) {
 			indPointPtrOff = position();
-			position(position() + 2);
+			position(position() + 2L);
 		}
 
 		if (sd.needsPolylinePtr()) {
 			polylinePtrOff = position();
-			position(position() + 2);
+			position(position() + 2L);
 		}
 
 		if (sd.needsPolygonPtr()) {
 			polygonPtrOff = position();
-			position(position() + 2);
+			position(position() + 2L);
 		}
 
 		currentDivision = sd;
 	}
 
 	public void addMapObject(MapObject item) {
-		if(item.hasExtendedType()) {
+		if (item.hasExtendedType()) {
 			try {
-				if(item instanceof Point) {
-					if(extTypePointsData == null)
-						extTypePointsData = new ByteArrayOutputStream();
+				if (item instanceof Point) {
 					item.write(extTypePointsData);
-				}
-				else if(item instanceof Polygon) {
-					if(extTypeAreasData == null)
-						extTypeAreasData = new ByteArrayOutputStream();
+				} else if (item instanceof Polygon) {
 					item.write(extTypeAreasData);
-				}
-				else if(item instanceof Polyline) {
-					if(extTypeLinesData == null)
-						extTypeLinesData = new ByteArrayOutputStream();
+				} else if (item instanceof Polyline) {
 					item.write(extTypeLinesData);
-				}
-				else
+				} else
 					log.error("Can't add object of type " + item.getClass());
-			}
-			catch (IOException ioe) {
+			} catch (IOException ioe) {
 				log.error("Error writing extended type object: " + ioe.getMessage());
 			}
-		}
-		else {
+		} else {
 			item.write(getWriter());
 		}
 	}
@@ -192,20 +181,20 @@ public class RGNFile extends ImgFile {
 	}
 
 	public int getExtTypePointsSize() {
-		return (extTypePointsData == null)? 0 : extTypePointsData.size();
+		return extTypePointsData.size();
 	}
 
 	public int getExtTypeLinesSize() {
-		return (extTypeLinesData == null)? 0 : extTypeLinesData.size();
+		return extTypeLinesData.size();
 	}
 
 	public int getExtTypeAreasSize() {
-		return (extTypeAreasData == null)? 0 : extTypeAreasData.size();
+		return extTypeAreasData.size();
 	}
 
 	public boolean haveExtendedTypes() {
-		return extTypePointsData != null ||
-				extTypeLinesData != null ||
-				extTypeAreasData != null;
+		return extTypeAreasData.size() != 0 || 
+				extTypeLinesData.size() != 0 || 
+				extTypePointsData.size() != 0;
 	}
 }


=====================================
src/uk/me/parabola/imgfmt/app/trergn/RGNFileReader.java
=====================================
@@ -85,7 +85,7 @@ public class RGNFileReader extends ImgReader {
 			fetchPointsCommon(sd, rgnOffsets.getPointStart(), rgnOffsets.getPointEnd(), list);
 		}
 		if (withExtType && sd.getExtTypePointsSize() > 0)
-			fetchPointsCommonExtType(sd, rgnHeader.getExtTypePointsOffset() + sd.getExtTypePointsOffset(), sd.getExtTypePointsSize(), list);
+			fetchPointsExtType(sd, list);
 
 		return list;
 	}
@@ -128,7 +128,6 @@ public class RGNFileReader extends ImgReader {
 			if (hasSubtype) {
 				int st = reader.get1u();
 				t |= st;
-				//p.setHasSubtype(true);
 			}
 			p.setType(t);
 
@@ -138,9 +137,11 @@ public class RGNFileReader extends ImgReader {
 	}
 
 	/**
-	 * The indexed points and the points sections are both read just the same.
+	 * The points with extended types
 	 */
-	private void fetchPointsCommonExtType(Subdivision sd, long start, long end, List<Point> points) {
+	private void fetchPointsExtType(Subdivision sd, List<Point> points) {
+		long start = rgnHeader.getExtTypePointsOffset() + sd.getExtTypePointsOffset();
+		long end = start + sd.getExtTypePointsSize();
 		position(start);
 		ImgFileReader reader = getReader();
 
@@ -339,16 +340,7 @@ public class RGNFileReader extends ImgReader {
 	
 		if (hasLabel){
 			int labelOffset = reader.get3u();
-			Label label;			
-			if ((labelOffset & 0x800000) == 0) {
-				label = lblFile.fetchLabel(labelOffset & 0x7fffff);
-			} else {
-					int netoff = labelOffset & 0x3fffff;
-					labelOffset = netFile.getLabelOffset(netoff);
-					label = lblFile.fetchLabel(labelOffset);
-					RoadDef roadDef = new RoadDef(0, netoff, label.getText());
-					line.setRoadDef(roadDef);
-			}
+			Label label = lblFile.fetchLabel(labelOffset & 0x3fffff);
 			line.setLabel(label);
 		}
 		if (hasExtraBytes){


=====================================
src/uk/me/parabola/imgfmt/app/trergn/Subdivision.java
=====================================
@@ -68,6 +68,7 @@ public class Subdivision {
 	private boolean hasIndPoints;
 	private boolean hasPolylines;
 	private boolean hasPolygons;
+	private boolean hasRoadRefs;
 
 	private int numPolylines;
 
@@ -167,7 +168,9 @@ public class Subdivision {
 			setHasPolylines(true);
 		if ((elem & 0x80) != 0)
 			setHasPolygons(true);
-	}
+		if ((elem & 0x1) != 0) // from top bit in height 
+			setHasRoadRefs(true);
+	}	
 
 	/**
 	 * Create a subdivision at a given zoom level.
@@ -399,6 +402,10 @@ public class Subdivision {
 		this.hasPolygons = hasPolygons;
 	}
 
+	public void setHasRoadRefs(boolean hasRoeadRefs) {
+		this.hasRoadRefs = hasRoeadRefs;
+	}
+
 	public boolean hasPoints() {
 		return hasPoints;
 	}
@@ -415,6 +422,10 @@ public class Subdivision {
 		return hasPolygons;
 	}
 
+	public boolean hasRoadRefs() {
+		return hasRoadRefs;
+	}
+
 	/**
 	 * Needed if it exists and is not first, ie there is a points
 	 * section.
@@ -434,14 +445,23 @@ public class Subdivision {
 	}
 
 	/**
-	 * As this is last in the list it is needed if it exists and there
-	 * is another section.
+	 * Needed if it exists and is not first, ie there is a points or
+	 * indexed points or polyline section.
 	 * @return true if pointer needed.
 	 */
 	public boolean needsPolygonPtr() {
 		return hasPolygons && (hasPoints || hasIndPoints || hasPolylines);
 	}
 
+	/**
+	 * As this is last in the list it is needed if it exists and there
+	 * is another section.
+	 * @return true if pointer needed.
+	 */
+	public boolean needsRoadRefPtr() {
+		return hasRoadRefs && (hasPoints || hasIndPoints || hasPolylines || hasPolygons);
+	}
+	
 	public String toString() {
 		return "Sub" + zoomLevel + '(' + getCenter().toOSMURL() + ')';
 	}


=====================================
src/uk/me/parabola/imgfmt/app/trergn/TREFileReader.java
=====================================
@@ -50,9 +50,13 @@ public class TREFileReader extends ImgReader {
 
 
 	public TREFileReader(ImgChannel chan) {
+		this(chan, 0);
+	}
+
+	public TREFileReader(ImgChannel chan, int gmpOffset) {
 		setHeader(header);
 
-		setReader(new BufferedImgFileReader(chan));
+		setReader(new BufferedImgFileReader(chan, gmpOffset));
 		header.readHeader(getReader());
 		readMapLevels();
 		readSubdivs();
@@ -108,14 +112,18 @@ public class TREFileReader extends ImgReader {
 				int lat = reader.get3s();
 				int width = reader.get2u() & 0x7fff;
 				int height = reader.get2u();
+				int extFlags = flags; 
+				if (reader.getGMPOffset() > 0 && (height & 0x8000) != 0) {
+					extFlags |= 0x1;
+					height &= 0x7fff;
+				}
 
 				if (count < levelDivs.length-1)
 					reader.get2u();
 
 				int endRgnOffset = reader.get3u();
 
-				SubdivData subdivData = new SubdivData(flags,
-// why???					lat, lon, 2*width, 2*height,
+				SubdivData subdivData = new SubdivData(extFlags,
 						lat, lon, width, height,
 						lastRgnOffset, endRgnOffset);
 
@@ -170,15 +178,30 @@ public class TREFileReader extends ImgReader {
 		int levelsPos = header.getMapLevelsPos();
 		int levelsSize = header.getMapLevelsSize();
 		reader.position(levelsPos);
+		byte[] levelsData = reader.get(levelsSize);
 
 		List<Subdivision[]> levelDivsList = new ArrayList<>();
 		List<Zoom> mapLevelsList = new ArrayList<>();
-		int end = levelsPos + levelsSize;
-		while (reader.position() < end) {
-			int level = reader.get1u();
-			int nbits = reader.get1u();
-			int ndivs = reader.get2u();
-
+		int key = 0;
+		if (header.getLockFlag() != 0) {
+			long pos = reader.position();
+			if (header.getHeaderLength() >= 0xAA) {
+				reader.position((reader.getGMPOffset() + 0xAA));
+				key = reader.get4();
+				
+			}
+			reader.position(pos);
+			
+			demangle(levelsData, levelsSize, key);
+		}
+		
+		int used = 0;
+		while (used < levelsSize) {
+			int level = levelsData[used++] & 0xff;
+			int nbits = levelsData[used++] & 0xff;
+			byte b1 = levelsData[used++];
+			byte b2 = levelsData[used++];
+			int ndivs = (b1 & 0xff) | ((b2 & 0xff) << 8);
 			Subdivision[] divs = new Subdivision[ndivs];
 			levelDivsList.add(divs);
 			level &= 0x7f;
@@ -238,4 +261,37 @@ public class TREFileReader extends ImgReader {
 		}
 		return msgs.toArray(new String[msgs.size()]);
 	}
+	
+	
+	// code taken from GPXsee 
+	// origin is much older: 
+	// https://github.com/wuyongzheng/gimgtools/blob/92d015749e105c5fb8eb704ae503a5c7e51af2bd/gimgunlock.c#L15
+	private static void demangle(byte[] data, int size, int key) {
+		final byte[] shuf = {
+			0xb, 0xc, 0xa, 0x0,
+			0x8, 0xf, 0x2, 0x1,
+			0x6, 0x4, 0x9, 0x3,
+			0xd, 0x5, 0x7, 0xe
+		};
+
+		int sum = shuf[((key >> 24) + (key >> 16) + (key >> 8) + key) & 0xf];
+		int ringctr = 16;
+		for (int i = 0; i < size; i++) {
+			int upper = data[i] >> 4;
+			int lower = data[i];
+
+			upper -= sum;
+			upper -= key >> ringctr;
+			upper -= shuf[(key >> ringctr) & 0xf];
+			ringctr = ringctr != 0 ? ringctr - 4 : 16;
+
+			lower -= sum;
+			lower -= key >> ringctr;
+			lower -= shuf[(key >> ringctr) & 0xf];
+			ringctr = ringctr != 0 ? ringctr - 4 : 16;
+
+			data[i] = (byte) (((upper << 4) & 0xf0) | (lower & 0xf));
+		}
+	}
+	 	
 }


=====================================
src/uk/me/parabola/imgfmt/app/trergn/TREHeader.java
=====================================
@@ -107,7 +107,7 @@ public class TREHeader extends CommonHeader {
 	 * @param reader The header is read from here.
 	 */
 	protected void readFileHeader(ImgFileReader reader) throws ReadFailedException {
-		if (reader.position() != COMMON_HEADER_LEN) {
+		if (reader.position() - reader.getGMPOffset() != COMMON_HEADER_LEN) {
 			throw new ReadFailedException("Reader position not at expected header length", new IOException());
 		}
 		int maxLat = reader.get3s();


=====================================
src/uk/me/parabola/imgfmt/sys/ImgHeader.java
=====================================
@@ -357,16 +357,6 @@ class ImgHeader {
 		header.put((byte) 0); // really?
 	}
 
-	/**
-	 * Convert a string to a byte array.
-	 * @param s The string
-	 * @return A byte array.
-	 */
-	private static byte[] toByte(String s) {
-		// NB: what character set should be used?
-		return s.getBytes();
-	}
-
 	/**
 	 * Convert to the one byte code that is used for the year.
 	 * If the year is in the 1900, then subtract 1900 and add the result to 0x63,


=====================================
src/uk/me/parabola/mkgmap/build/MapSplitter.java
=====================================
@@ -37,8 +37,8 @@ public class MapSplitter {
 
 	private final MapDataSource mapSource;
 
-	// There is an absolute largest size as offsets are in 16 bits, we are
-	//  staying safely inside it however.
+	// There is an absolute largest size as offsets are in 16 bits, but
+	// the top bit of height is probably a flag for GMP "RoadRef" data.  
 	public static final int MAX_DIVISION_SIZE = 0x7fff;
 
 	// Not a real limit.  Note that the offset to the start of a section


=====================================
src/uk/me/parabola/mkgmap/combiners/FileInfo.java
=====================================
@@ -336,7 +336,7 @@ public class FileInfo {
 	}
 
 	private static void lblInfo(ImgChannel chan, FileInfo info) {
-		try (LBLFileReader lblFile = new LBLFileReader(chan, false)) {
+		try (LBLFileReader lblFile = new LBLFileReader(chan, false, 0)) {
 			info.setCodePage(lblFile.getCodePage());
 			info.setSortOrderId(lblFile.getSortOrderId());
 		}



View it on GitLab: https://salsa.debian.org/debian-gis-team/mkgmap/-/commit/021c85ed1822ef8baf3ee4d97be1c784fa0acb4e

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/mkgmap/-/commit/021c85ed1822ef8baf3ee4d97be1c784fa0acb4e
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20220201/79b7314d/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list