SkDPoint SkDQuad::top(double startT, double endT) const { SkDQuad sub = subDivide(startT, endT); SkDPoint topPt = sub[0]; if (topPt.fY > sub[2].fY || (topPt.fY == sub[2].fY && topPt.fX > sub[2].fX)) { topPt = sub[2]; } if (!between(sub[0].fY, sub[1].fY, sub[2].fY)) { double extremeT; if (FindExtrema(sub[0].fY, sub[1].fY, sub[2].fY, &extremeT)) { extremeT = startT + (endT - startT) * extremeT; SkDPoint test = ptAtT(extremeT); if (topPt.fY > test.fY || (topPt.fY == test.fY && topPt.fX > test.fX)) { topPt = test; } } } return topPt; }
SkDPoint SkDCubic::top(double startT, double endT) const { SkDCubic sub = subDivide(startT, endT); SkDPoint topPt = sub[0]; if (topPt.fY > sub[3].fY || (topPt.fY == sub[3].fY && topPt.fX > sub[3].fX)) { topPt = sub[3]; } double extremeTs[2]; if (!sub.monotonicInY()) { int roots = FindExtrema(sub[0].fY, sub[1].fY, sub[2].fY, sub[3].fY, extremeTs); for (int index = 0; index < roots; ++index) { double t = startT + (endT - startT) * extremeTs[index]; SkDPoint mid = ptAtT(t); if (topPt.fY > mid.fY || (topPt.fY == mid.fY && topPt.fX > mid.fX)) { topPt = mid; } } } return topPt; }
FS_PUBLIC int32 fsc_MeasureGlyph( ContourList* pclContour, /* glyph outline */ GlyphBitMap* pbmpBitMap, /* to return bounds */ WorkScan* pwsWork, /* to return values */ uint16 usScanKind, /* dropout control value */ uint16 usRoundXMin /* for gray scale alignment */ ) { uint16 usCont; /* contour index */ int16 sPt; /* point index */ int16 sStart, sEnd; /* start and end point of contours */ int16 sOrgDir; /* original contour direction */ int16 sDir; /* current contour direction */ int16 sFlatCount; /* for contours starting flat */ int32 lVScanCount; /* total vertical scan lines */ int32 lHScanCount; /* total horizontal scan lines */ int32 lTotalHIx; int32 lTotalVIx; int32 lElementCount; /* total element point estimate */ int32 lDivide; /* spline element point counter */ int32 lErrCode; F26Dot6 fxX1, fxX2; /* x coord endpoints */ F26Dot6 fxY1, fxY2; /* y coord endpoints */ F26Dot6 *pfxXCoord, *pfxYCoord; /* for fast point array access */ F26Dot6 fxAbsDelta; /* for element count check */ uint8 byF1, byF2; /* oncurve flag values */ uint8 *pbyFlags; /* for element count check */ PRevRoot prrRoots; /* reversal list roots structure */ lErrCode = FindExtrema(pclContour, pbmpBitMap); /* calc bounding box */ if (lErrCode != NO_ERR) return lErrCode; pbmpBitMap->rectBounds.left &= -((int32)usRoundXMin); /* mask off low n bits */ prrRoots = fsc_SetupRevRoots(pwsWork->pchRBuffer, pwsWork->lRMemSize); lElementCount = 0; /* smart point counter */ for (usCont = 0; usCont < pclContour->usContourCount; usCont++) { sStart = pclContour->asStartPoint[usCont]; sEnd = pclContour->asEndPoint[usCont]; if (sStart == sEnd) { continue; /* for anchor points */ } /* check contour Y values for direction reversals */ fxY1 = pclContour->afxYCoord[sEnd]; /* start by closing */ pfxYCoord = &pclContour->afxYCoord[sStart]; sPt = sStart; sDir = 0; /* starting dir unknown */ sFlatCount = 0; while ((sDir == 0) && (sPt <= sEnd)) { fxY2 = *pfxYCoord++; if (fxY2 > fxY1) /* find first up or down */ { sDir = 1; } else if (fxY2 < fxY1) { sDir = -1; } else { sFlatCount++; /* countour starts flat */ } fxY1 = fxY2; sPt++; } sOrgDir = sDir; /* save original ep check */ while (sPt <= sEnd) { fxY2 = *pfxYCoord++; if (sDir == 1) { if (fxY2 <= fxY1) /* = is for endpoint cases */ { fsc_AddYReversal (prrRoots, fxY1, 1); sDir = -1; } } else /* if sDir == -1 */ { if (fxY2 >= fxY1) /* = is for endpoint cases */ { fsc_AddYReversal (prrRoots, fxY1, -1); sDir = 1; } } fxY1 = fxY2; /* next segment */ sPt++; } while (sFlatCount > 0) /* if contour started flat */ { if (sDir == 0) /* if completely flat */ { sDir = 1; /* then pick a direction */ sOrgDir = 1; } fsc_AddYReversal (prrRoots, fxY1, sDir); /* add one per point */ sDir = -sDir; sFlatCount--; } if (sOrgDir != sDir) /* if endpoint reverses */ { fsc_AddYReversal (prrRoots, fxY1, sDir); /* then balance up/down */ } /* if doing dropout control, check contour X values for direction reversals */ if (!(usScanKind & SK_NODROPOUT)) /* if any kind of dropout */ { fxX1 = pclContour->afxXCoord[sEnd]; /* start by closing */ pfxXCoord = &pclContour->afxXCoord[sStart]; sPt = sStart; sDir = 0; /* starting dir unknown */ sFlatCount = 0; while ((sDir == 0) && (sPt <= sEnd)) { fxX2 = *pfxXCoord++; if (fxX2 > fxX1) /* find first up or down */ { sDir = 1; } else if (fxX2 < fxX1) { sDir = -1; } else { sFlatCount++; /* countour starts flat */ } fxX1 = fxX2; sPt++; } sOrgDir = sDir; /* save original ep check */ while (sPt <= sEnd) { fxX2 = *pfxXCoord++; if (sDir == 1) { if (fxX2 <= fxX1) /* = is for endpoint cases */ { fsc_AddXReversal (prrRoots, fxX1, 1); sDir = -1; } } else /* if sDir == -1 */ { if (fxX2 >= fxX1) /* = is for endpoint cases */ { fsc_AddXReversal (prrRoots, fxX1, -1); sDir = 1; } } fxX1 = fxX2; /* next segment */ sPt++; } while (sFlatCount > 0) /* if contour started flat */ { if (sDir == 0) /* if completely flat */ { sDir = 1; /* then pick a direction */ sOrgDir = 1; } fsc_AddXReversal (prrRoots, fxX1, sDir); /* add one per point */ sDir = -sDir; sFlatCount--; } if (sOrgDir != sDir) /* if endpoint reverses */ { fsc_AddXReversal (prrRoots, fxX1, sDir); /* then balance up/down */ } if (usScanKind & SK_SMART) /* if smart dropout control */ { /* estimate the elem point count */ fxX1 = pclContour->afxXCoord[sEnd]; fxY1 = pclContour->afxYCoord[sEnd]; byF1 = pclContour->abyOnCurve[sEnd]; pfxXCoord = &pclContour->afxXCoord[sStart]; pfxYCoord = &pclContour->afxYCoord[sStart]; pbyFlags = &pclContour->abyOnCurve[sStart]; lElementCount += (uint32)(sEnd - sStart) + 2L; /* 1/pt + 1/contour */ for (sPt = sStart; sPt <= sEnd; sPt++) { fxX2 = *pfxXCoord++; fxY2 = *pfxYCoord++; byF2 = *pbyFlags++; if (((byF1 & byF2) & ONCURVE) == 0) /* if this is a spline */ { if (((byF1 | byF2) & ONCURVE) == 0) { lElementCount++; /* +1 for midpoint */ } if (FXABS(fxX2 - fxX1) > FXABS(fxY2 - fxY1)) { fxAbsDelta = FXABS(fxX2 - fxX1); } else { fxAbsDelta = FXABS(fxY2 - fxY1); } lDivide = 0; while (fxAbsDelta > (MAXSPLINELENGTH / 2)) { lDivide++; lDivide <<= 1; fxAbsDelta >>= 1; } lElementCount += lDivide; /* for subdivision */ } fxX1 = fxX2; fxY1 = fxY2; byF1 = byF2; } } }