Program: 110373
Project: 110373
Buggy source:
/** 
 * Draws the provided   {@link Cue} into a canvas with the specified styling.<p> A call to this method is able to use cached results of calculations made during the previous call, and so an instance of this class is able to optimize repeated calls to this method in which the same parameters are passed.
 * @param cue The cue to draw.
 * @param applyEmbeddedStyles Whether styling embedded within the cue should be applied.
 * @param style The style to use when drawing the cue text.
 * @param textSizePx The text size to use when drawing the cue text, in pixels.
 * @param bottomPaddingFraction The bottom padding fraction to apply when {@link Cue#line} is{@link Cue#DIMEN_UNSET}, as a fraction of the viewport height
 * @param canvas The canvas into which to draw.
 * @param cueBoxLeft The left position of the enclosing cue box.
 * @param cueBoxTop The top position of the enclosing cue box.
 * @param cueBoxRight The right position of the enclosing cue box.
 * @param cueBoxBottom The bottom position of the enclosing cue box.
 */
public void draw(Cue cue,boolean applyEmbeddedStyles,CaptionStyleCompat style,float textSizePx,float bottomPaddingFraction,Canvas canvas,int cueBoxLeft,int cueBoxTop,int cueBoxRight,int cueBoxBottom){
  CharSequence cueText=cue.text;
  if (TextUtils.isEmpty(cueText)) {
    return;
  }
  if (!applyEmbeddedStyles) {
    cueText=cueText.toString();
  }
  if (areCharSequencesEqual(this.cueText,cueText) && Util.areEqual(this.cueTextAlignment,cue.textAlignment) && this.cueLine == cue.line && this.cueLineType == cue.lineType && Util.areEqual(this.cueLineAnchor,cue.lineAnchor) && this.cuePosition == cue.position && Util.areEqual(this.cuePositionAnchor,cue.positionAnchor) && this.cueSize == cue.size && this.applyEmbeddedStyles == applyEmbeddedStyles && this.foregroundColor == style.foregroundColor && this.backgroundColor == style.backgroundColor && this.windowColor == style.windowColor && this.edgeType == style.edgeType && this.edgeColor == style.edgeColor && Util.areEqual(this.textPaint.getTypeface(),style.typeface) && this.textSizePx == textSizePx && this.bottomPaddingFraction == bottomPaddingFraction && this.parentLeft == cueBoxLeft && this.parentTop == cueBoxTop && this.parentRight == cueBoxRight && this.parentBottom == cueBoxBottom) {
    drawLayout(canvas);
    return;
  }
  this.cueText=cueText;
  this.cueTextAlignment=cue.textAlignment;
  this.cueLine=cue.line;
  this.cueLineType=cue.lineType;
  this.cueLineAnchor=cue.lineAnchor;
  this.cuePosition=cue.position;
  this.cuePositionAnchor=cue.positionAnchor;
  this.cueSize=cue.size;
  this.applyEmbeddedStyles=applyEmbeddedStyles;
  this.foregroundColor=style.foregroundColor;
  this.backgroundColor=style.backgroundColor;
  this.windowColor=style.windowColor;
  this.edgeType=style.edgeType;
  this.edgeColor=style.edgeColor;
  this.textPaint.setTypeface(style.typeface);
  this.textSizePx=textSizePx;
  this.bottomPaddingFraction=bottomPaddingFraction;
  this.parentLeft=cueBoxLeft;
  this.parentTop=cueBoxTop;
  this.parentRight=cueBoxRight;
  this.parentBottom=cueBoxBottom;
  int parentWidth=parentRight - parentLeft;
  int parentHeight=parentBottom - parentTop;
  textPaint.setTextSize(textSizePx);
  int textPaddingX=(int)(textSizePx * INNER_PADDING_RATIO + 0.5f);
  int availableWidth=parentWidth - textPaddingX * 2;
  if (cueSize != Cue.DIMEN_UNSET) {
    availableWidth=(int)(availableWidth * cueSize);
  }
  if (availableWidth <= 0) {
    Log.w(TAG,"String_Node_Str");
    return;
  }
  Alignment textAlignment=cueTextAlignment == null ? Alignment.ALIGN_CENTER : cueTextAlignment;
  textLayout=new StaticLayout(cueText,textPaint,availableWidth,textAlignment,spacingMult,spacingAdd,true);
  int textHeight=textLayout.getHeight();
  int textWidth=0;
  int lineCount=textLayout.getLineCount();
  for (int i=0; i < lineCount; i++) {
    textWidth=Math.max((int)Math.ceil(textLayout.getLineWidth(i)),textWidth);
  }
  textWidth+=textPaddingX * 2;
  int textLeft;
  int textRight;
  if (cuePosition != Cue.DIMEN_UNSET) {
    int anchorPosition=Math.round(parentWidth * cuePosition) + parentLeft;
    textLeft=cuePositionAnchor == Cue.ANCHOR_TYPE_END ? anchorPosition - textWidth : cuePositionAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorPosition * 2 - textWidth) / 2 : anchorPosition;
    textLeft=Math.max(textLeft,parentLeft);
    textRight=Math.min(textLeft + textWidth,parentRight);
  }
 else {
    textLeft=(parentWidth - textWidth) / 2;
    textRight=textLeft + textWidth;
  }
  int textTop;
  if (cueLine != Cue.DIMEN_UNSET) {
    int anchorPosition;
    if (cueLineType == Cue.LINE_TYPE_FRACTION) {
      anchorPosition=Math.round(parentHeight * cueLine) + parentTop;
    }
 else {
      int firstLineHeight=textLayout.getLineBottom(0) - textLayout.getLineTop(0);
      if (cueLine >= 0) {
        anchorPosition=Math.round(cueLine * firstLineHeight) + parentTop;
      }
 else {
        anchorPosition=Math.round(cueLine * firstLineHeight) + parentBottom;
      }
    }
    textTop=cueLineAnchor == Cue.ANCHOR_TYPE_END ? anchorPosition - textHeight : cueLineAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorPosition * 2 - textHeight) / 2 : anchorPosition;
    if (textTop + textHeight > parentBottom) {
      textTop=parentBottom - textHeight;
    }
 else     if (textTop < parentTop) {
      textTop=parentTop;
    }
  }
 else {
    textTop=parentBottom - textHeight - (int)(parentHeight * bottomPaddingFraction);
  }
  textWidth=textRight - textLeft;
  this.textLayout=new StaticLayout(cueText,textPaint,textWidth,textAlignment,spacingMult,spacingAdd,true);
  this.textLeft=textLeft;
  this.textTop=textTop;
  this.textPaddingX=textPaddingX;
  drawLayout(canvas);
}

Fixed version (ground truth):
/** 
 * Draws the provided   {@link Cue} into a canvas with the specified styling.<p> A call to this method is able to use cached results of calculations made during the previous call, and so an instance of this class is able to optimize repeated calls to this method in which the same parameters are passed.
 * @param cue The cue to draw.
 * @param applyEmbeddedStyles Whether styling embedded within the cue should be applied.
 * @param style The style to use when drawing the cue text.
 * @param textSizePx The text size to use when drawing the cue text, in pixels.
 * @param bottomPaddingFraction The bottom padding fraction to apply when {@link Cue#line} is{@link Cue#DIMEN_UNSET}, as a fraction of the viewport height
 * @param canvas The canvas into which to draw.
 * @param cueBoxLeft The left position of the enclosing cue box.
 * @param cueBoxTop The top position of the enclosing cue box.
 * @param cueBoxRight The right position of the enclosing cue box.
 * @param cueBoxBottom The bottom position of the enclosing cue box.
 */
public void draw(Cue cue,boolean applyEmbeddedStyles,CaptionStyleCompat style,float textSizePx,float bottomPaddingFraction,Canvas canvas,int cueBoxLeft,int cueBoxTop,int cueBoxRight,int cueBoxBottom){
  CharSequence cueText=cue.text;
  if (TextUtils.isEmpty(cueText)) {
    return;
  }
  if (!applyEmbeddedStyles) {
    cueText=cueText.toString();
  }
  if (areCharSequencesEqual(this.cueText,cueText) && Util.areEqual(this.cueTextAlignment,cue.textAlignment) && this.cueLine == cue.line && this.cueLineType == cue.lineType && Util.areEqual(this.cueLineAnchor,cue.lineAnchor) && this.cuePosition == cue.position && Util.areEqual(this.cuePositionAnchor,cue.positionAnchor) && this.cueSize == cue.size && this.applyEmbeddedStyles == applyEmbeddedStyles && this.foregroundColor == style.foregroundColor && this.backgroundColor == style.backgroundColor && this.windowColor == style.windowColor && this.edgeType == style.edgeType && this.edgeColor == style.edgeColor && Util.areEqual(this.textPaint.getTypeface(),style.typeface) && this.textSizePx == textSizePx && this.bottomPaddingFraction == bottomPaddingFraction && this.parentLeft == cueBoxLeft && this.parentTop == cueBoxTop && this.parentRight == cueBoxRight && this.parentBottom == cueBoxBottom) {
    drawLayout(canvas);
    return;
  }
  this.cueText=cueText;
  this.cueTextAlignment=cue.textAlignment;
  this.cueLine=cue.line;
  this.cueLineType=cue.lineType;
  this.cueLineAnchor=cue.lineAnchor;
  this.cuePosition=cue.position;
  this.cuePositionAnchor=cue.positionAnchor;
  this.cueSize=cue.size;
  this.applyEmbeddedStyles=applyEmbeddedStyles;
  this.foregroundColor=style.foregroundColor;
  this.backgroundColor=style.backgroundColor;
  this.windowColor=style.windowColor;
  this.edgeType=style.edgeType;
  this.edgeColor=style.edgeColor;
  this.textPaint.setTypeface(style.typeface);
  this.textSizePx=textSizePx;
  this.bottomPaddingFraction=bottomPaddingFraction;
  this.parentLeft=cueBoxLeft;
  this.parentTop=cueBoxTop;
  this.parentRight=cueBoxRight;
  this.parentBottom=cueBoxBottom;
  int parentWidth=parentRight - parentLeft;
  int parentHeight=parentBottom - parentTop;
  textPaint.setTextSize(textSizePx);
  int textPaddingX=(int)(textSizePx * INNER_PADDING_RATIO + 0.5f);
  int availableWidth=parentWidth - textPaddingX * 2;
  if (cueSize != Cue.DIMEN_UNSET) {
    availableWidth=(int)(availableWidth * cueSize);
  }
  if (availableWidth <= 0) {
    Log.w(TAG,"String_Node_Str");
    return;
  }
  Alignment textAlignment=cueTextAlignment == null ? Alignment.ALIGN_CENTER : cueTextAlignment;
  textLayout=new StaticLayout(cueText,textPaint,availableWidth,textAlignment,spacingMult,spacingAdd,true);
  int textHeight=textLayout.getHeight();
  int textWidth=0;
  int lineCount=textLayout.getLineCount();
  for (int i=0; i < lineCount; i++) {
    textWidth=Math.max((int)Math.ceil(textLayout.getLineWidth(i)),textWidth);
  }
  if (cueSize != Cue.DIMEN_UNSET && textWidth < availableWidth) {
    textWidth=availableWidth;
  }
  textWidth+=textPaddingX * 2;
  int textLeft;
  int textRight;
  if (cuePosition != Cue.DIMEN_UNSET) {
    int anchorPosition=Math.round(parentWidth * cuePosition) + parentLeft;
    textLeft=cuePositionAnchor == Cue.ANCHOR_TYPE_END ? anchorPosition - textWidth : cuePositionAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorPosition * 2 - textWidth) / 2 : anchorPosition;
    textLeft=Math.max(textLeft,parentLeft);
    textRight=Math.min(textLeft + textWidth,parentRight);
  }
 else {
    textLeft=(parentWidth - textWidth) / 2;
    textRight=textLeft + textWidth;
  }
  int textTop;
  if (cueLine != Cue.DIMEN_UNSET) {
    int anchorPosition;
    if (cueLineType == Cue.LINE_TYPE_FRACTION) {
      anchorPosition=Math.round(parentHeight * cueLine) + parentTop;
    }
 else {
      int firstLineHeight=textLayout.getLineBottom(0) - textLayout.getLineTop(0);
      if (cueLine >= 0) {
        anchorPosition=Math.round(cueLine * firstLineHeight) + parentTop;
      }
 else {
        anchorPosition=Math.round(cueLine * firstLineHeight) + parentBottom;
      }
    }
    textTop=cueLineAnchor == Cue.ANCHOR_TYPE_END ? anchorPosition - textHeight : cueLineAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorPosition * 2 - textHeight) / 2 : anchorPosition;
    if (textTop + textHeight > parentBottom) {
      textTop=parentBottom - textHeight;
    }
 else     if (textTop < parentTop) {
      textTop=parentTop;
    }
  }
 else {
    textTop=parentBottom - textHeight - (int)(parentHeight * bottomPaddingFraction);
  }
  textWidth=textRight - textLeft;
  this.textLayout=new StaticLayout(cueText,textPaint,textWidth,textAlignment,spacingMult,spacingAdd,true);
  this.textLeft=textLeft;
  this.textTop=textTop;
  this.textPaddingX=textPaddingX;
  drawLayout(canvas);
}