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)); }