summaryrefslogtreecommitdiffstats
path: root/gfx/graphite2/src/inc/opcodes.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/graphite2/src/inc/opcodes.h')
-rw-r--r--gfx/graphite2/src/inc/opcodes.h691
1 files changed, 691 insertions, 0 deletions
diff --git a/gfx/graphite2/src/inc/opcodes.h b/gfx/graphite2/src/inc/opcodes.h
new file mode 100644
index 0000000000..ff2f1741e2
--- /dev/null
+++ b/gfx/graphite2/src/inc/opcodes.h
@@ -0,0 +1,691 @@
+/* GRAPHITE2 LICENSING
+
+ Copyright 2010, SIL International
+ All rights reserved.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of License, or
+ (at your option) any later version.
+
+ 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
+ Lesser General Public License for more details.
+
+ You should also have received a copy of the GNU Lesser General Public
+ License along with this library in the file named "LICENSE".
+ If not, write to the Free Software Foundation, 51 Franklin Street,
+ Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
+ internet at http://www.fsf.org/licenses/lgpl.html.
+
+Alternatively, the contents of this file may be used under the terms of the
+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+License, as published by the Free Software Foundation, either version 2
+of the License or (at your option) any later version.
+*/
+#pragma once
+// This file will be pulled into and integrated into a machine implmentation
+// DO NOT build directly and under no circumstances ever #include headers in
+// here or you will break the direct_machine.
+//
+// Implementers' notes
+// ==================
+// You have access to a few primitives and the full C++ code:
+// declare_params(n) Tells the interpreter how many bytes of parameter
+// space to claim for this instruction uses and
+// initialises the param pointer. You *must* before the
+// first use of param.
+// use_params(n) Claim n extra bytes of param space beyond what was
+// claimed using delcare_param.
+// param A const byte pointer for the parameter space claimed by
+// this instruction.
+// binop(op) Implement a binary operation on the stack using the
+// specified C++ operator.
+// NOT_IMPLEMENTED Any instruction body containing this will exit the
+// program with an assertion error. Instructions that are
+// not implemented should also be marked NILOP in the
+// opcodes tables this will cause the code class to spot
+// them in a live code stream and throw a runtime_error
+// instead.
+// push(n) Push the value n onto the stack.
+// pop() Pop the top most value and return it.
+//
+// You have access to the following named fast 'registers':
+// sp = The pointer to the current top of stack, the last value
+// pushed.
+// seg = A reference to the Segment this code is running over.
+// is = The current slot index
+// isb = The original base slot index at the start of this rule
+// isf = The first positioned slot
+// isl = The last positioned slot
+// ip = The current instruction pointer
+// endPos = Position of advance of last cluster
+// dir = writing system directionality of the font
+
+
+// #define NOT_IMPLEMENTED assert(false)
+// #define NOT_IMPLEMENTED
+
+#define binop(op) const uint32 a = pop(); *sp = uint32(*sp) op a
+#define sbinop(op) const int32 a = pop(); *sp = int32(*sp) op a
+#define use_params(n) dp += n
+
+#define declare_params(n) const byte * param = dp; \
+ use_params(n);
+
+#define push(n) { *++sp = n; }
+#define pop() (*sp--)
+#define slotat(x) (map[(x)])
+#define DIE { is=seg.last(); status = Machine::died_early; EXIT(1); }
+#define POSITIONED 1
+
+STARTOP(nop)
+ do {} while (0);
+ENDOP
+
+STARTOP(push_byte)
+ declare_params(1);
+ push(int8(*param));
+ENDOP
+
+STARTOP(push_byte_u)
+ declare_params(1);
+ push(uint8(*param));
+ENDOP
+
+STARTOP(push_short)
+ declare_params(2);
+ const int16 r = int16(param[0]) << 8
+ | uint8(param[1]);
+ push(r);
+ENDOP
+
+STARTOP(push_short_u)
+ declare_params(2);
+ const uint16 r = uint16(param[0]) << 8
+ | uint8(param[1]);
+ push(r);
+ENDOP
+
+STARTOP(push_long)
+ declare_params(4);
+ const int32 r = int32(param[0]) << 24
+ | uint32(param[1]) << 16
+ | uint32(param[2]) << 8
+ | uint8(param[3]);
+ push(r);
+ENDOP
+
+STARTOP(add)
+ binop(+);
+ENDOP
+
+STARTOP(sub)
+ binop(-);
+ENDOP
+
+STARTOP(mul)
+ binop(*);
+ENDOP
+
+STARTOP(div_)
+ const int32 b = pop();
+ const int32 a = int32(*sp);
+ if (b == 0 || (a == std::numeric_limits<int32>::min() && b == -1)) DIE;
+ *sp = int32(*sp) / b;
+ENDOP
+
+STARTOP(min_)
+ const int32 a = pop(), b = *sp;
+ if (a < b) *sp = a;
+ENDOP
+
+STARTOP(max_)
+ const int32 a = pop(), b = *sp;
+ if (a > b) *sp = a;
+ENDOP
+
+STARTOP(neg)
+ *sp = uint32(-int32(*sp));
+ENDOP
+
+STARTOP(trunc8)
+ *sp = uint8(*sp);
+ENDOP
+
+STARTOP(trunc16)
+ *sp = uint16(*sp);
+ENDOP
+
+STARTOP(cond)
+ const uint32 f = pop(), t = pop(), c = pop();
+ push(c ? t : f);
+ENDOP
+
+STARTOP(and_)
+ binop(&&);
+ENDOP
+
+STARTOP(or_)
+ binop(||);
+ENDOP
+
+STARTOP(not_)
+ *sp = !*sp;
+ENDOP
+
+STARTOP(equal)
+ binop(==);
+ENDOP
+
+STARTOP(not_eq_)
+ binop(!=);
+ENDOP
+
+STARTOP(less)
+ sbinop(<);
+ENDOP
+
+STARTOP(gtr)
+ sbinop(>);
+ENDOP
+
+STARTOP(less_eq)
+ sbinop(<=);
+ENDOP
+
+STARTOP(gtr_eq)
+ sbinop(>=);
+ENDOP
+
+STARTOP(next)
+ if (map - &smap[0] >= int(smap.size())) DIE
+ if (is)
+ {
+ if (is == smap.highwater())
+ smap.highpassed(true);
+ is = is->next();
+ }
+ ++map;
+ENDOP
+
+//STARTOP(next_n)
+// use_params(1);
+// NOT_IMPLEMENTED;
+ //declare_params(1);
+ //const size_t num = uint8(*param);
+//ENDOP
+
+//STARTOP(copy_next)
+// if (is) is = is->next();
+// ++map;
+// ENDOP
+
+STARTOP(put_glyph_8bit_obs)
+ declare_params(1);
+ const unsigned int output_class = uint8(*param);
+ is->setGlyph(&seg, seg.getClassGlyph(output_class, 0));
+ENDOP
+
+STARTOP(put_subs_8bit_obs)
+ declare_params(3);
+ const int slot_ref = int8(param[0]);
+ const unsigned int input_class = uint8(param[1]),
+ output_class = uint8(param[2]);
+ uint16 index;
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ index = seg.findClassIndex(input_class, slot->gid());
+ is->setGlyph(&seg, seg.getClassGlyph(output_class, index));
+ }
+ENDOP
+
+STARTOP(put_copy)
+ declare_params(1);
+ const int slot_ref = int8(*param);
+ if (is && !is->isDeleted())
+ {
+ slotref ref = slotat(slot_ref);
+ if (ref && ref != is)
+ {
+ int16 *tempUserAttrs = is->userAttrs();
+ if (is->attachedTo() || is->firstChild()) DIE
+ Slot *prev = is->prev();
+ Slot *next = is->next();
+ memcpy(tempUserAttrs, ref->userAttrs(), seg.numAttrs() * sizeof(uint16));
+ memcpy(is, ref, sizeof(Slot));
+ is->firstChild(NULL);
+ is->nextSibling(NULL);
+ is->userAttrs(tempUserAttrs);
+ is->next(next);
+ is->prev(prev);
+ if (is->attachedTo())
+ is->attachedTo()->child(is);
+ }
+ is->markCopied(false);
+ is->markDeleted(false);
+ }
+ENDOP
+
+STARTOP(insert)
+ if (smap.decMax() <= 0) DIE;
+ Slot *newSlot = seg.newSlot();
+ if (!newSlot) DIE;
+ Slot *iss = is;
+ while (iss && iss->isDeleted()) iss = iss->next();
+ if (!iss)
+ {
+ if (seg.last())
+ {
+ seg.last()->next(newSlot);
+ newSlot->prev(seg.last());
+ newSlot->before(seg.last()->before());
+ seg.last(newSlot);
+ }
+ else
+ {
+ seg.first(newSlot);
+ seg.last(newSlot);
+ }
+ }
+ else if (iss->prev())
+ {
+ iss->prev()->next(newSlot);
+ newSlot->prev(iss->prev());
+ newSlot->before(iss->prev()->after());
+ }
+ else
+ {
+ newSlot->prev(NULL);
+ newSlot->before(iss->before());
+ seg.first(newSlot);
+ }
+ newSlot->next(iss);
+ if (iss)
+ {
+ iss->prev(newSlot);
+ newSlot->originate(iss->original());
+ newSlot->after(iss->before());
+ }
+ else if (newSlot->prev())
+ {
+ newSlot->originate(newSlot->prev()->original());
+ newSlot->after(newSlot->prev()->after());
+ }
+ else
+ {
+ newSlot->originate(seg.defaultOriginal());
+ }
+ if (is == smap.highwater())
+ smap.highpassed(false);
+ is = newSlot;
+ seg.extendLength(1);
+ if (map != &smap[-1])
+ --map;
+ENDOP
+
+STARTOP(delete_)
+ if (!is || is->isDeleted()) DIE
+ is->markDeleted(true);
+ if (is->prev())
+ is->prev()->next(is->next());
+ else
+ seg.first(is->next());
+
+ if (is->next())
+ is->next()->prev(is->prev());
+ else
+ seg.last(is->prev());
+
+
+ if (is == smap.highwater())
+ smap.highwater(is->next());
+ if (is->prev())
+ is = is->prev();
+ seg.extendLength(-1);
+ENDOP
+
+STARTOP(assoc)
+ declare_params(1);
+ unsigned int num = uint8(*param);
+ const int8 * assocs = reinterpret_cast<const int8 *>(param+1);
+ use_params(num);
+ int max = -1;
+ int min = -1;
+
+ while (num-- > 0)
+ {
+ int sr = *assocs++;
+ slotref ts = slotat(sr);
+ if (ts && (min == -1 || ts->before() < min)) min = ts->before();
+ if (ts && ts->after() > max) max = ts->after();
+ }
+ if (min > -1) // implies max > -1
+ {
+ is->before(min);
+ is->after(max);
+ }
+ENDOP
+
+STARTOP(cntxt_item)
+ // It turns out this is a cunningly disguised condition forward jump.
+ declare_params(3);
+ const int is_arg = int8(param[0]);
+ const size_t iskip = uint8(param[1]),
+ dskip = uint8(param[2]);
+
+ if (mapb + is_arg != map)
+ {
+ ip += iskip;
+ dp += dskip;
+ push(true);
+ }
+ENDOP
+
+STARTOP(attr_set)
+ declare_params(1);
+ const attrCode slat = attrCode(uint8(*param));
+ const int val = pop();
+ is->setAttr(&seg, slat, 0, val, smap);
+ENDOP
+
+STARTOP(attr_add)
+ declare_params(1);
+ const attrCode slat = attrCode(uint8(*param));
+ const uint32_t val = pop();
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ uint32_t res = uint32_t(is->getAttr(&seg, slat, 0));
+ is->setAttr(&seg, slat, 0, int32_t(val + res), smap);
+ENDOP
+
+STARTOP(attr_sub)
+ declare_params(1);
+ const attrCode slat = attrCode(uint8(*param));
+ const uint32_t val = pop();
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ uint32_t res = uint32_t(is->getAttr(&seg, slat, 0));
+ is->setAttr(&seg, slat, 0, int32_t(res - val), smap);
+ENDOP
+
+STARTOP(attr_set_slot)
+ declare_params(1);
+ const attrCode slat = attrCode(uint8(*param));
+ const int offset = int(map - smap.begin())*int(slat == gr_slatAttTo);
+ const int val = pop() + offset;
+ is->setAttr(&seg, slat, offset, val, smap);
+ENDOP
+
+STARTOP(iattr_set_slot)
+ declare_params(2);
+ const attrCode slat = attrCode(uint8(param[0]));
+ const uint8 idx = uint8(param[1]);
+ const int val = int(pop() + (map - smap.begin())*int(slat == gr_slatAttTo));
+ is->setAttr(&seg, slat, idx, val, smap);
+ENDOP
+
+STARTOP(push_slot_attr)
+ declare_params(2);
+ const attrCode slat = attrCode(uint8(param[0]));
+ const int slot_ref = int8(param[1]);
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ int res = slot->getAttr(&seg, slat, 0);
+ push(res);
+ }
+ENDOP
+
+STARTOP(push_glyph_attr_obs)
+ declare_params(2);
+ const unsigned int glyph_attr = uint8(param[0]);
+ const int slot_ref = int8(param[1]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
+ENDOP
+
+STARTOP(push_glyph_metric)
+ declare_params(3);
+ const unsigned int glyph_attr = uint8(param[0]);
+ const int slot_ref = int8(param[1]);
+ const signed int attr_level = uint8(param[2]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ push(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir));
+ENDOP
+
+STARTOP(push_feat)
+ declare_params(2);
+ const unsigned int feat = uint8(param[0]);
+ const int slot_ref = int8(param[1]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ uint8 fid = seg.charinfo(slot->original())->fid();
+ push(seg.getFeature(fid, feat));
+ }
+ENDOP
+
+STARTOP(push_att_to_gattr_obs)
+ declare_params(2);
+ const unsigned int glyph_attr = uint8(param[0]);
+ const int slot_ref = int8(param[1]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ slotref att = slot->attachedTo();
+ if (att) slot = att;
+ push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
+ }
+ENDOP
+
+STARTOP(push_att_to_glyph_metric)
+ declare_params(3);
+ const unsigned int glyph_attr = uint8(param[0]);
+ const int slot_ref = int8(param[1]);
+ const signed int attr_level = uint8(param[2]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ slotref att = slot->attachedTo();
+ if (att) slot = att;
+ push(int32(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir)));
+ }
+ENDOP
+
+STARTOP(push_islot_attr)
+ declare_params(3);
+ const attrCode slat = attrCode(uint8(param[0]));
+ const int slot_ref = int8(param[1]),
+ idx = uint8(param[2]);
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ int res = slot->getAttr(&seg, slat, idx);
+ push(res);
+ }
+ENDOP
+
+#if 0
+STARTOP(push_iglyph_attr) // not implemented
+ NOT_IMPLEMENTED;
+ENDOP
+#endif
+
+STARTOP(pop_ret)
+ const uint32 ret = pop();
+ EXIT(ret);
+ENDOP
+
+STARTOP(ret_zero)
+ EXIT(0);
+ENDOP
+
+STARTOP(ret_true)
+ EXIT(1);
+ENDOP
+
+STARTOP(iattr_set)
+ declare_params(2);
+ const attrCode slat = attrCode(uint8(param[0]));
+ const uint8 idx = uint8(param[1]);
+ const int val = pop();
+ is->setAttr(&seg, slat, idx, val, smap);
+ENDOP
+
+STARTOP(iattr_add)
+ declare_params(2);
+ const attrCode slat = attrCode(uint8(param[0]));
+ const uint8 idx = uint8(param[1]);
+ const uint32_t val = pop();
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ uint32_t res = uint32_t(is->getAttr(&seg, slat, idx));
+ is->setAttr(&seg, slat, idx, int32_t(val + res), smap);
+ENDOP
+
+STARTOP(iattr_sub)
+ declare_params(2);
+ const attrCode slat = attrCode(uint8(param[0]));
+ const uint8 idx = uint8(param[1]);
+ const uint32_t val = pop();
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ uint32_t res = uint32_t(is->getAttr(&seg, slat, idx));
+ is->setAttr(&seg, slat, idx, int32_t(res - val), smap);
+ENDOP
+
+STARTOP(push_proc_state)
+ use_params(1);
+ push(1);
+ENDOP
+
+STARTOP(push_version)
+ push(0x00030000);
+ENDOP
+
+STARTOP(put_subs)
+ declare_params(5);
+ const int slot_ref = int8(param[0]);
+ const unsigned int input_class = uint8(param[1]) << 8
+ | uint8(param[2]);
+ const unsigned int output_class = uint8(param[3]) << 8
+ | uint8(param[4]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ int index = seg.findClassIndex(input_class, slot->gid());
+ is->setGlyph(&seg, seg.getClassGlyph(output_class, index));
+ }
+ENDOP
+
+#if 0
+STARTOP(put_subs2) // not implemented
+ NOT_IMPLEMENTED;
+ENDOP
+
+STARTOP(put_subs3) // not implemented
+ NOT_IMPLEMENTED;
+ENDOP
+#endif
+
+STARTOP(put_glyph)
+ declare_params(2);
+ const unsigned int output_class = uint8(param[0]) << 8
+ | uint8(param[1]);
+ is->setGlyph(&seg, seg.getClassGlyph(output_class, 0));
+ENDOP
+
+STARTOP(push_glyph_attr)
+ declare_params(3);
+ const unsigned int glyph_attr = uint8(param[0]) << 8
+ | uint8(param[1]);
+ const int slot_ref = int8(param[2]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
+ENDOP
+
+STARTOP(push_att_to_glyph_attr)
+ declare_params(3);
+ const unsigned int glyph_attr = uint8(param[0]) << 8
+ | uint8(param[1]);
+ const int slot_ref = int8(param[2]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ slotref att = slot->attachedTo();
+ if (att) slot = att;
+ push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
+ }
+ENDOP
+
+STARTOP(temp_copy)
+ slotref newSlot = seg.newSlot();
+ if (!newSlot || !is) DIE;
+ int16 *tempUserAttrs = newSlot->userAttrs();
+ memcpy(newSlot, is, sizeof(Slot));
+ memcpy(tempUserAttrs, is->userAttrs(), seg.numAttrs() * sizeof(uint16));
+ newSlot->userAttrs(tempUserAttrs);
+ newSlot->markCopied(true);
+ *map = newSlot;
+ENDOP
+
+STARTOP(band)
+ binop(&);
+ENDOP
+
+STARTOP(bor)
+ binop(|);
+ENDOP
+
+STARTOP(bnot)
+ *sp = ~*sp;
+ENDOP
+
+STARTOP(setbits)
+ declare_params(4);
+ const uint16 m = uint16(param[0]) << 8
+ | uint8(param[1]);
+ const uint16 v = uint16(param[2]) << 8
+ | uint8(param[3]);
+ *sp = ((*sp) & ~m) | v;
+ENDOP
+
+STARTOP(set_feat)
+ declare_params(2);
+ const unsigned int feat = uint8(param[0]);
+ const int slot_ref = int8(param[1]);
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ uint8 fid = seg.charinfo(slot->original())->fid();
+ seg.setFeature(fid, feat, pop());
+ }
+ENDOP