Exemple #1
0
bool EditorObject::build(ResourceFile & resources)
{
    // create the container to hold the graphic ids
    delete m_compiledGraphics;
    m_compiledGraphics = new Array3<QString>(tileCountX(), tileCountY(), layerCount());

    Array3< QList<QImage> * > animations(tileCountX(), tileCountY(), layerCount());
    // initialize animation list
    for (int z=0; z<layerCount(); z++) {
        for (int y=0; y<tileCountY(); ++y) {
            for (int x=0; x<tileCountX(); ++x) {
                animations.set(x,y,z,new QList<QImage>());
            }
        }
    }

    // find out the greatest frames per second
    int fps = 0;
    for (int layerIndex=0; layerIndex<m_graphics.size(); ++layerIndex) {
        QList<ObjectGraphic *> * layer = m_graphics.at(layerIndex);
        for (int i=0; i<layer->size(); ++i) {
            ObjectGraphic * graphicInstance = layer->at(i);
            if (graphicInstance->graphic->framesPerSecond() > fps)
                fps = graphicInstance->graphic->framesPerSecond();
        }
    }

    // for each animation frame
    int frame = 0;
    while (true) {
        if (frame > 0) {
            // check if the animation has looped yet.
            bool firstFrame = true;
            for (int layerIndex=0; layerIndex<m_graphics.size(); ++layerIndex) {
                QList<ObjectGraphic *> * layer = m_graphics.at(layerIndex);
                for (int i=0; i<layer->size(); ++i) {
                    ObjectGraphic * graphicInstance = layer->at(i);
                    if ((frame+1) % graphicInstance->graphic->frameCount() != 0) {
                        firstFrame = false;
                        break;
                    }
                }
                if (! firstFrame)
                    break;
            }

            // this means all animations have looped and we're done
            // collecting frames
            if (firstFrame)
                break;
        }

        for (int z=0; z<layerCount(); ++z) {
            // render the layer once into a QImage
            QImage layerImage(tileCountX() * Tile::sizeInt, tileCountY() * Tile::sizeInt, QImage::Format_ARGB32);
            layerImage.fill(Qt::transparent);
            QPainter layerPainter(&layerImage);
            render(layerPainter, z, frame, fps);

            // for each tile, draw that tile into a different QImage
            for (int y=0; y<tileCountY(); ++y) {
                for (int x=0; x<tileCountX(); ++x) {
                    QImage tileImage(Tile::sizeInt, Tile::sizeInt, QImage::Format_ARGB32);
                    tileImage.fill(Qt::transparent);
                    QPainter p(&tileImage);
                    p.drawImage(0, 0, layerImage, x * Tile::sizeInt, y * Tile::sizeInt, Tile::sizeInt, Tile::sizeInt);

                    QList<QImage> * frames = animations.get(x,y,z);
                    frames->append(tileImage);
                }
            }
        }

        ++frame;
    }
    int frameCount = frame;

    // create a spritesheet for each tile
    for (int z=0; z<layerCount(); ++z) {
        for (int y=0; y<tileCountY(); ++y) {
            for (int x=0; x<tileCountX(); ++x ) {
                // create the spritesheet
                QList<QImage> * frames = animations.get(x,y,z);
                QImage spritesheet(Tile::sizeInt * frameCount, Tile::sizeInt, QImage::Format_ARGB32);
                spritesheet.fill(Qt::transparent);
                QPainter p(&spritesheet);
                for (int i=0; i<frameCount; ++i)
                    p.drawImage(i * Tile::sizeInt, 0, frames->at(i % frames->size()));

                // create the binary data
                QByteArray tile;
                // magic character
                tile.append("G");

                int codeVersion = 1;
                tile.append((char *) &codeVersion, 4);

                int graphicType = Graphic::gtAnimation;
                tile.append((char *) &graphicType, 4);

                int storageType = Graphic::stPNG;
                tile.append((char *) &storageType, 4);

                // color key: hardcode magenta
                char red = 255;
                char green = 0;
                char blue = 255;
                tile.append(&red, 1);
                tile.append(&green, 1);
                tile.append(&blue, 1);

                tile.append((char *) &frameCount, 4);
                tile.append((char *) &fps, 4);

                // frame width and height
                tile.append((char *) &Tile::sizeInt, 4);
                tile.append((char *) &Tile::sizeInt, 4);

                // save spritesheet into memory
                QByteArray imageData;
                QBuffer buffer(&imageData);
                buffer.open(QIODevice::WriteOnly);
                spritesheet.save(&buffer, "PNG");

                int imageDataSize = imageData.size();
                tile.append((char *) &imageDataSize, 4);

                tile.append(imageData);

                // come up with a name
                QString dash = "-";
                QString ext = ".ani";
                QString graphicName = m_name + dash + QString::number(x) +
                    dash + QString::number(y) + dash + QString::number(z) + ext;

                resources.updateResource(graphicName.toStdString(), tile.constData(), tile.size());
                m_compiledGraphics->set(x,y,z,graphicName);
            }
        }
    }

    // cleanup animation list
    for (int z=0; z<layerCount(); z++) {
        for (int y=0; y<tileCountY(); ++y) {
            for (int x=0; x<tileCountX(); ++x) {
                delete animations.get(x,y,z);
            }
        }
    }

    return true;
}
void FramePainter::paintContents(GraphicsContext& context, const GlobalPaintFlags globalPaintFlags, const IntRect& rect)
{
    Document* document = frameView().frame().document();

#ifndef NDEBUG
    bool fillWithRed;
    if (document->printing())
        fillWithRed = false; // Printing, don't fill with red (can't remember why).
    else if (frameView().frame().owner())
        fillWithRed = false; // Subframe, don't fill with red.
    else if (frameView().isTransparent())
        fillWithRed = false; // Transparent, don't fill with red.
    else if (globalPaintFlags & GlobalPaintSelectionOnly)
        fillWithRed = false; // Selections are transparent, don't fill with red.
    else
        fillWithRed = true;

    if (fillWithRed && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, *frameView().layoutView(), DisplayItem::DebugRedFill, LayoutPoint())) {
        IntRect contentRect(IntPoint(), frameView().contentsSize());
        LayoutObjectDrawingRecorder drawingRecorder(context, *frameView().layoutView(), DisplayItem::DebugRedFill, contentRect, LayoutPoint());
    }
#endif

    LayoutView* layoutView = frameView().layoutView();
    if (!layoutView) {
        WTF_LOG_ERROR("called FramePainter::paint with nil layoutObject");
        return;
    }

    if (!frameView().shouldThrottleRendering()) {
        RELEASE_ASSERT(!frameView().needsLayout());
        ASSERT(document->lifecycle().state() >= DocumentLifecycle::CompositingClean);
    }

    TRACE_EVENT1("devtools.timeline", "Paint", "data", InspectorPaintEvent::data(layoutView, LayoutRect(rect), 0));

    bool isTopLevelPainter = !s_inPaintContents;
    s_inPaintContents = true;

    FontCachePurgePreventer fontCachePurgePreventer;

    // TODO(jchaffraix): GlobalPaintFlags should be const during a paint
    // phase. Thus we should set this flag upfront (crbug.com/510280).
    GlobalPaintFlags localPaintFlags = globalPaintFlags;
    if (document->printing())
        localPaintFlags |= GlobalPaintFlattenCompositingLayers | GlobalPaintPrinting;

    PaintLayer* rootLayer = layoutView->layer();

#if ENABLE(ASSERT)
    if (!frameView().shouldThrottleRendering())
        layoutView->assertSubtreeIsLaidOut();
    LayoutObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(*rootLayer->layoutObject());
#endif

    PaintLayerPainter layerPainter(*rootLayer);

    float deviceScaleFactor = blink::deviceScaleFactor(rootLayer->layoutObject()->frame());
    context.setDeviceScaleFactor(deviceScaleFactor);

    layerPainter.paint(context, LayoutRect(rect), localPaintFlags);

    if (rootLayer->containsDirtyOverlayScrollbars())
        layerPainter.paintOverlayScrollbars(context, LayoutRect(rect), localPaintFlags);

    // Regions may have changed as a result of the visibility/z-index of element changing.
    if (document->annotatedRegionsDirty())
        frameView().updateDocumentAnnotatedRegions();

    if (isTopLevelPainter) {
        // Everything that happens after paintContents completions is considered
        // to be part of the next frame.
        memoryCache()->updateFramePaintTimestamp();
        s_inPaintContents = false;
    }

    InspectorInstrumentation::didPaint(layoutView, 0, context, LayoutRect(rect));
}
void FramePainter::paintContents(GraphicsContext* context, const IntRect& rect)
{
    Document* document = m_frameView.frame().document();

#ifndef NDEBUG
    bool fillWithRed;
    if (document->printing())
        fillWithRed = false; // Printing, don't fill with red (can't remember why).
    else if (m_frameView.frame().owner())
        fillWithRed = false; // Subframe, don't fill with red.
    else if (m_frameView.isTransparent())
        fillWithRed = false; // Transparent, don't fill with red.
    else if (m_frameView.paintBehavior() & PaintBehaviorSelectionOnly)
        fillWithRed = false; // Selections are transparent, don't fill with red.
    else if (m_frameView.nodeToDraw())
        fillWithRed = false; // Element images are transparent, don't fill with red.
    else
        fillWithRed = true;

    if (fillWithRed) {
        IntRect contentRect(IntPoint(), m_frameView.contentsSize());
        DrawingRecorder drawingRecorder(*context, *m_frameView.layoutView(), DisplayItem::DebugRedFill, contentRect);
        if (!drawingRecorder.canUseCachedDrawing())
            context->fillRect(contentRect, Color(0xFF, 0, 0));
    }
#endif

    LayoutView* layoutView = m_frameView.layoutView();
    if (!layoutView) {
        WTF_LOG_ERROR("called FramePainter::paint with nil renderer");
        return;
    }

    RELEASE_ASSERT(!m_frameView.needsLayout());
    ASSERT(document->lifecycle().state() >= DocumentLifecycle::CompositingClean);

    TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Paint", "data", InspectorPaintEvent::data(layoutView, LayoutRect(rect), 0));

    bool isTopLevelPainter = !s_inPaintContents;
    s_inPaintContents = true;

    FontCachePurgePreventer fontCachePurgePreventer;

    PaintBehavior oldPaintBehavior = m_frameView.paintBehavior();

    if (FrameView* parentView = m_frameView.parentFrameView()) {
        if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
            m_frameView.setPaintBehavior(m_frameView.paintBehavior() | PaintBehaviorFlattenCompositingLayers);
    }

    if (m_frameView.paintBehavior() == PaintBehaviorNormal)
        document->markers().invalidateRenderedRectsForMarkersInRect(LayoutRect(rect));

    if (document->printing())
        m_frameView.setPaintBehavior(m_frameView.paintBehavior() | PaintBehaviorFlattenCompositingLayers);

    ASSERT(!m_frameView.isPainting());
    m_frameView.setIsPainting(true);

    // m_frameView.nodeToDraw() is used to draw only one element (and its descendants)
    LayoutObject* renderer = m_frameView.nodeToDraw() ? m_frameView.nodeToDraw()->layoutObject() : 0;
    DeprecatedPaintLayer* rootLayer = layoutView->layer();

#if ENABLE(ASSERT)
    layoutView->assertSubtreeIsLaidOut();
    LayoutObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(*rootLayer->layoutObject());
#endif

    DeprecatedPaintLayerPainter layerPainter(*rootLayer);

    float deviceScaleFactor = blink::deviceScaleFactor(rootLayer->layoutObject()->frame());
    context->setDeviceScaleFactor(deviceScaleFactor);

    layerPainter.paint(context, LayoutRect(rect), m_frameView.paintBehavior(), renderer);

    if (rootLayer->containsDirtyOverlayScrollbars())
        layerPainter.paintOverlayScrollbars(context, LayoutRect(rect), m_frameView.paintBehavior(), renderer);

    m_frameView.setIsPainting(false);

    m_frameView.setPaintBehavior(oldPaintBehavior);
    m_frameView.setLastPaintTime(currentTime());

    // Regions may have changed as a result of the visibility/z-index of element changing.
    if (document->annotatedRegionsDirty())
        m_frameView.updateAnnotatedRegions();

    if (isTopLevelPainter) {
        // Everything that happens after paintContents completions is considered
        // to be part of the next frame.
        memoryCache()->updateFramePaintTimestamp();
        s_inPaintContents = false;
    }

    InspectorInstrumentation::didPaint(layoutView, 0, context, LayoutRect(rect));
}