/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/pdf/SkPDFMakeCIDGlyphWidthsArray.h"

#include "include/core/SkPaint.h"
#include "include/private/SkTo.h"
#include "src/core/SkScalerCache.h"
#include "src/core/SkStrikeSpec.h"
#include "src/pdf/SkPDFGlyphUse.h"

#include <algorithm>
#include <vector>

// TODO(halcanary): Write unit tests for SkPDFMakeCIDGlyphWidthsArray().

// TODO(halcanary): The logic in this file originated in several
// disparate places.  I feel sure that someone could simplify this
// down to a single easy-to-read function.

namespace {

// scale from em-units to base-1000, returning as a SkScalar
SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
    if (emSize == 1000) {
        return scaled;
    } else {
        return scaled * 1000 / emSize;
    }
}

SkScalar scale_from_font_units(int16_t val, uint16_t emSize) {
    return from_font_units(SkIntToScalar(val), emSize);
}

// Unfortunately poppler does not appear to respect the default width setting.
#if defined(SK_PDF_CAN_USE_DW)
int16_t findMode(SkSpan<const int16_t> advances) {
    if (advances.empty()) {
        return 0;
    }

    int16_t previousAdvance = advances[0];
    int16_t currentModeAdvance = advances[0];
    size_t currentCount = 1;
    size_t currentModeCount = 1;

    for (size_t i = 1; i < advances.size(); ++i) {
        if (advances[i] == previousAdvance) {
            ++currentCount;
        } else {
            if (currentCount > currentModeCount) {
                currentModeAdvance = previousAdvance;
                currentModeCount = currentCount;
            }
            previousAdvance = advances[i];
            currentCount = 1;
        }
    }

    return currentCount > currentModeCount ? previousAdvance : currentModeAdvance;
}
#endif
} // namespace

/** Retrieve advance data for glyphs. Used by the PDF backend. */
// TODO(halcanary): this function is complex enough to need its logic
// tested with unit tests.
std::unique_ptr<SkPDFArray> SkPDFMakeCIDGlyphWidthsArray(const SkTypeface& typeface,
                                                         const SkPDFGlyphUse& subset,
                                                         SkScalar* defaultAdvance) {
    // There are two ways of expressing advances
    //
    // range: " gfid [adv.ances adv.ances ... adv.ances]"
    //   run: " gfid gfid adv.ances"
    //
    // Assuming that on average
    // the ASCII representation of an advance plus a space is 10 characters
    // the ASCII representation of a glyph id plus a space is 4 characters
    // the ASCII representation of unused gid plus a space in a range is 2 characters
    //
    // When not in a range or run
    //  a. Skipping don't cares or defaults is a win (trivial)
    //  b. Run wins for 2+ repeats " gid gid adv.ances"
    //                             " gid [adv.ances adv.ances]"
    //     rule: 2+ repeats create run as long as possible, else start range
    //
    // When in a range
    // Cost of stopping and starting a range is 8 characters  "] gid ["
    //  c. Skipping defaults is always a win                  " adv.ances"
    //     rule: end range if default seen
    //  d. Skipping 4+ don't cares is a win                   " 0 0 0 0"
    //     rule: end range if 4+ don't cares
    // Cost of stop and start range plus run is 28 characters "] gid gid adv.ances gid ["
    //  e. Switching for 2+ repeats and 4+ don't cares wins   " 0 0 adv.ances 0 0 adv.ances"
    //     rule: end range for 2+ repeats with 4+ don't cares
    //  f. Switching for 3+ repeats wins                      " adv.ances adv.ances adv.ances"
    //     rule: end range for 3+ repeats

    int emSize;
    SkStrikeSpec strikeSpec = SkStrikeSpec::MakePDFVector(typeface, &emSize);
    SkBulkGlyphMetricsAndPaths paths{strikeSpec};

    auto result = SkPDFMakeArray();

    std::vector<SkGlyphID> glyphIDs;
    subset.getSetValues([&](unsigned index) {
        glyphIDs.push_back(SkToU16(index));
    });
    auto glyphs = paths.glyphs(SkSpan(glyphIDs));

#if defined(SK_PDF_CAN_USE_DW)
    std::vector<int16_t> advances;
    advances.reserve_back(glyphs.size());
    for (const SkGlyph* glyph : glyphs) {
        advances.push_back((int16_t)glyph->advanceX());
    }
    std::sort(advances.begin(), advances.end());
    int16_t modeAdvance = findMode(SkMakeSpan(advances));
    *defaultAdvance = scale_from_font_units(modeAdvance, emSize);
#else
    *defaultAdvance = 0;
#endif

    for (size_t i = 0; i < glyphs.size(); ++i) {
        int16_t advance = (int16_t)glyphs[i]->advanceX();

#if defined(SK_PDF_CAN_USE_DW)
        // a. Skipping don't cares or defaults is a win (trivial)
        if (advance == modeAdvance) {
            continue;
        }
#endif

        // b. 2+ repeats create run as long as possible, else start range
        {
            size_t j = i + 1; // j is always one past the last known repeat
            for (; j < glyphs.size(); ++j) {
                int16_t next_advance = (int16_t)glyphs[j]->advanceX();
                if (advance != next_advance) {
                    break;
                }
            }
            if (j - i >= 2) {
                result->appendInt(glyphs[i]->getGlyphID());
                result->appendInt(glyphs[j - 1]->getGlyphID());
                result->appendScalar(scale_from_font_units(advance, emSize));
                i = j - 1;
                continue;
            }
        }

        {
            result->appendInt(glyphs[i]->getGlyphID());
            auto advanceArray = SkPDFMakeArray();
            advanceArray->appendScalar(scale_from_font_units(advance, emSize));
            size_t j = i + 1; // j is always one past the last output
            for (; j < glyphs.size(); ++j) {
                advance = (int16_t)glyphs[j]->advanceX();
#if defined(SK_PDF_CAN_USE_DW)
                // c. end range if default seen
                if (advance == modeAdvance) {
                    break;
                }
#endif

                int dontCares = glyphs[j]->getGlyphID() - glyphs[j - 1]->getGlyphID() - 1;
                // d. end range if 4+ don't cares
                if (dontCares >= 4) {
                    break;
                }

                int16_t next_advance = 0;
                // e. end range for 2+ repeats with 4+ don't cares
                if (j + 1 < glyphs.size()) {
                    next_advance = (int16_t)glyphs[j+1]->advanceX();
                    int next_dontCares = glyphs[j+1]->getGlyphID() - glyphs[j]->getGlyphID() - 1;
                    if (advance == next_advance && dontCares + next_dontCares >= 4) {
                        break;
                    }
                }

                // f. end range for 3+ repeats
                if (j + 2 < glyphs.size() && advance == next_advance) {
                    next_advance = (int16_t)glyphs[j+2]->advanceX();
                    if (advance == next_advance) {
                        break;
                    }
                }

                while (dontCares --> 0) {
                    advanceArray->appendScalar(0);
                }
                advanceArray->appendScalar(scale_from_font_units(advance, emSize));
            }
            result->appendObject(std::move(advanceArray));
            i = j - 1;
        }
    }

    return result;
}
