1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/graphite2/src/inc/opcodes.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,646 @@ 1.4 +/* GRAPHITE2 LICENSING 1.5 + 1.6 + Copyright 2010, SIL International 1.7 + All rights reserved. 1.8 + 1.9 + This library is free software; you can redistribute it and/or modify 1.10 + it under the terms of the GNU Lesser General Public License as published 1.11 + by the Free Software Foundation; either version 2.1 of License, or 1.12 + (at your option) any later version. 1.13 + 1.14 + This program is distributed in the hope that it will be useful, 1.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of 1.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.17 + Lesser General Public License for more details. 1.18 + 1.19 + You should also have received a copy of the GNU Lesser General Public 1.20 + License along with this library in the file named "LICENSE". 1.21 + If not, write to the Free Software Foundation, 51 Franklin Street, 1.22 + Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 1.23 + internet at http://www.fsf.org/licenses/lgpl.html. 1.24 + 1.25 +Alternatively, the contents of this file may be used under the terms of the 1.26 +Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public 1.27 +License, as published by the Free Software Foundation, either version 2 1.28 +of the License or (at your option) any later version. 1.29 +*/ 1.30 +#pragma once 1.31 +// This file will be pulled into and integrated into a machine implmentation 1.32 +// DO NOT build directly and under no circumstances every #include headers in 1.33 +// here or you will break the direct_machine. 1.34 +// 1.35 +// Implementers' notes 1.36 +// ================== 1.37 +// You have access to a few primitives and the full C++ code: 1.38 +// declare_params(n) Tells the interpreter how many bytes of parameter 1.39 +// space to claim for this instruction uses and 1.40 +// initialises the param pointer. You *must* before the 1.41 +// first use of param. 1.42 +// use_params(n) Claim n extra bytes of param space beyond what was 1.43 +// claimed using delcare_param. 1.44 +// param A const byte pointer for the parameter space claimed by 1.45 +// this instruction. 1.46 +// binop(op) Implement a binary operation on the stack using the 1.47 +// specified C++ operator. 1.48 +// NOT_IMPLEMENTED Any instruction body containing this will exit the 1.49 +// program with an assertion error. Instructions that are 1.50 +// not implemented should also be marked NILOP in the 1.51 +// opcodes tables this will cause the code class to spot 1.52 +// them in a live code stream and throw a runtime_error 1.53 +// instead. 1.54 +// push(n) Push the value n onto the stack. 1.55 +// pop() Pop the top most value and return it. 1.56 +// 1.57 +// You have access to the following named fast 'registers': 1.58 +// sp = The pointer to the current top of stack, the last value 1.59 +// pushed. 1.60 +// seg = A reference to the Segment this code is running over. 1.61 +// is = The current slot index 1.62 +// isb = The original base slot index at the start of this rule 1.63 +// isf = The first positioned slot 1.64 +// isl = The last positioned slot 1.65 +// ip = The current instruction pointer 1.66 +// endPos = Position of advance of last cluster 1.67 + 1.68 + 1.69 +// #define NOT_IMPLEMENTED assert(false) 1.70 +#define NOT_IMPLEMENTED 1.71 + 1.72 +#define binop(op) const int32 a = pop(); *sp = int32(*sp) op a 1.73 +#define use_params(n) dp += n 1.74 + 1.75 +#define declare_params(n) const byte * param = dp; \ 1.76 + use_params(n); 1.77 + 1.78 +#define push(n) { *++sp = n; } 1.79 +#define pop() (*sp--) 1.80 +#define slotat(x) (map[(x)]) 1.81 +#define DIE { is=seg.last(); EXIT(1); } 1.82 +#define POSITIONED 1 1.83 + 1.84 +STARTOP(nop) 1.85 + do {} while (0); 1.86 +ENDOP 1.87 + 1.88 +STARTOP(push_byte) 1.89 + declare_params(1); 1.90 + push(int8(*param)); 1.91 +ENDOP 1.92 + 1.93 +STARTOP(push_byte_u) 1.94 + declare_params(1); 1.95 + push(uint8(*param)); 1.96 +ENDOP 1.97 + 1.98 +STARTOP(push_short) 1.99 + declare_params(2); 1.100 + const int16 r = int16(param[0]) << 8 1.101 + | uint8(param[1]); 1.102 + push(r); 1.103 +ENDOP 1.104 + 1.105 +STARTOP(push_short_u) 1.106 + declare_params(2); 1.107 + const uint16 r = uint16(param[0]) << 8 1.108 + | uint8(param[1]); 1.109 + push(r); 1.110 +ENDOP 1.111 + 1.112 +STARTOP(push_long) 1.113 + declare_params(4); 1.114 + const int32 r = int32(param[0]) << 24 1.115 + | uint32(param[1]) << 16 1.116 + | uint32(param[2]) << 8 1.117 + | uint8(param[3]); 1.118 + push(r); 1.119 +ENDOP 1.120 + 1.121 +STARTOP(add) 1.122 + binop(+); 1.123 +ENDOP 1.124 + 1.125 +STARTOP(sub) 1.126 + binop(-); 1.127 +ENDOP 1.128 + 1.129 +STARTOP(mul) 1.130 + binop(*); 1.131 +ENDOP 1.132 + 1.133 +STARTOP(div_) 1.134 + if (*sp == 0) DIE; 1.135 + binop(/); 1.136 +ENDOP 1.137 + 1.138 +STARTOP(min_) 1.139 + const int32 a = pop(), b = *sp; 1.140 + if (a < b) *sp = a; 1.141 +ENDOP 1.142 + 1.143 +STARTOP(max_) 1.144 + const int32 a = pop(), b = *sp; 1.145 + if (a > b) *sp = a; 1.146 +ENDOP 1.147 + 1.148 +STARTOP(neg) 1.149 + *sp = uint32(-int32(*sp)); 1.150 +ENDOP 1.151 + 1.152 +STARTOP(trunc8) 1.153 + *sp = uint8(*sp); 1.154 +ENDOP 1.155 + 1.156 +STARTOP(trunc16) 1.157 + *sp = uint16(*sp); 1.158 +ENDOP 1.159 + 1.160 +STARTOP(cond) 1.161 + const uint32 f = pop(), t = pop(), c = pop(); 1.162 + push(c ? t : f); 1.163 +ENDOP 1.164 + 1.165 +STARTOP(and_) 1.166 + binop(&&); 1.167 +ENDOP 1.168 + 1.169 +STARTOP(or_) 1.170 + binop(||); 1.171 +ENDOP 1.172 + 1.173 +STARTOP(not_) 1.174 + *sp = !*sp; 1.175 +ENDOP 1.176 + 1.177 +STARTOP(equal) 1.178 + binop(==); 1.179 +ENDOP 1.180 + 1.181 +STARTOP(not_eq_) 1.182 + binop(!=); 1.183 +ENDOP 1.184 + 1.185 +STARTOP(less) 1.186 + binop(<); 1.187 +ENDOP 1.188 + 1.189 +STARTOP(gtr) 1.190 + binop(>); 1.191 +ENDOP 1.192 + 1.193 +STARTOP(less_eq) 1.194 + binop(<=); 1.195 +ENDOP 1.196 + 1.197 +STARTOP(gtr_eq) 1.198 + binop(>=); 1.199 +ENDOP 1.200 + 1.201 +STARTOP(next) 1.202 + if (map - &smap[0] >= int(smap.size())) DIE 1.203 + if (is) 1.204 + { 1.205 + if (is == smap.highwater()) 1.206 + smap.highpassed(true); 1.207 + is = is->next(); 1.208 + } 1.209 + ++map; 1.210 +ENDOP 1.211 + 1.212 +STARTOP(next_n) 1.213 + use_params(1); 1.214 + NOT_IMPLEMENTED; 1.215 + //declare_params(1); 1.216 + //const size_t num = uint8(*param); 1.217 +ENDOP 1.218 + 1.219 +//STARTOP(copy_next) 1.220 +// if (is) is = is->next(); 1.221 +// ++map; 1.222 +// ENDOP 1.223 + 1.224 +STARTOP(put_glyph_8bit_obs) 1.225 + declare_params(1); 1.226 + const unsigned int output_class = uint8(*param); 1.227 + is->setGlyph(&seg, seg.getClassGlyph(output_class, 0)); 1.228 +ENDOP 1.229 + 1.230 +STARTOP(put_subs_8bit_obs) 1.231 + declare_params(3); 1.232 + const int slot_ref = int8(param[0]); 1.233 + const unsigned int input_class = uint8(param[1]), 1.234 + output_class = uint8(param[2]); 1.235 + uint16 index; 1.236 + slotref slot = slotat(slot_ref); 1.237 + if (slot) 1.238 + { 1.239 + index = seg.findClassIndex(input_class, slot->gid()); 1.240 + is->setGlyph(&seg, seg.getClassGlyph(output_class, index)); 1.241 + } 1.242 +ENDOP 1.243 + 1.244 +STARTOP(put_copy) 1.245 + declare_params(1); 1.246 + const int slot_ref = int8(*param); 1.247 + if (is && (slot_ref ||is != *map)) 1.248 + { 1.249 + int16 *tempUserAttrs = is->userAttrs(); 1.250 + slotref ref = slotat(slot_ref); 1.251 + if (ref) 1.252 + { 1.253 + memcpy(tempUserAttrs, ref->userAttrs(), seg.numAttrs() * sizeof(uint16)); 1.254 + Slot *prev = is->prev(); 1.255 + Slot *next = is->next(); 1.256 + memcpy(is, slotat(slot_ref), sizeof(Slot)); 1.257 + is->userAttrs(tempUserAttrs); 1.258 + is->next(next); 1.259 + is->prev(prev); 1.260 + is->sibling(NULL); 1.261 + } 1.262 + is->markCopied(false); 1.263 + is->markDeleted(false); 1.264 + } 1.265 +ENDOP 1.266 + 1.267 +STARTOP(insert) 1.268 + Slot *newSlot = seg.newSlot(); 1.269 + if (!newSlot) DIE; 1.270 + Slot *iss = is; 1.271 + while (iss && iss->isDeleted()) iss = iss->next(); 1.272 + if (!iss) 1.273 + { 1.274 + if (seg.last()) 1.275 + { 1.276 + seg.last()->next(newSlot); 1.277 + newSlot->prev(seg.last()); 1.278 + newSlot->before(seg.last()->before()); 1.279 + seg.last(newSlot); 1.280 + } 1.281 + else 1.282 + { 1.283 + seg.first(newSlot); 1.284 + seg.last(newSlot); 1.285 + } 1.286 + } 1.287 + else if (iss->prev()) 1.288 + { 1.289 + iss->prev()->next(newSlot); 1.290 + newSlot->prev(iss->prev()); 1.291 + newSlot->before(iss->prev()->after()); 1.292 + } 1.293 + else 1.294 + { 1.295 + newSlot->prev(NULL); 1.296 + newSlot->before(iss->before()); 1.297 + seg.first(newSlot); 1.298 + } 1.299 + newSlot->next(iss); 1.300 + if (iss) 1.301 + { 1.302 + iss->prev(newSlot); 1.303 + newSlot->originate(iss->original()); 1.304 + newSlot->after(iss->before()); 1.305 + } 1.306 + else if (newSlot->prev()) 1.307 + { 1.308 + newSlot->originate(newSlot->prev()->original()); 1.309 + newSlot->after(newSlot->prev()->after()); 1.310 + } 1.311 + else 1.312 + { 1.313 + newSlot->originate(seg.defaultOriginal()); 1.314 + } 1.315 + is = newSlot; 1.316 + seg.extendLength(1); 1.317 + if (map != &smap[-1]) 1.318 + --map; 1.319 +ENDOP 1.320 + 1.321 +STARTOP(delete_) 1.322 + if (!is) DIE 1.323 + is->markDeleted(true); 1.324 + if (is->prev()) 1.325 + is->prev()->next(is->next()); 1.326 + else 1.327 + seg.first(is->next()); 1.328 + 1.329 + if (is->next()) 1.330 + is->next()->prev(is->prev()); 1.331 + else 1.332 + seg.last(is->prev()); 1.333 + 1.334 + if (is == smap.highwater()) 1.335 + smap.highwater(is->next()); 1.336 + if (is->prev()) 1.337 + is = is->prev(); 1.338 + seg.extendLength(-1); 1.339 +ENDOP 1.340 + 1.341 +STARTOP(assoc) 1.342 + declare_params(1); 1.343 + unsigned int num = uint8(*param); 1.344 + const int8 * assocs = reinterpret_cast<const int8 *>(param+1); 1.345 + use_params(num); 1.346 + int max = -1; 1.347 + int min = -1; 1.348 + 1.349 + while (num-- > 0) 1.350 + { 1.351 + int sr = *assocs++; 1.352 + slotref ts = slotat(sr); 1.353 + if (ts && (min == -1 || ts->before() < min)) min = ts->before(); 1.354 + if (ts && ts->after() > max) max = ts->after(); 1.355 + } 1.356 + if (min > -1) // implies max > -1 1.357 + { 1.358 + is->before(min); 1.359 + is->after(max); 1.360 + } 1.361 +ENDOP 1.362 + 1.363 +STARTOP(cntxt_item) 1.364 + // It turns out this is a cunningly disguised condition forward jump. 1.365 + declare_params(3); 1.366 + const int is_arg = int8(param[0]); 1.367 + const size_t iskip = uint8(param[1]), 1.368 + dskip = uint8(param[2]); 1.369 + 1.370 + if (mapb + is_arg != map) 1.371 + { 1.372 + ip += iskip; 1.373 + dp += dskip; 1.374 + push(true); 1.375 + } 1.376 +ENDOP 1.377 + 1.378 +STARTOP(attr_set) 1.379 + declare_params(1); 1.380 + const attrCode slat = attrCode(uint8(*param)); 1.381 + const int val = int(pop()); 1.382 + is->setAttr(&seg, slat, 0, val, smap); 1.383 +ENDOP 1.384 + 1.385 +STARTOP(attr_add) 1.386 + declare_params(1); 1.387 + const attrCode slat = attrCode(uint8(*param)); 1.388 + const int val = int(pop()); 1.389 + if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0) 1.390 + { 1.391 + seg.positionSlots(0, *smap.begin(), *(smap.end()-1)); 1.392 + flags |= POSITIONED; 1.393 + } 1.394 + int res = is->getAttr(&seg, slat, 0); 1.395 + is->setAttr(&seg, slat, 0, val + res, smap); 1.396 +ENDOP 1.397 + 1.398 +STARTOP(attr_sub) 1.399 + declare_params(1); 1.400 + const attrCode slat = attrCode(uint8(*param)); 1.401 + const int val = int(pop()); 1.402 + if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0) 1.403 + { 1.404 + seg.positionSlots(0, *smap.begin(), *(smap.end()-1)); 1.405 + flags |= POSITIONED; 1.406 + } 1.407 + int res = is->getAttr(&seg, slat, 0); 1.408 + is->setAttr(&seg, slat, 0, res - val, smap); 1.409 +ENDOP 1.410 + 1.411 +STARTOP(attr_set_slot) 1.412 + declare_params(1); 1.413 + const attrCode slat = attrCode(uint8(*param)); 1.414 + const int offset = (map - smap.begin())*int(slat == gr_slatAttTo); 1.415 + const int val = int(pop()) + offset; 1.416 + is->setAttr(&seg, slat, offset, val, smap); 1.417 +ENDOP 1.418 + 1.419 +STARTOP(iattr_set_slot) 1.420 + declare_params(2); 1.421 + const attrCode slat = attrCode(uint8(param[0])); 1.422 + const size_t idx = uint8(param[1]); 1.423 + const int val = int(pop()) + (map - smap.begin())*int(slat == gr_slatAttTo); 1.424 + is->setAttr(&seg, slat, idx, val, smap); 1.425 +ENDOP 1.426 + 1.427 +STARTOP(push_slot_attr) 1.428 + declare_params(2); 1.429 + const attrCode slat = attrCode(uint8(param[0])); 1.430 + const int slot_ref = int8(param[1]); 1.431 + if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0) 1.432 + { 1.433 + seg.positionSlots(0, *smap.begin(), *(smap.end()-1)); 1.434 + flags |= POSITIONED; 1.435 + } 1.436 + slotref slot = slotat(slot_ref); 1.437 + if (slot) 1.438 + { 1.439 + int res = slot->getAttr(&seg, slat, 0); 1.440 + push(res); 1.441 + } 1.442 +ENDOP 1.443 + 1.444 +STARTOP(push_glyph_attr_obs) 1.445 + declare_params(2); 1.446 + const unsigned int glyph_attr = uint8(param[0]); 1.447 + const int slot_ref = int8(param[1]); 1.448 + slotref slot = slotat(slot_ref); 1.449 + if (slot) 1.450 + push(int32(seg.glyphAttr(slot->gid(), glyph_attr))); 1.451 +ENDOP 1.452 + 1.453 +STARTOP(push_glyph_metric) 1.454 + declare_params(3); 1.455 + const unsigned int glyph_attr = uint8(param[0]); 1.456 + const int slot_ref = int8(param[1]); 1.457 + const signed int attr_level = uint8(param[2]); 1.458 + slotref slot = slotat(slot_ref); 1.459 + if (slot) 1.460 + push(seg.getGlyphMetric(slot, glyph_attr, attr_level)); 1.461 +ENDOP 1.462 + 1.463 +STARTOP(push_feat) 1.464 + declare_params(2); 1.465 + const unsigned int feat = uint8(param[0]); 1.466 + const int slot_ref = int8(param[1]); 1.467 + slotref slot = slotat(slot_ref); 1.468 + if (slot) 1.469 + { 1.470 + uint8 fid = seg.charinfo(slot->original())->fid(); 1.471 + push(seg.getFeature(fid, feat)); 1.472 + } 1.473 +ENDOP 1.474 + 1.475 +STARTOP(push_att_to_gattr_obs) 1.476 + declare_params(2); 1.477 + const unsigned int glyph_attr = uint8(param[0]); 1.478 + const int slot_ref = int8(param[1]); 1.479 + slotref slot = slotat(slot_ref); 1.480 + if (slot) 1.481 + { 1.482 + slotref att = slot->attachedTo(); 1.483 + if (att) slot = att; 1.484 + push(int32(seg.glyphAttr(slot->gid(), glyph_attr))); 1.485 + } 1.486 +ENDOP 1.487 + 1.488 +STARTOP(push_att_to_glyph_metric) 1.489 + declare_params(3); 1.490 + const unsigned int glyph_attr = uint8(param[0]); 1.491 + const int slot_ref = int8(param[1]); 1.492 + const signed int attr_level = uint8(param[2]); 1.493 + slotref slot = slotat(slot_ref); 1.494 + if (slot) 1.495 + { 1.496 + slotref att = slot->attachedTo(); 1.497 + if (att) slot = att; 1.498 + push(int32(seg.getGlyphMetric(slot, glyph_attr, attr_level))); 1.499 + } 1.500 +ENDOP 1.501 + 1.502 +STARTOP(push_islot_attr) 1.503 + declare_params(3); 1.504 + const attrCode slat = attrCode(uint8(param[0])); 1.505 + const int slot_ref = int8(param[1]), 1.506 + idx = uint8(param[2]); 1.507 + if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0) 1.508 + { 1.509 + seg.positionSlots(0, *smap.begin(), *(smap.end()-1)); 1.510 + flags |= POSITIONED; 1.511 + } 1.512 + slotref slot = slotat(slot_ref); 1.513 + if (slot) 1.514 + { 1.515 + int res = slot->getAttr(&seg, slat, idx); 1.516 + push(res); 1.517 + } 1.518 +ENDOP 1.519 + 1.520 +#if 0 1.521 +STARTOP(push_iglyph_attr) // not implemented 1.522 + NOT_IMPLEMENTED; 1.523 +ENDOP 1.524 +#endif 1.525 + 1.526 +STARTOP(pop_ret) 1.527 + const uint32 ret = pop(); 1.528 + EXIT(ret); 1.529 +ENDOP 1.530 + 1.531 +STARTOP(ret_zero) 1.532 + EXIT(0); 1.533 +ENDOP 1.534 + 1.535 +STARTOP(ret_true) 1.536 + EXIT(1); 1.537 +ENDOP 1.538 + 1.539 +STARTOP(iattr_set) 1.540 + declare_params(2); 1.541 + const attrCode slat = attrCode(uint8(param[0])); 1.542 + const size_t idx = uint8(param[1]); 1.543 + const int val = int(pop()); 1.544 + is->setAttr(&seg, slat, idx, val, smap); 1.545 +ENDOP 1.546 + 1.547 +STARTOP(iattr_add) 1.548 + declare_params(2); 1.549 + const attrCode slat = attrCode(uint8(param[0])); 1.550 + const size_t idx = uint8(param[1]); 1.551 + const int val = int(pop()); 1.552 + if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0) 1.553 + { 1.554 + seg.positionSlots(0, *smap.begin(), *(smap.end()-1)); 1.555 + flags |= POSITIONED; 1.556 + } 1.557 + int res = is->getAttr(&seg, slat, idx); 1.558 + is->setAttr(&seg, slat, idx, val + res, smap); 1.559 +ENDOP 1.560 + 1.561 +STARTOP(iattr_sub) 1.562 + declare_params(2); 1.563 + const attrCode slat = attrCode(uint8(param[0])); 1.564 + const size_t idx = uint8(param[1]); 1.565 + const int val = int(pop()); 1.566 + if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0) 1.567 + { 1.568 + seg.positionSlots(0, *smap.begin(), *(smap.end()-1)); 1.569 + flags |= POSITIONED; 1.570 + } 1.571 + int res = is->getAttr(&seg, slat, idx); 1.572 + is->setAttr(&seg, slat, idx, res - val, smap); 1.573 +ENDOP 1.574 + 1.575 +STARTOP(push_proc_state) 1.576 + use_params(1); 1.577 + push(1); 1.578 +ENDOP 1.579 + 1.580 +STARTOP(push_version) 1.581 + push(0x00030000); 1.582 +ENDOP 1.583 + 1.584 +STARTOP(put_subs) 1.585 + declare_params(5); 1.586 + const int slot_ref = int8(param[0]); 1.587 + const unsigned int input_class = uint8(param[1]) << 8 1.588 + | uint8(param[2]); 1.589 + const unsigned int output_class = uint8(param[3]) << 8 1.590 + | uint8(param[4]); 1.591 + slotref slot = slotat(slot_ref); 1.592 + if (slot) 1.593 + { 1.594 + int index = seg.findClassIndex(input_class, slot->gid()); 1.595 + is->setGlyph(&seg, seg.getClassGlyph(output_class, index)); 1.596 + } 1.597 +ENDOP 1.598 + 1.599 +#if 0 1.600 +STARTOP(put_subs2) // not implemented 1.601 + NOT_IMPLEMENTED; 1.602 +ENDOP 1.603 + 1.604 +STARTOP(put_subs3) // not implemented 1.605 + NOT_IMPLEMENTED; 1.606 +ENDOP 1.607 +#endif 1.608 + 1.609 +STARTOP(put_glyph) 1.610 + declare_params(2); 1.611 + const unsigned int output_class = uint8(param[0]) << 8 1.612 + | uint8(param[1]); 1.613 + is->setGlyph(&seg, seg.getClassGlyph(output_class, 0)); 1.614 +ENDOP 1.615 + 1.616 +STARTOP(push_glyph_attr) 1.617 + declare_params(3); 1.618 + const unsigned int glyph_attr = uint8(param[0]) << 8 1.619 + | uint8(param[1]); 1.620 + const int slot_ref = int8(param[2]); 1.621 + slotref slot = slotat(slot_ref); 1.622 + if (slot) 1.623 + push(int32(seg.glyphAttr(slot->gid(), glyph_attr))); 1.624 +ENDOP 1.625 + 1.626 +STARTOP(push_att_to_glyph_attr) 1.627 + declare_params(3); 1.628 + const unsigned int glyph_attr = uint8(param[0]) << 8 1.629 + | uint8(param[1]); 1.630 + const int slot_ref = int8(param[2]); 1.631 + slotref slot = slotat(slot_ref); 1.632 + if (slot) 1.633 + { 1.634 + slotref att = slot->attachedTo(); 1.635 + if (att) slot = att; 1.636 + push(int32(seg.glyphAttr(slot->gid(), glyph_attr))); 1.637 + } 1.638 +ENDOP 1.639 + 1.640 +STARTOP(temp_copy) 1.641 + slotref newSlot = seg.newSlot(); 1.642 + if (!newSlot) DIE; 1.643 + int16 *tempUserAttrs = newSlot->userAttrs(); 1.644 + memcpy(newSlot, is, sizeof(Slot)); 1.645 + memcpy(tempUserAttrs, is->userAttrs(), seg.numAttrs() * sizeof(uint16)); 1.646 + newSlot->userAttrs(tempUserAttrs); 1.647 + newSlot->markCopied(true); 1.648 + *map = newSlot; 1.649 +ENDOP