/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2000 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved.
 * Copyright (c) 2007, 2008, 2010 Google Inc. 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 "platform/fonts/Font.h"

#include "platform/LayoutTestSupport.h"
#include "platform/LayoutUnit.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/fonts/CharacterRange.h"
#include "platform/fonts/FontCache.h"
#include "platform/fonts/FontFallbackIterator.h"
#include "platform/fonts/FontFallbackList.h"
#include "platform/fonts/GlyphBuffer.h"
#include "platform/fonts/SimpleFontData.h"
#include "platform/fonts/shaping/CachingWordShaper.h"
#include "platform/geometry/FloatRect.h"
#include "platform/text/BidiResolver.h"
#include "platform/text/Character.h"
#include "platform/text/TextRun.h"
#include "platform/text/TextRunIterator.h"
#include "platform/transforms/AffineTransform.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkTextBlob.h"
#include "wtf/StdLibExtras.h"
#include "wtf/text/CharacterNames.h"
#include "wtf/text/Unicode.h"

using namespace WTF;
using namespace Unicode;

namespace blink {

Font::Font() : m_canShapeWordByWord(0), m_shapeWordByWordComputed(0) {}

Font::Font(const FontDescription& fd)
    : m_fontDescription(fd),
      m_canShapeWordByWord(0),
      m_shapeWordByWordComputed(0) {}

Font::Font(const Font& other)
    : m_fontDescription(other.m_fontDescription),
      m_fontFallbackList(other.m_fontFallbackList),
      // TODO(yosin): We should have a comment the reason why don't we copy
      // |m_canShapeWordByWord| and |m_shapeWordByWordComputed| from |other|,
      // since |operator=()| copies them from |other|.
      m_canShapeWordByWord(0),
      m_shapeWordByWordComputed(0) {}

Font& Font::operator=(const Font& other) {
  m_fontDescription = other.m_fontDescription;
  m_fontFallbackList = other.m_fontFallbackList;
  m_canShapeWordByWord = other.m_canShapeWordByWord;
  m_shapeWordByWordComputed = other.m_shapeWordByWordComputed;
  return *this;
}

bool Font::operator==(const Font& other) const {
  FontSelector* first =
      m_fontFallbackList ? m_fontFallbackList->getFontSelector() : 0;
  FontSelector* second = other.m_fontFallbackList
                             ? other.m_fontFallbackList->getFontSelector()
                             : 0;

  return first == second && m_fontDescription == other.m_fontDescription &&
         (m_fontFallbackList ? m_fontFallbackList->fontSelectorVersion() : 0) ==
             (other.m_fontFallbackList
                  ? other.m_fontFallbackList->fontSelectorVersion()
                  : 0) &&
         (m_fontFallbackList ? m_fontFallbackList->generation() : 0) ==
             (other.m_fontFallbackList ? other.m_fontFallbackList->generation()
                                       : 0);
}

void Font::update(FontSelector* fontSelector) const {
  // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr,
  // but it ends up being reasonably safe (because inherited fonts in the render
  // tree pick up the new style anyway. Other copies are transient, e.g., the
  // state in the GraphicsContext, and won't stick around long enough to get you
  // in trouble). Still, this is pretty disgusting, and could eventually be
  // rectified by using RefPtrs for Fonts themselves.
  if (!m_fontFallbackList)
    m_fontFallbackList = FontFallbackList::create();
  m_fontFallbackList->invalidate(fontSelector);
}

float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo,
                             GlyphBuffer& glyphBuffer,
                             const GlyphData* emphasisData) const {
  float width;
  CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription));
  if (emphasisData) {
    width = shaper.fillGlyphBufferForTextEmphasis(this, runInfo.run,
                                                  emphasisData, &glyphBuffer,
                                                  runInfo.from, runInfo.to);
  } else {
    width = shaper.fillGlyphBuffer(this, runInfo.run, nullptr, &glyphBuffer,
                                   runInfo.from, runInfo.to);
  }
  return width;
}

bool Font::drawText(SkCanvas* canvas,
                    const TextRunPaintInfo& runInfo,
                    const FloatPoint& point,
                    float deviceScaleFactor,
                    const SkPaint& paint) const {
  // Don't draw anything while we are using custom fonts that are in the process
  // of loading.
  if (shouldSkipDrawing())
    return false;

  if (runInfo.cachedTextBlob && runInfo.cachedTextBlob->get()) {
    // we have a pre-cached blob -- happy joy!
    canvas->drawTextBlob(runInfo.cachedTextBlob->get(), point.x(), point.y(),
                         paint);
    return true;
  }

  GlyphBuffer glyphBuffer;
  buildGlyphBuffer(runInfo, glyphBuffer);

  drawGlyphBuffer(canvas, paint, runInfo, glyphBuffer, point,
                  deviceScaleFactor);
  return true;
}

bool Font::drawBidiText(SkCanvas* canvas,
                        const TextRunPaintInfo& runInfo,
                        const FloatPoint& point,
                        CustomFontNotReadyAction customFontNotReadyAction,
                        float deviceScaleFactor,
                        const SkPaint& paint) const {
  // Don't draw anything while we are using custom fonts that are in the process
  // of loading, except if the 'force' argument is set to true (in which case it
  // will use a fallback font).
  if (shouldSkipDrawing() &&
      customFontNotReadyAction == DoNotPaintIfFontNotReady)
    return false;

  // sub-run painting is not supported for Bidi text.
  const TextRun& run = runInfo.run;
  ASSERT((runInfo.from == 0) && (runInfo.to == run.length()));
  BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
  bidiResolver.setStatus(
      BidiStatus(run.direction(), run.directionalOverride()));
  bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0));

  // FIXME: This ownership should be reversed. We should pass BidiRunList
  // to BidiResolver in createBidiRunsForLine.
  BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs();
  bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length()));
  if (!bidiRuns.runCount())
    return true;

  FloatPoint currPoint = point;
  BidiCharacterRun* bidiRun = bidiRuns.firstRun();
  while (bidiRun) {
    TextRun subrun =
        run.subRun(bidiRun->start(), bidiRun->stop() - bidiRun->start());
    bool isRTL = bidiRun->level() % 2;
    subrun.setDirection(isRTL ? TextDirection::Rtl : TextDirection::Ltr);
    subrun.setDirectionalOverride(bidiRun->dirOverride(false));

    TextRunPaintInfo subrunInfo(subrun);
    subrunInfo.bounds = runInfo.bounds;

    // TODO: investigate blob consolidation/caching (technically,
    //       all subruns could be part of the same blob).
    GlyphBuffer glyphBuffer;
    float runWidth = buildGlyphBuffer(subrunInfo, glyphBuffer);
    drawGlyphBuffer(canvas, paint, subrunInfo, glyphBuffer, currPoint,
                    deviceScaleFactor);

    bidiRun = bidiRun->next();
    currPoint.move(runWidth, 0);
  }

  bidiRuns.deleteRuns();
  return true;
}

void Font::drawEmphasisMarks(SkCanvas* canvas,
                             const TextRunPaintInfo& runInfo,
                             const AtomicString& mark,
                             const FloatPoint& point,
                             float deviceScaleFactor,
                             const SkPaint& paint) const {
  if (shouldSkipDrawing())
    return;

  FontCachePurgePreventer purgePreventer;

  GlyphData emphasisGlyphData;
  if (!getEmphasisMarkGlyphData(mark, emphasisGlyphData))
    return;

  ASSERT(emphasisGlyphData.fontData);
  if (!emphasisGlyphData.fontData)
    return;

  GlyphBuffer glyphBuffer;
  buildGlyphBuffer(runInfo, glyphBuffer, &emphasisGlyphData);

  if (glyphBuffer.isEmpty())
    return;

  drawGlyphBuffer(canvas, paint, runInfo, glyphBuffer, point,
                  deviceScaleFactor);
}

float Font::width(const TextRun& run,
                  HashSet<const SimpleFontData*>* fallbackFonts,
                  FloatRect* glyphBounds) const {
  FontCachePurgePreventer purgePreventer;
  CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription));
  float width = shaper.width(this, run, fallbackFonts, glyphBounds);
  return width;
}

namespace {

enum BlobRotation {
  NoRotation,
  CCWRotation,
};

class GlyphBufferBloberizer {
  STACK_ALLOCATED()
 public:
  GlyphBufferBloberizer(const GlyphBuffer& buffer,
                        const Font* font,
                        float deviceScaleFactor)
      : m_buffer(buffer),
        m_font(font),
        m_deviceScaleFactor(deviceScaleFactor),
        m_hasVerticalOffsets(buffer.hasVerticalOffsets()),
        m_index(0),
        m_blobCount(0),
        m_rotation(buffer.isEmpty() ? NoRotation : computeBlobRotation(
                                                       buffer.fontDataAt(0))) {}

  bool done() const { return m_index >= m_buffer.size(); }
  unsigned blobCount() const { return m_blobCount; }

  std::pair<sk_sp<SkTextBlob>, BlobRotation> next() {
    ASSERT(!done());
    const BlobRotation currentRotation = m_rotation;

    while (m_index < m_buffer.size()) {
      const SimpleFontData* fontData = m_buffer.fontDataAt(m_index);
      ASSERT(fontData);

      const BlobRotation newRotation = computeBlobRotation(fontData);
      if (newRotation != m_rotation) {
        // We're switching to an orientation which requires a different rotation
        //   => emit the pending blob (and start a new one with the new
        //      rotation).
        m_rotation = newRotation;
        break;
      }

      const unsigned start = m_index++;
      while (m_index < m_buffer.size() &&
             m_buffer.fontDataAt(m_index) == fontData)
        m_index++;

      appendRun(start, m_index - start, fontData);
    }

    m_blobCount++;
    return std::make_pair(m_builder.make(), currentRotation);
  }

 private:
  static BlobRotation computeBlobRotation(const SimpleFontData* font) {
    // For vertical upright text we need to compensate the inherited 90deg CW
    // rotation (using a 90deg CCW rotation).
    return (font->platformData().isVerticalAnyUpright() && font->verticalData())
               ? CCWRotation
               : NoRotation;
  }

  void appendRun(unsigned start,
                 unsigned count,
                 const SimpleFontData* fontData) {
    SkPaint paint;
    fontData->platformData().setupPaint(&paint, m_deviceScaleFactor, m_font);
    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);

    const SkTextBlobBuilder::RunBuffer& buffer =
        m_hasVerticalOffsets ? m_builder.allocRunPos(paint, count)
                             : m_builder.allocRunPosH(paint, count, 0);

    const uint16_t* glyphs = m_buffer.glyphs(start);
    const float* offsets = m_buffer.offsets(start);
    std::copy(glyphs, glyphs + count, buffer.glyphs);

    if (m_rotation == NoRotation) {
      std::copy(offsets, offsets + (m_hasVerticalOffsets ? 2 * count : count),
                buffer.pos);
    } else {
      ASSERT(m_hasVerticalOffsets);

      const float verticalBaselineXOffset =
          fontData->getFontMetrics().floatAscent() -
          fontData->getFontMetrics().floatAscent(IdeographicBaseline);

      // TODO(fmalita): why don't we apply this adjustment when building the
      // glyph buffer?
      for (unsigned i = 0; i < 2 * count; i += 2) {
        buffer.pos[i] = SkFloatToScalar(offsets[i] + verticalBaselineXOffset);
        buffer.pos[i + 1] = SkFloatToScalar(offsets[i + 1]);
      }
    }
  }

  const GlyphBuffer& m_buffer;
  const Font* m_font;
  const float m_deviceScaleFactor;
  const bool m_hasVerticalOffsets;

  SkTextBlobBuilder m_builder;
  unsigned m_index;
  unsigned m_blobCount;
  BlobRotation m_rotation;
};

}  // anonymous namespace

void Font::drawGlyphBuffer(SkCanvas* canvas,
                           const SkPaint& paint,
                           const TextRunPaintInfo& runInfo,
                           const GlyphBuffer& glyphBuffer,
                           const FloatPoint& point,
                           float deviceScaleFactor) const {
  GlyphBufferBloberizer bloberizer(glyphBuffer, this, deviceScaleFactor);
  std::pair<sk_sp<SkTextBlob>, BlobRotation> blob;

  while (!bloberizer.done()) {
    blob = bloberizer.next();
    ASSERT(blob.first);

    SkAutoCanvasRestore autoRestore(canvas, false);
    if (blob.second == CCWRotation) {
      canvas->save();

      SkMatrix m;
      m.setSinCos(-1, 0, point.x(), point.y());
      canvas->concat(m);
    }

    canvas->drawTextBlob(blob.first, point.x(), point.y(), paint);
  }

  // Cache results when
  //   1) requested by clients, and
  //   2) the glyph buffer is encoded as a single blob, and
  //   3) the blob is not upright/rotated
  if (runInfo.cachedTextBlob && bloberizer.blobCount() == 1 &&
      blob.second == NoRotation) {
    ASSERT(!*runInfo.cachedTextBlob);
    *runInfo.cachedTextBlob = std::move(blob.first);
    ASSERT(*runInfo.cachedTextBlob);
  }
}

static int getInterceptsFromBloberizer(const GlyphBuffer& glyphBuffer,
                                       const Font* font,
                                       const SkPaint& paint,
                                       float deviceScaleFactor,
                                       const std::tuple<float, float>& bounds,
                                       SkScalar* interceptsBuffer) {
  SkScalar boundsArray[2] = {std::get<0>(bounds), std::get<1>(bounds)};
  GlyphBufferBloberizer bloberizer(glyphBuffer, font, deviceScaleFactor);
  std::pair<sk_sp<SkTextBlob>, BlobRotation> blob;

  int numIntervals = 0;
  while (!bloberizer.done()) {
    blob = bloberizer.next();
    DCHECK(blob.first);

    // GlyphBufferBloberizer splits for a new blob rotation, but does not split
    // for a change in font. A TextBlob can contain runs with differing fonts
    // and the getTextBlobIntercepts method handles multiple fonts for us. For
    // upright in vertical blobs we currently have to bail, see crbug.com/655154
    if (blob.second == BlobRotation::CCWRotation)
      continue;

    SkScalar* offsetInterceptsBuffer = nullptr;
    if (interceptsBuffer)
      offsetInterceptsBuffer = &interceptsBuffer[numIntervals];
    numIntervals += paint.getTextBlobIntercepts(blob.first.get(), boundsArray,
                                                offsetInterceptsBuffer);
  }
  return numIntervals;
}

void Font::getTextIntercepts(const TextRunPaintInfo& runInfo,
                             float deviceScaleFactor,
                             const SkPaint& paint,
                             const std::tuple<float, float>& bounds,
                             Vector<TextIntercept>& intercepts) const {
  if (shouldSkipDrawing())
    return;

  if (runInfo.cachedTextBlob && runInfo.cachedTextBlob->get()) {
    SkScalar boundsArray[2] = {std::get<0>(bounds), std::get<1>(bounds)};
    int numIntervals = paint.getTextBlobIntercepts(
        runInfo.cachedTextBlob->get(), boundsArray, nullptr);
    if (!numIntervals)
      return;
    DCHECK_EQ(numIntervals % 2, 0);
    intercepts.resize(numIntervals / 2);
    paint.getTextBlobIntercepts(runInfo.cachedTextBlob->get(), boundsArray,
                                reinterpret_cast<SkScalar*>(intercepts.data()));
    return;
  }

  GlyphBuffer glyphBuffer;
  buildGlyphBuffer(runInfo, glyphBuffer);

  // Get the number of intervals, without copying the actual values by
  // specifying nullptr for the buffer, following the Skia allocation model for
  // retrieving text intercepts.
  int numIntervals = getInterceptsFromBloberizer(
      glyphBuffer, this, paint, deviceScaleFactor, bounds, nullptr);
  if (!numIntervals)
    return;
  DCHECK_EQ(numIntervals % 2, 0);
  intercepts.resize(numIntervals / 2);

  getInterceptsFromBloberizer(glyphBuffer, this, paint, deviceScaleFactor,
                              bounds,
                              reinterpret_cast<SkScalar*>(intercepts.data()));
}

static inline FloatRect pixelSnappedSelectionRect(FloatRect rect) {
  // Using roundf() rather than ceilf() for the right edge as a compromise to
  // ensure correct caret positioning.
  float roundedX = roundf(rect.x());
  return FloatRect(roundedX, rect.y(), roundf(rect.maxX() - roundedX),
                   rect.height());
}

FloatRect Font::selectionRectForText(const TextRun& run,
                                     const FloatPoint& point,
                                     int height,
                                     int from,
                                     int to,
                                     bool accountForGlyphBounds) const {
  to = (to == -1 ? run.length() : to);

  TextRunPaintInfo runInfo(run);
  runInfo.from = from;
  runInfo.to = to;

  FontCachePurgePreventer purgePreventer;

  CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription));
  CharacterRange range = shaper.getCharacterRange(this, run, from, to);

  return pixelSnappedSelectionRect(
      FloatRect(point.x() + range.start, point.y(), range.width(), height));
}

int Font::offsetForPosition(const TextRun& run,
                            float xFloat,
                            bool includePartialGlyphs) const {
  FontCachePurgePreventer purgePreventer;
  CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription));
  return shaper.offsetForPosition(this, run, xFloat, includePartialGlyphs);
}

ShapeCache* Font::shapeCache() const {
  return m_fontFallbackList->shapeCache(m_fontDescription);
}

bool Font::canShapeWordByWord() const {
  if (!m_shapeWordByWordComputed) {
    m_canShapeWordByWord = computeCanShapeWordByWord();
    m_shapeWordByWordComputed = true;
  }
  return m_canShapeWordByWord;
};

bool Font::computeCanShapeWordByWord() const {
  if (!getFontDescription().getTypesettingFeatures())
    return true;

  if (!primaryFont())
    return false;

  const FontPlatformData& platformData = primaryFont()->platformData();
  TypesettingFeatures features = getFontDescription().getTypesettingFeatures();
  return !platformData.hasSpaceInLigaturesOrKerning(features);
};

void Font::willUseFontData(const String& text) const {
  const FontFamily& family = getFontDescription().family();
  if (m_fontFallbackList && m_fontFallbackList->getFontSelector() &&
      !family.familyIsEmpty())
    m_fontFallbackList->getFontSelector()->willUseFontData(
        getFontDescription(), family.family(), text);
}

PassRefPtr<FontFallbackIterator> Font::createFontFallbackIterator(
    FontFallbackPriority fallbackPriority) const {
  return FontFallbackIterator::create(m_fontDescription, m_fontFallbackList,
                                      fallbackPriority);
}

bool Font::getEmphasisMarkGlyphData(const AtomicString& mark,
                                    GlyphData& glyphData) const {
  if (mark.isEmpty())
    return false;

  TextRun emphasisMarkRun(mark, mark.length());
  TextRunPaintInfo emphasisPaintInfo(emphasisMarkRun);
  GlyphBuffer glyphBuffer;
  buildGlyphBuffer(emphasisPaintInfo, glyphBuffer);

  if (glyphBuffer.isEmpty())
    return false;

  ASSERT(glyphBuffer.fontDataAt(0));
  glyphData.fontData =
      glyphBuffer.fontDataAt(0)->emphasisMarkFontData(m_fontDescription).get();
  glyphData.glyph = glyphBuffer.glyphAt(0);

  return true;
}

int Font::emphasisMarkAscent(const AtomicString& mark) const {
  FontCachePurgePreventer purgePreventer;

  GlyphData markGlyphData;
  if (!getEmphasisMarkGlyphData(mark, markGlyphData))
    return 0;

  const SimpleFontData* markFontData = markGlyphData.fontData;
  ASSERT(markFontData);
  if (!markFontData)
    return 0;

  return markFontData->getFontMetrics().ascent();
}

int Font::emphasisMarkDescent(const AtomicString& mark) const {
  FontCachePurgePreventer purgePreventer;

  GlyphData markGlyphData;
  if (!getEmphasisMarkGlyphData(mark, markGlyphData))
    return 0;

  const SimpleFontData* markFontData = markGlyphData.fontData;
  ASSERT(markFontData);
  if (!markFontData)
    return 0;

  return markFontData->getFontMetrics().descent();
}

int Font::emphasisMarkHeight(const AtomicString& mark) const {
  FontCachePurgePreventer purgePreventer;

  GlyphData markGlyphData;
  if (!getEmphasisMarkGlyphData(mark, markGlyphData))
    return 0;

  const SimpleFontData* markFontData = markGlyphData.fontData;
  ASSERT(markFontData);
  if (!markFontData)
    return 0;

  return markFontData->getFontMetrics().height();
}

CharacterRange Font::getCharacterRange(const TextRun& run,
                                       unsigned from,
                                       unsigned to) const {
  FontCachePurgePreventer purgePreventer;
  CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription));
  return shaper.getCharacterRange(this, run, from, to);
}

Vector<CharacterRange> Font::individualCharacterRanges(
    const TextRun& run) const {
  FontCachePurgePreventer purgePreventer;
  CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription));
  auto ranges = shaper.individualCharacterRanges(this, run);
  // The shaper should return ranges.size == run.length but on some platforms
  // (OSX10.9.5) we are seeing cases in the upper end of the unicode range
  // where this is not true (see: crbug.com/620952). To catch these cases on
  // more popular platforms, and to protect users, we are using a CHECK here.
  CHECK_EQ(ranges.size(), run.length());
  return ranges;
}

bool Font::loadingCustomFonts() const {
  return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts();
}

bool Font::isFallbackValid() const {
  return !m_fontFallbackList || m_fontFallbackList->isValid();
}

}  // namespace blink
