/*
 * 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 "SkPDFFormXObject.h"
#include "SkPDFUtils.h"
#include "SkPaint.h"
#include "SkTo.h"

static const char* as_pdf_blend_mode_name(SkBlendMode mode) {
    // PDF32000.book section 11.3.5 "Blend Mode"
    switch (mode) {
        case SkBlendMode::kScreen:      return "Screen";
        case SkBlendMode::kOverlay:     return "Overlay";
        case SkBlendMode::kDarken:      return "Darken";
        case SkBlendMode::kLighten:     return "Lighten";
        case SkBlendMode::kColorDodge:  return "ColorDodge";
        case SkBlendMode::kColorBurn:   return "ColorBurn";
        case SkBlendMode::kHardLight:   return "HardLight";
        case SkBlendMode::kSoftLight:   return "SoftLight";
        case SkBlendMode::kDifference:  return "Difference";
        case SkBlendMode::kExclusion:   return "Exclusion";
        case SkBlendMode::kMultiply:    return "Multiply";
        case SkBlendMode::kHue:         return "Hue";
        case SkBlendMode::kSaturation:  return "Saturation";
        case SkBlendMode::kColor:       return "Color";
        case SkBlendMode::kLuminosity:  return "Luminosity";
        // Other blendmodes are either unsupported or handled in
        // SkPDFDevice::setUpContentEntry.
        default:                        return "Normal";
    }
}

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) {
    switch (mode) {
        case SkBlendMode::kSrcOver:
        case SkBlendMode::kMultiply:
        case SkBlendMode::kScreen:
        case SkBlendMode::kOverlay:
        case SkBlendMode::kDarken:
        case SkBlendMode::kLighten:
        case SkBlendMode::kColorDodge:
        case SkBlendMode::kColorBurn:
        case SkBlendMode::kHardLight:
        case SkBlendMode::kSoftLight:
        case SkBlendMode::kDifference:
        case SkBlendMode::kExclusion:
        case SkBlendMode::kHue:
        case SkBlendMode::kSaturation:
        case SkBlendMode::kColor:
        case SkBlendMode::kLuminosity:
            return SkToU8((unsigned)mode);
        default:
            return SkToU8((unsigned)SkBlendMode::kSrcOver);
    }
}

sk_sp<SkPDFDict> SkPDFGraphicState::GetGraphicStateForPaint(SkPDFCanon* canon,
                                                            const SkPaint& p) {
    SkASSERT(canon);
    if (SkPaint::kFill_Style == p.getStyle()) {
        SkPDFFillGraphicState fillKey = {p.getAlpha(), pdf_blend_mode(p.getBlendMode())};
        auto& fillMap = canon->fFillGSMap;
        if (sk_sp<SkPDFDict>* statePtr = fillMap.find(fillKey)) {
            return *statePtr;
        }
        auto state = sk_make_sp<SkPDFDict>();
        state->reserve(2);
        state->insertScalar("ca", fillKey.fAlpha / 255.0f);
        state->insertName("BM", as_pdf_blend_mode_name((SkBlendMode)fillKey.fBlendMode));
        fillMap.set(fillKey, state);
        return state;
    } else {
        SkPDFStrokeGraphicState strokeKey = {
            p.getStrokeWidth(), p.getStrokeMiter(),
            SkToU8(p.getStrokeCap()), SkToU8(p.getStrokeJoin()),
            p.getAlpha(), pdf_blend_mode(p.getBlendMode())};
        auto& sMap = canon->fStrokeGSMap;
        if (sk_sp<SkPDFDict>* statePtr = sMap.find(strokeKey)) {
            return *statePtr;
        }
        auto state = sk_make_sp<SkPDFDict>();
        state->reserve(8);
        state->insertScalar("CA", strokeKey.fAlpha / 255.0f);
        state->insertScalar("ca", strokeKey.fAlpha / 255.0f);
        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));
        sMap.set(strokeKey, state);
        return state;
    }
}

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

static sk_sp<SkPDFStream> make_invert_function() {
    // 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.
    auto domainAndRange = sk_make_sp<SkPDFArray>();
    domainAndRange->reserve(2);
    domainAndRange->appendInt(0);
    domainAndRange->appendInt(1);

    static const char psInvert[] = "{1 exch sub}";
    // Do not copy the trailing '\0' into the SkData.
    auto invertFunction = sk_make_sp<SkPDFStream>(
            SkData::MakeWithoutCopy(psInvert, strlen(psInvert)));
    invertFunction->dict()->insertInt("FunctionType", 4);
    invertFunction->dict()->insertObject("Domain", domainAndRange);
    invertFunction->dict()->insertObject("Range", std::move(domainAndRange));
    return invertFunction;
}

sk_sp<SkPDFDict> SkPDFGraphicState::GetSMaskGraphicState(
        sk_sp<SkPDFObject> sMask,
        bool invert,
        SkPDFSMaskMode sMaskMode,
        SkPDFCanon* canon) {
    // The practical chances of using the same mask more than once are unlikely
    // enough that it's not worth canonicalizing.
    auto sMaskDict = sk_make_sp<SkPDFDict>("Mask");
    if (sMaskMode == kAlpha_SMaskMode) {
        sMaskDict->insertName("S", "Alpha");
    } else if (sMaskMode == kLuminosity_SMaskMode) {
        sMaskDict->insertName("S", "Luminosity");
    }
    sMaskDict->insertObjRef("G", std::move(sMask));
    if (invert) {
        // Instead of calling SkPDFGraphicState::MakeInvertFunction,
        // let the canon deduplicate this object.
        sk_sp<SkPDFStream>& invertFunction = canon->fInvertFunction;
        if (!invertFunction) {
            invertFunction = make_invert_function();
        }
        sMaskDict->insertObjRef("TR", invertFunction);
    }
    auto result = sk_make_sp<SkPDFDict>("ExtGState");
    result->insertObject("SMask", std::move(sMaskDict));
    return result;
}
