/*
 * Copyright (C) 2007 Rob Buis <buis@kde.org>
 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) Research In Motion Limited 2010. 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/line/SVGInlineTextBox.h"

#include "core/layout/HitTestResult.h"
#include "core/layout/PointerEventsHitRules.h"
#include "core/layout/api/LineLayoutSVGInlineText.h"
#include "core/layout/svg/LayoutSVGInlineText.h"
#include "core/paint/SVGInlineTextBoxPainter.h"
#include "wtf/MathExtras.h"

namespace blink {

struct ExpectedSVGInlineTextBoxSize : public InlineTextBox {
  LayoutUnit float1;
  uint32_t bitfields : 1;
  Vector<SVGTextFragment> vector;
};

static_assert(sizeof(SVGInlineTextBox) == sizeof(ExpectedSVGInlineTextBoxSize),
              "SVGInlineTextBox has an unexpected size");

SVGInlineTextBox::SVGInlineTextBox(LineLayoutItem item,
                                   int start,
                                   unsigned short length)
    : InlineTextBox(item, start, length), m_startsNewTextChunk(false) {}

void SVGInlineTextBox::dirtyLineBoxes() {
  InlineTextBox::dirtyLineBoxes();

  // Clear the now stale text fragments.
  clearTextFragments();

  // And clear any following text fragments as the text on which they depend may
  // now no longer exist, or glyph positions may be wrong.
  InlineTextBox* nextBox = nextTextBox();
  if (nextBox)
    nextBox->dirtyLineBoxes();
}

int SVGInlineTextBox::offsetForPosition(LayoutUnit, bool) const {
  // SVG doesn't use the standard offset <-> position selection system, as it's
  // not suitable for SVGs complex needs. Vertical text selection, inline boxes
  // spanning multiple lines (contrary to HTML, etc.)
  ASSERT_NOT_REACHED();
  return 0;
}

int SVGInlineTextBox::offsetForPositionInFragment(
    const SVGTextFragment& fragment,
    LayoutUnit position,
    bool includePartialGlyphs) const {
  LineLayoutSVGInlineText lineLayoutItem =
      LineLayoutSVGInlineText(this->getLineLayoutItem());

  float scalingFactor = lineLayoutItem.scalingFactor();
  ASSERT(scalingFactor);

  const ComputedStyle& style = lineLayoutItem.styleRef();

  TextRun textRun = constructTextRun(style, fragment);

  // Eventually handle lengthAdjust="spacingAndGlyphs".
  // FIXME: Handle vertical text.
  if (fragment.isTransformed()) {
    AffineTransform fragmentTransform = fragment.buildFragmentTransform();
    textRun.setHorizontalGlyphStretch(
        clampTo<float>(fragmentTransform.xScale()));
  }

  return fragment.characterOffset - start() +
         lineLayoutItem.scaledFont().offsetForPosition(
             textRun, position * scalingFactor, includePartialGlyphs);
}

LayoutUnit SVGInlineTextBox::positionForOffset(int) const {
  // SVG doesn't use the offset <-> position selection system.
  ASSERT_NOT_REACHED();
  return LayoutUnit();
}

FloatRect SVGInlineTextBox::selectionRectForTextFragment(
    const SVGTextFragment& fragment,
    int startPosition,
    int endPosition,
    const ComputedStyle& style) const {
  ASSERT(startPosition < endPosition);

  LineLayoutSVGInlineText lineLayoutItem =
      LineLayoutSVGInlineText(this->getLineLayoutItem());

  float scalingFactor = lineLayoutItem.scalingFactor();
  ASSERT(scalingFactor);

  const Font& scaledFont = lineLayoutItem.scaledFont();
  const FontMetrics& scaledFontMetrics = scaledFont.getFontMetrics();
  FloatPoint textOrigin(fragment.x, fragment.y);
  if (scalingFactor != 1)
    textOrigin.scale(scalingFactor, scalingFactor);

  textOrigin.move(0, -scaledFontMetrics.floatAscent());

  FloatRect selectionRect = scaledFont.selectionRectForText(
      constructTextRun(style, fragment), textOrigin,
      fragment.height * scalingFactor, startPosition, endPosition);
  if (scalingFactor == 1)
    return selectionRect;

  selectionRect.scale(1 / scalingFactor);
  return selectionRect;
}

LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition,
                                                int endPosition) const {
  int boxStart = start();
  startPosition = std::max(startPosition - boxStart, 0);
  endPosition = std::min(endPosition - boxStart, static_cast<int>(len()));
  if (startPosition >= endPosition)
    return LayoutRect();

  const ComputedStyle& style = getLineLayoutItem().styleRef();

  FloatRect selectionRect;
  int fragmentStartPosition = 0;
  int fragmentEndPosition = 0;

  unsigned textFragmentsSize = m_textFragments.size();
  for (unsigned i = 0; i < textFragmentsSize; ++i) {
    const SVGTextFragment& fragment = m_textFragments.at(i);

    fragmentStartPosition = startPosition;
    fragmentEndPosition = endPosition;
    if (!mapStartEndPositionsIntoFragmentCoordinates(
            fragment, fragmentStartPosition, fragmentEndPosition))
      continue;

    FloatRect fragmentRect = selectionRectForTextFragment(
        fragment, fragmentStartPosition, fragmentEndPosition, style);
    if (fragment.isTransformed())
      fragmentRect = fragment.buildFragmentTransform().mapRect(fragmentRect);

    selectionRect.unite(fragmentRect);
  }

  return LayoutRect(enclosingIntRect(selectionRect));
}

void SVGInlineTextBox::paint(const PaintInfo& paintInfo,
                             const LayoutPoint& paintOffset,
                             LayoutUnit,
                             LayoutUnit) const {
  SVGInlineTextBoxPainter(*this).paint(paintInfo, paintOffset);
}

TextRun SVGInlineTextBox::constructTextRun(
    const ComputedStyle& style,
    const SVGTextFragment& fragment) const {
  LineLayoutText text = getLineLayoutItem();
  CHECK(!text.needsLayout());

  TextRun run(
      // characters, will be set below if non-zero.
      static_cast<const LChar*>(nullptr),
      0,  // length, will be set below if non-zero.
      0,  // xPos, only relevant with allowTabs=true
      0,  // padding, only relevant for justified text, not relevant for SVG
      TextRun::AllowTrailingExpansion, direction(),
      dirOverride() ||
          style.rtlOrdering() == VisualOrder /* directionalOverride */);

  if (fragment.length) {
    if (text.is8Bit())
      run.setText(text.characters8() + fragment.characterOffset,
                  fragment.length);
    else
      run.setText(text.characters16() + fragment.characterOffset,
                  fragment.length);
  }

  // We handle letter & word spacing ourselves.
  run.disableSpacing();

  // Propagate the maximum length of the characters buffer to the TextRun, even
  // when we're only processing a substring.
  run.setCharactersLength(text.textLength() - fragment.characterOffset);
  ASSERT(run.charactersLength() >= run.length());
  return run;
}

bool SVGInlineTextBox::mapStartEndPositionsIntoFragmentCoordinates(
    const SVGTextFragment& fragment,
    int& startPosition,
    int& endPosition) const {
  int fragmentOffsetInBox =
      static_cast<int>(fragment.characterOffset) - start();

  // Compute positions relative to the fragment.
  startPosition -= fragmentOffsetInBox;
  endPosition -= fragmentOffsetInBox;

  // Intersect with the fragment range.
  startPosition = std::max(startPosition, 0);
  endPosition = std::min(endPosition, static_cast<int>(fragment.length));

  return startPosition < endPosition;
}

void SVGInlineTextBox::paintDocumentMarker(GraphicsContext&,
                                           const LayoutPoint&,
                                           DocumentMarker*,
                                           const ComputedStyle&,
                                           const Font&,
                                           bool) const {
  // SVG does not have support for generic document markers (e.g.,
  // spellchecking, etc).
}

void SVGInlineTextBox::paintTextMatchMarkerForeground(
    const PaintInfo& paintInfo,
    const LayoutPoint& point,
    DocumentMarker* marker,
    const ComputedStyle& style,
    const Font& font) const {
  SVGInlineTextBoxPainter(*this).paintTextMatchMarkerForeground(
      paintInfo, point, marker, style, font);
}

void SVGInlineTextBox::paintTextMatchMarkerBackground(
    const PaintInfo& paintInfo,
    const LayoutPoint& point,
    DocumentMarker* marker,
    const ComputedStyle& style,
    const Font& font) const {
  SVGInlineTextBoxPainter(*this).paintTextMatchMarkerBackground(
      paintInfo, point, marker, style, font);
}

LayoutRect SVGInlineTextBox::calculateBoundaries() const {
  LineLayoutSVGInlineText lineLayoutItem =
      LineLayoutSVGInlineText(this->getLineLayoutItem());
  float scalingFactor = lineLayoutItem.scalingFactor();
  ASSERT(scalingFactor);
  LayoutUnit baseline(
      lineLayoutItem.scaledFont().getFontMetrics().floatAscent() /
      scalingFactor);

  LayoutRect textBoundingRect;
  for (const SVGTextFragment& fragment : m_textFragments)
    textBoundingRect.unite(LayoutRect(fragment.overflowBoundingBox(baseline)));

  return textBoundingRect;
}

bool SVGInlineTextBox::nodeAtPoint(HitTestResult& result,
                                   const HitTestLocation& locationInContainer,
                                   const LayoutPoint& accumulatedOffset,
                                   LayoutUnit,
                                   LayoutUnit) {
  // FIXME: integrate with InlineTextBox::nodeAtPoint better.
  ASSERT(!isLineBreak());

  PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING,
                                 result.hitTestRequest(),
                                 getLineLayoutItem().style()->pointerEvents());
  bool isVisible =
      getLineLayoutItem().style()->visibility() == EVisibility::Visible;
  if (isVisible || !hitRules.requireVisible) {
    if (hitRules.canHitBoundingBox ||
        (hitRules.canHitStroke &&
         (getLineLayoutItem().style()->svgStyle().hasStroke() ||
          !hitRules.requireStroke)) ||
        (hitRules.canHitFill &&
         (getLineLayoutItem().style()->svgStyle().hasFill() ||
          !hitRules.requireFill))) {
      LayoutRect rect(topLeft(), LayoutSize(logicalWidth(), logicalHeight()));
      rect.moveBy(accumulatedOffset);
      if (locationInContainer.intersects(rect)) {
        LineLayoutSVGInlineText lineLayoutItem =
            LineLayoutSVGInlineText(this->getLineLayoutItem());
        ASSERT(lineLayoutItem.scalingFactor());
        float baseline =
            lineLayoutItem.scaledFont().getFontMetrics().floatAscent() /
            lineLayoutItem.scalingFactor();

        FloatPoint floatLocation = FloatPoint(locationInContainer.point());
        for (const SVGTextFragment& fragment : m_textFragments) {
          FloatQuad fragmentQuad = fragment.boundingQuad(baseline);
          if (fragmentQuad.containsPoint(floatLocation)) {
            lineLayoutItem.updateHitTestResult(
                result,
                locationInContainer.point() - toLayoutSize(accumulatedOffset));
            if (result.addNodeToListBasedTestResult(lineLayoutItem.node(),
                                                    locationInContainer,
                                                    rect) == StopHitTesting)
              return true;
          }
        }
      }
    }
  }
  return false;
}

}  // namespace blink
