/*
 * 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.mutateClipArea().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 and clipSideFlags
        clipSideFlags = computeClipSideFlags(clipRect, clippedBounds);
        clippedBounds.doIntersect(clipRect);
    }
}

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

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

} // namespace uirenderer
} // namespace android
