<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';

import {
  callIfDefined,
  measureFontOffset,
} from './shared/util';

// Render disproportion above which font will be considered broken and fallback will be used
const BROKEN_FONT_ALARM_THRESHOLD = 0.1;

export default class PageTextContent extends Component {
  state = {
    textItems: null,
  }

  componentDidMount() {
    this.getTextContent();
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.page !== this.props.page) {
      this.getTextContent(nextProps);
    }
  }

  onGetTextSuccess = (textContent) => {
    let textItems = null;
    if (textContent) {
      textItems = textContent.items;
    }

    callIfDefined(
      this.props.onGetTextSuccess,
      textItems,
    );

    this.setState({ textItems });
  }

  onGetTextError = (error) => {
    callIfDefined(
      this.props.onGetTextError,
      error,
    );

    this.setState({ textItems: false });
  }

  get unrotatedViewport() {
    const { page, scale } = this.props;

    return page.getViewport(scale);
  }

  getTextContent(props = this.props) {
    const { page } = props;

    if (!page) {
      throw new Error('Attempted to load page text content, but no page was specified.');
    }

    if (this.state.textItems !== null) {
      this.setState({ textItems: null });
    }

    page.getTextContent()
      .then(this.onGetTextSuccess)
      .catch(this.onGetTextError);
  }

  alignTextItem(element, width, fontFamily) {
    if (!element) {
      return;
    }

    const { scale } = this.props;

    const targetWidth = width * scale;
    let actualWidth = element.getBoundingClientRect().width;
    let fontOffset = measureFontOffset(fontFamily);
    const fontDisproportion = Math.abs((targetWidth / actualWidth) - 1);

    // Font has severe rendering disproportions, possibly the font is broken completely
    if (fontDisproportion > BROKEN_FONT_ALARM_THRESHOLD) {
      const fallbackFontFamily = fontFamily.split(', ').slice(1).join(', ');
      element.style.fontFamily = fallbackFontFamily;
      actualWidth = element.getBoundingClientRect().width;
      fontOffset = measureFontOffset(fontFamily);
    }

    element.style.transform = `scaleX(${targetWidth / actualWidth}) translateY(${fontOffset * 100}%)`;
  }

  renderTextItem = (textItem, itemIndex) => {
    const [fontSizePx, , , , left, baselineBottom] = textItem.transform;
    const { scale } = this.props;
    // Distance from top of the page to the baseline
    const fontFamily = `${textItem.fontName}, sans-serif`;
    const fontSize = `${fontSizePx * scale}px`;

    return (
      <div
        key={itemIndex}
        style={{
          position: 'absolute',
          fontSize,
          fontFamily,
          height: '1em',
          left: `${left * scale}px`,<commit_msg>Fix wrongly calculated fontOffset for fallbackFontFamily<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';

import {
  callIfDefined,
  measureFontOffset,
} from './shared/util';

// Render disproportion above which font will be considered broken and fallback will be used
const BROKEN_FONT_ALARM_THRESHOLD = 0.1;

export default class PageTextContent extends Component {
  state = {
    textItems: null,
  }

  componentDidMount() {
    this.getTextContent();
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.page !== this.props.page) {
      this.getTextContent(nextProps);
    }
  }

  onGetTextSuccess = (textContent) => {
    let textItems = null;
    if (textContent) {
      textItems = textContent.items;
    }

    callIfDefined(
      this.props.onGetTextSuccess,
      textItems,
    );

    this.setState({ textItems });
  }

  onGetTextError = (error) => {
    callIfDefined(
      this.props.onGetTextError,
      error,
    );

    this.setState({ textItems: false });
  }

  get unrotatedViewport() {
    const { page, scale } = this.props;

    return page.getViewport(scale);
  }

  getTextContent(props = this.props) {
    const { page } = props;

    if (!page) {
      throw new Error('Attempted to load page text content, but no page was specified.');
    }

    if (this.state.textItems !== null) {
      this.setState({ textItems: null });
    }

    page.getTextContent()
      .then(this.onGetTextSuccess)
      .catch(this.onGetTextError);
  }

  alignTextItem(element, width, fontFamily) {
    if (!element) {
      return;
    }

    const { scale } = this.props;

    const targetWidth = width * scale;
    let actualWidth = element.getBoundingClientRect().width;
    let fontOffset = measureFontOffset(fontFamily);
    const fontDisproportion = Math.abs((targetWidth / actualWidth) - 1);

    // Font has severe rendering disproportions, possibly the font is broken completely
    if (fontDisproportion > BROKEN_FONT_ALARM_THRESHOLD) {
      const fallbackFontFamily = fontFamily.split(', ').slice(1).join(', ');
      element.style.fontFamily = fallbackFontFamily;
      actualWidth = element.getBoundingClientRect().width;
      fontOffset = measureFontOffset(fallbackFontFamily);
    }

    element.style.transform = `scaleX(${targetWidth / actualWidth}) translateY(${fontOffset * 100}%)`;
  }

  renderTextItem = (textItem, itemIndex) => {
    const [fontSizePx, , , , left, baselineBottom] = textItem.transform;
    const { scale } = this.props;
    // Distance from top of the page to the baseline
    const fontFamily = `${textItem.fontName}, sans-serif`;
    const fontSize = `${fontSizePx * scale}px`;

    return (
      <div
        key={itemIndex}
        style={{
          height: '1em',
          fontFamily,
          fontSize,
          position: 'absolute',
          left: `${left * scale}px`,
{'fraction_non_alphanumeric': 0.1179745954410997, 'fraction_numerical': 0.002784061249347486, 'mean_word_length': 2.9696132596685083, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '886626', 'n_tokens_mistral': 1791, 'n_tokens_neox': 1731, 'n_words': 404}