1822f270创建于 2022年7月13日历史提交
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* 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 "render_pixfmt_rgba_blend.h"

namespace OHOS {
bool RenderPixfmtRgbaBlend::Attach(RenderPixfmtRgbaBlend& pixf, int32_t x1, int32_t y1, int32_t x2, int32_t y2)
{
    Rect32 r(x1, y1, x2, y2);
    if (r.Intersect(r, Rect32(0, 0, pixf.GetWidth() - 1, pixf.GetHeight() - 1))) {
        int32_t stride = pixf.GetStride();
        rBuf_->Attach(pixf.PixPtr(r.GetLeft(), stride < 0 ? r.GetBottom() : r.GetTop()),
                      (r.GetRight() - r.GetLeft()) + 1, (r.GetBottom() - r.GetTop()) + 1, stride);
        return true;
    }
    return false;
}

void RenderPixfmtRgbaBlend::CopyHLine(int32_t x, int32_t y,
                                      uint32_t len,
                                      const Rgba8T& color)
{
    PixelColorType vPixelValue;
    vPixelValue.SetPixelColor(color);
    PixelColorType* pixelPtr = PixValuePtr(x, y);
#ifdef NEON_ARM_OPT
    int16_t step = NEON_STEP_8 * PIX_STEP;
    while (len >= NEON_STEP_8) {
        SetPixelColor_ARGB8888(pixelPtr->colors, color->red,
                               colors->green, colors->blue,
                               colors->alpha);
        pixelPtr = pixelPtr->colors + step;
        len -= NEON_STEP_8;
    };
#endif
    for (uint32_t iPixel = 0; iPixel < len; ++iPixel) {
        *pixelPtr = vPixelValue;
        pixelPtr = pixelPtr->Next();
    }
}

void RenderPixfmtRgbaBlend::BlendHLine(int32_t x, int32_t y,
                                       uint32_t len,
                                       const Rgba8T& color,
                                       uint8_t cover)
{
    if (!color.IsTransparent()) {
        PixelColorType* pPixel = PixValuePtr(x, y);
#ifdef NEON_ARM_OPT
        int16_t step = NEON_STEP_8 * PIX_STEP;
        while (len >= NEON_STEP_8) {
            NeonBlendPix(pixelPtr, color, cover);
            pixelPtr = pixelPtr->colors + step;
            len -= NEON_STEP_8;
        };
#endif
        if (color.IsOpaque() && cover == COVER_MASK) {
            for (uint32_t iPixel = 0; iPixel < len; ++iPixel) {
                PixelColorType pixelValue;
                pixelValue.SetPixelColor(color);
                *pPixel = pixelValue;
                pPixel = pPixel->Next();
            }
        } else {
            if (cover == COVER_MASK) {
                for (uint32_t iPixel = 0; iPixel < len; ++iPixel) {
                    BlendPix(pPixel, color);
                    pPixel = pPixel->Next();
                }
            } else {
                for (uint32_t iPixel = 0; iPixel < len; ++iPixel) {
                    BlendPix(pPixel, color, cover);
                    pPixel = pPixel->Next();
                }
            }
        }
    }
}

void RenderPixfmtRgbaBlend::BlendSolidHSpan(int32_t x, int32_t y,
                                            uint32_t len,
                                            const Rgba8T& color,
                                            const uint8_t* covers)
{
    if (!color.IsTransparent()) {
        PixelColorType* pixelPtr = PixValuePtr(x, y);

#ifdef NEON_ARM_OPT
        int16_t step = NEON_STEP_8 * PIX_STEP;
        while (len >= NEON_STEP_8) {
            NeonBlendPix(pixelPtr->colors, color, covers);
            pixelPtr = pixelPtr->colors + step;
            covers += NEON_STEP_8;
            len -= NEON_STEP_8;
        };
#endif

        for (uint32_t iPixel = 0; iPixel < len; ++iPixel) {
            if (color.IsOpaque() && *covers == COVER_MASK) {
                pixelPtr->SetPixelColor(color);
            } else {
                BlendPix(pixelPtr, color, *covers);
            }
            pixelPtr = pixelPtr->Next();
            ++covers;
        }
    }
}

void RenderPixfmtRgbaBlend::BlendSolidVSpan(int32_t x, int32_t y,
                                            uint32_t len,
                                            const Rgba8T& color,
                                            const uint8_t* covers)
{
    if (!color.IsTransparent()) {
        do {
            PixelColorType* pixelPtr = PixValuePtr(x, y++);
            if (color.IsOpaque() && *covers == COVER_MASK) {
                pixelPtr->SetPixelColor(color);
            } else {
                BlendPix(pixelPtr, color, *covers);
            }
            ++covers;
        } while (--len);
    }
}

void RenderPixfmtRgbaBlend::CopyColorHSpan(int32_t x, int32_t y,
                                           uint32_t len,
                                           const Rgba8T* colors)
{
    PixelColorType* pixelPtr = PixValuePtr(x, y);
#ifdef NEON_ARM_OPT
    int16_t step = NEON_STEP_8 * PIX_STEP;
    const int16_t NEON_STEP_COMPONENTS = NEON_STEP_8 * NUM_COMPONENTS;
    uint8_t mColors[NEON_STEP_COMPONENTS];
    while (len >= NEON_STEP_8) {
        if (memset_s(mColors, size_t(NEON_STEP_COMPONENTS), 0, size_t(NEON_STEP_COMPONENTS)) != EOK) {
            return GRAPHIC_LOGE("CopyColorHSpan faile");
        }
        NeonMemcpy(mColors, NEON_STEP_COMPONENTS, colors, NEON_STEP_COMPONENTS);

        SetPixelColor_ARGB8888(pixelPtr->colors, mColors);
        pixelPtr = pixelPtr->colors + step;
        colors += NEON_STEP_8;
        len -= NEON_STEP_8;
    };
#endif
    for (uint32_t iPixel = 0; iPixel < len; ++iPixel) {
        pixelPtr->SetPixelColor(*colors++);
        pixelPtr = pixelPtr->Next();
    }
}

void RenderPixfmtRgbaBlend::CopyColorVSpan(int32_t x, int32_t y,
                                           uint32_t len,
                                           const Rgba8T* colors)
{
    do {
        PixValuePtr(x, y++)->SetPixelColor(*colors++);
    } while (--len);
}

void RenderPixfmtRgbaBlend::BlendColorHSpan(int32_t x, int32_t y,
                                            uint32_t len,
                                            const Rgba8T* colors,
                                            const uint8_t* covers,
                                            uint8_t cover)
{
    PixelColorType* pixelPtr = PixValuePtr(x, y);
    if (covers) {
#ifdef NEON_ARM_OPT
        int16_t step = NEON_STEP_8 * PIX_STEP;
        const int16_t NEON_STEP_COMPONENTS = NEON_STEP_8 * NUM_COMPONENTS;
        uint8_t mColors[NEON_STEP_COMPONENTS];
        while (len >= NEON_STEP_8) {
            if (memset_s(mColors, size_t(NEON_STEP_COMPONENTS), 0, size_t(NEON_STEP_COMPONENTS)) != EOK) {
                GRAPHIC_LOGE("BlendColorHSpan fail");
                return;
            }
            NeonMemcpy(mColors, NEON_STEP_COMPONENTS, colors, NEON_STEP_COMPONENTS);

            NeonBlendPix(pixelPtr->colors, mColors, covers);
            pixelPtr = pixelPtr->colors + step;
            colors += NEON_STEP_8;
            covers += NEON_STEP_8;
            len -= NEON_STEP_8;
        };
#endif
        for (uint32_t iPixel = 0; iPixel < len; ++iPixel) {
            CopyOrBlendPix(pixelPtr, *colors++, *covers++);
            pixelPtr = pixelPtr->Next();
        }
    } else {
#ifdef NEON_ARM_OPT
        int16_t step = NEON_STEP_8 * PIX_STEP;
        const int16_t NEON_STEP_COMPONENTS = NEON_STEP_8 * NUM_COMPONENTS;
        uint8_t mColors[NEON_STEP_COMPONENTS];
        while (len >= NEON_STEP_8) {
            if (memset_s(mColors, size_t(NEON_STEP_COMPONENTS), 0, size_t(NEON_STEP_COMPONENTS)) != EOK) {
                GRAPHIC_LOGE("BlendColorHSpan fail");
                return;
            }
            NeonMemcpy(mColors, NEON_STEP_COMPONENTS, colors, NEON_STEP_COMPONENTS);

            NeonBlendPix(pixelPtr->colors, mColors, cover);
            pixelPtr = pixelPtr->colors + step;
            colors += NEON_STEP_8;
            len -= NEON_STEP_8;
        };
#endif
        if (cover == COVER_MASK) {
            for (uint32_t iPixel = 0; iPixel < len; ++iPixel) {
                cover == COVER_MASK ? CopyOrBlendPix(pixelPtr, *colors++) :
                                      CopyOrBlendPix(pixelPtr, *colors++, cover);
                pixelPtr = pixelPtr->Next();
            }
        }
    }
}
} // namespace OHOS