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

#include "SkData.h"
#include "SkPDFCanon.h"
#include "SkPDFDocumentPriv.h"
#include "SkPDFFormXObject.h"
#include "SkPDFUtils.h"
#include "SkPaint.h"
#include "SkTo.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) {
    SkPDFCanon* canon = doc->canon();
    SkASSERT(canon);
    if (SkPaint::kFill_Style == p.getStyle()) {
        SkPDFFillGraphicState fillKey = {p.getColor4f().fA, pdf_blend_mode(p.getBlendMode())};
        auto& fillMap = canon->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(p.getBlendMode())
        };
        auto& sMap = canon->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.
    SkPDFCanon* canon = doc->canon();
    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 canon deduplicate this object.
        if (canon->fInvertFunction == SkPDFIndirectReference()) {
            canon->fInvertFunction = make_invert_function(doc);
        }
        sMaskDict->insertRef("TR", canon->fInvertFunction);
    }
    SkPDFDict result("ExtGState");
    result.insertObject("SMask", std::move(sMaskDict));
    return doc->emit(result);
}
