From a69e97943539a8abc4d2762638c169dc19c88516 Mon Sep 17 00:00:00 2001 From: Javier Date: Sun, 7 Jun 2015 21:22:45 +0200 Subject: initial import --- stfreader.cc | 336 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 stfreader.cc (limited to 'stfreader.cc') diff --git a/stfreader.cc b/stfreader.cc new file mode 100644 index 0000000..c5edff0 --- /dev/null +++ b/stfreader.cc @@ -0,0 +1,336 @@ +#include +#include + +#include "stfreader.h" + +#define TABLE_v(i, ...) static qint8 tab_ ## i [] = { __VA_ARGS__ } +#define TABLE static CodeTable table[] = { +#define TABLE_i(i) {i, sizeof(tab_ ## i), tab_ ## i}, +#define END_TABLE }; static int table_size = sizeof(table) / sizeof(CodeTable); + +StfReader::StfReader() +: handler(0) +{ +} + +StfReader::~StfReader() +{ +} + +StfReader::StrokeHandler::~StrokeHandler() +{ +} + +bool StfReader::parseV1(BitReader& br) +{ + quint64 cur_time = 0; + + while (!br.atEnd()) { + syncV1(br); + quint8 header = br.readBits(8); + quint64 time; + QPoint p0, pa; + int f0; + + switch (header) { + case 0x80: /* End of file. */ + return true; + break; + case 0: + time = br.readBits(8); + break; + case 0x08: + time = br.readBits(16); + break; + case 0x10: + time = br.readBits(32); + break; + case 0x18: + time = br.readBits(64); + break; + default: + qWarning("Unknown header 0x%x", header); + break; + } + + /* Start of a stroke. */ + cur_time += time; + p0.setX(br.readBits(16)); + p0.setY(br.readBits(16)); + f0 = readForce(br); + + if (handler) { + bool res = handler->startStroke(p0, f0, cur_time); + if (!res) return false; + } + + while (!br.atEnd()) { + header = readHeader(br); + if (header == 0 || header == 1) { + time = readTime(br); + } else { + int header2 = readHeader2(br); + switch (header2) { + case 0: + time = br.readBits(8); + break; + case 1: + time = br.readBits(16); + break; + case 2: + time = br.readBits(32); + break; + default: + qWarning("Unknown stroke time header %d", header2); + } + } + + if (time == 0) { + if (handler) { + bool res = handler->endStroke(); + if (!res) return false; + } + break; + } + + bool do_delta; + QPoint delta; + qint8 deltaf; + + if (header > 0) { + bool have_len = br.readBits(1); + if (have_len) { + do_delta = false; + QPoint p1; + p1.setX(br.readBits(16)); + p1.setY(br.readBits(16)); + pa = p1 - p0; + } else { + do_delta = true; + delta.setX(br.readBits(8)); + delta.setY(br.readBits(8)); + } + } else { + do_delta = true; + delta.setX(readDeltaX(br)); + delta.setY(readDeltaY(br)); + } + + deltaf = readDeltaF(br); + + if (do_delta) { + pa = delta + (pa * static_cast(time)) / 255; + } + + p0 += pa; + pa *= 256 / static_cast(time); + f0 += deltaf; + + if (handler) { + bool res = handler->strokePoint(p0, f0, cur_time); + if (!res) return false; + } + } + + } + + return false; +} + +void StfReader::syncV1(BitReader &br) +{ + br.skipUntilNextByte(); + while (!br.atEnd() && (br.peekBits(8) & ~(0x80|0x10|0x08))) { + br.readBits(8); + } +} + +qint8 StfReader::decodeV1(BitReader& br, CodeTable* tab, int tab_size) +{ + int got_bits = 0; + int codeacc = 0; + int stream = 0; + + for (int i = 0; i < tab_size; i++) { + int get_bits = tab[i].bits - got_bits; + codeacc <<= get_bits; + codeacc += tab[i].size; + + stream <<= get_bits; + stream |= br.readBits(get_bits); + + got_bits += get_bits; + + int idx = stream - codeacc; + if (idx < 0) { + idx = tab[i].size + idx; + Q_ASSERT(idx >= 0 && idx < tab[i].size); + return tab[i].data[idx]; + } + } + + qWarning("Unknown code"); + return 0; +} + +qint8 StfReader::readForce(BitReader &br) +{ + TABLE_v(1, 0); + TABLE_v(6, 1,4,7,9,10,11,13,15,17,20,21,22,23,24,25,26,27,28,30); + TABLE_v(7, 2,3,5,6,8,12,14,16,18,19,29,31,32,33,34,35,36,49,52); + TABLE_v(8, 37,45,46,47,48,50,51,53,54); + TABLE_v(9, 38,39,40,41,44,55,56); + TABLE_v(10, 43,57,58); + TABLE_v(11, 42,59,60,61,62,63); + TABLE + TABLE_i(1) TABLE_i(6) TABLE_i(7) TABLE_i(8) TABLE_i(9) TABLE_i(10) TABLE_i(11) + END_TABLE + + return decodeV1(br, table, table_size); +} + +qint8 StfReader::readHeader(BitReader &br) +{ + TABLE_v(1, 0); + TABLE_v(2, 1, 2); + TABLE + TABLE_i(1) TABLE_i(2) + END_TABLE + + return decodeV1(br, table, table_size); +} + +qint8 StfReader::readHeader2(BitReader &br) +{ + TABLE_v(1, 0); + TABLE_v(2, 1, 3); + TABLE + TABLE_i(1) TABLE_i(2) + END_TABLE + + return decodeV1(br, table, table_size); +} + +qint8 StfReader::readHeader3(BitReader &br) +{ + TABLE_v(1, 0,1); + TABLE + TABLE_i(1) + END_TABLE + + return decodeV1(br, table, table_size); +} + +qint8 StfReader::readTime(BitReader &br) +{ + TABLE_v(1, 1); + TABLE_v(2, 2); + TABLE_v(4, 0,3,4); + TABLE_v(6, 5,6); + TABLE_v(7, 7,8); + TABLE_v(8, 9); + TABLE_v(9, 10,11); + TABLE_v(10, 12,13,14); + TABLE_v(11, 15); + TABLE_v(12, 16,17,18,19,21,22); + TABLE_v(13, 20,23,24,25,26,27); + TABLE_v(14, 28,29,30,31,32,35,36,37,40); + TABLE_v(15, 38,39,41,44,45,48,50,53,59,60,67,73,82,91,98,99,102); + TABLE_v(16, 33,34,42,43,46,47,49,51,52,54,55,56,57,58,61,62,63,64,65,66,68,69,70,71,72,74,75,76,77,78,79,80,81,83,84,85,86,87,88,89,90,92,93,94,95,96,97,100,101,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127); + TABLE + TABLE_i(1) TABLE_i(2) TABLE_i(4) TABLE_i(6) TABLE_i(7) TABLE_i(8) + TABLE_i(9) TABLE_i(10) TABLE_i(11) TABLE_i(12) TABLE_i(13) TABLE_i(14) + TABLE_i(15) TABLE_i(16) + END_TABLE + + return decodeV1(br, table, table_size); +} + +qint8 StfReader::readDeltaX(BitReader &br) +{ + TABLE_v(4, 3,4,5); + TABLE_v(5, 0,1,2,6,7,8,9,-8,-7,-6,-5,-4,-3,-2,-1); + TABLE_v(6, 10,11,12,13,-13,-12,-11,-10,-9); + TABLE_v(7, 14,15,16,17,18,19,-18,-17,-16,-15,-14); + TABLE_v(8, 20,21,22,23,24,26,-25,-24,-23,-22,-21,-20,-19); + TABLE_v(9, 25,27,28,29,30,31,32,33,34,36,38,-36,-34,-33,-32,-31,-30,-29,-28,-27,-26); + TABLE_v(10, 35,37,39,40,41,42,43,44,45,46,47,49,55,-57,-50,-47,-46,-44,-43,-42,-41,-40,-39,-38,-37,-35); + TABLE + TABLE_i(4) TABLE_i(5) TABLE_i(6) TABLE_i(7) TABLE_i(8) TABLE_i(9) TABLE_i(10) + END_TABLE + + return decodeV1(br, table, table_size); +} + +qint8 StfReader::readDeltaY(BitReader &br) +{ + TABLE_v(5, 0,1,2,3,4,5,6,7,8,-9,-8,-7,-6,-5,-4,-3,-2,-1); + TABLE_v(6, 9,10,11,12,13,-14,-13,-12,-11,-10); + TABLE_v(7, 14,15,16,17,18,19,20,-20,-19,-18,-17,-16,-15); + TABLE_v(8, 21,22,23,24,25,26,27,28,29,30,31,-27,-26,-25,-24,-23,-22,-21); + TABLE_v(9, 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,49,-45,-44,-43,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28); + TABLE_v(10, 47,48,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,66,67,68,69,71,72,73,78,85,-75,-69,-64,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-42,-41); + + TABLE + TABLE_i(5) TABLE_i(6) TABLE_i(7) TABLE_i(8) TABLE_i(9) TABLE_i(10) + END_TABLE + + return decodeV1(br, table, table_size); +} + +qint8 StfReader::readDeltaF(BitReader &br) +{ + TABLE_v(1, 0); + TABLE_v(3, 1); + TABLE_v(4, -1); + TABLE_v(5, 2,-2); + TABLE_v(6, 3,-3); + TABLE_v(7, 4,52,53,-4); + TABLE_v(8, 5,6,49,50,51,54,55,-17,-16,-15,-14,-13,-12,-7,-6,-5); + TABLE_v(9, 7,8,9,10,11,12,13,30,31,36,37,38,39,40,41,46,48,56,57,-56,-55,-54,-53,-52,-51,-50,-49,-40,-38,-21,-20,-19,-18,-11,-10,-9,-8); + TABLE_v(10, 14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,32,33,34,35,42,43,44,45,47,58,-57,-48,-47,-46,-45,-44,-43,-42,-41,-39,-37,-36,-35,-34,-33,-32,-31,-29,-28,-27,-26,-25,-24,-23,-22); + TABLE_v(11, -59,-58,-30); + TABLE_v(12, 59,-64); + TABLE_v(13, 60,61,62,63,-63,-62,-61,-60); + TABLE + TABLE_i(1) TABLE_i(3) TABLE_i(4) TABLE_i(5) TABLE_i(6) TABLE_i(7) + TABLE_i(8) TABLE_i(9) TABLE_i(10) TABLE_i(11) TABLE_i(12) TABLE_i(13) + END_TABLE + + return decodeV1(br, table, table_size); +} + +bool StfReader::parse(QIODevice *device) +{ + char magic; + if (!device->getChar(&magic)) return false; + if (magic != 0x1) return false; + if (!device->getChar(&magic)) return false; + if (magic != 0x0) return false; + + QString version(device->read(14)); + if (version != "Anoto STF v1.0") { + return false; + } + + BitReader br(device); + + speed = br.readBits(16); + + return parseV1(br); +} + +bool StfReader::parse(const QString &filename) +{ + QFile f(filename); + if (!f.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open" << f.fileName(); + } + return parse(&f); +} + +void StfReader::setStrokeHandler(StrokeHandler *newHandler) +{ + Q_ASSERT(newHandler); + handler = newHandler; +} -- cgit v1.2.3