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++;
   }
 }
Exemplo n.º 2
0
  /**
   * 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;
  }