Пример #1
0
void SkOpAngle::debugSameAs(const SkOpAngle* compare) const {
    SK_ALWAYSBREAK(fSegment == compare->fSegment);
    const SkOpSpan& startSpan = fSegment->span(fStart);
    const SkOpSpan& oStartSpan = fSegment->span(compare->fStart);
    SK_ALWAYSBREAK(startSpan.fToAngle == oStartSpan.fToAngle);
    SK_ALWAYSBREAK(startSpan.fFromAngle == oStartSpan.fFromAngle);
    const SkOpSpan& endSpan = fSegment->span(fEnd);
    const SkOpSpan& oEndSpan = fSegment->span(compare->fEnd);
    SK_ALWAYSBREAK(endSpan.fToAngle == oEndSpan.fToAngle);
    SK_ALWAYSBREAK(endSpan.fFromAngle == oEndSpan.fFromAngle);
}
Пример #2
0
void SkOpSegment::debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding,
                                      int oppWinding) {
    const SkPoint& pt = xyAtT(&span);
    SkDebugf("%s id=%d", fun, fID);
    SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
    for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
        SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
    }
    SK_ALWAYSBREAK(&span == &span.fOther->fTs[span.fOtherIndex].fOther->
            fTs[span.fOther->fTs[span.fOtherIndex].fOtherIndex]);
    SkDebugf(") t=%1.9g [%d] (%1.9g,%1.9g) tEnd=%1.9g newWindSum=%d newOppSum=%d oppSum=",
            span.fT, span.fOther->fTs[span.fOtherIndex].fOtherIndex, pt.fX, pt.fY,
            (&span)[1].fT, winding, oppWinding);
    if (span.fOppSum == SK_MinS32) {
        SkDebugf("?");
    } else {
        SkDebugf("%d", span.fOppSum);
    }
    SkDebugf(" windSum=");
    if (span.fWindSum == SK_MinS32) {
        SkDebugf("?");
    } else {
        SkDebugf("%d", span.fWindSum);
    }
    SkDebugf(" windValue=%d oppValue=%d\n", span.fWindValue, span.fOppValue);
}
Пример #3
0
void SkOpSegment::debugCheckPointsEqualish(int tStart, int tEnd) const {
    const SkPoint& basePt = fTs[tStart].fPt;
    while (++tStart < tEnd) {
       const SkPoint& cmpPt = fTs[tStart].fPt;
       SK_ALWAYSBREAK(SkDPoint::ApproximatelyEqual(basePt, cmpPt));
    }
}
Пример #4
0
// SK_ALWAYSBREAK if pair has not already been added
void SkOpSegment::debugAddTPair(double t, const SkOpSegment& other, double otherT) const {
    for (int i = 0; i < fTs.count(); ++i) {
        if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == otherT) {
            return;
        }
    }
    SK_ALWAYSBREAK(0);
}
Пример #5
0
static SkCachedData* make_data(size_t size, SkDiscardableMemoryPool* pool) {
    if (pool) {
        SkDiscardableMemory* dm = pool->create(size);
        // the pool "can" return null, but it shouldn't in these controlled conditions
        SK_ALWAYSBREAK(dm);
        return new SkCachedData(size, dm);
    } else {
        return new SkCachedData(sk_malloc_throw(size), size);
    }
}
Пример #6
0
    /** localeNameLength must include the null terminator. */
    SkFontMgr_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* fontCollection,
                          WCHAR* localeName, int localeNameLength)
        : fFactory(SkRefComPtr(factory))
        , fFontCollection(SkRefComPtr(fontCollection))
        , fLocaleName(localeNameLength)
    {
#if SK_HAS_DWRITE_2_H
        if (!SUCCEEDED(fFactory->QueryInterface(&fFactory2))) {
            // IUnknown::QueryInterface states that if it fails, punk will be set to NULL.
            // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/26/96777.aspx
            SK_ALWAYSBREAK(NULL == fFactory2.get());
        }
#endif
        memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
    }
Пример #7
0
void SkOpAngle::debugValidateNext() const {
    const SkOpAngle* first = this;
    const SkOpAngle* next = first;
    SkTDArray<const SkOpAngle*>(angles);
    do {
//        SK_ALWAYSBREAK(next->fSegment->debugContains(next));
        angles.push(next);
        next = next->next();
        if (next == first) {
            break;
        }
        SK_ALWAYSBREAK(!angles.contains(next));
        if (!next) {
            return;
        }
    } while (true);
}
Пример #8
0
void SkOpSegment::debugShowActiveSpans() const {
    debugValidate();
    if (done()) {
        return;
    }
#if DEBUG_ACTIVE_SPANS_SHORT_FORM
    int lastId = -1;
    double lastT = -1;
#endif
    for (int i = 0; i < fTs.count(); ++i) {
        if (fTs[i].fDone) {
            continue;
        }
        SK_ALWAYSBREAK(i < fTs.count() - 1);
#if DEBUG_ACTIVE_SPANS_SHORT_FORM
        if (lastId == fID && lastT == fTs[i].fT) {
            continue;
        }
        lastId = fID;
        lastT = fTs[i].fT;
#endif
        SkDebugf("%s id=%d", __FUNCTION__, fID);
        SkDebugf(" (%1.9g,%1.9g", fPts[0].fX, fPts[0].fY);
        for (int vIndex = 1; vIndex <= SkPathOpsVerbToPoints(fVerb); ++vIndex) {
            SkDebugf(" %1.9g,%1.9g", fPts[vIndex].fX, fPts[vIndex].fY);
        }
        const SkOpSpan* span = &fTs[i];
        SkDebugf(") t=%1.9g (%1.9g,%1.9g)", span->fT, xAtT(span), yAtT(span));
        int iEnd = i + 1;
        while (fTs[iEnd].fT < 1 && approximately_equal(fTs[i].fT, fTs[iEnd].fT)) {
            ++iEnd;
        }
        SkDebugf(" tEnd=%1.9g", fTs[iEnd].fT);
        const SkOpSegment* other = fTs[i].fOther;
        SkDebugf(" other=%d otherT=%1.9g otherIndex=%d windSum=",
                other->fID, fTs[i].fOtherT, fTs[i].fOtherIndex);
        if (fTs[i].fWindSum == SK_MinS32) {
            SkDebugf("?");
        } else {
            SkDebugf("%d", fTs[i].fWindSum);
        }
        SkDebugf(" windValue=%d oppValue=%d\n", fTs[i].fWindValue, fTs[i].fOppValue);
    }
}
Пример #9
0
Error HWUISink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const {
    // Do all setup in this function because we don't know the size
    // for the RenderNode and RenderProxy during the constructor.
    // In practice this doesn't seem too expensive.
    const SkISize size = src.size();

    // Based on android::SurfaceTexture_init()
    android::sp<android::IGraphicBufferProducer> producer;
    android::sp<android::IGraphicBufferConsumer> consumer;
    android::BufferQueue::createBufferQueue(&producer, &consumer);

    // Consumer setup

    android::sp<android::CpuConsumer> cpuConsumer =
        new android::CpuConsumer(consumer, 1);
    cpuConsumer->setName(android::String8("SkiaTestClient"));
    cpuConsumer->setDefaultBufferSize(size.width(), size.height());

    // Producer setup

    android::sp<android::Surface> surface = new android::Surface(producer);
    native_window_set_buffers_dimensions(surface.get(), size.width(), size.height());
    native_window_set_buffers_format(surface.get(), android::PIXEL_FORMAT_RGBA_8888);
    native_window_set_usage(surface.get(), GRALLOC_USAGE_SW_READ_OFTEN |
                                           GRALLOC_USAGE_SW_WRITE_NEVER |
                                           GRALLOC_USAGE_HW_RENDER);

    // RenderNode setup based on hwui/tests/main.cpp:TreeContentAnimation
    SkAutoTDelete<android::uirenderer::RenderNode> rootNode
        (new android::uirenderer::RenderNode());
    rootNode->incStrong(nullptr);

    // Values set here won't be applied until the framework has called
    // RenderNode::pushStagingPropertiesChanges() during RenderProxy::syncAndDrawFrame().
    rootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, size.width(), size.height());
    rootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::X |
                                     android::uirenderer::RenderNode::Y);
    rootNode->mutateStagingProperties().setClipToBounds(false);
    rootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::GENERIC);

    // RenderProxy setup based on hwui/tests/main.cpp:TreeContentAnimation
    ContextFactory factory;
    SkAutoTDelete<android::uirenderer::renderthread::RenderProxy> proxy
        (new android::uirenderer::renderthread::RenderProxy(false, rootNode, &factory));
    proxy->loadSystemProperties();

    proxy->initialize(surface.get());

    float lightX = size.width() / 2.0f;
    android::uirenderer::Vector3 lightVector { lightX, dp(-200.0f), dp(800.0f) };
    proxy->setup(size.width(), size.height(), lightVector, dp(800.0f), 255 * 0.075f, 255 * 0.15f,
                 kDensity);

    // Do the draw

    SkAutoTDelete<android::uirenderer::DisplayListRenderer> renderer
        (new android::uirenderer::DisplayListRenderer());
    renderer->setViewport(size.width(), size.height());
    renderer->prepare();
    renderer->clipRect(0, 0, size.width(), size.height(), SkRegion::Op::kReplace_Op);

    Error err = src.draw(renderer->asSkCanvas());
    if (!err.isEmpty()) {
        return err;
    }

    renderer->finish();
    rootNode->setStagingDisplayList(renderer->finishRecording());

    proxy->syncAndDrawFrame();
    proxy->fence();

    // Capture pixels

    SkImageInfo destinationConfig =
        SkImageInfo::Make(size.width(), size.height(),
                          kRGBA_8888_SkColorType, kPremul_SkAlphaType);
    dst->allocPixels(destinationConfig);
    sk_memset32((uint32_t*) dst->getPixels(), SK_ColorRED, size.width() * size.height());

    android::CpuConsumer::LockedBuffer nativeBuffer;
    android::status_t retval = cpuConsumer->lockNextBuffer(&nativeBuffer);
    if (retval == android::BAD_VALUE) {
        SkDebugf("HWUISink::draw() got no buffer; returning transparent");
        // No buffer ready to read - commonly triggered by dm sending us
        // a no-op source, or calling code that doesn't do anything on this
        // backend.
        dst->eraseColor(SK_ColorTRANSPARENT);
        return "";
    } else if (retval) {
        return SkStringPrintf("Failed to lock buffer to read pixels: %d.", retval);
    }

    // Move the pixels into the destination SkBitmap

    SK_ALWAYSBREAK(nativeBuffer.format == android::PIXEL_FORMAT_RGBA_8888 &&
                   "Native buffer not RGBA!");
    SkImageInfo nativeConfig =
        SkImageInfo::Make(nativeBuffer.width, nativeBuffer.height,
                          kRGBA_8888_SkColorType, kPremul_SkAlphaType);

    // Android stride is in pixels, Skia stride is in bytes
    SkBitmap nativeWrapper;
    bool success =
        nativeWrapper.installPixels(nativeConfig, nativeBuffer.data, nativeBuffer.stride * 4);
    if (!success) {
        return "Failed to wrap HWUI buffer in a SkBitmap";
    }

    SK_ALWAYSBREAK(dst->colorType() == kRGBA_8888_SkColorType &&
                   "Destination buffer not RGBA!");
    success =
        nativeWrapper.readPixels(destinationConfig, dst->getPixels(), dst->rowBytes(), 0, 0);
    if (!success) {
        return "Failed to extract pixels from HWUI buffer";
    }

    cpuConsumer->unlockBuffer(nativeBuffer);
    return "";
}
Пример #10
0
void SkOpSegment::debugValidate() const {
#if DEBUG_VALIDATE
    int count = fTs.count();
    SK_ALWAYSBREAK(count >= 2);
    SK_ALWAYSBREAK(fTs[0].fT == 0);
    SK_ALWAYSBREAK(fTs[count - 1].fT == 1);
    int done = 0;
    double t = -1;
    const SkOpSpan* last = NULL;
    bool tinyTFound = false;
    bool hasLoop = false;
    for (int i = 0; i < count; ++i) {
        const SkOpSpan& span = fTs[i];
        SK_ALWAYSBREAK(t <= span.fT);
        t = span.fT;
        int otherIndex = span.fOtherIndex;
        const SkOpSegment* other = span.fOther;
        SK_ALWAYSBREAK(other != this || fVerb == SkPath::kCubic_Verb);
        const SkOpSpan& otherSpan = other->fTs[otherIndex];
        SK_ALWAYSBREAK(otherSpan.fPt == span.fPt);
        SK_ALWAYSBREAK(otherSpan.fOtherT == t);
        SK_ALWAYSBREAK(&fTs[i] == &otherSpan.fOther->fTs[otherSpan.fOtherIndex]);
        done += span.fDone;
        if (last) {
            SK_ALWAYSBREAK(last->fT != span.fT || last->fOther != span.fOther);
            bool tsEqual = last->fT == span.fT;
            bool tsPreciselyEqual = precisely_equal(last->fT, span.fT);
            SK_ALWAYSBREAK(!tsEqual || tsPreciselyEqual);
            bool pointsEqual = last->fPt == span.fPt;
            bool pointsNearlyEqual = AlmostEqualUlps(last->fPt, span.fPt);
#if 0  // bufferOverflow test triggers this
            SK_ALWAYSBREAK(!tsPreciselyEqual || pointsNearlyEqual);
#endif
//            SK_ALWAYSBREAK(!last->fTiny || !tsPreciselyEqual || span.fTiny || tinyTFound);
            SK_ALWAYSBREAK(last->fTiny || tsPreciselyEqual || !pointsEqual || hasLoop);
            SK_ALWAYSBREAK(!last->fTiny || pointsEqual);
            SK_ALWAYSBREAK(!last->fTiny || last->fDone);
            SK_ALWAYSBREAK(!last->fSmall || pointsNearlyEqual);
            SK_ALWAYSBREAK(!last->fSmall || last->fDone);
//            SK_ALWAYSBREAK(!last->fSmall || last->fTiny);
//            SK_ALWAYSBREAK(last->fTiny || !pointsEqual || last->fDone == span.fDone);
            if (last->fTiny) {
                tinyTFound |= !tsPreciselyEqual;
            } else {
                tinyTFound = false;
            }
        }
        last = &span;
        hasLoop |= last->fLoop;
    }
    SK_ALWAYSBREAK(done == fDoneSpans);
//    if (fAngles.count() ) {
//        fAngles.begin()->debugValidateLoop();
//    }
#endif
}
Пример #11
0
void SkOpAngle::debugValidateLoop() const {
    const SkOpAngle* first = this;
    const SkOpAngle* next = first;
    SK_ALWAYSBREAK(first->next() != first);
    int signSum = 0;
    int oppSum = 0;
    bool firstOperand = fSegment->operand();
    bool unorderable = false;
    do {
        unorderable |= next->fUnorderable;
        const SkOpSegment* segment = next->fSegment;
        bool operandsMatch = firstOperand == segment->operand();
        signSum += operandsMatch ? segment->spanSign(next) : segment->oppSign(next);
        oppSum += operandsMatch ? segment->oppSign(next) : segment->spanSign(next);
        const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
        if (segment->_xor()) {
//            SK_ALWAYSBREAK(span.fWindValue == 1);
//            SK_ALWAYSBREAK(span.fWindSum == SK_MinS32 || span.fWindSum == 1);
        }
        if (segment->oppXor()) {
            SK_ALWAYSBREAK(span.fOppValue == 0 || abs(span.fOppValue) == 1);
//            SK_ALWAYSBREAK(span.fOppSum == SK_MinS32 || span.fOppSum == 0 || abs(span.fOppSum) == 1);
        }
        next = next->next();
        if (!next) {
            return;
        }
    } while (next != first);
    if (unorderable) {
        return;
    }
    SK_ALWAYSBREAK(!signSum || fSegment->_xor());
    SK_ALWAYSBREAK(!oppSum || fSegment->oppXor());
    int lastWinding;
    int lastOppWinding;
    int winding;
    int oppWinding;
    do {
        const SkOpSegment* segment = next->fSegment;
        const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
        winding = span.fWindSum;
        if (winding != SK_MinS32) {
//            SK_ALWAYSBREAK(winding != 0);
            SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
            lastWinding = winding;
            int diffWinding = segment->spanSign(next);
            if (!segment->_xor()) {
                SK_ALWAYSBREAK(diffWinding != 0);
                bool sameSign = (winding > 0) == (diffWinding > 0);
                winding -= sameSign ? diffWinding : -diffWinding;
                SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
                SK_ALWAYSBREAK(abs(winding) <= abs(lastWinding));
                if (!sameSign) {
                    SkTSwap(winding, lastWinding);
                }
            }
            lastOppWinding = oppWinding = span.fOppSum;
            if (oppWinding != SK_MinS32 && !segment->oppXor()) {
                int oppDiffWinding = segment->oppSign(next);
//                SK_ALWAYSBREAK(abs(oppDiffWinding) <= abs(diffWinding) || segment->_xor());
                if (oppDiffWinding) {
                    bool oppSameSign = (oppWinding > 0) == (oppDiffWinding > 0);
                    oppWinding -= oppSameSign ? oppDiffWinding : -oppDiffWinding;
                    SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
                    SK_ALWAYSBREAK(abs(oppWinding) <= abs(lastOppWinding));
                    if (!oppSameSign) {
                        SkTSwap(oppWinding, lastOppWinding);
                    }
                }
            }
            firstOperand = segment->operand();
            break;
        }
        SK_ALWAYSBREAK(span.fOppSum == SK_MinS32);
        next = next->next();
    } while (next != first);
    if (winding == SK_MinS32) {
        return;
    }
    SK_ALWAYSBREAK(oppWinding == SK_MinS32 || SkPathOpsDebug::ValidWind(oppWinding));
    first = next;
    next = next->next();
    do {
        const SkOpSegment* segment = next->fSegment;
        lastWinding = winding;
        lastOppWinding = oppWinding;
        bool operandsMatch = firstOperand == segment->operand();
        if (operandsMatch) {
            if (!segment->_xor()) {
                winding -= segment->spanSign(next);
                SK_ALWAYSBREAK(winding != lastWinding);
                SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
            }
            if (!segment->oppXor()) {
                int oppDiffWinding = segment->oppSign(next);
                if (oppWinding != SK_MinS32) {
                    oppWinding -= oppDiffWinding;
                    SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
                } else {
                    SK_ALWAYSBREAK(oppDiffWinding == 0);
                }
            }
        } else {
            if (!segment->oppXor()) {
                winding -= segment->oppSign(next);
                SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(winding));
            }
            if (!segment->_xor()) {
                oppWinding -= segment->spanSign(next);
                SK_ALWAYSBREAK(oppWinding != lastOppWinding);
                SK_ALWAYSBREAK(SkPathOpsDebug::ValidWind(oppWinding));
            }
        }
        bool useInner = SkOpSegment::UseInnerWinding(lastWinding, winding);
        int sumWinding = useInner ? winding : lastWinding;
        bool oppUseInner = SkOpSegment::UseInnerWinding(lastOppWinding, oppWinding);
        int oppSumWinding = oppUseInner ? oppWinding : lastOppWinding;
        if (!operandsMatch) {
            SkTSwap(useInner, oppUseInner);
            SkTSwap(sumWinding, oppSumWinding);
        }
        const SkOpSpan& span = segment->span(SkMin32(next->fStart, next->fEnd));
        if (winding == -lastWinding) {
            if (span.fWindSum != SK_MinS32) {
                SkDebugf("%s useInner=%d spanSign=%d lastWinding=%d winding=%d windSum=%d\n",
                        __FUNCTION__,
                        useInner, segment->spanSign(next), lastWinding, winding, span.fWindSum);
            }
        }
        if (oppWinding != SK_MinS32) {
            if (span.fOppSum != SK_MinS32) {
                SK_ALWAYSBREAK(span.fOppSum == oppSumWinding || segment->oppXor() || segment->_xor());
            }
        } else {
            SK_ALWAYSBREAK(!firstOperand);
            SK_ALWAYSBREAK(!segment->operand());
            SK_ALWAYSBREAK(!span.fOppValue);
        }
        next = next->next();
    } while (next != first);
}