<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

package com.facebook.react.flat;

import javax.annotation.Nullable;

import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;

import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.ViewProps;

/**
 * RCTVirtualText is a {@link FlatTextShadowNode} that can contain font styling information.
 */
/* package */ class RCTVirtualText extends FlatTextShadowNode {

  private static final String BOLD = "bold";
  private static final String ITALIC = "italic";
  private static final String NORMAL = "normal";

  private static final String PROP_SHADOW_OFFSET = "textShadowOffset";
  private static final String PROP_SHADOW_RADIUS = "textShadowRadius";
  private static final String PROP_SHADOW_COLOR = "textShadowColor";
  private static final int DEFAULT_TEXT_SHADOW_COLOR = 0x55000000;

  private FontStylingSpan mFontStylingSpan = FontStylingSpan.INSTANCE;
  private ShadowStyleSpan mShadowStyleSpan = ShadowStyleSpan.INSTANCE;

  @Override
  protected void performCollectText(SpannableStringBuilder builder) {
    for (int i = 0, childCount = getChildCount(); i < childCount; ++i) {
      FlatTextShadowNode child = (FlatTextShadowNode) getChildAt(i);
      child.collectText(builder);
    }
  }

  @Override
  protected void performApplySpans(SpannableStringBuilder builder, int begin, int end) {
    mFontStylingSpan.freeze();

    // All spans will automatically extend to the right of the text, but not the left - except
    // for spans that start at the beginning of the text.
    final int flag = begin == 0 ?
        Spannable.SPAN_INCLUSIVE_INCLUSIVE :
        Spannable.SPAN_EXCLUSIVE_INCLUSIVE;

    builder.setSpan(
        mFontStylingSpan,
        begin,
        end,
        flag);

    if (mShadowStyleSpan.getColor() != 0 && mShadowStyleSpan.getRadius() != 0) {
      mShadowStyleSpan.freeze();

      builder.setSpan(
          mShadowStyleSpan,
          begin,<commit_msg>Make sure we call notifyChanged(true) when a child is added to RCTVirtualText<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

package com.facebook.react.flat;

import javax.annotation.Nullable;

import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;

import com.facebook.csslayout.CSSNode;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;

/**
 * RCTVirtualText is a {@link FlatTextShadowNode} that can contain font styling information.
 */
/* package */ class RCTVirtualText extends FlatTextShadowNode {

  private static final String BOLD = "bold";
  private static final String ITALIC = "italic";
  private static final String NORMAL = "normal";

  private static final String PROP_SHADOW_OFFSET = "textShadowOffset";
  private static final String PROP_SHADOW_RADIUS = "textShadowRadius";
  private static final String PROP_SHADOW_COLOR = "textShadowColor";
  private static final int DEFAULT_TEXT_SHADOW_COLOR = 0x55000000;

  private FontStylingSpan mFontStylingSpan = FontStylingSpan.INSTANCE;
  private ShadowStyleSpan mShadowStyleSpan = ShadowStyleSpan.INSTANCE;

  @Override
  public void addChildAt(CSSNode child, int i) {
    super.addChildAt(child, i);
    notifyChanged(true);
  }

  @Override
  protected void performCollectText(SpannableStringBuilder builder) {
    for (int i = 0, childCount = getChildCount(); i < childCount; ++i) {
      FlatTextShadowNode child = (FlatTextShadowNode) getChildAt(i);
      child.collectText(builder);
    }
  }

  @Override
  protected void performApplySpans(SpannableStringBuilder builder, int begin, int end) {
    mFontStylingSpan.freeze();

    // All spans will automatically extend to the right of the text, but not the left - except
    // for spans that start at the beginning of the text.
    final int flag = begin == 0 ?
        Spannable.SPAN_INCLUSIVE_INCLUSIVE :
        Spannable.SPAN_EXCLUSIVE_INCLUSIVE;

    builder.setSpan(
        mFontStylingSpan,
        begin,
        end,
        flag);

    if (mShadowStyleSpan.getColor() != 0 && mShadowStyleSpan.getRadius() != 0) {
      mShadowStyleSpan.freeze();

      builder.setSpan(
          mShadowStyleSpan,
          begin,
{'fraction_non_alphanumeric': 0.0805817610062893, 'fraction_numerical': 0.0066823899371069185, 'mean_word_length': 4.003933136676499, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2893740', 'n_tokens_mistral': 1538, 'n_tokens_neox': 1443, 'n_words': 442}