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

#include "GrStrokeInfo.h"
#include "GrResourceKey.h"
#include "SkDashPathPriv.h"

bool all_dash_intervals_zero(const SkScalar* intervals, int count) {
    for (int i = 0 ; i < count; ++i) {
        if (intervals[i] != 0) {
            return false;
        }
    }
    return true;
}

bool GrStrokeInfo::applyDashToPath(SkPath* dst, GrStrokeInfo* dstStrokeInfo,
                                   const SkPath& src) const {
    if (this->isDashed()) {
        SkPathEffect::DashInfo info;
        info.fIntervals = fIntervals.get();
        info.fCount = fIntervals.count();
        info.fPhase = fDashPhase;
        GrStrokeInfo filteredStroke(*this, false);
        // Handle the case where all intervals are 0 and we simply drop the dash effect
        if (all_dash_intervals_zero(fIntervals.get(), fIntervals.count())) {
            *dstStrokeInfo = filteredStroke;
            *dst = src;
            return true;
        }
        // See if we can filter the dash into a path on cpu
        if (SkDashPath::FilterDashPath(dst, src, &filteredStroke, nullptr, info)) {
            *dstStrokeInfo = filteredStroke;
            return true;
        }
    }
    return false;
}

void GrStrokeInfo::asUniqueKeyFragment(uint32_t* data) const {
    const int kSkScalarData32Cnt = sizeof(SkScalar) / sizeof(uint32_t);
    enum {
        kStyleBits = 2,
        kJoinBits = 2,
        kCapBits = 32 - kStyleBits - kJoinBits,

        kJoinShift = kStyleBits,
        kCapShift = kJoinShift + kJoinBits,
    };

    static_assert(SkStrokeRec::kStyleCount <= (1 << kStyleBits), "style_shift_will_be_wrong");
    static_assert(SkPaint::kJoinCount <= (1 << kJoinBits), "cap_shift_will_be_wrong");
    static_assert(SkPaint::kCapCount <= (1 << kCapBits), "cap_does_not_fit");
    uint32_t styleKey = this->getStyle();
    if (this->needToApply()) {
        styleKey |= this->getJoin() << kJoinShift;
        styleKey |= this->getCap() << kCapShift;
    }
    int i = 0;
    data[i++] = styleKey;

    // Memcpy the scalar fields. Does not "reinterpret_cast<SkScalar&>(data[i]) = ..." due to
    // scalars having more strict alignment requirements than what data can guarantee. The
    // compiler should optimize memcpys to assignments.
    SkScalar scalar;
    scalar = this->getMiter();
    memcpy(&data[i], &scalar, sizeof(scalar));
    i += kSkScalarData32Cnt;

    scalar = this->getWidth();
    memcpy(&data[i], &scalar, sizeof(scalar));
    i += kSkScalarData32Cnt;

    if (this->isDashed()) {
        SkScalar phase = this->getDashPhase();
        memcpy(&data[i], &phase, sizeof(phase));
        i += kSkScalarData32Cnt;

        int32_t count = this->getDashCount() & static_cast<int32_t>(~1);
        SkASSERT(count == this->getDashCount());
        const SkScalar* intervals = this->getDashIntervals();
        int intervalByteCnt = count * sizeof(SkScalar);
        memcpy(&data[i], intervals, intervalByteCnt);
        // Enable the line below if fields are added after dashing.
        SkDEBUGCODE(i += kSkScalarData32Cnt * count);
    }

    SkASSERT(this->computeUniqueKeyFragmentData32Cnt() == i);
}

