#![allow(unused_parens)]
#![allow(non_upper_case_globals)]
const HFD32_INITIAL_SHIFT: i32 = 10;
const HFD32_ADDITIONAL_SHIFT: i32 = 3;
use crate::types::*;
const HFD32_SHIFT: LONG = HFD32_INITIAL_SHIFT + HFD32_ADDITIONAL_SHIFT;
const HFD32_ROUND: LONG = 1 << (HFD32_SHIFT - 1);
const HFD32_TOLERANCE: LONGLONG = 24;
const HFD32_INITIAL_TEST_MAGNITUDE: LONGLONG = HFD32_TOLERANCE << HFD32_INITIAL_SHIFT;
const HFD32_TEST_MAGNITUDE: LONGLONG = HFD32_INITIAL_TEST_MAGNITUDE << HFD32_ADDITIONAL_SHIFT;
const HFD32_MAX_ERROR: INT = (HFD32_TOLERANCE as i32) << ((2 * HFD32_INITIAL_SHIFT) / 3);
const HFD32_MAX_SIZE: LONGLONG = 0xffffc000;
#[derive(Default)]
struct HfdBasis32
{
e0: LONG,
e1: LONG,
e2: LONG,
e3: LONG,
}
impl HfdBasis32 {
fn lParentErrorDividedBy4(&self) -> LONG {
self.e3.abs().max((self.e2 + self.e2 - self.e3).abs())
}
fn lError(&self) -> LONG
{
self.e2.abs().max(self.e3.abs())
}
fn fxValue(&self) -> INT
{
return((self.e0 + HFD32_ROUND) >> HFD32_SHIFT);
}
fn bInit(&mut self, p1: INT, p2: INT, p3: INT, p4: INT) -> bool
{
self.e0 = (p1 ) << HFD32_INITIAL_SHIFT;
self.e1 = (p4 - p1 ) << HFD32_INITIAL_SHIFT;
self.e2 = 6 * (p2 - p3 - p3 + p4);
self.e3 = 6 * (p1 - p2 - p2 + p3);
if (self.lError() >= HFD32_MAX_ERROR)
{
return false;
}
self.e2 <<= HFD32_INITIAL_SHIFT;
self.e3 <<= HFD32_INITIAL_SHIFT;
return true;
}
fn vLazyHalveStepSize(&mut self, cShift: LONG)
{
self.e2 = self.ExactShiftRight(self.e2 + self.e3, 1);
self.e1 = self.ExactShiftRight(self.e1 - self.ExactShiftRight(self.e2, cShift), 1);
}
fn vSteadyState(&mut self, cShift: LONG)
{
self.e0 <<= HFD32_ADDITIONAL_SHIFT;
self.e1 <<= HFD32_ADDITIONAL_SHIFT;
let mut lShift = cShift - HFD32_ADDITIONAL_SHIFT;
if (lShift < 0)
{
lShift = -lShift;
self.e2 <<= lShift;
self.e3 <<= lShift;
}
else
{
self.e2 >>= lShift;
self.e3 >>= lShift;
}
}
fn vHalveStepSize(&mut self)
{
self.e2 = self.ExactShiftRight(self.e2 + self.e3, 3);
self.e1 = self.ExactShiftRight(self.e1 - self.e2, 1);
self.e3 = self.ExactShiftRight(self.e3, 2);
}
fn vDoubleStepSize(&mut self)
{
self.e1 += self.e1 + self.e2;
self.e3 <<= 2;
self.e2 = (self.e2 << 3) - self.e3;
}
fn vTakeStep(&mut self)
{
self.e0 += self.e1;
let lTemp = self.e2;
self.e1 += lTemp;
self.e2 += lTemp - self.e3;
self.e3 = lTemp;
}
fn ExactShiftRight(&self, num: i32, shift: i32) -> i32
{
assert!(num == (num >> shift) << shift);
return num >> shift;
}
}
fn vBoundBox(
aptfx: &[POINT; 4]) -> RECT
{
let mut left = aptfx[0].x;
let mut right = aptfx[0].x;
let mut top = aptfx[0].y;
let mut bottom = aptfx[0].y;
for i in 1..4
{
left = left.min(aptfx[i].x);
top = top.min(aptfx[i].y);
right = right.max(aptfx[i].x);
bottom = bottom.max(aptfx[i].y);
}
RECT { left: left - 16, top: top - 16, right: right + 16, bottom: bottom + 16}
}
fn bIntersect(
a: &RECT,
b: &RECT) -> bool
{
return((a.left < b.right) &&
(a.top < b.bottom) &&
(a.right > b.left) &&
(a.bottom > b.top));
}
#[derive(Default)]
pub struct Bezier32
{
cSteps: LONG,
x: HfdBasis32,
y: HfdBasis32,
rcfxBound: RECT
}
impl Bezier32 {
fn bInit(&mut self,
aptfxBez: &[POINT; 4],
prcfxClip: Option<&RECT>) -> bool
{
let mut aptfx;
let mut cShift = 0;
self.cSteps = 1;
self.rcfxBound = vBoundBox(aptfxBez);
aptfx = aptfxBez.clone();
{
let mut fxOr;
let mut fxOffset;
fxOffset = self.rcfxBound.left;
fxOr = {aptfx[0].x -= fxOffset; aptfx[0].x};
fxOr |= {aptfx[1].x -= fxOffset; aptfx[1].x};
fxOr |= {aptfx[2].x -= fxOffset; aptfx[2].x};
fxOr |= {aptfx[3].x -= fxOffset; aptfx[3].x};
fxOffset = self.rcfxBound.top;
fxOr |= {aptfx[0].y -= fxOffset; aptfx[0].y};
fxOr |= {aptfx[1].y -= fxOffset; aptfx[1].y};
fxOr |= {aptfx[2].y -= fxOffset; aptfx[2].y};
fxOr |= {aptfx[3].y -= fxOffset; aptfx[3].y};
if ((fxOr as i64 & HFD32_MAX_SIZE) != 0) {
return false;
}
}
if (!self.x.bInit(aptfx[0].x, aptfx[1].x, aptfx[2].x, aptfx[3].x))
{
return false;
}
if (!self.y.bInit(aptfx[0].y, aptfx[1].y, aptfx[2].y, aptfx[3].y))
{
return false;
}
if (match prcfxClip { None => true, Some(clip) => bIntersect(&self.rcfxBound, clip)})
{
loop {
let lTestMagnitude = (HFD32_INITIAL_TEST_MAGNITUDE << cShift) as LONG;
if (self.x.lError() <= lTestMagnitude && self.y.lError() <= lTestMagnitude) {
break;
}
cShift += 2;
self.x.vLazyHalveStepSize(cShift);
self.y.vLazyHalveStepSize(cShift);
self.cSteps <<= 1;
}
}
self.x.vSteadyState(cShift);
self.y.vSteadyState(cShift);
self.x.vTakeStep();
self.y.vTakeStep();
self.cSteps-=1;
return true;
}
fn cFlatten(&mut self,
mut pptfx: &mut [POINT],
pbMore: &mut bool) -> i32
{
let mut cptfx = pptfx.len();
assert!(cptfx > 0);
let cptfxOriginal = cptfx;
while {
pptfx[0].x = self.x.fxValue() + self.rcfxBound.left;
pptfx[0].y = self.y.fxValue() + self.rcfxBound.top;
pptfx = &mut pptfx[1..];
if (self.cSteps == 0)
{
*pbMore = false;
return(cptfxOriginal - cptfx + 1) as i32;
}
if (self.x.lError().max(self.y.lError()) > HFD32_TEST_MAGNITUDE as LONG)
{
self.x.vHalveStepSize();
self.y.vHalveStepSize();
self.cSteps <<= 1;
}
assert!(self.x.lError().max(self.y.lError()) <= HFD32_TEST_MAGNITUDE as LONG);
while (!(self.cSteps & 1 != 0) &&
self.x.lParentErrorDividedBy4() <= (HFD32_TEST_MAGNITUDE as LONG >> 2) &&
self.y.lParentErrorDividedBy4() <= (HFD32_TEST_MAGNITUDE as LONG >> 2))
{
self.x.vDoubleStepSize();
self.y.vDoubleStepSize();
self.cSteps >>= 1;
}
self.cSteps -=1 ;
self.x.vTakeStep();
self.y.vTakeStep();
cptfx -= 1;
cptfx != 0
} {}
*pbMore = true;
return cptfxOriginal as i32;
}
}
#[derive(Default)]
struct HfdBasis64
{
e0: LONGLONG,
e1: LONGLONG,
e2: LONGLONG,
e3: LONGLONG,
}
impl HfdBasis64 {
fn vParentError(&self) -> LONGLONG
{
(self.e3 << 2).abs().max(((self.e2 << 3) - (self.e3 << 2)).abs())
}
fn vError(&self) -> LONGLONG
{
self.e2.abs().max(self.e3.abs())
}
fn fxValue(&self) -> INT
{
let mut eq = self.e0;
eq += (1 << (BEZIER64_FRACTION - 1));
eq >>= BEZIER64_FRACTION;
return eq as LONG as INT;
}
fn vInit(&mut self, p1: INT, p2: INT, p3: INT, p4: INT)
{
let mut eqTmp;
let eqP2 = p2 as LONGLONG;
let eqP3 = p3 as LONGLONG;
self.e0 = p1 as LONGLONG; self.e1 = p4 as LONGLONG;
self.e2 = eqP2; self.e2 -= eqP3; self.e2 -= eqP3; self.e2 += self.e1; self.e3 = self.e0; self.e3 -= eqP2; self.e3 -= eqP2; self.e3 += eqP3; self.e1 -= self.e0;
self.e0 <<= BEZIER64_FRACTION;
self.e1 <<= BEZIER64_FRACTION;
eqTmp = self.e2; self.e2 += eqTmp; self.e2 += eqTmp; self.e2 <<= (BEZIER64_FRACTION + 1);
eqTmp = self.e3; self.e3 += eqTmp; self.e3 += eqTmp; self.e3 <<= (BEZIER64_FRACTION + 1);
}
fn vUntransform<F: Fn(&mut POINT) -> &mut LONG>(&self,
afx: &mut [POINT; 4], field: F)
{
let mut eqP0;
let mut eqP1;
let mut eqP2;
let mut eqP3;
eqP0 = self.e0;
eqP2 = self.e1;
eqP2 += self.e1;
eqP2 += self.e1;
eqP1 = eqP2;
eqP1 += eqP2; eqP1 -= self.e2; eqP2 = eqP1;
eqP2 += eqP1; eqP2 -= self.e3; eqP1 -= self.e3;
eqP1 -= self.e3;
eqP1 /= 18;
eqP2 /= 18;
eqP1 += self.e0;
eqP2 += self.e0;
eqP3 = self.e0;
eqP3 += self.e1;
eqP0 += (1 << (BEZIER64_FRACTION - 1)); eqP0 >>= BEZIER64_FRACTION; *field(&mut afx[0]) = eqP0 as LONG;
eqP1 += (1 << (BEZIER64_FRACTION - 1)); eqP1 >>= BEZIER64_FRACTION; *field(&mut afx[1]) = eqP1 as LONG;
eqP2 += (1 << (BEZIER64_FRACTION - 1)); eqP2 >>= BEZIER64_FRACTION; *field(&mut afx[2]) = eqP2 as LONG;
eqP3 += (1 << (BEZIER64_FRACTION - 1)); eqP3 >>= BEZIER64_FRACTION; *field(&mut afx[3]) = eqP3 as LONG;
}
fn vHalveStepSize(&mut self)
{
self.e2 += self.e3; self.e2 >>= 3;
self.e1 -= self.e2; self.e1 >>= 1;
self.e3 >>= 2;
}
fn vDoubleStepSize(&mut self)
{
self.e1 <<= 1; self.e1 += self.e2;
self.e3 <<= 2;
self.e2 <<= 3; self.e2 -= self.e3;
}
fn vTakeStep(&mut self)
{
self.e0 += self.e1;
let eqTmp = self.e2;
self.e1 += self.e2;
self.e2 += eqTmp; self.e2 -= self.e3;
self.e3 = eqTmp;
}
}
const BEZIER64_FRACTION: LONG = 28;
const geqErrorHigh: LONGLONG = (6 * (1 << 15) >> (32 - BEZIER64_FRACTION)) << 32;
use crate::types::POINT;
const geqErrorLow: LONGLONG = (3) << 31;
#[derive(Default)]
pub struct Bezier64
{
xLow: HfdBasis64,
yLow: HfdBasis64,
xHigh: HfdBasis64,
yHigh: HfdBasis64,
eqErrorLow: LONGLONG,
rcfxClip: Option<RECT>,
cStepsHigh: LONG,
cStepsLow: LONG
}
impl Bezier64 {
fn vInit(&mut self,
aptfx: &[POINT; 4],
prcfxVis: Option<&RECT>,
eqError: LONGLONG)
{
self.cStepsHigh = 1;
self.cStepsLow = 0;
self.xHigh.vInit(aptfx[0].x, aptfx[1].x, aptfx[2].x, aptfx[3].x);
self.yHigh.vInit(aptfx[0].y, aptfx[1].y, aptfx[2].y, aptfx[3].y);
self.eqErrorLow = eqError;
self.rcfxClip = prcfxVis.cloned();
while (((self.xHigh.vError()) > geqErrorHigh) ||
((self.yHigh.vError()) > geqErrorHigh))
{
self.cStepsHigh <<= 1;
self.xHigh.vHalveStepSize();
self.yHigh.vHalveStepSize();
}
}
fn cFlatten(
&mut self,
mut pptfx: &mut [POINT],
pbMore: &mut bool) -> INT
{
let mut aptfx: [POINT; 4] = Default::default();
let mut cptfx = pptfx.len();
let mut rcfxBound: RECT;
let cptfxOriginal = cptfx;
assert!(cptfx > 0);
while {
if (self.cStepsLow == 0)
{
self.xHigh.vUntransform(&mut aptfx, |p| &mut p.x);
self.yHigh.vUntransform(&mut aptfx, |p| &mut p.y);
self.xLow.vInit(aptfx[0].x, aptfx[1].x, aptfx[2].x, aptfx[3].x);
self.yLow.vInit(aptfx[0].y, aptfx[1].y, aptfx[2].y, aptfx[3].y);
self.cStepsLow = 1;
if (match &self.rcfxClip { None => true, Some(clip) => {rcfxBound = vBoundBox(&aptfx); bIntersect(&rcfxBound, &clip)}})
{
while (((self.xLow.vError()) > self.eqErrorLow) ||
((self.yLow.vError()) > self.eqErrorLow))
{
self.cStepsLow <<= 1;
self.xLow.vHalveStepSize();
self.yLow.vHalveStepSize();
}
}
if ({self.cStepsHigh -= 1; self.cStepsHigh} != 0)
{
self.xHigh.vTakeStep();
self.yHigh.vTakeStep();
if (((self.xHigh.vError()) > geqErrorHigh) ||
((self.yHigh.vError()) > geqErrorHigh))
{
self.cStepsHigh <<= 1;
self.xHigh.vHalveStepSize();
self.yHigh.vHalveStepSize();
}
while (!(self.cStepsHigh & 1 != 0) &&
((self.xHigh.vParentError()) <= geqErrorHigh) &&
((self.yHigh.vParentError()) <= geqErrorHigh))
{
self.xHigh.vDoubleStepSize();
self.yHigh.vDoubleStepSize();
self.cStepsHigh >>= 1;
}
}
}
self.xLow.vTakeStep();
self.yLow.vTakeStep();
pptfx[0].x = self.xLow.fxValue();
pptfx[0].y = self.yLow.fxValue();
pptfx = &mut pptfx[1..];
self.cStepsLow-=1;
if (self.cStepsLow == 0 && self.cStepsHigh == 0)
{
*pbMore = false;
return(cptfxOriginal - cptfx + 1) as INT;
}
if ((self.xLow.vError() > self.eqErrorLow) ||
(self.yLow.vError() > self.eqErrorLow))
{
self.cStepsLow <<= 1;
self.xLow.vHalveStepSize();
self.yLow.vHalveStepSize();
}
while (!(self.cStepsLow & 1 != 0) &&
((self.xLow.vParentError()) <= self.eqErrorLow) &&
((self.yLow.vParentError()) <= self.eqErrorLow))
{
self.xLow.vDoubleStepSize();
self.yLow.vDoubleStepSize();
self.cStepsLow >>= 1;
}
cptfx -= 1;
cptfx != 0
} {};
*pbMore = true;
return(cptfxOriginal) as INT;
}
}
pub (crate) enum CMILBezier
{
Bezier64(Bezier64),
Bezier32(Bezier32)
}
impl CMILBezier {
pub fn new(aptfxBez: &[POINT; 4], prcfxClip: Option<&RECT>) -> Self {
let mut bez32 = Bezier32::default();
let bBez32 = bez32.bInit(aptfxBez, prcfxClip);
if bBez32 {
CMILBezier::Bezier32(bez32)
} else {
let mut bez64 = Bezier64::default();
bez64.vInit(aptfxBez, prcfxClip, geqErrorLow);
CMILBezier::Bezier64(bez64)
}
}
pub fn Flatten( &mut self,
pptfx: &mut [POINT],
pbMore: &mut bool) -> INT {
match self {
CMILBezier::Bezier32(bez) => bez.cFlatten(pptfx, pbMore),
CMILBezier::Bezier64(bez) => bez.cFlatten(pptfx, pbMore)
}
}
}
#[test]
fn flatten() {
let curve: [POINT; 4] = [
POINT{x: 1715, y: 6506},
POINT{x: 1692, y: 6506},
POINT{x: 1227, y: 5148},
POINT{x: 647, y: 5211}];
let mut bez = CMILBezier::new(&curve, None);
let mut result: [POINT; 32] = Default::default();
let mut more: bool = false;
let count = bez.Flatten(&mut result, &mut more);
assert_eq!(count, 21);
assert_eq!(more, false);
}
#[test]
fn split_flatten32() {
let curve: [POINT; 4] = [
POINT{x: 1795, y: 8445},
POINT{x: 1795, y: 8445},
POINT{x: 1908, y: 8683},
POINT{x: 2043, y: 8705}];
let mut bez = CMILBezier::new(&curve, None);
let mut result: [POINT; 8] = Default::default();
let mut more: bool = false;
let count = bez.Flatten(&mut result[..5], &mut more);
assert_eq!(count, 5);
assert_eq!(more, true);
let count = bez.Flatten(&mut result[5..], &mut more);
assert_eq!(count, 3);
assert_eq!(more, false);
let mut bez = CMILBezier::new(&curve, None);
let mut full_result: [POINT; 8] = Default::default();
let mut more: bool = false;
let count = bez.Flatten(&mut full_result, &mut more);
assert_eq!(count, 8);
assert_eq!(more, false);
assert!(result == full_result);
}
#[test]
fn flatten32() {
let curve: [POINT; 4] = [
POINT{x: 100, y: 100},
POINT{x: 110, y: 100},
POINT{x: 110, y: 110},
POINT{x: 110, y: 100}];
let mut bez = CMILBezier::new(&curve, None);
let mut result: [POINT; 32] = Default::default();
let mut more: bool = false;
let count = bez.Flatten(&mut result, &mut more);
assert_eq!(count, 3);
assert_eq!(more, false);
}
#[test]
fn flatten32_double_step_size() {
let curve: [POINT; 4] = [
POINT{x: 1761, y: 8152},
POINT{x: 1761, y: 8152},
POINT{x: 1750, y: 8355},
POINT{x: 1795, y: 8445}];
let mut bez = CMILBezier::new(&curve, None);
let mut result: [POINT; 32] = Default::default();
let mut more: bool = false;
let count = bez.Flatten(&mut result, &mut more);
assert_eq!(count, 7);
assert_eq!(more, false);
}
#[test]
fn bezier64_init_high_num_steps() {
let curve: [POINT; 4] = [
POINT{x: 33, y: -1},
POINT{x: -1, y: -1},
POINT{x: -1, y: -16385},
POINT{x: -226, y: 10}];
let mut bez = CMILBezier::new(&curve, None);
let mut result: [POINT; 32] = Default::default();
let mut more: bool = false;
let count = bez.Flatten(&mut result, &mut more);
assert_eq!(count, 32);
assert_eq!(more, true);
}
#[test]
fn bezier64_high_error() {
let curve: [POINT; 4] = [
POINT{x: -1, y: -1},
POINT{x: -4097, y: -1},
POINT{x: 65471, y: -256},
POINT{x: -1, y: 0}];
let mut bez = CMILBezier::new(&curve, None);
let mut result: [POINT; 32] = Default::default();
let mut more: bool = false;
let count = bez.Flatten(&mut result, &mut more);
assert_eq!(count, 32);
assert_eq!(more, true);
}