fixed_t FV_Distance(const vector_t *p1, const vector_t *p2) { INT32 xs = FixedMul(p2->x-p1->x,p2->x-p1->x); INT32 ys = FixedMul(p2->y-p1->y,p2->y-p1->y); INT32 zs = FixedMul(p2->z-p1->z,p2->z-p1->z); return FixedSqrt(xs+ys+zs); }
fixed_t FV_Magnitude(const vector_t *a_normal) { INT32 xs = FixedMul(a_normal->x,a_normal->x); INT32 ys = FixedMul(a_normal->y,a_normal->y); INT32 zs = FixedMul(a_normal->z,a_normal->z); return FixedSqrt(xs+ys+zs); }
fixed_t FixedHypot(fixed_t x, fixed_t y) { #ifdef HAVE_HYPOT const float fx = FIXED_TO_FLOAT(x); const float fy = FIXED_TO_FLOAT(y); float fz; #ifdef HAVE_HYPOTF fz = hypotf(fx, fy); #else fz = (float)hypot(fx, fy); #endif return FLOAT_TO_FIXED(fz); #else // !HAVE_HYPOT fixed_t ax, yx, yx2, yx1; if (abs(y) > abs(x)) // |y|>|x| { ax = abs(y); // |y| => ax yx = FixedDiv(x, y); // (x/y) } else // |x|>|y| { ax = abs(x); // |x| => ax yx = FixedDiv(y, x); // (x/y) } yx2 = FixedMul(yx, yx); // (x/y)^2 yx1 = FixedSqrt(1+FRACUNIT + yx2); // (1 + (x/y)^2)^1/2 return FixedMul(ax, yx1); // |x|*((1 + (x/y)^2)^1/2) #endif }
// // IntersectRaySphere // Input : rO - origin of ray in world space // rV - vector describing direction of ray in world space // sO - Origin of sphere // sR - radius of sphere // Notes : Normalized directional vectors expected // Return: distance to sphere in world units, -1 if no intersection. // fixed_t FV_IntersectRaySphere(const vector_t *rO, const vector_t *rV, const vector_t *sO, fixed_t sR) { vector_t Q; fixed_t c, v, d; FV_SubEx(sO, rO, &Q); c = FV_Magnitude(&Q); v = FV_Dot(&Q, rV); d = FixedMul(sR, sR) - (FixedMul(c,c) - FixedMul(v,v)); // If there was no intersection, return -1 if (d < 0*FRACUNIT) return (-1*FRACUNIT); // Return the distance to the [first] intersecting point return (v - FixedSqrt(d)); }
/* Read Type 13 charstring. Initial seek to offset performed if offset != -1 */ static void t13Read(cffCtx h, Offset offset, int init, int csLen) { unsigned length; switch (init) { case cstr_GLYPH: /* Initialize glyph charstring */ h->stack.cnt = 0; h->path.nStems = 0; h->path.flags = GET_WIDTH|FIRST_MOVE|FIRST_MASK; break; case cstr_DICT: /* Initialize DICT charstring */ h->path.flags = DICT_CSTR; break; case cstr_METRIC: /* Initialize metric charstring */ h->stack.cnt = 0; h->path.flags = 0; break; } if (offset != -1) /* Seek to position of charstring if not already positioned */ seekbyte(h, offset); for (;;) { int j; Fixed a; Fixed b; int byte0 = GETBYTE(h); switch (byte0) { case t13_endchar: if (!(h->path.flags & DICT_CSTR)) { if (h->path.flags & FIRST_MOVE) { /* Non-marking glyph; set bounds */ h->path.left = h->path.right = 0; h->path.bottom = h->path.top = 0; } if ((h->path.flags & GET_WIDTH) && setAdvance(h)) return; /* Stop after getting width */ if (h->stack.cnt > 1) { /* Process seac components */ int base; int accent; j = (h->stack.cnt == 4)? 0: 1; a = indexFix(h, j++); b = indexFix(h, j++); base = indexInt(h, j++); accent = indexInt(h, j); setComponentBounds(h, 0, base, 0, 0); setComponentBounds(h, 1, accent, a, b); } } PATH_FUNC_CALL(endchar,(h->cb.ctx)); h->path.flags |= SEEN_END; return; case t13_reserved0: case t13_reserved236: case t13_reserved237: case t13_reserved244: case t13_reserved255: fatal(h, "reserved charstring op"); case t13_rlineto: for (j = 0; j < h->stack.cnt; j += 2) addLine(h, indexFix(h, j + 0), indexFix(h, j + 1)); h->stack.cnt = 0; break; case t13_hlineto: case t13_vlineto: { int horz = byte0 == t13_hlineto; for (j = 0; j < h->stack.cnt; j++) if (horz++ & 1) addLine(h, indexFix(h, j), 0); else addLine(h, 0, indexFix(h, j)); } h->stack.cnt = 0; break; case t13_rrcurveto: for (j = 0; j < h->stack.cnt; j += 6) addCurve(h, 0, indexFix(h, j + 0), indexFix(h, j + 1), indexFix(h, j + 2), indexFix(h, j + 3), indexFix(h, j + 4), indexFix(h, j + 5)); h->stack.cnt = 0; break; case t13_callsubr: { Offset save = TELL(h); Offset localOffset = INDEXGet(h, &h->index.Subrs, popInt(h) + h->index.Subrs.bias, &length); t13Read(h, localOffset, cstr_NONE, length); if (h->path.flags & SEEN_END) return; /* endchar operator terminated subr */ seekbyte(h, save); } break; case t13_return: return; case t13_rcurveline: for (j = 0; j < h->stack.cnt - 2; j += 6) addCurve(h, 0, indexFix(h, j + 0), indexFix(h, j + 1), indexFix(h, j + 2), indexFix(h, j + 3), indexFix(h, j + 4), indexFix(h, j + 5)); addLine(h, indexFix(h, j + 0), indexFix(h, j + 1)); h->stack.cnt = 0; break; case t13_rlinecurve: for (j = 0; j < h->stack.cnt - 6; j += 2) addLine(h, indexFix(h, j + 0), indexFix(h, j + 1)); addCurve(h, 0, indexFix(h, j + 0), indexFix(h, j + 1), indexFix(h, j + 2), indexFix(h, j + 3), indexFix(h, j + 4), indexFix(h, j + 5)); h->stack.cnt = 0; break; case t13_vvcurveto: if (h->stack.cnt & 1) { /* Add initial curve */ addCurve(h, 0, indexFix(h, 0), indexFix(h, 1), indexFix(h, 2), indexFix(h, 3), 0, indexFix(h, 4)); j = 5; } else j = 0; /* Add remaining curve(s) */ for (; j < h->stack.cnt; j += 4) addCurve(h, 0, 0, indexFix(h, j + 0), indexFix(h, j + 1), indexFix(h, j + 2), 0, indexFix(h, j + 3)); h->stack.cnt = 0; break; case t13_hhcurveto: if (h->stack.cnt & 1) { /* Add initial curve */ addCurve(h, 0, indexFix(h, 1), indexFix(h, 0), indexFix(h, 2), indexFix(h, 3), indexFix(h, 4), 0); j = 5; } else j = 0; /* Add remaining curve(s) */ for (; j < h->stack.cnt; j += 4) addCurve(h, 0, indexFix(h, j + 0), 0, indexFix(h, j + 1), indexFix(h, j + 2), indexFix(h, j + 3), 0); h->stack.cnt = 0; break; case t13_callgsubr: { Offset save = TELL(h); Offset localOffset = INDEXGet(h, &h->index.global, popInt(h) + h->index.global.bias, &length); t13Read(h, localOffset, cstr_NONE, length); if (h->path.flags & SEEN_END) return; /* endchar operator terminated subr */ seekbyte(h, save); } break; case t13_vhcurveto: case t13_hvcurveto: { int adjust = (h->stack.cnt & 1)? 5: 0; int horz = byte0 == t13_hvcurveto; /* Add initial curve(s) */ for (j = 0; j < h->stack.cnt - adjust; j += 4) if (horz++ & 1) addCurve(h, 0, indexFix(h, j + 0), 0, indexFix(h, j + 1), indexFix(h, j + 2), 0, indexFix(h, j + 3)); else addCurve(h, 0, 0, indexFix(h, j + 0), indexFix(h, j + 1), indexFix(h, j + 2), indexFix(h, j + 3), 0); if (j < h->stack.cnt) { /* Add last curve */ if (horz & 1) addCurve(h, 0, indexFix(h, j + 0), 0, indexFix(h, j + 1), indexFix(h, j + 2), indexFix(h, j + 4), indexFix(h, j + 3)); else addCurve(h, 0, 0, indexFix(h, j + 0), indexFix(h, j + 1), indexFix(h, j + 2), indexFix(h, j + 3), indexFix(h, j + 4)); } h->stack.cnt = 0; } break; case t13_rmoveto: b = popFix(h); a = popFix(h); if (addMove(h, a, b)) return; /* Stop after getting width */ h->stack.cnt = 0; break; case t13_hmoveto: if (addMove(h, popFix(h), 0)) return; /* Stop after getting width */ h->stack.cnt = 0; break; case t13_vmoveto: if (addMove(h, 0, popFix(h))) return; /* Stop after getting width */ h->stack.cnt = 0; break; case t13_hstem: case t13_vstem: case t13_hstemhm: case t13_vstemhm: if ((h->path.flags & GET_WIDTH) && setAdvance(h)) return; /* Stop after getting width */ h->path.nStems += h->stack.cnt / 2; if (PATH_FUNC_DEFINED(hintstem)) { int vert = byte0 == tx_vstem || byte0 == t2_vstemhm; b = vert? h->path.vstem: h->path.hstem; for (j = h->stack.cnt & 1; j < h->stack.cnt; j += 2) { a = b + indexFix(h, j); b = a + indexFix(h, j + 1); h->path.cb->hintstem(h->cb.ctx, vert, a, b); } if (vert) h->path.vstem = b; else h->path.hstem = b; } h->stack.cnt = 0; break; case t13_hintmask: case t13_cntrmask: { int cnt; if (h->path.flags & FIRST_MASK) { /* The vstem(hm) op may be omitted if stem list is followed by a mask op. In this case count the additional stems */ if (PATH_FUNC_DEFINED(hintstem)) { b = h->path.vstem; for (j = h->stack.cnt & 1; j < h->stack.cnt; j += 2) { a = b + indexFix(h, j); b = a + indexFix(h, j + 1); h->path.cb->hintstem(h->cb.ctx, 1, a, b); } } h->path.nStems += h->stack.cnt / 2; h->stack.cnt = 0; h->path.flags &= ~FIRST_MASK; } cnt = (h->path.nStems + 7) / 8; if (PATH_FUNC_DEFINED(hintmask)) { char mask[CFF_MAX_MASK_BYTES]; for (j = 0; j < cnt; j++) mask[j] = GETBYTE(h); h->path.cb->hintmask(h->cb.ctx, byte0 == t2_cntrmask, cnt, mask); } else while (cnt--) (void)GETBYTE(h); /* Discard mask bytes */ } break; case t13_escape: { double x; double y; switch (t13_ESC(GETBYTE(h))) { case t13_dotsection: break; default: case t13_reservedESC255: case t13_cntron: fatal(h, "reserved charstring op"); case t13_and: b = popFix(h); a = popFix(h); pushInt(h, a && b); break; case t13_or: b = popFix(h); a = popFix(h); pushInt(h, a || b); break; case t13_not: a = popFix(h); pushInt(h, !a); break; case t13_store: { int count = popInt(h); int i = popInt(h); int j = popInt(h); int iReg = popInt(h); int regSize; Fixed *reg = selRegItem(h, iReg, ®Size); if (i < 0 || i + count - 1 >= h->BCA.size || j < 0 || j + count - 1 >= regSize) fatal(h, "bounds check (store)\n"); memcpy(®[j], &h->BCA.array[i], sizeof(Fixed) * count); } break; case t13_abs: a = popFix(h); pushFix(h, (a < 0)? -a: a); break; case t13_add: b = popFix(h); a = popFix(h); pushFix(h, a + b); break; case t13_sub: b = popFix(h); a = popFix(h); pushFix(h, a - b); break; case t13_div: y = popDbl(h); x = popDbl(h); if (y == 0.0) fatal(h, "divide by zero (div)"); pushFix(h, DBL2FIX(x / y)); break; case t13_load: { int regSize; int count = popInt(h); int i = popInt(h); int iReg = popInt(h); Fixed *reg = selRegItem(h, iReg, ®Size); if (i < 0 || i + count - 1 >= h->BCA.size || count > regSize) fatal(h, "bounds check (load)\n"); memcpy(&h->BCA.array[i], reg, sizeof(Fixed) * count); } break; case t13_neg: a = popFix(h); pushFix(h, -a); break; case t13_eq: b = popFix(h); a = popFix(h); pushInt(h, a == b); break; case t13_drop: (void)popFix(h); break; case t13_put: { int i = popInt(h); if (i < 0 || i >= h->BCA.size) fatal(h, "bounds check (put)\n"); h->BCA.array[i] = popFix(h); } break; case t13_get: { int i = popInt(h); if (i < 0 || i >= h->BCA.size) fatal(h, "bounds check (get)\n"); pushFix(h, h->BCA.array[i]); } break; case t13_ifelse: { Fixed v2 = popFix(h); Fixed v1 = popFix(h); Fixed s2 = popFix(h); Fixed s1 = popFix(h); pushFix(h, (v1 > v2)? s2: s1); } break; case t13_random: pushFix(h, PMRand()); break; case t13_mul: y = popDbl(h); x = popDbl(h); pushFix(h, DBL2FIX(x * y)); break; case t13_sqrt: pushFix(h, FixedSqrt(popFix(h))); break; case t13_dup: pushFix(h, h->stack.array[h->stack.cnt - 1].f); break; case t13_exch: b = popFix(h); a = popFix(h); pushFix(h, b); pushFix(h, a); break; case t13_index: { int i = popInt(h); if (i < 0) i = 0; /* Duplicate top element */ if (i >= h->stack.cnt) fatal(h, "limit check (index)"); pushFix(h, h->stack.array[h->stack.cnt - 1 - i].f); } break; case t13_roll: { int j = popInt(h); int n = popInt(h); int iTop = h->stack.cnt - 1; int iBottom = h->stack.cnt - n; if (n < 0 || iBottom < 0) fatal(h, "limit check (roll)"); /* Constrain j to [0,n) */ if (j < 0) j = n - (-j % n); j %= n; reverse(h, iTop - j + 1, iTop); reverse(h, iBottom, iTop - j); reverse(h, iBottom, iTop); } break; case t13_hflex: addCurve(h, 1, indexFix(h, 0), 0, indexFix(h, 1), indexFix(h, 2), indexFix(h, 3), 0); addCurve(h, 1, indexFix(h, 4), 0, indexFix(h, 5), 0, indexFix(h, 6), -indexFix(h, 2)); h->stack.cnt = 0; break; case t13_flex: addCurve(h, 1, indexFix(h, 0), indexFix(h, 1), indexFix(h, 2), indexFix(h, 3), indexFix(h, 4), indexFix(h, 5)); addCurve(h, 1, indexFix(h, 6), indexFix(h, 7), indexFix(h, 8), indexFix(h, 9), indexFix(h, 10), indexFix(h, 11)); h->stack.cnt = 0; break; case t13_hflex1: { Fixed dy1 = indexFix(h, 1); Fixed dy2 = indexFix(h, 3); Fixed dy5 = indexFix(h, 7); addCurve(h, 1, indexFix(h, 0), dy1, indexFix(h, 2), dy2, indexFix(h, 4), 0); addCurve(h, 1, indexFix(h, 5), 0, indexFix(h, 6), dy5, indexFix(h, 8), -(dy1 + dy2 + dy5)); } h->stack.cnt = 0; break; case t13_flex1: { Fixed dx1 = indexFix(h, 0); Fixed dy1 = indexFix(h, 1); Fixed dx2 = indexFix(h, 2); Fixed dy2 = indexFix(h, 3); Fixed dx3 = indexFix(h, 4); Fixed dy3 = indexFix(h, 5); Fixed dx4 = indexFix(h, 6); Fixed dy4 = indexFix(h, 7); Fixed dx5 = indexFix(h, 8); Fixed dy5 = indexFix(h, 9); Fixed dx = dx1 + dx2 + dx3 + dx4 + dx5; Fixed dy = dy1 + dy2 + dy3 + dy4 + dy5; if (ABS(dx) > ABS(dy)) { dx = indexFix(h, 10); dy = -dy; } else { dx = -dx; dy = indexFix(h, 10); } addCurve(h, 1, dx1, dy1, dx2, dy2, dx3, dy3); addCurve(h, 1, dx4, dy4, dx5, dy5, dx, dy); } h->stack.cnt = 0; break; } } break; case t13_blend: blendValues(h); break; default: /* Matches 1..215, result -107..107 */ pushInt(h, 108 - byte0); break; case 241: /* 108..363 */ pushInt(h, 363 - GETBYTE(h)); break; case 239: /* 364..619 */ pushInt(h, 619 - GETBYTE(h)); break; case 246: /* 620..875 */ pushInt(h, GETBYTE(h) + 620); break; case 235: /* 876..1131 */ pushInt(h, 1131 - GETBYTE(h)); break; case 232: /* -108..-363 */ pushInt(h, GETBYTE(h) - 363); break; case 228: /* -364..-619 */ pushInt(h, GETBYTE(h) - 619); break; case 224: /* -620..-875 */ pushInt(h, GETBYTE(h) - 875); break; case 220: /* -876..-1131 */ pushInt(h, GETBYTE(h) - 1131); break; case t13_shortint: { /* 2 byte number */ long byte1 = GETBYTE(h); pushInt(h, byte1<<8 | GETBYTE(h)); } break; case t13_shftshort: { long byte1 = GETBYTE(h); pushFix(h, byte1<<23 | GETBYTE(h)<<15); } break; case 254: { /* 5 byte number */ long byte1 = GETBYTE(h); long byte2 = GETBYTE(h); long byte3 = GETBYTE(h); pushFix(h, byte1<<24 | byte2<<16 | byte3<<8 | GETBYTE(h)); } break; } } }