float addStyleRun(TextPaint paint, int len, FontMetricsInt fm) { if (fm != null) { paint.getFontMetricsInt(fm); } int p = this.mPos; this.mPos = p + len; if (this.mEasy) { return paint.getTextRunAdvances(this.mChars, p, len, p, len, this.mDir != 1, this.mWidths, p); } float totalAdvance = 0.0f; int level = this.mLevels[p]; int q = p; int i = p + 1; int e = p + len; while (true) { if (i == e || this.mLevels[i] != level) { totalAdvance += paint.getTextRunAdvances( this.mChars, q, i - q, q, i - q, (level & 1) != 0, this.mWidths, q); if (i == e) { return totalAdvance; } q = i; level = this.mLevels[i]; } i++; } }
/** * Utility function for measuring and rendering text. The text must not include a tab or emoji. * * @param wp the working paint * @param start the start of the text * @param end the end of the text * @param runIsRtl true if the run is right-to-left * @param c the canvas, can be null if rendering is not needed * @param x the edge of the run closest to the leading margin * @param top the top of the line * @param y the baseline * @param bottom the bottom of the line * @param fmi receives metrics information, can be null * @param needWidth true if the width of the run is needed * @return the signed width of the run based on the run direction; only valid if needWidth is true */ private float handleText( TextPaint wp, int start, int end, int contextStart, int contextEnd, boolean runIsRtl, Canvas c, float x, int top, int y, int bottom, FontMetricsInt fmi, boolean needWidth) { // Get metrics first (even for empty strings or "0" width runs) if (fmi != null) { /// M: new FontMetrics method for complex text support. expandMetricsFromPaint(fmi, wp, mText); } int runLen = end - start; // No need to do anything if the run width is "0" if (runLen == 0) { return 0f; } float ret = 0; int contextLen = contextEnd - contextStart; if (needWidth || (c != null && (wp.bgColor != 0 || wp.underlineColor != 0 || runIsRtl))) { int flags = runIsRtl ? Paint.DIRECTION_RTL : Paint.DIRECTION_LTR; if (mCharsValid) { ret = wp.getTextRunAdvances(mChars, start, runLen, contextStart, contextLen, flags, null, 0); } else { int delta = mStart; ret = wp.getTextRunAdvances( mText, delta + start, delta + end, delta + contextStart, delta + contextEnd, flags, null, 0); } } if (c != null) { if (runIsRtl) { x -= ret; } if (wp.bgColor != 0) { int previousColor = wp.getColor(); Paint.Style previousStyle = wp.getStyle(); wp.setColor(wp.bgColor); wp.setStyle(Paint.Style.FILL); c.drawRect(x, top, x + ret, bottom, wp); wp.setStyle(previousStyle); wp.setColor(previousColor); } if (wp.underlineColor != 0) { // kStdUnderline_Offset = 1/9, defined in SkTextFormatParams.h float underlineTop = y + wp.baselineShift + (1.0f / 9.0f) * wp.getTextSize(); int previousColor = wp.getColor(); Paint.Style previousStyle = wp.getStyle(); boolean previousAntiAlias = wp.isAntiAlias(); wp.setStyle(Paint.Style.FILL); wp.setAntiAlias(true); wp.setColor(wp.underlineColor); c.drawRect(x, underlineTop, x + ret, underlineTop + wp.underlineThickness, wp); wp.setStyle(previousStyle); wp.setColor(previousColor); wp.setAntiAlias(previousAntiAlias); } drawTextRun(c, wp, start, end, contextStart, contextEnd, runIsRtl, x, y + wp.baselineShift); } return runIsRtl ? -ret : ret; }