/*
 * Copyright (C) 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include "FloatPoint.h"
#include "GlyphBuffer.h"
#include <wtf/HashSet.h>
#include <wtf/RefCounted.h>
#include <wtf/RetainPtr.h>
#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>

typedef unsigned short CGGlyph;

typedef const struct __CTRun * CTRunRef;
typedef const struct __CTLine * CTLineRef;

typedef struct hb_buffer_t hb_buffer_t;

namespace WebCore {

class FontCascade;
class Font;
class TextRun;

enum GlyphIterationStyle { IncludePartialGlyphs, ByWholeGlyphs };

// See https://trac.webkit.org/wiki/ComplexTextController for more information about ComplexTextController.
class ComplexTextController {
    WTF_MAKE_FAST_ALLOCATED;
public:
    ComplexTextController(const FontCascade&, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const Font*>* fallbackFonts = 0, bool forTextEmphasis = false);

    class ComplexTextRun;
    WEBCORE_EXPORT ComplexTextController(const FontCascade&, const TextRun&, Vector<Ref<ComplexTextRun>>&);

    // Advance and emit glyphs up to the specified character.
    WEBCORE_EXPORT void advance(unsigned to, GlyphBuffer* = nullptr, GlyphIterationStyle = IncludePartialGlyphs, HashSet<const Font*>* fallbackFonts = nullptr);

    // Compute the character offset for a given x coordinate.
    unsigned offsetForPosition(float x, bool includePartialGlyphs);

    // Returns the width of everything we've consumed so far.
    float runWidthSoFar() const { return m_runWidthSoFar; }

    FloatSize totalAdvance() const { return m_totalAdvance; }

    float minGlyphBoundingBoxX() const { return m_minGlyphBoundingBoxX; }
    float maxGlyphBoundingBoxX() const { return m_maxGlyphBoundingBoxX; }
    float minGlyphBoundingBoxY() const { return m_minGlyphBoundingBoxY; }
    float maxGlyphBoundingBoxY() const { return m_maxGlyphBoundingBoxY; }

    class ComplexTextRun : public RefCounted<ComplexTextRun> {
    public:
        static Ref<ComplexTextRun> create(CTRunRef ctRun, const Font& font, const UChar* characters, unsigned stringLocation, unsigned stringLength, unsigned indexBegin, unsigned indexEnd)
        {
            return adoptRef(*new ComplexTextRun(ctRun, font, characters, stringLocation, stringLength, indexBegin, indexEnd));
        }

        static Ref<ComplexTextRun> create(hb_buffer_t* buffer, const Font& font, const UChar* characters, unsigned stringLocation, unsigned stringLength, unsigned indexBegin, unsigned indexEnd)
        {
            return adoptRef(*new ComplexTextRun(buffer, font, characters, stringLocation, stringLength, indexBegin, indexEnd));
        }

        static Ref<ComplexTextRun> create(const Font& font, const UChar* characters, unsigned stringLocation, unsigned stringLength, unsigned indexBegin, unsigned indexEnd, bool ltr)
        {
            return adoptRef(*new ComplexTextRun(font, characters, stringLocation, stringLength, indexBegin, indexEnd, ltr));
        }

        static Ref<ComplexTextRun> create(const Vector<FloatSize>& advances, const Vector<FloatPoint>& origins, const Vector<Glyph>& glyphs, const Vector<unsigned>& stringIndices, FloatSize initialAdvance, const Font& font, const UChar* characters, unsigned stringLocation, unsigned stringLength, unsigned indexBegin, unsigned indexEnd, bool ltr)
        {
            return adoptRef(*new ComplexTextRun(advances, origins, glyphs, stringIndices, initialAdvance, font, characters, stringLocation, stringLength, indexBegin, indexEnd, ltr));
        }

        unsigned glyphCount() const { return m_glyphCount; }
        const Font& font() const { return m_font; }
        const UChar* characters() const { return m_characters; }
        unsigned stringLocation() const { return m_stringLocation; }
        unsigned stringLength() const { return m_stringLength; }
        ALWAYS_INLINE unsigned indexAt(unsigned) const;
        unsigned indexBegin() const { return m_indexBegin; }
        unsigned indexEnd() const { return m_indexEnd; }
        unsigned endOffsetAt(unsigned i) const { ASSERT(!m_isMonotonic); return m_glyphEndOffsets[i]; }
        const CGGlyph* glyphs() const { return m_glyphs.data(); }

        /*
         * This is the format of the information CoreText gives us about each run:
         *
         *                                        ----->X (Paint glyph position)   X (Paint glyph position)   X (Paint glyph position)
         *                                       /     7                          7                          7
         *                                      /     /                          /                          /
         *                   (Initial advance) /     / (Glyph origin)           / (Glyph origin)           / (Glyph origin)
         *                  -------------------     /                          /                          /
         *                 /                       /                          /                          /
         *                X                       X--------------------------X--------------------------X--------------------------X
         * (text position ^)                             (base advance)             (base advance)             (base advance)
         *
         *
         *
         *
         *
         * And here is the output we transform this into (for each run):
         *
         *                                        ----->X------------------------->X------------------------->X
         *                                       /            (Paint advance)            (Paint advance)       \
         *                                      /                                                               \
         *                   (Initial advance) /                                                                 \ (Paint advance)
         *                  -------------------                                                                   ----------------
         *                 /                                                                                                      \
         *                X--------------------------------------------------X--------------------------X--------------------------X
         * (text position ^)                (layout advance)                       (layout advance)           (layout advance)
         */
        void growInitialAdvanceHorizontally(float delta) { m_initialAdvance.expand(delta, 0); }
        FloatSize initialAdvance() const { return m_initialAdvance; }
        const FloatSize* baseAdvances() const { return m_baseAdvances.data(); }
        const FloatPoint* glyphOrigins() const { return m_glyphOrigins.size() == glyphCount() ? m_glyphOrigins.data() : nullptr; }
        bool isLTR() const { return m_isLTR; }
        bool isMonotonic() const { return m_isMonotonic; }
        void setIsNonMonotonic();

    private:
        ComplexTextRun(CTRunRef, const Font&, const UChar* characters, unsigned stringLocation, unsigned stringLength, unsigned indexBegin, unsigned indexEnd);
        ComplexTextRun(hb_buffer_t*, const Font&, const UChar* characters, unsigned stringLocation, unsigned stringLength, unsigned indexBegin, unsigned indexEnd);
        ComplexTextRun(const Font&, const UChar* characters, unsigned stringLocation, unsigned stringLength, unsigned indexBegin, unsigned indexEnd, bool ltr);
        WEBCORE_EXPORT ComplexTextRun(const Vector<FloatSize>& advances, const Vector<FloatPoint>& origins, const Vector<Glyph>& glyphs, const Vector<unsigned>& stringIndices, FloatSize initialAdvance, const Font&, const UChar* characters, unsigned stringLocation, unsigned stringLength, unsigned indexBegin, unsigned indexEnd, bool ltr);

        Vector<FloatSize, 64> m_baseAdvances;
        Vector<FloatPoint, 64> m_glyphOrigins;
        Vector<CGGlyph, 64> m_glyphs;
        Vector<unsigned, 64> m_glyphEndOffsets;
        Vector<unsigned, 64> m_coreTextIndices;
        FloatSize m_initialAdvance;
        const Font& m_font;
        const UChar* m_characters;
        unsigned m_stringLength;
        unsigned m_indexBegin;
        unsigned m_indexEnd;
        unsigned m_glyphCount;
        unsigned m_stringLocation;
        bool m_isLTR;
        bool m_isMonotonic { true };
    };
private:
    void computeExpansionOpportunity();
    void finishConstruction();
    
    static unsigned stringBegin(const ComplexTextRun& run) { return run.stringLocation() + run.indexBegin(); }
    static unsigned stringEnd(const ComplexTextRun& run) { return run.stringLocation() + run.indexEnd(); }

    void collectComplexTextRuns();

    void collectComplexTextRunsForCharacters(const UChar*, unsigned length, unsigned stringLocation, const Font*);
    void adjustGlyphsAndAdvances();

    unsigned indexOfCurrentRun(unsigned& leftmostGlyph);
    unsigned incrementCurrentRun(unsigned& leftmostGlyph);

    float runWidthSoFarFraction(unsigned glyphStartOffset, unsigned glyphEndOffset, unsigned oldCharacterInCurrentGlyph, GlyphIterationStyle) const;

    FloatPoint glyphOrigin(unsigned index) const { return index < m_glyphOrigins.size() ? m_glyphOrigins[index] : FloatPoint(); }

    Vector<FloatSize, 256> m_adjustedBaseAdvances;
    Vector<FloatPoint, 256> m_glyphOrigins;
    Vector<CGGlyph, 256> m_adjustedGlyphs;

    Vector<UChar, 256> m_smallCapsBuffer;

    // There is a 3-level hierarchy here. At the top, we are interested in m_run.string(). We partition that string
    // into Lines, each of which is a sequence of characters which should use the same Font. Core Text then partitions
    // the Line into ComplexTextRuns.
    // ComplexTextRun::stringLocation() and ComplexTextRun::stringLength() refer to the offset and length of the Line
    // relative to m_run.string(). ComplexTextRun::indexAt() returns to the offset of a codepoint relative to
    // its Line. ComplexTextRun::glyphs() and ComplexTextRun::advances() refer to glyphs relative to the ComplexTextRun.
    // The length of the entire TextRun is m_run.length()
    Vector<RefPtr<ComplexTextRun>, 16> m_complexTextRuns;

    // The initial capacity of these vectors was selected as being the smallest power of two greater than
    // the average (3.5) plus one standard deviation (7.5) of nonzero sizes used on Arabic Wikipedia.
    Vector<unsigned, 16> m_runIndices;
    Vector<unsigned, 16> m_glyphCountFromStartToIndex;

#if PLATFORM(COCOA)
    Vector<RetainPtr<CTLineRef>> m_coreTextLines;
#endif

    Vector<String> m_stringsFor8BitRuns;

    HashSet<const Font*>* m_fallbackFonts { nullptr };

    const FontCascade& m_font;
    const TextRun& m_run;

    unsigned m_currentCharacter { 0 };
    unsigned m_end { 0 };

    FloatSize m_totalAdvance;
    float m_runWidthSoFar { 0 };
    unsigned m_numGlyphsSoFar { 0 };
    unsigned m_currentRun { 0 };
    unsigned m_glyphInCurrentRun { 0 };
    unsigned m_characterInCurrentGlyph { 0 };
    float m_expansion { 0 };
    float m_expansionPerOpportunity { 0 };

    float m_minGlyphBoundingBoxX { std::numeric_limits<float>::max() };
    float m_maxGlyphBoundingBoxX { std::numeric_limits<float>::min() };
    float m_minGlyphBoundingBoxY { std::numeric_limits<float>::max() };
    float m_maxGlyphBoundingBoxY { std::numeric_limits<float>::min() };

    bool m_isLTROnly { true };
    bool m_mayUseNaturalWritingDirection { false };
    bool m_forTextEmphasis { false };
};

} // namespace WebCore
