diff options
author | Ben Murdoch <benm@google.com> | 2015-01-16 13:22:33 +0000 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2015-01-16 13:22:33 +0000 |
commit | 2e473b9e39cddff89bc3b5dbc4b62c6443d140e0 (patch) | |
tree | bf39d3b47a73b8efb4c319ed60a1bef3d6977ccd | |
parent | 097478c1a38c1b7c44825045bf02f635e0948918 (diff) | |
download | WebKit-2e473b9e39cddff89bc3b5dbc4b62c6443d140e0.tar.gz |
Merge from Chromium at DEPS revision 40.0.2214.87
This commit was generated by merge_to_master.py.
Change-Id: I6a8b2e88ece9403ee841196f2f7fd91017710005
22 files changed, 150 insertions, 77 deletions
diff --git a/Source/core/css/html.css b/Source/core/css/html.css index 00df89252..05c18bdbd 100644 --- a/Source/core/css/html.css +++ b/Source/core/css/html.css @@ -397,6 +397,7 @@ input, textarea, keygen, select, button, meter, progress { input, textarea, keygen, select, button { margin: 0__qem; font: -webkit-small-control; + text-rendering: auto; /* FIXME: Remove when tabs work with optimizeLegibility. */ color: initial; letter-spacing: normal; word-spacing: normal; diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp index 07c3cab27..eaf16ebae 100644 --- a/Source/core/dom/Element.cpp +++ b/Source/core/dom/Element.cpp @@ -3277,12 +3277,8 @@ v8::Handle<v8::Object> Element::wrapCustomElement(v8::Handle<v8::Object> creatio return v8::Handle<v8::Object>(); V8PerContextData* perContextData = V8PerContextData::from(context); - if (!perContextData) - return wrapper; - - CustomElementBinding* binding = perContextData->customElementBinding(customElementDefinition()); - - wrapper->SetPrototype(binding->prototype()); + if (perContextData) + wrapper->SetPrototype(perContextData->customElementBinding(customElementDefinition())->prototype()); return V8DOMWrapper::associateObjectWithWrapper(isolate, this, wrapperType, wrapper); } diff --git a/Source/core/events/KeyboardEvent.cpp b/Source/core/events/KeyboardEvent.cpp index 99be09ca9..e0d77f6ef 100644 --- a/Source/core/events/KeyboardEvent.cpp +++ b/Source/core/events/KeyboardEvent.cpp @@ -172,6 +172,14 @@ int KeyboardEvent::keyCode() const // We match IE. if (!m_keyEvent) return 0; + +#if OS(ANDROID) + // FIXME: Check to see if this applies to other OS. + // If the key event belongs to IME composition then propagate to JS. + if (m_keyEvent->nativeVirtualKeyCode() == 0xE5) // VKEY_PROCESSKEY + return m_keyEvent->nativeVirtualKeyCode(); +#endif + if (type() == EventTypeNames::keydown || type() == EventTypeNames::keyup) return windowsVirtualKeyCodeWithoutLocation(m_keyEvent->windowsVirtualKeyCode()); diff --git a/Source/core/rendering/RenderBlock.cpp b/Source/core/rendering/RenderBlock.cpp index 8fbdcc841..2e101f13e 100644 --- a/Source/core/rendering/RenderBlock.cpp +++ b/Source/core/rendering/RenderBlock.cpp @@ -4345,6 +4345,26 @@ bool RenderBlock::recalcOverflowAfterStyleChange() return !hasOverflowClip(); } +// Called when a positioned object moves but doesn't necessarily change size. A simplified layout is attempted +// that just updates the object's position. If the size does change, the object remains dirty. +bool RenderBlock::tryLayoutDoingPositionedMovementOnly() +{ + LayoutUnit oldWidth = logicalWidth(); + LogicalExtentComputedValues computedValues; + logicalExtentAfterUpdatingLogicalWidth(logicalTop(), computedValues); + // If we shrink to fit our width may have changed, so we still need full layout. + if (oldWidth != computedValues.m_extent) + return false; + setLogicalWidth(computedValues.m_extent); + setLogicalLeft(computedValues.m_position); + setMarginStart(computedValues.m_margins.m_start); + setMarginEnd(computedValues.m_margins.m_end); + + LayoutUnit oldHeight = logicalHeight(); + updateLogicalHeight(); + return !hasPercentHeightDescendants() || oldHeight == logicalHeight(); +} + #if ENABLE(ASSERT) void RenderBlock::checkPositionedObjectsNeedLayout() { diff --git a/Source/core/rendering/RenderBlock.h b/Source/core/rendering/RenderBlock.h index d4e3bdbdd..c5aef0eaa 100644 --- a/Source/core/rendering/RenderBlock.h +++ b/Source/core/rendering/RenderBlock.h @@ -369,7 +369,8 @@ private: Node* nodeForHitTest() const; -private: + bool tryLayoutDoingPositionedMovementOnly(); + virtual bool avoidsFloats() const override { return true; } bool hitTestColumns(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction); diff --git a/Source/core/rendering/RenderBlockFlow.cpp b/Source/core/rendering/RenderBlockFlow.cpp index 13bfdc885..a22f5c313 100644 --- a/Source/core/rendering/RenderBlockFlow.cpp +++ b/Source/core/rendering/RenderBlockFlow.cpp @@ -1887,8 +1887,9 @@ LayoutUnit RenderBlockFlow::getClearDelta(RenderBox* child, LayoutUnit logicalTo LayoutRect borderBox = child->borderBoxRect(); LayoutUnit childLogicalWidthAtOldLogicalTopOffset = isHorizontalWritingMode() ? borderBox.width() : borderBox.height(); - borderBox = child->borderBoxAfterUpdatingLogicalWidth(newLogicalTop); - LayoutUnit childLogicalWidthAtNewLogicalTopOffset = isHorizontalWritingMode() ? borderBox.width() : borderBox.height(); + LogicalExtentComputedValues computedValues; + child->logicalExtentAfterUpdatingLogicalWidth(newLogicalTop, computedValues); + LayoutUnit childLogicalWidthAtNewLogicalTopOffset = computedValues.m_extent; if (childLogicalWidthAtNewLogicalTopOffset <= availableLogicalWidthAtNewLogicalTopOffset) { // Even though we may not be moving, if the logical width did shrink because of the presence of new floats, then diff --git a/Source/core/rendering/RenderBlockLineLayout.cpp b/Source/core/rendering/RenderBlockLineLayout.cpp index 93dd3c5c9..91db4b5c2 100644 --- a/Source/core/rendering/RenderBlockLineLayout.cpp +++ b/Source/core/rendering/RenderBlockLineLayout.cpp @@ -1164,17 +1164,28 @@ static LayoutUnit getBorderPaddingMargin(RenderBoxModelObject* child, bool endOf child->borderStart(); } -static inline void stripTrailingSpace(float& inlineMax, float& inlineMin, RenderObject* trailingSpaceChild) +static inline void stripTrailingSpace(float& inlineMax, float& inlineMin, + RenderObject* trailingSpaceChild) { if (trailingSpaceChild && trailingSpaceChild->isText()) { - // Collapse away the trailing space at the end of a block. + // Collapse away the trailing space at the end of a block by finding + // the first white-space character and subtracting its width. Subsequent + // white-space characters have been collapsed into the first one (which + // can be either a space or a tab character). RenderText* text = toRenderText(trailingSpaceChild); - bool useComplexCodePath = !text->canUseSimpleFontCodePath(); - const UChar space = ' '; - const Font& font = text->style()->font(); // FIXME: This ignores first-line. - TextRun run = constructTextRun(text, font, &space, 1, text->style(), LTR); - if (useComplexCodePath) - run.setUseComplexCodePath(true); + UChar trailingWhitespaceChar = ' '; + for (unsigned i = text->textLength(); i > 0; i--) { + UChar c = text->characterAt(i - 1); + if (!Character::treatAsSpace(c)) + break; + trailingWhitespaceChar = c; + } + + // FIXME: This ignores first-line. + const Font& font = text->style()->font(); + TextRun run = constructTextRun(text, font, &trailingWhitespaceChar, 1, + text->style(), text->style()->direction()); + run.setUseComplexCodePath(!text->canUseSimpleFontCodePath()); float spaceWidth = font.width(run); inlineMax -= spaceWidth + font.fontDescription().wordSpacing(); if (inlineMin > inlineMax) diff --git a/Source/core/rendering/RenderBox.cpp b/Source/core/rendering/RenderBox.cpp index e5f766df3..3dbd51f14 100644 --- a/Source/core/rendering/RenderBox.cpp +++ b/Source/core/rendering/RenderBox.cpp @@ -2456,16 +2456,9 @@ bool RenderBox::logicalHeightComputesAsNone(SizeType sizeType) const if (logicalHeight == initialLogicalHeight) return true; - if (!logicalHeight.isPercent() || isOutOfFlowPositioned()) - return false; - - // Anonymous block boxes are ignored when resolving percentage values that would refer to it: - // the closest non-anonymous ancestor box is used instead. - RenderBlock* containingBlock = this->containingBlock(); - while (containingBlock->isAnonymous()) - containingBlock = containingBlock->containingBlock(); - - return containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight(); + if (RenderBlock* cb = containingBlockForAutoHeightDetection(logicalHeight)) + return cb->hasAutoHeightOrContainingBlockWithAutoHeight(); + return false; } LayoutUnit RenderBox::computeReplacedLogicalHeightRespectingMinMaxHeight(LayoutUnit logicalHeight) const @@ -4448,24 +4441,28 @@ LayoutSize RenderBox::computePreviousBorderBoxSize(const LayoutSize& previousBou return previousBoundsSize; } -LayoutRect RenderBox::borderBoxAfterUpdatingLogicalWidth(const LayoutUnit& newLogicalTop) +void RenderBox::logicalExtentAfterUpdatingLogicalWidth(const LayoutUnit& newLogicalTop, RenderBox::LogicalExtentComputedValues& computedValues) { // FIXME: None of this is right for perpendicular writing-mode children. LayoutUnit oldLogicalWidth = logicalWidth(); + LayoutUnit oldLogicalLeft = logicalLeft(); LayoutUnit oldMarginLeft = marginLeft(); LayoutUnit oldMarginRight = marginRight(); LayoutUnit oldLogicalTop = logicalTop(); setLogicalTop(newLogicalTop); updateLogicalWidth(); - LayoutRect borderBox = borderBoxRect(); + + computedValues.m_extent = logicalWidth(); + computedValues.m_position = logicalLeft(); + computedValues.m_margins.m_start = marginStart(); + computedValues.m_margins.m_end = marginEnd(); setLogicalTop(oldLogicalTop); setLogicalWidth(oldLogicalWidth); + setLogicalLeft(oldLogicalLeft); setMarginLeft(oldMarginLeft); setMarginRight(oldMarginRight); - - return borderBox; } } // namespace blink diff --git a/Source/core/rendering/RenderBox.h b/Source/core/rendering/RenderBox.h index f383ed5c4..5ca9d9277 100644 --- a/Source/core/rendering/RenderBox.h +++ b/Source/core/rendering/RenderBox.h @@ -494,22 +494,7 @@ public: virtual void paintClippingMask(PaintInfo&, const LayoutPoint&); virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) override; - LayoutRect borderBoxAfterUpdatingLogicalWidth(const LayoutUnit& logicalTop); - - // Called when a positioned object moves but doesn't necessarily change size. A simplified layout is attempted - // that just updates the object's position. If the size does change, the object remains dirty. - bool tryLayoutDoingPositionedMovementOnly() - { - LayoutUnit oldWidth = width(); - LayoutUnit newWidth = borderBoxAfterUpdatingLogicalWidth(logicalTop()).width(); - // If we shrink to fit our width may have changed, so we still need full layout. - // FIXME: We check for potential change of width when deciding to set needsPositionedMovementLayout. - // So either that check or this one is unnecessary, probably the former. crbug.com/428050 - if (oldWidth != newWidth) - return false; - updateLogicalHeight(); - return true; - } + void logicalExtentAfterUpdatingLogicalWidth(const LayoutUnit& logicalTop, LogicalExtentComputedValues&); virtual PositionWithAffinity positionForPoint(const LayoutPoint&) override; diff --git a/Source/core/rendering/RenderBoxModelObject.cpp b/Source/core/rendering/RenderBoxModelObject.cpp index 69d48478f..43e3b2efb 100644 --- a/Source/core/rendering/RenderBoxModelObject.cpp +++ b/Source/core/rendering/RenderBoxModelObject.cpp @@ -155,17 +155,13 @@ static LayoutSize accumulateInFlowPositionOffsets(const RenderObject* child) return offset; } -bool RenderBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const +RenderBlock* RenderBoxModelObject::containingBlockForAutoHeightDetection(Length logicalHeight) const { - Length logicalHeightLength = style()->logicalHeight(); - if (logicalHeightLength.isAuto()) - return true; - // For percentage heights: The percentage is calculated with respect to the height of the generated box's // containing block. If the height of the containing block is not specified explicitly (i.e., it depends // on content height), and this element is not absolutely positioned, the value computes to 'auto'. - if (!logicalHeightLength.isPercent() || isOutOfFlowPositioned() || document().inQuirksMode()) - return false; + if (!logicalHeight.isPercent() || isOutOfFlowPositioned()) + return 0; // Anonymous block boxes are ignored when resolving percentage values that would refer to it: // the closest non-anonymous ancestor box is used instead. @@ -178,18 +174,32 @@ bool RenderBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const // what the CSS spec says to do with heights. Basically we // don't care if the cell specified a height or not. if (cb->isTableCell()) - return false; + return 0; // Match RenderBox::availableLogicalHeightUsing by special casing // the render view. The available height is taken from the frame. if (cb->isRenderView()) - return false; + return 0; if (cb->isOutOfFlowPositioned() && !cb->style()->logicalTop().isAuto() && !cb->style()->logicalBottom().isAuto()) + return 0; + + return cb; +} + +bool RenderBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const +{ + Length logicalHeightLength = style()->logicalHeight(); + if (logicalHeightLength.isAuto()) + return true; + + if (document().inQuirksMode()) return false; // If the height of the containing block computes to 'auto', then it hasn't been 'specified explicitly'. - return cb->hasAutoHeightOrContainingBlockWithAutoHeight(); + if (RenderBlock* cb = containingBlockForAutoHeightDetection(logicalHeightLength)) + return cb->hasAutoHeightOrContainingBlockWithAutoHeight(); + return false; } LayoutSize RenderBoxModelObject::relativePositionOffset() const diff --git a/Source/core/rendering/RenderBoxModelObject.h b/Source/core/rendering/RenderBoxModelObject.h index 40adffa5e..164c0aef8 100644 --- a/Source/core/rendering/RenderBoxModelObject.h +++ b/Source/core/rendering/RenderBoxModelObject.h @@ -179,6 +179,7 @@ protected: LayoutRect localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset); bool hasAutoHeightOrContainingBlockWithAutoHeight() const; + RenderBlock* containingBlockForAutoHeightDetection(Length logicalHeight) const; public: diff --git a/Source/core/rendering/RenderInline.cpp b/Source/core/rendering/RenderInline.cpp index d156b0b6a..b436757d8 100644 --- a/Source/core/rendering/RenderInline.cpp +++ b/Source/core/rendering/RenderInline.cpp @@ -1019,29 +1019,42 @@ LayoutRect RenderInline::linesVisualOverflowBoundingBox() const return rect; } +LayoutRect RenderInline::absoluteClippedOverflowRect() const +{ + return clippedOverflowRect(view()); +} + LayoutRect RenderInline::clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const { + // If we don't create line boxes, we don't have any invalidations to do. + if (!alwaysCreateLineBoxes()) + return LayoutRect(); + return clippedOverflowRect(paintInvalidationContainer); +} + +LayoutRect RenderInline::clippedOverflowRect(const RenderLayerModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState) const +{ if ((!firstLineBoxIncludingCulling() && !continuation()) || style()->visibility() != VISIBLE) return LayoutRect(); - LayoutRect paintInvalidationRect(linesVisualOverflowBoundingBox()); + LayoutRect overflowRect(linesVisualOverflowBoundingBox()); LayoutUnit outlineSize = style()->outlineSize(); - paintInvalidationRect.inflate(outlineSize); + overflowRect.inflate(outlineSize); - mapRectToPaintInvalidationBacking(paintInvalidationContainer, paintInvalidationRect, paintInvalidationState); + mapRectToPaintInvalidationBacking(paintInvalidationContainer, overflowRect, paintInvalidationState); if (outlineSize) { for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { if (!curr->isText()) - paintInvalidationRect.unite(curr->rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineSize)); + overflowRect.unite(curr->rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineSize)); } if (continuation() && !continuation()->isInline() && continuation()->parent()) - paintInvalidationRect.unite(continuation()->rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineSize)); + overflowRect.unite(continuation()->rectWithOutlineForPaintInvalidation(paintInvalidationContainer, outlineSize)); } - return paintInvalidationRect; + return overflowRect; } LayoutRect RenderInline::rectWithOutlineForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, LayoutUnit outlineWidth, const PaintInvalidationState* paintInvalidationState) const diff --git a/Source/core/rendering/RenderInline.h b/Source/core/rendering/RenderInline.h index c277d9e76..6c25269c2 100644 --- a/Source/core/rendering/RenderInline.h +++ b/Source/core/rendering/RenderInline.h @@ -144,10 +144,15 @@ private: virtual LayoutUnit offsetWidth() const override final { return linesBoundingBox().width(); } virtual LayoutUnit offsetHeight() const override final { return linesBoundingBox().height(); } + virtual LayoutRect absoluteClippedOverflowRect() const override; virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, const PaintInvalidationState* = 0) const override; virtual LayoutRect rectWithOutlineForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, LayoutUnit outlineWidth, const PaintInvalidationState* = 0) const override final; virtual void mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect&, const PaintInvalidationState*) const override final; + // This method differs from clippedOverflowRectForPaintInvalidation in that it includes + // the rects for culled inline boxes, which aren't necessary for paint invalidation. + LayoutRect clippedOverflowRect(const RenderLayerModelObject*, const PaintInvalidationState* = 0) const; + virtual void mapLocalToContainer(const RenderLayerModelObject* paintInvalidationContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0, const PaintInvalidationState* = 0) const override; virtual PositionWithAffinity positionForPoint(const LayoutPoint&) override final; diff --git a/Source/core/rendering/RenderObject.h b/Source/core/rendering/RenderObject.h index 618de57e7..503113dd3 100644 --- a/Source/core/rendering/RenderObject.h +++ b/Source/core/rendering/RenderObject.h @@ -864,7 +864,7 @@ public: // Returns the rect that should have paint invalidated whenever this object changes. The rect is in the view's // coordinate space. This method deals with outlines and overflow. - LayoutRect absoluteClippedOverflowRect() const; + virtual LayoutRect absoluteClippedOverflowRect() const; IntRect pixelSnappedAbsoluteClippedOverflowRect() const; virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, const PaintInvalidationState* = 0) const; virtual LayoutRect rectWithOutlineForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, LayoutUnit outlineWidth, const PaintInvalidationState* = 0) const; diff --git a/Source/core/rendering/RenderView.cpp b/Source/core/rendering/RenderView.cpp index 02367e0b4..206710635 100644 --- a/Source/core/rendering/RenderView.cpp +++ b/Source/core/rendering/RenderView.cpp @@ -333,7 +333,7 @@ void RenderView::invalidateTreeIfNeeded(const PaintInvalidationState& paintInval LayoutRect dirtyRect = viewRect(); if (doingFullPaintInvalidation() && !dirtyRect.isEmpty()) { const RenderLayerModelObject* paintInvalidationContainer = &paintInvalidationState.paintInvalidationContainer(); - mapRectToPaintInvalidationBacking(paintInvalidationContainer, dirtyRect, &paintInvalidationState); + RenderLayer::mapRectToPaintInvalidationBacking(this, paintInvalidationContainer, dirtyRect, &paintInvalidationState); invalidatePaintUsingContainer(paintInvalidationContainer, dirtyRect, PaintInvalidationFull); } RenderBlock::invalidateTreeIfNeeded(paintInvalidationState); diff --git a/Source/core/xml/XSLImportRule.cpp b/Source/core/xml/XSLImportRule.cpp index b391b30ee..66e6178a3 100644 --- a/Source/core/xml/XSLImportRule.cpp +++ b/Source/core/xml/XSLImportRule.cpp @@ -106,7 +106,7 @@ void XSLImportRule::loadSheet() ASSERT(!m_styleSheet); if (SharedBuffer* data = resource->resourceBuffer()) - setXSLStyleSheet(absHref, parentSheet->baseURL(), UTF8Encoding().decode(data->data(), data->size())); + setXSLStyleSheet(absHref, resource->response().url(), UTF8Encoding().decode(data->data(), data->size())); } void XSLImportRule::trace(Visitor* visitor) diff --git a/Source/devtools/front_end/timeline/TracingTimelineUIUtils.js b/Source/devtools/front_end/timeline/TracingTimelineUIUtils.js index 32736d3b3..1f5023302 100644 --- a/Source/devtools/front_end/timeline/TracingTimelineUIUtils.js +++ b/Source/devtools/front_end/timeline/TracingTimelineUIUtils.js @@ -169,7 +169,7 @@ WebInspector.TracingTimelineUIUtils.prototype = { */ hiddenEmptyRecordsFilter: function() { - var hiddenEmptyRecords = [WebInspector.TimelineModel.RecordType.EventDispatch]; + var hiddenEmptyRecords = [WebInspector.TimelineModel.RecordType.EventDispatch, WebInspector.TimelineModel.RecordType.UpdateCounters]; return new WebInspector.TimelineRecordHiddenEmptyTypeFilter(hiddenEmptyRecords); }, @@ -247,6 +247,7 @@ WebInspector.TracingTimelineUIUtils._initEventStyles = function() eventStyles[recordTypes.EmbedderCallback] = new WebInspector.TimelineRecordStyle(WebInspector.UIString("Embedder Callback"), categories["scripting"]); eventStyles[recordTypes.DecodeImage] = new WebInspector.TimelineRecordStyle(WebInspector.UIString("Image Decode"), categories["painting"]); eventStyles[recordTypes.ResizeImage] = new WebInspector.TimelineRecordStyle(WebInspector.UIString("Image Resize"), categories["painting"]); + eventStyles[recordTypes.UpdateCounters] = new WebInspector.TimelineRecordStyle(WebInspector.UIString("UpdateCounters"), categories["other"]); WebInspector.TracingTimelineUIUtils._eventStylesMap = eventStyles; return eventStyles; } diff --git a/Source/modules/webaudio/AudioBufferSourceNode.cpp b/Source/modules/webaudio/AudioBufferSourceNode.cpp index 05738f9d7..3c57b56dc 100644 --- a/Source/modules/webaudio/AudioBufferSourceNode.cpp +++ b/Source/modules/webaudio/AudioBufferSourceNode.cpp @@ -233,7 +233,7 @@ bool AudioBufferSourceNode::renderFromBuffer(AudioBus* bus, unsigned destination // If we're looping and the offset (virtualReadIndex) is past the end of the loop, wrap back to // the beginning of the loop. For other cases, nothing needs to be done. if (loop() && m_virtualReadIndex >= virtualEndFrame) - m_virtualReadIndex = m_loopStart * buffer()->sampleRate(); + m_virtualReadIndex = (m_loopStart < 0) ? 0 : (m_loopStart * buffer()->sampleRate()); double pitchRate = totalPitchRate(); @@ -250,6 +250,10 @@ bool AudioBufferSourceNode::renderFromBuffer(AudioBus* bus, unsigned destination const float** sourceChannels = m_sourceChannels.get(); float** destinationChannels = m_destinationChannels.get(); + ASSERT(virtualReadIndex >= 0); + ASSERT(virtualDeltaFrames >= 0); + ASSERT(virtualEndFrame >= 0); + // Optimize for the very common case of playing back with pitchRate == 1. // We can avoid the linear interpolation. if (pitchRate == 1 && virtualReadIndex == floor(virtualReadIndex) diff --git a/Source/modules/webaudio/AudioContext.cpp b/Source/modules/webaudio/AudioContext.cpp index ded030c4b..878b124bc 100644 --- a/Source/modules/webaudio/AudioContext.cpp +++ b/Source/modules/webaudio/AudioContext.cpp @@ -533,6 +533,11 @@ PeriodicWave* AudioContext::createPeriodicWave(DOMFloat32Array* real, DOMFloat32 return PeriodicWave::create(sampleRate(), real->view(), imag->view()); } +void AudioContext::notifyNodeStartedProcessing(AudioNode* node) +{ + refNode(node); +} + void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) { ASSERT(isAudioThread()); diff --git a/Source/modules/webaudio/AudioContext.h b/Source/modules/webaudio/AudioContext.h index f84804be5..8243f054c 100644 --- a/Source/modules/webaudio/AudioContext.h +++ b/Source/modules/webaudio/AudioContext.h @@ -129,7 +129,11 @@ public: OscillatorNode* createOscillator(); PeriodicWave* createPeriodicWave(DOMFloat32Array* real, DOMFloat32Array* imag, ExceptionState&); - // When a source node has no more processing to do (has finished playing), then it tells the context to dereference it. + // When a source node has started processing and needs to be protected, + // this method tells the context to protect the node. + void notifyNodeStartedProcessing(AudioNode*); + // When a source node has no more processing to do (has finished playing), + // this method tells the context to dereference the node. void notifyNodeFinishedProcessing(AudioNode*); // Called at the start of each render quantum. diff --git a/Source/modules/webaudio/OfflineAudioDestinationNode.cpp b/Source/modules/webaudio/OfflineAudioDestinationNode.cpp index 11da9795e..66b60a9a7 100644 --- a/Source/modules/webaudio/OfflineAudioDestinationNode.cpp +++ b/Source/modules/webaudio/OfflineAudioDestinationNode.cpp @@ -81,12 +81,13 @@ void OfflineAudioDestinationNode::uninitialize() void OfflineAudioDestinationNode::startRendering() { ASSERT(isMainThread()); - ASSERT(m_renderTarget.get()); - if (!m_renderTarget.get()) + ASSERT(m_renderTarget); + if (!m_renderTarget) return; if (!m_startedRendering) { m_startedRendering = true; + context()->notifyNodeStartedProcessing(this); m_renderThread = adoptPtr(blink::Platform::current()->createThread("Offline Audio Renderer")); m_renderThread->postTask(new Task(bind(&OfflineAudioDestinationNode::offlineRender, this))); } @@ -94,9 +95,16 @@ void OfflineAudioDestinationNode::startRendering() void OfflineAudioDestinationNode::offlineRender() { + offlineRenderInternal(); + context()->notifyNodeFinishedProcessing(this); + context()->handlePostRenderTasks(); +} + +void OfflineAudioDestinationNode::offlineRenderInternal() +{ ASSERT(!isMainThread()); - ASSERT(m_renderBus.get()); - if (!m_renderBus.get()) + ASSERT(m_renderBus); + if (!m_renderBus) return; bool isAudioContextInitialized = context()->isInitialized(); diff --git a/Source/modules/webaudio/OfflineAudioDestinationNode.h b/Source/modules/webaudio/OfflineAudioDestinationNode.h index 05dba11c9..6e267f2d6 100644 --- a/Source/modules/webaudio/OfflineAudioDestinationNode.h +++ b/Source/modules/webaudio/OfflineAudioDestinationNode.h @@ -60,6 +60,12 @@ public: private: OfflineAudioDestinationNode(AudioContext*, AudioBuffer* renderTarget); + void offlineRender(); + void offlineRenderInternal(); + + // For completion callback on main thread. + void notifyComplete(); + // This AudioNode renders into this AudioBuffer. Member<AudioBuffer> m_renderTarget; // Temporary AudioBus for each render quantum. @@ -68,10 +74,6 @@ private: // Rendering thread. OwnPtr<WebThread> m_renderThread; bool m_startedRendering; - void offlineRender(); - - // For completion callback on main thread. - void notifyComplete(); }; } // namespace blink |