Beispiel #1
0
void RasterShapeIntervals::appendInterval(int y, int x1, int x2)
{
    ASSERT(y >= 0 && y < size() && x1 >= 0 && x2 > x1 && (m_intervalLists[y].isEmpty() || x1 > m_intervalLists[y].last().x2()));

    m_bounds.unite(IntRect(x1, y, x2 - x1, 1));
    m_intervalLists[y].append(IntShapeInterval(x1, x2));
}
Beispiel #2
0
bool RasterShapeIntervals::contains(const IntRect& rect) const
{
    if (!bounds().contains(rect))
        return false;

    const IntShapeInterval& rectInterval = IntShapeInterval(rect.x(), rect.maxX());
    for (int y = rect.y(); y < rect.maxY(); y++) {
        if (!shapeIntervalsContain(intervalsAt(y), rectInterval))
            return false;
    }

    return true;
}
Beispiel #3
0
PassOwnPtr<Shape> Shape::createRasterShape(Image* image, float threshold, const LayoutRect& imageR, const LayoutRect& marginR, WritingMode writingMode, float margin)
{
    IntRect imageRect = pixelSnappedIntRect(imageR);
    IntRect marginRect = pixelSnappedIntRect(marginR);

    OwnPtr<RasterShapeIntervals> intervals = adoptPtr(new RasterShapeIntervals(marginRect.height(), -marginRect.y()));
    OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(imageRect.size());

    if (image && imageBuffer) {
        // FIXME: This is not totally correct but it is needed to prevent shapes
        // that loads SVG Images during paint invalidations to mark layoutObjects for
        // layout, which is not allowed. See https://crbug.com/429346
        ImageObserverDisabler disabler(image);
        SkPaint paint;
        IntRect imageSourceRect(IntPoint(), image->size());
        IntRect imageDestRect(IntPoint(), imageRect.size());
        image->draw(imageBuffer->canvas(), paint, imageDestRect, imageSourceRect, DoNotRespectImageOrientation, Image::DoNotClampImageToSourceRect);

        WTF::ArrayBufferContents contents;
        imageBuffer->getImageData(Unmultiplied, IntRect(IntPoint(), imageRect.size()), contents);
        RefPtr<DOMArrayBuffer> arrayBuffer = DOMArrayBuffer::create(contents);
        RefPtr<DOMUint8ClampedArray> pixelArray = DOMUint8ClampedArray::create(arrayBuffer, 0, arrayBuffer->byteLength());
        unsigned pixelArrayOffset = 3; // Each pixel is four bytes: RGBA.
        uint8_t alphaPixelThreshold = threshold * 255;

        ASSERT(static_cast<unsigned>(imageRect.width() * imageRect.height() * 4) == pixelArray->length());

        int minBufferY = std::max(0, marginRect.y() - imageRect.y());
        int maxBufferY = std::min(imageRect.height(), marginRect.maxY() - imageRect.y());

        for (int y = minBufferY; y < maxBufferY; ++y) {
            int startX = -1;
            for (int x = 0; x < imageRect.width(); ++x, pixelArrayOffset += 4) {
                uint8_t alpha = pixelArray->item(pixelArrayOffset);
                bool alphaAboveThreshold = alpha > alphaPixelThreshold;
                if (startX == -1 && alphaAboveThreshold) {
                    startX = x;
                } else if (startX != -1 && (!alphaAboveThreshold || x == imageRect.width() - 1)) {
                    int endX = alphaAboveThreshold ? x + 1 : x;
                    intervals->intervalAt(y + imageRect.y()).unite(IntShapeInterval(startX + imageRect.x(), endX + imageRect.x()));
                    startX = -1;
                }
            }
        }
    }

    OwnPtr<RasterShape> rasterShape = adoptPtr(new RasterShape(intervals.release(), marginRect.size()));
    rasterShape->m_writingMode = writingMode;
    rasterShape->m_margin = margin;
    return rasterShape.release();
}
Beispiel #4
0
std::unique_ptr<Shape> Shape::createRasterShape(Image* image, float threshold, const LayoutRect& imageR, const LayoutRect& marginR, WritingMode writingMode, float margin)
{
    IntRect imageRect = pixelSnappedIntRect(imageR);
    IntRect marginRect = pixelSnappedIntRect(marginR);
    auto intervals = std::make_unique<RasterShapeIntervals>(marginRect.height(), -marginRect.y());
    std::unique_ptr<ImageBuffer> imageBuffer = ImageBuffer::create(imageRect.size());

    if (imageBuffer) {
        GraphicsContext* graphicsContext = imageBuffer->context();
        graphicsContext->drawImage(image, ColorSpaceDeviceRGB, IntRect(IntPoint(), imageRect.size()));

        RefPtr<Uint8ClampedArray> pixelArray = imageBuffer->getUnmultipliedImageData(IntRect(IntPoint(), imageRect.size()));
        unsigned pixelArrayLength = pixelArray->length();
        unsigned pixelArrayOffset = 3; // Each pixel is four bytes: RGBA.
        uint8_t alphaPixelThreshold = threshold * 255;

        int minBufferY = std::max(0, marginRect.y() - imageRect.y());
        int maxBufferY = std::min(imageRect.height(), marginRect.maxY() - imageRect.y());

        if (static_cast<unsigned>(imageRect.width() * imageRect.height() * 4) == pixelArrayLength) {
            for (int y = minBufferY; y < maxBufferY; ++y) {
                int startX = -1;
                for (int x = 0; x < imageRect.width(); ++x, pixelArrayOffset += 4) {
                    uint8_t alpha = pixelArray->item(pixelArrayOffset);
                    bool alphaAboveThreshold = alpha > alphaPixelThreshold;
                    if (startX == -1 && alphaAboveThreshold) {
                        startX = x;
                    } else if (startX != -1 && (!alphaAboveThreshold || x == imageRect.width() - 1)) {
                        // We're creating "end-point exclusive" intervals here. The value of an interval's x1 is
                        // the first index of an above-threshold pixel for y, and the value of x2 is 1+ the index
                        // of the last above-threshold pixel.
                        int endX = alphaAboveThreshold ? x + 1 : x;
                        intervals->intervalAt(y + imageRect.y()).unite(IntShapeInterval(startX + imageRect.x(), endX + imageRect.x()));
                        startX = -1;
                    }
                }
            }
        }
    }

    auto rasterShape = std::make_unique<RasterShape>(WTF::move(intervals), marginRect.size());
    rasterShape->m_writingMode = writingMode;
    rasterShape->m_margin = margin;
    return WTF::move(rasterShape);
}
Beispiel #5
0
IntShapeInterval MarginIntervalGenerator::intervalAt(int y) const
{
    unsigned xInterceptsIndex = abs(y - m_y);
    int dx = (xInterceptsIndex >= m_xIntercepts.size()) ? 0 : m_xIntercepts[xInterceptsIndex];
    return IntShapeInterval(m_x1 - dx, m_x2 + dx);
}
void RasterShapeIntervals::appendInterval(int y, int x1, int x2)
{
    ASSERT(x2 > x1 && (intervalsAt(y).isEmpty() || x1 > intervalsAt(y).last().x2()));
    m_bounds.unite(IntRect(x1, y, x2 - x1, 1));
    intervalsAt(y).append(IntShapeInterval(x1, x2));
}