Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/graphite/src/inc/opcodes.h
9906 views
1
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
2
// Copyright 2010, SIL International, All rights reserved.
3
4
#pragma once
5
// This file will be pulled into and integrated into a machine implmentation
6
// DO NOT build directly and under no circumstances ever #include headers in
7
// here or you will break the direct_machine.
8
//
9
// Implementers' notes
10
// ==================
11
// You have access to a few primitives and the full C++ code:
12
// declare_params(n) Tells the interpreter how many bytes of parameter
13
// space to claim for this instruction uses and
14
// initialises the param pointer. You *must* before the
15
// first use of param.
16
// use_params(n) Claim n extra bytes of param space beyond what was
17
// claimed using delcare_param.
18
// param A const byte pointer for the parameter space claimed by
19
// this instruction.
20
// binop(op) Implement a binary operation on the stack using the
21
// specified C++ operator.
22
// NOT_IMPLEMENTED Any instruction body containing this will exit the
23
// program with an assertion error. Instructions that are
24
// not implemented should also be marked NILOP in the
25
// opcodes tables this will cause the code class to spot
26
// them in a live code stream and throw a runtime_error
27
// instead.
28
// push(n) Push the value n onto the stack.
29
// pop() Pop the top most value and return it.
30
//
31
// You have access to the following named fast 'registers':
32
// sp = The pointer to the current top of stack, the last value
33
// pushed.
34
// seg = A reference to the Segment this code is running over.
35
// is = The current slot index
36
// isb = The original base slot index at the start of this rule
37
// isf = The first positioned slot
38
// isl = The last positioned slot
39
// ip = The current instruction pointer
40
// endPos = Position of advance of last cluster
41
// dir = writing system directionality of the font
42
43
44
// #define NOT_IMPLEMENTED assert(false)
45
// #define NOT_IMPLEMENTED
46
47
#define binop(op) const uint32 a = pop(); *sp = uint32(*sp) op a
48
#define sbinop(op) const int32 a = pop(); *sp = int32(*sp) op a
49
#define use_params(n) dp += n
50
51
#define declare_params(n) const byte * param = dp; \
52
use_params(n);
53
54
#define push(n) { *++sp = n; }
55
#define pop() (*sp--)
56
#define slotat(x) (map[(x)])
57
#define DIE { is=seg.last(); status = Machine::died_early; EXIT(1); }
58
#define POSITIONED 1
59
60
STARTOP(nop)
61
do {} while (0);
62
ENDOP
63
64
STARTOP(push_byte)
65
declare_params(1);
66
push(int8(*param));
67
ENDOP
68
69
STARTOP(push_byte_u)
70
declare_params(1);
71
push(uint8(*param));
72
ENDOP
73
74
STARTOP(push_short)
75
declare_params(2);
76
const int16 r = int16(param[0]) << 8
77
| uint8(param[1]);
78
push(r);
79
ENDOP
80
81
STARTOP(push_short_u)
82
declare_params(2);
83
const uint16 r = uint16(param[0]) << 8
84
| uint8(param[1]);
85
push(r);
86
ENDOP
87
88
STARTOP(push_long)
89
declare_params(4);
90
const int32 r = int32(param[0]) << 24
91
| uint32(param[1]) << 16
92
| uint32(param[2]) << 8
93
| uint8(param[3]);
94
push(r);
95
ENDOP
96
97
STARTOP(add)
98
binop(+);
99
ENDOP
100
101
STARTOP(sub)
102
binop(-);
103
ENDOP
104
105
STARTOP(mul)
106
binop(*);
107
ENDOP
108
109
STARTOP(div_)
110
const int32 b = pop();
111
const int32 a = int32(*sp);
112
if (b == 0 || (a == std::numeric_limits<int32>::min() && b == -1)) DIE;
113
*sp = int32(*sp) / b;
114
ENDOP
115
116
STARTOP(min_)
117
const int32 a = pop(), b = *sp;
118
if (a < b) *sp = a;
119
ENDOP
120
121
STARTOP(max_)
122
const int32 a = pop(), b = *sp;
123
if (a > b) *sp = a;
124
ENDOP
125
126
STARTOP(neg)
127
*sp = uint32(-int32(*sp));
128
ENDOP
129
130
STARTOP(trunc8)
131
*sp = uint8(*sp);
132
ENDOP
133
134
STARTOP(trunc16)
135
*sp = uint16(*sp);
136
ENDOP
137
138
STARTOP(cond)
139
const uint32 f = pop(), t = pop(), c = pop();
140
push(c ? t : f);
141
ENDOP
142
143
STARTOP(and_)
144
binop(&&);
145
ENDOP
146
147
STARTOP(or_)
148
binop(||);
149
ENDOP
150
151
STARTOP(not_)
152
*sp = !*sp;
153
ENDOP
154
155
STARTOP(equal)
156
binop(==);
157
ENDOP
158
159
STARTOP(not_eq_)
160
binop(!=);
161
ENDOP
162
163
STARTOP(less)
164
sbinop(<);
165
ENDOP
166
167
STARTOP(gtr)
168
sbinop(>);
169
ENDOP
170
171
STARTOP(less_eq)
172
sbinop(<=);
173
ENDOP
174
175
STARTOP(gtr_eq)
176
sbinop(>=);
177
ENDOP
178
179
STARTOP(next)
180
if (map - &smap[0] >= int(smap.size())) DIE
181
if (is)
182
{
183
if (is == smap.highwater())
184
smap.highpassed(true);
185
is = is->next();
186
}
187
++map;
188
ENDOP
189
190
//STARTOP(next_n)
191
// use_params(1);
192
// NOT_IMPLEMENTED;
193
//declare_params(1);
194
//const size_t num = uint8(*param);
195
//ENDOP
196
197
//STARTOP(copy_next)
198
// if (is) is = is->next();
199
// ++map;
200
// ENDOP
201
202
STARTOP(put_glyph_8bit_obs)
203
declare_params(1);
204
const unsigned int output_class = uint8(*param);
205
is->setGlyph(&seg, seg.getClassGlyph(output_class, 0));
206
ENDOP
207
208
STARTOP(put_subs_8bit_obs)
209
declare_params(3);
210
const int slot_ref = int8(param[0]);
211
const unsigned int input_class = uint8(param[1]),
212
output_class = uint8(param[2]);
213
uint16 index;
214
slotref slot = slotat(slot_ref);
215
if (slot)
216
{
217
index = seg.findClassIndex(input_class, slot->gid());
218
is->setGlyph(&seg, seg.getClassGlyph(output_class, index));
219
}
220
ENDOP
221
222
STARTOP(put_copy)
223
declare_params(1);
224
const int slot_ref = int8(*param);
225
if (is && !is->isDeleted())
226
{
227
slotref ref = slotat(slot_ref);
228
if (ref && ref != is)
229
{
230
int16 *tempUserAttrs = is->userAttrs();
231
if (is->attachedTo() || is->firstChild()) DIE
232
Slot *prev = is->prev();
233
Slot *next = is->next();
234
memcpy(tempUserAttrs, ref->userAttrs(), seg.numAttrs() * sizeof(uint16));
235
memcpy(is, ref, sizeof(Slot));
236
is->firstChild(NULL);
237
is->nextSibling(NULL);
238
is->userAttrs(tempUserAttrs);
239
is->next(next);
240
is->prev(prev);
241
if (is->attachedTo())
242
is->attachedTo()->child(is);
243
}
244
is->markCopied(false);
245
is->markDeleted(false);
246
}
247
ENDOP
248
249
STARTOP(insert)
250
if (smap.decMax() <= 0) DIE;
251
Slot *newSlot = seg.newSlot();
252
if (!newSlot) DIE;
253
Slot *iss = is;
254
while (iss && iss->isDeleted()) iss = iss->next();
255
if (!iss)
256
{
257
if (seg.last())
258
{
259
seg.last()->next(newSlot);
260
newSlot->prev(seg.last());
261
newSlot->before(seg.last()->before());
262
seg.last(newSlot);
263
}
264
else
265
{
266
seg.first(newSlot);
267
seg.last(newSlot);
268
}
269
}
270
else if (iss->prev())
271
{
272
iss->prev()->next(newSlot);
273
newSlot->prev(iss->prev());
274
newSlot->before(iss->prev()->after());
275
}
276
else
277
{
278
newSlot->prev(NULL);
279
newSlot->before(iss->before());
280
seg.first(newSlot);
281
}
282
newSlot->next(iss);
283
if (iss)
284
{
285
iss->prev(newSlot);
286
newSlot->originate(iss->original());
287
newSlot->after(iss->before());
288
}
289
else if (newSlot->prev())
290
{
291
newSlot->originate(newSlot->prev()->original());
292
newSlot->after(newSlot->prev()->after());
293
}
294
else
295
{
296
newSlot->originate(seg.defaultOriginal());
297
}
298
if (is == smap.highwater())
299
smap.highpassed(false);
300
is = newSlot;
301
seg.extendLength(1);
302
if (map != &smap[-1])
303
--map;
304
ENDOP
305
306
STARTOP(delete_)
307
if (!is || is->isDeleted()) DIE
308
is->markDeleted(true);
309
if (is->prev())
310
is->prev()->next(is->next());
311
else
312
seg.first(is->next());
313
314
if (is->next())
315
is->next()->prev(is->prev());
316
else
317
seg.last(is->prev());
318
319
320
if (is == smap.highwater())
321
smap.highwater(is->next());
322
if (is->prev())
323
is = is->prev();
324
seg.extendLength(-1);
325
ENDOP
326
327
STARTOP(assoc)
328
declare_params(1);
329
unsigned int num = uint8(*param);
330
const int8 * assocs = reinterpret_cast<const int8 *>(param+1);
331
use_params(num);
332
int max = -1;
333
int min = -1;
334
335
while (num-- > 0)
336
{
337
int sr = *assocs++;
338
slotref ts = slotat(sr);
339
if (ts && (min == -1 || ts->before() < min)) min = ts->before();
340
if (ts && ts->after() > max) max = ts->after();
341
}
342
if (min > -1) // implies max > -1
343
{
344
is->before(min);
345
is->after(max);
346
}
347
ENDOP
348
349
STARTOP(cntxt_item)
350
// It turns out this is a cunningly disguised condition forward jump.
351
declare_params(3);
352
const int is_arg = int8(param[0]);
353
const size_t iskip = uint8(param[1]),
354
dskip = uint8(param[2]);
355
356
if (mapb + is_arg != map)
357
{
358
ip += iskip;
359
dp += dskip;
360
push(true);
361
}
362
ENDOP
363
364
STARTOP(attr_set)
365
declare_params(1);
366
const attrCode slat = attrCode(uint8(*param));
367
const int val = pop();
368
is->setAttr(&seg, slat, 0, val, smap);
369
ENDOP
370
371
STARTOP(attr_add)
372
declare_params(1);
373
const attrCode slat = attrCode(uint8(*param));
374
const uint32_t val = pop();
375
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
376
{
377
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
378
flags |= POSITIONED;
379
}
380
uint32_t res = uint32_t(is->getAttr(&seg, slat, 0));
381
is->setAttr(&seg, slat, 0, int32_t(val + res), smap);
382
ENDOP
383
384
STARTOP(attr_sub)
385
declare_params(1);
386
const attrCode slat = attrCode(uint8(*param));
387
const uint32_t val = pop();
388
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
389
{
390
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
391
flags |= POSITIONED;
392
}
393
uint32_t res = uint32_t(is->getAttr(&seg, slat, 0));
394
is->setAttr(&seg, slat, 0, int32_t(res - val), smap);
395
ENDOP
396
397
STARTOP(attr_set_slot)
398
declare_params(1);
399
const attrCode slat = attrCode(uint8(*param));
400
const int offset = int(map - smap.begin())*int(slat == gr_slatAttTo);
401
const int val = pop() + offset;
402
is->setAttr(&seg, slat, offset, val, smap);
403
ENDOP
404
405
STARTOP(iattr_set_slot)
406
declare_params(2);
407
const attrCode slat = attrCode(uint8(param[0]));
408
const uint8 idx = uint8(param[1]);
409
const int val = int(pop() + (map - smap.begin())*int(slat == gr_slatAttTo));
410
is->setAttr(&seg, slat, idx, val, smap);
411
ENDOP
412
413
STARTOP(push_slot_attr)
414
declare_params(2);
415
const attrCode slat = attrCode(uint8(param[0]));
416
const int slot_ref = int8(param[1]);
417
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
418
{
419
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
420
flags |= POSITIONED;
421
}
422
slotref slot = slotat(slot_ref);
423
if (slot)
424
{
425
int res = slot->getAttr(&seg, slat, 0);
426
push(res);
427
}
428
ENDOP
429
430
STARTOP(push_glyph_attr_obs)
431
declare_params(2);
432
const unsigned int glyph_attr = uint8(param[0]);
433
const int slot_ref = int8(param[1]);
434
slotref slot = slotat(slot_ref);
435
if (slot)
436
push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
437
ENDOP
438
439
STARTOP(push_glyph_metric)
440
declare_params(3);
441
const unsigned int glyph_attr = uint8(param[0]);
442
const int slot_ref = int8(param[1]);
443
const signed int attr_level = uint8(param[2]);
444
slotref slot = slotat(slot_ref);
445
if (slot)
446
push(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir));
447
ENDOP
448
449
STARTOP(push_feat)
450
declare_params(2);
451
const unsigned int feat = uint8(param[0]);
452
const int slot_ref = int8(param[1]);
453
slotref slot = slotat(slot_ref);
454
if (slot)
455
{
456
uint8 fid = seg.charinfo(slot->original())->fid();
457
push(seg.getFeature(fid, feat));
458
}
459
ENDOP
460
461
STARTOP(push_att_to_gattr_obs)
462
declare_params(2);
463
const unsigned int glyph_attr = uint8(param[0]);
464
const int slot_ref = int8(param[1]);
465
slotref slot = slotat(slot_ref);
466
if (slot)
467
{
468
slotref att = slot->attachedTo();
469
if (att) slot = att;
470
push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
471
}
472
ENDOP
473
474
STARTOP(push_att_to_glyph_metric)
475
declare_params(3);
476
const unsigned int glyph_attr = uint8(param[0]);
477
const int slot_ref = int8(param[1]);
478
const signed int attr_level = uint8(param[2]);
479
slotref slot = slotat(slot_ref);
480
if (slot)
481
{
482
slotref att = slot->attachedTo();
483
if (att) slot = att;
484
push(int32(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir)));
485
}
486
ENDOP
487
488
STARTOP(push_islot_attr)
489
declare_params(3);
490
const attrCode slat = attrCode(uint8(param[0]));
491
const int slot_ref = int8(param[1]),
492
idx = uint8(param[2]);
493
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
494
{
495
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
496
flags |= POSITIONED;
497
}
498
slotref slot = slotat(slot_ref);
499
if (slot)
500
{
501
int res = slot->getAttr(&seg, slat, idx);
502
push(res);
503
}
504
ENDOP
505
506
#if 0
507
STARTOP(push_iglyph_attr) // not implemented
508
NOT_IMPLEMENTED;
509
ENDOP
510
#endif
511
512
STARTOP(pop_ret)
513
const uint32 ret = pop();
514
EXIT(ret);
515
ENDOP
516
517
STARTOP(ret_zero)
518
EXIT(0);
519
ENDOP
520
521
STARTOP(ret_true)
522
EXIT(1);
523
ENDOP
524
525
STARTOP(iattr_set)
526
declare_params(2);
527
const attrCode slat = attrCode(uint8(param[0]));
528
const uint8 idx = uint8(param[1]);
529
const int val = pop();
530
is->setAttr(&seg, slat, idx, val, smap);
531
ENDOP
532
533
STARTOP(iattr_add)
534
declare_params(2);
535
const attrCode slat = attrCode(uint8(param[0]));
536
const uint8 idx = uint8(param[1]);
537
const uint32_t val = pop();
538
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
539
{
540
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
541
flags |= POSITIONED;
542
}
543
uint32_t res = uint32_t(is->getAttr(&seg, slat, idx));
544
is->setAttr(&seg, slat, idx, int32_t(val + res), smap);
545
ENDOP
546
547
STARTOP(iattr_sub)
548
declare_params(2);
549
const attrCode slat = attrCode(uint8(param[0]));
550
const uint8 idx = uint8(param[1]);
551
const uint32_t val = pop();
552
if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
553
{
554
seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
555
flags |= POSITIONED;
556
}
557
uint32_t res = uint32_t(is->getAttr(&seg, slat, idx));
558
is->setAttr(&seg, slat, idx, int32_t(res - val), smap);
559
ENDOP
560
561
STARTOP(push_proc_state)
562
use_params(1);
563
push(1);
564
ENDOP
565
566
STARTOP(push_version)
567
push(0x00030000);
568
ENDOP
569
570
STARTOP(put_subs)
571
declare_params(5);
572
const int slot_ref = int8(param[0]);
573
const unsigned int input_class = uint8(param[1]) << 8
574
| uint8(param[2]);
575
const unsigned int output_class = uint8(param[3]) << 8
576
| uint8(param[4]);
577
slotref slot = slotat(slot_ref);
578
if (slot)
579
{
580
int index = seg.findClassIndex(input_class, slot->gid());
581
is->setGlyph(&seg, seg.getClassGlyph(output_class, index));
582
}
583
ENDOP
584
585
#if 0
586
STARTOP(put_subs2) // not implemented
587
NOT_IMPLEMENTED;
588
ENDOP
589
590
STARTOP(put_subs3) // not implemented
591
NOT_IMPLEMENTED;
592
ENDOP
593
#endif
594
595
STARTOP(put_glyph)
596
declare_params(2);
597
const unsigned int output_class = uint8(param[0]) << 8
598
| uint8(param[1]);
599
is->setGlyph(&seg, seg.getClassGlyph(output_class, 0));
600
ENDOP
601
602
STARTOP(push_glyph_attr)
603
declare_params(3);
604
const unsigned int glyph_attr = uint8(param[0]) << 8
605
| uint8(param[1]);
606
const int slot_ref = int8(param[2]);
607
slotref slot = slotat(slot_ref);
608
if (slot)
609
push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
610
ENDOP
611
612
STARTOP(push_att_to_glyph_attr)
613
declare_params(3);
614
const unsigned int glyph_attr = uint8(param[0]) << 8
615
| uint8(param[1]);
616
const int slot_ref = int8(param[2]);
617
slotref slot = slotat(slot_ref);
618
if (slot)
619
{
620
slotref att = slot->attachedTo();
621
if (att) slot = att;
622
push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
623
}
624
ENDOP
625
626
STARTOP(temp_copy)
627
slotref newSlot = seg.newSlot();
628
if (!newSlot || !is) DIE;
629
int16 *tempUserAttrs = newSlot->userAttrs();
630
memcpy(newSlot, is, sizeof(Slot));
631
memcpy(tempUserAttrs, is->userAttrs(), seg.numAttrs() * sizeof(uint16));
632
newSlot->userAttrs(tempUserAttrs);
633
newSlot->markCopied(true);
634
*map = newSlot;
635
ENDOP
636
637
STARTOP(band)
638
binop(&);
639
ENDOP
640
641
STARTOP(bor)
642
binop(|);
643
ENDOP
644
645
STARTOP(bnot)
646
*sp = ~*sp;
647
ENDOP
648
649
STARTOP(setbits)
650
declare_params(4);
651
const uint16 m = uint16(param[0]) << 8
652
| uint8(param[1]);
653
const uint16 v = uint16(param[2]) << 8
654
| uint8(param[3]);
655
*sp = ((*sp) & ~m) | v;
656
ENDOP
657
658
STARTOP(set_feat)
659
declare_params(2);
660
const unsigned int feat = uint8(param[0]);
661
const int slot_ref = int8(param[1]);
662
slotref slot = slotat(slot_ref);
663
if (slot)
664
{
665
uint8 fid = seg.charinfo(slot->original())->fid();
666
seg.setFeature(fid, feat, pop());
667
}
668
ENDOP
669
670