/*
 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "core/layout/svg/SVGTextLayoutEngine.h"

#include "core/layout/api/LineLayoutAPIShim.h"
#include "core/layout/api/LineLayoutSVGTextPath.h"
#include "core/layout/svg/LayoutSVGInlineText.h"
#include "core/layout/svg/SVGTextChunkBuilder.h"
#include "core/layout/svg/SVGTextLayoutEngineBaseline.h"
#include "core/layout/svg/SVGTextLayoutEngineSpacing.h"
#include "core/layout/svg/line/SVGInlineFlowBox.h"
#include "core/layout/svg/line/SVGInlineTextBox.h"
#include "core/svg/SVGElement.h"
#include "core/svg/SVGLengthContext.h"
#include "core/svg/SVGTextContentElement.h"
#include "wtf/AutoReset.h"

namespace blink {

SVGTextLayoutEngine::SVGTextLayoutEngine(
    const Vector<LayoutSVGInlineText*>& descendantTextNodes)
    : m_descendantTextNodes(descendantTextNodes),
      m_currentLogicalTextNodeIndex(0),
      m_logicalCharacterOffset(0),
      m_logicalMetricsListOffset(0),
      m_isVerticalText(false),
      m_inPathLayout(false),
      m_textLengthSpacingInEffect(false),
      m_textPath(nullptr),
      m_textPathCurrentOffset(0),
      m_textPathDisplacement(0),
      m_textPathSpacing(0),
      m_textPathScaling(1) {
  ASSERT(!m_descendantTextNodes.isEmpty());
}

SVGTextLayoutEngine::~SVGTextLayoutEngine() = default;

bool SVGTextLayoutEngine::setCurrentTextPosition(const SVGCharacterData& data) {
  bool hasX = data.hasX();
  if (hasX)
    m_textPosition.setX(data.x);

  bool hasY = data.hasY();
  if (hasY)
    m_textPosition.setY(data.y);

  // If there's an absolute x/y position available, it marks the beginning of
  // a new position along the path.
  if (m_inPathLayout) {
    // TODO(fs): If a new chunk (== absolute position) is defined while in
    // path layout mode, alignment should be based on that chunk and not
    // the path as a whole. (Re: the addition of m_textPathStartOffset
    // below.)
    if (m_isVerticalText) {
      if (hasY)
        m_textPathCurrentOffset = data.y + m_textPathStartOffset;
    } else {
      if (hasX)
        m_textPathCurrentOffset = data.x + m_textPathStartOffset;
    }
  }
  return hasX || hasY;
}

void SVGTextLayoutEngine::advanceCurrentTextPosition(float glyphAdvance) {
  // TODO(fs): m_textPathCurrentOffset should preferably also be updated
  // here, but that requires a bit more untangling yet.
  if (m_isVerticalText)
    m_textPosition.setY(m_textPosition.y() + glyphAdvance);
  else
    m_textPosition.setX(m_textPosition.x() + glyphAdvance);
}

bool SVGTextLayoutEngine::applyRelativePositionAdjustmentsIfNeeded(
    const SVGCharacterData& data) {
  FloatPoint delta;
  bool hasDx = data.hasDx();
  if (hasDx)
    delta.setX(data.dx);

  bool hasDy = data.hasDy();
  if (hasDy)
    delta.setY(data.dy);

  // Apply dx/dy value adjustments to current text position, if needed.
  m_textPosition.moveBy(delta);

  if (m_inPathLayout) {
    if (m_isVerticalText)
      delta = delta.transposedPoint();

    m_textPathCurrentOffset += delta.x();
    m_textPathDisplacement += delta.y();
  }
  return hasDx || hasDy;
}

void SVGTextLayoutEngine::computeCurrentFragmentMetrics(
    SVGInlineTextBox* textBox) {
  LineLayoutSVGInlineText textLineLayout =
      LineLayoutSVGInlineText(textBox->getLineLayoutItem());
  TextRun run = textBox->constructTextRun(textLineLayout.styleRef(),
                                          m_currentTextFragment);

  float scalingFactor = textLineLayout.scalingFactor();
  ASSERT(scalingFactor);
  const Font& scaledFont = textLineLayout.scaledFont();
  FloatRect glyphOverflowBounds;

  float width = scaledFont.width(run, nullptr, &glyphOverflowBounds);
  float ascent = scaledFont.getFontMetrics().floatAscent();
  float descent = scaledFont.getFontMetrics().floatDescent();
  m_currentTextFragment.glyphOverflow.setFromBounds(glyphOverflowBounds, ascent,
                                                    descent, width);
  m_currentTextFragment.glyphOverflow.top /= scalingFactor;
  m_currentTextFragment.glyphOverflow.left /= scalingFactor;
  m_currentTextFragment.glyphOverflow.right /= scalingFactor;
  m_currentTextFragment.glyphOverflow.bottom /= scalingFactor;

  float height = scaledFont.getFontMetrics().floatHeight();
  m_currentTextFragment.height = height / scalingFactor;
  m_currentTextFragment.width = width / scalingFactor;
}

void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox* textBox) {
  ASSERT(!m_currentTextFragment.length);

  // Figure out length of fragment.
  m_currentTextFragment.length = m_visualMetricsIterator.characterOffset() -
                                 m_currentTextFragment.characterOffset;

  // Figure out fragment metrics.
  computeCurrentFragmentMetrics(textBox);

  textBox->textFragments().append(m_currentTextFragment);
  m_currentTextFragment = SVGTextFragment();
}

void SVGTextLayoutEngine::beginTextPathLayout(SVGInlineFlowBox* flowBox) {
  // Build text chunks for all <textPath> children, using the line layout
  // algorithm. This is needeed as text-anchor is just an additional startOffset
  // for text paths.
  SVGTextLayoutEngine lineLayout(m_descendantTextNodes);
  lineLayout.m_textLengthSpacingInEffect = m_textLengthSpacingInEffect;
  lineLayout.layoutCharactersInTextBoxes(flowBox);

  m_inPathLayout = true;
  LineLayoutSVGTextPath textPath =
      LineLayoutSVGTextPath(flowBox->getLineLayoutItem());

  m_textPath = textPath.layoutPath();
  if (!m_textPath)
    return;
  m_textPathStartOffset = textPath.calculateStartOffset(m_textPath->length());

  SVGTextPathChunkBuilder textPathChunkLayoutBuilder;
  textPathChunkLayoutBuilder.processTextChunks(lineLayout.m_lineLayoutBoxes);

  m_textPathStartOffset += textPathChunkLayoutBuilder.totalTextAnchorShift();
  m_textPathCurrentOffset = m_textPathStartOffset;

  // Eventually handle textLength adjustments.
  SVGLengthAdjustType lengthAdjust = SVGLengthAdjustUnknown;
  float desiredTextLength = 0;

  if (SVGTextContentElement* textContentElement =
          SVGTextContentElement::elementFromLineLayoutItem(textPath)) {
    SVGLengthContext lengthContext(textContentElement);
    lengthAdjust =
        textContentElement->lengthAdjust()->currentValue()->enumValue();
    if (textContentElement->textLengthIsSpecifiedByUser())
      desiredTextLength =
          textContentElement->textLength()->currentValue()->value(
              lengthContext);
    else
      desiredTextLength = 0;
  }

  if (!desiredTextLength)
    return;

  float totalLength = textPathChunkLayoutBuilder.totalLength();
  if (lengthAdjust == SVGLengthAdjustSpacing)
    m_textPathSpacing = (desiredTextLength - totalLength) /
                        textPathChunkLayoutBuilder.totalCharacters();
  else
    m_textPathScaling = desiredTextLength / totalLength;
}

void SVGTextLayoutEngine::endTextPathLayout() {
  m_inPathLayout = false;
  m_textPath = nullptr;
  m_textPathStartOffset = 0;
  m_textPathCurrentOffset = 0;
  m_textPathSpacing = 0;
  m_textPathScaling = 1;
}

void SVGTextLayoutEngine::layoutInlineTextBox(SVGInlineTextBox* textBox) {
  ASSERT(textBox);

  LineLayoutSVGInlineText textLineLayout =
      LineLayoutSVGInlineText(textBox->getLineLayoutItem());
  ASSERT(textLineLayout.parent());
  ASSERT(textLineLayout.parent().node());
  ASSERT(textLineLayout.parent().node()->isSVGElement());

  const ComputedStyle& style = textLineLayout.styleRef();

  textBox->clearTextFragments();
  m_isVerticalText = !style.isHorizontalWritingMode();
  layoutTextOnLineOrPath(textBox, textLineLayout, style);

  if (m_inPathLayout)
    return;

  m_lineLayoutBoxes.append(textBox);
}

static bool definesTextLengthWithSpacing(const InlineFlowBox* start) {
  SVGTextContentElement* textContentElement =
      SVGTextContentElement::elementFromLineLayoutItem(
          start->getLineLayoutItem());
  return textContentElement &&
         textContentElement->lengthAdjust()->currentValue()->enumValue() ==
             SVGLengthAdjustSpacing &&
         textContentElement->textLengthIsSpecifiedByUser();
}

void SVGTextLayoutEngine::layoutCharactersInTextBoxes(InlineFlowBox* start) {
  bool textLengthSpacingInEffect =
      m_textLengthSpacingInEffect || definesTextLengthWithSpacing(start);
  AutoReset<bool> textLengthSpacingScope(&m_textLengthSpacingInEffect,
                                         textLengthSpacingInEffect);

  for (InlineBox* child = start->firstChild(); child;
       child = child->nextOnLine()) {
    if (child->isSVGInlineTextBox()) {
      ASSERT(child->getLineLayoutItem().isSVGInlineText());
      layoutInlineTextBox(toSVGInlineTextBox(child));
    } else {
      // Skip generated content.
      Node* node = child->getLineLayoutItem().node();
      if (!node)
        continue;

      SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child);
      bool isTextPath = isSVGTextPathElement(*node);
      if (isTextPath)
        beginTextPathLayout(flowBox);

      layoutCharactersInTextBoxes(flowBox);

      if (isTextPath)
        endTextPathLayout();
    }
  }
}

void SVGTextLayoutEngine::finishLayout() {
  m_visualMetricsIterator = SVGInlineTextMetricsIterator();

  // After all text fragments are stored in their correpsonding
  // SVGInlineTextBoxes, we can layout individual text chunks.
  // Chunk layouting is only performed for line layout boxes, not for path
  // layout, where it has already been done.
  SVGTextChunkBuilder chunkLayoutBuilder;
  chunkLayoutBuilder.processTextChunks(m_lineLayoutBoxes);

  m_lineLayoutBoxes.clear();
}

const LayoutSVGInlineText* SVGTextLayoutEngine::nextLogicalTextNode() {
  ASSERT(m_currentLogicalTextNodeIndex < m_descendantTextNodes.size());
  ++m_currentLogicalTextNodeIndex;
  if (m_currentLogicalTextNodeIndex == m_descendantTextNodes.size())
    return nullptr;

  m_logicalMetricsListOffset = 0;
  m_logicalCharacterOffset = 0;
  return m_descendantTextNodes[m_currentLogicalTextNodeIndex];
}

const LayoutSVGInlineText* SVGTextLayoutEngine::currentLogicalCharacterMetrics(
    SVGTextMetrics& logicalMetrics) {
  // If we've consumed all text nodes, there can be no more metrics.
  if (m_currentLogicalTextNodeIndex == m_descendantTextNodes.size())
    return nullptr;

  const LayoutSVGInlineText* logicalTextNode =
      m_descendantTextNodes[m_currentLogicalTextNodeIndex];
  const Vector<SVGTextMetrics>* metricsList = &logicalTextNode->metricsList();
  unsigned metricsListSize = metricsList->size();
  ASSERT(m_logicalMetricsListOffset <= metricsListSize);

  // Find the next non-collapsed text metrics cell.
  while (true) {
    // If we run out of metrics, move to the next set of non-empty layout
    // attributes.
    if (m_logicalMetricsListOffset == metricsListSize) {
      logicalTextNode = nextLogicalTextNode();
      if (!logicalTextNode)
        return nullptr;
      metricsList = &logicalTextNode->metricsList();
      metricsListSize = metricsList->size();
      // Return to the while so that we check if the new metrics list is
      // non-empty before using it.
      continue;
    }

    ASSERT(metricsListSize);
    logicalMetrics = metricsList->at(m_logicalMetricsListOffset);
    // Stop if we found the next valid logical text metrics object.
    if (!logicalMetrics.isEmpty())
      break;

    advanceToNextLogicalCharacter(logicalMetrics);
  }

  return logicalTextNode;
}

void SVGTextLayoutEngine::advanceToNextLogicalCharacter(
    const SVGTextMetrics& logicalMetrics) {
  ++m_logicalMetricsListOffset;
  m_logicalCharacterOffset += logicalMetrics.length();
}

void SVGTextLayoutEngine::layoutTextOnLineOrPath(
    SVGInlineTextBox* textBox,
    LineLayoutSVGInlineText textLineLayout,
    const ComputedStyle& style) {
  if (m_inPathLayout && !m_textPath)
    return;

  // Find the start of the current text box in the metrics list.
  m_visualMetricsIterator.advanceToTextStart(textLineLayout, textBox->start());

  const Font& font = style.font();

  SVGTextLayoutEngineSpacing spacingLayout(font, style.effectiveZoom());
  SVGTextLayoutEngineBaseline baselineLayout(font, style.effectiveZoom());

  bool didStartTextFragment = false;
  bool applySpacingToNextCharacter = false;
  bool needsFragmentPerGlyph =
      m_isVerticalText || m_inPathLayout || m_textLengthSpacingInEffect;

  float lastAngle = 0;
  float baselineShiftValue = baselineLayout.calculateBaselineShift(style);
  baselineShiftValue -= baselineLayout.calculateAlignmentBaselineShift(
      m_isVerticalText, textLineLayout);
  FloatPoint baselineShift;
  if (m_isVerticalText)
    baselineShift.setX(baselineShiftValue);
  else
    baselineShift.setY(-baselineShiftValue);

  // Main layout algorithm.
  const unsigned boxEndOffset = textBox->start() + textBox->len();
  while (!m_visualMetricsIterator.isAtEnd() &&
         m_visualMetricsIterator.characterOffset() < boxEndOffset) {
    const SVGTextMetrics& visualMetrics = m_visualMetricsIterator.metrics();
    if (visualMetrics.isEmpty()) {
      m_visualMetricsIterator.next();
      continue;
    }

    SVGTextMetrics logicalMetrics(SVGTextMetrics::SkippedSpaceMetrics);
    const LayoutSVGInlineText* logicalTextNode =
        currentLogicalCharacterMetrics(logicalMetrics);
    if (!logicalTextNode)
      break;

    const SVGCharacterData data =
        logicalTextNode->characterDataMap().get(m_logicalCharacterOffset + 1);

    // TODO(fs): Use the return value to eliminate the additional
    // hash-lookup below when determining if this text box should be tagged
    // as starting a new text chunk.
    setCurrentTextPosition(data);

    // When we've advanced to the box start offset, determine using the original
    // x/y values, whether this character starts a new text chunk, before doing
    // any further processing.
    if (m_visualMetricsIterator.characterOffset() == textBox->start())
      textBox->setStartsNewTextChunk(
          logicalTextNode->characterStartsNewTextChunk(
              m_logicalCharacterOffset));

    bool hasRelativePosition = applyRelativePositionAdjustmentsIfNeeded(data);

    // Determine the orientation of the current glyph.
    // Font::width() calculates the resolved FontOrientation for each character,
    // but that value is not exposed today to avoid the API complexity.
    UChar32 currentCharacter =
        textLineLayout.codepointAt(m_visualMetricsIterator.characterOffset());
    FontOrientation fontOrientation = font.getFontDescription().orientation();
    fontOrientation = adjustOrientationForCharacterInMixedVertical(
        fontOrientation, currentCharacter);

    // Calculate glyph advance. The shaping engine takes care of x/y orientation
    // shifts for different fontOrientation values.
    float glyphAdvance = visualMetrics.advance(fontOrientation);

    // Calculate CSS 'letter-spacing' and 'word-spacing' for the character, if
    // needed.
    float spacing = spacingLayout.calculateCSSSpacing(currentCharacter);

    FloatPoint textPathShift;
    float angle = 0;
    FloatPoint position;
    if (m_inPathLayout) {
      float scaledGlyphAdvance = glyphAdvance * m_textPathScaling;
      // Setup translations that move to the glyph midpoint.
      textPathShift.set(-scaledGlyphAdvance / 2, m_textPathDisplacement);
      if (m_isVerticalText)
        textPathShift = textPathShift.transposedPoint();
      textPathShift += baselineShift;

      // Calculate current offset along path.
      float textPathOffset = m_textPathCurrentOffset + scaledGlyphAdvance / 2;

      // Move to next character.
      m_textPathCurrentOffset +=
          scaledGlyphAdvance + m_textPathSpacing + spacing * m_textPathScaling;

      PathPositionMapper::PositionType positionType =
          m_textPath->pointAndNormalAtLength(textPathOffset, position, angle);

      // Skip character, if we're before the path.
      if (positionType == PathPositionMapper::BeforePath) {
        advanceToNextLogicalCharacter(logicalMetrics);
        m_visualMetricsIterator.next();
        continue;
      }

      // Stop processing if the next character lies behind the path.
      if (positionType == PathPositionMapper::AfterPath)
        break;

      m_textPosition = position;

      // For vertical text on path, the actual angle has to be rotated 90
      // degrees anti-clockwise, not the orientation angle!
      if (m_isVerticalText)
        angle -= 90;
    } else {
      position = m_textPosition;
      position += baselineShift;
    }

    if (data.hasRotate())
      angle += data.rotate;

    // Determine whether we have to start a new fragment.
    bool shouldStartNewFragment =
        needsFragmentPerGlyph || hasRelativePosition || angle ||
        angle != lastAngle || applySpacingToNextCharacter;

    // If we already started a fragment, close it now.
    if (didStartTextFragment && shouldStartNewFragment) {
      applySpacingToNextCharacter = false;
      recordTextFragment(textBox);
    }

    // Eventually start a new fragment, if not yet done.
    if (!didStartTextFragment || shouldStartNewFragment) {
      ASSERT(!m_currentTextFragment.characterOffset);
      ASSERT(!m_currentTextFragment.length);

      didStartTextFragment = true;
      m_currentTextFragment.characterOffset =
          m_visualMetricsIterator.characterOffset();
      m_currentTextFragment.metricsListOffset =
          m_visualMetricsIterator.metricsListOffset();
      m_currentTextFragment.x = position.x();
      m_currentTextFragment.y = position.y();

      // Build fragment transformation.
      if (angle)
        m_currentTextFragment.transform.rotate(angle);

      if (textPathShift.x() || textPathShift.y())
        m_currentTextFragment.transform.translate(textPathShift.x(),
                                                  textPathShift.y());

      // For vertical text, always rotate by 90 degrees regardless of
      // fontOrientation.
      // The shaping engine takes care of the necessary orientation.
      if (m_isVerticalText)
        m_currentTextFragment.transform.rotate(90);

      m_currentTextFragment.isVertical = m_isVerticalText;
      m_currentTextFragment.isTextOnPath =
          m_inPathLayout && m_textPathScaling != 1;
      if (m_currentTextFragment.isTextOnPath)
        m_currentTextFragment.lengthAdjustScale = m_textPathScaling;
    }

    // Advance current text position after processing of the current character
    // finished.
    advanceCurrentTextPosition(glyphAdvance + spacing);

    // Apply CSS 'letter-spacing' and 'word-spacing' to the next character, if
    // needed.
    if (!m_inPathLayout && spacing)
      applySpacingToNextCharacter = true;

    advanceToNextLogicalCharacter(logicalMetrics);
    m_visualMetricsIterator.next();
    lastAngle = angle;
  }

  if (!didStartTextFragment)
    return;

  // Close last open fragment, if needed.
  recordTextFragment(textBox);
}

}  // namespace blink
