void nsSMILKeySpline::CalcSampleValues() { for (int i = 0; i < kSplineTableSize; ++i) { mSampleValues[i] = CalcBezier(double(i) * kSampleStepSize, mX1, mX2); } }
double nsSMILKeySpline::GetSplineValue(double aX) const { if (mX1 == mY1 && mX2 == mY2) return aX; return CalcBezier(GetTForX(aX), mY1, mY2); }
double nsSMILKeySpline::NewtonRaphsonIterate(double aX, double aGuessT) const { // Refine guess with Newton-Raphson iteration for (int i = 0; i < NEWTON_ITERATIONS; ++i) { // We're trying to find where f(t) = aX, // so we're actually looking for a root for: CalcBezier(t) - aX double currentX = CalcBezier(aGuessT, mX1, mX2) - aX; double currentSlope = GetSlope(aGuessT, mX1, mX2); if (currentSlope == 0.0) return aGuessT; aGuessT -= currentX / currentSlope; } return aGuessT; }
double nsSMILKeySpline::BinarySubdivide(double aX, double aA, double aB) const { double currentX; double currentT; int i = 0; do { currentT = aA + (aB - aA) / 2.0; currentX = CalcBezier(currentT, mX1, mX2) - aX; if (currentX > 0.0) { aB = currentT; } else { aA = currentT; } } while (fabs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS); return currentT; }
void CDSegment::Draw(CDC *pDC, CDoubleRect DrawPlace, int iWidth) const { int i, nBez,b; CPoint * paPoints; double daContr[4]; double *pBezPts; double dRelWidth, dRelHeight; paPoints = new CPoint[m_nCount]; if (paPoints == NULL) return; dRelWidth = DrawPlace.Width() / iWidth; dRelHeight = DrawPlace.Height() / NORM_DIGIHEIGHT; for (i = 0; i < m_nCount; i++) { if (m_paTypes[i] != PT_BEZIERTO) { paPoints[i] = CPoint(DrawPlace.left + dRelWidth * m_paPoints[i].x + 0.5, DrawPlace.top + dRelHeight * m_paPoints[i].y + 0.5); } } for (i = 0; i < m_nCount; i++) { if (m_paTypes[i] == PT_MOVETO) { pDC->MoveTo(paPoints[i]); } else if (m_paTypes[i] == PT_LINETO) { VERIFY(pDC->LineTo(paPoints[i])); } else if (m_paTypes[i] == PT_BEZIERTO) { // Look for the first non-bezier point(This is the EndPoint)... nBez = 0; do { nBez++; } while (m_paTypes[i+nBez] == PT_BEZIERTO); pBezPts = new double[2*(nBez+2)]; for (b = 0; b < (nBez+2)*2; b += 2) { pBezPts[b ] = DrawPlace.left + dRelWidth * m_paPoints[i-1+b/2].x; pBezPts[b+1] = DrawPlace.top + dRelHeight * m_paPoints[i-1+b/2].y; } CalcBezier(pBezPts, 2*(nBez+2), daContr); delete[] pBezPts; paPoints[i ].x = daContr[0] + 0.5; paPoints[i ].y = daContr[1] + 0.5; paPoints[i+1].x = daContr[2] + 0.5; paPoints[i+1].y = daContr[3] + 0.5; paPoints[i+2] = paPoints[i+nBez]; VERIFY(pDC->PolyBezierTo(&paPoints[i], 3)); i += nBez; } } // for delete[] paPoints; }