content: /*
   * Copyright (C) 2015-2023 Emanuel Moecklin
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.onegravity.rteditor.spans;
  
  import android.graphics.Canvas;
  import android.graphics.Paint;
  import android.graphics.Path;
  import android.graphics.Path.Direction;
  import android.text.Layout;
  import android.text.Spanned;
  import android.text.style.LeadingMarginSpan;
  
  /**
   * Implementation for a bullet point LeadingMarginSpan
   * <p>
   * Android seems to add the leading margin for an empty paragraph to the
   * previous paragraph (]0, 4][4, 4] --> the leading margin of the second span is
   * added to the ]0, 4] paragraph regardless of the Spanned.flags) --> therefore
   * we ignore the leading margin for the last, empty paragraph unless it's the
   * only one
   */
  public class BulletSpan extends BaseListItemSpan implements LeadingMarginSpan, RTSpan<Boolean>, RTParagraphSpan<Boolean> {
  
      private static Path sBulletPath = null;
  
      private final int mGapWidth;
      private final boolean mIgnoreSpan;
  
      public BulletSpan(int gapWidth, boolean isEmpty, boolean isFirst, boolean isLast) {
          mGapWidth = gapWidth;
          mIgnoreSpan = isEmpty && isLast && !isFirst;
          if (sBulletPath == null) {
              sBulletPath = new Path();
          }
      }
  
      private BulletSpan(int gapWidth, boolean ignoreSpan) {
          mGapWidth = gapWidth;
          mIgnoreSpan = ignoreSpan;
      }
  
      @Override
      public int getLeadingMargin(boolean first) {
          return mIgnoreSpan ? 0 : mGapWidth;
      }
  
      @Override
      public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom,
                                    CharSequence text, int start, int end, boolean first, Layout l) {
          Spanned spanned = (Spanned) text;
          if (!mIgnoreSpan && spanned.getSpanStart(this) == start) {
              // set paint
              Paint.Style oldStyle = p.getStyle();
              p.setStyle(Paint.Style.FILL);
  
              // draw the bullet point
              int size = Math.max(Math.round(determineTextSize(spanned, start, end, p.getTextSize()) / 9f), 4);
              draw(c, p, x, dir, top, bottom, size);
  
              // restore paint
              p.setStyle(oldStyle);
          }
      }
  
      private void draw(Canvas c, Paint p, int x, int dir, int top, int bottom, int size) {
          sBulletPath.reset();
          sBulletPath.addCircle(0.0f, 0.0f, size, Direction.CW);
  
          c.save();
          c.translate(x + dir * size, (top + bottom) / 2.0f);
          c.drawPath(sBulletPath, p);
          c.restore();
      }
  
      @Override
      public Boolean getValue() {
          return Boolean.TRUE;
      }
  
      @Override
      public BulletSpan createClone() {
          return new BulletSpan(mGapWidth, mIgnoreSpan);
      }
  
  }
  