Пример #1
0
bool SkPixmap::erase(const SkColor4f& origColor, const SkIRect* subset) const {
    SkPixmap pm;
    if (subset) {
        if (!this->extractSubset(&pm, *subset)) {
            return false;
        }
    } else {
        pm = *this;
    }

    const SkColor4f color = origColor.pin();

    if (kRGBA_F16_SkColorType != pm.colorType()) {
        Sk4f c4 = Sk4f::Load(color.vec());
        SkColor c;
        (c4 * Sk4f(255) + Sk4f(0.5f)).store(&c);
        return pm.erase(c);
    }

    const uint64_t half4 = color.premul().toF16();
    for (int y = 0; y < pm.height(); ++y) {
        sk_memset64(pm.writable_addr64(0, y), half4, pm.width());
    }
    return true;
}
Пример #2
0
static Sk4f set_argb(float a, float r, float g, float b) {
    if (0 == SkPM4f::R) {
        return Sk4f(r, g, b, a);
    } else {
        return Sk4f(b, g, r, a);
    }
}
Пример #3
0
template <DstType D> void srcover_1(const SkXfermode::PM4fState& state, uint32_t dst[],
                                    const SkPM4f& src, int count, const SkAlpha aa[]) {
    Sk4f s4 = Sk4f::Load(src.fVec);
    Sk4f scale = Sk4f(1 - get_alpha(s4));

    if (aa) {
        for (int i = 0; i < count; ++i) {
            unsigned a = aa[i];
            if (0 == a) {
                continue;
            }
            Sk4f d4 = load_dst<D>(dst[i]);
            Sk4f r4;
            if (a != 0xFF) {
                s4 = scale_by_coverage(s4, a);
                r4 = s4 + d4 * Sk4f(1 - get_alpha(s4));
            } else {
                r4 = s4 + d4 * scale;
            }
            dst[i] = store_dst<D>(r4);
        }
    } else {
        for (int i = 0; i < count; ++i) {
            Sk4f d4 = load_dst<D>(dst[i]);
            Sk4f r4 = s4 + d4 * scale;
            dst[i] = store_dst<D>(r4);
        }
    }
}
Пример #4
0
 void compute_interval_props(SkScalar t) {
     fDc   = dst_swizzle<DstType>(fInterval->fDc);
     fCc   = dst_swizzle<DstType>(fInterval->fC0);
     fCc   = fCc + fDc * Sk4f(t);
     fCc   = scale_for_dest<DstType, profile>(fCc);
     fDcDx = scale_for_dest<DstType, profile>(fDc * Sk4f(fDx));
     fZeroRamp = fIsVertical || fInterval->isZeroRamp();
 }
Пример #5
0
    sk_sp<SkData> encode_bitmap_for_png(SkBitmap bitmap) {
        const int w = bitmap.width(),
                h = bitmap.height();
        // PNG wants unpremultiplied 8-bit RGBA pixels (16-bit could work fine too).
        // We leave the gamma of these bytes unspecified, to continue the status quo,
        // which we think generally is to interpret them as sRGB.

        SkAutoTMalloc<uint32_t> rgba(w*h);

        auto srgbColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
        if (bitmap. colorType() ==  kN32_SkColorType &&
            bitmap.colorSpace() == srgbColorSpace.get()) {
            // These are premul sRGB 8-bit pixels in SkPMColor order.
            // We want unpremul sRGB 8-bit pixels in RGBA order.  We'll get there via floats.
            bitmap.lockPixels();
            auto px = (const uint32_t*)bitmap.getPixels();
            if (!px) {
                return nullptr;
            }
            for (int i = 0; i < w*h; i++) {
                Sk4f fs = Sk4f_fromS32(px[i]);         // Convert up to linear floats.
#if defined(SK_PMCOLOR_IS_BGRA)
                fs = SkNx_shuffle<2,1,0,3>(fs);        // Shuffle to RGBA, if not there already.
#endif
                float invA = 1.0f / fs[3];
                fs = fs * Sk4f(invA, invA, invA, 1);   // Unpremultiply.
                rgba[i] = Sk4f_toS32(fs);              // Pack down to sRGB bytes.
            }

        } else if (bitmap.colorType() == kRGBA_F16_SkColorType) {
            // These are premul linear half-float pixels in RGBA order.
            // We want unpremul sRGB 8-bit pixels in RGBA order.  We'll get there via floats.
            bitmap.lockPixels();
            auto px = (const uint64_t*)bitmap.getPixels();
            if (!px) {
                return nullptr;
            }
            for (int i = 0; i < w*h; i++) {
                // Convert up to linear floats.
                Sk4f fs(SkHalfToFloat(static_cast<SkHalf>(px[i] >> (0 * 16))),
                        SkHalfToFloat(static_cast<SkHalf>(px[i] >> (1 * 16))),
                        SkHalfToFloat(static_cast<SkHalf>(px[i] >> (2 * 16))),
                        SkHalfToFloat(static_cast<SkHalf>(px[i] >> (3 * 16))));
                fs = Sk4f::Max(0.0f, Sk4f::Min(fs, 1.0f));  // Clamp
                float invA = 1.0f / fs[3];
                fs = fs * Sk4f(invA, invA, invA, 1);  // Unpremultiply.
                rgba[i] = Sk4f_toS32(fs);             // Pack down to sRGB bytes.
            }

        } else {
Пример #6
0
DEF_TEST(Sk4x_Swizzle, r) {
    ASSERT_EQ(Sk4f(3,4,1,2), Sk4f(1,2,3,4).zwxy());
    ASSERT_EQ(Sk4f(1,2,5,6), Sk4f::XYAB(Sk4f(1,2,3,4), Sk4f(5,6,7,8)));
    ASSERT_EQ(Sk4f(3,4,7,8), Sk4f::ZWCD(Sk4f(1,2,3,4), Sk4f(5,6,7,8)));
    ASSERT_EQ(Sk4i(3,4,1,2), Sk4i(1,2,3,4).zwxy());
    ASSERT_EQ(Sk4i(1,2,5,6), Sk4i::XYAB(Sk4i(1,2,3,4), Sk4i(5,6,7,8)));
    ASSERT_EQ(Sk4i(3,4,7,8), Sk4i::ZWCD(Sk4i(1,2,3,4), Sk4i(5,6,7,8)));
}
Пример #7
0
void GrCCFillGeometry::conicTo(const SkPoint P[3], float w) {
    SkASSERT(fBuildingContour);
    SkASSERT(P[0] == fPoints.back());
    Sk2f p0 = Sk2f::Load(P);
    Sk2f p1 = Sk2f::Load(P+1);
    Sk2f p2 = Sk2f::Load(P+2);

    Sk2f tan0 = p1 - p0;
    Sk2f tan1 = p2 - p1;

    if (!is_convex_curve_monotonic(p0, tan0, p2, tan1)) {
        // The derivative of a conic has a cumbersome order-4 denominator. However, this isn't
        // necessary if we are only interested in a vector in the same *direction* as a given
        // tangent line. Since the denominator scales dx and dy uniformly, we can throw it out
        // completely after evaluating the derivative with the standard quotient rule. This leaves
        // us with a simpler quadratic function that we use to find the midtangent.
        float midT = find_midtangent(tan0, tan1, (w - 1) * (p2 - p0),
                                                 (p2 - p0) - 2*w*(p1 - p0),
                                                 w*(p1 - p0));
        // Use positive logic since NaN fails comparisons. (However midT should not be NaN since we
        // cull near-linear conics above. And while w=0 is flat, it's not a line and has valid
        // midtangents.)
        if (!(midT > 0 && midT < 1)) {
            // The conic is flat. Otherwise there would be a real midtangent inside T=0..1.
            this->appendLine(p0, p2);
            return;
        }

        // Chop the conic at midtangent to produce two monotonic segments.
        Sk4f p3d0 = Sk4f(p0[0], p0[1], 1, 0);
        Sk4f p3d1 = Sk4f(p1[0], p1[1], 1, 0) * w;
        Sk4f p3d2 = Sk4f(p2[0], p2[1], 1, 0);
        Sk4f midT4 = midT;

        Sk4f p3d01 = lerp(p3d0, p3d1, midT4);
        Sk4f p3d12 = lerp(p3d1, p3d2, midT4);
        Sk4f p3d012 = lerp(p3d01, p3d12, midT4);

        Sk2f midpoint = Sk2f(p3d012[0], p3d012[1]) / p3d012[2];
        Sk2f ww = Sk2f(p3d01[2], p3d12[2]) * Sk2f(p3d012[2]).rsqrt();

        this->appendMonotonicConic(p0, Sk2f(p3d01[0], p3d01[1]) / p3d01[2], midpoint, ww[0]);
        this->appendMonotonicConic(midpoint, Sk2f(p3d12[0], p3d12[1]) / p3d12[2], p2, ww[1]);
        return;
    }

    this->appendMonotonicConic(p0, p1, p2, w);
}
Пример #8
0
SkPM4f SkColor4f::premul() const {
    auto src = Sk4f::Load(this->pin().vec());
    float srcAlpha = src[3];  // need the pinned version of our alpha
    src = src * Sk4f(srcAlpha, srcAlpha, srcAlpha, 1);

    return SkPM4f::From4f(src);
}
void filter_span(const float array[], const T src[], int count, T dst[]) {
    // c0-c3 are already in [0,1].
    const Sk4f c0 = Sk4f::Load(array + 0);
    const Sk4f c1 = Sk4f::Load(array + 4);
    const Sk4f c2 = Sk4f::Load(array + 8);
    const Sk4f c3 = Sk4f::Load(array + 12);
    // c4 (the translate vector) is in [0, 255].  Bring it back to [0,1].
    const Sk4f c4 = Sk4f::Load(array + 16)*Sk4f(1.0f/255);

    // todo: we could cache this in the constructor...
    T matrix_translate_pmcolor = Adaptor::From4f(premul(clamp_0_1(c4)));

    for (int i = 0; i < count; i++) {
        Sk4f srcf = Adaptor::To4f(src[i]);
        float srcA = srcf.kth<SkPM4f::A>();

        if (0 == srcA) {
            dst[i] = matrix_translate_pmcolor;
            continue;
        }
        if (1 != srcA) {
            srcf = unpremul(srcf);
        }

        Sk4f r4 = SkNx_dup<SK_R32_SHIFT/8>(srcf);
        Sk4f g4 = SkNx_dup<SK_G32_SHIFT/8>(srcf);
        Sk4f b4 = SkNx_dup<SK_B32_SHIFT/8>(srcf);
        Sk4f a4 = SkNx_dup<SK_A32_SHIFT/8>(srcf);

        // apply matrix
        Sk4f dst4 = c0 * r4 + c1 * g4 + c2 * b4 + c3 * a4 + c4;

        dst[i] = Adaptor::From4f(premul(clamp_0_1(dst4)));
    }
}
Пример #10
0
 void compute_interval_props(SkScalar t) {
     const Sk4f dC = DstTraits<dstType>::load(fInterval->fDc);
     fCc           = DstTraits<dstType>::load(fInterval->fC0);
     fCc           = fCc + dC * Sk4f(t);
     fDcDx         = dC * fDx;
     fZeroRamp     = fIsVertical || fInterval->isZeroRamp();
 }
Пример #11
0
void SkColorFilter::filterSpan4f(const SkPM4f[], int count, SkPM4f span[]) const {
    const int N = 128;
    SkPMColor tmp[N];
    while (count > 0) {
        int n = SkTMin(count, N);
        for (int i = 0; i < n; ++i) {
            SkNx_cast<uint8_t>(Sk4f::Load(span[i].fVec) * Sk4f(255) + Sk4f(0.5f)).store(&tmp[i]);
        }
        this->filterSpan(tmp, n, tmp);
        for (int i = 0; i < n; ++i) {
            span[i] = SkPM4f::FromPMColor(tmp[i]);
        }
        span += n;
        count -= n;
    }
}
Пример #12
0
void src_1_lcd(uint32_t dst[], const SkPM4f* src, int count, const uint16_t lcd[]) {
    const Sk4f s4 = Sk4f::Load(src->fVec);

    if (D == kLinear_Dst) {
        // operate in bias-255 space for src and dst
        const Sk4f s4bias = s4 * Sk4f(255);
        for (int i = 0; i < count; ++i) {
            uint16_t rgb = lcd[i];
            if (0 == rgb) {
                continue;
            }
            Sk4f d4bias = to_4f(dst[i]);
            dst[i] = to_4b(lerp(s4bias, d4bias, lcd16_to_unit_4f(rgb))) | (SK_A32_MASK << SK_A32_SHIFT);
        }
    } else {    // kSRGB
        for (int i = 0; i < count; ++i) {
            uint16_t rgb = lcd[i];
            if (0 == rgb) {
                continue;
            }
            Sk4f d4 = load_dst<D>(dst[i]);
            dst[i] = store_dst<D>(lerp(s4, d4, lcd16_to_unit_4f(rgb))) | (SK_A32_MASK << SK_A32_SHIFT);
        }
    }
}
Пример #13
0
static Sk4f colorburn_4f(const Sk4f& s, const Sk4f& d) {
    Sk4f sa  = alpha(s);
    Sk4f da  = alpha(d);
    Sk4f isa = Sk4f(1) - sa;
    Sk4f ida = Sk4f(1) - da;

    Sk4f srcover = s + d * isa;
    Sk4f dstover = d + s * ida;
    Sk4f otherwise = sa * (da - Sk4f::Min(da, (da - d) * sa / s)) + s * ida + d * isa;

    // Order matters here, preferring d==da over s==0.
    auto colors = (d == da).thenElse(dstover,
                                     (s == Sk4f(0)).thenElse(srcover,
                                                             otherwise));
    return color_alpha(colors, srcover);
}
Пример #14
0
static Sk4f lcd16_to_unit_4f(uint16_t rgb) {
#ifdef SK_PMCOLOR_IS_RGBA
    Sk4i rgbi = Sk4i(SkGetPackedR16(rgb), SkGetPackedG16(rgb), SkGetPackedB16(rgb), 0);
#else
    Sk4i rgbi = Sk4i(SkGetPackedB16(rgb), SkGetPackedG16(rgb), SkGetPackedR16(rgb), 0);
#endif
    return SkNx_cast<float>(rgbi) * Sk4f(1.0f/31, 1.0f/63, 1.0f/31, 0);
}
Пример #15
0
static void srcover_srgb_dst_1(const SkXfermode*, uint32_t dst[],
                               const SkPM4f* src, int count, const SkAlpha aa[]) {
    Sk4f s4 = src->to4f_pmorder();
    Sk4f dst_scale = Sk4f(1 - get_alpha(s4));

    if (aa) {
        for (int i = 0; i < count; ++i) {
            unsigned a = aa[i];
            if (0 == a) {
                continue;
            }
            Sk4f d4 = srgb_4b_to_linear_unit(dst[i]);
            Sk4f r4;
            if (a != 0xFF) {
                const Sk4f s4_aa = scale_by_coverage(s4, a);
                r4 = s4_aa + d4 * Sk4f(1 - get_alpha(s4_aa));
            } else {
                r4 = s4 + d4 * dst_scale;
            }
            dst[i] = to_4b(linear_unit_to_srgb_255f(r4));
        }
    } else {
        while (count >= 4) {
            auto d = load_4_srgb(dst);

            auto s = Sk4x4f{{ src->r() }, { src->g() }, { src->b() }, { src->a() }};
        #if defined(SK_PMCOLOR_IS_BGRA)
            SkTSwap(s.r, s.b);
        #endif

            auto invSA = 1.0f - s.a;
            auto r = s.r + d.r * invSA,
                 g = s.g + d.g * invSA,
                 b = s.b + d.b * invSA,
                 a = s.a + d.a * invSA;

            store_4_srgb(dst, Sk4x4f{r,g,b,a});
            count -= 4;
            dst += 4;
        }
        for (int i = 0; i < count; ++i) {
            Sk4f d4 = srgb_4b_to_linear_unit(dst[i]);
            dst[i] = to_4b(linear_unit_to_srgb_255f(s4 + d4 * dst_scale));
        }
    }
}
Пример #16
0
    void compute_interval_props(SkScalar t) {
        SkASSERT(in_range(t, fInterval->fT0, fInterval->fT1));

        const Sk4f dc = DstTraits<dstType, premul>::load(fInterval->fCg);
                  fCc = DstTraits<dstType, premul>::load(fInterval->fCb) + dc * Sk4f(t);
                fDcDx = dc * fDx;
            fZeroRamp = fIsVertical || (dc == 0).allTrue();
    }
Пример #17
0
static Sk4f overlay_4f(const Sk4f& s, const Sk4f& d) {
    Sk4f sa = alpha(s);
    Sk4f da = alpha(d);
    Sk4f two = Sk4f(2);
    Sk4f rc = (two * d <= da).thenElse(two * s * d,
                                       sa * da - two * (da - d) * (sa - s));
    return pin_1(s + d - s * da + color_alpha(rc - d * sa, 0));
}
Пример #18
0
template <DstType D> void srcover_n(const SkXfermode*, uint32_t dst[],
                                    const SkPM4f src[], int count, const SkAlpha aa[]) {
    if (aa) {
        for (int i = 0; i < count; ++i) {
            unsigned a = aa[i];
            if (0 == a) {
                continue;
            }
            Sk4f s4 = src[i].to4f_pmorder();
            Sk4f d4 = load_dst<D>(dst[i]);
            if (a != 0xFF) {
                s4 = scale_by_coverage(s4, a);
            }
            Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4));
            dst[i] = store_dst<D>(r4);
        }
    } else {
        while (count >= 4 && D == kSRGB_Dst) {
            auto d = load_4_srgb(dst);

            auto s = Sk4x4f::Transpose(src->fVec);
        #if defined(SK_PMCOLOR_IS_BGRA)
            SkTSwap(s.r, s.b);
        #endif

            auto invSA = 1.0f - s.a;
            auto r = s.r + d.r * invSA,
                 g = s.g + d.g * invSA,
                 b = s.b + d.b * invSA,
                 a = s.a + d.a * invSA;

            store_4_srgb(dst, Sk4x4f{r,g,b,a});
            count -= 4;
            dst += 4;
            src += 4;
        }
        for (int i = 0; i < count; ++i) {
            Sk4f s4 = src[i].to4f_pmorder();
            Sk4f d4 = load_dst<D>(dst[i]);
            Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4));
            dst[i] = store_dst<D>(r4);
        }
    }
}
Пример #19
0
void SkLinearGradient::
LinearGradient4fContext::mapTs(int x, int y, SkScalar ts[], int count) const {
    SkASSERT(count > 0);
    SkASSERT(fDstToPosClass != kLinear_MatrixClass);

    SkScalar sx = x + SK_ScalarHalf;
    const SkScalar sy = y + SK_ScalarHalf;
    SkPoint pt;

    if (fDstToPosClass != kPerspective_MatrixClass) {
        // kLinear_MatrixClass, kFixedStepInX_MatrixClass => fixed dt per scanline
        const SkScalar dtdx = fDstToPos.fixedStepInX(sy).x();
        fDstToPosProc(fDstToPos, sx, sy, &pt);

        const Sk4f dtdx4 = Sk4f(4 * dtdx);
        Sk4f t4 = Sk4f(pt.x() + 0 * dtdx,
                       pt.x() + 1 * dtdx,
                       pt.x() + 2 * dtdx,
                       pt.x() + 3 * dtdx);

        while (count >= 4) {
            t4.store(ts);
            t4 = t4 + dtdx4;
            ts += 4;
            count -= 4;
        }

        if (count & 2) {
            *ts++ = t4[0];
            *ts++ = t4[1];
            t4 = SkNx_shuffle<2, 0, 1, 3>(t4);
        }

        if (count & 1) {
            *ts++ = t4[0];
        }
    } else {
        for (int i = 0; i < count; ++i) {
            fDstToPosProc(fDstToPos, sx, sy, &pt);
            ts[i] = pt.x();
            sx += SK_Scalar1;
        }
    }
}
Пример #20
0
static void srcover_linear_dst_1(const SkXfermode*, uint32_t dst[],
                                 const SkPM4f* src, int count, const SkAlpha aa[]) {
    const Sk4f s4 = src->to4f_pmorder();
    const Sk4f dst_scale = Sk4f(1 - get_alpha(s4));

    if (aa) {
        for (int i = 0; i < count; ++i) {
            unsigned a = aa[i];
            if (0 == a) {
                continue;
            }
            Sk4f d4 = Sk4f_fromL32(dst[i]);
            Sk4f r4;
            if (a != 0xFF) {
                Sk4f s4_aa = scale_by_coverage(s4, a);
                r4 = s4_aa + d4 * Sk4f(1 - get_alpha(s4_aa));
            } else {
                r4 = s4 + d4 * dst_scale;
            }
            dst[i] = Sk4f_toL32(r4);
        }
    } else {
        const Sk4f s4_255 = s4 * Sk4f(255) + Sk4f(0.5f);   // +0.5 to pre-bias for rounding
        while (count >= 4) {
            Sk4f d0 = to_4f(dst[0]);
            Sk4f d1 = to_4f(dst[1]);
            Sk4f d2 = to_4f(dst[2]);
            Sk4f d3 = to_4f(dst[3]);
            Sk4f_ToBytes((uint8_t*)dst,
                         s4_255 + d0 * dst_scale,
                         s4_255 + d1 * dst_scale,
                         s4_255 + d2 * dst_scale,
                         s4_255 + d3 * dst_scale);
            dst += 4;
            count -= 4;
        }
        for (int i = 0; i < count; ++i) {
            Sk4f d4 = to_4f(dst[i]);
            dst[i] = to_4b(s4_255 + d4 * dst_scale);
        }
    }
}
Пример #21
0
void GrCCPathParser::parsePath(const SkMatrix& m, const SkPath& path, SkRect* devBounds,
                               SkRect* devBounds45) {
    const SkPoint* pts = SkPathPriv::PointData(path);
    int numPts = path.countPoints();
    SkASSERT(numPts + 1 <= fLocalDevPtsBuffer.count());

    if (!numPts) {
        devBounds->setEmpty();
        devBounds45->setEmpty();
        this->parsePath(path, nullptr);
        return;
    }

    // m45 transforms path points into "45 degree" device space. A bounding box in this space gives
    // the circumscribing octagon's diagonals. We could use SK_ScalarRoot2Over2, but an orthonormal
    // transform is not necessary as long as the shader uses the correct inverse.
    SkMatrix m45;
    m45.setSinCos(1, 1);
    m45.preConcat(m);

    // X,Y,T are two parallel view matrices that accumulate two bounding boxes as they map points:
    // device-space bounds and "45 degree" device-space bounds (| 1 -1 | * devCoords).
    //                                                          | 1  1 |
    Sk4f X = Sk4f(m.getScaleX(), m.getSkewY(), m45.getScaleX(), m45.getSkewY());
    Sk4f Y = Sk4f(m.getSkewX(), m.getScaleY(), m45.getSkewX(), m45.getScaleY());
    Sk4f T = Sk4f(m.getTranslateX(), m.getTranslateY(), m45.getTranslateX(), m45.getTranslateY());

    // Map the path's points to device space and accumulate bounding boxes.
    Sk4f devPt = SkNx_fma(Y, Sk4f(pts[0].y()), T);
    devPt = SkNx_fma(X, Sk4f(pts[0].x()), devPt);
    Sk4f topLeft = devPt;
    Sk4f bottomRight = devPt;

    // Store all 4 values [dev.x, dev.y, dev45.x, dev45.y]. We are only interested in the first two,
    // and will overwrite [dev45.x, dev45.y] with the next point. This is why the dst buffer must
    // be at least one larger than the number of points.
    devPt.store(&fLocalDevPtsBuffer[0]);

    for (int i = 1; i < numPts; ++i) {
        devPt = SkNx_fma(Y, Sk4f(pts[i].y()), T);
        devPt = SkNx_fma(X, Sk4f(pts[i].x()), devPt);
        topLeft = Sk4f::Min(topLeft, devPt);
        bottomRight = Sk4f::Max(bottomRight, devPt);
        devPt.store(&fLocalDevPtsBuffer[i]);
    }

    SkPoint topLeftPts[2], bottomRightPts[2];
    topLeft.store(topLeftPts);
    bottomRight.store(bottomRightPts);
    devBounds->setLTRB(topLeftPts[0].x(), topLeftPts[0].y(), bottomRightPts[0].x(),
                       bottomRightPts[0].y());
    devBounds45->setLTRB(topLeftPts[1].x(), topLeftPts[1].y(), bottomRightPts[1].x(),
                         bottomRightPts[1].y());

    this->parsePath(path, fLocalDevPtsBuffer.get());
}
Пример #22
0
static void clear(const SkXfermode*, uint64_t dst[], const SkPM4f*, int count, const SkAlpha aa[]) {
    if (aa) {
        for (int i = 0; i < count; ++i) {
            if (aa[i]) {
                const Sk4f d4 = SkHalfToFloat_finite_ftz(dst[i]);
                SkFloatToHalf_finite_ftz(d4 * Sk4f((255 - aa[i]) * 1.0f/255)).store(&dst[i]);
            }
        }
    } else {
        sk_memset64(dst, 0, count);
    }
}
Пример #23
0
    void advance(SkScalar advX) {
        SkASSERT(advX > 0);
        SkASSERT(fAdvX >= 0);

        if (advX >= fAdvX) {
            advX = this->advance_interval(advX);
        }
        SkASSERT(advX < fAdvX);

        fCc = fCc + fDcDx * Sk4f(advX);
        fAdvX -= advX;
    }
Пример #24
0
static void clear_srgb(const SkXfermode*, uint32_t dst[], const SkPM4f[],
                       int count, const SkAlpha aa[]) {
    if (aa) {
        for (int i = 0; i < count; ++i) {
            if (aa[i]) {
                Sk4f d = Sk4f_fromS32(dst[i]) * Sk4f((255 - aa[i]) * (1/255.0f));
                dst[i] = Sk4f_toS32(d);
            }
        }
    } else {
        sk_memset32(dst, 0, count);
    }
}
Пример #25
0
static void clear_srgb_n(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f[],
                           int count, const SkAlpha aa[]) {
    if (aa) {
        for (int i = 0; i < count; ++i) {
            unsigned a = aa[i];
            if (a) {
                Sk4f d = Sk4f_fromS32(dst[i]) * Sk4f((255 - a) * (1/255.0f));
                dst[i] = Sk4f_toS32(d);
            }
        }
    } else {
        sk_bzero(dst, count * sizeof(SkPMColor));
    }
}
Пример #26
0
static void srcover_1(const SkXfermode*, uint64_t dst[], const SkPM4f* src, int count,
                      const SkAlpha aa[]) {
    const Sk4f s4 = Sk4f::Load(src->fVec);
    const Sk4f dst_scale = Sk4f(1 - get_alpha(s4));
    for (int i = 0; i < count; ++i) {
        const Sk4f d4 = SkHalfToFloat_finite_ftz(dst[i]);
        const Sk4f r4 = s4 + d4 * dst_scale;
        if (aa) {
            SkFloatToHalf_finite_ftz(lerp_by_coverage(r4, d4, aa[i])).store(&dst[i]);
        } else {
            SkFloatToHalf_finite_ftz(r4).store(&dst[i]);
        }
    }
}
Пример #27
0
void srcover_n_lcd(uint32_t dst[], const SkPM4f src[], int count, const uint16_t lcd[]) {
    for (int i = 0; i < count; ++i) {
        uint16_t rgb = lcd[i];
        if (0 == rgb) {
            continue;
        }
        Sk4f s4 = Sk4f::Load(src[i].fVec);
        Sk4f dst_scale = Sk4f(1 - get_alpha(s4));
        Sk4f d4 = load_dst<D>(dst[i]);
        Sk4f r4 = s4 + d4 * dst_scale;
        r4 = lerp(r4, d4, lcd16_to_unit_4f(rgb));
        dst[i] = store_dst<D>(r4) | (SK_A32_MASK << SK_A32_SHIFT);
    }
}
Пример #28
0
template <DstType D> void srcover_n(const SkXfermode::U64State& state, uint64_t dst[],
                                    const SkPM4f src[], int count, const SkAlpha aa[]) {
    for (int i = 0; i < count; ++i) {
        const Sk4f s4 = pm_to_rgba_order(Sk4f::Load(src[i].fVec));
        const Sk4f dst_scale = Sk4f(1 - get_alpha(s4));
        const Sk4f s4bias = unit_to_bias<D>(s4);
        const Sk4f d4bias = load_from_dst<D>(dst[i]);
        const Sk4f r4bias = s4bias + d4bias * dst_scale;
        if (aa) {
            dst[i] = store_to_dst<D>(lerp_by_coverage(r4bias, d4bias, aa[i]));
        } else {
            dst[i] = store_to_dst<D>(r4bias);
        }
    }
}
Пример #29
0
static Sk4f softlight_4f(const Sk4f& s, const Sk4f& d) {
    Sk4f sa  = alpha(s);
    Sk4f da  = alpha(d);
    Sk4f isa = Sk4f(1) - sa;
    Sk4f ida = Sk4f(1) - da;

    // Some common terms.
    Sk4f m  = (da > Sk4f(0)).thenElse(d / da, Sk4f(0));
    Sk4f s2 = Sk4f(2) * s;
    Sk4f m4 = Sk4f(4) * m;

    // The logic forks three ways:
    //    1. dark src?
    //    2. light src, dark dst?
    //    3. light src, light dst?
    Sk4f darkSrc = d * (sa + (s2 - sa) * (Sk4f(1) - m));            // Used in case 1.
    Sk4f darkDst = (m4 * m4 + m4) * (m - Sk4f(1)) + Sk4f(7) * m;    // Used in case 2.
    Sk4f liteDst = m.sqrt() - m;                                    // Used in case 3.
    Sk4f liteSrc = d * sa + da * (s2 - sa) * (Sk4f(4) * d <= da).thenElse(darkDst,
                                                                          liteDst); // Case 2 or 3?

    return color_alpha(s * ida + d * isa + (s2 <= sa).thenElse(darkSrc, liteSrc), // Case 1 or 2/3?
                       s + d * isa);
}
Пример #30
0
SkPM4f SkColor4f::premul() const {
    auto src = Sk4f::Load(this->pin().vec());
    float srcAlpha = src.kth<0>();  // need the pinned version of our alpha
    src = src * Sk4f(1, srcAlpha, srcAlpha, srcAlpha);

#ifdef SK_PMCOLOR_IS_BGRA
    // ARGB -> BGRA
    Sk4f dst = SkNx_shuffle<3,2,1,0>(src);
#else
    // ARGB -> RGBA
    Sk4f dst = SkNx_shuffle<1,2,3,0>(src);
#endif

    SkPM4f pm4;
    dst.store(&pm4);
    return pm4;
}