aboutsummaryrefslogtreecommitdiff
path: root/stfreader.cc
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2015-06-07 21:22:45 +0200
committerJavier <dev.git@javispedro.com>2015-06-07 21:22:45 +0200
commita69e97943539a8abc4d2762638c169dc19c88516 (patch)
treef3516ea29745db65971247cee4c260b49f1067b2 /stfreader.cc
downloadscribiu-a69e97943539a8abc4d2762638c169dc19c88516.tar.gz
scribiu-a69e97943539a8abc4d2762638c169dc19c88516.zip
initial import
Diffstat (limited to 'stfreader.cc')
-rw-r--r--stfreader.cc336
1 files changed, 336 insertions, 0 deletions
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 <QtCore/QDebug>
+#include <QtCore/QFile>
+
+#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<int>(time)) / 255;
+ }
+
+ p0 += pa;
+ pa *= 256 / static_cast<int>(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;
+}