/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "BakedOpState.h"

#include "ClipArea.h"

namespace android {
namespace uirenderer {

static int computeClipSideFlags(const Rect& clip, const Rect& bounds) {
    int clipSideFlags = 0;
    if (clip.left > bounds.left) clipSideFlags |= OpClipSideFlags::Left;
    if (clip.top > bounds.top) clipSideFlags |= OpClipSideFlags::Top;
    if (clip.right < bounds.right) clipSideFlags |= OpClipSideFlags::Right;
    if (clip.bottom < bounds.bottom) clipSideFlags |= OpClipSideFlags::Bottom;
    return clipSideFlags;
}

ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
        const RecordedOp& recordedOp, bool expandForStroke) {
    // resolvedMatrix = parentMatrix * localMatrix
    transform.loadMultiply(*snapshot.transform, recordedOp.localMatrix);

    // resolvedClippedBounds = intersect(resolvedMatrix * opBounds, resolvedClipRect)
    clippedBounds = recordedOp.unmappedBounds;
    if (CC_UNLIKELY(expandForStroke)) {
        // account for non-hairline stroke
        clippedBounds.outset(recordedOp.paint->getStrokeWidth() * 0.5f);
    }
    transform.mapRect(clippedBounds);
    if (CC_UNLIKELY(expandForStroke
            && (!transform.isPureTranslate() || recordedOp.paint->getStrokeWidth() < 1.0f))) {
        // account for hairline stroke when stroke may be < 1 scaled pixel
        // Non translate || strokeWidth < 1 is conservative, but will cover all cases
        clippedBounds.outset(0.5f);
    }

    // resolvedClipRect = intersect(parentMatrix * localClip, parentClip)
    clipState = snapshot.serializeIntersectedClip(allocator,
            recordedOp.localClip, *(snapshot.transform));
    LOG_ALWAYS_FATAL_IF(!clipState, "must clip!");

    const Rect& clipRect = clipState->rect;
    if (CC_UNLIKELY(clipRect.isEmpty() || !clippedBounds.intersects(clipRect))) {
        // Rejected based on either empty clip, or bounds not intersecting with clip

        // Note: we could rewind the clipState object in situations where the clipRect is empty,
        // but *only* if the caching logic within ClipArea was aware of the rewind.
        clipState = nullptr;
        clippedBounds.setEmpty();
    } else {
        // Not rejected! compute true clippedBounds, clipSideFlags, and path mask
        clipSideFlags = computeClipSideFlags(clipRect, clippedBounds);
        clippedBounds.doIntersect(clipRect);

        if (CC_UNLIKELY(snapshot.projectionPathMask)) {
            // map projection path mask from render target space into op space,
            // so intersection with op geometry is possible
            Matrix4 inverseTransform;
            inverseTransform.loadInverse(transform);
            SkMatrix skInverseTransform;
            inverseTransform.copyTo(skInverseTransform);

            auto localMask = allocator.create<SkPath>();
            snapshot.projectionPathMask->transform(skInverseTransform, localMask);
            localProjectionPathMask = localMask;
        }
    }
}

ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
        const Matrix4& localTransform, const ClipBase* localClip) {
    transform.loadMultiply(*snapshot.transform, localTransform);
    clipState = snapshot.serializeIntersectedClip(allocator, localClip, *(snapshot.transform));
    clippedBounds = clipState->rect;
    clipSideFlags = OpClipSideFlags::Full;
    localProjectionPathMask = nullptr;
}

ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot)
        : transform(*snapshot.transform)
        , clipState(snapshot.mutateClipArea().serializeClip(allocator))
        , clippedBounds(clipState->rect)
        , clipSideFlags(OpClipSideFlags::Full)
        , localProjectionPathMask(nullptr) {}

ResolvedRenderState::ResolvedRenderState(const ClipRect* clipRect, const Rect& dstRect)
        : transform(Matrix4::identity())
        , clipState(clipRect)
        , clippedBounds(dstRect)
        , clipSideFlags(computeClipSideFlags(clipRect->rect, dstRect))
        , localProjectionPathMask(nullptr) {
    clippedBounds.doIntersect(clipRect->rect);
}

BakedOpState* BakedOpState::tryConstruct(LinearAllocator& allocator,
        Snapshot& snapshot, const RecordedOp& recordedOp) {
    if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
    BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
            allocator, snapshot, recordedOp, false);
    if (bakedState->computedState.clippedBounds.isEmpty()) {
        // bounds are empty, so op is rejected
        allocator.rewindIfLastAlloc(bakedState);
        return nullptr;
    }
    return bakedState;
}

BakedOpState* BakedOpState::tryConstructUnbounded(LinearAllocator& allocator,
        Snapshot& snapshot, const RecordedOp& recordedOp) {
    if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
    return allocator.create_trivial<BakedOpState>(allocator, snapshot, recordedOp);
}

BakedOpState* BakedOpState::tryStrokeableOpConstruct(LinearAllocator& allocator,
        Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior) {
    if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
    bool expandForStroke = (strokeBehavior == StrokeBehavior::StyleDefined)
            ? (recordedOp.paint && recordedOp.paint->getStyle() != SkPaint::kFill_Style)
            : true;

    BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
           allocator, snapshot, recordedOp, expandForStroke);
    if (bakedState->computedState.clippedBounds.isEmpty()) {
        // bounds are empty, so op is rejected
        // NOTE: this won't succeed if a clip was allocated
        allocator.rewindIfLastAlloc(bakedState);
        return nullptr;
    }
    return bakedState;
}

BakedOpState* BakedOpState::tryShadowOpConstruct(LinearAllocator& allocator,
        Snapshot& snapshot, const ShadowOp* shadowOpPtr) {
    if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;

    // clip isn't empty, so construct the op
    return allocator.create_trivial<BakedOpState>(allocator, snapshot, shadowOpPtr);
}

BakedOpState* BakedOpState::directConstruct(LinearAllocator& allocator,
        const ClipRect* clip, const Rect& dstRect, const RecordedOp& recordedOp) {
    return allocator.create_trivial<BakedOpState>(clip, dstRect, recordedOp);
}

void BakedOpState::setupOpacity(const SkPaint* paint) {
    computedState.opaqueOverClippedBounds = computedState.transform.isSimple()
            && computedState.clipState->mode == ClipMode::Rectangle
            && MathUtils::areEqual(alpha, 1.0f)
            && !roundRectClipState
            && PaintUtils::isOpaquePaint(paint);
}

} // namespace uirenderer
} // namespace android
