Rev 4168 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* Copyright (C) 2010.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 or
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
package uk.me.parabola.imgfmt.app.srt;
import uk.me.parabola.imgfmt.ReadFailedException;
import uk.me.parabola.imgfmt.app.CommonHeader;
import uk.me.parabola.imgfmt.app.ImgFileReader;
import uk.me.parabola.imgfmt.app.ImgFileWriter;
import uk.me.parabola.imgfmt.app.Section;
import uk.me.parabola.imgfmt.app.SectionWriter;
/**
* The header of the SRT file.
*
* This file determines the sort order of the label characters.
*
* @author Steve Ratcliffe
*/
public class SRTHeader extends CommonHeader {
// The header length we are using for the SRT file
public static final int HEADER_LEN = 29; // newer files use 37
protected static final int HEADER2_LEN = 16;
protected static final int HEADER3_LEN = 52;
protected static final int HEADER3_MULTI_LEN = 92;
// The section structure of this file is somewhat different to other
// files, but I am still going to model it using Section.
private final Section header2 = new Section();
private final Section desc = new Section(header2);
private final Section subheader = new Section(desc);
private final Section chartab = new Section(3);
private final Section expansions = new Section(chartab, 2);
private final Section srt8 = new Section(expansions, 5);
private final Section srt7 = new Section(srt8, 4);
private Sort sort;
public SRTHeader() {
this(HEADER_LEN);
}
public SRTHeader(int headerLen) {
super(headerLen, "GARMIN SRT");
header2.setPosition(headerLen);
header2.setSize(16);
chartab.setPosition(HEADER3_LEN);
}
protected void readFileHeader(ImgFileReader reader) throws ReadFailedException {
reader.get2u(); // expected: 1
header2.setPosition(reader.get4());
header2.setSize(reader.get2u());
}
/**
* Write out the application header. This is unusual as it just points
* to an area which is itself just a header.
*/
protected void writeFileHeader(ImgFileWriter writer) {
if (getHeaderLength() <= 29) {
writer.put2u(1);
writer.put4(header2.getPosition());
writer.put2u(header2.getSize());
} else {
// this appears in unicode maps dated 2016 and 2017
writer.put2u(0);
writer.put4(header2.getPosition());
writer.put2u(header2.getSize());
writer.put2u(1);
writer.put4(header2.getPosition());
writer.put2u(header2.getSize());
// older maps contain this variant (note the different order)
// writer.putChar((char) 1);
// writer.putInt(header2.getPosition());
// writer.putChar((char) header2.getSize());
// writer.putChar((char) 0);
// writer.putInt(desc.getPosition());
// writer.putChar((char) 0x10);
}
}
/**
* Section writer to write the character and expansions sections. These two sections are embedded within another
* section and their offsets are relative to that section.
* @param writer The real underlying writer.
* @return A new writer where offsets are relative to the start of the sub-header section.
*/
SectionWriter makeSectionWriter(ImgFileWriter writer) {
return new SectionWriter(writer, subheader);
}
/**
* This is a header with pointers to the description and the main section.
* The offsets contained in this section are relative to the beginning of the file.
* @param writer Header is written here.
*/
protected void writeHeader2(ImgFileWriter writer) {
desc.writeSectionInfo(writer);
subheader.writeSectionInfo(writer);
}
/**
* Header contained within the main section. Offsets within this section are relative to the beginning
* of the section.
* @param writer Header is written here.
*/
protected void writeHeader3(ImgFileWriter writer) {
if (sort.isMulti()) {
writer.put2u(HEADER3_MULTI_LEN);
} else {
writer.put2u(HEADER3_LEN);
}
writer.put2u(sort.getId1());
writer.put2u(sort.getId2());
writer.put2u(sort.getCodepage());
if (sort.isMulti())
writer.put4(0x6f02);
else
writer.put4(0x2002);
chartab.writeSectionInfo(writer, true, true);
writer.put2u(0);
expansions.writeSectionInfo(writer, true, true);
writer.put2u(0);
// SRT6 A repeat pointer to the single byte character table
writer.put4(chartab.getPosition());
writer.put4(0);
if (sort.isMulti()) {
writer.put4(1);
writer.put4(sort.getMaxPage()); // max block in srt7
srt7.writeSectionInfo(writer, true);
writer.put2u(0);
writer.put4(0);
srt8.writeSectionInfo(writer, true);
writer.put2u(0);
writer.put4(0);
}
}
public void setSort(Sort sort) {
this.sort = sort;
if (sort.isMulti()) {
chartab.setPosition(HEADER3_MULTI_LEN);
chartab.setItemSize(5);
expansions.setItemSize(4);
}
}
/** Called after the description has been written to record the position. */
public void endDescription(int position) {
desc.setSize(position - desc.getPosition());
subheader.setPosition(position);
}
/** Called after the character table has been written to record the position. */
public void endCharTable(int position) {
chartab.setSize(position - chartab.getPosition());
}
/** Called after the expansions has been written to record the position. */
public void endTab2(int postition) {
subheader.setSize(postition - subheader.getPosition());
expansions.setSize(postition - expansions.getPosition());
}
public void endSrt8(int position) {
srt8.setSize(position - srt8.getPosition());
}
public void endSrt7(int position) {
srt7.setSize(position - srt7.getPosition());
}
}