Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/meshoptimizer/indexcodec.cpp
9903 views
1
// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
2
#include "meshoptimizer.h"
3
4
#include <assert.h>
5
#include <string.h>
6
7
// This work is based on:
8
// Fabian Giesen. Simple lossless index buffer compression & follow-up. 2013
9
// Conor Stokes. Vertex Cache Optimised Index Buffer Compression. 2014
10
namespace meshopt
11
{
12
13
const unsigned char kIndexHeader = 0xe0;
14
const unsigned char kSequenceHeader = 0xd0;
15
16
static int gEncodeIndexVersion = 1;
17
const int kDecodeIndexVersion = 1;
18
19
typedef unsigned int VertexFifo[16];
20
typedef unsigned int EdgeFifo[16][2];
21
22
static const unsigned int kTriangleIndexOrder[3][3] = {
23
{0, 1, 2},
24
{1, 2, 0},
25
{2, 0, 1},
26
};
27
28
static const unsigned char kCodeAuxEncodingTable[16] = {
29
0x00, 0x76, 0x87, 0x56, 0x67, 0x78, 0xa9, 0x86, 0x65, 0x89, 0x68, 0x98, 0x01, 0x69,
30
0, 0, // last two entries aren't used for encoding
31
};
32
33
static int rotateTriangle(unsigned int a, unsigned int b, unsigned int c, unsigned int next)
34
{
35
(void)a;
36
37
return (b == next) ? 1 : (c == next ? 2 : 0);
38
}
39
40
static int getEdgeFifo(EdgeFifo fifo, unsigned int a, unsigned int b, unsigned int c, size_t offset)
41
{
42
for (int i = 0; i < 16; ++i)
43
{
44
size_t index = (offset - 1 - i) & 15;
45
46
unsigned int e0 = fifo[index][0];
47
unsigned int e1 = fifo[index][1];
48
49
if (e0 == a && e1 == b)
50
return (i << 2) | 0;
51
if (e0 == b && e1 == c)
52
return (i << 2) | 1;
53
if (e0 == c && e1 == a)
54
return (i << 2) | 2;
55
}
56
57
return -1;
58
}
59
60
static void pushEdgeFifo(EdgeFifo fifo, unsigned int a, unsigned int b, size_t& offset)
61
{
62
fifo[offset][0] = a;
63
fifo[offset][1] = b;
64
offset = (offset + 1) & 15;
65
}
66
67
static int getVertexFifo(VertexFifo fifo, unsigned int v, size_t offset)
68
{
69
for (int i = 0; i < 16; ++i)
70
{
71
size_t index = (offset - 1 - i) & 15;
72
73
if (fifo[index] == v)
74
return i;
75
}
76
77
return -1;
78
}
79
80
static void pushVertexFifo(VertexFifo fifo, unsigned int v, size_t& offset, int cond = 1)
81
{
82
fifo[offset] = v;
83
offset = (offset + cond) & 15;
84
}
85
86
static void encodeVByte(unsigned char*& data, unsigned int v)
87
{
88
// encode 32-bit value in up to 5 7-bit groups
89
do
90
{
91
*data++ = (v & 127) | (v > 127 ? 128 : 0);
92
v >>= 7;
93
} while (v);
94
}
95
96
static unsigned int decodeVByte(const unsigned char*& data)
97
{
98
unsigned char lead = *data++;
99
100
// fast path: single byte
101
if (lead < 128)
102
return lead;
103
104
// slow path: up to 4 extra bytes
105
// note that this loop always terminates, which is important for malformed data
106
unsigned int result = lead & 127;
107
unsigned int shift = 7;
108
109
for (int i = 0; i < 4; ++i)
110
{
111
unsigned char group = *data++;
112
result |= unsigned(group & 127) << shift;
113
shift += 7;
114
115
if (group < 128)
116
break;
117
}
118
119
return result;
120
}
121
122
static void encodeIndex(unsigned char*& data, unsigned int index, unsigned int last)
123
{
124
unsigned int d = index - last;
125
unsigned int v = (d << 1) ^ (int(d) >> 31);
126
127
encodeVByte(data, v);
128
}
129
130
static unsigned int decodeIndex(const unsigned char*& data, unsigned int last)
131
{
132
unsigned int v = decodeVByte(data);
133
unsigned int d = (v >> 1) ^ -int(v & 1);
134
135
return last + d;
136
}
137
138
static int getCodeAuxIndex(unsigned char v, const unsigned char* table)
139
{
140
for (int i = 0; i < 16; ++i)
141
if (table[i] == v)
142
return i;
143
144
return -1;
145
}
146
147
static void writeTriangle(void* destination, size_t offset, size_t index_size, unsigned int a, unsigned int b, unsigned int c)
148
{
149
if (index_size == 2)
150
{
151
static_cast<unsigned short*>(destination)[offset + 0] = (unsigned short)(a);
152
static_cast<unsigned short*>(destination)[offset + 1] = (unsigned short)(b);
153
static_cast<unsigned short*>(destination)[offset + 2] = (unsigned short)(c);
154
}
155
else
156
{
157
static_cast<unsigned int*>(destination)[offset + 0] = a;
158
static_cast<unsigned int*>(destination)[offset + 1] = b;
159
static_cast<unsigned int*>(destination)[offset + 2] = c;
160
}
161
}
162
163
} // namespace meshopt
164
165
size_t meshopt_encodeIndexBuffer(unsigned char* buffer, size_t buffer_size, const unsigned int* indices, size_t index_count)
166
{
167
using namespace meshopt;
168
169
assert(index_count % 3 == 0);
170
171
// the minimum valid encoding is header, 1 byte per triangle and a 16-byte codeaux table
172
if (buffer_size < 1 + index_count / 3 + 16)
173
return 0;
174
175
int version = gEncodeIndexVersion;
176
177
buffer[0] = (unsigned char)(kIndexHeader | version);
178
179
EdgeFifo edgefifo;
180
memset(edgefifo, -1, sizeof(edgefifo));
181
182
VertexFifo vertexfifo;
183
memset(vertexfifo, -1, sizeof(vertexfifo));
184
185
size_t edgefifooffset = 0;
186
size_t vertexfifooffset = 0;
187
188
unsigned int next = 0;
189
unsigned int last = 0;
190
191
unsigned char* code = buffer + 1;
192
unsigned char* data = code + index_count / 3;
193
unsigned char* data_safe_end = buffer + buffer_size - 16;
194
195
int fecmax = version >= 1 ? 13 : 15;
196
197
// use static encoding table; it's possible to pack the result and then build an optimal table and repack
198
// for now we keep it simple and use the table that has been generated based on symbol frequency on a training mesh set
199
const unsigned char* codeaux_table = kCodeAuxEncodingTable;
200
201
for (size_t i = 0; i < index_count; i += 3)
202
{
203
// make sure we have enough space to write a triangle
204
// each triangle writes at most 16 bytes: 1b for codeaux and 5b for each free index
205
// after this we can be sure we can write without extra bounds checks
206
if (data > data_safe_end)
207
return 0;
208
209
int fer = getEdgeFifo(edgefifo, indices[i + 0], indices[i + 1], indices[i + 2], edgefifooffset);
210
211
if (fer >= 0 && (fer >> 2) < 15)
212
{
213
// note: getEdgeFifo implicitly rotates triangles by matching a/b to existing edge
214
const unsigned int* order = kTriangleIndexOrder[fer & 3];
215
216
unsigned int a = indices[i + order[0]], b = indices[i + order[1]], c = indices[i + order[2]];
217
218
// encode edge index and vertex fifo index, next or free index
219
int fe = fer >> 2;
220
int fc = getVertexFifo(vertexfifo, c, vertexfifooffset);
221
222
int fec = (fc >= 1 && fc < fecmax) ? fc : (c == next ? (next++, 0) : 15);
223
224
if (fec == 15 && version >= 1)
225
{
226
// encode last-1 and last+1 to optimize strip-like sequences
227
if (c + 1 == last)
228
fec = 13, last = c;
229
if (c == last + 1)
230
fec = 14, last = c;
231
}
232
233
*code++ = (unsigned char)((fe << 4) | fec);
234
235
// note that we need to update the last index since free indices are delta-encoded
236
if (fec == 15)
237
encodeIndex(data, c, last), last = c;
238
239
// we only need to push third vertex since first two are likely already in the vertex fifo
240
if (fec == 0 || fec >= fecmax)
241
pushVertexFifo(vertexfifo, c, vertexfifooffset);
242
243
// we only need to push two new edges to edge fifo since the third one is already there
244
pushEdgeFifo(edgefifo, c, b, edgefifooffset);
245
pushEdgeFifo(edgefifo, a, c, edgefifooffset);
246
}
247
else
248
{
249
int rotation = rotateTriangle(indices[i + 0], indices[i + 1], indices[i + 2], next);
250
const unsigned int* order = kTriangleIndexOrder[rotation];
251
252
unsigned int a = indices[i + order[0]], b = indices[i + order[1]], c = indices[i + order[2]];
253
254
// if a/b/c are 0/1/2, we emit a reset code
255
bool reset = false;
256
257
if (a == 0 && b == 1 && c == 2 && next > 0 && version >= 1)
258
{
259
reset = true;
260
next = 0;
261
262
// reset vertex fifo to make sure we don't accidentally reference vertices from that in the future
263
// this makes sure next continues to get incremented instead of being stuck
264
memset(vertexfifo, -1, sizeof(vertexfifo));
265
}
266
267
int fb = getVertexFifo(vertexfifo, b, vertexfifooffset);
268
int fc = getVertexFifo(vertexfifo, c, vertexfifooffset);
269
270
// after rotation, a is almost always equal to next, so we don't waste bits on FIFO encoding for a
271
// note: decoder implicitly assumes that if feb=fec=0, then fea=0 (reset code); this is enforced by rotation
272
int fea = (a == next) ? (next++, 0) : 15;
273
int feb = (fb >= 0 && fb < 14) ? fb + 1 : (b == next ? (next++, 0) : 15);
274
int fec = (fc >= 0 && fc < 14) ? fc + 1 : (c == next ? (next++, 0) : 15);
275
276
// we encode feb & fec in 4 bits using a table if possible, and as a full byte otherwise
277
unsigned char codeaux = (unsigned char)((feb << 4) | fec);
278
int codeauxindex = getCodeAuxIndex(codeaux, codeaux_table);
279
280
// <14 encodes an index into codeaux table, 14 encodes fea=0, 15 encodes fea=15
281
if (fea == 0 && codeauxindex >= 0 && codeauxindex < 14 && !reset)
282
{
283
*code++ = (unsigned char)((15 << 4) | codeauxindex);
284
}
285
else
286
{
287
*code++ = (unsigned char)((15 << 4) | 14 | fea);
288
*data++ = codeaux;
289
}
290
291
// note that we need to update the last index since free indices are delta-encoded
292
if (fea == 15)
293
encodeIndex(data, a, last), last = a;
294
295
if (feb == 15)
296
encodeIndex(data, b, last), last = b;
297
298
if (fec == 15)
299
encodeIndex(data, c, last), last = c;
300
301
// only push vertices that weren't already in fifo
302
if (fea == 0 || fea == 15)
303
pushVertexFifo(vertexfifo, a, vertexfifooffset);
304
305
if (feb == 0 || feb == 15)
306
pushVertexFifo(vertexfifo, b, vertexfifooffset);
307
308
if (fec == 0 || fec == 15)
309
pushVertexFifo(vertexfifo, c, vertexfifooffset);
310
311
// all three edges aren't in the fifo; pushing all of them is important so that we can match them for later triangles
312
pushEdgeFifo(edgefifo, b, a, edgefifooffset);
313
pushEdgeFifo(edgefifo, c, b, edgefifooffset);
314
pushEdgeFifo(edgefifo, a, c, edgefifooffset);
315
}
316
}
317
318
// make sure we have enough space to write codeaux table
319
if (data > data_safe_end)
320
return 0;
321
322
// add codeaux encoding table to the end of the stream; this is used for decoding codeaux *and* as padding
323
// we need padding for decoding to be able to assume that each triangle is encoded as <= 16 bytes of extra data
324
// this is enough space for aux byte + 5 bytes per varint index which is the absolute worst case for any input
325
for (size_t i = 0; i < 16; ++i)
326
{
327
// decoder assumes that table entries never refer to separately encoded indices
328
assert((codeaux_table[i] & 0xf) != 0xf && (codeaux_table[i] >> 4) != 0xf);
329
330
*data++ = codeaux_table[i];
331
}
332
333
// since we encode restarts as codeaux without a table reference, we need to make sure 00 is encoded as a table reference
334
assert(codeaux_table[0] == 0);
335
336
assert(data >= buffer + index_count / 3 + 16);
337
assert(data <= buffer + buffer_size);
338
339
return data - buffer;
340
}
341
342
size_t meshopt_encodeIndexBufferBound(size_t index_count, size_t vertex_count)
343
{
344
assert(index_count % 3 == 0);
345
346
// compute number of bits required for each index
347
unsigned int vertex_bits = 1;
348
349
while (vertex_bits < 32 && vertex_count > size_t(1) << vertex_bits)
350
vertex_bits++;
351
352
// worst-case encoding is 2 header bytes + 3 varint-7 encoded index deltas
353
unsigned int vertex_groups = (vertex_bits + 1 + 6) / 7;
354
355
return 1 + (index_count / 3) * (2 + 3 * vertex_groups) + 16;
356
}
357
358
void meshopt_encodeIndexVersion(int version)
359
{
360
assert(unsigned(version) <= unsigned(meshopt::kDecodeIndexVersion));
361
362
meshopt::gEncodeIndexVersion = version;
363
}
364
365
int meshopt_decodeIndexVersion(const unsigned char* buffer, size_t buffer_size)
366
{
367
if (buffer_size < 1)
368
return -1;
369
370
unsigned char header = buffer[0];
371
372
if ((header & 0xf0) != meshopt::kIndexHeader && (header & 0xf0) != meshopt::kSequenceHeader)
373
return -1;
374
375
int version = header & 0x0f;
376
if (version > meshopt::kDecodeIndexVersion)
377
return -1;
378
379
return version;
380
}
381
382
int meshopt_decodeIndexBuffer(void* destination, size_t index_count, size_t index_size, const unsigned char* buffer, size_t buffer_size)
383
{
384
using namespace meshopt;
385
386
assert(index_count % 3 == 0);
387
assert(index_size == 2 || index_size == 4);
388
389
// the minimum valid encoding is header, 1 byte per triangle and a 16-byte codeaux table
390
if (buffer_size < 1 + index_count / 3 + 16)
391
return -2;
392
393
if ((buffer[0] & 0xf0) != kIndexHeader)
394
return -1;
395
396
int version = buffer[0] & 0x0f;
397
if (version > kDecodeIndexVersion)
398
return -1;
399
400
EdgeFifo edgefifo;
401
memset(edgefifo, -1, sizeof(edgefifo));
402
403
VertexFifo vertexfifo;
404
memset(vertexfifo, -1, sizeof(vertexfifo));
405
406
size_t edgefifooffset = 0;
407
size_t vertexfifooffset = 0;
408
409
unsigned int next = 0;
410
unsigned int last = 0;
411
412
int fecmax = version >= 1 ? 13 : 15;
413
414
// since we store 16-byte codeaux table at the end, triangle data has to begin before data_safe_end
415
const unsigned char* code = buffer + 1;
416
const unsigned char* data = code + index_count / 3;
417
const unsigned char* data_safe_end = buffer + buffer_size - 16;
418
419
const unsigned char* codeaux_table = data_safe_end;
420
421
for (size_t i = 0; i < index_count; i += 3)
422
{
423
// make sure we have enough data to read for a triangle
424
// each triangle reads at most 16 bytes of data: 1b for codeaux and 5b for each free index
425
// after this we can be sure we can read without extra bounds checks
426
if (data > data_safe_end)
427
return -2;
428
429
unsigned char codetri = *code++;
430
431
if (codetri < 0xf0)
432
{
433
int fe = codetri >> 4;
434
435
// fifo reads are wrapped around 16 entry buffer
436
unsigned int a = edgefifo[(edgefifooffset - 1 - fe) & 15][0];
437
unsigned int b = edgefifo[(edgefifooffset - 1 - fe) & 15][1];
438
unsigned int c = 0;
439
440
int fec = codetri & 15;
441
442
// note: this is the most common path in the entire decoder
443
// inside this if we try to stay branchless (by using cmov/etc.) since these aren't predictable
444
if (fec < fecmax)
445
{
446
// fifo reads are wrapped around 16 entry buffer
447
unsigned int cf = vertexfifo[(vertexfifooffset - 1 - fec) & 15];
448
c = (fec == 0) ? next : cf;
449
450
int fec0 = fec == 0;
451
next += fec0;
452
453
// push vertex fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
454
pushVertexFifo(vertexfifo, c, vertexfifooffset, fec0);
455
}
456
else
457
{
458
// fec - (fec ^ 3) decodes 13, 14 into -1, 1
459
// note that we need to update the last index since free indices are delta-encoded
460
last = c = (fec != 15) ? last + (fec - (fec ^ 3)) : decodeIndex(data, last);
461
462
// push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
463
pushVertexFifo(vertexfifo, c, vertexfifooffset);
464
}
465
466
// push edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
467
pushEdgeFifo(edgefifo, c, b, edgefifooffset);
468
pushEdgeFifo(edgefifo, a, c, edgefifooffset);
469
470
// output triangle
471
writeTriangle(destination, i, index_size, a, b, c);
472
}
473
else
474
{
475
// fast path: read codeaux from the table
476
if (codetri < 0xfe)
477
{
478
unsigned char codeaux = codeaux_table[codetri & 15];
479
480
// note: table can't contain feb/fec=15
481
int feb = codeaux >> 4;
482
int fec = codeaux & 15;
483
484
// fifo reads are wrapped around 16 entry buffer
485
// also note that we increment next for all three vertices before decoding indices - this matches encoder behavior
486
unsigned int a = next++;
487
488
unsigned int bf = vertexfifo[(vertexfifooffset - feb) & 15];
489
unsigned int b = (feb == 0) ? next : bf;
490
491
int feb0 = feb == 0;
492
next += feb0;
493
494
unsigned int cf = vertexfifo[(vertexfifooffset - fec) & 15];
495
unsigned int c = (fec == 0) ? next : cf;
496
497
int fec0 = fec == 0;
498
next += fec0;
499
500
// output triangle
501
writeTriangle(destination, i, index_size, a, b, c);
502
503
// push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
504
pushVertexFifo(vertexfifo, a, vertexfifooffset);
505
pushVertexFifo(vertexfifo, b, vertexfifooffset, feb0);
506
pushVertexFifo(vertexfifo, c, vertexfifooffset, fec0);
507
508
pushEdgeFifo(edgefifo, b, a, edgefifooffset);
509
pushEdgeFifo(edgefifo, c, b, edgefifooffset);
510
pushEdgeFifo(edgefifo, a, c, edgefifooffset);
511
}
512
else
513
{
514
// slow path: read a full byte for codeaux instead of using a table lookup
515
unsigned char codeaux = *data++;
516
517
int fea = codetri == 0xfe ? 0 : 15;
518
int feb = codeaux >> 4;
519
int fec = codeaux & 15;
520
521
// reset: codeaux is 0 but encoded as not-a-table
522
if (codeaux == 0)
523
next = 0;
524
525
// fifo reads are wrapped around 16 entry buffer
526
// also note that we increment next for all three vertices before decoding indices - this matches encoder behavior
527
unsigned int a = (fea == 0) ? next++ : 0;
528
unsigned int b = (feb == 0) ? next++ : vertexfifo[(vertexfifooffset - feb) & 15];
529
unsigned int c = (fec == 0) ? next++ : vertexfifo[(vertexfifooffset - fec) & 15];
530
531
// note that we need to update the last index since free indices are delta-encoded
532
if (fea == 15)
533
last = a = decodeIndex(data, last);
534
535
if (feb == 15)
536
last = b = decodeIndex(data, last);
537
538
if (fec == 15)
539
last = c = decodeIndex(data, last);
540
541
// output triangle
542
writeTriangle(destination, i, index_size, a, b, c);
543
544
// push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
545
pushVertexFifo(vertexfifo, a, vertexfifooffset);
546
pushVertexFifo(vertexfifo, b, vertexfifooffset, (feb == 0) | (feb == 15));
547
pushVertexFifo(vertexfifo, c, vertexfifooffset, (fec == 0) | (fec == 15));
548
549
pushEdgeFifo(edgefifo, b, a, edgefifooffset);
550
pushEdgeFifo(edgefifo, c, b, edgefifooffset);
551
pushEdgeFifo(edgefifo, a, c, edgefifooffset);
552
}
553
}
554
}
555
556
// we should've read all data bytes and stopped at the boundary between data and codeaux table
557
if (data != data_safe_end)
558
return -3;
559
560
return 0;
561
}
562
563
size_t meshopt_encodeIndexSequence(unsigned char* buffer, size_t buffer_size, const unsigned int* indices, size_t index_count)
564
{
565
using namespace meshopt;
566
567
// the minimum valid encoding is header, 1 byte per index and a 4-byte tail
568
if (buffer_size < 1 + index_count + 4)
569
return 0;
570
571
int version = gEncodeIndexVersion;
572
573
buffer[0] = (unsigned char)(kSequenceHeader | version);
574
575
unsigned int last[2] = {};
576
unsigned int current = 0;
577
578
unsigned char* data = buffer + 1;
579
unsigned char* data_safe_end = buffer + buffer_size - 4;
580
581
for (size_t i = 0; i < index_count; ++i)
582
{
583
// make sure we have enough data to write
584
// each index writes at most 5 bytes of data; there's a 4 byte tail after data_safe_end
585
// after this we can be sure we can write without extra bounds checks
586
if (data >= data_safe_end)
587
return 0;
588
589
unsigned int index = indices[i];
590
591
// this is a heuristic that switches between baselines when the delta grows too large
592
// we want the encoded delta to fit into one byte (7 bits), but 2 bits are used for sign and baseline index
593
// for now we immediately switch the baseline when delta grows too large - this can be adjusted arbitrarily
594
int cd = int(index - last[current]);
595
current ^= ((cd < 0 ? -cd : cd) >= 30);
596
597
// encode delta from the last index
598
unsigned int d = index - last[current];
599
unsigned int v = (d << 1) ^ (int(d) >> 31);
600
601
// note: low bit encodes the index of the last baseline which will be used for reconstruction
602
encodeVByte(data, (v << 1) | current);
603
604
// update last for the next iteration that uses it
605
last[current] = index;
606
}
607
608
// make sure we have enough space to write tail
609
if (data > data_safe_end)
610
return 0;
611
612
for (int k = 0; k < 4; ++k)
613
*data++ = 0;
614
615
return data - buffer;
616
}
617
618
size_t meshopt_encodeIndexSequenceBound(size_t index_count, size_t vertex_count)
619
{
620
// compute number of bits required for each index
621
unsigned int vertex_bits = 1;
622
623
while (vertex_bits < 32 && vertex_count > size_t(1) << vertex_bits)
624
vertex_bits++;
625
626
// worst-case encoding is 1 varint-7 encoded index delta for a K bit value and an extra bit
627
unsigned int vertex_groups = (vertex_bits + 1 + 1 + 6) / 7;
628
629
return 1 + index_count * vertex_groups + 4;
630
}
631
632
int meshopt_decodeIndexSequence(void* destination, size_t index_count, size_t index_size, const unsigned char* buffer, size_t buffer_size)
633
{
634
using namespace meshopt;
635
636
// the minimum valid encoding is header, 1 byte per index and a 4-byte tail
637
if (buffer_size < 1 + index_count + 4)
638
return -2;
639
640
if ((buffer[0] & 0xf0) != kSequenceHeader)
641
return -1;
642
643
int version = buffer[0] & 0x0f;
644
if (version > kDecodeIndexVersion)
645
return -1;
646
647
const unsigned char* data = buffer + 1;
648
const unsigned char* data_safe_end = buffer + buffer_size - 4;
649
650
unsigned int last[2] = {};
651
652
for (size_t i = 0; i < index_count; ++i)
653
{
654
// make sure we have enough data to read
655
// each index reads at most 5 bytes of data; there's a 4 byte tail after data_safe_end
656
// after this we can be sure we can read without extra bounds checks
657
if (data >= data_safe_end)
658
return -2;
659
660
unsigned int v = decodeVByte(data);
661
662
// decode the index of the last baseline
663
unsigned int current = v & 1;
664
v >>= 1;
665
666
// reconstruct index as a delta
667
unsigned int d = (v >> 1) ^ -int(v & 1);
668
unsigned int index = last[current] + d;
669
670
// update last for the next iteration that uses it
671
last[current] = index;
672
673
if (index_size == 2)
674
{
675
static_cast<unsigned short*>(destination)[i] = (unsigned short)(index);
676
}
677
else
678
{
679
static_cast<unsigned int*>(destination)[i] = index;
680
}
681
}
682
683
// we should've read all data bytes and stopped at the boundary between data and tail
684
if (data != data_safe_end)
685
return -3;
686
687
return 0;
688
}
689
690