static void showPath(const SkPath& path, const char* pathName, bool includeDeclaration) {
    SkPath::RawIter iter(path);
#define SUPPORT_RECT_CONTOUR_DETECTION 0
#if SUPPORT_RECT_CONTOUR_DETECTION
    int rectCount = path.isRectContours() ? path.rectContours(NULL, NULL) : 0;
    if (rectCount > 0) {
        SkTDArray<SkRect> rects;
        SkTDArray<SkPath::Direction> directions;
        rects.setCount(rectCount);
        directions.setCount(rectCount);
        path.rectContours(rects.begin(), directions.begin());
        for (int contour = 0; contour < rectCount; ++contour) {
            const SkRect& rect = rects[contour];
            SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop,
                    rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction
                    ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction");
        }
        return;
    }
#endif
    SkPath::FillType fillType = path.getFillType();
    SkASSERT(fillType >= SkPath::kWinding_FillType && fillType <= SkPath::kInverseEvenOdd_FillType);
    if (includeDeclaration) {
        SkDebugf("    SkPath %s;\n", pathName);
    }
    SkDebugf("    %s.setFillType(SkPath::%s);\n", pathName, gFillTypeStr[fillType]);
    iter.setPath(path);
    showPathContours(iter, pathName);
}
Exemple #2
0
void initializeTests(skiatest::Reporter* reporter, const char* test) {
#if 0  // doesn't work yet
    SK_CONF_SET("images.jpeg.suppressDecoderWarnings", true);
    SK_CONF_SET("images.png.suppressDecoderWarnings", true);
#endif
    if (reporter->verbose()) {
        SkAutoMutexAcquire lock(gMutex);
        testName = test;
        size_t testNameSize = strlen(test);
        SkFILEStream inFile("../../experimental/Intersection/op.htm");
        if (inFile.isValid()) {
            SkTDArray<char> inData;
            inData.setCount((int) inFile.getLength());
            size_t inLen = inData.count();
            inFile.read(inData.begin(), inLen);
            inFile.setPath(nullptr);
            char* insert = strstr(inData.begin(), marker);
            if (insert) {
                insert += sizeof(marker) - 1;
                const char* numLoc = insert + 4 /* indent spaces */ + testNameSize - 1;
                testNumber = atoi(numLoc) + 1;
            }
        }
    }
}
void draw(SkCanvas* canvas) {
    SkPath path, copy;
    path.lineTo(6.f / 7, 2.f / 3);
    size_t size = path.writeToMemory(nullptr);
    SkTDArray<char> storage;
    storage.setCount(size);
    path.writeToMemory(storage.begin());
    copy.readFromMemory(storage.begin(), size);
    SkDebugf("path is " "%s" "equal to copy\n", path == copy ? "" : "not ");
}
Exemple #4
0
void showPath(const SkPath& path, const char* str) {
    SkDebugf("%s\n", !str ? "original:" : str);
    SkPath::Iter iter(path, true);
    int rectCount = path.isRectContours() ? path.rectContours(NULL, NULL) : 0;
    if (rectCount > 0) {
        SkTDArray<SkRect> rects;
        SkTDArray<SkPath::Direction> directions;
        rects.setCount(rectCount);
        directions.setCount(rectCount);
        path.rectContours(rects.begin(), directions.begin());
        for (int contour = 0; contour < rectCount; ++contour) {
            const SkRect& rect = rects[contour];
            SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g, %s);\n", rect.fLeft, rect.fTop,
                    rect.fRight, rect.fBottom, directions[contour] == SkPath::kCCW_Direction
                    ? "SkPath::kCCW_Direction" : "SkPath::kCW_Direction");
        }
        return;
    }
    iter.setPath(path, true);
    showPathContour(iter);
}
void SkTileGrid::search(const SkIRect& query, SkTDArray<void*>* results) {
    SkIRect adjustedQuery = query;
    // The inset is to counteract the outset that was applied in 'insert'
    // The outset/inset is to optimize for lookups of size
    // 'tileInterval + 2 * margin' that are aligned with the tile grid.
    adjustedQuery.inset(fInfo.fMargin.width(), fInfo.fMargin.height());
    adjustedQuery.offset(fInfo.fOffset);
    adjustedQuery.sort();  // in case the inset inverted the rectangle
    // Convert the query rectangle from device coordinates to tile coordinates
    // by rounding outwards to the nearest tile boundary so that the resulting tile
    // region includes the query rectangle. (using truncating division to "floor")
    int tileStartX = adjustedQuery.left() / fInfo.fTileInterval.width();
    int tileEndX = (adjustedQuery.right() + fInfo.fTileInterval.width() - 1) /
        fInfo.fTileInterval.width();
    int tileStartY = adjustedQuery.top() / fInfo.fTileInterval.height();
    int tileEndY = (adjustedQuery.bottom() + fInfo.fTileInterval.height() - 1) /
        fInfo.fTileInterval.height();

    tileStartX = SkPin32(tileStartX, 0, fXTileCount - 1);
    tileEndX = SkPin32(tileEndX, tileStartX+1, fXTileCount);
    tileStartY = SkPin32(tileStartY, 0, fYTileCount - 1);
    tileEndY = SkPin32(tileEndY, tileStartY+1, fYTileCount);

    int queryTileCount = (tileEndX - tileStartX) * (tileEndY - tileStartY);
    SkASSERT(queryTileCount);
    if (queryTileCount == 1) {
        *results = this->tile(tileStartX, tileStartY);
    } else {
        results->reset();
        SkTDArray<int> curPositions;
        curPositions.setCount(queryTileCount);
        // Note: Reserving space for 1024 tile pointers on the stack. If the
        // malloc becomes a bottleneck, we may consider increasing that number.
        // Typical large web page, say 2k x 16k, would require 512 tiles of
        // size 256 x 256 pixels.
        SkAutoSTArray<1024, SkTDArray<void *>*> storage(queryTileCount);
        SkTDArray<void *>** tileRange = storage.get();
        int tile = 0;
        for (int x = tileStartX; x < tileEndX; ++x) {
            for (int y = tileStartY; y < tileEndY; ++y) {
                tileRange[tile] = &this->tile(x, y);
                curPositions[tile] = tileRange[tile]->count() ? 0 : kTileFinished;
                ++tile;
            }
        }
        void *nextElement;
        while(NULL != (nextElement = fNextDatumFunction(tileRange, curPositions))) {
            results->push(nextElement);
        }
    }
}
bool SkConcaveToTriangles(size_t numPts,
                          const SkPoint pts[],
                          SkTDArray<SkPoint> *triangles) {
    DebugPrintf("SkConcaveToTriangles()\n");

    SkTDArray<Vertex> vertices;
    vertices.setCount(numPts);
    if (!ConvertPointsToVertices(numPts, pts, vertices.begin()))
        return false;

    triangles->setReserve(numPts);
    triangles->setCount(0);
    return Triangulate(vertices.begin(), vertices.end() - 1, triangles);
}
Exemple #7
0
void SkTileGrid::search(const SkIRect& query, SkTDArray<void*>* results) {
    SkIRect adjustedQuery = query;
    adjustedQuery.inset(fInfo.fMargin.width(), fInfo.fMargin.height());
    adjustedQuery.offset(fInfo.fOffset);
    // Convert the query rectangle from device coordinates to tile coordinates
    // by rounding outwards to the nearest tile boundary so that the resulting tile
    // region includes the query rectangle. (using truncating division to "floor")
    int tileStartX = adjustedQuery.left() / fInfo.fTileInterval.width();
    int tileEndX = (adjustedQuery.right() + fInfo.fTileInterval.width() - 1) /
                   fInfo.fTileInterval.width();
    int tileStartY = adjustedQuery.top() / fInfo.fTileInterval.height();
    int tileEndY = (adjustedQuery.bottom() + fInfo.fTileInterval.height() - 1) /
                   fInfo.fTileInterval.height();
    if (tileStartX >= fXTileCount || tileStartY >= fYTileCount || tileEndX <= 0 || tileEndY <= 0) {
        return; // query does not intersect the grid
    }
    // clamp to grid
    if (tileStartX < 0) tileStartX = 0;
    if (tileStartY < 0) tileStartY = 0;
    if (tileEndX > fXTileCount) tileEndX = fXTileCount;
    if (tileEndY > fYTileCount) tileEndY = fYTileCount;

    int queryTileCount = (tileEndX - tileStartX) * (tileEndY - tileStartY);
    if (queryTileCount == 1) {
        *results = this->tile(tileStartX, tileStartY);
    } else {
        results->reset();
        SkTDArray<int> curPositions;
        curPositions.setCount(queryTileCount);
        // Note: Reserving space for 1024 tile pointers on the stack. If the
        // malloc becomes a bottleneck, we may consider increasing that number.
        // Typical large web page, say 2k x 16k, would require 512 tiles of
        // size 256 x 256 pixels.
        SkAutoSTArray<1024, SkTDArray<void *>*> storage(queryTileCount);
        SkTDArray<void *>** tileRange = storage.get();
        int tile = 0;
        for (int x = tileStartX; x < tileEndX; ++x) {
            for (int y = tileStartY; y < tileEndY; ++y) {
                tileRange[tile] = &this->tile(x, y);
                curPositions[tile] = tileRange[tile]->count() ? 0 : kTileFinished;
                ++tile;
            }
        }
        void *nextElement;
        while(NULL != (nextElement = fNextDatumFunction(tileRange, curPositions))) {
            results->push(nextElement);
        }
    }
}
Exemple #8
0
static bool contains_only_moveTo(const SkPath& path) {
    int verbCount = path.countVerbs();
    if (verbCount == 0) {
        return true;
    }
    SkTDArray<uint8_t> verbs;
    verbs.setCount(verbCount);
    SkDEBUGCODE(int getVerbResult = ) path.getVerbs(verbs.begin(), verbCount);
    SkASSERT(getVerbResult == verbCount);
    for (int index = 0; index < verbCount; ++index) {
        if (verbs[index] != SkPath::kMove_Verb) {
            return false;
        }
    }
    return true;
}
int SkWGLExtensions::selectFormat(const int formats[],
                                  int formatCount,
                                  HDC dc,
                                  int desiredSampleCount) {
    PixelFormat desiredFormat = {
        0,
        desiredSampleCount,
        0,
        0,
    };
    SkTDArray<PixelFormat> rankedFormats;
    rankedFormats.setCount(formatCount);
    bool supportsCoverage = this->hasExtension(dc,
                                               "WGL_NV_multisample_coverage");
    for (int i = 0; i < formatCount; ++i) {
        static const int queryAttrs[] = {
            SK_WGL_COVERAGE_SAMPLES,
            // Keep COLOR_SAMPLES at the end so it can be skipped
            SK_WGL_COLOR_SAMPLES,
        };
        int answers[2];
        int queryAttrCnt = supportsCoverage ?
                                    SK_ARRAY_COUNT(queryAttrs) :
                                    SK_ARRAY_COUNT(queryAttrs) - 1;
        this->getPixelFormatAttribiv(dc,
                                     formats[i],
                                     0,
                                     queryAttrCnt,
                                     queryAttrs,
                                     answers);
        rankedFormats[i].fFormat =  formats[i];
        rankedFormats[i].fCoverageSamples = answers[0];
        rankedFormats[i].fColorSamples = answers[supportsCoverage ? 1 : 0];
        rankedFormats[i].fChoosePixelFormatRank = i;
    }
    SkTQSort(rankedFormats.begin(),
             rankedFormats.begin() + rankedFormats.count() - 1,
             SkTLessFunctionToFunctorAdaptor<PixelFormat, pf_less>());
    int idx = SkTSearch<PixelFormat, pf_less>(rankedFormats.begin(),
                                              rankedFormats.count(),
                                              desiredFormat,
                                              sizeof(PixelFormat));
    if (idx < 0) {
        idx = ~idx;
    }
    return rankedFormats[idx].fFormat;
}
Exemple #10
0
void initializeTests(const char* test, size_t testNameSize) {
    testName = test;
    if (!gRunTestsInOneThread) {
        int threads = -1;
        size_t size = sizeof(threads);
        sysctlbyname("hw.logicalcpu_max", &threads, &size, NULL, 0);
        if (threads > 0) {
            maxThreads = threads;
        } else {
            maxThreads = 8;
        }
    }
    SkFILEStream inFile("../../experimental/Intersection/op.htm");
    if (inFile.isValid()) {
        SkTDArray<char> inData;
        inData.setCount(inFile.getLength());
        size_t inLen = inData.count();
        inFile.read(inData.begin(), inLen);
        inFile.setPath(NULL);
        char* insert = strstr(inData.begin(), marker);
        if (insert) {
            insert += sizeof(marker) - 1;
            const char* numLoc = insert + 4 /* indent spaces */ + testNameSize - 1;
            testNumber = atoi(numLoc) + 1;
        }
    }
    const char* filename = preferredFilename;
    SkFILEWStream preferredTest(filename);
    if (!preferredTest.isValid()) {
        filename = backupFilename;
        SkFILEWStream backupTest(filename);
        SkASSERT(backupTest.isValid());
    }
    for (int index = 0; index < maxThreads; ++index) {
        State4* statePtr = &threadState[index];
        strcpy(statePtr->filename, filename);
        size_t len = strlen(filename);
        SkASSERT(statePtr->filename[len - 6] == 'X');
        SkASSERT(statePtr->filename[len - 5] == 'X');
        statePtr->filename[len - 6] = '0' + index / 10;
        statePtr->filename[len - 5] = '0' + index % 10;
    }
    threadIndex = 0;
}
static uint32_t compute_checksum(const SkTypeface* tf) {
    SkFontData* fontData = tf->createFontData();
    if (!fontData) {
        return 0;
    }
    SkStreamAsset* fontStream = fontData->getStream();
    if (!fontStream) {
        return 0;
    }
    SkTDArray<char> data;
    size_t length = fontStream->getLength();
    if (!length) {
        return 0;
    }
    data.setCount((int) length);
    if (!fontStream->peek(data.begin(), length)) {
        return 0;
    }
    return SkChecksum::Murmur3(data.begin(), length);
}
Exemple #12
0
int SkWGLExtensions::selectFormat(const int formats[],
                                  int formatCount,
                                  HDC dc,
                                  int desiredSampleCount) const {
    if (formatCount <= 0) {
        return -1;
    }
    PixelFormat desiredFormat = {
        0,
        desiredSampleCount,
        0,
    };
    SkTDArray<PixelFormat> rankedFormats;
    rankedFormats.setCount(formatCount);
    for (int i = 0; i < formatCount; ++i) {
        static const int kQueryAttr = SK_WGL_SAMPLES;
        int numSamples;
        this->getPixelFormatAttribiv(dc,
                                     formats[i],
                                     0,
                                     1,
                                     &kQueryAttr,
                                     &numSamples);
        rankedFormats[i].fFormat =  formats[i];
        rankedFormats[i].fSampleCnt = numSamples;
        rankedFormats[i].fChoosePixelFormatRank = i;
    }
    SkTQSort(rankedFormats.begin(),
             rankedFormats.begin() + rankedFormats.count() - 1,
             SkTLessFunctionToFunctorAdaptor<PixelFormat, pf_less>());
    int idx = SkTSearch<PixelFormat, pf_less>(rankedFormats.begin(),
                                              rankedFormats.count(),
                                              desiredFormat,
                                              sizeof(PixelFormat));
    if (idx < 0) {
        idx = ~idx;
    }
    return rankedFormats[idx].fFormat;
}
// Enhance the polygon with trapezoids.
bool ConvertPointsToVertices(size_t numPts, const SkPoint *pts, Vertex *vta) {
    DebugPrintf("ConvertPointsToVertices()\n");

    // Clear everything.
    DebugPrintf("Zeroing vertices\n");
    sk_bzero(vta, numPts * sizeof(*vta));

    // Initialize vertices.
    DebugPrintf("Initializing vertices\n");
    SetVertexPoints(numPts, pts, vta);
    InitializeVertexTopology(numPts, vta);

    PrintVertices(numPts, vta);

    SkTDArray<VertexPtr> vtptr;
    vtptr.setCount(numPts);
    for (int i = numPts; i-- != 0;)
        vtptr[i].vt = vta + i;
    PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);
    DebugPrintf("Sorting vertrap ptr array [%d] %p %p\n", vtptr.count(),
        &vtptr[0], &vtptr[vtptr.count() - 1]
    );
//  SkTHeapSort(vtptr.begin(), vtptr.count());
    BubbleSort(vtptr.begin(), vtptr.count());
    DebugPrintf("Done sorting\n");
    PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);

    DebugPrintf("Traversing sorted vertrap ptrs\n");
    ActiveTrapezoids incompleteTrapezoids;
    for (VertexPtr *vtpp = vtptr.begin(); vtpp < vtptr.end(); ++vtpp) {
        DebugPrintf("%d: sorted vertrap %d\n",
                    vtpp - vtptr.begin(), vtpp->vt - vta);
        Vertex *vt = vtpp->vt;
        Vertex *e0, *e1;
        Trapezoid *t;
        switch (vt->classify(&e0, &e1)) {
            case Vertex::MONOTONE:
            monotone:
                DebugPrintf("MONOTONE %d %d\n", e0 - vta, e1 - vta);
                // We should find one edge.
                t = incompleteTrapezoids.getTrapezoidWithEdge(e0);
                if (t == NULL) {      // One of the edges is flat.
                    DebugPrintf("Monotone: cannot find a trapezoid with e0: "
                                "trying convex\n");
                    goto convex;
                }
                t->setBottom(vt);     // This trapezoid is now complete.
                incompleteTrapezoids.remove(t);

                if (e0 == t->left())  // Replace the left edge.
                    incompleteTrapezoids.insertNewTrapezoid(vt, e1, t->right());
                else                  // Replace the right edge.
                    incompleteTrapezoids.insertNewTrapezoid(vt, t->left(), e1);
                break;

            case Vertex::CONVEX:      // Start of a new trapezoid.
            convex:
                // We don't expect to find any edges.
                DebugPrintf("CONVEX %d %d\n", e0 - vta, e1 - vta);
                if (incompleteTrapezoids.withinActiveTrapezoid(
                        vt->point(), &t)) {
                    // Complete trapezoid.
                    SkASSERT(t != NULL);
                    t->setBottom(vt);
                    incompleteTrapezoids.remove(t);
                    // Introduce two new trapezoids.
                    incompleteTrapezoids.insertNewTrapezoid(vt, t->left(), e0);
                    incompleteTrapezoids.insertNewTrapezoid(vt, e1, t->right());
                } else {
                    // Insert a new trapezoid.
                    incompleteTrapezoids.insertNewTrapezoid(vt, e0, e1);
                }
                break;

            case Vertex::CONCAVE:   // End of a trapezoid.
                DebugPrintf("CONCAVE %d %d\n", e0 - vta, e1 - vta);
                // We should find two edges.
                t = incompleteTrapezoids.getTrapezoidWithEdge(e0);
                if (t == NULL) {
                    DebugPrintf("Concave: cannot find a trapezoid with e0: "
                                " trying monotone\n");
                    goto monotone;
                }
                SkASSERT(t != NULL);
                if (e0 == t->left() && e1 == t->right()) {
                    DebugPrintf(
                            "Concave edges belong to the same trapezoid.\n");
                    // Edges belong to the same trapezoid.
                    // Complete trapezoid & transfer it from the active list.
                    t->setBottom(vt);
                    incompleteTrapezoids.remove(t);
                } else {  // Edges belong to different trapezoids
                    DebugPrintf(
                            "Concave edges belong to different trapezoids.\n");
                    // Complete left and right trapezoids.
                    Trapezoid *s = incompleteTrapezoids.getTrapezoidWithEdge(
                                                                            e1);
                    if (s == NULL) {
                        DebugPrintf(
                                "Concave: cannot find a trapezoid with e1: "
                                " trying monotone\n");
                        goto monotone;
                    }
                    t->setBottom(vt);
                    s->setBottom(vt);
                    incompleteTrapezoids.remove(t);
                    incompleteTrapezoids.remove(s);

                    // Merge the two trapezoids into one below this vertex.
                    incompleteTrapezoids.insertNewTrapezoid(vt, t->left(),
                                                                s->right());
                }
                break;
        }
    }

    RemoveDegenerateTrapezoids(numPts, vta);

    DebugPrintf("Done making trapezoids\n");
    PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);

    size_t k = incompleteTrapezoids.count();
    if (k > 0) {
        FailureMessage("%d incomplete trapezoids\n", k);
        return false;
    }
    return true;
}
Exemple #14
0
void SkDebugger::getOverviewText(const SkTDArray<double>* typeTimes,
                                 double totTime,
                                 SkString* overview,
                                 int numRuns) {
    const SkTDArray<SkDrawCommand*>& commands = this->getDrawCommands();

    SkTDArray<int> counts;
    counts.setCount(LAST_DRAWTYPE_ENUM+1);
    for (int i = 0; i < LAST_DRAWTYPE_ENUM+1; ++i) {
        counts[i] = 0;
    }

    for (int i = 0; i < commands.count(); i++) {
        counts[commands[i]->getType()]++;
    }

    overview->reset();
    int total = 0;
#ifdef SK_DEBUG
    double totPercent = 0, tempSum = 0;
#endif
    for (int i = 0; i < LAST_DRAWTYPE_ENUM+1; ++i) {
        if (0 == counts[i]) {
            // if there were no commands of this type then they should've consumed no time
            SkASSERT(NULL == typeTimes || 0.0 == (*typeTimes)[i]);
            continue;
        }

        overview->append(SkDrawCommand::GetCommandString((DrawType) i));
        overview->append(": ");
        overview->appendS32(counts[i]);
        if (NULL != typeTimes && totTime >= 0.0) {
            overview->append(" - ");
            overview->appendf("%.2f", (*typeTimes)[i]/(float)numRuns);
            overview->append("ms");
            overview->append(" - ");
            double percent = 100.0*(*typeTimes)[i]/totTime;
            overview->appendf("%.2f", percent);
            overview->append("%");
#ifdef SK_DEBUG
            totPercent += percent;
            tempSum += (*typeTimes)[i];
#endif
        }
        overview->append("<br/>");
        total += counts[i];
    }
#ifdef SK_DEBUG
    if (NULL != typeTimes) {
        SkASSERT(SkScalarNearlyEqual(SkDoubleToScalar(totPercent),
                                     SkDoubleToScalar(100.0)));
        SkASSERT(SkScalarNearlyEqual(SkDoubleToScalar(tempSum),
                                     SkDoubleToScalar(totTime)));
    }
#endif

    if (totTime > 0.0) {
        overview->append("Total Time: ");
        overview->appendf("%.2f", totTime/(float)numRuns);
        overview->append("ms");
#ifdef SK_DEBUG
        overview->append(" ");
        overview->appendScalar(SkDoubleToScalar(totPercent));
        overview->append("% ");
#endif
        overview->append("<br/>");
    }

    SkString totalStr;
    totalStr.append("Total Draw Commands: ");
    totalStr.appendScalar(SkDoubleToScalar(total));
    totalStr.append("<br/>");
    overview->insert(0, totalStr);

    overview->append("<br/>");
    overview->append("SkPicture Width: ");
    overview->appendS32(pictureWidth());
    overview->append("px<br/>");
    overview->append("SkPicture Height: ");
    overview->appendS32(pictureHeight());
    overview->append("px");
}