/*
 * Copyright 2011 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/SkPDFGraphicState.h"

#include "include/core/SkData.h"
#include "include/core/SkPaint.h"
#include "include/docs/SkPDFDocument.h"
#include "include/private/base/SkTo.h"
#include "src/pdf/SkPDFDocumentPriv.h"
#include "src/pdf/SkPDFFormXObject.h"
#include "src/pdf/SkPDFUtils.h"

static const char* as_pdf_blend_mode_name(SkBlendMode mode) {
    const char* name = SkPDFUtils::BlendModeName(mode);
    SkASSERT(name);
    return name;
}

static int to_stroke_cap(uint8_t cap) {
    // PDF32000.book section 8.4.3.3 "Line Cap Style"
    switch ((SkPaint::Cap)cap) {
        case SkPaint::kButt_Cap:   return 0;
        case SkPaint::kRound_Cap:  return 1;
        case SkPaint::kSquare_Cap: return 2;
        default: SkASSERT(false);  return 0;
    }
}

static int to_stroke_join(uint8_t join) {
    // PDF32000.book section 8.4.3.4 "Line Join Style"
    switch ((SkPaint::Join)join) {
        case SkPaint::kMiter_Join: return 0;
        case SkPaint::kRound_Join: return 1;
        case SkPaint::kBevel_Join: return 2;
        default: SkASSERT(false);  return 0;
    }
}

// If a SkXfermode is unsupported in PDF, this function returns
// SrcOver, otherwise, it returns that Xfermode as a Mode.
static uint8_t pdf_blend_mode(SkBlendMode mode) {
    if (!SkPDFUtils::BlendModeName(mode)
        || SkBlendMode::kXor  == mode
        || SkBlendMode::kPlus == mode)
    {
        mode = SkBlendMode::kSrcOver;
    }
    return SkToU8((unsigned)mode);
}

SkPDFIndirectReference SkPDFGraphicState::GetGraphicStateForPaint(SkPDFDocument* doc,
                                                                  const SkPaint& p) {
    SkASSERT(doc);
    const SkBlendMode mode = p.getBlendMode_or(SkBlendMode::kSrcOver);

    if (SkPaint::kFill_Style == p.getStyle()) {
        SkPDFFillGraphicState fillKey = {p.getColor4f().fA, pdf_blend_mode(mode)};
        auto& fillMap = doc->fFillGSMap;
        if (SkPDFIndirectReference* statePtr = fillMap.find(fillKey)) {
            return *statePtr;
        }
        SkPDFDict state;
        state.reserve(2);
        state.insertColorComponentF("ca", fillKey.fAlpha);
        state.insertName("BM", as_pdf_blend_mode_name((SkBlendMode)fillKey.fBlendMode));
        SkPDFIndirectReference ref = doc->emit(state);
        fillMap.set(fillKey, ref);
        return ref;
    } else {
        SkPDFStrokeGraphicState strokeKey = {
            p.getStrokeWidth(),
            p.getStrokeMiter(),
            p.getColor4f().fA,
            SkToU8(p.getStrokeCap()),
            SkToU8(p.getStrokeJoin()),
            pdf_blend_mode(mode)
        };
        auto& sMap = doc->fStrokeGSMap;
        if (SkPDFIndirectReference* statePtr = sMap.find(strokeKey)) {
            return *statePtr;
        }
        SkPDFDict state;
        state.reserve(8);
        state.insertColorComponentF("CA", strokeKey.fAlpha);
        state.insertColorComponentF("ca", strokeKey.fAlpha);
        state.insertInt("LC", to_stroke_cap(strokeKey.fStrokeCap));
        state.insertInt("LJ", to_stroke_join(strokeKey.fStrokeJoin));
        state.insertScalar("LW", strokeKey.fStrokeWidth);
        state.insertScalar("ML", strokeKey.fStrokeMiter);
        state.insertBool("SA", true);  // SA = Auto stroke adjustment.
        state.insertName("BM", as_pdf_blend_mode_name((SkBlendMode)strokeKey.fBlendMode));
        SkPDFIndirectReference ref = doc->emit(state);
        sMap.set(strokeKey, ref);
        return ref;
    }
}

////////////////////////////////////////////////////////////////////////////////

static SkPDFIndirectReference make_invert_function(SkPDFDocument* doc) {
    // Acrobat crashes if we use a type 0 function, kpdf crashes if we use
    // a type 2 function, so we use a type 4 function.
    static const char psInvert[] = "{1 exch sub}";
    // Do not copy the trailing '\0' into the SkData.
    auto invertFunction = SkData::MakeWithoutCopy(psInvert, strlen(psInvert));

    std::unique_ptr<SkPDFDict> dict = SkPDFMakeDict();
    dict->insertInt("FunctionType", 4);
    dict->insertObject("Domain", SkPDFMakeArray(0, 1));
    dict->insertObject("Range", SkPDFMakeArray(0, 1));
    return SkPDFStreamOut(std::move(dict), SkMemoryStream::Make(std::move(invertFunction)), doc);
}

SkPDFIndirectReference SkPDFGraphicState::GetSMaskGraphicState(SkPDFIndirectReference sMask,
                                                               bool invert,
                                                               SkPDFSMaskMode sMaskMode,
                                                               SkPDFDocument* doc) {
    // The practical chances of using the same mask more than once are unlikely
    // enough that it's not worth canonicalizing.
    auto sMaskDict = SkPDFMakeDict("Mask");
    if (sMaskMode == kAlpha_SMaskMode) {
        sMaskDict->insertName("S", "Alpha");
    } else if (sMaskMode == kLuminosity_SMaskMode) {
        sMaskDict->insertName("S", "Luminosity");
    }
    sMaskDict->insertRef("G", sMask);
    if (invert) {
        // let the doc deduplicate this object.
        if (doc->fInvertFunction == SkPDFIndirectReference()) {
            doc->fInvertFunction = make_invert_function(doc);
        }
        sMaskDict->insertRef("TR", doc->fInvertFunction);
    }
    SkPDFDict result("ExtGState");
    result.insertObject("SMask", std::move(sMaskDict));
    return doc->emit(result);
}
