diff options
Diffstat (limited to 'WebCore')
307 files changed, 8567 insertions, 3161 deletions
diff --git a/WebCore/Android.mk b/WebCore/Android.mk index 9af1bae..f6576ae 100644 --- a/WebCore/Android.mk +++ b/WebCore/Android.mk @@ -646,6 +646,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ rendering/RenderSVGInline.cpp \ rendering/RenderSVGInlineText.cpp \ rendering/RenderSVGModelObject.cpp \ + rendering/RenderSVGResourceMasker.cpp \ rendering/RenderSVGRoot.cpp \ rendering/RenderSVGShadowTreeRootContainer.cpp \ rendering/RenderSVGTSpan.cpp \ @@ -901,7 +902,6 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ svg/graphics/SVGResourceClipper.cpp \ svg/graphics/SVGResourceFilter.cpp \ svg/graphics/SVGResourceMarker.cpp \ - svg/graphics/SVGResourceMasker.cpp \ \ svg/graphics/filters/SVGFEConvolveMatrix.cpp \ svg/graphics/filters/SVGFEDiffuseLighting.cpp \ diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog index 5a13318..01d1a54 100644 --- a/WebCore/ChangeLog +++ b/WebCore/ChangeLog @@ -1,3 +1,2863 @@ +2010-02-19 Dirk Schulze <krit@webkit.org> + + Reviewed by Nikolas Zimmermann. + + RenderSVGResourceMasker causes an Assert on Wind builds during DRT + https://bugs.webkit.org/show_bug.cgi?id=35182 + + We remove the Assert for now and return earlier, if the HashMap of the Masker + does not contain the RenderObject. The RenderObject is an identifiert to get + a already calculated mask. + A race condition during parsing can cause the invalidation call, before the mask + got calculated (only during DRT on Win build bots). + The real bug will be fixed with: https://bugs.webkit.org/show_bug.cgi?id=35181 + + * rendering/RenderSVGResourceMasker.cpp: + (WebCore::RenderSVGResourceMasker::invalidateClient): + +2010-02-18 Peter Kasting <pkasting@google.com> + + Reviewed by Darin Fisher. + + Make Pasteboard::writeImage() safe against NULL cachedImages, and clean + up some code. + https://bugs.webkit.org/show_bug.cgi?id=35136 + + * loader/ImageLoader.cpp: + (WebCore::ImageLoader::updateRenderer): Shorten some code. + * page/DragController.cpp: + (WebCore::getImage): Shorten some code. + * platform/chromium/PasteboardChromium.cpp: + (WebCore::Pasteboard::writeImage): NULL-check cachedImage(). + * platform/gtk/PasteboardGtk.cpp: + (WebCore::Pasteboard::writeImage): NULL-check cachedImage(). + * platform/mac/PasteboardMac.mm: + (WebCore::Pasteboard::writeImage): NULL-check cachedImage(). + * platform/qt/PasteboardQt.cpp: + (WebCore::Pasteboard::writeImage): NULL-check cachedImage(). + * platform/win/PasteboardWin.cpp: + (WebCore::Pasteboard::writeImage): NULL-check cachedImage(). + +2010-02-19 Kenneth Rohde Christiansen <kenneth@webkit.org> + + Rubberstamped by Noam Rosenthal, who wrote the original code. + + Make mouse wheel scrolling work when using the GraphicsLayer. + + * platform/graphics/qt/GraphicsLayerQt.cpp: + (WebCore::GraphicsLayerQtImpl::GraphicsLayerQtImpl): + +2010-02-19 Nate Chapin <japhet@chromium.org> + + Reviewed by Dimitri Glazkov. + + [V8] Fix Worker crash regression in r54972 + + https://bugs.webkit.org/show_bug.cgi?id=35166 + + * bindings/v8/V8DOMWrapper.cpp: + (WebCore::V8DOMWrapper::instantiateV8Object): Properly unwrap global objects when inside a WorkerContext. + +2010-02-19 Steve Block <steveblock@google.com> + + Not reviewed. Reverts r55020 which causes crashes in Chromium LayoutTests + + * bindings/generic/RuntimeEnabledFeatures.cpp: + * storage/Database.cpp: + +2010-02-19 Steve Block <steveblock@google.com> + + Reviewed by David Levin. + + Sets default values of V8 runtime enabler flags to match behavior with JSC + https://bugs.webkit.org/show_bug.cgi?id=35095 + + No new tests, modifies a Chromium feature only. + + * bindings/generic/RuntimeEnabledFeatures.cpp: Modified. Sets appcache and geolocation flag defaults to 'on' + * storage/Database.cpp: Modified. Sets database flag default to 'on'. + +2010-02-19 Alexander Pavlov <apavlov@chromium.org> + + Reviewed by Pavel Feldman. + + WebInspector: Elements panel: Correctly show empty elements' ending tags + for XML and HTML documents. + https://bugs.webkit.org/show_bug.cgi?id=26315 + + Test: inspector/elements-panel-xhtml-structure.xhtml + + * inspector/InspectorController.cpp: + (WebCore::InspectorController::populateScriptObjects): + * inspector/front-end/ElementsTreeOutline.js: + (WebInspector.ElementsTreeOutline.prototype.set rootDOMNode): + (WebInspector.ElementsTreeOutline.prototype.get isXMLMimeType): + (WebInspector.ElementsTreeOutline.prototype._contextMenuEventFired): + (WebInspector.ElementsTreeElement.prototype.onexpand): + (WebInspector.ElementsTreeElement.prototype.oncollapse): + (WebInspector.ElementsTreeElement.prototype.updateTitle.callback): + (WebInspector.ElementsTreeElement.prototype.updateTitle): + (WebInspector.ElementsTreeElement.prototype._nodeTitleInfo): + +2010-02-19 Pavel Feldman <pfeldman@chromium.org> + + Not reviewed. Chromium build fix: reverting r54997 and r54998. + + * bindings/v8/custom/V8LocationCustom.cpp: + (WebCore::V8Location::protocolAccessorSetter): + * platform/KURLGoogle.cpp: + (WebCore::KURL::setProtocol): + (WebCore::KURL::isHierarchical): + +2010-02-17 Philippe Normand <pnormand@igalia.com> + + Reviewed by Eric Seidel. + + [GTK] RTP/RTSP streams playback support + https://bugs.webkit.org/show_bug.cgi?id=33662 + + Added live pipelines support in updateStates(). + + * manual-tests/video-rtsp.html: Added. + * platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp: + (WebCore::MediaPlayerPrivate::seek): + (WebCore::MediaPlayerPrivate::updateStates): + +2010-02-18 Yaar Schnitman <yaar@chromium.org> + + Reviewed by Darin Adler. + + Normalize custom ctors for Image, Option, Audio + https://bugs.webkit.org/show_bug.cgi?id=34782 + + Test: fast/js/custom-constructors.html + + * bindings/js/JSAudioConstructor.cpp: + (WebCore::JSAudioConstructor::JSAudioConstructor): + (WebCore::constructAudio): + * bindings/js/JSImageConstructor.cpp: + (WebCore::constructImage): + * bindings/js/JSOptionConstructor.cpp: + (WebCore::constructHTMLOptionElement): + * bindings/v8/custom/V8HTMLAudioElementConstructor.cpp: + (WebCore::v8HTMLAudioElementConstructorCallback): + * bindings/v8/custom/V8HTMLImageElementConstructor.cpp: + (WebCore::v8HTMLImageElementConstructorCallback): + * bindings/v8/custom/V8HTMLOptionElementConstructor.cpp: + (WebCore::v8HTMLOptionElementConstructorCallback): + * html/HTMLAudioElement.cpp: + (WebCore::HTMLAudioElement::HTMLAudioElement): + (WebCore::HTMLAudioElement::createForJSConstructor): + * html/HTMLAudioElement.h: + * html/HTMLImageElement.cpp: + (WebCore::HTMLImageElement::createForJSConstructor): + (WebCore::HTMLImageElement::mapToEntry): + (WebCore::HTMLImageElement::createRenderer): + (WebCore::HTMLImageElement::attach): + (WebCore::HTMLImageElement::width): + (WebCore::HTMLImageElement::height): + (WebCore::HTMLImageElement::naturalHeight): + * html/HTMLImageElement.h: + * html/HTMLOptionElement.cpp: + (WebCore::HTMLOptionElement::HTMLOptionElement): + (WebCore::HTMLOptionElement::createForJSConstructor): + (WebCore::HTMLOptionElement::ownerSelectElement): + (WebCore::HTMLOptionElement::nonRendererRenderStyle): + (WebCore::HTMLOptionElement::disabled): + (WebCore::HTMLOptionElement::insertedIntoTree): + * html/HTMLOptionElement.h: + +2010-02-12 Brett Wilson <brettw@chromium.org> + + Reviewed by Adam Barth. + + Update the Google-URL version of KURL and the V8 bindings to the new + behavior of KURL.IsStandard. + + https://bugs.webkit.org/show_bug.cgi?id=34859 + + This is covered by fast/dom/Window/invalid-protocol.html + + * bindings/v8/custom/V8LocationCustom.cpp: + (WebCore::V8Location::protocolAccessorSetter): + * platform/KURLGoogle.cpp: + (WebCore::KURL::setProtocol): + (WebCore::KURL::isHierarchical): + +2010-02-18 Simon Fraser <simon.fraser@apple.com> + + No Review. + + Remove a couple of extraneous spaces that got added to the project file + by hand-ending. + + * WebCore.xcodeproj/project.pbxproj: + +2010-02-18 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Dan Bernstein. + + <rdar://problem/7535894> Page contents missing from snapshot on Newsweek.com article + + Add logic to determine when painting via the software rendering path will give an equivalent + result to the accelerated compositing presentation. This tests for the presence of 3D transforms + via the existing RenderLayerCompositor::has3DContent() method. + + * WebCore.base.exp: Export FrameView's isSoftwareRenderable(), paintBehavior() and setPaintBehavior(). + * page/FrameView.h: + * page/FrameView.cpp: + (WebCore::FrameView::isSoftwareRenderable): New method. + (WebCore::FrameView::paintBehavior): Make this non-inline so that we can reliably export it. + +2010-02-18 Dan Bernstein <mitz@apple.com> + + Reviewed by John Sullivan. + + <rdar://problem/7658811> Multiple style recalcs due to getComputedStyle() on “display: none;” element + when there are pending style sheets + + Test: fast/css/getComputedStyle/pending-stylesheet.html + + When querying a property of a computed style declaration for a non-rendered element, + CSSStyleSelector::styleForElement() was called, and if there were pending style sheet, it + would behave as if the lack of renderer is due to FOUC suppression, and set a flag on + the document causing it to recalculate style. On the next computed style property access, + style would be recalculated for the document, but then the flag would get set again if the + element did not have a renderer. + + * dom/Document.cpp: + (WebCore::Document::styleForElementIgnoringPendingStylesheets): Added. Temporarily sets + m_ignorePendingStylesheets around the call to CSSStyleSelector::styleForElement(). + * dom/Document.h: + * dom/Element.cpp: + (WebCore::Element::computedStyle): Use Document::styleForElementIgnoringPendingStylesheets(). + +2010-02-18 Dirk Schulze <krit@webkit.org> + + Reviewed by Nikolas Zimmermann. + + Move SVGResources to Renderers, starting with Masker + https://bugs.webkit.org/show_bug.cgi?id=35020 + + We have rendering specific code in WebCore/svg/graphics. The goal is to move + this code into suitable Renderers. This helps us to clean up the code and makes + maintenance easier. It also makes it possible to remove rendering specific code + from SVG*Elements into this renderers. So the Renderer contains everything that + is needed to use the resource. + RenderSVGResource will be the base class for all new resource render classes like + RenderSVGResourceMasker, RenderSVGResourceClipper and the other resources. + + This patch starts moving SVGResourceMasker to RenderSVGResourceMasker. + Another benefit is the much more useful result in DRT on using masker. + + * Android.mk: + * GNUmakefile.am: + * WebCore.gypi: + * WebCore.pro: + * WebCore.vcproj/WebCore.vcproj: + * WebCore.xcodeproj/project.pbxproj: + * rendering/RenderObject.cpp: + (WebCore::RenderObject::toRenderSVGResource): Conversion to RenderSVGResource base class. + * rendering/RenderObject.h: + (WebCore::RenderObject::isSVGResource): Check if renderer is a resource. + * rendering/RenderPath.cpp: + * rendering/RenderSVGImage.cpp: + (WebCore::RenderSVGImage::destroy): Renderer gets destroyed, unregister it from it's resources. + * rendering/RenderSVGImage.h: Some code clean up according to the webkit style. + (WebCore::RenderSVGImage::toSVGRenderBase): + (WebCore::RenderSVGImage::renderName): + (WebCore::RenderSVGImage::isSVGImage): + (WebCore::RenderSVGImage::localToParentTransform): + (WebCore::RenderSVGImage::strokeBoundingBox): + (WebCore::RenderSVGImage::requiresLayer): + (WebCore::RenderSVGImage::localTransform): + * rendering/RenderSVGInlineText.h: + (WebCore::RenderSVGInlineText::objectBoundingBox): Needed for SVGRenderTreeAsText + * rendering/RenderSVGModelObject.cpp: + (WebCore::RenderSVGModelObject::destroy): Renderer gets destroyed, unregister it from it's resources. + * rendering/RenderSVGModelObject.h: + * rendering/RenderSVGResource.h: Added. + (WebCore::): Base class for all Resource renderers like masker, clipper and others. + (WebCore::RenderSVGResource::RenderSVGResource): + (WebCore::RenderSVGResource::cast): + (WebCore::RenderSVGResource::toRenderSVGResource): + (WebCore::RenderSVGResource::isSVGResource): + (WebCore::RenderSVGResource::drawsContents): + (WebCore::getRenderSVGResourceById): + * rendering/RenderSVGResourceMasker.cpp: Added. + (WebCore::RenderSVGResourceMasker::RenderSVGResourceMasker): + (WebCore::RenderSVGResourceMasker::~RenderSVGResourceMasker): + (WebCore::RenderSVGResourceMasker::invalidateClients): Status of masker changed, remove all clients. + (WebCore::RenderSVGResourceMasker::invalidateClient): Status of an object changed, remove pending client. + (WebCore::RenderSVGResourceMasker::applyResource): Apply masker to object. + (WebCore::RenderSVGResourceMasker::resourceBoundingBox): boundingBox of the resource, depending on the object. + (WebCore::RenderSVGResourceMasker::createMaskImage): Creates the mask image, the context gets clipped with. + * rendering/RenderSVGResourceMasker.h: Added. + (WebCore::MaskerData::MaskerData): + (WebCore::RenderSVGResourceMasker::renderName): + (WebCore::RenderSVGResourceMasker::maskUnits): Unit of mask for DRT. + (WebCore::RenderSVGResourceMasker::maskContentUnits): Unit of childs from mask for DRT. + (WebCore::RenderSVGResourceMasker::resourceType): + * rendering/RenderSVGRoot.cpp: + (WebCore::RenderSVGRoot::destroy): Renderer gets destroyed, unregister it from it's resources. + * rendering/RenderSVGRoot.h: + * rendering/RenderSVGText.cpp: + (WebCore::RenderSVGText::destroy): dito. + * rendering/RenderSVGText.h: + * rendering/RenderTreeAsText.cpp: + (WebCore::write): + * rendering/SVGRenderSupport.cpp: + (WebCore::SVGRenderBase::prepareToRenderSVGContent): + (WebCore::SVGRenderBase::maskerBoundingBoxForRenderer): + (WebCore::SVGRenderBase::deregisterFromResources): Unregister object from all it's resources after status changed. + * rendering/SVGRenderSupport.h: + (WebCore::SVGRenderBase::toSVGRenderBase): + (WebCore::SVGRenderBase::strokeBoundingBox): + (WebCore::SVGRenderBase::markerBoundingBox): + * rendering/SVGRenderTreeAsText.cpp: Update TreeAsText to dump maskers correctly. + (WebCore::operator<<): + (WebCore::writeSVGResource): + (WebCore::writeSVGContainer): + (WebCore::writeSVGText): + (WebCore::writeSVGInlineText): + (WebCore::writeSVGImage): + (WebCore::write): + (WebCore::writeResourcesToObject): + * rendering/SVGRenderTreeAsText.h: + * svg/SVGMaskElement.cpp: Update Masker to use the new renderer. + (WebCore::SVGMaskElement::svgAttributeChanged): + (WebCore::SVGMaskElement::childrenChanged): + (WebCore::SVGMaskElement::maskBoundingBox): + (WebCore::SVGMaskElement::createRenderer): + * svg/SVGMaskElement.h: + * svg/SVGStyledElement.cpp: We need to tell the renderer to unregister object, after the status changed. + (WebCore::SVGStyledElement::invalidateResources): + (WebCore::SVGStyledElement::invalidateResourcesInAncestorChain): + * svg/SVGUnitTypes.h: Conversion of integer to SVGUnitType. + (WebCore::toUnitType): + * svg/graphics/SVGResource.h: + (WebCore::): + (WebCore::SVGResource::isMarker): + * svg/graphics/SVGResourceMasker.cpp: Removed. + * svg/graphics/SVGResourceMasker.h: Removed. + +2010-02-18 Dumitru Daniliuc <dumi@chromium.org> + + Reviewed by Dimitri Glazkov. + + Allow creating/dropping virtual tables when the module is FTS2. + + https://bugs.webkit.org/show_bug.cgi?id=34867 + + * storage/DatabaseAuthorizer.cpp: + (WebCore::DatabaseAuthorizer::createVTable): + (WebCore::DatabaseAuthorizer::dropVTable): + +2010-02-18 Peter Kasting <pkasting@google.com> + + Not reviewed, Chromium build fix. + + r54963 had a typo in the WebCore.gypi change. + https://bugs.webkit.org/show_bug.cgi?id=35003 + + * WebCore.gypi: + +2010-02-18 Vangelis Kokkevis <vangelis@chromium.org> + + Reviewed by Simon Fraser. + + Changing forward declaration of TimingFunction in GraphicsLayer.h from + class to struct to match its actual definition in TimingFunction.h + + https://bugs.webkit.org/show_bug.cgi?id=35069 + + + * platform/graphics/GraphicsLayer.h: + Change forward declaration from: class TimingFunction to: + struct TimingFunction + +2010-02-18 Noam Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Minor improvement to hybrid QPixmap + https://bugs.webkit.org/show_bug.cgi?id=34507 + Instead of having toHTMLImageElement which creates a new element, + assignToHTMLImageElement would set an existing HTML <img/> element to + contain the native QPixmap/QImge. + Also made some style fixes. + + Additions to existing tests: see WebKit/qt/tests + + * bridge/qt/qt_pixmapruntime.cpp: + (JSC::Bindings::QtPixmapWidthField::valueFromInstance): style + (JSC::Bindings::QtPixmapHeightField::valueFromInstance): style + (JSC::Bindings::QtPixmapAssignToElementMethod::name): assignTo + (JSC::Bindings::QtPixmapAssignToElementMethod::invoke): new function + (JSC::Bindings::QtPixmapAssignToElementMethod::numParameters): 1 + (JSC::Bindings::QtPixmapToDataUrlMethod::invoke): style + (JSC::Bindings::QtPixmapToStringMethod::invoke): style + (JSC::Bindings::QtPixmapInstance::invokeMethod): style + (JSC::Bindings::QtPixmapClass::methodsNamed): new func, removed old + (JSC::Bindings::QtPixmapInstance::getPropertyNames): ditto + (JSC::Bindings::QtPixmapInstance::defaultValue): style + (JSC::Bindings::QtPixmapInstance::valueOf): style + (JSC::Bindings::QtPixmapInstance::toPixmap): style + (JSC::Bindings::QtPixmapInstance::variantFromObject): style + +2010-02-18 Peter Kasting <pkasting@google.com> + + Not reviewed, bustage fix. + + An extraneous line in r54839 broke GIF animation. + + * platform/image-decoders/gif/GIFImageReader.cpp: + (GIFImageReader::read): + +2010-02-18 Dan Bernstein <mitz@apple.com> + + Reviewed by Simon Fraser. + + <rdar://problem/7650652> REGRESSION: Selection painting issue in bug review textbox + https://bugs.webkit.org/show_bug.cgi?id=34946 + + Test: fast/repaint/selection-gap-overflow-scroll-2.html + + * rendering/RenderBlock.cpp: + (WebCore::RenderBlock::paintSelection): localToContainerQuad() adjusts for + overflow scroll, but RenderLayer::addBlockSelectionGapsBounds() takes + non-scrolled coordinates, so account for that. + +2010-02-17 Dumitru Daniliuc <dumi@chromium.org> + + Reviewed by Darin Adler. + + Change the V8 and JSC SQLStatementErrorCallback to interpret + 'undefined' return values as 'true', as required by the spec. + + https://bugs.webkit.org/show_bug.cgi?id=35048 + + * bindings/js/JSCustomSQLStatementErrorCallback.cpp: + (WebCore::JSCustomSQLStatementErrorCallback::handleEvent): + * bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp: + (WebCore::V8CustomSQLStatementErrorCallback::handleEvent): + * bindings/v8/custom/V8CustomVoidCallback.cpp: + (WebCore::invokeCallbackHelper): + (WebCore::invokeCallback): + (WebCore::invokeCallbackTreatUndefinedAsTrue): + * bindings/v8/custom/V8CustomVoidCallback.h: + +2010-02-17 Ojan Vafai <ojan@chromium.org> + + Reviewed by Adam Barth. + + keyboard selection sometimes moves the wrong end of the selection for Win/Linux + https://bugs.webkit.org/show_bug.cgi?id=35066 + + On Windows/Linux keyboard based selections should always move the same + end of the seleciton. On Mac, lineboundary and documentboundary changes + move different ends of the selection depending on which direction your + extending. + + Test: editing/selection/extend-after-mouse-selection.html + + * editing/SelectionController.cpp: + (WebCore::SelectionController::positionForPlatform): + (WebCore::SelectionController::startForPlatform): + (WebCore::SelectionController::endForPlatform): + (WebCore::SelectionController::modifyExtendingRight): + (WebCore::SelectionController::modifyExtendingForward): + (WebCore::SelectionController::modifyMovingForward): + (WebCore::SelectionController::modifyExtendingBackward): + (WebCore::SelectionController::modifyMovingBackward): + * editing/SelectionController.h: + +2010-02-18 Timothy Hatcher <timothy@apple.com> + + Add "with" to the list of keywords to syntax highlight. + + http://webkit.org/b/35123 + + Reviewed by Pavel Feldman. + + * inspector/front-end/SourceJavaScriptTokenizer.js: + (WebInspector.SourceJavaScriptTokenizer): Add "width" to _keywords. + * inspector/front-end/SourceJavaScriptTokenizer.re2js: + (WebInspector.SourceJavaScriptTokenizer): Ditto. + +2010-02-17 Peter Kasting <pkasting@google.com> + + Reviewed by Adam Barth. + + Rework PNG-in-ICO decoding to copy the decoded framebuffer into the ICO + decoder, making the logic less crazy and more like the other decoders. + https://bugs.webkit.org/show_bug.cgi?id=28751 + + * platform/image-decoders/ImageDecoder.cpp: + (WebCore::RGBA32Buffer::operator=): + * platform/image-decoders/ImageDecoder.h: + (WebCore::RGBA32Buffer::RGBA32Buffer): + * platform/image-decoders/ico/ICOImageDecoder.cpp: + (WebCore::ICOImageDecoder::frameBufferAtIndex): + (WebCore::ICOImageDecoder::decodeAtIndex): + * platform/image-decoders/ico/ICOImageDecoder.h: + * platform/image-decoders/qt/RGBA32BufferQt.cpp: + (WebCore::RGBA32Buffer::operator=): + * platform/image-decoders/skia/ImageDecoderSkia.cpp: + (WebCore::RGBA32Buffer::operator=): + +2010-02-18 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: multiple popovers on screen at the same time. + + https://bugs.webkit.org/show_bug.cgi?id=35105 + + * inspector/front-end/Popover.js: + (WebInspector.Popover.prototype.show): + (WebInspector.Popover.prototype.hide): + * inspector/front-end/SourceFrame.js: + (WebInspector.SourceFrame.prototype._showPopup): + +2010-02-18 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: Expand Object.__proto__ properly. + + https://bugs.webkit.org/show_bug.cgi?id=35113 + + * inspector/front-end/EventListenersSidebarPane.js: + * inspector/front-end/InjectedScript.js: + (injectedScriptConstructor): + * inspector/front-end/ObjectProxy.js: + (WebInspector.ObjectProxy): + * inspector/front-end/PropertiesSidebarPane.js: + (WebInspector.PropertiesSidebarPane.prototype.update.callback): + * inspector/front-end/inspector.js: + (WebInspector.log.logMessage): + (WebInspector.log): + +2010-02-18 Nate Chapin <japhet@chromium.org> + + Reviewed by Adam Barth. + + [V8] Merge the DOMWindow and WorkerContext object wrapping code paths, + and use a faster method of disambiguating between the types of contexts. + + https://bugs.webkit.org/show_bug.cgi?id=35009 + + * bindings/scripts/CodeGeneratorV8.pm: Remove logic determining whether we need to + handle the WorkerContext case. + * bindings/v8/V8DOMWrapper.cpp: + (WebCore::globalObjectPrototypeIsDOMWindow): + (WebCore::V8DOMWrapper::instantiateV8Object): Merge instantiateV8Object paths. + * bindings/v8/V8DOMWrapper.h: + +2010-02-18 Xan Lopez <xlopez@igalia.com> + + Reviewed by Gustavo Noronha. + + Remove some duplication between PluginView and Widget methods, and + move the setSelfVisible calls to the parent class. + + * platform/gtk/WidgetGtk.cpp: + (WebCore::Widget::show): + (WebCore::Widget::hide): + * plugins/gtk/PluginViewGtk.cpp: + (WebCore::PluginView::setFocus): + (WebCore::PluginView::show): + (WebCore::PluginView::hide): + +2010-02-18 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Darin Adler. + + <rdar://problem/7655195> Switch Leopard back to using CGShading to avoid CGGradient leaks + + Define USE_CG_SHADING on for Tiger and Leopard, and use it to toggle the methods + used for Core Graphics gradient drawing. + + * platform/graphics/Gradient.h: + * platform/graphics/cg/GradientCG.cpp: + (WebCore::Gradient::platformDestroy): + (WebCore::Gradient::paint): + +2010-02-18 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: on-hover evaluation renders nodes and arrays as strings. + + https://bugs.webkit.org/show_bug.cgi?id=35103 + + * inspector/front-end/SourceFrame.js: + (WebInspector.SourceFrame.prototype._showPopup.showObjectPopup): + +2010-02-18 Brady Eidson <beidson@apple.com> + + Reviewed by Sam Weinig. + + Particularly constructed WebFrames can try to access a null HistoryItem + <rdar://problem/7638892> and https://bugs.webkit.org/show_bug.cgi?id=35063 + + Test: fast/loader/api-test-new-window-data-load-base-url.html + + * loader/HistoryController.cpp: + (WebCore::HistoryController::updateBackForwardListForFragmentScroll): We have a known case where a fragment scroll + might take place with a null m_currentItem. updateBackForwardListClippedAtTarget() will either move m_currentItem + to m_previousItem then create a new m_currentItem... or it will do nothing. So we either have both an m_currentItem + and m_previousItem, or we have neither. In the case where we have no m_previousItem, return early. + +2010-02-18 Nate Chapin <japhet@chromium.org> + + Reviewed by Eric Seidel. + + [V8] Correctly handle the case where the event field on the + global object is a v8::Object, but not a DOM wrapper. + + https://bugs.webkit.org/show_bug.cgi?id=34899 + + Test: fast/dom/Window/window-event-override-no-crash.html + + * bindings/v8/ScriptController.cpp: + (WebCore::ScriptController::processingUserGesture): + * bindings/v8/V8DOMWrapper.cpp: + (WebCore::V8DOMWrapper::isValidDOMObject): + (WebCore::V8DOMWrapper::isWrapperOfType): + * bindings/v8/V8DOMWrapper.h: + +2010-02-18 Pavel Feldman <pfeldman@chromium.org> + + Not reviewed, Qt build fix. + + * inspector/front-end/WebKit.qrc: + +2010-02-18 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: Implement evaluate-on-hover for scripts panel. + + https://bugs.webkit.org/show_bug.cgi?id=35003 + + * WebCore.gypi: + * WebCore.vcproj/WebCore.vcproj: + * inspector/front-end/Images/gearButtonGlyph.png: Added. + * inspector/front-end/Images/popoverArrows.png: Added. + * inspector/front-end/Images/popoverBackground.png: Added. + * inspector/front-end/Images/thumbActiveHoriz.png: Added. + * inspector/front-end/Images/thumbActiveVert.png: Added. + * inspector/front-end/Images/thumbHoriz.png: Added. + * inspector/front-end/Images/thumbHoverHoriz.png: Added. + * inspector/front-end/Images/thumbHoverVert.png: Added. + * inspector/front-end/Images/thumbVert.png: Added. + * inspector/front-end/Images/trackHoriz.png: Added. + * inspector/front-end/Images/trackVert.png: Added. + * inspector/front-end/Popup.js: + (WebInspector.Popup): + (WebInspector.Popup.prototype.show): + (WebInspector.Popup.prototype.hide): + (WebInspector.Popup.prototype._positionElement): + * inspector/front-end/SourceFrame.js: + (WebInspector.SourceFrame.prototype._createViewerIfNeeded): + (WebInspector.SourceFrame.prototype._scroll): + (WebInspector.SourceFrame.prototype._mouseDown): + (WebInspector.SourceFrame.prototype._mouseUp): + (WebInspector.SourceFrame.prototype._mouseMove): + (WebInspector.SourceFrame.prototype._mouseOut): + (WebInspector.SourceFrame.prototype._resetHoverTimer): + (WebInspector.SourceFrame.prototype._hidePopup): + (WebInspector.SourceFrame.prototype._mouseHover): + (WebInspector.SourceFrame.prototype._showPopup.showTextPopup): + (WebInspector.SourceFrame.prototype._showPopup.showObjectPopup): + (WebInspector.SourceFrame.prototype._showPopup.evaluateCallback): + (WebInspector.SourceFrame.prototype._showPopup): + (WebInspector.HoverPropertiesSection): + (WebInspector.HoverPropertiesSection.prototype.update): + * inspector/front-end/TextEditorHighlighter.js: + (WebInspector.TextEditorHighlighter): + (WebInspector.TextEditorHighlighter.prototype._lex): + * inspector/front-end/TextViewer.js: + (WebInspector.TextViewer.prototype._paintLine): + * inspector/front-end/WebKit.qrc: + * inspector/front-end/inspector.css: + * inspector/front-end/inspector.html: + * inspector/front-end/inspectorSyntaxHighlight.css: + * inspector/front-end/popover.css: Added. + +2010-02-18 Ben Murdoch <benm@google.com> + + Reviewed by Jeremy Orlow. + + [v8] Complete upstreaming of V8 Touch Event bindings + https://bugs.webkit.org/show_bug.cgi?id=35094 + + No new tests required. + + * bindings/v8/V8Index.cpp: Add generated touch event headers. + +2010-02-18 Steve Block <steveblock@google.com> + + Reviewed by Jeremy Orlow. + + Updates Android V8 build to use DerivedSourcesAllInOne.cpp + https://bugs.webkit.org/show_bug.cgi?id=35083 + + No new tests, build fix only. + + * Android.derived.v8bindings.mk: + * Android.v8bindings.mk: + +2010-02-18 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Reviewed by Xan Lopez. + + fast/frames/iframe-reparenting.html crashing on GTK Debug bots + https://bugs.webkit.org/show_bug.cgi?id=35081 + + Check that the client is alive after every call to it, since any + of them could cause the load to be cancelled, and the client to go + away. + + This is much better than protecting a specific subclass of + ResourceHandleClient (ResourceLoader), which makes us fail when + any other client is used. + + Test: fast/frames/iframe-reparenting.html + + * platform/network/soup/ResourceHandleSoup.cpp: + (WebCore::parseDataUrl): + +2010-02-18 Ben Murdoch <benm@google.com> + + Reviewed by Nate Chapin. + + [v8] [Android] V8 bindings for touch events are missing. + https://bugs.webkit.org/show_bug.cgi?id=33795 + + No new tests as this just enables touch events in V8. Existing touch tests suffice. + + * WebCore.gypi: Add Touch idl files. + * bindings/scripts/CodeGeneratorV8.pm: Add TouchList to typeCanFailConversion map. + * bindings/v8/DOMObjectsInclude.h: Add touch headers. + * bindings/v8/DerivedSourcesAllInOne.cpp: Add touch generated bindings. + * bindings/v8/V8Index.h: Add touch DOM object types. + * bindings/v8/custom/V8EventCustom.cpp: Add conversion of event to touch event. + * Android.derived.jscbindings.mk: Add the touch derived sources to the makefile. + * Android.derived.v8bindings.mk: Add the touch derived sources to the makefile. + +2010-02-18 William Chan <willchan@chromium.org> + + Reviewed by Adam Barth. + + https://bugs.webkit.org/show_bug.cgi?id=35071 + Disable loader limiting of requests per host for the chromium port. + + No tests because we're only changing a constant. + + * platform/network/chromium/ResourceRequest.cpp: + (WebCore::initializeMaximumHTTPConnectionCountPerHost): + +2010-02-18 Xan Lopez <xlopez@igalia.com> + + Reviewed by Eric Seidel. + + [Linux] Webkit incompatible with Java plugins + https://bugs.webkit.org/show_bug.cgi?id=24912 + + The NP Version supported by WebKit is at the moment hardcoded in + PluginPackage.cpp (to 24), but not all backends actually implement + the methods needed to claim this. Introduce a new method to be + implemented by each backend where the maximum supported version + can be specified, and set the GTK+ port NPVersion to 19. This + fixes an instantaneous crasher in the Sun Java NPAPI plugin. + + * plugins/PluginPackage.cpp: + (WebCore::PluginPackage::initializeBrowserFuncs): + * plugins/PluginPackage.h: + * plugins/gtk/PluginPackageGtk.cpp: + (WebCore::PluginPackage::NPVersion): + * plugins/mac/PluginPackageMac.cpp: + (WebCore::PluginPackage::NPVersion): + * plugins/qt/PluginPackageQt.cpp: + (WebCore::PluginPackage::NPVersion): + * plugins/symbian/PluginPackageSymbian.cpp: + (WebCore::PluginPackage::NPVersion): + * plugins/win/PluginPackageWin.cpp: + (WebCore::PluginPackage::NPVersion): + +2010-02-17 Dmitry Titov <dimich@chromium.org> + + Reviewed by David Levin, Darin Fisher, Simon Hausmann. + + When a live iframe element is moved between pages, it still depends on the old page. + https://bugs.webkit.org/show_bug.cgi?id=34382 + + Test: fast/frames/iframe-reparenting-new-page.html + + * html/HTMLFrameElementBase.cpp: + (WebCore::HTMLFrameElementBase::setName): + Move the code setting the frame name into a separate function. + + (WebCore::HTMLFrameElementBase::setNameAndOpenURL): + (WebCore::HTMLFrameElementBase::updateOnReparenting): + Called on the frame that was just re-parented and inserted into another Document. + Simply invoke Frame::transferChildFrameToNewDocument(...); + + (WebCore::HTMLFrameElementBase::insertedIntoDocument): + * html/HTMLFrameElementBase.h: + * html/HTMLFrameOwnerElement.h: + (WebCore::HTMLFrameOwnerElement::setName): + Make this a virtual function, to be able to reach it via Frame::m_ownerElement. + + * loader/EmptyClients.h: + (WebCore::EmptyFrameLoaderClient::adoptFrame): + * loader/FrameLoaderClient.h: + Add a new method, didTransferChildFrameToNewDocument(). + It compliments createFrame() in that a frame which was re-parented + in DOM and potentially changes Page, should notify the WebKit + implementation about potential ownership change. + Many embedders assume that Page owns all the Frames, or at least + all Frames are destroyed before 'their' Page is destroyed. Obviously, if Frame + can be transferred to another Page, the embedders should be notified. + + * page/Frame.cpp: + (WebCore::Frame::transferChildFrameToNewDocument): + Added, makes actual adjustments for Frame - resets the Page, + updates the frame tree and frame name, calls to FrameLoaderClient + to update external objects and recurses into children. + Can only be used on child frames. + + * page/Frame.h: + +2010-02-17 Tony Chang <tony@chromium.org> + + Reviewed by Eric Seidel. + + Copying and pasting into a contenteditable area can create <div>s surrounded by <span>s + https://bugs.webkit.org/show_bug.cgi?id=26937 + + This happens because of a span added when we copy that is used to + preserve styles. To avoid this, when we paste, make sure to apply + the styles to the span's children and then remove the style span. + + This change is covered by existing layout tests. + + * editing/ReplaceSelectionCommand.cpp: + (WebCore::ReplaceSelectionCommand::handleStyleSpans): + (WebCore::ReplaceSelectionCommand::copyStyleToChildren): + * editing/ReplaceSelectionCommand.h: + +2010-02-17 Tony Chang <tony@chromium.org> + + Reviewed by Eric Seidel. + + https://bugs.webkit.org/show_bug.cgi?id=34914 + When pasting absolute font sizes into a content editable area with + page zoom, adjust the font sizes to be the same after page zoom is + applied. + + Test: editing/pasteboard/page-zoom.html + + * editing/ReplaceSelectionCommand.cpp: + (WebCore::ReplaceSelectionCommand::negateStyleRulesThatAffectAppearance): + +2010-02-17 Tony Chang <tony@chromium.org> + + Reviewed by Eric Seidel. + + https://bugs.webkit.org/show_bug.cgi?id=34737 + Copying styled list items then pasting into a list + should work the same as copying unstyle list items: + it shouldn't indent an extra level, but styles should + be copied. + + Small cleanups to insertAsListItems to make variable names + more descriptive. + + Test: editing/pasteboard/paste-list-003.html + + * editing/ReplaceSelectionCommand.cpp: + (WebCore::ReplaceSelectionCommand::doApply): + (WebCore::ReplaceSelectionCommand::insertAsListItems): + +2010-02-17 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Eric Seidel. + + [BREWMP] Port PlatformKeyboardEvent + https://bugs.webkit.org/show_bug.cgi?id=34794 + + Retrieve the type, key code, text and modifiers from BREW's keyboard event. + + * platform/PlatformKeyboardEvent.h: + * platform/brew/PlatformKeyboardEventBrew.cpp: Added. + (WebCore::keyIdentifierForBrewKeyCode): + (WebCore::windowsKeyCodeForKeyEvent): + (WebCore::singleCharacterString): + (WebCore::PlatformKeyboardEvent::PlatformKeyboardEvent): + (WebCore::PlatformKeyboardEvent::disambiguateKeyDownEvent): + (WebCore::PlatformKeyboardEvent::currentCapsLockState): + +2010-02-17 Hayato Ito <hayato@chromium.org> + + Reviewed by Eric Seidel. + + Support CSS page-break-inside with a value of 'avoid'. + + https://bugs.webkit.org/show_bug.cgi?id=34080 + + Test: printing/page-break-inside.html + + * rendering/RenderBlock.cpp: + (WebCore::RenderBlock::paintChildren): + +2010-02-17 Fumitoshi Ukai <ukai@chromium.org> + + Reviewed by Alexey Proskuryakov. + + WebSocket bufferedAmount should not be 0 when send after close. + https://bugs.webkit.org/show_bug.cgi?id=34633 + + Fixed bug in webkit r54694. check m_client after it calls user + callback, because user callback may call close(), which would + call onclose event handler. + + Test: websocket/tests/bufferedAmount-after-close.html + + * websockets/ThreadableWebSocketChannelClientWrapper.h: + (WebCore::ThreadableWebSocketChannelClientWrapper::didClose): + * websockets/WebSocket.cpp: + (WebCore::WebSocket::WebSocket): + (WebCore::WebSocket::send): + (WebCore::WebSocket::close): + (WebCore::WebSocket::bufferedAmount): + (WebCore::WebSocket::didConnect): + (WebCore::WebSocket::didClose): + * websockets/WebSocket.h: + * websockets/WebSocketChannel.cpp: + (WebCore::WebSocketChannel::WebSocketChannel): + (WebCore::WebSocketChannel::send): + (WebCore::WebSocketChannel::bufferedAmount): + (WebCore::WebSocketChannel::didClose): + (WebCore::WebSocketChannel::didReceiveData): + * websockets/WebSocketChannel.h: + * websockets/WebSocketChannelClient.h: + (WebCore::WebSocketChannelClient::didClose): + * websockets/WorkerThreadableWebSocketChannel.cpp: + (WebCore::workerContextDidClose): + (WebCore::WorkerThreadableWebSocketChannel::Peer::didClose): + * websockets/WorkerThreadableWebSocketChannel.h: + +2010-02-17 Yuzo Fujishima <yuzo@google.com> + + Reviewed by Eric Seidel. + + In diffing render styles, consider all pseudo style changes. + Without this patch, only :before and :after are considered. This is the cause of the following bug. + https://bugs.webkit.org/show_bug.cgi?id=32187 + + Test: fast/css/first-letter-first-line-hover.html + + * dom/Node.cpp: + (WebCore::Node::diff): + * rendering/style/RenderStyle.cpp: + (WebCore::RenderStyle::hasAnyPublicPseudoStyles): + * rendering/style/RenderStyle.h: + * rendering/style/RenderStyleConstants.h: + (WebCore::): + +2010-02-17 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Eric Seidel. + + [BREWMP] Add WebCore::prefetchDNS + https://bugs.webkit.org/show_bug.cgi?id=34873 + + DNS prefetching is not implemented because the maximum number + of UDP sockets is quite small in most BREW devices. + + * platform/network/brew/DNSBrew.cpp: Added. + (WebCore::prefetchDNS): + +2010-02-17 Kent Tamura <tkent@chromium.org> + + Reviewed by Eric Seidel. + + Introduces new Icon loading interface in order to support + asynchronous loading. + https://bugs.webkit.org/show_bug.cgi?id=32054 + + It's hard for Chromium port to load an icon inside + Icon::createIconForFiles() because of sanbox and multi-process + architecture. So this change adds a method to request an icon to + Chrome class, and makes FileChooser receives an Icon instance + asynchronously. Synchronous loading also works with the new interface. + + Because all ports don't have implementations of Chrome::iconForFiles() + yet, FileChooser tries to load an Icon synchronously with + Icon::createIconForFiles(), then tries to load an Icon asynchronously + with Chrome::iconForFiles() if Icon::createIconForFiles() returns 0. + + The existing Icon::createIconForFiles() implementations should be + moved to Chrome::iconForFiles(). We're going to remove + Icon::createIconForFiles(). + + * loader/EmptyClients.h: + (WebCore::EmptyChromeClient::iconForFiles): Add an empty implementation. + * page/Chrome.cpp: + (WebCore::Chrome::iconForFiles): Delegate to ChromeClient::iconForFiles(). + * page/Chrome.h: + * page/ChromeClient.h: + (WebCore::ChromeClient::iconForFiles): Add a declaration as a pure virtual method. + * platform/FileChooser.cpp: + (WebCore::FileChooser::FileChooser): Use loadIcon(). + (WebCore::FileChooser::chooseFiles): ditto. + (WebCore::FileChooser::loadIcon): Added. + (WebCore::FileChooser::iconLoaded): Added. + * platform/FileChooser.h: Add two methods to FileChooserClient; repaint() and iconForFiles(). + * platform/graphics/Icon.h: Add a FIXME comment. + * platform/graphics/gtk/IconGtk.cpp: ditto. + * platform/graphics/mac/IconMac.mm: ditto. + * platform/graphics/qt/IconQt.cpp: ditto. + * platform/graphics/win/IconWin.cpp: ditto. + * rendering/RenderFileUploadControl.cpp: + (WebCore::RenderFileUploadControl::iconForFiles): Delegate to Chrome::iconForFiles(). + (WebCore::RenderFileUploadControl::click): Use chrome(). + (WebCore::RenderFileUploadControl::chrome): + * rendering/RenderFileUploadControl.h: + (WebCore::RenderFileUploadControl::repaint): + +2010-02-17 Mark Rowe <mrowe@apple.com> + + Reviewed by Darin Adler. + + Bug 35065: Delay between page loading and animated GIF playing + <http://webkit.org/b/35065> / <rdar://problem/7109548> + + BitmapImage::startAnimation was adding the current frame duration to the desired start time + of the frame for every time it was called. If the function then bailed out due to not having + sufficient data to render the frame, this would lead to the desired start time of the frame + being pushed out multiple times. On an animated GIF that took mulitple seconds to load this + could happen many times for a single frame, resulting in the start time of the second frame + of the animation being pushed out by as much as five seconds. + + * platform/graphics/BitmapImage.cpp: + (WebCore::BitmapImage::startAnimation): Change the order of the code slightly so that the + desired start time is only updated after determining that we have sufficient data to handle + the next frame. + +2010-02-17 Stephan Aßmus <superstippi@gmx.de> + + Reviewed by Eric Seidel. + + Implemented homeDirectoryPath() and listDirectory() on the Haiku platform. + https://bugs.webkit.org/show_bug.cgi?id=34687 + + Covered by existing tests. + + * platform/haiku/FileSystemHaiku.cpp: + (WebCore::homeDirectoryPath): Implemented + (WebCore::listDirectory): Implemented + +2010-02-17 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Eric Seidel. + + [BREWMP] Port userIdleTime + https://bugs.webkit.org/show_bug.cgi?id=34259 + + Return an arbitrarily high userIdleTime so that releasing pages from the page + cache isn't postponed. + + * platform/brew/SystemTimeBrew.cpp: Added. + (WebCore::userIdleTime): + +2010-02-17 Dirk Schulze <krit@webkit.org> + + Rolling out r54909. Breaks SL and Win. + +2010-02-17 Dumitru Daniliuc <dumi@chromium.org> + + Reviewed by Dimitri Glazkov. + + Fix Chromium's bindings for Database.transaction(): a 'null' + callback should be treated as no callback. + + Test: storage/null-callbacks.html + + https://bugs.webkit.org/show_bug.cgi?id=35047 + + * bindings/v8/custom/V8DatabaseCustom.cpp: + (WebCore::createTransaction): + +2010-02-17 Dirk Schulze <krit@webkit.org> + + Reviewed by Nikolas Zimmermann. + + Move SVGResources to Renderers, starting with Masker + https://bugs.webkit.org/show_bug.cgi?id=35020 + + We have rendering specific code in WebCore/svg/graphics. The goal is to move + this code into suitable Renderers. This helps us to clean up the code and makes + maintenance easier. It also makes it possible to remove rendering specific code + from SVG*Elements into this renderers. So the Renderer contains everything that + is needed to use the resource. + RenderSVGResource will be the base class for all new resource render classes like + RenderSVGResourceMasker, RenderSVGResourceClipper and the other resources. + + This patch starts moving SVGResourceMasker to RenderSVGResourceMasker. + Another benefit is the much more useful result in DRT on using masker. + + * Android.mk: + * GNUmakefile.am: + * WebCore.gypi: + * WebCore.pro: + * WebCore.vcproj/WebCore.vcproj: + * WebCore.xcodeproj/project.pbxproj: + * rendering/RenderObject.cpp: + (WebCore::RenderObject::toRenderSVGResource): Conversion to RenderSVGResource base class. + * rendering/RenderObject.h: + (WebCore::RenderObject::isSVGResource): Check if renderer is a resource. + * rendering/RenderPath.cpp: + * rendering/RenderSVGImage.cpp: + (WebCore::RenderSVGImage::destroy): Renderer gets destroyed, unregister it from it's resources. + * rendering/RenderSVGImage.h: Some code clean up according to the webkit style. + (WebCore::RenderSVGImage::toSVGRenderBase): + (WebCore::RenderSVGImage::renderName): + (WebCore::RenderSVGImage::isSVGImage): + (WebCore::RenderSVGImage::localToParentTransform): + (WebCore::RenderSVGImage::strokeBoundingBox): + (WebCore::RenderSVGImage::requiresLayer): + (WebCore::RenderSVGImage::localTransform): + * rendering/RenderSVGInlineText.h: + (WebCore::RenderSVGInlineText::objectBoundingBox): Needed for SVGRenderTreeAsText + * rendering/RenderSVGModelObject.cpp: + (WebCore::RenderSVGModelObject::destroy): Renderer gets destroyed, unregister it from it's resources. + * rendering/RenderSVGModelObject.h: + * rendering/RenderSVGResource.h: Added. + (WebCore::): Base class for all Resource renderers like masker, clipper and others. + (WebCore::RenderSVGResource::RenderSVGResource): + (WebCore::RenderSVGResource::cast): + (WebCore::RenderSVGResource::toRenderSVGResource): + (WebCore::RenderSVGResource::isSVGResource): + (WebCore::RenderSVGResource::drawsContents): + (WebCore::getRenderSVGResourceById): + * rendering/RenderSVGResourceMasker.cpp: Added. + (WebCore::RenderSVGResourceMasker::RenderSVGResourceMasker): + (WebCore::RenderSVGResourceMasker::~RenderSVGResourceMasker): + (WebCore::RenderSVGResourceMasker::invalidateClients): Status of masker changed, remove all clients. + (WebCore::RenderSVGResourceMasker::invalidateClient): Status of an object changed, remove pending client. + (WebCore::RenderSVGResourceMasker::applyResource): Apply masker to object. + (WebCore::RenderSVGResourceMasker::resourceBoundingBox): boundingBox of the resource, depending on the object. + (WebCore::RenderSVGResourceMasker::createMaskImage): Creates the mask image, the context gets clipped with. + * rendering/RenderSVGResourceMasker.h: Added. + (WebCore::MaskerData::MaskerData): + (WebCore::RenderSVGResourceMasker::renderName): + (WebCore::RenderSVGResourceMasker::maskUnits): Unit of mask for DRT. + (WebCore::RenderSVGResourceMasker::maskContentUnits): Unit of childs from mask for DRT. + (WebCore::RenderSVGResourceMasker::resourceType): + * rendering/RenderSVGRoot.cpp: + (WebCore::RenderSVGRoot::destroy): Renderer gets destroyed, unregister it from it's resources. + * rendering/RenderSVGRoot.h: + * rendering/RenderSVGText.cpp: + (WebCore::RenderSVGText::destroy): dito. + * rendering/RenderSVGText.h: + * rendering/RenderTreeAsText.cpp: + (WebCore::write): + * rendering/SVGRenderSupport.cpp: + (WebCore::SVGRenderBase::prepareToRenderSVGContent): + (WebCore::SVGRenderBase::maskerBoundingBoxForRenderer): + (WebCore::SVGRenderBase::deregisterFromResources): Unregister object from all it's resources after status changed. + * rendering/SVGRenderSupport.h: + (WebCore::SVGRenderBase::toSVGRenderBase): + (WebCore::SVGRenderBase::strokeBoundingBox): + (WebCore::SVGRenderBase::markerBoundingBox): + * rendering/SVGRenderTreeAsText.cpp: Update TreeAsText to dump maskers correctly. + (WebCore::operator<<): + (WebCore::writeSVGResource): + (WebCore::writeSVGContainer): + (WebCore::writeSVGText): + (WebCore::writeSVGInlineText): + (WebCore::writeSVGImage): + (WebCore::write): + (WebCore::writeResourcesToObject): + * rendering/SVGRenderTreeAsText.h: + * svg/SVGMaskElement.cpp: Update Masker to use the new renderer. + (WebCore::SVGMaskElement::svgAttributeChanged): + (WebCore::SVGMaskElement::childrenChanged): + (WebCore::SVGMaskElement::maskBoundingBox): + (WebCore::SVGMaskElement::createRenderer): + * svg/SVGMaskElement.h: + * svg/SVGStyledElement.cpp: We need to tell the renderer to unregister object, after the status changed. + (WebCore::SVGStyledElement::invalidateResources): + (WebCore::SVGStyledElement::invalidateResourcesInAncestorChain): + * svg/SVGUnitTypes.h: Conversion of integer to SVGUnitType. + (WebCore::toUnitType): + * svg/graphics/SVGResource.h: + (WebCore::): + (WebCore::SVGResource::isMarker): + * svg/graphics/SVGResourceMasker.cpp: Removed. + * svg/graphics/SVGResourceMasker.h: Removed. + +2010-02-17 Kenneth Russell <kbr@google.com> + + Reviewed by Oliver Hunt. + + Refactor texImage2D and texSubImage2D taking Image to use common code + https://bugs.webkit.org/show_bug.cgi?id=34458 + + Merged the Safari and Chromium code which extracts the data from + Image objects into common entry points on GraphicsContext3D. This + immediately fixes the following three problems: + - Chromium not implementing texSubImage2D taking Image. + - Safari not obeying the flipY parameter to texImage2D or + texSubImage2D taking Image. + - Safari not obeying the premultipyAlpha parameter to texImage2D + or texSubImage2D taking Image. + Added new test verifying the behavior of texImage2D and + texSubImage2D and the flipY parameter. The premultiplyAlpha + parameter can not be tested yet as the implementation is not yet + spec compliant. This will be fixed in a follow-on bug. + + Ran all WebGL demos in demo repository on Safari and Chromium; + textures are now the right way up in both browsers, and + transparent textures in Particles demo now look correct in Safari. + + Test: fast/canvas/webgl/tex-image-and-sub-image-2d-with-image.html + + * WebCore.gyp/WebCore.gyp: + * WebCore.gypi: + * WebCore.xcodeproj/project.pbxproj: + * platform/graphics/GraphicsContext3D.cpp: Added. + (WebCore::GraphicsContext3D::extractImageData): + (WebCore::GraphicsContext3D::processImageData): + (WebCore::GraphicsContext3D::premultiplyAlpha): + (WebCore::GraphicsContext3D::unmultiplyAlpha): + * platform/graphics/GraphicsContext3D.h: + (WebCore::GraphicsContext3D::): + * platform/graphics/cg/GraphicsContext3DCG.cpp: Added. + (WebCore::GraphicsContext3D::getImageData): + * platform/graphics/mac/GraphicsContext3DMac.cpp: + (WebCore::GraphicsContext3D::texImage2D): + (WebCore::GraphicsContext3D::texSubImage2D): + * platform/graphics/skia/GraphicsContext3DSkia.cpp: Added. + (WebCore::GraphicsContext3D::getImageData): + +2010-02-17 Noam Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Ariya Hidayat. + + [Qt] GraphicsLayer: support perspective and 3D transforms + https://bugs.webkit.org/show_bug.cgi?id=34960 + + New tests: http://webkit.org/blog-files/3d-transforms/perspective-by-example.html + + * platform/graphics/qt/GraphicsLayerQt.cpp: + (WebCore::GraphicsLayerQtImpl::updateTransform): + (WebCore::GraphicsLayerQtImpl::setBaseTransform): + (WebCore::GraphicsLayerQtImpl::computeTransform): + (WebCore::GraphicsLayerQtImpl::flushChanges): + (WebCore::TransformAnimationQt::~TransformAnimationQt): + +2010-02-17 Peter Kasting <pkasting@google.com> + + Unreviewed, build fix. + + Fix crashes due to an omitted line in r54839. + + * platform/image-decoders/png/PNGImageDecoder.cpp: + (WebCore::decodingFailed): + +2010-02-17 Alok Priyadarshi <alokp@chromium.org> + + Reviewed by Ariya Hidayat. + + Bug 34900: Implement accelerated compositing for chromium. + https://bugs.webkit.org/show_bug.cgi?id=34900 + + Do not exclude files needed for accelerated compositing. In fact there is no need to exclude these files. + These files are already guarded with WTF_USE_ACCELERATED_COMPOSITING flag. + + * WebCore.gyp/WebCore.gyp: Removed GraphicsLayer.cpp, RenderLayerBacking.cpp, + and RenderLayerCompositor.cpp from excluded list. + +2010-02-17 Jian Li <jianli@chromium.org> + + Reviewed by Darin Fisher. + + [chromium] Remove the obsolete chromium interface for handling DownloadURL. + https://bugs.webkit.org/show_bug.cgi?id=34982 + + * platform/chromium/ChromiumDataObject.cpp: + (WebCore::ChromiumDataObject::clear): + (WebCore::ChromiumDataObject::hasData): + (WebCore::ChromiumDataObject::ChromiumDataObject): + * platform/chromium/ChromiumDataObject.h: + * platform/chromium/ClipboardChromium.cpp: + (WebCore::ClipboardChromium::setData): + +2010-02-17 Dan Bernstein <mitz@apple.com> + + Reviewed by Darin Adler. + + <rdar://problem/7645569> REGRESSION (r51324): Incorrect marker rects for blocks that span multiple columns + + * manual-tests/match-marker-rects.html: Added. + * rendering/InlineTextBox.cpp: + (WebCore::InlineTextBox::paintTextMatchMarker): Use the text renderer rather + than its ancestor block for the local-to-absolute transformation. + (WebCore::InlineTextBox::computeRectForReplacementMarker): Ditto. + +2010-02-17 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Reviewed by Xan Lopez. + + Does not send an Accept header for subresources, causing some sites to break + https://bugs.webkit.org/show_bug.cgi?id=33242 + + Set */* as the Accept header when downloading resources + that did not set an Accept header. This behaviour is similar to + the one adopted by Chromium. + + Test: http/tests/misc/image-checks-for-accept.html + + * platform/network/soup/ResourceHandleSoup.cpp: + (WebCore::startHttp): + +2010-02-17 Marcus Bulach <bulach@chromium.org> + + Reviewed by Jeremy Orlow. + + Fixes initialization order of members for GeolocationServiceChromium. + https://bugs.webkit.org/show_bug.cgi?id=35034 + + * platform/chromium/GeolocationServiceChromium.cpp: + +2010-02-17 Xan Lopez <xlopez@igalia.com> + + Reviewed by Gustavo Noronha. + + [Linux] Webkit incompatible with Java plugins + https://bugs.webkit.org/show_bug.cgi?id=24912 + + Resolve symlinks before trying to load plugins as modules, since + GModule won't do it. + + Based on original work by Gustavo Noronha. + + * plugins/gtk/PluginPackageGtk.cpp: + (WebCore::PluginPackage::load): + +2010-02-17 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Reviewed by Xan Lopez. + + Protect the resource loader object from disappearing during + parseDataUrl. + + Tested by testdownload API test. + + * platform/network/soup/ResourceHandleSoup.cpp: + (WebCore::parseDataUrl): + +2010-02-17 Marcus Bulach <bulach@chromium.org> + + Reviewed by Jeremy Orlow. + + Implements GeolocationServices for Chromium. + https://bugs.webkit.org/show_bug.cgi?id=32068 + + This is part of implementing Geolocation framework for Chromium. Existing layout tests should pass. + + * WebCore.gypi: + * page/Geolocation.h: + * platform/GeolocationService.h: + +2010-02-17 Steve Block <steveblock@google.com> + + Reviewed by Ariya Hidayat. + + Adds missing platform and feature guards to V8 bindings + https://bugs.webkit.org/show_bug.cgi?id=34987 + + No new tests, build fix only. + + * bindings/v8/V8Proxy.cpp: Modified. Adds CHROMIUM guards and uses PlatformBridge in place of ChromiumBridge + * bindings/v8/V8Proxy.h: Modified. Adds CHROMIUM guards and uses PlatformBridge in place of ChromiumBridge + * bindings/v8/custom/V8DocumentCustom.cpp: Modified. Adds XPATH guards + +2010-02-17 Steve Block <steveblock@google.com> + + Reviewed by Ariya Hidayat. + + Include WebCore's npruntime.h for Android in V8 bindings + https://bugs.webkit.org/show_bug.cgi?id=35002 + + Currently, the V8 bindings include bindings/npruntime.h, which is a + Chromium-specific file outside of the WebKit tree. + + No new tests, build fix only. + + * bindings/v8/NPV8Object.cpp: + * bindings/v8/NPV8Object.h: + * bindings/v8/V8NPObject.h: + * bindings/v8/V8NPUtils.h: + * bindings/v8/npruntime_impl.h: + * bindings/v8/npruntime_priv.h: + +2010-01-07 Philippe Normand <pnormand@igalia.com> + + Reviewed by Gustavo Noronha Silva. + + [GStreamer] Should handle BUFFERING messages + https://bugs.webkit.org/show_bug.cgi?id=30004 + + Initial support for on-disk buffering of videos. This works only + for Quicktime and flv though. + + * css/mediaControlsGtk.css: + * platform/gtk/RenderThemeGtk.cpp: + (WebCore::RenderThemeGtk::paintMediaSliderTrack): Draw the + buffering status in the media controls. + * platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp: + (WebCore::mediaPlayerPrivateMessageCallback): Defer buffering + messages handling to processBufferingStats(). + (WebCore::bufferingTimeoutCallback): Closure called periodically + during the on-disk buffering process. + (WebCore::MediaPlayerPrivate::MediaPlayerPrivate): New instance + variables and create playbin2 here instead of doing it in load(). + (WebCore::MediaPlayerPrivate::~MediaPlayerPrivate): New instance + variables. + (WebCore::MediaPlayerPrivate::load): Simply set uri on playbin2 + instead of creating the pipeline and setting uri all together. + (WebCore::MediaPlayerPrivate::processBufferingStats): Start a new + timeout source if the player is starting on-disk buffering. + (WebCore::MediaPlayerPrivate::queryBufferingStats): Method called + 200ms during on-disk buffering to update the maxTimeLoaded and few + other private variables. + (WebCore::MediaPlayerPrivate::maxTimeSeekable): + (WebCore::MediaPlayerPrivate::maxTimeLoaded): + (WebCore::MediaPlayerPrivate::bytesLoaded): Fixed implementations + regarding buffering. + (WebCore::MediaPlayerPrivate::totalBytes): Improved logging. + (WebCore::MediaPlayerPrivate::updateStates): Start playback if it + was internally paused at beginning of on-disk buffering and set + ready/network states depending on the state of the on-disk + buffering process. + (WebCore::MediaPlayerPrivate::didEnd): Emit durationChanged. + (WebCore::MediaPlayerPrivate::setAutobuffer): Edit playbin2 flags + property depending on autoBuffer value. + (WebCore::MediaPlayerPrivate::createGSTPlayBin): Don't set uri + there, it is now done in load(). + * platform/graphics/gtk/MediaPlayerPrivateGStreamer.h: New methods + and instance variables. + +2010-02-16 Chris Evans <cevans@chromium.org> + + Reviewed by Adam Barth. + + Add a new setting which gives the option of assigning every file:/// + to its own unique domain. + + https://bugs.webkit.org/show_bug.cgi?id=34778 + + Test: Pending in forthcoming separate change due to non-trivial + dependencies. + + * dom/Document.cpp: + (WebCore::Document::initSecurityContext): Place file:/// URI documents + into their own unique domains if the new setting requires it. + * page/Settings.h: + * page/Settings.cpp: + (WebCore::Settings::setAllowFileAccessFromFileURLs): Simple setter. + * page/SecurityOrigin.h: + * page/SecurityOrigin.cpp: + (WebCore::SecurityOrigin::makeUnique): Add simple ability to force an + origin to be considered unique. + +2010-02-16 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: drosera/demo.js not syntax highlighted correctly. + + https://bugs.webkit.org/show_bug.cgi?id=35008 + + * inspector/front-end/SourceTokenizer.js: + (WebInspector.SourceTokenizer.Registry): + (WebInspector.SourceTokenizer.Registry.prototype.getTokenizer): + +2010-02-16 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: prefer smooth scrolling to instant highlight. + + https://bugs.webkit.org/show_bug.cgi?id=34978 + + * inspector/front-end/TextViewer.js: + (WebInspector.TextViewer): + (WebInspector.TextViewer.prototype._scroll): + (WebInspector.TextChunk): + (WebInspector.TextChunk.prototype._createRow): + * inspector/front-end/textViewer.css: + +2010-02-16 Yael Aharon <yael.aharon@nokia.com> + + Reviewed by Nikolas Zimmermann. + + SVG not rendered as background-image from data URI + https://bugs.webkit.org/show_bug.cgi?id=33630 + + When the background image is an SVG image, and it is smaller than the area + it is supposed to fill, we were using renderSubTreeToImage to draw it. + That call was not going through all the drawing phases, and so the SVG itself + would not be drawn. + + Test: svg/css/background-image-svg.html + + * svg/graphics/SVGImage.cpp: + (WebCore::SVGImage::nativeImageForCurrentFrame): + +2010-02-16 Bryan Yeung <bryeung@chromium.org> + + Reviewed by Nikolas Zimmermann. + + Remove the bounds on stroke width and miter for the skia platform. + https://bugs.webkit.org/show_bug.cgi?id=34954 + + Test: svg/custom/stroke-width-large.svg + + * platform/graphics/skia/PlatformContextSkia.cpp: + (PlatformContextSkia::setupPaintForStroking): + +2010-02-16 MORITA Hajime <morrita@gmail.com> + + Reviewed by Nikolas Zimmermann. + + REGRESSION: SVG text disappaears after double click + https://bugs.webkit.org/show_bug.cgi?id=34880 + + Tests: svg/text/selection-doubleclick.svg + svg/text/selection-tripleclick.svg + + * rendering/SVGRootInlineBox.cpp: + (WebCore::SVGRootInlineBoxPaintWalker::mayHaveSelection): + Use InlineTextBox::selectionStartEnd() instead of + RenderObject::selectionStartEnd() because latter may span multiple + comparing startPos and endPos is irrelevant in some cases. + former selectionStartEnd() is for single line and comparing + startPos and endPos will make sense. + +2010-02-16 Jessie Berlin <jberlin@webkit.org> + + Reviewed by Timothy Hatcher. + + Inspector should display Array lengths in the property lists. + https://bugs.webkit.org/show_bug.cgi?id=20695 + + * inspector/front-end/InjectedScript.js: + (injectedScriptConstructor): + For objects of type 'array' (which includes Arrays, NodeLists, and HTMLCollections), make the length of the object available via propertyLength on the proxy object. + * inspector/front-end/ObjectPropertiesSection.js: + (WebInspector.ObjectPropertyTreeElement.prototype.update): + For properties that have propertyLength defined, append it to the displayed description. + +2010-02-16 Yusuke Sato <yusukes@chromium.org> + + Reviewed by Dimitri Glazkov. + + [Chromium] OpenType font with CFF glyphs is not handled correctly on Windows XP + https://bugs.webkit.org/show_bug.cgi?id=34735 + + Use 0xFFFF as invalidGlyph when fontData is a OpenType font with CFF glyphs. + + Test: fast/css/font-face-opentype.html + + * platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp: + (WebCore::fillBMPGlyphs): + +2010-02-16 Darin Adler <darin@apple.com> + + * page/MediaCanStartListener.h: Fixed license. + +2010-02-16 Darin Adler <darin@apple.com> + + Reviewed by Sam Weinig. + + Generalize delayed plug-in start for background tabs for use for other media + https://bugs.webkit.org/show_bug.cgi?id=34981 + + Also did some simple cleanup of HTMLMediaElement to get ready to make it + a client of the same mechanism. + + * WebCore.base.exp: Added Page::setCanStartMedia and resorted. + * WebCore.xcodeproj/project.pbxproj: Added MediaCanStartListener.h. + + * html/HTMLAudioElement.h: Added an implementation of isVideo since that + is now a pure virtual function in HTMLMediaElement. Also made tagPriority + private. + + * html/HTMLMediaElement.h: Made it clearer that HTMLMediaElement is an + abstract base class by making its constructor protected and making the + isVideo function a pure virtual function. + + * page/Page.cpp: + (WebCore::Page::Page): Updated for name change from m_canStartPlugins + to m_canStartMedia. + (WebCore::Page::addMediaCanStartListener): Renamed and added an assertion. + (WebCore::Page::removeUnstartedMedia): Ditto. + (WebCore::Page::setCanStartMedia): Renamed plugin to media and moved + the code here from PageWin.cpp. The main change from the one in PageWin.cpp + is that this function calls mediaCanStart rather than explicitly calling a + combination of start and dispatchDidFailToStartPlugin on a PluginView. + + * page/Page.h: Re-sorted forward class declarations. Renamed the plugin + starting functions to media starting names and changed types from + PluginView to MediaCanStartListener. + + * page/MediaCanStartListener.h: Added. + + * page/win/PageWin.cpp: Moved setCanStartPlugins to the platform-independent + Page.cpp file so it can be used for more than just Windows plug-ins. + + * plugins/PluginView.cpp: Sorted includes. + (WebCore::PluginView::startOrAddToUnstartedList): Use addMediaCanStartListener. + (WebCore::PluginView::mediaCanStart): Added. Called when the page decides that + media can start. Contains the code that used to be in Page::setCanStartPlugins. + (WebCore::PluginView::removeFromUnstartedListIfNecessary): Use + removeMediaCanStartListener. + + * plugins/PluginView.h: Adopted MediaCanStartListener. + +2010-02-16 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Dan Bernstein. + + https://bugs.webkit.org/show_bug.cgi?id=34999 + Compositing layers inside overflow:scroll divs are not always updated on scrolling + + When RenderLayer::scrollToOffset() updates compositing layer positions, it needs + to start updating at its stacking context rather than just its compositing ancestor. + The stacking context is guaranteed to contain all descendants of the overflow + layer, including those that are not direct descendants of the overflow layer in stacking + (and therefore compositing) order. + + Test: compositing/overflow/scroll-ancestor-update.html + + * rendering/RenderLayer.cpp: + (WebCore::RenderLayer::scrollToOffset): + +2010-02-16 Dan Bernstein <mitz@apple.com> + + Reviewed by Simon Fraser. + + Allow FloatRect::center() to return fractional coordinates. It was + mistakenly converting to integers. + + * platform/graphics/FloatRect.h: + (WebCore::FloatRect::center): + +2010-02-16 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=34964 + Leaks tool reports false memory leaks due to Rope implementation. + + Renamed cUStringImpl::size() to UStringImpl::size()UStringImpl::length() + (matches WebCore::StringImpl). + + * bridge/jni/jsc/JavaStringJSC.h: + (JSC::Bindings::JavaStringImpl::length): + * platform/text/AtomicString.cpp: + (WebCore::AtomicString::add): + (WebCore::AtomicString::find): + +2010-02-15 Jon Honeycutt <jhoneycutt@apple.com> + + <rdar://problem/7288853> Message about missing plugin does not specify + the type or download link for download + + Reviewed by Mark Rowe. + + * plugins/PluginDatabase.cpp: + (WebCore::PluginDatabase::findPlugin): + Only update the mimeType out param if we find a plug-in for the file + extension. + +2010-02-16 Simon Fraser <simon.fraser@apple.com> + + Build fix for Tiger. + + Add #if USE(ACCELERATED_COMPOSITING) around the call to mediaPlayerRenderingModeChanged(). + + * platform/graphics/mac/MediaPlayerPrivateQTKit.mm: + (WebCore::MediaPlayerPrivate::setUpVideoRendering): + +2010-02-16 Csaba Osztrogonác <ossy@webkit.org> + + Reviewed by Eric Carlson. + + Buildfix for r54826. + + HTMLMediaElement class defined by HTMLMediaElement.h in #if ENABLE(VIDEO) block, + it should be in #if ENABLE(VIDEO) block in rendering/RenderLayerBacking.cpp too. + + * rendering/RenderLayerBacking.cpp: Missing #if ENABLE(VIDEO) guard added. + (WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): + +2010-02-16 Julie Parent <jparent@chromium.org> + + Unreviewed: Chromium build fix. + + http://trac.webkit.org/changeset/54823 introduced an unused variable. Remove it. + + * platform/image-decoders/ImageDecoder.cpp: + (WebCore::ImageDecoder::create): + +2010-02-16 Mark Rowe <mrowe@apple.com> + + Reviewed by Alexey Proskuryakov. + + Bug 34974: Leak of ScheduledAction during layout tests + <https://bugs.webkit.org/show_bug.cgi?id=34974> + + ScheduledAction::create was returning a raw pointer which was threaded down through to an OwnPtr in DOMTimer. + If any of the code paths in between hit an error case and returned early the raw pointer would be leaked. We + can avoid this by passing it as a PassOwnPtr. This will ensure that the ScheduledAction is cleaned up should + an error case be hit. + + * bindings/js/JSDOMWindowCustom.cpp: + (WebCore::JSDOMWindow::setTimeout): Store the newly-created ScheduledAction in an OwnPtr and then hand it off + as the function argument. + (WebCore::JSDOMWindow::setInterval): Ditto. + * bindings/js/JSWorkerContextCustom.cpp: + (WebCore::JSWorkerContext::setTimeout): Ditto. + (WebCore::JSWorkerContext::setInterval): Ditto. + * bindings/js/ScheduledAction.cpp: + (WebCore::ScheduledAction::create): Return a PassOwnPtr. + * bindings/js/ScheduledAction.h: + * page/DOMTimer.cpp: + (WebCore::DOMTimer::DOMTimer): Update argument type. + (WebCore::DOMTimer::install): Ditto. + * page/DOMTimer.h: + * page/DOMWindow.cpp: + (WebCore::DOMWindow::setTimeout): Ditto. + (WebCore::DOMWindow::setInterval): Ditto. + * page/DOMWindow.h: + +2010-02-16 Nikolas Zimmermann <nzimmermann@rim.com> + + Reviewed by David Hyatt. + + SVG units don't stay consistently sized on zoom + https://bugs.webkit.org/show_bug.cgi?id=14004 + + Large step towards making WebKit an usable SVG viewer. + + Make zooming into SVG documents work as expected, in both standalone and XHTML/SVG compound documents. + SVG applies a global scale to the document, whereas CSS zooms all individual length units (on full-page-zoom). + Scaling has to be avoided for all SVG specific CSS properties (already works) and for some selected CSS + properties shared between CSS & SVG that explicitely need a different treatment in the context of SVG. + To name a few: font-size, letter-spacing, etc. should stay invariant under zoom in SVG document fragments. + + Some new rules regarding zooming: + - "Zoom text only" should never affect SVG documents, neither text nor content should zoom. + This option doesn't make much sense for SVG, so it's wise to avoid side-effects and disable it. + In compound documents the SVG would stay as-is and only text of surrounding XHTML content would zoom. + + - "Full page zoom" is the only zoom mode affecting SVG. (Panning only works in standalone documents.) + + Cover all mentioned cases above by a new set of layout tests. + + Tests: svg/zoom/page/absolute-sized-document-no-scrollbars.svg + svg/zoom/page/absolute-sized-document-scrollbars.svg + svg/zoom/page/relative-sized-document-scrollbars.svg + svg/zoom/page/zoom-coords-viewattr-01-b.svg + svg/zoom/page/zoom-foreignObject.svg + svg/zoom/page/zoom-hixie-mixed-008.xml + svg/zoom/page/zoom-hixie-mixed-009.xml + svg/zoom/page/zoom-hixie-rendering-model-004.xhtml + svg/zoom/page/zoom-svg-float-border-padding.xml + svg/zoom/text/absolute-sized-document-no-scrollbars.svg + svg/zoom/text/absolute-sized-document-scrollbars.svg + svg/zoom/text/relative-sized-document-scrollbars.svg + svg/zoom/text/zoom-coords-viewattr-01-b.svg + svg/zoom/text/zoom-foreignObject.svg + svg/zoom/text/zoom-hixie-mixed-008.xml + svg/zoom/text/zoom-hixie-mixed-009.xml + svg/zoom/text/zoom-hixie-rendering-model-004.xhtml + svg/zoom/text/zoom-svg-float-border-padding.xml + + * css/CSSStyleSelector.cpp: Blacklist certain properties not to be zoomed for SVG elements. + (WebCore::CSSStyleSelector::styleForDocument): Don't zoom font-sizes. + (WebCore::CSSStyleSelector::applyProperty): Ditto (+ letter/word-spacing). + (WebCore::CSSStyleSelector::setFontSize): Ditto. + (WebCore::CSSStyleSelector::getComputedSizeFromSpecifiedSize): Never apply text zoom to SVG. + * css/CSSStyleSelector.h: + * css/SVGCSSStyleSelector.cpp: -webkit-shadow + SVG was incorrectly respecting zoom factor. + (WebCore::CSSStyleSelector::applySVGProperty): + * page/Frame.cpp: + (WebCore::Frame::shouldApplyTextZoom): Remove SVG special cases. + (WebCore::Frame::shouldApplyPageZoom): Ditto. + (WebCore::Frame::setZoomFactor): Don't force setZoomsTextOnly() - SVG now uses FPZ as well. + * rendering/RenderSVGRoot.cpp: + (WebCore::RenderSVGRoot::calcReplacedWidth): CSSPropertyWidth is explicitely not scaled by CSSStyleSelector, fix that for outermost <svg> elements. + (WebCore::RenderSVGRoot::calcReplacedHeight): Ditto for CSSPropertyHeight. + (WebCore::RenderSVGRoot::layout): Simplify & cleanup code, take advantage of new calcWidth/Height functionality, no need to scale anything here. + (WebCore::RenderSVGRoot::paint): Use parentOriginToBorderBox() instead of duplicating code. + (WebCore::RenderSVGRoot::calcViewport): Simplify code. + (WebCore::RenderSVGRoot::localToBorderBoxTransform): Calculate viewBoxToViewTransformation() against unscaled width()/height() values. + * rendering/RenderSVGRoot.h: + * svg/SVGLength.cpp: + (WebCore::SVGLength::PercentageOfViewport): Cleanup & document function. + * svg/SVGSVGElement.cpp: + (WebCore::SVGSVGElement::currentScale): Return pageZoomFactor(), not just the zoomFactor() - as we want to ignore text-only zoom. + (WebCore::SVGSVGElement::setCurrentScale): Pass isTextOnly=false to setZoomFactor(). + +2010-02-16 Julie Parent <jparent@chromium.org> + + Unreviewed: Chromium build fix. + + https://bugs.webkit.org/show_bug.cgi?id=34998 + + Move include of JavaScriptProfile.h behind if (USE_JSC). + + * inspector/InspectorController.cpp: + +2010-02-16 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Geoffrey Garen and Kevin Decker. + + https://bugs.webkit.org/show_bug.cgi?id=34989 + <rdar://problem/7417965> Cursor disappears on scroll bars that are over plugin content + + * html/HTMLPlugInElement.cpp: (WebCore::HTMLPlugInElement::defaultEventHandler): Added some + comments about the way we pass events down to plug-ins. + +2010-02-16 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Eric Carlson. + + With hardware acceleration turned off, video frames never display if poster + image is specified + https://bugs.webkit.org/show_bug.cgi?id=34965 + + HTMLVideoElement's m_shouldDisplayPosterImage was never updated after + the movie supplied its first video frame, so the poster would continue to show. + + Fixed by calling updatePosterImage() from mediaPlayerRepaint(), which is called + each time a new frame is available. updatePosterImage() is cheap. + + Also made updatePosterImage() virtual on HTMLMediaElement to avoid a number of + ugly casts. + + Test: manual-tests/media-elements/video-replaces-poster.html + + * html/HTMLMediaElement.cpp: + (WebCore::HTMLMediaElement::noneSupported): Call updatePosterImage() without video check. + (WebCore::HTMLMediaElement::setNetworkState): Ditto. + (WebCore::HTMLMediaElement::setReadyState): Ditto. + (WebCore::HTMLMediaElement::mediaPlayerRepaint): Call udpatePosterImage(). + * html/HTMLMediaElement.h: + (WebCore::HTMLMediaElement::updatePosterImage): Make this an empty virtual + method on the base class. + * html/HTMLVideoElement.h: Override updatePosterImage(). + +2010-02-16 Simon Fraser <simon.fraser@apple.com> + + Build fix for platforms without ACCELERATED_COMPOSITING defined. + + mediaPlayerRenderingModeChanged() is only available when ACCELERATED_COMPOSITING is defined. + + * platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp: + (WebCore::MediaPlayerPrivate::setUpVideoRendering): + +2010-02-16 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Eric Carlson. + + Autoplaying video with poster doesn't reliably show up + https://bugs.webkit.org/show_bug.cgi?id=34966 + + A timing issue with compositing updates when replacing the poster image + with the video could cause the video to not display. + + Fix by making video layer hook up more similar to WebGL etc, by having the + video kick off a recalcStyle() via a SyntheticStyleChange. This requires + vending a PlaformLayer* from the media player, up through the element. + + Test: media/video-replaces-poster.html + + * html/HTMLMediaElement.cpp: + (WebCore::HTMLMediaElement::mediaPlayerRenderingModeChanged): Use setNeedsStyleRecalc() + to kick off a compositing update. + + * html/HTMLMediaElement.h: + (WebCore::HTMLMediaElement::platformLayer): Export the media engine's layer. + + * platform/graphics/MediaPlayer.cpp: + (WebCore::NullMediaPlayerPrivate::platformLayer): Method to vend the media layer. + (WebCore::MediaPlayer::platformLayer): + + * platform/graphics/MediaPlayer.h: + (WebCore::MediaPlayerClient::mediaPlayerRenderingModeChanged): New client callback + to indicate that the rendering mode changed. The element uses this to kick off a + recalcStyle. + + * platform/graphics/MediaPlayerPrivate.h: + (WebCore::MediaPlayerPrivateInterface::platformLayer): Method to vend the media layer. + * platform/graphics/mac/MediaPlayerPrivateQTKit.h: Ditto + * platform/graphics/mac/MediaPlayerPrivateQTKit.mm: + (WebCore::MediaPlayerPrivate::createQTMovieLayer): No longer parent the layer directly + via setContentsToMedia(). + (WebCore::MediaPlayerPrivate::acceleratedRenderingStateChanged): Ditto. + (WebCore::MediaPlayerPrivate::setUpVideoRendering): Tell the client that the + rendering mode changed. + (WebCore::MediaPlayerPrivate::platformLayer): Method to vend the media layer. + * rendering/RenderLayerBacking.cpp: + (WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): Call setContentsToMedia() + here. + + * platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h: Add platformLayer(). + * platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp: + (WebCore::MediaPlayerPrivate::platformLayer): Method to vend the media layer. + (WebCore::MediaPlayerPrivate::setUpVideoRendering): Call mediaPlayerRenderingModeChanged() + (WebCore::MediaPlayerPrivate::createLayerForMovie): Don't parent the layer ourselves any more. + + * rendering/RenderVideo.h: videoGraphicsLayer() is no longer needed. + * rendering/RenderVideo.cpp: Ditto. + +2010-02-12 Peter Kasting <pkasting@google.com> + + Reviewed by Adam Barth. + + Code cleanup in ImageDecoders; no functional change. + https://bugs.webkit.org/show_bug.cgi?id=28751 + + * Make code mostly comply with the style guide (switch indenting, use of + "!" vs. "== 0", don't unnecessarily wrap lines, etc.) + * Eliminate m_allDataReceived in ICO/BMP decoders since it's in the + base ImageDecoder class + * Remove some useless or wrong comments, add others + * Wrap comments at 80 columns (most already were) for + consistency/readability + * Avoid casts by using correct variable types + * Consistent naming of decode() function/args + * Shorter code in some places + * Make declaration and definition order match + + * platform/graphics/qt/ImageDecoderQt.cpp: + (WebCore::ImageDecoderQt::frameCount): + (WebCore::ImageDecoderQt::frameBufferAtIndex): + (WebCore::ImageDecoderQt::forceLoadEverything): + * platform/image-decoders/ImageDecoder.cpp: + (WebCore::ImageDecoder::create): + (WebCore::RGBA32Buffer::clear): + (WebCore::RGBA32Buffer::setSize): + * platform/image-decoders/ImageDecoder.h: + (WebCore::RGBA32Buffer::): + (WebCore::ImageDecoder::ImageDecoder): + * platform/image-decoders/bmp/BMPImageDecoder.cpp: + (WebCore::BMPImageDecoder::BMPImageDecoder): + (WebCore::BMPImageDecoder::setData): + (WebCore::BMPImageDecoder::isSizeAvailable): + (WebCore::BMPImageDecoder::frameBufferAtIndex): + (WebCore::BMPImageDecoder::decode): + (WebCore::BMPImageDecoder::decodeHelper): + (WebCore::BMPImageDecoder::processFileHeader): + * platform/image-decoders/bmp/BMPImageDecoder.h: + (WebCore::BMPImageDecoder::readUint32): + * platform/image-decoders/bmp/BMPImageReader.cpp: + (WebCore::BMPImageReader::BMPImageReader): + (WebCore::BMPImageReader::decodeBMP): + (WebCore::BMPImageReader::readInfoHeaderSize): + (WebCore::BMPImageReader::processInfoHeader): + (WebCore::BMPImageReader::readInfoHeader): + (WebCore::BMPImageReader::isInfoHeaderValid): + (WebCore::BMPImageReader::processBitmasks): + (WebCore::BMPImageReader::processColorTable): + (WebCore::BMPImageReader::processRLEData): + (WebCore::BMPImageReader::processNonRLEData): + * platform/image-decoders/bmp/BMPImageReader.h: + (WebCore::BMPImageReader::readUint32): + (WebCore::BMPImageReader::pastEndOfImage): + (WebCore::BMPImageReader::readCurrentPixel): + (WebCore::BMPImageReader::getComponent): + (WebCore::BMPImageReader::getAlpha): + (WebCore::BMPImageReader::setI): + (WebCore::BMPImageReader::setRGBA): + * platform/image-decoders/gif/GIFImageDecoder.cpp: + (WebCore::GIFImageDecoder::GIFImageDecoder): + (WebCore::GIFImageDecoder::setData): + (WebCore::GIFImageDecoder::isSizeAvailable): + (WebCore::GIFImageDecoder::frameCount): + (WebCore::GIFImageDecoder::frameBufferAtIndex): + (WebCore::GIFImageDecoder::clearFrameBufferCache): + (WebCore::GIFImageDecoder::sizeNowAvailable): + (WebCore::GIFImageDecoder::haveDecodedRow): + (WebCore::GIFImageDecoder::frameComplete): + (WebCore::GIFImageDecoder::decode): + (WebCore::GIFImageDecoder::initFrameBuffer): + * platform/image-decoders/gif/GIFImageDecoder.h: + (WebCore::GIFImageDecoder::): + (WebCore::GIFImageDecoder::filenameExtension): + * platform/image-decoders/gif/GIFImageReader.cpp: + (GIFImageReader::do_lzw): + (GIFImageReader::read): + * platform/image-decoders/gif/GIFImageReader.h: + (GIFImageReader::~GIFImageReader): + * platform/image-decoders/ico/ICOImageDecoder.cpp: + (WebCore::ICOImageDecoder::ICOImageDecoder): + (WebCore::ICOImageDecoder::~ICOImageDecoder): + (WebCore::ICOImageDecoder::setData): + (WebCore::ICOImageDecoder::isSizeAvailable): + (WebCore::ICOImageDecoder::frameSizeAtIndex): + (WebCore::ICOImageDecoder::frameCount): + (WebCore::ICOImageDecoder::frameBufferAtIndex): + (WebCore::ICOImageDecoder::compareEntries): + (WebCore::ICOImageDecoder::setDataForPNGDecoderAtIndex): + (WebCore::ICOImageDecoder::decode): + (WebCore::ICOImageDecoder::decodeDirectory): + (WebCore::ICOImageDecoder::decodeAtIndex): + (WebCore::ICOImageDecoder::processDirectoryEntries): + (WebCore::ICOImageDecoder::readDirectoryEntry): + * platform/image-decoders/ico/ICOImageDecoder.h: + (WebCore::ICOImageDecoder::readUint16): + (WebCore::ICOImageDecoder::readUint32): + * platform/image-decoders/jpeg/JPEGImageDecoder.cpp: + (WebCore::): + (WebCore::JPEGImageReader::JPEGImageReader): + (WebCore::JPEGImageReader::skipBytes): + (WebCore::JPEGImageReader::decode): + (WebCore::error_exit): + (WebCore::fill_input_buffer): + (WebCore::term_source): + (WebCore::JPEGImageDecoder::setData): + (WebCore::JPEGImageDecoder::setSize): + (WebCore::JPEGImageDecoder::frameBufferAtIndex): + (WebCore::JPEGImageDecoder::jpegComplete): + (WebCore::JPEGImageDecoder::decode): + * platform/image-decoders/jpeg/JPEGImageDecoder.h: + (WebCore::JPEGImageDecoder::filenameExtension): + * platform/image-decoders/png/PNGImageDecoder.cpp: + (WebCore::decodingFailed): + (WebCore::decodingWarning): + (WebCore::headerAvailable): + (WebCore::rowAvailable): + (WebCore::pngComplete): + (WebCore::PNGImageReader::PNGImageReader): + (WebCore::PNGImageReader::close): + (WebCore::PNGImageReader::decode): + (WebCore::PNGImageReader::createInterlaceBuffer): + (WebCore::PNGImageDecoder::setData): + (WebCore::PNGImageDecoder::frameBufferAtIndex): + (WebCore::PNGImageDecoder::headerAvailable): + (WebCore::PNGImageDecoder::rowAvailable): + (WebCore::PNGImageDecoder::pngComplete): + (WebCore::PNGImageDecoder::decode): + * platform/image-decoders/png/PNGImageDecoder.h: + (WebCore::PNGImageDecoder::filenameExtension): + * platform/image-decoders/qt/RGBA32BufferQt.cpp: + (WebCore::RGBA32Buffer::setDecodedImage): + +2010-02-16 Csaba Osztrogonác <ossy@webkit.org> + + [Qt] Unreviewed buildfix. + + * WebCore.pro: Missing backslash added. + +2010-02-16 Mikhail Naganov <mnaganov@chromium.org> + + Reviewed by Pavel Feldman. + + Move JSC-specific wrappers for Profile and ProfileNode to bindings/js. + + https://bugs.webkit.org/show_bug.cgi?id=34848 + + * GNUmakefile.am: + * WebCore.gypi: + * WebCore.pro: + * WebCore.vcproj/WebCore.vcproj: + * WebCore.xcodeproj/project.pbxproj: + * bindings/js/JavaScriptProfile.cpp: Added. + (WebCore::profileCache): + (WebCore::getTitleCallback): + (WebCore::getHeadCallback): + (WebCore::getUniqueIdCallback): + (WebCore::focus): + (WebCore::exclude): + (WebCore::restoreAll): + (WebCore::finalize): + (WebCore::ProfileClass): + (WebCore::toJS): + * bindings/js/JavaScriptProfile.h: Added. + * bindings/js/JavaScriptProfileNode.cpp: Added. + (WebCore::profileNodeCache): + (WebCore::getFunctionName): + (WebCore::getURL): + (WebCore::getLineNumber): + (WebCore::getTotalTime): + (WebCore::getSelfTime): + (WebCore::getNumberOfCalls): + (WebCore::getChildren): + (WebCore::getVisible): + (WebCore::getCallUID): + (WebCore::finalize): + (WebCore::ProfileNodeClass): + (WebCore::toJS): + * bindings/js/JavaScriptProfileNode.h: Added. + * inspector/JavaScriptProfile.cpp: Removed. + * inspector/JavaScriptProfile.h: Removed. + * inspector/JavaScriptProfileNode.cpp: Removed. + * inspector/JavaScriptProfileNode.h: Removed. + +2010-02-16 Alexander Pavlov <apavlov@chromium.org> + + Reviewed by Pavel Feldman. + + Web Inspector: Elements Panel: Limit the number of initially loaded element children + https://bugs.webkit.org/show_bug.cgi?id=34421 + + Test: inspector/elements-panel-limited-children.html + + * English.lproj/localizedStrings.js: + * inspector/front-end/DOMAgent.js: + (WebInspector.DOMNode.prototype._insertChild): + * inspector/front-end/ElementsPanel.js: + (WebInspector.ElementsPanel.prototype.updateModifiedNodes): + * inspector/front-end/ElementsTreeOutline.js: + (WebInspector.ElementsTreeOutline.prototype.createTreeElementFor): + (WebInspector.ElementsTreeOutline.prototype.revealAndSelectNode): + (WebInspector.ElementsTreeElement): + (WebInspector.ElementsTreeElement.prototype.get expandedChildrenLimit): + (WebInspector.ElementsTreeElement.prototype.set expandedChildrenLimit): + (WebInspector.ElementsTreeElement.prototype.get expandedChildCount): + (WebInspector.ElementsTreeElement.prototype.showChild): + (WebInspector.ElementsTreeElement.prototype.insertChildElement): + (WebInspector.ElementsTreeElement.prototype.moveChild): + (WebInspector.ElementsTreeElement.prototype._updateChildren.updateChildrenOfNode): + (WebInspector.ElementsTreeElement.prototype._updateChildren): + (WebInspector.ElementsTreeElement.prototype.adjustCollapsedRange): + (WebInspector.ElementsTreeElement.prototype.handleLoadAllChildren): + (): + * inspector/front-end/inspector.css: + +2010-02-16 Ismail Donmez <ismail@namtrac.org> + + Reviewed by Pavel Feldman. + + Fix compilation with inspector disabled. + https://bugs.webkit.org/show_bug.cgi?id=32724 + + * rendering/RenderLayerBacking.cpp: + (WebCore::inspectorTimelineAgent): + +2010-02-16 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: turn off line wrapping in source view. + + https://bugs.webkit.org/show_bug.cgi?id=34935 + + * inspector/front-end/TextViewer.js: + (WebInspector.TextViewer.prototype.markAndRevealRange): + (WebInspector.TextViewer.prototype._paintLine): + * inspector/front-end/textViewer.css: + * inspector/front-end/utilities.js: + +2010-02-16 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: let search iterate over views in Resources + and keep the view in Scripts. + + https://bugs.webkit.org/show_bug.cgi?id=34968 + + * inspector/front-end/Panel.js: + (WebInspector.Panel.prototype.jumpToNextSearchResult): + (WebInspector.Panel.prototype.jumpToPreviousSearchResult): + (WebInspector.Panel.prototype.showSourceLineForURL): + (WebInspector.Panel.prototype.searchIteratesOverViews): + * inspector/front-end/ResourcesPanel.js: + (WebInspector.ResourcesPanel.prototype.get _resources): + (WebInspector.ResourcesPanel.prototype.searchIteratesOverViews): + * inspector/front-end/SourceView.js: + (WebInspector.SourceView.prototype.showingLastSearchResult): + * inspector/front-end/inspector.js: + (WebInspector.documentKeyDown): + (WebInspector.focusSearchField): + +2010-02-16 Noam Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Ariya Hidayat. + + [Qt] canvas clipping is buggy + https://bugs.webkit.org/show_bug.cgi?id=32405 + + Apparently the bug was in GraphicsContext::roundToDevicePixels, we + didn't take unto accounts rotation, so the device pixels were rounded + incorrectly. The new formula is a 1:1 copy from GraphicsContextCG so + it should be rather safe + + Test: http://glimr.rubyforge.org/cake/canvas.html#Polaroids now looks right + + * platform/graphics/qt/GraphicsContextQt.cpp: + (WebCore::GraphicsContext::roundToDevicePixels): Copy the formula from + GraphicsContextCG + +2010-02-16 Yury Semikhatsky <yurys@chromium.org> + + Not Reviewed, build fix. + + * platform/graphics/FloatRect.h: + (WebCore::FloatRect::center): make conversion from float to int explicit so that compiler + doesn't complain about that. + +2010-02-15 Dan Bernstein <mitz@apple.com> + + Reviewed by Simon Fraser. + + <rdar://problem/7645609> [webView selectionRect] API is broken for multicolumn layout + + Refine the fix for https://bugs.webkit.org/show_bug.cgi?id=34923 by using the center of + a quad’s bounding box, rather than its top left, as the reference point passed to + offsetFromContainer(). This ensures that if a sliver off the top of the selection rect is in + one column, but most of it is on another column, the single rect we return will be for the + second column. + + * platform/graphics/FloatRect.h: + (WebCore::FloatRect::center): Added. + * rendering/RenderObject.cpp: + (WebCore::RenderObject::localToContainerQuad): Use the center instead of the top left. + +2010-02-15 MORITA Hajime <morrita@gmail.com> + + Reviewed by Nikolas Zimmermann. + + SVG text refactor: reduce paint specific callbacks on SVGTextChunkWalker + + https://bugs.webkit.org/show_bug.cgi?id=34831 + + No new tests, no change of functionality. + + * rendering/SVGCharacterLayoutInfo.h: + (WebCore::SVGTextChunkWalker::SVGTextChunkWalker): + Removed setupBackground(), setupFill(), setupFillSelection(), + setupStroke(), setupStrokeSelection(), setupForeground() + and associated member variables. + + * rendering/SVGRootInlineBox.cpp: + (WebCore::SVGRootInlineBoxPaintWalker::setupBackground): + renamed from chunkSetupBackgroundCallback. + (WebCore::SVGRootInlineBoxPaintWalker::setupFill): + renamed from chunkSetupFillCallback. + (WebCore::SVGRootInlineBoxPaintWalker::setupFillSelection): + renamed from chunkSetupFillSelectionCallback. + (WebCore::SVGRootInlineBoxPaintWalker::setupStroke): + renamed from chunkSetupStrokeCallback. + (WebCore::SVGRootInlineBoxPaintWalker::setupStrokeSelection): + renamed from chunkSetupStrokeSelectionCallback. + (WebCore::SVGRootInlineBoxPaintWalker::setupForeground): + renamed from chunkSetupForegroundCallback. + (WebCore::SVGRootInlineBoxPaintWalker::paintChunk): + renamed from chunkPortionCallback. + (WebCore::SVGRootInlineBoxPaintWalker::chunkPortionCallback): + extracted from walkTextChunks. + (WebCore::SVGRootInlineBox::paint): + follow SVGTextChunkWalker change. + (WebCore::SVGRootInlineBox::walkTextChunks): + moved paint some specific code to SVGRootInlineBoxPaintWalker::chunkPortionCallback(). + +2010-02-15 Dan Bernstein <mitz@apple.com> + + Try to fix the Chromium build. + + * rendering/RenderThemeChromiumMac.mm: + (WebCore::RenderThemeChromiumMac::convertToPaintingRect): + +2010-02-14 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=33731 + Many false leaks in release builds due to PtrAndFlags + + PtrAndFlags has now been removed; remove forwarding header. + + * ForwardingHeaders/wtf/PtrAndFlags.h: Removed. + +2010-02-15 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Bug 34952 - String lengths in UString should be unsigned. + This matches WebCore::StringImpl, and better unifies behaviour throughout JSC. + + * bindings/js/JSDOMWindowCustom.cpp: + (WebCore::JSDOMWindow::atob): + (WebCore::JSDOMWindow::btoa): + +2010-02-15 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Reviewed by Xan Lopez. + + [GTK] Crashes when going back to a page that has data: URIs, with page cache enabled + https://bugs.webkit.org/show_bug.cgi?id=34944 + + Set the URL in the newly created response, when parsing data: + URIs. + + Test: fast/harness/page-cache-crash-on-data-urls.html + + * platform/network/soup/ResourceHandleSoup.cpp: + (WebCore::parseDataUrl): + +2010-02-15 Dan Bernstein <mitz@apple.com> + + Reviewed by Simon Fraser. + + <rdar://problem/7647300> Incorrect client rects for blocks the span multiple columns and their descendants + https://bugs.webkit.org/show_bug.cgi?id=34923 + + Test: fast/multicol/client-rects.html + + In column layout, a different transform applies to different points in + the block and its descendants, depending on their y coordinate within the + block. offsetFromContainer() used to return the offset that applied to + the origin. With this change, it returns the offset that applies to a + given reference point. When mapping a quad from local to absolute + coordinates, the top left of the quad’s bounding box is used as that + reference point. + + * editing/SelectionController.cpp: + (WebCore::SelectionController::layout): Pass the caret’s origin as the + reference point to offsetFromContainer(). + * rendering/RenderBlock.cpp: + (WebCore::RenderBlock::adjustForColumns): Adds the offset between the + given point and its image under the column paint-time transform to the + given offset. Used by offsetFromContainer() where it had previously used + adjustRectForColumns(), which takes a rect and operates less efficiently. + * rendering/RenderBlock.h: + * rendering/RenderBox.cpp: + (WebCore::RenderBox::mapLocalToContainer): Pass the transformed point as + the reference point to offsetFromContainer(). + (WebCore::RenderBox::mapAbsoluteToLocalPoint): Pass a point to + offsetFromContainer(). + (WebCore::RenderBox::offsetFromContainer): Use adjustForColumns() instead + of adjustRectForColumns(), and use the reference point to get the right + adjustment for the point of interest, instead of the origin, in case this + box spans multiple columns. + * rendering/RenderBox.h: + * rendering/RenderInline.cpp: + (WebCore::RenderInline::offsetFromContainer): Ditto. Actually apply the + column offset to the computation, which previously this function didn’t + do. + (WebCore::RenderInline::mapLocalToContainer): Pass the transformed point + as the reference point to offsetFromContainer(). + (WebCore::RenderInline::mapAbsoluteToLocalPoint): Pass a point to + offsetFromContainer(). + * rendering/RenderInline.h: + * rendering/RenderObject.cpp: + (WebCore::RenderObject::mapLocalToContainer): Apply column adjustment, + based on the reference point, to the transform if needed. + (WebCore::RenderObject::localToContainerQuad): Initialize the + TransformState with the top left corner of the quad’s bounding box. It + is later used as the reference point when deciding on which column to + base the calculations. + (WebCore::RenderObject::offsetFromContainer): Adjust for columns. + (WebCore::RenderObject::offsetFromAncestorContainer): Pass the origin + as the reference point to offsetFromContainer(). + * rendering/RenderObject.h: + (WebCore::RenderObject::adjustForColumns): Added. + * rendering/RenderTableCell.cpp: + (WebCore::RenderTableCell::offsetFromContainer): Pass the reference + point through. + * rendering/RenderTableCell.h: + * rendering/RenderText.cpp: + (WebCore::RenderText::absoluteRectsForRange): Map (the origin of) each + rect to absolute coordinates individually. + * rendering/RenderThemeMac.mm: + (WebCore::RenderThemeMac::convertToPaintingRect): Pass a point to + offsetFromContainer(). + +2010-02-12 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Kevin Decker. + + <rdar://problem/7130641> Browser objects identity is not preserved by Safari + + Test: plugins/netscape-browser-object-identity.html + + * bridge/runtime_root.h: (JSC::Bindings::RootObject::addInvalidationCallback): + RootObject can now call out during invalidation, making it possible for other code to know + when this happens. + + * bridge/runtime_root.cpp: + (JSC::Bindings::RootObject::InvalidationCallback::~InvalidationCallback): Empty destructor, + in cpp file since it's virtual. + (JSC::Bindings::RootObject::invalidate): Invoke invalidation callbacks. + + * bridge/NP_jsobject.cpp: + (ObjectMap): Keep a JSObject->NPObject map for each RootObject. It somewhat cleaner to + keep it outside RootObject, because (1) it is agnostic of what kinds of objects can wrap + JSObject, and (2) out of process NPAPI implementation also keeps its corresponding map + separately, due to supporting per-instance granularity (as opposed to per-RootObject here). + (jsDeallocate): Remove the corresponding map entry. + (_NPN_CreateScriptObject): Try to fetch existing object from the map, incrementing refcount. + +2010-02-15 Philippe Normand <pnormand@igalia.com> + + Rubber-stamped by Gustavo Noronha Silva. + + Removed redefine of LOG_VERBOSE. This should not have commited in + the first place. + + * platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp: + +2010-02-15 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: incorrect syntax highlighting as HTML in a script tag. + We were preserving initial lexer state upon entering other tags while in <script> + but were not doing it for <script tag itself. As a result, nested script + tags were failing to highlight. + + https://bugs.webkit.org/show_bug.cgi?id=34934 + + * inspector/front-end/SourceHTMLTokenizer.js: + (WebInspector.SourceHTMLTokenizer.prototype.nextToken): + * inspector/front-end/SourceHTMLTokenizer.re2js: + +2010-02-15 Brady Eidson <beidson@apple.com> + + Reviewed by Dan Bernstein. + + Add a progress-indicator logging channel to WebCore, and convert the old WebKit Logging + messages over to WebCore-style. + + No new tests. (Logging changes only) + + * loader/ProgressTracker.cpp: + (WebCore::ProgressTracker::progressStarted): + (WebCore::ProgressTracker::progressCompleted): + (WebCore::ProgressTracker::finalProgressComplete): + (WebCore::ProgressTracker::incrementProgress): + + * platform/Logging.cpp: + (WebCore::): + (WebCore::getChannelFromName): + * platform/Logging.h: + +2010-02-15 Noam Rosenthal <noam.rosenthal@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] QtWebkit bridge: enable passing a QWebElement to a signal/slot/property + https://bugs.webkit.org/show_bug.cgi?id=34901 + + When a signal/slot/property is of type QWebElement, it can seamlessly + connect with JS objects that hold a WebCore element. + + New tests, see WebKit/qt/ChangeLog + + * bridge/qt/qt_runtime.cpp: + (JSC::Bindings::QtWebElementRuntime::create): A proxy to QWebElement + constructor + (JSC::Bindings::QtWebElementRuntime::get): A proxy to + QWebElement::element + (JSC::Bindings::convertValueToQVariant): handle QWebElement + (JSC::Bindings::convertQVariantToValue): handle QWebElement + +2010-02-15 Pavel Feldman <pfeldman@chromium.org> + + Not reviewed, Chromium build fix (force conversion of property names to + strings in Web Inspector's injected script). + + * inspector/front-end/InjectedScript.js: + (injectedScriptConstructor): + +2010-02-15 Pavel Feldman <pfeldman@chromium.org> + + Not reviewed: touch InspectorController in order to kick win bot tests + with new injected script contents. + + * inspector/InspectorController.cpp: + +2010-02-14 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: highlight actual search match in elements panel. + + https://bugs.webkit.org/show_bug.cgi?id=34251 + + * inspector/front-end/ElementsPanel.js: + (WebInspector.ElementsPanel.prototype.searchCanceled): + (WebInspector.ElementsPanel.prototype.performSearch): + (WebInspector.ElementsPanel.prototype.addNodesToSearchResult): + (WebInspector.ElementsPanel.prototype.jumpToNextSearchResult): + (WebInspector.ElementsPanel.prototype.jumpToPreviousSearchResult): + (WebInspector.ElementsPanel.prototype._highlightCurrentSearchResult): + (WebInspector.ElementsPanel.prototype._hideSearchHighlights): + * inspector/front-end/InjectedScript.js: + * inspector/front-end/SourceFrame.js: + (WebInspector.SourceFrame.prototype.findSearchMatches): + * inspector/front-end/TextViewer.js: + (WebInspector.TextViewer.prototype._paintLine): + * inspector/front-end/textViewer.css: + * inspector/front-end/utilities.js: + +2010-02-14 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: XPathResult objects are not expanded in console. + + https://bugs.webkit.org/show_bug.cgi?id=34926 + + * inspector/front-end/InjectedScript.js: + (injectedScriptConstructor): + * inspector/front-end/ObjectPropertiesSection.js: + (WebInspector.ObjectPropertiesSection.prototype.updateProperties): + (WebInspector.ObjectPropertiesSection.CompareProperties): + (WebInspector.ObjectPropertyTreeElement.prototype.update): + * inspector/front-end/Section.js: + (WebInspector.Section): + * inspector/front-end/inspector.css: + +2010-02-10 Philippe Normand <pnormand@igalia.com> + + Reviewed by Gustavo Noronha Silva. + + [Gtk] wrong video aspect ratio + https://bugs.webkit.org/show_bug.cgi?id=34790 + + Fixed natural size calculation regarding pixel aspect ratio and + display aspect ratio. + + Test: media/video-display-aspect-ratio.html + + * platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp: + (WebCore::greatestCommonDivisor): + (WebCore::MediaPlayerPrivate::naturalSize): + +2010-02-14 Adam Barth <abarth@webkit.org> + + Reviewed by Darin Adler. + + HTML5 iframe sandbox bypass of window.top.location navigation via <form target="_top"> + https://bugs.webkit.org/show_bug.cgi?id=33277 + + submitForm wasn't respecting shouldAllowNavigation. Instead of calling + the wrapper function, we need to call shouldAllowNavigation because we + need to handle the "frame not found" case differently than the + "navigation denied" case. + + Test: http/tests/security/sandboxed-iframe-form-top.html + + * loader/FrameLoader.cpp: + (WebCore::FrameLoader::submitForm): + +2010-02-14 Kent Tamura <tkent@chromium.org> + + No review. Touch RenderRuny*.cpp to fix Chromium/Windows build bot. + + * rendering/RenderRuby.cpp: Add a comment for #endf. + * rendering/RenderRubyBase.cpp: Add a comment for #endf. + * rendering/RenderRubyRun.cpp: Add a comment for #endf. + * rendering/RenderRubyText.cpp: Add a comment for #endf. + +2010-02-13 Pavel Feldman <pfeldman@chromium.org> + + Reviewed by Timothy Hatcher. + + Web Inspector: cache created row, span and text elements + in TextView to improve scroller performance on debug build. + + https://bugs.webkit.org/show_bug.cgi?id=34921 + + * inspector/front-end/SourceFrame.js: + (WebInspector.SourceFrame.prototype.set visible): + * inspector/front-end/TextViewer.js: + (WebInspector.TextViewer): + (WebInspector.TextViewer.prototype.freeCachedElements): + (WebInspector.TextViewer.prototype._buildChunks): + (WebInspector.TextViewer.prototype._makeLineAChunk): + (WebInspector.TextViewer.prototype._paintLine): + (WebInspector.TextViewer.prototype._releaseLines): + (WebInspector.TextViewer.prototype._appendSpan): + (WebInspector.TextViewer.prototype._appendTextNode): + (WebInspector.TextChunk): + (WebInspector.TextChunk.prototype.set expanded): + (WebInspector.TextChunk.prototype._lineNumberText): + (WebInspector.TextChunk.prototype._createRow): + +2010-02-13 Kent Tamura <tkent@chromium.org> + + Reviewed by Darin Adler. + + Refactor parsing/serialization functions in HTMLInputElement. + https://bugs.webkit.org/show_bug.cgi?id=34852 + + - Rename formStringToDouble() to parseToDoubleForNumberType() + - Rename formStringToDateComponents() to parseToDateComponents() + - Rename formStringFromDouble() to serializeForNumberType() + - Add serializeForDateTimeTypes() + The code is moved from setValueAsDate() and setDateValue(). + - Add serialize() + + parseToDouble() is the top-level function to parse a + type-dependent string and return a double + value. parseToDoubleForNumber() and parseToDateComponents() + functions are helper functions for it. serialize() is the + top-level function to serialize a double value to a type-dependent + string, and serializeForNumberType() and + serializeForDateTimeTypes() are helper functions for it. + + No tests because of no functional changes. + + * html/HTMLInputElement.cpp: + (WebCore::HTMLInputElement::stepMismatch): + (WebCore::HTMLInputElement::getAllowedValueStep): + (WebCore::HTMLInputElement::parseToDouble): + (WebCore::HTMLInputElement::valueAsDate): + (WebCore::HTMLInputElement::setValueAsDate): + (WebCore::HTMLInputElement::setValueAsNumber): + (WebCore::HTMLInputElement::serializeForDateTimeTypes): + (WebCore::HTMLInputElement::serialize): + (WebCore::HTMLInputElement::serializeForNumberType): + (WebCore::HTMLInputElement::parseToDoubleForNumberType): + (WebCore::HTMLInputElement::parseToDateComponents): + * html/HTMLInputElement.h: + * html/ValidityState.cpp: + (WebCore::ValidityState::typeMismatch): + * rendering/RenderSlider.cpp: + (WebCore::SliderRange::valueFromElement): + (WebCore::RenderSlider::updateFromElement): + (WebCore::RenderSlider::setValueForPosition): + +2010-01-05 Ojan Vafai <ojan@chromium.org> + + Reviewed by Dan Bernstein. + + Improve text control intrinsic widths. + https://bugs.webkit.org/show_bug.cgi?id=25566 + https://bugs.webkit.org/show_bug.cgi?id=25581 + https://bugs.webkit.org/show_bug.cgi?id=25958 + + For Mac fonts that have invalid avgCharWidth entries in the OS/2 table, + fallback to the Safari 4- behavior of using the width of a zero. For other + fonts, make Mac match Windows (and thus IE) metrics. + + Lucida Grande is hard-coded to match MS Shell Dlg for inputs and + Courier New for textareas in order to match Safari Win, Firefox and, in + some cases IE (IE uses different default fonts depending on encoding). + + The only case where we still don't match Windows is if no font-size is + set. The default font-size for form controls on the Mac is smaller and + thus text-control widths will be slightly smaller. + + No new tests. Covered by existing tests. + + * platform/graphics/mac/SimpleFontDataMac.mm: + (WebCore::SimpleFontData::platformCharWidthInit): + * rendering/RenderTextControl.cpp: + (WebCore::): + (WebCore::RenderTextControl::hasValidAvgCharWidth): + (WebCore::RenderTextControl::getAvgCharWidth): + (WebCore::RenderTextControl::calcPrefWidths): + * rendering/RenderTextControl.h: + (WebCore::RenderTextControl::scaleEmToUnits): + * rendering/RenderTextControlMultiLine.cpp: + (WebCore::RenderTextControlMultiLine::getAvgCharWidth): + * rendering/RenderTextControlMultiLine.h: + * rendering/RenderTextControlSingleLine.cpp: + (WebCore::RenderTextControlSingleLine::getAvgCharWidth): + (WebCore::RenderTextControlSingleLine::preferredContentWidth): + * rendering/RenderTextControlSingleLine.h: + +2010-02-11 Ariya Hidayat <ariya.hidayat@gmail.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Unnecessary QBrush construction for doing a solid color stroke + https://bugs.webkit.org/show_bug.cgi?id=34874 + + Use the similar trick like in r54347, i.e. use the special brush for + solid color to avoid expensive QBrush constructor. + + * platform/graphics/qt/GraphicsContextQt.cpp: + (WebCore::GraphicsContext::setPlatformStrokeColor): + +2010-02-11 Darin Fisher <darin@chromium.org> + + Reviewed by Jeremy Orlow. + + Pass the Document along to the ChromiumBridge cookie methods. + + https://bugs.webkit.org/show_bug.cgi?id=34878 + + * platform/chromium/ChromiumBridge.h: + * platform/network/chromium/CookieJarChromium.cpp: + (WebCore::setCookies): + (WebCore::cookies): + (WebCore::cookiesEnabled): + (WebCore::getRawCookies): + (WebCore::deleteCookie): + +2010-02-12 Eric Seidel <eric@webkit.org> + + No review, rolling out r54694. + http://trac.webkit.org/changeset/54694 + https://bugs.webkit.org/show_bug.cgi?id=34633 + + This appears to have caused crashes on the Leopard bot. See + bug 34898. + + * websockets/ThreadableWebSocketChannelClientWrapper.h: + (WebCore::ThreadableWebSocketChannelClientWrapper::didClose): + * websockets/WebSocket.cpp: + (WebCore::WebSocket::WebSocket): + (WebCore::WebSocket::send): + (WebCore::WebSocket::close): + (WebCore::WebSocket::bufferedAmount): + (WebCore::WebSocket::didConnect): + (WebCore::WebSocket::didClose): + * websockets/WebSocket.h: + * websockets/WebSocketChannel.cpp: + (WebCore::WebSocketChannel::WebSocketChannel): + (WebCore::WebSocketChannel::send): + (WebCore::WebSocketChannel::bufferedAmount): + (WebCore::WebSocketChannel::didClose): + * websockets/WebSocketChannel.h: + * websockets/WebSocketChannelClient.h: + (WebCore::WebSocketChannelClient::didClose): + * websockets/WorkerThreadableWebSocketChannel.cpp: + (WebCore::workerContextDidClose): + (WebCore::WorkerThreadableWebSocketChannel::Peer::didClose): + * websockets/WorkerThreadableWebSocketChannel.h: + +2010-02-12 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + Workers' EventListeners should be removed before JSGlobalData is destroyed + https://bugs.webkit.org/show_bug.cgi?id=34903 + + (Patch co-developed with Alexey Proskuryakov). + + Since http://trac.webkit.org/changeset/54460 the EventListeners registered by a + worker thread are not removed until after the thread's JSGlobalData has been + destroyed. This is slightly worrisome since the JSEventListener contains + JSObject*s, which will be dangling once the heap is destroyed. The + JSEventListeners may also reference the worker thread's normal world, which + again it makes no sense to keep around after the JSGlobalData is freed. + + Remove all event listeners immediately prior to tearing down the JSGlobalData. + + https://bugs.webkit.org/show_bug.cgi?id=34728 addressed the symptoms of this + problem, and it is probably cleaner to make the client data's normal world no + longer be a member (since it is a ref-counted object), however they should be + no requirement to 'detatch' – it makes no sense for anyone to be referencing + the world after the JSGlobalData has gone away (the world's purpose is to hold + wrapper objects in the JSGlobalData's heap). Keep the restructuring that makes + the normal world no longer be a member, but remove the detach mechanism this + patch added & replace with stronger ASSERTs. + + * bindings/js/JSDOMBinding.cpp: + (WebCore::DOMWrapperWorld::~DOMWrapperWorld): + * bindings/js/JSDOMBinding.h: + (WebCore::WebCoreJSClientData::~WebCoreJSClientData): + * workers/WorkerThread.cpp: + (WebCore::WorkerThreadShutdownStartTask::performTask): + +2010-02-12 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + https://bugs.webkit.org/show_bug.cgi?id=33731 + Remove uses of PtrAndFlags from WebCore::StringImpl. + + These break the OS X Leaks tool. Use a bits stolen from the refCount to hold the + 'InTable' and 'HasTerminatingNullCharacter' flags, along with the string type + (fixes a leak where the string data is allocated at the address (this + 1), and is + misinterpreted as being an internal buffer). + + * WebCore.base.exp: + * platform/text/StringImpl.cpp: + (WebCore::StringImpl::StringImpl): + (WebCore::StringImpl::~StringImpl): + (WebCore::StringImpl::create): + (WebCore::StringImpl::createWithTerminatingNullCharacter): + (WebCore::StringImpl::crossThreadString): + (WebCore::StringImpl::sharedBuffer): + * platform/text/StringImpl.h: + (WebCore::StringImpl::): + (WebCore::StringImpl::hasTerminatingNullCharacter): + (WebCore::StringImpl::inTable): + (WebCore::StringImpl::setInTable): + (WebCore::StringImpl::ref): + (WebCore::StringImpl::deref): + (WebCore::StringImpl::hasOneRef): + (WebCore::StringImpl::operator new): + (WebCore::StringImpl::bufferOwnership): + * storage/OriginUsageRecord.cpp: + (WebCore::OriginUsageRecord::addDatabase): + (WebCore::OriginUsageRecord::markDatabase): + +2010-02-12 Nikolas Zimmermann <nzimmermann@rim.com> + + Reviewed by Dirk Schulze. + + Repaint bug on Text selection in foreignObject + https://bugs.webkit.org/show_bug.cgi?id=16939 + + Tests: svg/overflow/overflow-on-foreignObject.svg + svg/text/foreignObject-text-clipping-bug.xml + + Selecting text contained in <foreignObject> leads to artefacts. Same for zooming/panning. + RenderForeignObject contained old legacy code returning FloatRect() for repaintRectInLocalCoordinates, + which is obviously wrong. Fixing that leads to even more problems, as the underlying RenderBlock + did not reflect the x/y translation set on the <foreignObject>. This is problematic, as laying out + positioned objects in the XHTML subtree depends on proper size/location values of the frameRect. + + Correctly clip on overflow="hidden". overflow="scroll" & friends are not yet supported, see lengthy + comment in RenderSVGBlock why we either need RenderLayer for RenderForeignObject or need to rework + overflow handling to avoid RenderLayer. + + SVGForeignObjectElement uses a hacky custom solution to synchronize CSS width/height properties with + the SVG width/height attributes. Remove all of that code and just implement calcWidth/calcHeight in + RenderForeignObject, grabbing the right values from SVGForeignObjectElement::width/height upon layout. + + * rendering/RenderForeignObject.cpp: + (WebCore::RenderForeignObject::paint): Clip properly to the actual bounds of the foreignObject, respecting that x/y translation is handled by RenderBlock now. + (WebCore::RenderForeignObject::clippedOverflowRectForRepaint): Added missing function, forward to SVGRenderBase just like all other SVG renderers. + (WebCore::RenderForeignObject::computeRectForRepaint): Remove manual implementation, forward to SVGRenderBase. + (WebCore::RenderForeignObject::localToParentTransform): Respect x/y translation here _after_ applying localTransform(). + (WebCore::RenderForeignObject::calcWidth): Override RenderBlock::calcWidth to grab width() from SVGForeignObjectElement. + (WebCore::RenderForeignObject::calcHeight): Override RenderBlock::calcHeight to grab height() from SVGForeignObjectElement. + (WebCore::RenderForeignObject::layout): Calculate viewport once and cache it. Push x/y location down to RenderBlock - analogous to RenderSVGText. + (WebCore::RenderForeignObject::nodeAtFloatPoint): Adapt to x/y translation changes (map through localTransform, not localToParentTransform). Respect overflow clipping. + (WebCore::RenderForeignObject::mapLocalToContainer): Set useTransforms=true, to avoid assertions when selecting text in foreign objects. + * rendering/RenderForeignObject.h: + (WebCore::RenderForeignObject::objectBoundingBox): Return cached m_viewport. + (WebCore::RenderForeignObject::strokeBoundingBox): Ditto. + (WebCore::RenderForeignObject::repaintRectInLocalCoordinates): Ditto. + * rendering/RenderSVGBlock.cpp: + (WebCore::RenderSVGBlock::setStyle): Cleanup code, move setHasOverflowClip() overrides in updateBoxModelInfoFromStyle where it belongs. + (WebCore::RenderSVGBlock::updateBoxModelInfoFromStyle): Added to force setting setHasOverflowClip(false). + * rendering/RenderSVGBlock.h: + * svg/SVGForeignObjectElement.cpp: Kill a lot of custom code - it was just plain wrong to utilize CSS to push width/height information down to RenderBlock. + (WebCore::SVGForeignObjectElement::svgAttributeChanged): + 2010-02-12 Dan Bernstein <mitz@apple.com> Reviewed by Simon Fraser. @@ -152,6 +3012,31 @@ * websockets/WebSocketHandshake.cpp: (WebCore::WebSocketHandshake::clientHandshakeMessage): use cookieRequestHeaderFieldValue() instead of cookies() to include HttpOnly cookies. +2010-02-16 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + Reviewed by Gustavo Noronha Silva. + + Notify about size changes in the WebKit GStreamer source. + + https://bugs.webkit.org/show_bug.cgi?id=34881 + + * platform/graphics/gtk/WebKitWebSourceGStreamer.cpp: + (webkit_web_src_init): + (StreamingClient::didReceiveResponse): + * platform/graphics/gtk/WebKitWebSourceGStreamer.h: + This makes sure that other GStreamer elements know about the + size and on-disk buffering actually works. + Only notify about size changes if gst-plugins-base before + 0.10.27 is used, because from that version onwards this is + automatically handled. + + If appsrc 0.10.27 or later is used, set the min-percent property + to 20% to allow more time to pass between the need-data signal + and starvation of the pipeline. + + Also reset the size when stopping the source and send EOS + on seeking failures. + 2010-02-11 Ariya Hidayat <ariya.hidayat@gmail.com> Reviewed by Kenneth Rohde Christiansen. diff --git a/WebCore/English.lproj/localizedStrings.js b/WebCore/English.lproj/localizedStrings.js Binary files differindex 9196692..65d9528 100644 --- a/WebCore/English.lproj/localizedStrings.js +++ b/WebCore/English.lproj/localizedStrings.js diff --git a/WebCore/ForwardingHeaders/wtf/PtrAndFlags.h b/WebCore/ForwardingHeaders/wtf/PtrAndFlags.h deleted file mode 100644 index bb6ed9a..0000000 --- a/WebCore/ForwardingHeaders/wtf/PtrAndFlags.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef WebCore_FWD_PtrAndFlags_h -#define WebCore_FWD_PtrAndFlags_h -#include <JavaScriptCore/PtrAndFlags.h> -#endif - diff --git a/WebCore/GNUmakefile.am b/WebCore/GNUmakefile.am index e0c9dc6..17fe33f 100644 --- a/WebCore/GNUmakefile.am +++ b/WebCore/GNUmakefile.am @@ -465,6 +465,10 @@ webcore_sources += \ WebCore/bindings/js/JSXSLTProcessorConstructor.cpp \ WebCore/bindings/js/JSXSLTProcessorConstructor.h \ WebCore/bindings/js/JSXSLTProcessorCustom.cpp \ + WebCore/bindings/js/JavaScriptProfile.cpp \ + WebCore/bindings/js/JavaScriptProfile.h \ + WebCore/bindings/js/JavaScriptProfileNode.cpp \ + WebCore/bindings/js/JavaScriptProfileNode.h \ WebCore/bindings/js/ScheduledAction.cpp \ WebCore/bindings/js/ScheduledAction.h \ WebCore/bindings/js/ScriptArray.cpp \ @@ -1224,10 +1228,6 @@ webcore_sources += \ WebCore/inspector/JavaScriptDebugListener.h \ WebCore/inspector/JavaScriptDebugServer.cpp \ WebCore/inspector/JavaScriptDebugServer.h \ - WebCore/inspector/JavaScriptProfile.cpp \ - WebCore/inspector/JavaScriptProfile.h \ - WebCore/inspector/JavaScriptProfileNode.cpp \ - WebCore/inspector/JavaScriptProfileNode.h \ WebCore/inspector/TimelineRecordFactory.cpp \ WebCore/inspector/TimelineRecordFactory.h \ WebCore/loader/Cache.cpp \ @@ -2990,6 +2990,9 @@ webcore_sources += \ WebCore/rendering/RenderSVGInlineText.h \ WebCore/rendering/RenderSVGModelObject.cpp \ WebCore/rendering/RenderSVGModelObject.h \ + WebCore/rendering/RenderSVGResource.h \ + WebCore/rendering/RenderSVGResourceMasker.cpp \ + WebCore/rendering/RenderSVGResourceMasker.h \ WebCore/rendering/RenderSVGRoot.cpp \ WebCore/rendering/RenderSVGRoot.h \ WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp \ @@ -3332,8 +3335,6 @@ webcore_sources += \ WebCore/svg/graphics/SVGResourceListener.h \ WebCore/svg/graphics/SVGResourceMarker.cpp \ WebCore/svg/graphics/SVGResourceMarker.h \ - WebCore/svg/graphics/SVGResourceMasker.cpp \ - WebCore/svg/graphics/SVGResourceMasker.h \ WebCore/svg/graphics/filters/SVGDistantLightSource.h \ WebCore/svg/graphics/filters/SVGFEConvolveMatrix.cpp \ WebCore/svg/graphics/filters/SVGFEConvolveMatrix.h \ diff --git a/WebCore/WebCore.base.exp b/WebCore/WebCore.base.exp index a0a5262..2afdd34 100644 --- a/WebCore/WebCore.base.exp +++ b/WebCore/WebCore.base.exp @@ -144,7 +144,6 @@ __ZN7WebCore10StringImpl7ustringEv __ZN7WebCore10StringImpl8endsWithEPS0_b __ZN7WebCore10StringImplD1Ev __ZN7WebCore10StringImplcvP8NSStringEv -__ZN7WebCore10StringImpldlEPv __ZN7WebCore10handCursorEv __ZN7WebCore10setCookiesEPNS_8DocumentERKNS_4KURLERKNS_6StringE __ZN7WebCore11BitmapImageC1EP7CGImagePNS_13ImageObserverE @@ -495,6 +494,7 @@ __ZN7WebCore4Page14setMediaVolumeEf __ZN7WebCore4Page15addSchedulePairEN3WTF10PassRefPtrINS_12SchedulePairEEE __ZN7WebCore4Page15backForwardListEv __ZN7WebCore4Page15didMoveOnscreenEv +__ZN7WebCore4Page16setCanStartMediaEb __ZN7WebCore4Page16setDefersLoadingEb __ZN7WebCore4Page17willMoveOffscreenEv __ZN7WebCore4Page18removeSchedulePairEN3WTF10PassRefPtrINS_12SchedulePairEEE @@ -653,7 +653,6 @@ __ZN7WebCore8Settings23setEditableLinkBehaviorENS_20EditableLinkBehaviorE __ZN7WebCore8Settings23setLoadDeferringEnabledEb __ZN7WebCore8Settings23setNeedsTigerMailQuirksEb __ZN7WebCore8Settings23setPluginAllowedRunTimeEj -__ZN7WebCore8Settings28setFrameSetFlatteningEnabledEb __ZN7WebCore8Settings23setUsesEncodingDetectorEb __ZN7WebCore8Settings24setApplicationChromeModeEb __ZN7WebCore8Settings24setTextAreasAreResizableEb @@ -669,8 +668,10 @@ __ZN7WebCore8Settings27setFTPDirectoryTemplatePathERKNS_6StringE __ZN7WebCore8Settings27setLoadsImagesAutomaticallyEb __ZN7WebCore8Settings27setLocalStorageDatabasePathERKNS_6StringE __ZN7WebCore8Settings28setForceFTPDirectoryListingsEb +__ZN7WebCore8Settings28setFrameSetFlatteningEnabledEb __ZN7WebCore8Settings29setAuthorAndUserStylesEnabledEb __ZN7WebCore8Settings29setWebArchiveDebugModeEnabledEb +__ZN7WebCore8Settings30setAllowFileAccessFromFileURLsEb __ZN7WebCore8Settings31setShrinksStandaloneImagesToFitEb __ZN7WebCore8Settings32setAcceleratedCompositingEnabledEb __ZN7WebCore8Settings32setNeedsAdobeFrameReloadingQuirkEb @@ -712,6 +713,9 @@ __ZN7WebCore9FrameView23updateCanHaveScrollbarsEv __ZN7WebCore9FrameView29forceLayoutWithPageWidthRangeEffb __ZN7WebCore9FrameView29setShouldUpdateWhileOffscreenEb __ZN7WebCore9FrameView29syncCompositingStateRecursiveEv +__ZNK7WebCore9FrameView20isSoftwareRenderableEv +__ZN7WebCore9FrameView16setPaintBehaviorEj +__ZNK7WebCore9FrameView13paintBehaviorEv __ZN7WebCore9FrameView6createEPNS_5FrameE __ZN7WebCore9FrameView6createEPNS_5FrameERKNS_7IntSizeE __ZN7WebCore9HTMLNames10listingTagE diff --git a/WebCore/WebCore.gyp/WebCore.gyp b/WebCore/WebCore.gyp/WebCore.gyp index e40da56..0c8d035 100644 --- a/WebCore/WebCore.gyp/WebCore.gyp +++ b/WebCore/WebCore.gyp/WebCore.gyp @@ -741,9 +741,6 @@ '../dom/StaticStringList.cpp', '../loader/icon/IconFetcher.cpp', '../loader/UserStyleSheetLoader.cpp', - '../platform/graphics/GraphicsLayer.cpp', - '../platform/graphics/RenderLayerBacking.cpp', - '../platform/graphics/RenderLayerCompositor.cpp', # We use a multi-process version from the WebKit API. '../dom/default/PlatformMessagePortChannel.cpp', @@ -959,6 +956,7 @@ '../platform/graphics/skia/FloatPointSkia.cpp', '../platform/graphics/skia/FloatRectSkia.cpp', '../platform/graphics/skia/GradientSkia.cpp', + '../platform/graphics/skia/GraphicsContext3DSkia.cpp', '../platform/graphics/skia/GraphicsContextSkia.cpp', '../platform/graphics/skia/ImageBufferSkia.cpp', '../platform/graphics/skia/ImageSkia.cpp', diff --git a/WebCore/WebCore.gypi b/WebCore/WebCore.gypi index 63edea7..b8316cf 100644 --- a/WebCore/WebCore.gypi +++ b/WebCore/WebCore.gypi @@ -620,6 +620,10 @@ 'bindings/js/JSXSLTProcessorConstructor.cpp', 'bindings/js/JSXSLTProcessorConstructor.h', 'bindings/js/JSXSLTProcessorCustom.cpp', + 'bindings/js/JavaScriptProfile.cpp', + 'bindings/js/JavaScriptProfile.h', + 'bindings/js/JavaScriptProfileNode.cpp', + 'bindings/js/JavaScriptProfileNode.h', 'bindings/js/ScheduledAction.cpp', 'bindings/js/ScheduledAction.h', 'bindings/js/ScriptArray.cpp', @@ -1613,10 +1617,6 @@ 'inspector/JavaScriptDebugListener.h', 'inspector/JavaScriptDebugServer.cpp', 'inspector/JavaScriptDebugServer.h', - 'inspector/JavaScriptProfile.cpp', - 'inspector/JavaScriptProfile.h', - 'inspector/JavaScriptProfileNode.cpp', - 'inspector/JavaScriptProfileNode.h', 'inspector/TimelineRecordFactory.cpp', 'inspector/TimelineRecordFactory.h', 'loader/appcache/ApplicationCache.cpp', @@ -1928,6 +1928,7 @@ 'platform/chromium/FramelessScrollView.h', 'platform/chromium/FramelessScrollViewClient.h', 'platform/chromium/GeolocationServiceChromium.cpp', + 'platform/chromium/GeolocationServiceChromium.h', 'platform/chromium/KeyCodeConversion.h', 'platform/chromium/KeyCodeConversionGtk.cpp', 'platform/chromium/KeyboardCodesPosix.h', @@ -1979,6 +1980,7 @@ 'platform/graphics/cg/FloatRectCG.cpp', 'platform/graphics/cg/FloatSizeCG.cpp', 'platform/graphics/cg/GradientCG.cpp', + 'platform/graphics/cg/GraphicsContext3DCG.cpp', 'platform/graphics/cg/GraphicsContextCG.cpp', 'platform/graphics/cg/GraphicsContextPlatformPrivateCG.h', 'platform/graphics/cg/ImageBufferCG.cpp', @@ -2142,6 +2144,7 @@ 'platform/graphics/skia/GradientSkia.cpp', 'platform/graphics/skia/GraphicsContextPlatformPrivate.h', 'platform/graphics/skia/GraphicsContextSkia.cpp', + 'platform/graphics/skia/GraphicsContext3DSkia.cpp', 'platform/graphics/skia/ImageBufferSkia.cpp', 'platform/graphics/skia/ImageSkia.cpp', 'platform/graphics/skia/IntPointSkia.cpp', @@ -2279,6 +2282,7 @@ 'platform/graphics/Gradient.h', 'platform/graphics/GraphicsContext.cpp', 'platform/graphics/GraphicsContext.h', + 'platform/graphics/GraphicsContext3D.cpp', 'platform/graphics/GraphicsContext3D.h', 'platform/graphics/GraphicsContextPrivate.h', 'platform/graphics/GraphicsLayer.cpp', @@ -3097,6 +3101,9 @@ 'rendering/RenderSVGInlineText.h', 'rendering/RenderSVGModelObject.cpp', 'rendering/RenderSVGModelObject.h', + 'rendering/RenderSVGResource.h', + 'rendering/RenderSVGResourceMasker.cpp', + 'rendering/RenderSVGResourceMasker.h', 'rendering/RenderSVGRoot.cpp', 'rendering/RenderSVGRoot.h', 'rendering/RenderSVGShadowTreeRootContainer.cpp', @@ -3323,8 +3330,6 @@ 'svg/graphics/SVGResourceListener.h', 'svg/graphics/SVGResourceMarker.cpp', 'svg/graphics/SVGResourceMarker.h', - 'svg/graphics/SVGResourceMasker.cpp', - 'svg/graphics/SVGResourceMasker.h', 'svg/ColorDistance.cpp', 'svg/ColorDistance.h', 'svg/ElementTimeControl.h', @@ -3751,7 +3756,7 @@ 'inspector/front-end/Panel.js', 'inspector/front-end/PanelEnablerView.js', 'inspector/front-end/Placard.js', - 'inspector/front-end/Popup.js', + 'inspector/front-end/Popover.js', 'inspector/front-end/ProfileDataGridTree.js', 'inspector/front-end/ProfilesPanel.js', 'inspector/front-end/ProfileView.js', @@ -3797,6 +3802,7 @@ 'inspector/front-end/audits.css', 'inspector/front-end/inspector.css', 'inspector/front-end/inspectorSyntaxHighlight.css', + 'inspector/front-end/popover.css', 'inspector/front-end/textViewer.css', ], 'webinspector_image_files': [ @@ -3834,6 +3840,7 @@ 'inspector/front-end/Images/excludeButtonGlyph.png', 'inspector/front-end/Images/focusButtonGlyph.png', 'inspector/front-end/Images/forward.png', + 'inspector/front-end/Images/gearButtonGlyph.png', 'inspector/front-end/Images/glossyHeader.png', 'inspector/front-end/Images/glossyHeaderPressed.png', 'inspector/front-end/Images/glossyHeaderSelected.png', @@ -3851,6 +3858,8 @@ 'inspector/front-end/Images/paneSettingsButtons.png', 'inspector/front-end/Images/pauseOnExceptionButtonGlyph.png', 'inspector/front-end/Images/percentButtonGlyph.png', + 'inspector/front-end/Images/popoverArrows.png', + 'inspector/front-end/Images/popoverBackground.png', 'inspector/front-end/Images/profileGroupIcon.png', 'inspector/front-end/Images/profileIcon.png', 'inspector/front-end/Images/profilesIcon.png', @@ -3894,6 +3903,12 @@ 'inspector/front-end/Images/statusbarResizerVertical.png', 'inspector/front-end/Images/storageIcon.png', 'inspector/front-end/Images/successGreenDot.png', + 'inspector/front-end/Images/thumbActiveHoriz.png', + 'inspector/front-end/Images/thumbActiveVert.png', + 'inspector/front-end/Images/thumbHoriz.png', + 'inspector/front-end/Images/thumbVert.png', + 'inspector/front-end/Images/thumbHoverHoriz.png', + 'inspector/front-end/Images/thumbHoverVert.png', 'inspector/front-end/Images/timelineHollowPillBlue.png', 'inspector/front-end/Images/timelineHollowPillGray.png', 'inspector/front-end/Images/timelineHollowPillGreen.png', @@ -3919,6 +3934,8 @@ 'inspector/front-end/Images/timelinePillRed.png', 'inspector/front-end/Images/timelinePillYellow.png', 'inspector/front-end/Images/toolbarItemSelected.png', + 'inspector/front-end/Images/trackHoriz.png', + 'inspector/front-end/Images/trackVert.png', 'inspector/front-end/Images/treeDownTriangleBlack.png', 'inspector/front-end/Images/treeDownTriangleWhite.png', 'inspector/front-end/Images/treeRightTriangleBlack.png', diff --git a/WebCore/WebCore.pro b/WebCore/WebCore.pro index 13d6314..4cb4794 100644 --- a/WebCore/WebCore.pro +++ b/WebCore/WebCore.pro @@ -339,6 +339,10 @@ SOURCES += \ bindings/js/JSLazyEventListener.cpp \ bindings/js/JSPluginElementFunctions.cpp \ bindings/js/JSPopStateEventCustom.cpp \ + bindings/js/JavaScriptProfile.h \ + bindings/js/JavaScriptProfileNode.h \ + bindings/js/JavaScriptProfile.cpp \ + bindings/js/JavaScriptProfileNode.cpp \ bindings/js/ScriptArray.cpp \ bindings/js/ScriptCachedFrameData.cpp \ bindings/js/ScriptCallFrame.cpp \ @@ -1371,8 +1375,6 @@ HEADERS += \ inspector/InspectorTimelineAgent.h \ inspector/JavaScriptCallFrame.h \ inspector/JavaScriptDebugServer.h \ - inspector/JavaScriptProfile.h \ - inspector/JavaScriptProfileNode.h \ inspector/TimelineRecordFactory.h \ loader/appcache/ApplicationCacheGroup.h \ loader/appcache/ApplicationCacheHost.h \ @@ -1654,6 +1656,8 @@ HEADERS += \ rendering/RenderSVGInline.h \ rendering/RenderSVGInlineText.h \ rendering/RenderSVGModelObject.h \ + rendering/RenderSVGResource.h \ + rendering/RenderSVGResourceMasker.h \ rendering/RenderSVGRoot.h \ rendering/RenderSVGShadowTreeRootContainer.h \ rendering/RenderSVGText.h \ @@ -1745,7 +1749,6 @@ HEADERS += \ svg/graphics/SVGResourceFilter.h \ svg/graphics/SVGResource.h \ svg/graphics/SVGResourceMarker.h \ - svg/graphics/SVGResourceMasker.h \ svg/SVGAElement.h \ svg/SVGAltGlyphElement.h \ svg/SVGAngle.h \ @@ -2596,7 +2599,6 @@ contains(DEFINES, ENABLE_SVG=1) { svg/graphics/SVGResource.cpp \ svg/graphics/SVGResourceFilter.cpp \ svg/graphics/SVGResourceMarker.cpp \ - svg/graphics/SVGResourceMasker.cpp \ rendering/RenderForeignObject.cpp \ rendering/RenderPath.cpp \ rendering/RenderSVGBlock.cpp \ @@ -2607,6 +2609,7 @@ contains(DEFINES, ENABLE_SVG=1) { rendering/RenderSVGInline.cpp \ rendering/RenderSVGInlineText.cpp \ rendering/RenderSVGModelObject.cpp \ + rendering/RenderSVGResourceMasker.cpp \ rendering/RenderSVGRoot.cpp \ rendering/RenderSVGShadowTreeRootContainer.cpp \ rendering/RenderSVGText.cpp \ @@ -2628,8 +2631,6 @@ contains(DEFINES, ENABLE_JAVASCRIPT_DEBUGGER=1) { bindings/js/JSJavaScriptCallFrameCustom.cpp \ inspector/JavaScriptCallFrame.cpp \ inspector/JavaScriptDebugServer.cpp \ - inspector/JavaScriptProfile.cpp \ - inspector/JavaScriptProfileNode.cpp } contains(DEFINES, ENABLE_OFFLINE_WEB_APPLICATIONS=1) { diff --git a/WebCore/WebCore.vcproj/WebCore.vcproj b/WebCore/WebCore.vcproj/WebCore.vcproj index 14d93a9..02d3070 100644 --- a/WebCore/WebCore.vcproj/WebCore.vcproj +++ b/WebCore/WebCore.vcproj/WebCore.vcproj @@ -27641,6 +27641,18 @@ >
</File>
<File
+ RelativePath="..\rendering\RenderSVGResource.h"
+ >
+ </File>
+ <File
+ RelativePath="..\rendering\RenderSVGResourceMasker.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\rendering\RenderSVGResourceMasker.h"
+ >
+ </File>
+ <File
RelativePath="..\rendering\RenderSVGRoot.cpp"
>
</File>
@@ -39916,6 +39928,22 @@ </FileConfiguration>
</File>
<File
+ RelativePath="..\bindings\js\JavaScriptProfile.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\bindings\js\JavaScriptProfile.h"
+ >
+ </File>
+ <File
+ RelativePath="..\bindings\js\JavaScriptProfileNode.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\bindings\js\JavaScriptProfileNode.h"
+ >
+ </File>
+ <File
RelativePath="..\bindings\js\ScheduledAction.cpp"
>
<FileConfiguration
@@ -41775,14 +41803,6 @@ RelativePath="..\svg\graphics\SVGResourceMarker.h"
>
</File>
- <File
- RelativePath="..\svg\graphics\SVGResourceMasker.cpp"
- >
- </File>
- <File
- RelativePath="..\svg\graphics\SVGResourceMasker.h"
- >
- </File>
<Filter
Name="filters"
>
@@ -42701,22 +42721,6 @@ >
</File>
<File
- RelativePath="..\inspector\JavaScriptProfile.cpp"
- >
- </File>
- <File
- RelativePath="..\inspector\JavaScriptProfile.h"
- >
- </File>
- <File
- RelativePath="..\inspector\JavaScriptProfileNode.cpp"
- >
- </File>
- <File
- RelativePath="..\inspector\JavaScriptProfileNode.h"
- >
- </File>
- <File
RelativePath="..\inspector\TimelineRecordFactory.cpp"
>
</File>
@@ -42904,7 +42908,11 @@ >
</File>
<File
- RelativePath="..\inspector\front-end\Popup.js"
+ RelativePath="..\inspector\front-end\popover.css"
+ >
+ </File>
+ <File
+ RelativePath="..\inspector\front-end\Popover.js"
>
</File>
<File
diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj index 5fa0e31..289ae48 100644 --- a/WebCore/WebCore.xcodeproj/project.pbxproj +++ b/WebCore/WebCore.xcodeproj/project.pbxproj @@ -64,6 +64,9 @@ 082341C50FCF3A9500D75BD6 /* WMLSelectElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 082341C30FCF3A9400D75BD6 /* WMLSelectElement.cpp */; }; 082341C60FCF3A9500D75BD6 /* WMLSelectElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 082341C40FCF3A9400D75BD6 /* WMLSelectElement.h */; }; 082FCAC4110927CE00CC4821 /* JSSVGContextCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 082FCAC3110927CE00CC4821 /* JSSVGContextCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 083192AA112B43050083C3B9 /* RenderSVGResource.h in Headers */ = {isa = PBXBuildFile; fileRef = 083192A7112B43050083C3B9 /* RenderSVGResource.h */; }; + 083192AB112B43050083C3B9 /* RenderSVGResourceMasker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 083192A8112B43050083C3B9 /* RenderSVGResourceMasker.cpp */; }; + 083192AC112B43050083C3B9 /* RenderSVGResourceMasker.h in Headers */ = {isa = PBXBuildFile; fileRef = 083192A9112B43050083C3B9 /* RenderSVGResourceMasker.h */; }; 08385FF610F0186000BFE07B /* SVGMarkerData.h in Headers */ = {isa = PBXBuildFile; fileRef = 08385FF510F0186000BFE07B /* SVGMarkerData.h */; }; 0839476C0ECE4BD600027350 /* WMLElementFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08FB84B00ECE373300DC064E /* WMLElementFactory.cpp */; }; 0839476D0ECE4BD600027350 /* WMLElementFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 08FB84B10ECE373300DC064E /* WMLElementFactory.h */; }; @@ -528,10 +531,6 @@ 1C81B95A0E97330800266E07 /* InspectorController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C81B9560E97330800266E07 /* InspectorController.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1C81B95B0E97330800266E07 /* InspectorController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C81B9570E97330800266E07 /* InspectorController.cpp */; }; 1C81B95C0E97330800266E07 /* InspectorClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C81B9580E97330800266E07 /* InspectorClient.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 1C81B9FF0E9733CB00266E07 /* JavaScriptProfileNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C81B9FB0E9733CB00266E07 /* JavaScriptProfileNode.h */; }; - 1C81BA000E9733CB00266E07 /* JavaScriptProfileNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C81B9FC0E9733CB00266E07 /* JavaScriptProfileNode.cpp */; }; - 1C81BA010E9733CB00266E07 /* JavaScriptProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C81B9FD0E9733CB00266E07 /* JavaScriptProfile.h */; }; - 1C81BA020E9733CB00266E07 /* JavaScriptProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C81B9FE0E9733CB00266E07 /* JavaScriptProfile.cpp */; }; 1C81BA090E97348300266E07 /* JavaScriptCallFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C81BA030E97348300266E07 /* JavaScriptCallFrame.cpp */; }; 1C81BA0A0E97348300266E07 /* JavaScriptCallFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C81BA040E97348300266E07 /* JavaScriptCallFrame.h */; }; 1C81BA0C0E97348300266E07 /* JavaScriptDebugListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C81BA060E97348300266E07 /* JavaScriptDebugListener.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -1243,6 +1242,8 @@ 65DF323C09D1DE65000BE325 /* JSCanvasPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = 65DF323609D1DE65000BE325 /* JSCanvasPattern.h */; }; 65DF326109D1E199000BE325 /* UserAgentStyleSheetsData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 656581AF09D14EE6000E61D7 /* UserAgentStyleSheetsData.cpp */; }; 65FEA86909833ADE00BED4AB /* Page.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65FEA86809833ADE00BED4AB /* Page.cpp */; }; + 6E21C6C01126338500A7BE02 /* GraphicsContext3D.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E21C6BF1126338500A7BE02 /* GraphicsContext3D.cpp */; }; + 6E21C6C21126339900A7BE02 /* GraphicsContext3DCG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E21C6C11126339900A7BE02 /* GraphicsContext3DCG.cpp */; }; 6E47E66010B7944B00B186C8 /* WebGLGetInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E47E65E10B7944B00B186C8 /* WebGLGetInfo.cpp */; }; 6E47E66110B7944B00B186C8 /* WebGLGetInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E47E65F10B7944B00B186C8 /* WebGLGetInfo.h */; }; 6E4E91AC10F7FB3100A2779C /* CanvasContextAttributes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E4E91A710F7FB3100A2779C /* CanvasContextAttributes.cpp */; }; @@ -2194,6 +2195,7 @@ 9307F1D80AF2D59000DBA31A /* HitTestResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 9307F1D60AF2D59000DBA31A /* HitTestResult.h */; settings = {ATTRIBUTES = (Private, ); }; }; 930908910AF7EDE40081DF01 /* HitTestRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 930908900AF7EDE40081DF01 /* HitTestRequest.h */; }; 930FC68A1072B9280045293E /* TextRenderingMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 930FC6891072B9280045293E /* TextRenderingMode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 931BCC611124DFCB00BE70DD /* MediaCanStartListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 931BCC601124DFCB00BE70DD /* MediaCanStartListener.h */; }; 9326DC0C09DAD5D600AFC847 /* CharsetData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 656581AC09D14EE6000E61D7 /* CharsetData.cpp */; }; 9327A94209968D1A0068A546 /* HTMLOptionsCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9327A94109968D1A0068A546 /* HTMLOptionsCollection.cpp */; }; 932871C00B20DEB70049035A /* PlatformMenuDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 932871BF0B20DEB70049035A /* PlatformMenuDescription.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -2458,6 +2460,10 @@ 97DD4D860FDF4D6E00ECF9A4 /* XSSAuditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97DD4D840FDF4D6D00ECF9A4 /* XSSAuditor.cpp */; }; 97DD4D870FDF4D6E00ECF9A4 /* XSSAuditor.h in Headers */ = {isa = PBXBuildFile; fileRef = 97DD4D850FDF4D6E00ECF9A4 /* XSSAuditor.h */; }; 97EF7DFE107E55B700D7C49C /* ScriptControllerBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97EF7DFD107E55B700D7C49C /* ScriptControllerBase.cpp */; }; + 9F2A322B1125A0A2003C3056 /* JavaScriptProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9F2A32271125A0A2003C3056 /* JavaScriptProfile.cpp */; }; + 9F2A322C1125A0A2003C3056 /* JavaScriptProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F2A32281125A0A2003C3056 /* JavaScriptProfile.h */; }; + 9F2A322D1125A0A2003C3056 /* JavaScriptProfileNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9F2A32291125A0A2003C3056 /* JavaScriptProfileNode.cpp */; }; + 9F2A322E1125A0A2003C3056 /* JavaScriptProfileNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F2A322A1125A0A2003C3056 /* JavaScriptProfileNode.h */; }; 9F6FC1961122E82A00E80196 /* ScriptDebugServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9F6FC1941122E82A00E80196 /* ScriptDebugServer.cpp */; }; 9F6FC1971122E82A00E80196 /* ScriptDebugServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F6FC1951122E82A00E80196 /* ScriptDebugServer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 9F72304F11184B4100AD0126 /* ScriptProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F72304C11184B4100AD0126 /* ScriptProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -3687,8 +3693,6 @@ B25599B80D00D8BA00BB825C /* SVGResourceListener.h in Headers */ = {isa = PBXBuildFile; fileRef = B25599200D00D8B900BB825C /* SVGResourceListener.h */; }; B25599B90D00D8BA00BB825C /* SVGResourceMarker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B25599210D00D8B900BB825C /* SVGResourceMarker.cpp */; }; B25599BA0D00D8BA00BB825C /* SVGResourceMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = B25599220D00D8B900BB825C /* SVGResourceMarker.h */; }; - B25599BB0D00D8BA00BB825C /* SVGResourceMasker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B25599230D00D8B900BB825C /* SVGResourceMasker.cpp */; }; - B25599BC0D00D8BA00BB825C /* SVGResourceMasker.h in Headers */ = {isa = PBXBuildFile; fileRef = B25599240D00D8B900BB825C /* SVGResourceMasker.h */; }; B25DFAAF0B2E2929000E6510 /* JSSVGMatrixCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B25DFAAE0B2E2929000E6510 /* JSSVGMatrixCustom.cpp */; }; B262B8040D1F32D000158F09 /* SVGFont.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B262B8030D1F32D000158F09 /* SVGFont.cpp */; }; B26554EA0B80D74900A50EC3 /* RenderSVGTextPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B26554E80B80D74900A50EC3 /* RenderSVGTextPath.cpp */; }; @@ -4745,7 +4749,7 @@ E1C415DE0F655D7C0092D2FB /* CrossOriginPreflightResultCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1C415DD0F655D7C0092D2FB /* CrossOriginPreflightResultCache.cpp */; }; E1C416120F6562FD0092D2FB /* CrossOriginAccessControl.h in Headers */ = {isa = PBXBuildFile; fileRef = E1C416110F6562FD0092D2FB /* CrossOriginAccessControl.h */; }; E1C416170F6563180092D2FB /* CrossOriginAccessControl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1C416160F6563180092D2FB /* CrossOriginAccessControl.cpp */; }; - E1C4DE690EA75C1E0023CCD6 /* ActiveDOMObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E1C4DE680EA75C1E0023CCD6 /* ActiveDOMObject.h */; }; + E1C4DE690EA75C1E0023CCD6 /* ActiveDOMObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E1C4DE680EA75C1E0023CCD6 /* ActiveDOMObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; E1C4DE6E0EA75C650023CCD6 /* ActiveDOMObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1C4DE6D0EA75C650023CCD6 /* ActiveDOMObject.cpp */; }; E1C8BE5D0E8BD15A0064CB7D /* JSWorker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1C8BE5C0E8BD15A0064CB7D /* JSWorker.cpp */; }; E1CA5CBC0E8CDCAF00E8EF90 /* JSWorkerCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1CA5CBB0E8CDCAF00E8EF90 /* JSWorkerCustom.cpp */; }; @@ -5353,6 +5357,9 @@ 082341C30FCF3A9400D75BD6 /* WMLSelectElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLSelectElement.cpp; sourceTree = "<group>"; }; 082341C40FCF3A9400D75BD6 /* WMLSelectElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLSelectElement.h; sourceTree = "<group>"; }; 082FCAC3110927CE00CC4821 /* JSSVGContextCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSVGContextCache.h; sourceTree = "<group>"; }; + 083192A7112B43050083C3B9 /* RenderSVGResource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGResource.h; sourceTree = "<group>"; }; + 083192A8112B43050083C3B9 /* RenderSVGResourceMasker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGResourceMasker.cpp; sourceTree = "<group>"; }; + 083192A9112B43050083C3B9 /* RenderSVGResourceMasker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderSVGResourceMasker.h; sourceTree = "<group>"; }; 08385FF510F0186000BFE07B /* SVGMarkerData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGMarkerData.h; sourceTree = "<group>"; }; 083DAEA20F01A7FB00342754 /* RenderTextControlMultiLine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTextControlMultiLine.cpp; sourceTree = "<group>"; }; 083DAEA30F01A7FB00342754 /* RenderTextControlMultiLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTextControlMultiLine.h; sourceTree = "<group>"; }; @@ -5847,10 +5854,6 @@ 1C81B9570E97330800266E07 /* InspectorController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorController.cpp; sourceTree = "<group>"; }; 1C81B9580E97330800266E07 /* InspectorClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorClient.h; sourceTree = "<group>"; }; 1C81B9590E97330800266E07 /* front-end */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "front-end"; sourceTree = "<group>"; }; - 1C81B9FB0E9733CB00266E07 /* JavaScriptProfileNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptProfileNode.h; sourceTree = "<group>"; }; - 1C81B9FC0E9733CB00266E07 /* JavaScriptProfileNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JavaScriptProfileNode.cpp; sourceTree = "<group>"; }; - 1C81B9FD0E9733CB00266E07 /* JavaScriptProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptProfile.h; sourceTree = "<group>"; }; - 1C81B9FE0E9733CB00266E07 /* JavaScriptProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JavaScriptProfile.cpp; sourceTree = "<group>"; }; 1C81BA030E97348300266E07 /* JavaScriptCallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JavaScriptCallFrame.cpp; sourceTree = "<group>"; }; 1C81BA040E97348300266E07 /* JavaScriptCallFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptCallFrame.h; sourceTree = "<group>"; }; 1C81BA050E97348300266E07 /* JavaScriptCallFrame.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = JavaScriptCallFrame.idl; sourceTree = "<group>"; }; @@ -6657,6 +6660,8 @@ 65DF323609D1DE65000BE325 /* JSCanvasPattern.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSCanvasPattern.h; sourceTree = "<group>"; }; 65F80697054D9F86008BF776 /* BlockExceptions.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BlockExceptions.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 65FEA86809833ADE00BED4AB /* Page.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Page.cpp; sourceTree = "<group>"; }; + 6E21C6BF1126338500A7BE02 /* GraphicsContext3D.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsContext3D.cpp; sourceTree = "<group>"; }; + 6E21C6C11126339900A7BE02 /* GraphicsContext3DCG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsContext3DCG.cpp; sourceTree = "<group>"; }; 6E47E65E10B7944B00B186C8 /* WebGLGetInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebGLGetInfo.cpp; path = canvas/WebGLGetInfo.cpp; sourceTree = "<group>"; }; 6E47E65F10B7944B00B186C8 /* WebGLGetInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebGLGetInfo.h; path = canvas/WebGLGetInfo.h; sourceTree = "<group>"; }; 6E4E91A710F7FB3100A2779C /* CanvasContextAttributes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CanvasContextAttributes.cpp; path = canvas/CanvasContextAttributes.cpp; sourceTree = "<group>"; }; @@ -7565,6 +7570,7 @@ 9307F1D60AF2D59000DBA31A /* HitTestResult.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HitTestResult.h; sourceTree = "<group>"; }; 930908900AF7EDE40081DF01 /* HitTestRequest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HitTestRequest.h; sourceTree = "<group>"; }; 930FC6891072B9280045293E /* TextRenderingMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextRenderingMode.h; sourceTree = "<group>"; }; + 931BCC601124DFCB00BE70DD /* MediaCanStartListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaCanStartListener.h; sourceTree = "<group>"; }; 9327A94109968D1A0068A546 /* HTMLOptionsCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLOptionsCollection.cpp; sourceTree = "<group>"; }; 932871BF0B20DEB70049035A /* PlatformMenuDescription.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PlatformMenuDescription.h; sourceTree = "<group>"; }; 932E16080AF578340025F408 /* FrameLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrameLoader.cpp; sourceTree = "<group>"; }; @@ -7805,6 +7811,10 @@ 97DD4D840FDF4D6D00ECF9A4 /* XSSAuditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XSSAuditor.cpp; sourceTree = "<group>"; }; 97DD4D850FDF4D6E00ECF9A4 /* XSSAuditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XSSAuditor.h; sourceTree = "<group>"; }; 97EF7DFD107E55B700D7C49C /* ScriptControllerBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptControllerBase.cpp; sourceTree = "<group>"; }; + 9F2A32271125A0A2003C3056 /* JavaScriptProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JavaScriptProfile.cpp; sourceTree = "<group>"; }; + 9F2A32281125A0A2003C3056 /* JavaScriptProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptProfile.h; sourceTree = "<group>"; }; + 9F2A32291125A0A2003C3056 /* JavaScriptProfileNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JavaScriptProfileNode.cpp; sourceTree = "<group>"; }; + 9F2A322A1125A0A2003C3056 /* JavaScriptProfileNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptProfileNode.h; sourceTree = "<group>"; }; 9F6FC1941122E82A00E80196 /* ScriptDebugServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptDebugServer.cpp; sourceTree = "<group>"; }; 9F6FC1951122E82A00E80196 /* ScriptDebugServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptDebugServer.h; sourceTree = "<group>"; }; 9F72304C11184B4100AD0126 /* ScriptProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptProfile.h; sourceTree = "<group>"; }; @@ -8923,8 +8933,6 @@ B25599200D00D8B900BB825C /* SVGResourceListener.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGResourceListener.h; sourceTree = "<group>"; }; B25599210D00D8B900BB825C /* SVGResourceMarker.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SVGResourceMarker.cpp; sourceTree = "<group>"; }; B25599220D00D8B900BB825C /* SVGResourceMarker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGResourceMarker.h; sourceTree = "<group>"; }; - B25599230D00D8B900BB825C /* SVGResourceMasker.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SVGResourceMasker.cpp; sourceTree = "<group>"; }; - B25599240D00D8B900BB825C /* SVGResourceMasker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGResourceMasker.h; sourceTree = "<group>"; }; B25DFAAE0B2E2929000E6510 /* JSSVGMatrixCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSSVGMatrixCustom.cpp; sourceTree = "<group>"; }; B262B8030D1F32D000158F09 /* SVGFont.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SVGFont.cpp; sourceTree = "<group>"; }; B26554E80B80D74900A50EC3 /* RenderSVGTextPath.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGTextPath.cpp; sourceTree = "<group>"; }; @@ -10644,10 +10652,6 @@ 1C81BA060E97348300266E07 /* JavaScriptDebugListener.h */, 1C81BA070E97348300266E07 /* JavaScriptDebugServer.cpp */, 1C81BA080E97348300266E07 /* JavaScriptDebugServer.h */, - 1C81B9FE0E9733CB00266E07 /* JavaScriptProfile.cpp */, - 1C81B9FD0E9733CB00266E07 /* JavaScriptProfile.h */, - 1C81B9FC0E9733CB00266E07 /* JavaScriptProfileNode.cpp */, - 1C81B9FB0E9733CB00266E07 /* JavaScriptProfileNode.h */, BCC64F5F0DCFB84E0081EF3B /* localizedStrings.js */, 7553CFE7108F473F00EA281E /* TimelineRecordFactory.cpp */, 7553CFE6108F473F00EA281E /* TimelineRecordFactory.h */, @@ -11490,6 +11494,7 @@ BCE1C41A0D982980003B02F2 /* Location.cpp */, BCE1C4190D982980003B02F2 /* Location.h */, BCE1C4220D9829F2003B02F2 /* Location.idl */, + 931BCC601124DFCB00BE70DD /* MediaCanStartListener.h */, 93EB355E09E37FD600F43799 /* MouseEventWithHitTestResults.cpp */, 935C476209AC4CE600A6AAB4 /* MouseEventWithHitTestResults.h */, A9C6E5A30D746458006442E9 /* Navigator.cpp */, @@ -14274,8 +14279,6 @@ B25599200D00D8B900BB825C /* SVGResourceListener.h */, B25599210D00D8B900BB825C /* SVGResourceMarker.cpp */, B25599220D00D8B900BB825C /* SVGResourceMarker.h */, - B25599230D00D8B900BB825C /* SVGResourceMasker.cpp */, - B25599240D00D8B900BB825C /* SVGResourceMasker.h */, ); path = graphics; sourceTree = "<group>"; @@ -14326,6 +14329,7 @@ B275352C0B053814002CE64F /* FloatRectCG.cpp */, B275352D0B053814002CE64F /* FloatSizeCG.cpp */, BC53C60A0DA56CF10021EB5D /* GradientCG.cpp */, + 6E21C6C11126339900A7BE02 /* GraphicsContext3DCG.cpp */, B2ED97700B1F55CE00257D0F /* GraphicsContextCG.cpp */, A80D67070E9E9DEB00E420F0 /* GraphicsContextPlatformPrivateCG.h */, B2A10B930B3818D700099AA4 /* ImageBufferCG.cpp */, @@ -14441,6 +14445,7 @@ BC53C5F40DA56B920021EB5D /* Gradient.h */, B2A015920AF6CD53006BCE0E /* GraphicsContext.cpp */, B2A015930AF6CD53006BCE0E /* GraphicsContext.h */, + 6E21C6BF1126338500A7BE02 /* GraphicsContext3D.cpp */, 49C7B9FB1042D3650009D447 /* GraphicsContext3D.h */, A88FE3330E5EEE87008D8C0F /* GraphicsContextPrivate.h */, 0F580B090F12A2690051D689 /* GraphicsLayer.cpp */, @@ -14632,6 +14637,10 @@ B21127A50B3186770009BE53 /* JSSVGPODTypeWrapper.h */, E1C36D320EB0A094007410BC /* JSWorkerContextBase.cpp */, E1C36D330EB0A094007410BC /* JSWorkerContextBase.h */, + 9F2A32271125A0A2003C3056 /* JavaScriptProfile.cpp */, + 9F2A32281125A0A2003C3056 /* JavaScriptProfile.h */, + 9F2A32291125A0A2003C3056 /* JavaScriptProfileNode.cpp */, + 9F2A322A1125A0A2003C3056 /* JavaScriptProfileNode.h */, BCA378BA0D15F64200B793D6 /* ScheduledAction.cpp */, BCA378BB0D15F64200B793D6 /* ScheduledAction.h */, 7A1E88F3101CC384000C4DF5 /* ScriptArray.cpp */, @@ -15715,6 +15724,9 @@ 853CA9D10AEEC5E9002372DC /* RenderSVGInlineText.h */, A8F5C0B70F9285AC0098E06B /* RenderSVGModelObject.cpp */, A8F5C0B60F9285AC0098E06B /* RenderSVGModelObject.h */, + 083192A7112B43050083C3B9 /* RenderSVGResource.h */, + 083192A8112B43050083C3B9 /* RenderSVGResourceMasker.cpp */, + 083192A9112B43050083C3B9 /* RenderSVGResourceMasker.h */, AA31B5B20C1DFD1000AE7083 /* RenderSVGRoot.cpp */, AA31B5B30C1DFD1000AE7083 /* RenderSVGRoot.h */, 08DAB9B81103D9A5003E7ABA /* RenderSVGShadowTreeRootContainer.cpp */, @@ -17306,8 +17318,6 @@ 1C81BA0A0E97348300266E07 /* JavaScriptCallFrame.h in Headers */, 1C81BA0C0E97348300266E07 /* JavaScriptDebugListener.h in Headers */, 1C81BA0E0E97348300266E07 /* JavaScriptDebugServer.h in Headers */, - 1C81BA010E9733CB00266E07 /* JavaScriptProfile.h in Headers */, - 1C81B9FF0E9733CB00266E07 /* JavaScriptProfileNode.h in Headers */, 59BC393F11054A1300FD85DB /* JavaStringJSC.h in Headers */, 1A569D040D7E2B82007C3983 /* jni_jsobject.h in Headers */, 5913953B110758450083EC55 /* JNIBridge.h in Headers */, @@ -17953,6 +17963,8 @@ 853CA9DB0AEEC5E9002372DC /* RenderSVGInline.h in Headers */, 853CA9DD0AEEC5E9002372DC /* RenderSVGInlineText.h in Headers */, A8F5C0B80F9285AC0098E06B /* RenderSVGModelObject.h in Headers */, + 083192AA112B43050083C3B9 /* RenderSVGResource.h in Headers */, + 083192AC112B43050083C3B9 /* RenderSVGResourceMasker.h in Headers */, AA31B5B50C1DFD1000AE7083 /* RenderSVGRoot.h in Headers */, 08DAB9BB1103D9A5003E7ABA /* RenderSVGShadowTreeRootContainer.h in Headers */, 853CA9DF0AEEC5E9002372DC /* RenderSVGText.h in Headers */, @@ -18277,7 +18289,6 @@ B25599B70D00D8BA00BB825C /* SVGResourceFilter.h in Headers */, B25599B80D00D8BA00BB825C /* SVGResourceListener.h in Headers */, B25599BA0D00D8BA00BB825C /* SVGResourceMarker.h in Headers */, - B25599BC0D00D8BA00BB825C /* SVGResourceMasker.h in Headers */, 853CA9E90AEEC608002372DC /* SVGRootInlineBox.h in Headers */, B2227AA30D00BF220071B782 /* SVGScriptElement.h in Headers */, B2227AA60D00BF220071B782 /* SVGSetElement.h in Headers */, @@ -18533,6 +18544,9 @@ BCE789161120D6080060ECE5 /* InlineIterator.h in Headers */, BCE789861120E7A60060ECE5 /* BidiRun.h in Headers */, 9F6FC1971122E82A00E80196 /* ScriptDebugServer.h in Headers */, + 931BCC611124DFCB00BE70DD /* MediaCanStartListener.h in Headers */, + 9F2A322C1125A0A2003C3056 /* JavaScriptProfile.h in Headers */, + 9F2A322E1125A0A2003C3056 /* JavaScriptProfileNode.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -19498,8 +19512,6 @@ 59A9E7B01104758800DFB4C1 /* JavaInstanceJSC.cpp in Sources */, 1C81BA090E97348300266E07 /* JavaScriptCallFrame.cpp in Sources */, 1C81BA0D0E97348300266E07 /* JavaScriptDebugServer.cpp in Sources */, - 1C81BA020E9733CB00266E07 /* JavaScriptProfile.cpp in Sources */, - 1C81BA000E9733CB00266E07 /* JavaScriptProfileNode.cpp in Sources */, 1A569D030D7E2B82007C3983 /* jni_jsobject.mm in Sources */, 1A569D050D7E2B82007C3983 /* jni_objc.mm in Sources */, 5913953D1107584E0083EC55 /* JNIBridge.cpp in Sources */, @@ -20195,6 +20207,7 @@ 853CA9DA0AEEC5E9002372DC /* RenderSVGInline.cpp in Sources */, 853CA9DC0AEEC5E9002372DC /* RenderSVGInlineText.cpp in Sources */, A8F5C0B90F9285AC0098E06B /* RenderSVGModelObject.cpp in Sources */, + 083192AB112B43050083C3B9 /* RenderSVGResourceMasker.cpp in Sources */, AA31B5B40C1DFD1000AE7083 /* RenderSVGRoot.cpp in Sources */, 08DAB9BA1103D9A5003E7ABA /* RenderSVGShadowTreeRootContainer.cpp in Sources */, 853CA9DE0AEEC5E9002372DC /* RenderSVGText.cpp in Sources */, @@ -20495,7 +20508,6 @@ B25599B40D00D8BA00BB825C /* SVGResourceClipper.cpp in Sources */, B25599B60D00D8BA00BB825C /* SVGResourceFilter.cpp in Sources */, B25599B90D00D8BA00BB825C /* SVGResourceMarker.cpp in Sources */, - B25599BB0D00D8BA00BB825C /* SVGResourceMasker.cpp in Sources */, 853CA9E80AEEC608002372DC /* SVGRootInlineBox.cpp in Sources */, B2227AA20D00BF220071B782 /* SVGScriptElement.cpp in Sources */, B2227AA50D00BF220071B782 /* SVGSetElement.cpp in Sources */, @@ -20715,6 +20727,10 @@ BCE7898B1120E8020060ECE5 /* BidiRun.cpp in Sources */, 9F6FC1961122E82A00E80196 /* ScriptDebugServer.cpp in Sources */, 76FF17E311235673001D61B5 /* PluginViewNone.cpp in Sources */, + 9F2A322B1125A0A2003C3056 /* JavaScriptProfile.cpp in Sources */, + 9F2A322D1125A0A2003C3056 /* JavaScriptProfileNode.cpp in Sources */, + 6E21C6C01126338500A7BE02 /* GraphicsContext3D.cpp in Sources */, + 6E21C6C21126339900A7BE02 /* GraphicsContext3DCG.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/WebCore/bindings/js/JSAudioConstructor.cpp b/WebCore/bindings/js/JSAudioConstructor.cpp index 174cc11..77bb120 100644 --- a/WebCore/bindings/js/JSAudioConstructor.cpp +++ b/WebCore/bindings/js/JSAudioConstructor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,7 +20,7 @@ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" @@ -30,10 +30,7 @@ #include "JSAudioConstructor.h" #include "HTMLAudioElement.h" -#include "HTMLNames.h" #include "JSHTMLAudioElement.h" -#include "ScriptExecutionContext.h" -#include "Text.h" #include <runtime/Error.h> using namespace JSC; @@ -46,24 +43,30 @@ JSAudioConstructor::JSAudioConstructor(ExecState* exec, JSDOMGlobalObject* globa : DOMConstructorWithDocument(JSAudioConstructor::createStructure(globalObject->objectPrototype()), globalObject) { putDirect(exec->propertyNames().prototype, JSHTMLAudioElementPrototype::self(exec, globalObject), None); - putDirect(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly|DontDelete|DontEnum); + putDirect(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontDelete | DontEnum); } static JSObject* constructAudio(ExecState* exec, JSObject* constructor, const ArgList& args) { - JSAudioConstructor* jsAudio = static_cast<JSAudioConstructor*>(constructor); - // FIXME: Why doesn't this need the call toJS on the document like JSImageConstructor? - Document* document = jsAudio->document(); + JSAudioConstructor* jsConstructor = static_cast<JSAudioConstructor*>(constructor); + + Document* document = jsConstructor->document(); if (!document) return throwError(exec, ReferenceError, "Audio constructor associated document is unavailable"); - RefPtr<HTMLAudioElement> audio = new HTMLAudioElement(HTMLNames::audioTag, document); - audio->setAutobuffer(true); - if (args.size() > 0) { - audio->setSrc(args.at(0).toString(exec)); - audio->scheduleLoad(); - } - return asObject(toJS(exec, jsAudio->globalObject(), audio.release())); + // Calling toJS on the document causes the JS document wrapper to be + // added to the window object. This is done to ensure that JSDocument::markChildren + // will be called, which will cause the audio element to be marked if necessary. + toJS(exec, jsConstructor->globalObject(), document); + + // FIXME: This converts an undefined argument to the string "undefined", but possibly we + // should treat it as if no argument was passed instead, by checking the value of args.at + // rather than looking at args.size. + String src; + if (args.size() > 0) + src = args.at(0).toString(exec); + return asObject(toJS(exec, jsConstructor->globalObject(), + HTMLAudioElement::createForJSConstructor(document, src))); } ConstructType JSAudioConstructor::getConstructData(ConstructData& constructData) diff --git a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp b/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp index 6178509..4d5de79 100644 --- a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp +++ b/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp @@ -77,7 +77,7 @@ bool JSCustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, // Therefore an exception and returning true are the same thing - so, return true on an exception return true; } - return result.toBoolean(exec); + return !result.isFalse(); } } diff --git a/WebCore/bindings/js/JSDOMBinding.cpp b/WebCore/bindings/js/JSDOMBinding.cpp index d718cba..abba405 100644 --- a/WebCore/bindings/js/JSDOMBinding.cpp +++ b/WebCore/bindings/js/JSDOMBinding.cpp @@ -151,11 +151,9 @@ DOMWrapperWorld::DOMWrapperWorld(JSC::JSGlobalData* globalData, bool isNormal) DOMWrapperWorld::~DOMWrapperWorld() { - if (m_globalData) { - JSGlobalData::ClientData* clientData = m_globalData->clientData; - ASSERT(clientData); - static_cast<WebCoreJSClientData*>(clientData)->forgetWorld(this); - } + JSGlobalData::ClientData* clientData = m_globalData->clientData; + ASSERT(clientData); + static_cast<WebCoreJSClientData*>(clientData)->forgetWorld(this); for (HashSet<Document*>::iterator iter = documentsWithWrappers.begin(); iter != documentsWithWrappers.end(); ++iter) forgetWorldOfDOMNodesForDocument(*iter, this); diff --git a/WebCore/bindings/js/JSDOMBinding.h b/WebCore/bindings/js/JSDOMBinding.h index 930f9cc..807bf82 100644 --- a/WebCore/bindings/js/JSDOMBinding.h +++ b/WebCore/bindings/js/JSDOMBinding.h @@ -144,7 +144,6 @@ namespace WebCore { } ~DOMWrapperWorld(); - void detachFromGlobalData() { m_globalData = 0; } void rememberDocument(Document* document) { documentsWithWrappers.add(document); } void forgetDocument(Document* document) { documentsWithWrappers.remove(document); } @@ -201,7 +200,9 @@ namespace WebCore { { ASSERT(m_worldSet.contains(m_normalWorld.get())); ASSERT(m_worldSet.size() == 1); - m_normalWorld->detachFromGlobalData(); + ASSERT(m_normalWorld->hasOneRef()); + m_normalWorld.clear(); + ASSERT(m_worldSet.isEmpty()); } DOMWrapperWorld* normalWorld() { return m_normalWorld.get(); } diff --git a/WebCore/bindings/js/JSDOMWindowCustom.cpp b/WebCore/bindings/js/JSDOMWindowCustom.cpp index b8cd1dc..bbd4a51 100644 --- a/WebCore/bindings/js/JSDOMWindowCustom.cpp +++ b/WebCore/bindings/js/JSDOMWindowCustom.cpp @@ -912,13 +912,13 @@ JSValue JSDOMWindow::postMessage(ExecState* exec, const ArgList& args) JSValue JSDOMWindow::setTimeout(ExecState* exec, const ArgList& args) { - ScheduledAction* action = ScheduledAction::create(exec, args, currentWorld(exec)); + OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, args, currentWorld(exec)); if (exec->hadException()) return jsUndefined(); int delay = args.at(1).toInt32(exec); ExceptionCode ec = 0; - int result = impl()->setTimeout(action, delay, ec); + int result = impl()->setTimeout(action.release(), delay, ec); setDOMException(exec, ec); return jsNumber(exec, result); @@ -926,13 +926,13 @@ JSValue JSDOMWindow::setTimeout(ExecState* exec, const ArgList& args) JSValue JSDOMWindow::setInterval(ExecState* exec, const ArgList& args) { - ScheduledAction* action = ScheduledAction::create(exec, args, currentWorld(exec)); + OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, args, currentWorld(exec)); if (exec->hadException()) return jsUndefined(); int delay = args.at(1).toInt32(exec); ExceptionCode ec = 0; - int result = impl()->setInterval(action, delay, ec); + int result = impl()->setInterval(action.release(), delay, ec); setDOMException(exec, ec); return jsNumber(exec, result); @@ -954,7 +954,7 @@ JSValue JSDOMWindow::atob(ExecState* exec, const ArgList& args) } Vector<char> in(s.size()); - for (int i = 0; i < s.size(); ++i) + for (unsigned i = 0; i < s.size(); ++i) in[i] = static_cast<char>(s.data()[i]); Vector<char> out; @@ -980,7 +980,7 @@ JSValue JSDOMWindow::btoa(ExecState* exec, const ArgList& args) } Vector<char> in(s.size()); - for (int i = 0; i < s.size(); ++i) + for (unsigned i = 0; i < s.size(); ++i) in[i] = static_cast<char>(s.data()[i]); Vector<char> out; diff --git a/WebCore/bindings/js/JSImageConstructor.cpp b/WebCore/bindings/js/JSImageConstructor.cpp index 0f4a991..a574326 100644 --- a/WebCore/bindings/js/JSImageConstructor.cpp +++ b/WebCore/bindings/js/JSImageConstructor.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,7 +24,6 @@ #include "HTMLNames.h" #include "JSHTMLImageElement.h" #include "JSNode.h" -#include "ScriptExecutionContext.h" #include <runtime/Error.h> using namespace JSC; @@ -43,35 +42,30 @@ JSImageConstructor::JSImageConstructor(ExecState* exec, JSDOMGlobalObject* globa static JSObject* constructImage(ExecState* exec, JSObject* constructor, const ArgList& args) { - bool widthSet = false; - bool heightSet = false; - int width = 0; - int height = 0; - if (args.size() > 0) { - widthSet = true; - width = args.at(0).toInt32(exec); - } - if (args.size() > 1) { - heightSet = true; - height = args.at(1).toInt32(exec); - } - JSImageConstructor* jsConstructor = static_cast<JSImageConstructor*>(constructor); Document* document = jsConstructor->document(); if (!document) return throwError(exec, ReferenceError, "Image constructor associated document is unavailable"); // Calling toJS on the document causes the JS document wrapper to be - // added to the window object. This is done to ensure that JSDocument::mark - // will be called (which will cause the image element to be marked if necessary). + // added to the window object. This is done to ensure that JSDocument::markChildren + // will be called, which will cause the image element to be marked if necessary. toJS(exec, jsConstructor->globalObject(), document); + int width; + int height; + int* optionalWidth = 0; + int* optionalHeight = 0; + if (args.size() > 0) { + width = args.at(0).toInt32(exec); + optionalWidth = &width; + } + if (args.size() > 1) { + height = args.at(1).toInt32(exec); + optionalHeight = &height; + } - RefPtr<HTMLImageElement> image = new HTMLImageElement(HTMLNames::imgTag, document); - if (widthSet) - image->setWidth(width); - if (heightSet) - image->setHeight(height); - return asObject(toJS(exec, jsConstructor->globalObject(), image.release())); + return asObject(toJS(exec, jsConstructor->globalObject(), + HTMLImageElement::createForJSConstructor(document, optionalWidth, optionalHeight))); } ConstructType JSImageConstructor::getConstructData(ConstructData& constructData) diff --git a/WebCore/bindings/js/JSOptionConstructor.cpp b/WebCore/bindings/js/JSOptionConstructor.cpp index 7da0666..995903e 100644 --- a/WebCore/bindings/js/JSOptionConstructor.cpp +++ b/WebCore/bindings/js/JSOptionConstructor.cpp @@ -49,21 +49,18 @@ static JSObject* constructHTMLOptionElement(ExecState* exec, JSObject* construct if (!document) return throwError(exec, ReferenceError, "Option constructor associated document is unavailable"); - RefPtr<HTMLOptionElement> element = static_pointer_cast<HTMLOptionElement>(document->createElement(HTMLNames::optionTag, false)); - - ExceptionCode ec = 0; - RefPtr<Text> text = document->createTextNode(""); + String data; if (!args.at(0).isUndefined()) - text->setData(args.at(0).toString(exec), ec); - if (ec == 0) - element->appendChild(text.release(), ec); - if (ec == 0 && !args.at(1).isUndefined()) - element->setValue(args.at(1).toString(exec)); - if (ec == 0) - element->setDefaultSelected(args.at(2).toBoolean(exec)); - if (ec == 0) - element->setSelected(args.at(3).toBoolean(exec)); + data = args.at(0).toString(exec); + String value; + if (!args.at(1).isUndefined()) + value = args.at(1).toString(exec); + bool defaultSelected = args.at(2).toBoolean(exec); + bool selected = args.at(3).toBoolean(exec); + + ExceptionCode ec = 0; + RefPtr<HTMLOptionElement> element = HTMLOptionElement::createForJSConstructor(document, data, value, defaultSelected, selected, ec); if (ec) { setDOMException(exec, ec); return 0; diff --git a/WebCore/bindings/js/JSWorkerContextCustom.cpp b/WebCore/bindings/js/JSWorkerContextCustom.cpp index d6c8dbd..bf9409c 100644 --- a/WebCore/bindings/js/JSWorkerContextCustom.cpp +++ b/WebCore/bindings/js/JSWorkerContextCustom.cpp @@ -143,20 +143,20 @@ JSValue JSWorkerContext::removeEventListener(ExecState* exec, const ArgList& arg JSValue JSWorkerContext::setTimeout(ExecState* exec, const ArgList& args) { - ScheduledAction* action = ScheduledAction::create(exec, args, currentWorld(exec)); + OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, args, currentWorld(exec)); if (exec->hadException()) return jsUndefined(); int delay = args.at(1).toInt32(exec); - return jsNumber(exec, impl()->setTimeout(action, delay)); + return jsNumber(exec, impl()->setTimeout(action.release(), delay)); } JSValue JSWorkerContext::setInterval(ExecState* exec, const ArgList& args) { - ScheduledAction* action = ScheduledAction::create(exec, args, currentWorld(exec)); + OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, args, currentWorld(exec)); if (exec->hadException()) return jsUndefined(); int delay = args.at(1).toInt32(exec); - return jsNumber(exec, impl()->setInterval(action, delay)); + return jsNumber(exec, impl()->setInterval(action.release(), delay)); } diff --git a/WebCore/inspector/JavaScriptProfile.cpp b/WebCore/bindings/js/JavaScriptProfile.cpp index 2203f0b..8e56ed8 100644 --- a/WebCore/inspector/JavaScriptProfile.cpp +++ b/WebCore/bindings/js/JavaScriptProfile.cpp @@ -26,14 +26,14 @@ #include "config.h" #include "JavaScriptProfile.h" -#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) +#if ENABLE(JAVASCRIPT_DEBUGGER) #include "JavaScriptProfileNode.h" -#include <profiler/Profile.h> #include <JavaScriptCore/APICast.h> #include <JavaScriptCore/JSObjectRef.h> #include <JavaScriptCore/JSStringRef.h> #include <JavaScriptCore/OpaqueJSString.h> +#include <profiler/Profile.h> #include <runtime/JSObject.h> #include <runtime/JSValue.h> #include <wtf/StdLibExtras.h> @@ -47,7 +47,7 @@ namespace WebCore { typedef HashMap<Profile*, JSObject*> ProfileMap; static ProfileMap& profileCache() -{ +{ DEFINE_STATIC_LOCAL(ProfileMap, staticProfiles, ()); return staticProfiles; } diff --git a/WebCore/inspector/JavaScriptProfile.h b/WebCore/bindings/js/JavaScriptProfile.h index 2500881..7b75b97 100644 --- a/WebCore/inspector/JavaScriptProfile.h +++ b/WebCore/bindings/js/JavaScriptProfile.h @@ -26,18 +26,18 @@ #ifndef JavaScriptProfile_h #define JavaScriptProfile_h -#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) +#if ENABLE(JAVASCRIPT_DEBUGGER) #include <runtime/JSValue.h> namespace JSC { - class ExecState; - class Profile; +class ExecState; +class Profile; } namespace WebCore { - JSC::JSValue toJS(JSC::ExecState*, JSC::Profile*); +JSC::JSValue toJS(JSC::ExecState*, JSC::Profile*); } // namespace WebCore diff --git a/WebCore/inspector/JavaScriptProfileNode.cpp b/WebCore/bindings/js/JavaScriptProfileNode.cpp index 6387c85..7d60b24 100644 --- a/WebCore/inspector/JavaScriptProfileNode.cpp +++ b/WebCore/bindings/js/JavaScriptProfileNode.cpp @@ -26,15 +26,15 @@ #include "config.h" #include "JavaScriptProfileNode.h" -#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) +#if ENABLE(JAVASCRIPT_DEBUGGER) #include "JSDOMBinding.h" -#include <profiler/ProfileNode.h> #include <JavaScriptCore/APICast.h> -#include <JavaScriptCore/JSObjectRef.h> #include <JavaScriptCore/JSContextRef.h> +#include <JavaScriptCore/JSObjectRef.h> #include <JavaScriptCore/JSRetainPtr.h> #include <JavaScriptCore/JSStringRef.h> +#include <profiler/ProfileNode.h> #include <runtime/JSLock.h> #include <runtime/JSValue.h> #include <wtf/StdLibExtras.h> diff --git a/WebCore/inspector/JavaScriptProfileNode.h b/WebCore/bindings/js/JavaScriptProfileNode.h index 2685ac6..f01be19 100644 --- a/WebCore/inspector/JavaScriptProfileNode.h +++ b/WebCore/bindings/js/JavaScriptProfileNode.h @@ -26,20 +26,20 @@ #ifndef JavaScriptProfileNode_h #define JavaScriptProfileNode_h -#if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) +#if ENABLE(JAVASCRIPT_DEBUGGER) -#include <runtime/JSValue.h> #include <JavaScriptCore/JSBase.h> +#include <runtime/JSValue.h> namespace JSC { - class ExecState; - class ProfileNode; +class ExecState; +class ProfileNode; } namespace WebCore { - JSClassRef ProfileNodeClass(); - JSC::JSValue toJS(JSC::ExecState*, JSC::ProfileNode*); +JSClassRef ProfileNodeClass(); +JSC::JSValue toJS(JSC::ExecState*, JSC::ProfileNode*); } // namespace WebCore diff --git a/WebCore/bindings/js/ScheduledAction.cpp b/WebCore/bindings/js/ScheduledAction.cpp index be90125..be62bb8 100644 --- a/WebCore/bindings/js/ScheduledAction.cpp +++ b/WebCore/bindings/js/ScheduledAction.cpp @@ -47,7 +47,7 @@ using namespace JSC; namespace WebCore { -ScheduledAction* ScheduledAction::create(ExecState* exec, const ArgList& args, DOMWrapperWorld* isolatedWorld) +PassOwnPtr<ScheduledAction> ScheduledAction::create(ExecState* exec, const ArgList& args, DOMWrapperWorld* isolatedWorld) { JSValue v = args.at(0); CallData callData; diff --git a/WebCore/bindings/js/ScheduledAction.h b/WebCore/bindings/js/ScheduledAction.h index dd13ab1..3b7e001 100644 --- a/WebCore/bindings/js/ScheduledAction.h +++ b/WebCore/bindings/js/ScheduledAction.h @@ -24,6 +24,7 @@ #include <JSDOMBinding.h> #include <runtime/JSCell.h> #include <runtime/Protect.h> +#include <wtf/PassOwnPtr.h> #include <wtf/Vector.h> namespace JSC { @@ -42,7 +43,7 @@ namespace WebCore { */ class ScheduledAction : public Noncopyable { public: - static ScheduledAction* create(JSC::ExecState*, const JSC::ArgList&, DOMWrapperWorld* isolatedWorld); + static PassOwnPtr<ScheduledAction> create(JSC::ExecState*, const JSC::ArgList&, DOMWrapperWorld* isolatedWorld); void execute(ScriptExecutionContext*); @@ -56,7 +57,7 @@ namespace WebCore { void executeFunctionInContext(JSC::JSGlobalObject*, JSC::JSValue thisValue); void execute(Document*); -#if ENABLE(WORKERS) +#if ENABLE(WORKERS) void execute(WorkerContext*); #endif diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp index 4e8ba5e..40a71be 100644 --- a/WebCore/bindings/v8/ScriptController.cpp +++ b/WebCore/bindings/v8/ScriptController.cpp @@ -171,7 +171,7 @@ bool ScriptController::processingUserGesture(DOMWrapperWorld*) const v8::Handle<v8::Object> global = v8Context->Global(); v8::Handle<v8::Value> jsEvent = global->Get(v8::String::NewSymbol("event")); - Event* event = (!jsEvent.IsEmpty() && jsEvent->IsObject()) ? V8Event::toNative(v8::Handle<v8::Object>::Cast(jsEvent)) : 0; + Event* event = V8DOMWrapper::isValidDOMObject(jsEvent) ? V8Event::toNative(v8::Handle<v8::Object>::Cast(jsEvent)) : 0; // Based on code from kjs_bindings.cpp. // Note: This is more liberal than Firefox's implementation. diff --git a/WebCore/bindings/v8/V8DOMWrapper.cpp b/WebCore/bindings/v8/V8DOMWrapper.cpp index d567a49..cf11e6c 100644 --- a/WebCore/bindings/v8/V8DOMWrapper.cpp +++ b/WebCore/bindings/v8/V8DOMWrapper.cpp @@ -300,7 +300,7 @@ v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassI proxy = V8Proxy::retrieve(V8DOMWindow::toNative(globalPrototype)->frame()); #if ENABLE(WORKERS) else - workerContext = V8WorkerContext::toNative(globalPrototype); + workerContext = V8WorkerContext::toNative(lookupDOMWrapper(V8WorkerContext::GetTemplate(), context->Global())); #endif } } @@ -349,15 +349,19 @@ bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value) } #endif -bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8WrapperType classType) +bool V8DOMWrapper::isValidDOMObject(v8::Handle<v8::Value> value) { if (value.IsEmpty() || !value->IsObject()) return false; + return v8::Handle<v8::Object>::Cast(value)->InternalFieldCount(); +} - v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); - if (!object->InternalFieldCount()) +bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8WrapperType classType) +{ + if (!isValidDOMObject(value)) return false; + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); ASSERT(object->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount); v8::Handle<v8::Value> wrapper = object->GetInternalField(v8DOMWrapperObjectIndex); diff --git a/WebCore/bindings/v8/V8DOMWrapper.h b/WebCore/bindings/v8/V8DOMWrapper.h index afac577..8a3fa3f 100644 --- a/WebCore/bindings/v8/V8DOMWrapper.h +++ b/WebCore/bindings/v8/V8DOMWrapper.h @@ -179,6 +179,8 @@ namespace WebCore { static void setJSWrapperForActiveDOMObject(void*, v8::Persistent<v8::Object>); static void setJSWrapperForDOMNode(Node*, v8::Persistent<v8::Object>); + static bool isValidDOMObject(v8::Handle<v8::Value>); + // Check whether a V8 value is a wrapper of type |classType|. static bool isWrapperOfType(v8::Handle<v8::Value>, V8ClassIndex::V8WrapperType); diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp index 84a3b96..f733ede 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp @@ -75,10 +75,9 @@ bool V8CustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, // statement, if any, or onto the next overall step otherwise. Otherwise, // the error callback did not return false, or there was no error callback. // Jump to the last step in the overall steps. - return invokeCallback(m_callback, 2, argv, callbackReturnValue) || callbackReturnValue; + return invokeCallbackTreatOnlyExplicitFalseAsFalse(m_callback, 2, argv, callbackReturnValue) || callbackReturnValue; } } // namespace WebCore #endif - diff --git a/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp b/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp index 94cb104..8c69e76 100644 --- a/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp @@ -64,7 +64,7 @@ void V8CustomVoidCallback::handleEvent() invokeCallback(m_callback, 0, 0, callbackReturnValue); } -bool invokeCallback(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue) +static bool invokeCallbackHelper(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], v8::Handle<v8::Value>& returnValue) { v8::TryCatch exceptionCatcher; @@ -87,9 +87,7 @@ bool invokeCallback(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8 V8Proxy* proxy = V8Proxy::retrieve(); ASSERT(proxy); - v8::Handle<v8::Value> result = proxy->callFunction(callbackFunction, thisObject, argc, argv); - - callbackReturnValue = !result.IsEmpty() && result->IsBoolean() && result->BooleanValue(); + returnValue = proxy->callFunction(callbackFunction, thisObject, argc, argv); if (exceptionCatcher.HasCaught()) { v8::Local<v8::Message> message = exceptionCatcher.Message(); @@ -100,4 +98,20 @@ bool invokeCallback(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8 return false; } +bool invokeCallback(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue) +{ + v8::Handle<v8::Value> returnValue; + bool result = invokeCallbackHelper(callback, argc, argv, returnValue); + callbackReturnValue = !returnValue.IsEmpty() && returnValue->IsBoolean() && returnValue->BooleanValue(); + return result; +} + +bool invokeCallbackTreatOnlyExplicitFalseAsFalse(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue) +{ + v8::Handle<v8::Value> returnValue; + bool result = invokeCallbackHelper(callback, argc, argv, returnValue); + callbackReturnValue = !returnValue.IsEmpty() && !returnValue->IsFalse(); + return result; +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomVoidCallback.h b/WebCore/bindings/v8/custom/V8CustomVoidCallback.h index 586296b..6b7b3e8 100644 --- a/WebCore/bindings/v8/custom/V8CustomVoidCallback.h +++ b/WebCore/bindings/v8/custom/V8CustomVoidCallback.h @@ -60,6 +60,7 @@ private: // Returns false if callback failed (null, wrong type, or threw exception). bool invokeCallback(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue); +bool invokeCallbackTreatOnlyExplicitFalseAsFalse(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue); } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp b/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp index abd6ff6..9915d77 100644 --- a/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp @@ -104,7 +104,7 @@ static v8::Handle<v8::Value> createTransaction(const v8::Arguments& args, bool r RefPtr<V8CustomSQLTransactionCallback> callback = V8CustomSQLTransactionCallback::create(args[0], frame); RefPtr<V8CustomSQLTransactionErrorCallback> errorCallback; - if (args.Length() > 1) { + if (args.Length() > 1 && !isUndefinedOrNull(args[1])) { if (!args[1]->IsObject()) return throwError("Transaction error callback must be of valid type."); @@ -112,7 +112,7 @@ static v8::Handle<v8::Value> createTransaction(const v8::Arguments& args, bool r } RefPtr<V8CustomVoidCallback> successCallback; - if (args.Length() > 2) { + if (args.Length() > 2 && !isUndefinedOrNull(args[2])) { if (!args[2]->IsObject()) return throwError("Transaction success callback must be of valid type."); diff --git a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp index 06c6c1d..9b75db8 100644 --- a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp @@ -14,7 +14,7 @@ * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -60,15 +60,14 @@ static v8::Handle<v8::Value> v8HTMLAudioElementConstructorCallback(const v8::Arg return throwError("Audio constructor associated document is unavailable", V8Proxy::ReferenceError); // Make sure the document is added to the DOM Node map. Otherwise, the HTMLAudioElement instance - // may end up being the only node in the map and get garbage-ccollected prematurely. + // may end up being the only node in the map and get garbage-collected prematurely. toV8(document); - RefPtr<HTMLAudioElement> audio = new HTMLAudioElement(HTMLNames::audioTag, document); - audio->setAutobuffer(true); - if (args.Length() > 0) { - audio->setSrc(toWebCoreString(args[0])); - audio->scheduleLoad(); - } + + String src; + if (args.Length() > 0) + src = toWebCoreString(args[0]); + RefPtr<HTMLAudioElement> audio = HTMLAudioElement::createForJSConstructor(document, src); V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::AUDIO), audio.get()); audio->ref(); diff --git a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp index 1873188..29b4813 100644 --- a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2009, 2010 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -14,7 +14,7 @@ * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -61,15 +61,25 @@ static v8::Handle<v8::Value> v8HTMLImageElementConstructorCallback(const v8::Arg // Make sure the document is added to the DOM Node map. Otherwise, the HTMLImageElement instance // may end up being the only node in the map and get garbage-ccollected prematurely. + // FIXME: The correct way to do this would be to make HTMLImageElement derive from + // ActiveDOMObject and use its interface to keep its wrapper alive. Then we would + // remove this code and the special case in isObservableThroughDOM. toV8(document); - RefPtr<HTMLImageElement> image = new HTMLImageElement(HTMLNames::imgTag, document); + int width; + int height; + int* optionalWidth = 0; + int* optionalHeight = 0; if (args.Length() > 0) { - image->setWidth(toInt32(args[0])); - if (args.Length() > 1) - image->setHeight(toInt32(args[1])); + width = toInt32(args[0]); + optionalWidth = &width; + } + if (args.Length() > 1) { + height = toInt32(args[1]); + optionalHeight = &height; } + RefPtr<HTMLImageElement> image = HTMLImageElement::createForJSConstructor(document, optionalWidth, optionalHeight); V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::IMAGE), image.get()); image->ref(); V8DOMWrapper::setJSWrapperForDOMNode(image.get(), v8::Persistent<v8::Object>::New(args.Holder())); diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp index 3113eb5..1ff1d2e 100644 --- a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp @@ -14,7 +14,7 @@ * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -59,32 +59,24 @@ static v8::Handle<v8::Value> v8HTMLOptionElementConstructorCallback(const v8::Ar if (!document) return throwError("Option constructor associated document is unavailable", V8Proxy::ReferenceError); - RefPtr<HTMLOptionElement> option = new HTMLOptionElement(HTMLNames::optionTag, document); + String data; + String value; + bool defaultSelected = false; + bool selected = false; + if (args.Length() > 0 && !args[0]->IsUndefined()) + data = toWebCoreString(args[0]); + if (args.Length() > 1 && !args[1]->IsUndefined()) + value = toWebCoreString(args[1]); + if (args.Length() > 2) + defaultSelected = args[2]->BooleanValue(); + if (args.Length() > 3) + selected = args[3]->BooleanValue(); ExceptionCode ec = 0; - RefPtr<Text> text = document->createTextNode(""); - if (args.Length() > 0) { - if (!args[0]->IsUndefined()) { - text->setData(toWebCoreString(args[0]), ec); - if (ec) - throwError(ec); - } - - option->appendChild(text.release(), ec); - if (ec) - throwError(ec); - - if (args.Length() > 1) { - if (!args[1]->IsUndefined()) - option->setValue(toWebCoreString(args[1])); - - if (args.Length() > 2) { - option->setDefaultSelected(args[2]->BooleanValue()); - if (args.Length() > 3) - option->setSelected(args[3]->BooleanValue()); - } - } - } + RefPtr<HTMLOptionElement> option = HTMLOptionElement::createForJSConstructor(document, data, value, defaultSelected, selected, ec); + + if (ec) + throwError(ec); V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::OPTION), option.get()); option->ref(); diff --git a/WebCore/bridge/NP_jsobject.cpp b/WebCore/bridge/NP_jsobject.cpp index 09851df..2b1d17f 100644 --- a/WebCore/bridge/NP_jsobject.cpp +++ b/WebCore/bridge/NP_jsobject.cpp @@ -51,6 +51,64 @@ using namespace JSC; using namespace JSC::Bindings; using namespace WebCore; +class ObjectMap { +public: + NPObject* get(RootObject* rootObject, JSObject* jsObject) + { + return m_map.get(rootObject).get(jsObject); + } + + void add(RootObject* rootObject, JSObject* jsObject, NPObject* npObject) + { + HashMap<RootObject*, JSToNPObjectMap>::iterator iter = m_map.find(rootObject); + if (iter == m_map.end()) { + rootObject->addInvalidationCallback(&m_invalidationCallback); + iter = m_map.add(rootObject, JSToNPObjectMap()).first; + } + + ASSERT(iter->second.find(jsObject) == iter->second.end()); + iter->second.add(jsObject, npObject); + } + + void remove(RootObject* rootObject) + { + HashMap<RootObject*, JSToNPObjectMap>::iterator iter = m_map.find(rootObject); + ASSERT(iter != m_map.end()); + m_map.remove(iter); + } + + void remove(RootObject* rootObject, JSObject* jsObject) + { + HashMap<RootObject*, JSToNPObjectMap>::iterator iter = m_map.find(rootObject); + ASSERT(iter != m_map.end()); + ASSERT(iter->second.find(jsObject) != iter->second.end()); + + iter->second.remove(jsObject); + } + +private: + struct RootObjectInvalidationCallback : public RootObject::InvalidationCallback { + virtual void operator()(RootObject*); + }; + RootObjectInvalidationCallback m_invalidationCallback; + + // JSObjects are protected by RootObject. + typedef HashMap<JSObject*, NPObject*> JSToNPObjectMap; + HashMap<RootObject*, JSToNPObjectMap> m_map; +}; + + +static ObjectMap& objectMap() +{ + DEFINE_STATIC_LOCAL(ObjectMap, map, ()); + return map; +} + +void ObjectMap::RootObjectInvalidationCallback::operator()(RootObject* rootObject) +{ + objectMap().remove(rootObject); +} + static void getListFromVariantArgs(ExecState* exec, const NPVariant* args, unsigned argCount, RootObject* rootObject, MarkedArgumentBuffer& aList) { for (unsigned i = 0; i < argCount; ++i) @@ -66,8 +124,10 @@ static void jsDeallocate(NPObject* npObj) { JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(npObj); - if (obj->rootObject && obj->rootObject->isValid()) + if (obj->rootObject && obj->rootObject->isValid()) { + objectMap().remove(obj->rootObject, obj->imp); obj->rootObject->gcUnprotect(obj->imp); + } if (obj->rootObject) obj->rootObject->deref(); @@ -83,12 +143,18 @@ static NPClass* NPNoScriptObjectClass = &noScriptClass; NPObject* _NPN_CreateScriptObject(NPP npp, JSObject* imp, PassRefPtr<RootObject> rootObject) { + if (NPObject* object = objectMap().get(rootObject.get(), imp)) + return _NPN_RetainObject(object); + JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(_NPN_CreateObject(npp, NPScriptObjectClass)); obj->rootObject = rootObject.releaseRef(); - if (obj->rootObject) + if (obj->rootObject) { obj->rootObject->gcProtect(imp); + objectMap().add(obj->rootObject, imp, reinterpret_cast<NPObject*>(obj)); + } + obj->imp = imp; return reinterpret_cast<NPObject*>(obj); diff --git a/WebCore/bridge/jni/jsc/JavaStringJSC.h b/WebCore/bridge/jni/jsc/JavaStringJSC.h index 720f887..7c37f70 100644 --- a/WebCore/bridge/jni/jsc/JavaStringJSC.h +++ b/WebCore/bridge/jni/jsc/JavaStringJSC.h @@ -69,7 +69,7 @@ public: return m_utf8String.c_str(); } const jchar* uchars() const { return (const jchar*)m_rep->data(); } - int length() const { return m_rep->size(); } + int length() const { return m_rep->length(); } UString uString() const { return UString(m_rep); } private: diff --git a/WebCore/bridge/qt/qt_pixmapruntime.cpp b/WebCore/bridge/qt/qt_pixmapruntime.cpp index edae5a9..5978804 100644 --- a/WebCore/bridge/qt/qt_pixmapruntime.cpp +++ b/WebCore/bridge/qt/qt_pixmapruntime.cpp @@ -20,11 +20,7 @@ #include "qt_pixmapruntime.h" #include "CachedImage.h" -#include "DOMWindow.h" #include "HTMLImageElement.h" -#include "HTMLNames.h" -#include "JSDOMBinding.h" -#include "JSDOMWindow.h" #include "JSGlobalObject.h" #include "JSHTMLImageElement.h" #include "JSLock.h" @@ -54,18 +50,19 @@ public: class QtPixmapWidthField : public Field { public: static const char* name() { return "width"; } - virtual JSValue valueFromInstance(ExecState* exec, const Instance* pixmap) const + virtual JSValue valueFromInstance(ExecState* exec, const Instance* instance) const { - return jsNumber(exec, static_cast<const QtPixmapInstance*>(pixmap)->width()); + return jsNumber(exec, static_cast<const QtPixmapInstance*>(instance)->width()); } virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const {} }; + class QtPixmapHeightField : public Field { public: static const char* name() { return "height"; } - virtual JSValue valueFromInstance(ExecState* exec, const Instance* inst) const + virtual JSValue valueFromInstance(ExecState* exec, const Instance* instance) const { - return jsNumber(exec, static_cast<const QtPixmapInstance*>(inst)->height()); + return jsNumber(exec, static_cast<const QtPixmapInstance*>(instance)->height()); } virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const {} }; @@ -76,77 +73,68 @@ public: { return 0; } - virtual JSValue invoke(ExecState* exec, QVariant&, PassRefPtr<RootObject> root, QtPixmapInstance* inst) = 0; + virtual JSValue invoke(ExecState* exec, QtPixmapInstance*, const ArgList&) = 0; }; -class QtPixmapCreateElementMethod : public QtPixmapRuntimeMethod { +// this function receives an HTML image element as a parameter, makes it display the pixmap/image from Qt +class QtPixmapAssignToElementMethod : public QtPixmapRuntimeMethod { public: - static const char* name() { return "toHTMLImageElement"; } - JSValue invoke(ExecState* exec, QVariant& v, PassRefPtr<RootObject> root, QtPixmapInstance*) + static const char* name() { return "assignToHTMLImageElement"; } + JSValue invoke(ExecState* exec, QtPixmapInstance* instance, const ArgList& args) { - QPixmap pxm; - if (v.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>())) { - pxm = QPixmap::fromImage(v.value<QImage>()); - v = QVariant::fromValue<QPixmap>(pxm); - } else - pxm = v.value<QPixmap>(); - - Document* document = 0; - JSDOMGlobalObject* global = static_cast<JSDOMGlobalObject*>(root->globalObject()); - if (global) { - DOMWindow* dWindow = toDOMWindow(global); - if (dWindow) - document = dWindow->document(); - } - - if (document) { - PassRefPtr<StillImage> img = WebCore::StillImage::create(pxm); - RefPtr<HTMLImageElement> image = new HTMLImageElement(HTMLNames::imgTag, document); - image->setCachedImage(new CachedImage(img.get())); - toJS(exec, global, document); - return asObject(toJS(exec, global, image.release())); - } + if (!args.size()) + return jsUndefined(); + + JSObject* objectArg = args.at(0).toObject(exec); + if (!objectArg) + return jsUndefined(); + + if (!objectArg->inherits(&JSHTMLImageElement::s_info)) + return jsUndefined(); + + // we now know that we have a valid <img> element as the argument, we can attach the pixmap to it. + PassRefPtr<StillImage> stillImage = WebCore::StillImage::create(instance->toPixmap()); + HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(static_cast<JSHTMLImageElement*>(objectArg)->impl()); + imageElement->setCachedImage(new CachedImage(stillImage.get())); + JSDOMGlobalObject* global = static_cast<JSDOMGlobalObject*>(instance->rootObject()->globalObject()); + toJS(exec, global, imageElement->document()); return jsUndefined(); } + virtual int numParameters() const + { + return 1; + } }; +// this function encodes the image to a dataUrl, to be used in background etc. Note: very slow. class QtPixmapToDataUrlMethod : public QtPixmapRuntimeMethod { public: static const char* name() { return "toDataUrl"; } - JSValue invoke(ExecState* exec, QVariant& v, PassRefPtr<RootObject> root, QtPixmapInstance*) + JSValue invoke(ExecState* exec, QtPixmapInstance* instance, const ArgList&) { - QImage image; - // for getting the data url, we always prefer the image. - if (v.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>())) { - image = v.value<QPixmap>().toImage(); - v = QVariant::fromValue<QImage>(image); - } else - image = v.value<QImage>(); - QByteArray ba; - QBuffer b(&ba); - image.save(&b, "PNG"); - const QString b64 = QString("data:image/png;base64,") + ba.toBase64(); - const UString ustring((UChar*)b64.utf16(), b64.length()); + QByteArray byteArray; + QBuffer buffer(&byteArray); + instance->toImage().save(&buffer, "PNG"); + const QString encodedString = QString("data:image/png;base64,") + byteArray.toBase64(); + const UString ustring((UChar*)encodedString.utf16(), encodedString.length()); return jsString(exec, ustring); } - }; class QtPixmapToStringMethod : public QtPixmapRuntimeMethod { public: static const char* name() { return "toString"; } - JSValue invoke(ExecState* exec, QVariant& v, PassRefPtr<RootObject> root, QtPixmapInstance* inst) + JSValue invoke(ExecState* exec, QtPixmapInstance* instance, const ArgList&) { - return inst->valueOf(exec); + return instance->valueOf(exec); } - }; struct QtPixmapMetaData { QtPixmapToDataUrlMethod toDataUrlMethod; - QtPixmapCreateElementMethod createElementMethod; + QtPixmapAssignToElementMethod assignToElementMethod; QtPixmapToStringMethod toStringMethod; QtPixmapHeightField heightField; QtPixmapWidthField widthField; @@ -179,7 +167,6 @@ QtPixmapRuntimeObjectImp::QtPixmapRuntimeObjectImp(ExecState* exec, PassRefPtr<I const ClassInfo QtPixmapRuntimeObjectImp::s_info = { "QtPixmapRuntimeObject", &RuntimeObjectImp::s_info, 0, 0 }; - QtPixmapClass::QtPixmapClass() { } @@ -193,8 +180,8 @@ Class* QtPixmapInstance::getClass() const JSValue QtPixmapInstance::invokeMethod(ExecState* exec, const MethodList& methods, const ArgList& args) { if (methods.size() == 1) { - QtPixmapRuntimeMethod* mtd = static_cast<QtPixmapRuntimeMethod*>(methods[0]); - return mtd->invoke(exec, data, rootObject(), this); + QtPixmapRuntimeMethod* method = static_cast<QtPixmapRuntimeMethod*>(methods[0]); + return method->invoke(exec, this, args); } return jsUndefined(); } @@ -204,8 +191,8 @@ MethodList QtPixmapClass::methodsNamed(const Identifier& identifier, Instance*) MethodList methods; if (identifier == QtPixmapToDataUrlMethod::name()) methods.append(&qt_pixmap_metaData.toDataUrlMethod); - else if (identifier == QtPixmapCreateElementMethod::name()) - methods.append(&qt_pixmap_metaData.createElementMethod); + else if (identifier == QtPixmapAssignToElementMethod::name()) + methods.append(&qt_pixmap_metaData.assignToElementMethod); else if (identifier == QtPixmapToStringMethod::name()) methods.append(&qt_pixmap_metaData.toStringMethod); return methods; @@ -223,7 +210,7 @@ Field* QtPixmapClass::fieldNamed(const Identifier& identifier, Instance*) const void QtPixmapInstance::getPropertyNames(ExecState*exec, PropertyNameArray& arr) { arr.add(Identifier(exec, UString(QtPixmapToDataUrlMethod::name()))); - arr.add(Identifier(exec, UString(QtPixmapCreateElementMethod::name()))); + arr.add(Identifier(exec, UString(QtPixmapAssignToElementMethod::name()))); arr.add(Identifier(exec, UString(QtPixmapToStringMethod::name()))); arr.add(Identifier(exec, UString(QtPixmapWidthField::name()))); arr.add(Identifier(exec, UString(QtPixmapHeightField::name()))); @@ -236,15 +223,17 @@ JSValue QtPixmapInstance::defaultValue(ExecState* exec, PreferredPrimitiveType p (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>()) && !(data.value<QImage>()).isNull()) || (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>()) && !data.value<QPixmap>().isNull())); } + if (ptype == PreferString) return valueOf(exec); + return jsUndefined(); } JSValue QtPixmapInstance::valueOf(ExecState* exec) const { - const QString toStr = QString("[Qt Native Pixmap %1,%2]").arg(width()).arg(height()); - UString ustring((UChar*)toStr.utf16(), toStr.length()); + const QString stringValue = QString("[Qt Native Pixmap %1,%2]").arg(width()).arg(height()); + UString ustring((UChar*)stringValue.utf16(), stringValue.length()); return jsString(exec, ustring); } @@ -275,62 +264,78 @@ QPixmap QtPixmapInstance::toPixmap() { if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>())) return data.value<QPixmap>(); + if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>())) { - const QPixmap pxm = QPixmap::fromImage(data.value<QImage>()); - data = QVariant::fromValue<QPixmap>(pxm); - return pxm; + const QPixmap pixmap = QPixmap::fromImage(data.value<QImage>()); + data = QVariant::fromValue<QPixmap>(pixmap); + return pixmap; } - return QPixmap(); + return QPixmap(); } QImage QtPixmapInstance::toImage() { if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>())) return data.value<QImage>(); + if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>())) { - const QImage img = data.value<QPixmap>().toImage(); - data = QVariant::fromValue<QImage>(img); - return img; + const QImage image = data.value<QPixmap>().toImage(); + data = QVariant::fromValue<QImage>(image); + return image; } + return QImage(); } QVariant QtPixmapInstance::variantFromObject(JSObject* object, QMetaType::Type hint) { - if (!object) { + if (!object) + goto returnEmptyVariant; + + if (object->inherits(&JSHTMLImageElement::s_info)) { + JSHTMLImageElement* elementJSWrapper = static_cast<JSHTMLImageElement*>(object); + HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(elementJSWrapper->impl()); + + if (!imageElement) + goto returnEmptyVariant; + + CachedImage* cachedImage = imageElement->cachedImage(); + if (!cachedImage) + goto returnEmptyVariant; + + Image* image = cachedImage->image(); + if (!image) + goto returnEmptyVariant; + + QPixmap* pixmap = image->nativeImageForCurrentFrame(); + if (!pixmap) + goto returnEmptyVariant; + + return (hint == static_cast<QMetaType::Type>(qMetaTypeId<QPixmap>())) + ? QVariant::fromValue<QPixmap>(*pixmap) + : QVariant::fromValue<QImage>(pixmap->toImage()); + } + + if (object->inherits(&QtPixmapRuntimeObjectImp::s_info)) { + QtPixmapRuntimeObjectImp* imp = static_cast<QtPixmapRuntimeObjectImp*>(object); + QtPixmapInstance* instance = static_cast<QtPixmapInstance*>(imp->getInternalInstance()); + if (!instance) + goto returnEmptyVariant; + if (hint == qMetaTypeId<QPixmap>()) - return QVariant::fromValue<QPixmap>(QPixmap()); + return QVariant::fromValue<QPixmap>(instance->toPixmap()); + if (hint == qMetaTypeId<QImage>()) - return QVariant::fromValue<QImage>(QImage()); - } else if (object->inherits(&JSHTMLImageElement::s_info)) { - JSHTMLImageElement* el = static_cast<JSHTMLImageElement*>(object); - HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(el->impl()); - if (imageElement) { - CachedImage* cImg = imageElement->cachedImage(); - if (cImg) { - Image* img = cImg->image(); - if (img) { - QPixmap* pxm = img->nativeImageForCurrentFrame(); - if (pxm) { - return (hint == static_cast<QMetaType::Type>(qMetaTypeId<QPixmap>())) - ? QVariant::fromValue<QPixmap>(*pxm) - : QVariant::fromValue<QImage>(pxm->toImage()); - } - } - } - } - } else if (object->inherits(&QtPixmapRuntimeObjectImp::s_info)) { - QtPixmapRuntimeObjectImp* imp = static_cast<QtPixmapRuntimeObjectImp*>(object); - QtPixmapInstance* inst = static_cast<QtPixmapInstance*>(imp->getInternalInstance()); - if (inst) { - if (hint == qMetaTypeId<QPixmap >()) - return QVariant::fromValue<QPixmap>(inst->toPixmap()); - if (hint == qMetaTypeId<QImage>()) - return QVariant::fromValue<QImage>(inst->toImage()); - } + return QVariant::fromValue<QImage>(instance->toImage()); } - return 0; + +returnEmptyVariant: + if (hint == qMetaTypeId<QPixmap>()) + return QVariant::fromValue<QPixmap>(QPixmap()); + if (hint == qMetaTypeId<QImage>()) + return QVariant::fromValue<QImage>(QImage()); + return QVariant(); } JSObject* QtPixmapInstance::createRuntimeObject(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& data) { diff --git a/WebCore/bridge/qt/qt_runtime.cpp b/WebCore/bridge/qt/qt_runtime.cpp index 9601a4a..ada9f01 100644 --- a/WebCore/bridge/qt/qt_runtime.cpp +++ b/WebCore/bridge/qt/qt_runtime.cpp @@ -29,7 +29,10 @@ #include "JSArray.h" #include "JSByteArray.h" #include "JSDOMBinding.h" +#include "JSDOMWindow.h" +#include <JSFunction.h> #include "JSGlobalObject.h" +#include "JSHTMLElement.h" #include "JSLock.h" #include "JSObject.h" #include "ObjectPrototype.h" @@ -45,7 +48,7 @@ #include "qt_instance.h" #include "qt_pixmapruntime.h" #include "qvarlengtharray.h" -#include <JSFunction.h> +#include "qwebelement.h" #include <limits.h> #include <runtime/Error.h> #include <runtime_array.h> @@ -114,6 +117,21 @@ QDebug operator<<(QDebug dbg, const JSRealType &c) } #endif +// this is here as a proxy, so we'd have a class to friend in QWebElement, +// as getting/setting a WebCore in QWebElement is private +class QtWebElementRuntime { +public: + static QWebElement create(Element* element) + { + return QWebElement(element); + } + + static Element* get(const QWebElement& element) + { + return element.m_element; + } +}; + static JSRealType valueRealType(ExecState* exec, JSValue val) { if (val.isNumber()) @@ -722,6 +740,11 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type break; } else if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(hint))) { ret = QtPixmapInstance::variantFromObject(object, static_cast<QMetaType::Type>(hint)); + } else if (hint == (QMetaType::Type) qMetaTypeId<QWebElement>()) { + if (object && object->inherits(&JSHTMLElement::s_info)) + ret = QVariant::fromValue<QWebElement>(QtWebElementRuntime::create((static_cast<JSHTMLElement*>(object))->impl())); + else + ret = QVariant::fromValue<QWebElement>(QWebElement()); } else if (hint == (QMetaType::Type) qMetaTypeId<QVariant>()) { if (value.isUndefinedOrNull()) { if (distance) @@ -854,6 +877,17 @@ JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, con if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(variant.type()))) return QtPixmapInstance::createRuntimeObject(exec, root, variant); + if (type == qMetaTypeId<QWebElement>()) { + if (!root->globalObject()->inherits(&JSDOMWindow::s_info)) + return jsUndefined(); + + Document* document = (static_cast<JSDOMWindow*>(root->globalObject()))->impl()->document(); + if (!document) + return jsUndefined(); + + return toJS(exec, toJSDOMGlobalObject(document, exec), QtWebElementRuntime::get(variant.value<QWebElement>())); + } + if (type == QMetaType::QVariantMap) { // create a new object, and stuff properties into it JSObject* ret = constructEmptyObject(exec); diff --git a/WebCore/bridge/runtime_root.cpp b/WebCore/bridge/runtime_root.cpp index 143c3ad..b179d56 100644 --- a/WebCore/bridge/runtime_root.cpp +++ b/WebCore/bridge/runtime_root.cpp @@ -71,6 +71,10 @@ RootObject* findRootObject(JSGlobalObject* globalObject) return 0; } +RootObject::InvalidationCallback::~InvalidationCallback() +{ +} + PassRefPtr<RootObject> RootObject::create(const void* nativeHandle, JSGlobalObject* globalObject) { return adoptRef(new RootObject(nativeHandle, globalObject)); @@ -109,6 +113,14 @@ void RootObject::invalidate() m_nativeHandle = 0; m_globalObject = 0; + { + HashSet<InvalidationCallback*>::iterator end = m_invalidationCallbacks.end(); + for (HashSet<InvalidationCallback*>::iterator iter = m_invalidationCallbacks.begin(); iter != end; ++iter) + (**iter)(this); + + m_invalidationCallbacks.clear(); + } + ProtectCountSet::iterator end = m_protectCountSet.end(); for (ProtectCountSet::iterator it = m_protectCountSet.begin(); it != end; ++it) JSC::gcUnprotect(it->first); diff --git a/WebCore/bridge/runtime_root.h b/WebCore/bridge/runtime_root.h index fdd73c4..a81afb8 100644 --- a/WebCore/bridge/runtime_root.h +++ b/WebCore/bridge/runtime_root.h @@ -72,6 +72,13 @@ public: void addRuntimeObject(RuntimeObjectImp*); void removeRuntimeObject(RuntimeObjectImp*); + + struct InvalidationCallback { + virtual void operator()(RootObject*) = 0; + virtual ~InvalidationCallback(); + }; + void addInvalidationCallback(InvalidationCallback* callback) { m_invalidationCallbacks.add(callback); } + private: RootObject(const void* nativeHandle, JSGlobalObject*); @@ -79,9 +86,11 @@ private: const void* m_nativeHandle; ProtectedPtr<JSGlobalObject> m_globalObject; - ProtectCountSet m_protectCountSet; + ProtectCountSet m_protectCountSet; HashSet<RuntimeObjectImp*> m_runtimeObjects; + + HashSet<InvalidationCallback*> m_invalidationCallbacks; }; } // namespace Bindings diff --git a/WebCore/css/CSSStyleSelector.cpp b/WebCore/css/CSSStyleSelector.cpp index 8f00d2a..f7f2707 100644 --- a/WebCore/css/CSSStyleSelector.cpp +++ b/WebCore/css/CSSStyleSelector.cpp @@ -1119,7 +1119,8 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document) fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1); int size = CSSStyleSelector::fontSizeForKeyword(document, CSSValueMedium, false); fontDescription.setSpecifiedSize(size); - fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, fontDescription.isAbsoluteSize(), size, documentStyle->effectiveZoom())); + bool useSVGZoomRules = document->isSVGDocument(); + fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules)); } documentStyle->setFontDescription(fontDescription); @@ -2983,6 +2984,16 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) float zoomFactor = m_style->effectiveZoom(); + // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead + // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*() + // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that. + // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...) + // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like + // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale, + // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific + // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size). + bool useSVGZoomRules = m_element && m_element->isSVGElement(); + Length l; bool apply = false; @@ -3624,7 +3635,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) } else { if (!primitiveValue) return; - width = primitiveValue->computeLengthInt(style(), m_rootElementStyle, zoomFactor); + width = primitiveValue->computeLengthInt(style(), m_rootElementStyle, useSVGZoomRules ? 1.0f : zoomFactor); } switch (id) { case CSSPropertyLetterSpacing: @@ -4034,7 +4045,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) if (primitiveValue->getIdent() == CSSValueNormal) lineHeight = Length(-100.0, Percent); else if (CSSPrimitiveValue::isUnitTypeLength(type)) { - double multiplier = m_style->effectiveZoom(); + double multiplier = zoomFactor; if (m_style->textSizeAdjust() && m_checker.m_document->frame() && m_checker.m_document->frame()->shouldApplyTextZoom()) multiplier *= m_checker.m_document->frame()->textZoomFactor(); lineHeight = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, multiplier), Fixed); @@ -4516,7 +4527,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) fontDescription.setUsePrinterFont(m_checker.m_document->printing()); // Handle the zoom factor. - fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), m_style->effectiveZoom())); + fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, m_style.get(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules)); if (m_style->setFontDescription(fontDescription)) m_fontDirty = true; } @@ -5868,11 +5879,20 @@ void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* style, RenderSty void CSSStyleSelector::setFontSize(FontDescription& fontDescription, float size) { fontDescription.setSpecifiedSize(size); - fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, fontDescription.isAbsoluteSize(), size, m_style->effectiveZoom())); + + bool useSVGZoomRules = m_element && m_element->isSVGElement(); + fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, m_style.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules)); } -float CSSStyleSelector::getComputedSizeFromSpecifiedSize(Document* document, bool isAbsoluteSize, float specifiedSize, float zoomFactor) +float CSSStyleSelector::getComputedSizeFromSpecifiedSize(Document* document, RenderStyle* style, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules) { + float zoomFactor = 1.0f; + if (!useSVGZoomRules) { + zoomFactor = style->effectiveZoom(); + if (document->frame() && document->frame()->shouldApplyTextZoom()) + zoomFactor *= document->frame()->textZoomFactor(); + } + // We support two types of minimum font size. The first is a hard override that applies to // all fonts. This is "minSize." The second type of minimum font size is a "smart minimum" // that is applied only when the Web page can't know what size it really asked for, e.g., @@ -5889,10 +5909,6 @@ float CSSStyleSelector::getComputedSizeFromSpecifiedSize(Document* document, boo int minSize = settings->minimumFontSize(); int minLogicalSize = settings->minimumLogicalFontSize(); - - if (document->frame() && document->frame()->shouldApplyTextZoom()) - zoomFactor *= document->frame()->textZoomFactor(); - float zoomedSize = specifiedSize * zoomFactor; // Apply the hard minimum first. We only apply the hard minimum if after zooming we're still too small. diff --git a/WebCore/css/CSSStyleSelector.h b/WebCore/css/CSSStyleSelector.h index aac1bae..644051c 100644 --- a/WebCore/css/CSSStyleSelector.h +++ b/WebCore/css/CSSStyleSelector.h @@ -131,7 +131,7 @@ public: void applyPropertyToStyle(int id, CSSValue*, RenderStyle*); private: - static float getComputedSizeFromSpecifiedSize(Document*, bool isAbsoluteSize, float specifiedSize, float zoomFactor = 1.0f); + static float getComputedSizeFromSpecifiedSize(Document*, RenderStyle*, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules); public: Color getColorFromPrimitiveValue(CSSPrimitiveValue*); diff --git a/WebCore/css/SVGCSSStyleSelector.cpp b/WebCore/css/SVGCSSStyleSelector.cpp index 5ba7344..5651a0a 100644 --- a/WebCore/css/SVGCSSStyleSelector.cpp +++ b/WebCore/css/SVGCSSStyleSelector.cpp @@ -534,14 +534,12 @@ void CSSStyleSelector::applySVGProperty(int id, CSSValue* value) if (!value->isValueList()) return; - float zoomFactor = m_style->effectiveZoom(); - CSSValueList *list = static_cast<CSSValueList*>(value); ASSERT(list->length() == 1); ShadowValue* item = static_cast<ShadowValue*>(list->itemWithoutBoundsCheck(0)); - int x = item->x->computeLengthInt(style(), m_rootElementStyle, zoomFactor); - int y = item->y->computeLengthInt(style(), m_rootElementStyle, zoomFactor); - int blur = item->blur ? item->blur->computeLengthInt(style(), m_rootElementStyle, zoomFactor) : 0; + int x = item->x->computeLengthInt(style(), m_rootElementStyle); + int y = item->y->computeLengthInt(style(), m_rootElementStyle); + int blur = item->blur ? item->blur->computeLengthInt(style(), m_rootElementStyle) : 0; Color color; if (item->color) color = getColorFromPrimitiveValue(item->color.get()); @@ -564,5 +562,4 @@ void CSSStyleSelector::applySVGProperty(int id, CSSValue* value) } -// vim:ts=4:noet -#endif // ENABLE(SVG) +#endif diff --git a/WebCore/css/mediaControlsGtk.css b/WebCore/css/mediaControlsGtk.css index 8e98ab1..cc6da14 100644 --- a/WebCore/css/mediaControlsGtk.css +++ b/WebCore/css/mediaControlsGtk.css @@ -41,6 +41,8 @@ audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-bu audio::-webkit-media-controls-timeline-container, video::-webkit-media-controls-timeline-container { height: 20px; + border-left: 1px solid rgba(255, 255, 255, 0.2); + border-right: 1px solid rgba(255, 255, 255, 0.2); } audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline { diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp index 1f8edeb..ae23960 100644 --- a/WebCore/dom/Document.cpp +++ b/WebCore/dom/Document.cpp @@ -1500,6 +1500,17 @@ void Document::updateLayoutIgnorePendingStylesheets() m_ignorePendingStylesheets = oldIgnore; } +PassRefPtr<RenderStyle> Document::styleForElementIgnoringPendingStylesheets(Element* element) +{ + ASSERT_ARG(element, element->document() == this); + + bool oldIgnore = m_ignorePendingStylesheets; + m_ignorePendingStylesheets = true; + RefPtr<RenderStyle> style = styleSelector()->styleForElement(element, element->parent() ? element->parent()->computedStyle() : 0); + m_ignorePendingStylesheets = oldIgnore; + return style.release(); +} + void Document::createStyleSelector() { bool matchAuthorAndUserStyles = true; @@ -4522,6 +4533,10 @@ void Document::initSecurityContext() // Some clients want file:// URLs to have universal access, but that // setting is dangerous for other clients. securityOrigin()->grantUniversalAccess(); + } else if (!settings->allowFileAccessFromFileURLs() && securityOrigin()->isLocal()) { + // Some clients want file:// URLs to have even tighter restrictions by + // default, and not be able to access other local files. + securityOrigin()->makeUnique(); } } diff --git a/WebCore/dom/Document.h b/WebCore/dom/Document.h index e7c470b..3ddcaab 100644 --- a/WebCore/dom/Document.h +++ b/WebCore/dom/Document.h @@ -469,6 +469,7 @@ public: virtual void updateStyleIfNeeded(); void updateLayout(); void updateLayoutIgnorePendingStylesheets(); + PassRefPtr<RenderStyle> styleForElementIgnoringPendingStylesheets(Element*); static void updateStyleForAllDocuments(); // FIXME: Try to reduce the # of calls to this function. DocLoader* docLoader() { return m_docLoader.get(); } diff --git a/WebCore/dom/Element.cpp b/WebCore/dom/Element.cpp index 0a1bc75..9e4b48d 100644 --- a/WebCore/dom/Element.cpp +++ b/WebCore/dom/Element.cpp @@ -1359,7 +1359,7 @@ RenderStyle* Element::computedStyle() ElementRareData* data = ensureRareData(); if (!data->m_computedStyle) - data->m_computedStyle = document()->styleSelector()->styleForElement(this, parent() ? parent()->computedStyle() : 0); + data->m_computedStyle = document()->styleForElementIgnoringPendingStylesheets(this); return data->m_computedStyle.get(); } diff --git a/WebCore/dom/Node.cpp b/WebCore/dom/Node.cpp index efb6d78..49006fc 100644 --- a/WebCore/dom/Node.cpp +++ b/WebCore/dom/Node.cpp @@ -322,25 +322,20 @@ Node::StyleChange Node::diff(const RenderStyle* s1, const RenderStyle* s2) // If the pseudoStyles have changed, we want any StyleChange that is not NoChange // because setStyle will do the right thing with anything else. - if (ch == NoChange && s1->hasPseudoStyle(BEFORE)) { - RenderStyle* ps2 = s2->getCachedPseudoStyle(BEFORE); - if (!ps2) - ch = NoInherit; - else { - RenderStyle* ps1 = s1->getCachedPseudoStyle(BEFORE); - ch = ps1 && *ps1 == *ps2 ? NoChange : NoInherit; - } - } - if (ch == NoChange && s1->hasPseudoStyle(AFTER)) { - RenderStyle* ps2 = s2->getCachedPseudoStyle(AFTER); - if (!ps2) - ch = NoInherit; - else { - RenderStyle* ps1 = s1->getCachedPseudoStyle(AFTER); - ch = ps2 && *ps1 == *ps2 ? NoChange : NoInherit; + if (ch == NoChange && s1->hasAnyPublicPseudoStyles()) { + for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; ch == NoChange && pseudoId < FIRST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) { + if (s1->hasPseudoStyle(pseudoId)) { + RenderStyle* ps2 = s2->getCachedPseudoStyle(pseudoId); + if (!ps2) + ch = NoInherit; + else { + RenderStyle* ps1 = s1->getCachedPseudoStyle(pseudoId); + ch = ps1 && *ps1 == *ps2 ? NoChange : NoInherit; + } + } } } - + return ch; } diff --git a/WebCore/editing/ReplaceSelectionCommand.cpp b/WebCore/editing/ReplaceSelectionCommand.cpp index f26757e..bac090c 100644 --- a/WebCore/editing/ReplaceSelectionCommand.cpp +++ b/WebCore/editing/ReplaceSelectionCommand.cpp @@ -468,6 +468,17 @@ void ReplaceSelectionCommand::negateStyleRulesThatAffectAppearance() e->getInlineStyleDecl()->setProperty(CSSPropertyDisplay, CSSValueInline); if (e->renderer() && e->renderer()->style()->floating() != FNONE) e->getInlineStyleDecl()->setProperty(CSSPropertyFloat, CSSValueNone); + + // Undo the effects of page zoom if we have an absolute font size. When we copy, we + // compute the new font size as an absolute size so pasting will cause the zoom to be + // applied twice. + if (e->renderer() && e->renderer()->style() && e->renderer()->style()->effectiveZoom() != 1.0 + && e->renderer()->style()->fontDescription().isAbsoluteSize()) { + float newSize = e->renderer()->style()->fontDescription().specifiedSize() / e->renderer()->style()->effectiveZoom(); + ExceptionCode ec = 0; + e->style()->setProperty(CSSPropertyFontSize, String::number(newSize), false, ec); + ASSERT(!ec); + } } if (node == m_lastLeafInserted) break; @@ -638,10 +649,11 @@ void ReplaceSelectionCommand::handleStyleSpans() } // There are non-redundant styles on sourceDocumentStyleSpan, but there is no - // copiedRangeStyleSpan. Clear the redundant styles from sourceDocumentStyleSpan - // and return. + // copiedRangeStyleSpan. Remove the span, because it could be surrounding block elements, + // and apply the styles to its children. if (sourceDocumentStyle->length() > 0 && !copiedRangeStyleSpan) { - setNodeAttribute(static_cast<Element*>(sourceDocumentStyleSpan), styleAttr, sourceDocumentStyle->cssText()); + copyStyleToChildren(sourceDocumentStyleSpan, sourceDocumentStyle.get()); + removeNodePreservingChildren(sourceDocumentStyleSpan); return; } @@ -673,6 +685,34 @@ void ReplaceSelectionCommand::handleStyleSpans() setNodeAttribute(static_cast<Element*>(copiedRangeStyleSpan), styleAttr, copiedRangeStyle->cssText()); } +// Take the style attribute of a span and apply it to it's children instead. This allows us to +// convert invalid HTML where a span contains block elements into valid HTML while preserving +// styles. +void ReplaceSelectionCommand::copyStyleToChildren(Node* parentNode, const CSSMutableStyleDeclaration* parentStyle) +{ + ASSERT(parentNode->hasTagName(spanTag)); + for (Node* childNode = parentNode->firstChild(); childNode; childNode = childNode->nextSibling()) { + if (childNode->isTextNode() || !isBlock(childNode) || childNode->hasTagName(preTag)) { + // In this case, put a span tag around the child node. + RefPtr<Node> newSpan = parentNode->cloneNode(false); + setNodeAttribute(static_cast<Element*>(newSpan.get()), styleAttr, parentStyle->cssText()); + insertNodeAfter(newSpan, childNode); + ExceptionCode ec = 0; + newSpan->appendChild(childNode, ec); + ASSERT(!ec); + childNode = newSpan.get(); + } else if (childNode->isHTMLElement()) { + // Copy the style attribute and merge them into the child node. We don't want to override + // existing styles, so don't clobber on merge. + RefPtr<CSSMutableStyleDeclaration> newStyle = parentStyle->copy(); + HTMLElement* childElement = static_cast<HTMLElement*>(childNode); + RefPtr<CSSMutableStyleDeclaration> existingStyles = childElement->getInlineStyleDecl()->copy(); + existingStyles->merge(newStyle.get(), false); + setNodeAttribute(childElement, styleAttr, existingStyles->cssText()); + } + } +} + void ReplaceSelectionCommand::mergeEndIfNeeded() { if (!m_shouldMergeEnd) @@ -871,7 +911,8 @@ void ReplaceSelectionCommand::doApply() fragment.removeNode(refNode); Node* blockStart = enclosingBlock(insertionPos.node()); - if (isListElement(refNode.get()) && blockStart->renderer()->isListItem()) + if ((isListElement(refNode.get()) || (isStyleSpan(refNode.get()) && isListElement(refNode->firstChild()))) + && blockStart->renderer()->isListItem()) refNode = insertAsListItems(refNode, blockStart, insertionPos); else insertNodeAtAndUpdateNodesInserted(refNode, insertionPos); @@ -1122,15 +1163,15 @@ void ReplaceSelectionCommand::insertNodeBeforeAndUpdateNodesInserted(PassRefPtr< // If the user is inserting a list into an existing list, instead of nesting the list, // we put the list items into the existing list. -Node* ReplaceSelectionCommand::insertAsListItems(PassRefPtr<Node> listElement, Node* insertionNode, const Position& p) +Node* ReplaceSelectionCommand::insertAsListItems(PassRefPtr<Node> listElement, Node* insertionBlock, const Position& insertPos) { while (listElement->hasChildNodes() && isListElement(listElement->firstChild()) && listElement->childNodeCount() == 1) listElement = listElement->firstChild(); - bool isStart = isStartOfParagraph(p); - bool isEnd = isEndOfParagraph(p); + bool isStart = isStartOfParagraph(insertPos); + bool isEnd = isEndOfParagraph(insertPos); - Node* lastNode = insertionNode; + Node* lastNode = insertionBlock; while (RefPtr<Node> listItem = listElement->firstChild()) { ExceptionCode ec = 0; listElement->removeChild(listItem.get(), ec); diff --git a/WebCore/editing/ReplaceSelectionCommand.h b/WebCore/editing/ReplaceSelectionCommand.h index 19f63bb..e995e79 100644 --- a/WebCore/editing/ReplaceSelectionCommand.h +++ b/WebCore/editing/ReplaceSelectionCommand.h @@ -69,6 +69,7 @@ private: void negateStyleRulesThatAffectAppearance(); void handleStyleSpans(); + void copyStyleToChildren(Node* parentNode, const CSSMutableStyleDeclaration* parentStyle); void handlePasteAsQuotationNode(); virtual void removeNodePreservingChildren(Node*); diff --git a/WebCore/editing/SelectionController.cpp b/WebCore/editing/SelectionController.cpp index 5b2d0d0..25982d4 100644 --- a/WebCore/editing/SelectionController.cpp +++ b/WebCore/editing/SelectionController.cpp @@ -265,6 +265,33 @@ TextDirection SelectionController::directionOfEnclosingBlock() return LTR; } +VisiblePosition SelectionController::positionForPlatform(bool isGetStart) const +{ + Position pos; + Settings* settings = m_frame ? m_frame->settings() : 0; + if (settings && settings->editingBehavior() == EditingMacBehavior) + pos = isGetStart ? m_selection.start() : m_selection.end(); + else { + // Linux and Windows always extend selections from the extent endpoint. + // FIXME: VisibleSelection should be fixed to ensure as an invariant that + // base/extent always point to the same nodes as start/end, but which points + // to which depends on the value of isBaseFirst. Then this can be changed + // to just return m_sel.extent(). + pos = m_selection.isBaseFirst() ? m_selection.end() : m_selection.start(); + } + return VisiblePosition(pos, m_selection.affinity()); +} + +VisiblePosition SelectionController::startForPlatform() const +{ + return positionForPlatform(true); +} + +VisiblePosition SelectionController::endForPlatform() const +{ + return positionForPlatform(false); +} + VisiblePosition SelectionController::modifyExtendingRight(TextGranularity granularity) { VisiblePosition pos(m_selection.extent(), m_selection.affinity()); @@ -298,7 +325,7 @@ VisiblePosition SelectionController::modifyExtendingRight(TextGranularity granul pos = modifyExtendingForward(granularity); } return pos; -} +} VisiblePosition SelectionController::modifyExtendingForward(TextGranularity granularity) { @@ -320,16 +347,16 @@ VisiblePosition SelectionController::modifyExtendingForward(TextGranularity gran pos = nextParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT)); break; case SentenceBoundary: - pos = endOfSentence(VisiblePosition(m_selection.end(), m_selection.affinity())); + pos = endOfSentence(endForPlatform()); break; case LineBoundary: - pos = logicalEndOfLine(VisiblePosition(m_selection.end(), m_selection.affinity())); + pos = logicalEndOfLine(endForPlatform()); break; case ParagraphBoundary: - pos = endOfParagraph(VisiblePosition(m_selection.end(), m_selection.affinity())); + pos = endOfParagraph(endForPlatform()); break; case DocumentBoundary: - pos = VisiblePosition(m_selection.end(), m_selection.affinity()); + pos = endForPlatform(); if (isEditablePosition(pos.deepEquivalent())) pos = endOfEditableContent(pos); else @@ -385,25 +412,25 @@ VisiblePosition SelectionController::modifyMovingForward(TextGranularity granula case LineGranularity: { // down-arrowing from a range selection that ends at the start of a line needs // to leave the selection at that line start (no need to call nextLinePosition!) - pos = VisiblePosition(m_selection.end(), m_selection.affinity()); + pos = endForPlatform(); if (!isRange() || !isStartOfLine(pos)) pos = nextLinePosition(pos, xPosForVerticalArrowNavigation(START)); break; } case ParagraphGranularity: - pos = nextParagraphPosition(VisiblePosition(m_selection.end(), m_selection.affinity()), xPosForVerticalArrowNavigation(START)); + pos = nextParagraphPosition(endForPlatform(), xPosForVerticalArrowNavigation(START)); break; case SentenceBoundary: - pos = endOfSentence(VisiblePosition(m_selection.end(), m_selection.affinity())); + pos = endOfSentence(endForPlatform()); break; case LineBoundary: - pos = logicalEndOfLine(VisiblePosition(m_selection.end(), m_selection.affinity())); + pos = logicalEndOfLine(endForPlatform()); break; case ParagraphBoundary: - pos = endOfParagraph(VisiblePosition(m_selection.end(), m_selection.affinity())); + pos = endOfParagraph(endForPlatform()); break; case DocumentBoundary: - pos = VisiblePosition(m_selection.end(), m_selection.affinity()); + pos = endForPlatform(); if (isEditablePosition(pos.deepEquivalent())) pos = endOfEditableContent(pos); else @@ -473,16 +500,16 @@ VisiblePosition SelectionController::modifyExtendingBackward(TextGranularity gra pos = previousParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT)); break; case SentenceBoundary: - pos = startOfSentence(VisiblePosition(m_selection.start(), m_selection.affinity())); + pos = startOfSentence(startForPlatform()); break; case LineBoundary: - pos = logicalStartOfLine(VisiblePosition(m_selection.start(), m_selection.affinity())); + pos = logicalStartOfLine(startForPlatform()); break; case ParagraphBoundary: - pos = startOfParagraph(VisiblePosition(m_selection.start(), m_selection.affinity())); + pos = startOfParagraph(startForPlatform()); break; case DocumentBoundary: - pos = VisiblePosition(m_selection.start(), m_selection.affinity()); + pos = startForPlatform(); if (isEditablePosition(pos.deepEquivalent())) pos = startOfEditableContent(pos); else @@ -534,22 +561,22 @@ VisiblePosition SelectionController::modifyMovingBackward(TextGranularity granul pos = previousSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity())); break; case LineGranularity: - pos = previousLinePosition(VisiblePosition(m_selection.start(), m_selection.affinity()), xPosForVerticalArrowNavigation(START)); + pos = previousLinePosition(startForPlatform(), xPosForVerticalArrowNavigation(START)); break; case ParagraphGranularity: - pos = previousParagraphPosition(VisiblePosition(m_selection.start(), m_selection.affinity()), xPosForVerticalArrowNavigation(START)); + pos = previousParagraphPosition(startForPlatform(), xPosForVerticalArrowNavigation(START)); break; case SentenceBoundary: - pos = startOfSentence(VisiblePosition(m_selection.start(), m_selection.affinity())); + pos = startOfSentence(startForPlatform()); break; case LineBoundary: - pos = logicalStartOfLine(VisiblePosition(m_selection.start(), m_selection.affinity())); + pos = logicalStartOfLine(startForPlatform()); break; case ParagraphBoundary: - pos = startOfParagraph(VisiblePosition(m_selection.start(), m_selection.affinity())); + pos = startOfParagraph(startForPlatform()); break; case DocumentBoundary: - pos = VisiblePosition(m_selection.start(), m_selection.affinity()); + pos = startForPlatform(); if (isEditablePosition(pos.deepEquivalent())) pos = startOfEditableContent(pos); else @@ -840,7 +867,6 @@ void SelectionController::layout() RenderObject* caretPainter = caretRenderer(); // Compute an offset between the renderer and the caretPainter - IntSize offsetFromPainter; bool unrooted = false; while (renderer != caretPainter) { RenderObject* containerObject = renderer->container(); @@ -848,15 +874,12 @@ void SelectionController::layout() unrooted = true; break; } - offsetFromPainter += renderer->offsetFromContainer(containerObject); + localRect.move(renderer->offsetFromContainer(containerObject, localRect.location())); renderer = containerObject; } - if (!unrooted) { - // Move the caret rect to the coords of the painter - localRect.move(offsetFromPainter); + if (!unrooted) m_caretRect = localRect; - } m_absCaretBoundsDirty = true; } diff --git a/WebCore/editing/SelectionController.h b/WebCore/editing/SelectionController.h index 7cad435..6849cb6 100644 --- a/WebCore/editing/SelectionController.h +++ b/WebCore/editing/SelectionController.h @@ -140,6 +140,10 @@ private: TextDirection directionOfEnclosingBlock(); + VisiblePosition positionForPlatform(bool isGetStart) const; + VisiblePosition startForPlatform() const; + VisiblePosition endForPlatform() const; + VisiblePosition modifyExtendingRight(TextGranularity); VisiblePosition modifyExtendingForward(TextGranularity); VisiblePosition modifyMovingRight(TextGranularity); diff --git a/WebCore/html/HTMLAudioElement.cpp b/WebCore/html/HTMLAudioElement.cpp index 6adf9ea..347b8c4 100644 --- a/WebCore/html/HTMLAudioElement.cpp +++ b/WebCore/html/HTMLAudioElement.cpp @@ -1,5 +1,6 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,7 +21,7 @@ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" @@ -34,11 +35,22 @@ namespace WebCore { using namespace HTMLNames; -HTMLAudioElement::HTMLAudioElement(const QualifiedName& tagName, Document* doc) - : HTMLMediaElement(tagName, doc) +HTMLAudioElement::HTMLAudioElement(const QualifiedName& tagName, Document* document) + : HTMLMediaElement(tagName, document) { ASSERT(hasTagName(audioTag)); } +PassRefPtr<HTMLAudioElement> HTMLAudioElement::createForJSConstructor(Document* document, const String& src) +{ + RefPtr<HTMLAudioElement> audio = new HTMLAudioElement(audioTag, document); + audio->setAutobuffer(true); + if (!src.isNull()) { + audio->setSrc(src); + audio->scheduleLoad(); + } + return audio.release(); +} + } #endif diff --git a/WebCore/html/HTMLAudioElement.h b/WebCore/html/HTMLAudioElement.h index 1dbe44f..2f06f1a 100644 --- a/WebCore/html/HTMLAudioElement.h +++ b/WebCore/html/HTMLAudioElement.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,7 +21,7 @@ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef HTMLAudioElement_h @@ -28,14 +29,17 @@ #if ENABLE(VIDEO) +#include "Document.h" #include "HTMLMediaElement.h" namespace WebCore { class HTMLAudioElement : public HTMLMediaElement { public: + static PassRefPtr<HTMLAudioElement> createForJSConstructor(Document*, const String& src); HTMLAudioElement(const QualifiedName&, Document*); - +private: + virtual bool isVideo() const { return false; } virtual int tagPriority() const { return 5; } }; diff --git a/WebCore/html/HTMLFrameElementBase.cpp b/WebCore/html/HTMLFrameElementBase.cpp index 3890850..9d84b62 100644 --- a/WebCore/html/HTMLFrameElementBase.cpp +++ b/WebCore/html/HTMLFrameElementBase.cpp @@ -150,7 +150,7 @@ void HTMLFrameElementBase::parseMappedAttribute(MappedAttribute *attr) HTMLFrameOwnerElement::parseMappedAttribute(attr); } -void HTMLFrameElementBase::setNameAndOpenURL() +void HTMLFrameElementBase::setName() { m_frameName = getAttribute(nameAttr); if (m_frameName.isNull()) @@ -158,7 +158,11 @@ void HTMLFrameElementBase::setNameAndOpenURL() if (Frame* parentFrame = document()->frame()) m_frameName = parentFrame->tree()->uniqueChildName(m_frameName); - +} + +void HTMLFrameElementBase::setNameAndOpenURL() +{ + setName(); openURL(); } @@ -167,6 +171,14 @@ void HTMLFrameElementBase::setNameAndOpenURLCallback(Node* n) static_cast<HTMLFrameElementBase*>(n)->setNameAndOpenURL(); } +void HTMLFrameElementBase::updateOnReparenting() +{ + ASSERT(m_remainsAliveOnRemovalFromTree); + + if (Frame* frame = contentFrame()) + frame->transferChildFrameToNewDocument(); +} + void HTMLFrameElementBase::insertedIntoDocument() { HTMLFrameOwnerElement::insertedIntoDocument(); @@ -175,6 +187,9 @@ void HTMLFrameElementBase::insertedIntoDocument() // Othewise, a synchronous load that executed JavaScript would see incorrect // (0) values for the frame's renderer-dependent properties, like width. m_shouldOpenURLAfterAttach = true; + + if (m_remainsAliveOnRemovalFromTree) + updateOnReparenting(); } void HTMLFrameElementBase::removedFromDocument() diff --git a/WebCore/html/HTMLFrameElementBase.h b/WebCore/html/HTMLFrameElementBase.h index ea93ae7..7717df0 100644 --- a/WebCore/html/HTMLFrameElementBase.h +++ b/WebCore/html/HTMLFrameElementBase.h @@ -64,8 +64,11 @@ private: virtual bool isURLAttribute(Attribute*) const; + virtual void setName(); + virtual void willRemove(); void checkAttachedTimerFired(Timer<HTMLFrameElementBase>*); + void updateOnReparenting(); bool viewSourceMode() const { return m_viewSource; } diff --git a/WebCore/html/HTMLFrameOwnerElement.h b/WebCore/html/HTMLFrameOwnerElement.h index 4a56e45..804ab22 100644 --- a/WebCore/html/HTMLFrameOwnerElement.h +++ b/WebCore/html/HTMLFrameOwnerElement.h @@ -59,6 +59,7 @@ protected: private: friend class Frame; + virtual void setName() { } virtual bool isFrameOwnerElement() const { return true; } virtual bool isKeyboardFocusable(KeyboardEvent*) const { return m_contentFrame; } diff --git a/WebCore/html/HTMLImageElement.cpp b/WebCore/html/HTMLImageElement.cpp index 4592461..d3cea92 100644 --- a/WebCore/html/HTMLImageElement.cpp +++ b/WebCore/html/HTMLImageElement.cpp @@ -1,7 +1,8 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -58,6 +59,16 @@ HTMLImageElement::~HTMLImageElement() m_form->removeImgElement(this); } +PassRefPtr<HTMLImageElement> HTMLImageElement::createForJSConstructor(Document* document, const int* optionalWidth, const int* optionalHeight) +{ + RefPtr<HTMLImageElement> image = new HTMLImageElement(imgTag, document); + if (optionalWidth) + image->setWidth(*optionalWidth); + if (optionalHeight > 0) + image->setHeight(*optionalHeight); + return image.release(); +} + bool HTMLImageElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const { if (attrName == widthAttr || @@ -68,7 +79,7 @@ bool HTMLImageElement::mapToEntry(const QualifiedName& attrName, MappedAttribute result = eUniversal; return false; } - + if (attrName == borderAttr || attrName == alignAttr) { result = eReplaced; // Shared with embed and iframe elements. return false; @@ -161,7 +172,7 @@ RenderObject* HTMLImageElement::createRenderer(RenderArena* arena, RenderStyle* { if (style->contentData()) return RenderObject::createObject(this, style); - + return new (arena) RenderImage(this); } @@ -174,7 +185,7 @@ void HTMLImageElement::attach() if (imageObj->hasImage()) return; imageObj->setCachedImage(m_imageLoader.image()); - + // If we have no image at all because we have no src attribute, set // image height and width for the alt text instead. if (!m_imageLoader.image() && !imageObj->cachedImage()) @@ -241,7 +252,7 @@ int HTMLImageElement::width(bool ignorePendingStylesheets) const int width = getAttribute(widthAttr).toInt(&ok); if (ok) return width; - + // if the image is available, use its width if (m_imageLoader.image()) { float zoomFactor = document()->frame() ? document()->frame()->pageZoomFactor() : 1.0f; @@ -265,7 +276,7 @@ int HTMLImageElement::height(bool ignorePendingStylesheets) const int height = getAttribute(heightAttr).toInt(&ok); if (ok) return height; - + // if the image is available, use its height if (m_imageLoader.image()) { float zoomFactor = document()->frame() ? document()->frame()->pageZoomFactor() : 1.0f; @@ -293,10 +304,10 @@ int HTMLImageElement::naturalHeight() const { if (!m_imageLoader.image()) return 0; - + return m_imageLoader.image()->imageSize(1.0f).height(); } - + bool HTMLImageElement::isURLAttribute(Attribute* attr) const { return attr->name() == srcAttr diff --git a/WebCore/html/HTMLImageElement.h b/WebCore/html/HTMLImageElement.h index 14e5fa3..d7df1dc 100644 --- a/WebCore/html/HTMLImageElement.h +++ b/WebCore/html/HTMLImageElement.h @@ -1,7 +1,8 @@ /* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) - * Copyright (C) 2004, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -34,6 +35,8 @@ class HTMLFormElement; class HTMLImageElement : public HTMLElement { friend class HTMLFormElement; public: + static PassRefPtr<HTMLImageElement> createForJSConstructor(Document*, const int* optionalWidth, const int* optionalHeight); + HTMLImageElement(const QualifiedName&, Document*, HTMLFormElement* = 0); ~HTMLImageElement(); @@ -53,7 +56,7 @@ public: int naturalWidth() const; int naturalHeight() const; - + bool isServerMap() const { return ismap && usemap.isEmpty(); } String altText() const; diff --git a/WebCore/html/HTMLInputElement.cpp b/WebCore/html/HTMLInputElement.cpp index ee0c75d..c3f6703 100644 --- a/WebCore/html/HTMLInputElement.cpp +++ b/WebCore/html/HTMLInputElement.cpp @@ -503,7 +503,7 @@ bool HTMLInputElement::stepMismatch() const return false; case NUMBER: { double doubleValue; - if (!formStringToDouble(value(), &doubleValue)) + if (!parseToDoubleForNumberType(value(), &doubleValue)) return false; doubleValue = fabs(doubleValue - stepBase()); if (isinf(doubleValue)) @@ -624,7 +624,7 @@ bool HTMLInputElement::getAllowedValueStep(double* step) const if (equalIgnoringCase(stepString, "any")) return false; double parsed; - if (!formStringToDouble(stepString, &parsed) || parsed <= 0.0) { + if (!parseToDoubleForNumberType(stepString, &parsed) || parsed <= 0.0) { *step = defaultStep * stepScaleFactor; return true; } @@ -1618,7 +1618,7 @@ double HTMLInputElement::parseToDouble(const String& src, double defaultValue) c case TIME: case WEEK: { DateComponents date; - if (!formStringToDateComponents(inputType(), src, &date)) + if (!parseToDateComponents(inputType(), src, &date)) return defaultValue; double msec = date.millisecondsSinceEpoch(); ASSERT(isfinite(msec)); @@ -1626,7 +1626,7 @@ double HTMLInputElement::parseToDouble(const String& src, double defaultValue) c } case MONTH: { DateComponents date; - if (!formStringToDateComponents(inputType(), src, &date)) + if (!parseToDateComponents(inputType(), src, &date)) return defaultValue; double months = date.monthsSinceEpoch(); ASSERT(isfinite(months)); @@ -1635,7 +1635,7 @@ double HTMLInputElement::parseToDouble(const String& src, double defaultValue) c case NUMBER: case RANGE: { double numberValue; - if (!formStringToDouble(src, &numberValue)) + if (!parseToDoubleForNumberType(src, &numberValue)) return defaultValue; ASSERT(isfinite(numberValue)); return numberValue; @@ -1673,7 +1673,7 @@ double HTMLInputElement::valueAsDate() const return parseToDouble(value(), DateComponents::invalidMilliseconds()); case MONTH: { DateComponents date; - if (!formStringToDateComponents(inputType(), value(), &date)) + if (!parseToDateComponents(inputType(), value(), &date)) return DateComponents::invalidMilliseconds(); double msec = date.millisecondsSinceEpoch(); ASSERT(isfinite(msec)); @@ -1707,24 +1707,22 @@ double HTMLInputElement::valueAsDate() const void HTMLInputElement::setValueAsDate(double value, ExceptionCode& ec) { - DateComponents date; - bool success; switch (inputType()) { case DATE: - success = date.setMillisecondsSinceEpochForDate(value); - break; case DATETIME: - success = date.setMillisecondsSinceEpochForDateTime(value); - break; - case MONTH: - success = date.setMillisecondsSinceEpochForMonth(value); - break; case TIME: - success = date.setMillisecondsSinceMidnight(value); - break; case WEEK: - success = date.setMillisecondsSinceEpochForWeek(value); - break; + setValue(serializeForDateTimeTypes(value)); + return; + case MONTH: { + DateComponents date; + if (!date.setMillisecondsSinceEpochForMonth(value)) { + setValue(String()); + return; + } + setValue(date.toString()); + return; + } case BUTTON: case CHECKBOX: case COLOR: @@ -1746,33 +1744,8 @@ void HTMLInputElement::setValueAsDate(double value, ExceptionCode& ec) case URL: ec = INVALID_STATE_ERR; return; - default: - ASSERT_NOT_REACHED(); - success = false; } - if (!success) { - setValue(String()); - return; - } - setDateValue(date); -} - -void HTMLInputElement::setDateValue(const DateComponents& date) -{ - double step; - if (!getAllowedValueStep(&step)) { - setValue(date.toString()); - return; - } - if (!fmod(step, msecPerMinute)) { - setValue(date.toString(DateComponents::None)); - return; - } - if (!fmod(step, msecPerSecond)) { - setValue(date.toString(DateComponents::Second)); - return; - } - setValue(date.toString(DateComponents::Millisecond)); + ASSERT_NOT_REACHED(); } double HTMLInputElement::valueAsNumber() const @@ -1820,32 +1793,109 @@ void HTMLInputElement::setValueAsNumber(double newValue, ExceptionCode& ec) switch (inputType()) { case DATE: case DATETIME: + case DATETIMELOCAL: + case MONTH: + case NUMBER: + case RANGE: case TIME: case WEEK: - setValueAsDate(newValue, ec); + setValue(serialize(newValue)); return; - case MONTH: { - DateComponents date; - if (!date.setMonthsSinceEpoch(newValue)) { - setValue(String()); - return; - } - setValue(date.toString()); + + case BUTTON: + case CHECKBOX: + case COLOR: + case EMAIL: + case FILE: + case HIDDEN: + case IMAGE: + case ISINDEX: + case PASSWORD: + case RADIO: + case RESET: + case SEARCH: + case SUBMIT: + case TELEPHONE: + case TEXT: + case URL: + ec = INVALID_STATE_ERR; return; } - case DATETIMELOCAL: { - DateComponents date; - if (!date.setMillisecondsSinceEpochForDateTimeLocal(newValue)) { - setValue(String()); - return; - } - setDateValue(date); - return; + ASSERT_NOT_REACHED(); +} + +String HTMLInputElement::serializeForDateTimeTypes(double value) const +{ + bool success = false; + DateComponents date; + switch (inputType()) { + case DATE: + success = date.setMillisecondsSinceEpochForDate(value); + break; + case DATETIME: + success = date.setMillisecondsSinceEpochForDateTime(value); + break; + case DATETIMELOCAL: + success = date.setMillisecondsSinceEpochForDateTimeLocal(value); + break; + case MONTH: + success = date.setMonthsSinceEpoch(value); + break; + case TIME: + success = date.setMillisecondsSinceMidnight(value); + break; + case WEEK: + success = date.setMillisecondsSinceEpochForWeek(value); + break; + case NUMBER: + case RANGE: + case BUTTON: + case CHECKBOX: + case COLOR: + case EMAIL: + case FILE: + case HIDDEN: + case IMAGE: + case ISINDEX: + case PASSWORD: + case RADIO: + case RESET: + case SEARCH: + case SUBMIT: + case TELEPHONE: + case TEXT: + case URL: + ASSERT_NOT_REACHED(); + return String(); } + if (!success) + return String(); + + double step; + if (!getAllowedValueStep(&step)) + return date.toString(); + if (!fmod(step, msecPerMinute)) + return date.toString(DateComponents::None); + if (!fmod(step, msecPerSecond)) + return date.toString(DateComponents::Second); + return date.toString(DateComponents::Millisecond); +} + +String HTMLInputElement::serialize(double value) const +{ + if (!isfinite(value)) + return String(); + switch (inputType()) { + case DATE: + case DATETIME: + case DATETIMELOCAL: + case MONTH: + case TIME: + case WEEK: + return serializeForDateTimeTypes(value); case NUMBER: case RANGE: - setValue(formStringFromDouble(newValue)); - return; + return serializeForNumberType(value); case BUTTON: case CHECKBOX: @@ -1863,11 +1913,10 @@ void HTMLInputElement::setValueAsNumber(double newValue, ExceptionCode& ec) case TELEPHONE: case TEXT: case URL: - ec = INVALID_STATE_ERR; - return; + break; } ASSERT_NOT_REACHED(); - return; + return String(); } String HTMLInputElement::placeholder() const @@ -2573,7 +2622,7 @@ bool HTMLInputElement::willValidate() const inputType() != BUTTON && inputType() != RESET; } -String HTMLInputElement::formStringFromDouble(double number) +String HTMLInputElement::serializeForNumberType(double number) { // According to HTML5, "the best representation of the number n as a floating // point number" is a string produced by applying ToString() to n. @@ -2583,7 +2632,7 @@ String HTMLInputElement::formStringFromDouble(double number) return String(buffer, length); } -bool HTMLInputElement::formStringToDouble(const String& src, double* out) +bool HTMLInputElement::parseToDoubleForNumberType(const String& src, double* out) { // See HTML5 2.4.4.3 `Real numbers.' @@ -2609,7 +2658,7 @@ bool HTMLInputElement::formStringToDouble(const String& src, double* out) return true; } -bool HTMLInputElement::formStringToDateComponents(InputType type, const String& formString, DateComponents* out) +bool HTMLInputElement::parseToDateComponents(InputType type, const String& formString, DateComponents* out) { if (formString.isEmpty()) return false; diff --git a/WebCore/html/HTMLInputElement.h b/WebCore/html/HTMLInputElement.h index 4665437..40930ac 100644 --- a/WebCore/html/HTMLInputElement.h +++ b/WebCore/html/HTMLInputElement.h @@ -262,14 +262,14 @@ public: // Converts the specified string to a floating number. // If the conversion fails, the return value is false. Take care that leading or trailing unnecessary characters make failures. This returns false for an empty string input. // The double* parameter may be 0. - static bool formStringToDouble(const String&, double*); + static bool parseToDoubleForNumberType(const String&, double*); // Converts the specified number to a string. This is an implementation of // HTML5's "algorithm to convert a number to a string" for NUMBER/RANGE types. - static String formStringFromDouble(double); + static String serializeForNumberType(double); // Parses the specified string as the InputType, and returns true if it is successfully parsed. // An instance pointed by the DateComponents* parameter will have parsed values and be // modified even if the parsing fails. The DateComponents* parameter may be 0. - static bool formStringToDateComponents(InputType, const String&, DateComponents*); + static bool parseToDateComponents(InputType, const String&, DateComponents*); protected: virtual void willMoveToNewOwnerDocument(); @@ -305,11 +305,14 @@ private: // succeeds; Returns defaultValue otherwise. This function can // return NaN or Infinity only if defaultValue is NaN or Infinity. double parseToDouble(const String&, double defaultValue) const; - - // Generates a suitable string for the specified DateComponents and the - // step value, and calls setValue() with it. - void setDateValue(const DateComponents&); - + // Create a string representation of the specified double value for the + // current input type. If NaN or Infinity is specified, this returns an + // emtpy string. This should not be called for types without valueAsNumber. + String serialize(double) const; + // Create a string representation of the specified double value for the + // current input type. The type must be one of DATE, DATETIME, + // DATETIMELOCAL, MONTH, TIME, and WEEK. + String serializeForDateTimeTypes(double) const; #if ENABLE(DATALIST) HTMLDataListElement* dataList() const; diff --git a/WebCore/html/HTMLMediaElement.cpp b/WebCore/html/HTMLMediaElement.cpp index 279aac7..12b93ef 100644 --- a/WebCore/html/HTMLMediaElement.cpp +++ b/WebCore/html/HTMLMediaElement.cpp @@ -664,8 +664,8 @@ void HTMLMediaElement::noneSupported() // 9 -Abort these steps. Until the load() method is invoked, the element won't attempt to load another resource. - if (isVideo()) - static_cast<HTMLVideoElement*>(this)->updatePosterImage(); + updatePosterImage(); + if (renderer()) renderer()->updateFromElement(); } @@ -743,9 +743,7 @@ void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state) else if (state == MediaPlayer::FormatError && m_loadState == LoadingFromSrcAttr) noneSupported(); - if (isVideo()) - static_cast<HTMLVideoElement*>(this)->updatePosterImage(); - + updatePosterImage(); return; } @@ -883,8 +881,8 @@ void HTMLMediaElement::setReadyState(MediaPlayer::ReadyState state) shouldUpdatePosterImage = true; } - if (shouldUpdatePosterImage && isVideo()) - static_cast<HTMLVideoElement*>(this)->updatePosterImage(); + if (shouldUpdatePosterImage) + updatePosterImage(); updatePlayState(); } @@ -1506,6 +1504,8 @@ void HTMLMediaElement::mediaPlayerRepaint(MediaPlayer*) beginProcessingMediaPlayerCallback(); if (renderer()) renderer()->repaint(); + + updatePosterImage(); endProcessingMediaPlayerCallback(); } @@ -1529,11 +1529,10 @@ bool HTMLMediaElement::mediaPlayerRenderingCanBeAccelerated(MediaPlayer*) return false; } -GraphicsLayer* HTMLMediaElement::mediaPlayerGraphicsLayer(MediaPlayer*) +void HTMLMediaElement::mediaPlayerRenderingModeChanged(MediaPlayer*) { - if (renderer() && renderer()->isVideo()) - return toRenderVideo(renderer())->videoGraphicsLayer(); - return 0; + // Kick off a fake recalcStyle that will update the compositing tree. + setNeedsStyleRecalc(SyntheticStyleChange); } #endif @@ -1878,6 +1877,13 @@ PlatformMedia HTMLMediaElement::platformMedia() const return m_player ? m_player->platformMedia() : NoPlatformMedia; } +#if USE(ACCELERATED_COMPOSITING) +PlatformLayer* HTMLMediaElement::platformLayer() const +{ + return m_player ? m_player->platformLayer() : 0; +} +#endif + bool HTMLMediaElement::hasClosedCaptions() const { return m_player && m_player->hasClosedCaptions(); diff --git a/WebCore/html/HTMLMediaElement.h b/WebCore/html/HTMLMediaElement.h index 45a41c6..07801da 100644 --- a/WebCore/html/HTMLMediaElement.h +++ b/WebCore/html/HTMLMediaElement.h @@ -46,7 +46,6 @@ class TimeRanges; class HTMLMediaElement : public HTMLElement, public MediaPlayerClient { public: - HTMLMediaElement(const QualifiedName&, Document*); virtual ~HTMLMediaElement(); bool checkDTD(const Node* newChild); @@ -63,7 +62,7 @@ public: MediaPlayer* player() const { return m_player.get(); } - virtual bool isVideo() const { return false; } + virtual bool isVideo() const = 0; virtual bool hasVideo() const { return false; } virtual bool hasAudio() const; @@ -75,6 +74,9 @@ public: virtual bool supportsSave() const; PlatformMedia platformMedia() const; +#if USE(ACCELERATED_COMPOSITING) + PlatformLayer* platformLayer() const; +#endif void scheduleLoad(); @@ -174,12 +176,15 @@ public: bool processingUserGesture() const; protected: + HTMLMediaElement(const QualifiedName&, Document*); + float getTimeOffsetAttribute(const QualifiedName&, float valueOnError) const; void setTimeOffsetAttribute(const QualifiedName&, float value); virtual void documentWillBecomeInactive(); virtual void documentDidBecomeActive(); virtual void mediaVolumeDidChange(); + virtual void updatePosterImage() { } void setReadyState(MediaPlayer::ReadyState); void setNetworkState(MediaPlayer::NetworkState); @@ -200,7 +205,7 @@ private: // MediaPlayerClient virtual void mediaPlayerSizeChanged(MediaPlayer*); #if USE(ACCELERATED_COMPOSITING) virtual bool mediaPlayerRenderingCanBeAccelerated(MediaPlayer*); - virtual GraphicsLayer* mediaPlayerGraphicsLayer(MediaPlayer*); + virtual void mediaPlayerRenderingModeChanged(MediaPlayer*); #endif private: diff --git a/WebCore/html/HTMLOptionElement.cpp b/WebCore/html/HTMLOptionElement.cpp index cab4e18..2752cbb 100644 --- a/WebCore/html/HTMLOptionElement.cpp +++ b/WebCore/html/HTMLOptionElement.cpp @@ -2,8 +2,9 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. * (C) 2006 Alexey Proskuryakov (ap@nypop.com) + * Copyright (C) 2004, 2005, 2006, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -41,13 +42,33 @@ namespace WebCore { using namespace HTMLNames; -HTMLOptionElement::HTMLOptionElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f) - : HTMLFormControlElement(tagName, doc, f) +HTMLOptionElement::HTMLOptionElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form) + : HTMLFormControlElement(tagName, document, form) , m_style(0) { ASSERT(hasTagName(optionTag)); } +PassRefPtr<HTMLOptionElement> HTMLOptionElement::createForJSConstructor(Document* document, const String& data, const String& value, + bool defaultSelected, bool selected, ExceptionCode& ec) +{ + RefPtr<HTMLOptionElement> element = new HTMLOptionElement(optionTag, document); + + RefPtr<Text> text = Text::create(document, data.isNull() ? "" : data); + + ec = 0; + element->appendChild(text.release(), ec); + if (ec) + return 0; + + if (!value.isNull()) + element->setValue(value); + element->setDefaultSelected(defaultSelected); + element->setSelected(selected); + + return element.release(); +} + bool HTMLOptionElement::checkDTD(const Node* newChild) { return newChild->isTextNode() || newChild->hasTagName(scriptTag); @@ -178,7 +199,7 @@ HTMLSelectElement* HTMLOptionElement::ownerSelectElement() const if (!select) return 0; - + return static_cast<HTMLSelectElement*>(select); } @@ -207,9 +228,9 @@ void HTMLOptionElement::setRenderStyle(PassRefPtr<RenderStyle> newStyle) m_style = newStyle; } -RenderStyle* HTMLOptionElement::nonRendererRenderStyle() const -{ - return m_style.get(); +RenderStyle* HTMLOptionElement::nonRendererRenderStyle() const +{ + return m_style.get(); } String HTMLOptionElement::textIndentedToRespectGroupLabel() const @@ -218,8 +239,8 @@ String HTMLOptionElement::textIndentedToRespectGroupLabel() const } bool HTMLOptionElement::disabled() const -{ - return ownElementDisabled() || (parentNode() && static_cast<HTMLFormControlElement*>(parentNode())->disabled()); +{ + return ownElementDisabled() || (parentNode() && static_cast<HTMLFormControlElement*>(parentNode())->disabled()); } void HTMLOptionElement::insertedIntoTree(bool deep) @@ -231,7 +252,7 @@ void HTMLOptionElement::insertedIntoTree(bool deep) select->setSelectedIndex(index(), false); select->scrollToSelection(); } - + HTMLFormControlElement::insertedIntoTree(deep); } diff --git a/WebCore/html/HTMLOptionElement.h b/WebCore/html/HTMLOptionElement.h index 7be9e9a..4255f25 100644 --- a/WebCore/html/HTMLOptionElement.h +++ b/WebCore/html/HTMLOptionElement.h @@ -3,6 +3,7 @@ * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * Copyright (C) 2010 Google Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -39,6 +40,9 @@ class HTMLOptionElement : public HTMLFormControlElement, public OptionElement { public: HTMLOptionElement(const QualifiedName&, Document*, HTMLFormElement* = 0); + static PassRefPtr<HTMLOptionElement> createForJSConstructor(Document*, const String& data, const String& value, + bool defaultSelected, bool selected, ExceptionCode&); + virtual HTMLTagStatus endTagRequirement() const { return TagStatusOptional; } virtual int tagPriority() const { return 2; } virtual bool checkDTD(const Node* newChild); @@ -48,7 +52,7 @@ public: virtual void attach(); virtual void detach(); virtual void setRenderStyle(PassRefPtr<RenderStyle>); - + virtual const AtomicString& formControlType() const; virtual String text() const; @@ -78,10 +82,10 @@ public: bool ownElementDisabled() const { return HTMLFormControlElement::disabled(); } virtual bool disabled() const; - + virtual void insertedIntoTree(bool); virtual void accessKeyAction(bool); - + private: virtual RenderStyle* nonRendererRenderStyle() const; diff --git a/WebCore/html/HTMLPlugInElement.cpp b/WebCore/html/HTMLPlugInElement.cpp index 9319034..51db115 100644 --- a/WebCore/html/HTMLPlugInElement.cpp +++ b/WebCore/html/HTMLPlugInElement.cpp @@ -151,6 +151,12 @@ bool HTMLPlugInElement::checkDTD(const Node* newChild) void HTMLPlugInElement::defaultEventHandler(Event* event) { + // Firefox seems to use a fake event listener to dispatch events to plug-in (tested with mouse events only). + // This is observable via different order of events - in Firefox, event listeners specified in HTML attributes fires first, then an event + // gets dispatched to plug-in, and only then other event listeners fire. Hopefully, this difference does not matter in practice. + + // FIXME: Mouse down and scroll events are passed down to plug-in via custom code in EventHandler; these code paths should be united. + RenderObject* r = renderer(); if (!r || !r->isWidget()) return; diff --git a/WebCore/html/HTMLVideoElement.h b/WebCore/html/HTMLVideoElement.h index a5c005c..d12667e 100644 --- a/WebCore/html/HTMLVideoElement.h +++ b/WebCore/html/HTMLVideoElement.h @@ -70,7 +70,6 @@ public: bool webkitSupportsFullscreen(); bool webkitDisplayingFullscreen(); - void updatePosterImage(); bool shouldDisplayPosterImage() const { return m_shouldDisplayPosterImage; } void paint(GraphicsContext*, const IntRect&); @@ -79,6 +78,7 @@ public: private: virtual bool hasAvailableVideoFrame() const; + virtual void updatePosterImage(); OwnPtr<HTMLImageLoader> m_imageLoader; KURL m_posterURL; diff --git a/WebCore/html/ValidityState.cpp b/WebCore/html/ValidityState.cpp index 1e0a07b..c6c58a5 100644 --- a/WebCore/html/ValidityState.cpp +++ b/WebCore/html/ValidityState.cpp @@ -80,7 +80,7 @@ bool ValidityState::typeMismatch() const case HTMLInputElement::COLOR: return !isValidColorString(value); case HTMLInputElement::NUMBER: - return !HTMLInputElement::formStringToDouble(value, 0); + return !HTMLInputElement::parseToDoubleForNumberType(value, 0); case HTMLInputElement::URL: return !KURL(KURL(), value).isValid(); case HTMLInputElement::EMAIL: { @@ -100,7 +100,7 @@ bool ValidityState::typeMismatch() const case HTMLInputElement::MONTH: case HTMLInputElement::TIME: case HTMLInputElement::WEEK: - return !HTMLInputElement::formStringToDateComponents(input->inputType(), value, 0); + return !HTMLInputElement::parseToDateComponents(input->inputType(), value, 0); case HTMLInputElement::BUTTON: case HTMLInputElement::CHECKBOX: case HTMLInputElement::FILE: diff --git a/WebCore/inspector/InspectorController.cpp b/WebCore/inspector/InspectorController.cpp index 3d0ba9e..b487ad8 100644 --- a/WebCore/inspector/InspectorController.cpp +++ b/WebCore/inspector/InspectorController.cpp @@ -24,7 +24,7 @@ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" @@ -64,7 +64,6 @@ #include "InspectorFrontendHost.h" #include "InspectorResource.h" #include "InspectorTimelineAgent.h" -#include "JavaScriptProfile.h" #include "Page.h" #include "ProgressTracker.h" #include "Range.h" @@ -101,6 +100,7 @@ #include "JSJavaScriptCallFrame.h" #include "JavaScriptCallFrame.h" #include "JavaScriptDebugServer.h" +#include "JavaScriptProfile.h" #include <runtime/JSLock.h> #include <runtime/UString.h> @@ -654,12 +654,13 @@ void InspectorController::populateScriptObjects() return; m_frontend->populateFrontendSettings(setting(FrontendSettingsSettingName)); - m_domAgent->setDocument(m_inspectedPage->mainFrame()->document()); ResourcesMap::iterator resourcesEnd = m_resources.end(); for (ResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it) it->second->updateScriptObject(m_frontend.get()); + m_domAgent->setDocument(m_inspectedPage->mainFrame()->document()); + if (m_expiredConsoleMessageCount) m_frontend->updateConsoleMessageExpiredCount(m_expiredConsoleMessageCount); unsigned messageCount = m_consoleMessages.size(); diff --git a/WebCore/inspector/front-end/DOMAgent.js b/WebCore/inspector/front-end/DOMAgent.js index 6889408..834f527 100644 --- a/WebCore/inspector/front-end/DOMAgent.js +++ b/WebCore/inspector/front-end/DOMAgent.js @@ -153,10 +153,13 @@ WebInspector.DOMNode.prototype = { _insertChild: function(prev, payload) { var node = new WebInspector.DOMNode(this.ownerDocument, payload); - if (!prev) - // First node - this.children = [ node ]; - else + if (!prev) { + if (!this.children) { + // First node + this.children = [ node ]; + } else + this.children.unshift(node); + } else this.children.splice(this.children.indexOf(prev) + 1, 0, node); this._renumber(); return node; diff --git a/WebCore/inspector/front-end/ElementsPanel.js b/WebCore/inspector/front-end/ElementsPanel.js index e839a60..897fdd1 100644 --- a/WebCore/inspector/front-end/ElementsPanel.js +++ b/WebCore/inspector/front-end/ElementsPanel.js @@ -245,13 +245,8 @@ WebInspector.ElementsPanel.prototype = { searchCanceled: function() { - if (this._searchResults) { - for (var i = 0; i < this._searchResults.length; ++i) { - var treeElement = this.treeOutline.findTreeElement(this._searchResults[i]); - if (treeElement) - treeElement.highlighted = false; - } - } + delete this._searchQuery; + this._hideSearchHighlights(); WebInspector.updateSearchMatchesCount(0, this); @@ -271,6 +266,7 @@ WebInspector.ElementsPanel.prototype = { this._updatedMatchCountOnce = false; this._matchesCountUpdateTimeout = null; + this._searchQuery = query; InjectedScriptAccess.getDefault().performSearch(whitespaceTrimmedQuery, function() {}); }, @@ -304,25 +300,10 @@ WebInspector.ElementsPanel.prototype = { if (!node) continue; - if (!this._searchResults.length) { - this._currentSearchResultIndex = 0; - - // Only change the focusedDOMNode if the search was manually performed, because - // the search may have been performed programmatically and we wouldn't want to - // change the current focusedDOMNode. - if (WebInspector.currentFocusElement === document.getElementById("search")) - this.focusedDOMNode = node; - } - + this._currentSearchResultIndex = 0; this._searchResults.push(node); - - // Highlight the tree element to show it matched the search. - // FIXME: highlight the substrings in text nodes and attributes. - var treeElement = this.treeOutline.findTreeElement(node); - if (treeElement) - treeElement.highlighted = true; } - + this._highlightCurrentSearchResult(); this._updateMatchesCountSoon(); }, @@ -330,18 +311,41 @@ WebInspector.ElementsPanel.prototype = { { if (!this._searchResults || !this._searchResults.length) return; + if (++this._currentSearchResultIndex >= this._searchResults.length) this._currentSearchResultIndex = 0; - this.focusedDOMNode = this._searchResults[this._currentSearchResultIndex]; + this._highlightCurrentSearchResult(); }, jumpToPreviousSearchResult: function() { if (!this._searchResults || !this._searchResults.length) return; + if (--this._currentSearchResultIndex < 0) this._currentSearchResultIndex = (this._searchResults.length - 1); - this.focusedDOMNode = this._searchResults[this._currentSearchResultIndex]; + this._highlightCurrentSearchResult(); + }, + + _highlightCurrentSearchResult: function() + { + this._hideSearchHighlights(); + var node = this._searchResults[this._currentSearchResultIndex]; + var treeElement = this.treeOutline.findTreeElement(node); + if (treeElement) { + treeElement.highlightSearchResults(this._searchQuery); + treeElement.reveal(); + } + }, + + _hideSearchHighlights: function(node) + { + for (var i = 0; this._searchResults && i < this._searchResults.length; ++i) { + var node = this._searchResults[i]; + var treeElement = this.treeOutline.findTreeElement(node); + if (treeElement) + treeElement.highlightSearchResults(null); + } }, renameSelector: function(oldIdentifier, newIdentifier, oldSelector, newSelector) @@ -523,7 +527,8 @@ WebInspector.ElementsPanel.prototype = { if (this.recentlyModifiedNodes[i].updated) { var nodeItem = this.treeOutline.findTreeElement(node); - nodeItem.updateTitle(); + if (nodeItem) + nodeItem.updateTitle(); continue; } diff --git a/WebCore/inspector/front-end/ElementsTreeOutline.js b/WebCore/inspector/front-end/ElementsTreeOutline.js index 4a8dae0..fe7ae53 100644 --- a/WebCore/inspector/front-end/ElementsTreeOutline.js +++ b/WebCore/inspector/front-end/ElementsTreeOutline.js @@ -59,9 +59,16 @@ WebInspector.ElementsTreeOutline.prototype = { this._rootDOMNode = x; + this._isXMLMimeType = !!(WebInspector.mainResource && WebInspector.mainResource.mimeType && WebInspector.mainResource.mimeType.match(/x(?:ht)?ml/i)); + this.update(); }, + get isXMLMimeType() + { + return this._isXMLMimeType; + }, + get focusedDOMNode() { return this._focusedDOMNode; @@ -155,12 +162,27 @@ WebInspector.ElementsTreeOutline.prototype = { return treeElement; }, + createTreeElementFor: function(node) + { + var treeElement = this.findTreeElement(node); + if (treeElement) + return treeElement; + if (!node.parentNode) + return null; + + var treeElement = this.createTreeElementFor(node.parentNode); + if (treeElement && treeElement.showChild(node.index)) + return treeElement.children[node.index]; + + return null; + }, + revealAndSelectNode: function(node) { if (!node) return; - var treeElement = this.findTreeElement(node); + var treeElement = this.createTreeElementFor(node); if (!treeElement) return; @@ -277,9 +299,9 @@ WebInspector.ElementsTreeOutline.prototype = { var tag = event.target.enclosingNodeOrSelfWithClass("webkit-html-tag"); var textNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-text-node"); - if (tag) + if (tag && listItem.treeElement._populateTagContextMenu) listItem.treeElement._populateTagContextMenu(contextMenu, event); - else if (textNode) + else if (textNode && listItem.treeElement._populateTextContextMenu) listItem.treeElement._populateTextContextMenu(contextMenu, textNode); contextMenu.show(event); } @@ -296,27 +318,28 @@ WebInspector.ElementsTreeElement = function(node) if (this.representedObject.nodeType == Node.ELEMENT_NODE) this._canAddAttributes = true; + this._searchQuery = null; + this._expandedChildrenLimit = WebInspector.ElementsTreeElement.InitialChildrenLimit; } -WebInspector.ElementsTreeElement.prototype = { - get highlighted() - { - return this._highlighted; - }, +WebInspector.ElementsTreeElement.InitialChildrenLimit = 500; + +// A union of HTML4 and HTML5-Draft elements that explicitly +// or implicitly (for HTML5) forbid the closing tag. +// FIXME: Revise once HTML5 Final is published. +WebInspector.ElementsTreeElement.ForbiddenClosingTagElements = [ + "area", "base", "basefont", "br", "canvas", "col", "command", "embed", "frame", + "hr", "img", "input", "isindex", "keygen", "link", "meta", "param", "source" +].keySet(); - set highlighted(x) +WebInspector.ElementsTreeElement.prototype = { + highlightSearchResults: function(searchQuery) { - if (this._highlighted === x) + if (this._searchQuery === searchQuery) return; - this._highlighted = x; - - if (this.listItemElement) { - if (x) - this.listItemElement.addStyleClass("highlighted"); - else - this.listItemElement.removeStyleClass("highlighted"); - } + this._searchQuery = searchQuery; + this.updateTitle(); }, get hovered() @@ -341,6 +364,42 @@ WebInspector.ElementsTreeElement.prototype = { } }, + get expandedChildrenLimit() + { + return this._expandedChildrenLimit; + }, + + set expandedChildrenLimit(x) + { + if (this._expandedChildrenLimit === x) + return; + + this._expandedChildrenLimit = x; + if (this.treeOutline && !this._updateChildrenInProgress) + this._updateChildren(true); + }, + + get expandedChildCount() + { + var count = this.children.length; + if (count && this.children[count - 1].elementCloseTag) + count--; + if (count && this.children[count - 1].expandAllButton) + count--; + return count; + }, + + showChild: function(index) + { + if (index >= this.expandedChildrenLimit) { + this._expandedChildrenLimit = index + 1; + this._updateChildren(true); + } + + // Whether index-th child is visible in the children tree + return this.expandedChildCount > index; + }, + createTooltipForImageNode: function(node, callback) { function createTooltipThenCallback(properties) @@ -386,9 +445,6 @@ WebInspector.ElementsTreeElement.prototype = { { this.listItemElement.addEventListener("mousedown", this.onmousedown.bind(this), false); - if (this._highlighted) - this.listItemElement.addStyleClass("highlighted"); - if (this._hovered) { this.updateSelection(); this.listItemElement.addStyleClass("hovered"); @@ -422,9 +478,34 @@ WebInspector.ElementsTreeElement.prototype = { WebInspector.domAgent.getChildNodesAsync(this.representedObject, this._updateChildren.bind(this, fullRefresh)); }, + insertChildElement: function(child, index) + { + var newElement = new WebInspector.ElementsTreeElement(child); + newElement.selectable = this.treeOutline.selectEnabled; + this.insertChild(newElement, index); + return newElement; + }, + + moveChild: function(child, targetIndex) + { + var wasSelected = child.selected; + treeElement.removeChild(child); + treeElement.insertChild(child, targetIndex); + if (wasSelected) + existingTreeElement.select(); + }, + _updateChildren: function(fullRefresh) { + if (this._updateChildrenInProgress) + return; + + this._updateChildrenInProgress = true; + var focusedNode = this.treeOutline.focusedDOMNode; + var originalScrollTop; if (fullRefresh) { + var treeOutlineContainerElement = this.treeOutline.element.parentNode; + originalScrollTop = treeOutlineContainerElement.scrollTop; var selectedTreeElement = this.treeOutline.selectedTreeElement; if (selectedTreeElement && selectedTreeElement.hasAncestor(this)) this.select(); @@ -433,6 +514,7 @@ WebInspector.ElementsTreeElement.prototype = { var treeElement = this; var treeChildIndex = 0; + var elementToSelect; function updateChildrenOfNode(node) { @@ -443,7 +525,7 @@ WebInspector.ElementsTreeElement.prototype = { if (!currentTreeElement || currentTreeElement.representedObject !== child) { // Find any existing element that is later in the children list. var existingTreeElement = null; - for (var i = (treeChildIndex + 1); i < treeElement.children.length; ++i) { + for (var i = (treeChildIndex + 1), size = treeElement.expandedChildCount; i < size; ++i) { if (treeElement.children[i].representedObject === child) { existingTreeElement = treeElement.children[i]; break; @@ -452,16 +534,16 @@ WebInspector.ElementsTreeElement.prototype = { if (existingTreeElement && existingTreeElement.parent === treeElement) { // If an existing element was found and it has the same parent, just move it. - var wasSelected = existingTreeElement.selected; - treeElement.removeChild(existingTreeElement); - treeElement.insertChild(existingTreeElement, treeChildIndex); - if (wasSelected) - existingTreeElement.select(); + treeElement.moveChild(existingTreeElement, treeChildIndex); } else { // No existing element found, insert a new element. - var newElement = new WebInspector.ElementsTreeElement(child); - newElement.selectable = treeOutline.selectEnabled; - treeElement.insertChild(newElement, treeChildIndex); + if (treeChildIndex < treeElement.expandedChildrenLimit) { + var newElement = treeElement.insertChildElement(child, treeChildIndex); + if (child === focusedNode) + elementToSelect = newElement; + if (treeElement.expandedChildCount > treeElement.expandedChildrenLimit) + treeElement.expandedChildrenLimit++; + } } } @@ -490,6 +572,7 @@ WebInspector.ElementsTreeElement.prototype = { } updateChildrenOfNode(this.representedObject); + this.adjustCollapsedRange(false); var lastChild = this.children[this.children.length - 1]; if (this.representedObject.nodeType == Node.ELEMENT_NODE && (!lastChild || !lastChild.elementCloseTag)) { @@ -499,15 +582,66 @@ WebInspector.ElementsTreeElement.prototype = { item.elementCloseTag = true; this.appendChild(item); } + + // We want to restore the original selection and tree scroll position after a full refresh, if possible. + if (fullRefresh && elementToSelect) { + elementToSelect.select(); + if (treeOutlineContainerElement && originalScrollTop <= treeOutlineContainerElement.scrollHeight) + treeOutlineContainerElement.scrollTop = originalScrollTop; + } + + delete this._updateChildrenInProgress; + }, + + adjustCollapsedRange: function() + { + // Ensure precondition: only the tree elements for node children are found in the tree + // (not the Expand All button or the closing tag). + if (this.expandAllButtonElement && this.expandAllButtonElement.__treeElement.parent) + this.removeChild(this.expandAllButtonElement.__treeElement); + + const node = this.representedObject; + if (!node.children) + return; + const childNodeCount = node.children.length; + + // In case some nodes from the expanded range were removed, pull some nodes from the collapsed range into the expanded range at the bottom. + for (var i = this.expandedChildCount, limit = Math.min(this.expandedChildrenLimit, childNodeCount); i < limit; ++i) + this.insertChildElement(node.children[i], i); + + const expandedChildCount = this.expandedChildCount; + if (childNodeCount > this.expandedChildCount) { + var targetButtonIndex = expandedChildCount; + if (!this.expandAllButtonElement) { + var title = "<button class=\"show-all-nodes\" value=\"\" />"; + var item = new TreeElement(title, null, false); + item.selectable = false; + item.expandAllButton = true; + this.insertChild(item, targetButtonIndex); + this.expandAllButtonElement = item.listItemElement.firstChild; + this.expandAllButtonElement.__treeElement = item; + this.expandAllButtonElement.addEventListener("click", this.handleLoadAllChildren.bind(this), false); + } else if (!this.expandAllButtonElement.__treeElement.parent) + this.insertChild(this.expandAllButtonElement.__treeElement, targetButtonIndex); + this.expandAllButtonElement.textContent = WebInspector.UIString("Show All Nodes (%d More)", childNodeCount - expandedChildCount); + } else if (this.expandAllButtonElement) + delete this.expandAllButtonElement; + }, + + handleLoadAllChildren: function() + { + this.expandedChildrenLimit = Math.max(this.representedObject._childNodeCount, this.expandedChildrenLimit + WebInspector.ElementsTreeElement.InitialChildrenLimit); }, onexpand: function() { + this.updateTitle(); this.treeOutline.updateSelection(); }, oncollapse: function() { + this.updateTitle(); this.treeOutline.updateSelection(); }, @@ -879,11 +1013,12 @@ WebInspector.ElementsTreeElement.prototype = { var self = this; function callback(tooltipText) { - var title = self._nodeTitleInfo(self.representedObject, self.hasChildren, WebInspector.linkifyURL, tooltipText).title; + var title = self._nodeTitleInfo(WebInspector.linkifyURL, tooltipText).title; self.title = "<span class=\"highlight\">" + title + "</span>"; delete self.selectionElement; self.updateSelection(); self._preventFollowingLinksOnDoubleClick(); + self._highlightSearchResults(); }; // TODO: Replace with InjectedScriptAccess.getBasicProperties(obj, [names]). @@ -916,9 +1051,10 @@ WebInspector.ElementsTreeElement.prototype = { return hrefValue; }, - _nodeTitleInfo: function(node, hasChildren, linkify, tooltipText) + _nodeTitleInfo: function(linkify, tooltipText) { - var info = {title: "", hasChildren: hasChildren}; + var node = this.representedObject; + var info = {title: "", hasChildren: this.hasChildren}; switch (node.nodeType) { case Node.DOCUMENT_NODE: @@ -930,7 +1066,8 @@ WebInspector.ElementsTreeElement.prototype = { break; case Node.ELEMENT_NODE: - info.title = "<span class=\"webkit-html-tag\"><" + node.nodeName.toLowerCase().escapeHTML(); + var tagName = node.nodeName.toLowerCase().escapeHTML(); + info.title = "<span class=\"webkit-html-tag\"><" + tagName; if (node.hasAttributes()) { for (var i = 0; i < node.attributes.length; ++i) { @@ -951,15 +1088,21 @@ WebInspector.ElementsTreeElement.prototype = { } info.title += "></span>​"; + const closingTagHTML = "<span class=\"webkit-html-tag\"></" + tagName + "></span>​"; + var textChild = onlyTextChild.call(node); + var showInlineText = textChild && textChild.textContent.length < Preferences.maxInlineTextChildLength; + + if (!this.expanded && (!showInlineText && (this.treeOutline.isXMLMimeType || !WebInspector.ElementsTreeElement.ForbiddenClosingTagElements[tagName]))) { + if (this.hasChildren) + info.title += "<span class=\"webkit-html-text-node\">…</span>​"; + info.title += closingTagHTML; + } + // If this element only has a single child that is a text node, // just show that text and the closing tag inline rather than // create a subtree for them - - var textChild = onlyTextChild.call(node); - var showInlineText = textChild && textChild.textContent.length < Preferences.maxInlineTextChildLength; - if (showInlineText) { - info.title += "<span class=\"webkit-html-text-node\">" + textChild.nodeValue.escapeHTML() + "</span>​<span class=\"webkit-html-tag\"></" + node.nodeName.toLowerCase().escapeHTML() + "></span>"; + info.title += "<span class=\"webkit-html-text-node\">" + textChild.nodeValue.escapeHTML() + "</span>​" + closingTagHTML; info.hasChildren = false; } break; @@ -1038,6 +1181,7 @@ WebInspector.ElementsTreeElement.prototype = { return; parentElement.removeChild(self); + parentElement.adjustCollapsedRange(true); } var callId = WebInspector.Callback.wrap(removeNodeCallback); @@ -1077,6 +1221,23 @@ WebInspector.ElementsTreeElement.prototype = { _copyHTML: function() { InspectorBackend.copyNode(this.representedObject.id); + }, + + _highlightSearchResults: function() + { + if (!this._searchQuery) + return; + var text = this.listItemElement.textContent; + var regexObject = createSearchRegex(this._searchQuery); + + var offset = 0; + var match = regexObject.exec(text); + while (match) { + highlightSearchResult(this.listItemElement, offset + match.index, match[0].length); + offset += match.index + 1; + text = text.substring(match.index + 1); + match = regexObject.exec(text); + } } } diff --git a/WebCore/inspector/front-end/EventListenersSidebarPane.js b/WebCore/inspector/front-end/EventListenersSidebarPane.js index 649eea8..e454256 100644 --- a/WebCore/inspector/front-end/EventListenersSidebarPane.js +++ b/WebCore/inspector/front-end/EventListenersSidebarPane.js @@ -191,7 +191,7 @@ WebInspector.EventListenerBar.prototype = { // Just build properties in place - no need to reach out for injected script. var value = this.eventListener[propertyName]; if (value instanceof WebInspector.DOMNode) - value = new WebInspector.ObjectProxy(value.injectedScriptId, value.id, [], 0, appropriateSelectorForNode(value), true); + value = new WebInspector.ObjectProxy(value.injectedScriptId, value.id, [], appropriateSelectorForNode(value), true); else value = WebInspector.ObjectProxy.wrapPrimitiveValue(value); properties.push(new WebInspector.ObjectPropertyProxy(propertyName, value)); diff --git a/WebCore/inspector/front-end/Images/gearButtonGlyph.png b/WebCore/inspector/front-end/Images/gearButtonGlyph.png Binary files differnew file mode 100644 index 0000000..19659c9 --- /dev/null +++ b/WebCore/inspector/front-end/Images/gearButtonGlyph.png diff --git a/WebCore/inspector/front-end/Images/popoverArrows.png b/WebCore/inspector/front-end/Images/popoverArrows.png Binary files differnew file mode 100644 index 0000000..ccefa16 --- /dev/null +++ b/WebCore/inspector/front-end/Images/popoverArrows.png diff --git a/WebCore/inspector/front-end/Images/popoverBackground.png b/WebCore/inspector/front-end/Images/popoverBackground.png Binary files differnew file mode 100644 index 0000000..f20c988 --- /dev/null +++ b/WebCore/inspector/front-end/Images/popoverBackground.png diff --git a/WebCore/inspector/front-end/Images/thumbActiveHoriz.png b/WebCore/inspector/front-end/Images/thumbActiveHoriz.png Binary files differnew file mode 100644 index 0000000..a6ee561 --- /dev/null +++ b/WebCore/inspector/front-end/Images/thumbActiveHoriz.png diff --git a/WebCore/inspector/front-end/Images/thumbActiveVert.png b/WebCore/inspector/front-end/Images/thumbActiveVert.png Binary files differnew file mode 100644 index 0000000..a3eabe8 --- /dev/null +++ b/WebCore/inspector/front-end/Images/thumbActiveVert.png diff --git a/WebCore/inspector/front-end/Images/thumbHoriz.png b/WebCore/inspector/front-end/Images/thumbHoriz.png Binary files differnew file mode 100644 index 0000000..c16559a --- /dev/null +++ b/WebCore/inspector/front-end/Images/thumbHoriz.png diff --git a/WebCore/inspector/front-end/Images/thumbHoverHoriz.png b/WebCore/inspector/front-end/Images/thumbHoverHoriz.png Binary files differnew file mode 100644 index 0000000..0fe8d6a --- /dev/null +++ b/WebCore/inspector/front-end/Images/thumbHoverHoriz.png diff --git a/WebCore/inspector/front-end/Images/thumbHoverVert.png b/WebCore/inspector/front-end/Images/thumbHoverVert.png Binary files differnew file mode 100644 index 0000000..30e315a --- /dev/null +++ b/WebCore/inspector/front-end/Images/thumbHoverVert.png diff --git a/WebCore/inspector/front-end/Images/thumbVert.png b/WebCore/inspector/front-end/Images/thumbVert.png Binary files differnew file mode 100644 index 0000000..61fbc06 --- /dev/null +++ b/WebCore/inspector/front-end/Images/thumbVert.png diff --git a/WebCore/inspector/front-end/Images/trackHoriz.png b/WebCore/inspector/front-end/Images/trackHoriz.png Binary files differnew file mode 100644 index 0000000..517d306 --- /dev/null +++ b/WebCore/inspector/front-end/Images/trackHoriz.png diff --git a/WebCore/inspector/front-end/Images/trackVert.png b/WebCore/inspector/front-end/Images/trackVert.png Binary files differnew file mode 100644 index 0000000..d49620d --- /dev/null +++ b/WebCore/inspector/front-end/Images/trackVert.png diff --git a/WebCore/inspector/front-end/InjectedScript.js b/WebCore/inspector/front-end/InjectedScript.js index 95867c4..8d8fa88 100644 --- a/WebCore/inspector/front-end/InjectedScript.js +++ b/WebCore/inspector/front-end/InjectedScript.js @@ -485,25 +485,30 @@ InjectedScript.getProperties = function(objectProxy, ignoreHasOwnProperty, abbre var object = InjectedScript._resolveObject(objectProxy); if (!InjectedScript._isDefined(object)) return false; - var properties = []; + var propertyNames = ignoreHasOwnProperty ? InjectedScript._getPropertyNames(object) : Object.getOwnPropertyNames(object); + if (!ignoreHasOwnProperty && object.__proto__) + propertyNames.push("__proto__"); // Go over properties, prepare results. - for (var propertyName in object) { - if (!ignoreHasOwnProperty && "hasOwnProperty" in object && !object.hasOwnProperty(propertyName)) - continue; + for (var i = 0; i < propertyNames.length; ++i) { + var propertyName = propertyNames[i]; var property = {}; - property.name = propertyName; + property.name = propertyName + ""; property.parentObjectProxy = objectProxy; var isGetter = object["__lookupGetter__"] && object.__lookupGetter__(propertyName); if (!property.isGetter) { - var childObject = object[propertyName]; - var childObjectProxy = new InjectedScript.createProxyObject(childObject, objectProxy.objectId, abbreviate); - childObjectProxy.path = objectProxy.path ? objectProxy.path.slice() : []; - childObjectProxy.path.push(propertyName); - childObjectProxy.protoDepth = objectProxy.protoDepth || 0; - property.value = childObjectProxy; + try { + var childObject = object[propertyName]; + var childObjectProxy = new InjectedScript.createProxyObject(childObject, objectProxy.objectId, abbreviate); + childObjectProxy.path = objectProxy.path ? objectProxy.path.slice() : []; + childObjectProxy.path.push(propertyName); + property.value = childObjectProxy; + } catch(e) { + property.value = { description: e.toString() }; + property.isError = true; + } } else { // FIXME: this should show something like "getter" (bug 16734). property.value = { description: "\u2014" }; // em dash @@ -571,24 +576,25 @@ InjectedScript.setOuterHTML = function(nodeId, value, expanded) return InjectedScriptHost.pushNodePathToFrontend(newNode, expanded, false); } -InjectedScript._getPropertyNames = function(object, resultSet) +InjectedScript._populatePropertyNames = function(object, resultSet) { - if (Object.getOwnPropertyNames) { - for (var o = object; o; o = o.__proto__) { - try { - var names = Object.getOwnPropertyNames(o); - for (var i = 0; i < names.length; ++i) - resultSet[names[i]] = true; - } catch (e) { - } + for (var o = object; o; o = o.__proto__) { + try { + var names = Object.getOwnPropertyNames(o); + for (var i = 0; i < names.length; ++i) + resultSet[names[i] + ""] = true; + } catch (e) { } - } else { - // Chromium doesn't support getOwnPropertyNames yet. - for (var name in object) - resultSet[name] = true; } } +InjectedScript._getPropertyNames = function(object, resultSet) +{ + var propertyNameSet = {}; + InjectedScript._populatePropertyNames(object, propertyNameSet); + return Object.keys(propertyNameSet); +} + InjectedScript.getCompletions = function(expression, includeInspectorCommandLineAPI, callFrameId) { var props = {}; @@ -605,7 +611,7 @@ InjectedScript.getCompletions = function(expression, includeInspectorCommandLine // Evaluate into properties in scope of the selected call frame. var scopeChain = callFrame.scopeChain; for (var i = 0; i < scopeChain.length; ++i) - InjectedScript._getPropertyNames(scopeChain[i], props); + InjectedScript._populatePropertyNames(scopeChain[i], props); } } else { if (!expression) @@ -613,7 +619,7 @@ InjectedScript.getCompletions = function(expression, includeInspectorCommandLine expressionResult = InjectedScript._evaluateOn(InjectedScript._window().eval, InjectedScript._window(), expression); } if (typeof expressionResult == "object") - InjectedScript._getPropertyNames(expressionResult, props); + InjectedScript._populatePropertyNames(expressionResult, props); if (includeInspectorCommandLineAPI) for (var prop in InjectedScript._window().console._inspectorCommandLineAPI) if (prop.charAt(0) !== '_') @@ -677,6 +683,12 @@ InjectedScript.addInspectedNode = function(nodeId) InjectedScript.performSearch = function(whitespaceTrimmedQuery) { + // FIXME: Few things are missing here: + // 1) Search works with node granularity - number of matches within node is not calculated. + // 2) Search does not work outside main documents' domain - we need to use specific InjectedScript instances + // for other domains. + // 3) There is no need to push all search results to the front-end at a time, pushing next / previous result + // is sufficient. var tagNameQuery = whitespaceTrimmedQuery; var attributeNameQuery = whitespaceTrimmedQuery; var startTagFound = (tagNameQuery.indexOf("<") === 0); @@ -1073,10 +1085,6 @@ InjectedScript._resolveObject = function(objectProxy) for (var i = 0; InjectedScript._isDefined(object) && path && i < path.length; ++i) object = object[path[i]]; - // Get to the necessary proto layer. - for (var i = 0; InjectedScript._isDefined(object) && protoDepth && i < protoDepth; ++i) - object = object.__proto__; - return object; } @@ -1136,14 +1144,12 @@ InjectedScript.createProxyObject = function(object, objectId, abbreviate) result.injectedScriptId = injectedScriptId; result.objectId = objectId; result.type = InjectedScript._type(object); + if (result.type === "array") + result.propertyLength = object.length; var type = typeof object; - if ((type === "object" && object !== null) || type === "function") { - for (var subPropertyName in object) { - result.hasChildren = true; - break; - } - } + + result.hasChildren = (type === "object" && object !== null && (Object.getOwnPropertyNames(object).length || object.__proto__)) || type === "function"; try { result.description = InjectedScript._describe(object, abbreviate); } catch (e) { diff --git a/WebCore/inspector/front-end/ObjectPropertiesSection.js b/WebCore/inspector/front-end/ObjectPropertiesSection.js index 6d71090..a32e799 100644 --- a/WebCore/inspector/front-end/ObjectPropertiesSection.js +++ b/WebCore/inspector/front-end/ObjectPropertiesSection.js @@ -77,6 +77,7 @@ WebInspector.ObjectPropertiesSection.prototype = { var infoElement = new TreeElement(title, null, false); this.propertiesTreeOutline.appendChild(infoElement); } + this.propertiesForTest = properties; } } @@ -86,6 +87,10 @@ WebInspector.ObjectPropertiesSection.CompareProperties = function(propertyA, pro { var a = propertyA.name; var b = propertyB.name; + if (a === "__proto__") + return 1; + if (b === "__proto__") + return -1; // if used elsewhere make sure to // - convert a and b to strings (not needed here, properties are all strings) @@ -173,8 +178,12 @@ WebInspector.ObjectPropertyTreeElement.prototype = { this.valueElement = document.createElement("span"); this.valueElement.className = "value"; this.valueElement.textContent = this.property.value.description; + if (typeof this.property.value.propertyLength !== "undefined") + this.valueElement.textContent += " (" + this.property.value.propertyLength + ")"; if (this.property.isGetter) - this.valueElement.addStyleClass("dimmed"); + this.valueElement.addStyleClass("dimmed"); + if (this.property.isError) + this.valueElement.addStyleClass("error"); this.listItemElement.removeChildren(); diff --git a/WebCore/inspector/front-end/ObjectProxy.js b/WebCore/inspector/front-end/ObjectProxy.js index 62517b8..ef139c6 100644 --- a/WebCore/inspector/front-end/ObjectProxy.js +++ b/WebCore/inspector/front-end/ObjectProxy.js @@ -28,12 +28,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -WebInspector.ObjectProxy = function(injectedScriptId, objectId, path, protoDepth, description, hasChildren) +WebInspector.ObjectProxy = function(injectedScriptId, objectId, path, description, hasChildren) { this.objectId = objectId; this.injectedScriptId = injectedScriptId; this.path = path || []; - this.protoDepth = protoDepth || 0; this.description = description; this.hasChildren = hasChildren; } diff --git a/WebCore/inspector/front-end/Panel.js b/WebCore/inspector/front-end/Panel.js index 5e81e2d..5b01191 100644 --- a/WebCore/inspector/front-end/Panel.js +++ b/WebCore/inspector/front-end/Panel.js @@ -230,16 +230,17 @@ WebInspector.Panel.prototype = { var currentView = this._searchResults[this._currentSearchResultIndex]; if (currentView.showingLastSearchResult()) { - if (++this._currentSearchResultIndex >= this._searchResults.length) - this._currentSearchResultIndex = 0; - currentView = this._searchResults[this._currentSearchResultIndex]; + if (this.searchIteratesOverViews()) { + if (++this._currentSearchResultIndex >= this._searchResults.length) + this._currentSearchResultIndex = 0; + currentView = this._searchResults[this._currentSearchResultIndex]; + } showFirstResult = true; } if (currentView !== this.visibleView) { - currentView = this.visibleView; - this._currentSearchResultIndex = 0; - showFirstResult = true; + this.showView(currentView); + WebInspector.focusSearchField(); } if (showFirstResult) @@ -264,14 +265,18 @@ WebInspector.Panel.prototype = { var currentView = this._searchResults[this._currentSearchResultIndex]; if (currentView.showingFirstSearchResult()) { - if (--this._currentSearchResultIndex < 0) - this._currentSearchResultIndex = (this._searchResults.length - 1); - currentView = this._searchResults[this._currentSearchResultIndex]; + if (this.searchIteratesOverViews()) { + if (--this._currentSearchResultIndex < 0) + this._currentSearchResultIndex = (this._searchResults.length - 1); + currentView = this._searchResults[this._currentSearchResultIndex]; + } showLastResult = true; } - if (currentView !== this.visibleView) + if (currentView !== this.visibleView) { this.showView(currentView); + WebInspector.focusSearchField(); + } if (showLastResult) currentView.jumpToLastSearchResult(); @@ -376,6 +381,11 @@ WebInspector.Panel.prototype = { showSourceLineForURL: function(url, line) { return false; + }, + + searchIteratesOverViews: function() + { + return false; } } diff --git a/WebCore/inspector/front-end/Popover.js b/WebCore/inspector/front-end/Popover.js new file mode 100644 index 0000000..70e4ac9 --- /dev/null +++ b/WebCore/inspector/front-end/Popover.js @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +WebInspector.Popover = function(contentElement) +{ + this.element = document.createElement("div"); + this.element.className = "popover"; + + this._popupArrowElement = document.createElement("div"); + this._popupArrowElement.className = "arrow"; + this.element.appendChild(this._popupArrowElement); + + this.contentElement = contentElement; +} + +WebInspector.Popover.prototype = { + show: function(anchor, preferredWidth, preferredHeight) + { + // This should not happen, but we hide previous popup to be on the safe side. + if (WebInspector.Popover._popoverElement) + document.body.removeChild(WebInspector.Popover._popoverElement); + WebInspector.Popover._popoverElement = this.element; + + // Temporarily attach in order to measure preferred dimensions. + this.contentElement.positionAt(0, 0); + document.body.appendChild(this.contentElement); + var preferredWidth = preferredWidth || this.contentElement.offsetWidth; + var preferredHeight = preferredHeight || this.contentElement.offsetHeight; + + this.contentElement.addStyleClass("content"); + this.element.appendChild(this.contentElement); + document.body.appendChild(this.element); + this._positionElement(anchor, preferredWidth, preferredHeight); + }, + + hide: function() + { + delete WebInspector.Popover._popoverElement; + document.body.removeChild(this.element); + }, + + _positionElement: function(anchorElement, preferredWidth, preferredHeight) + { + const borderWidth = 25; + const scrollerWidth = 11; + const arrowHeight = 10; + const arrowOffset = 15; + + // Skinny tooltips are not pretty, their arrow location is not nice. + preferredWidth = Math.max(preferredWidth, 50); + const totalWidth = window.innerWidth; + const totalHeight = window.innerHeight; + + var anchorBox = {x: anchorElement.totalOffsetLeft, y: anchorElement.totalOffsetTop, width: anchorElement.offsetWidth, height: anchorElement.offsetHeight}; + while (anchorElement !== document.body) { + if (anchorElement.scrollLeft) + anchorBox.x -= anchorElement.scrollLeft; + if (anchorElement.scrollTop) + anchorBox.y -= anchorElement.scrollTop; + anchorElement = anchorElement.parentElement; + } + + var newElementPosition = { x: 0, y: 0, width: preferredWidth + borderWidth * 2, height: preferredHeight + borderWidth * 2 }; + + var verticalAlignment; + var roomAbove = anchorBox.y; + var roomBelow = totalHeight - anchorBox.y - anchorBox.height; + + if (roomAbove > roomBelow) { + // Positioning above the anchor. + if (anchorBox.y > newElementPosition.height) + newElementPosition.y = anchorBox.y - newElementPosition.height; + else { + newElementPosition.y = 0; + newElementPosition.height = anchorBox.y - newElementPosition.y; + // Reserve room for vertical scroller anyways. + newElementPosition.width += scrollerWidth; + } + verticalAlignment = "bottom"; + } else { + // Positioning below the anchor. + newElementPosition.y = anchorBox.y + anchorBox.height; + if (newElementPosition.y + newElementPosition.height >= totalHeight) { + newElementPosition.height = totalHeight - anchorBox.y - anchorBox.height; + // Reserve room for vertical scroller. + newElementPosition.width += scrollerWidth; + } + // Align arrow. + newElementPosition.y -= arrowHeight; + verticalAlignment = "top"; + } + + var horizontalAlignment; + if (anchorBox.x + newElementPosition.width < totalWidth) { + newElementPosition.x = Math.max(0, anchorBox.x) - borderWidth - arrowOffset; + horizontalAlignment = "left"; + } else if (newElementPosition.width < totalWidth) { + newElementPosition.x = totalWidth - newElementPosition.width; + horizontalAlignment = "right"; + // Position arrow accurately. + this._popupArrowElement.style.right = totalWidth - anchorBox.x - borderWidth - anchorBox.width + "px"; + } else { + newElementPosition.x = 0; + newElementPosition.width = totalWidth; + horizontalAlignment = "left"; + if (verticalAlignment === "bottom") + newElementPosition.y -= scrollerWidth; + // Position arrow accurately. + this._popupArrowElement.style.left = anchorBox.x - borderWidth + "px"; + } + + // Reserve room for horizontal scroller. + newElementPosition.height += scrollerWidth; + + this.element.className = "popover " + verticalAlignment + "-" + horizontalAlignment + "-arrow"; + this.element.positionAt(newElementPosition.x, newElementPosition.y); + this.element.style.width = newElementPosition.width + "px"; + this.element.style.height = newElementPosition.height + "px"; + } +} diff --git a/WebCore/inspector/front-end/Popup.js b/WebCore/inspector/front-end/Popup.js deleted file mode 100644 index 9c8ef24..0000000 --- a/WebCore/inspector/front-end/Popup.js +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * This class provides a popup that can be shown relative to an anchor element - * or at an arbitrary absolute position. - * Points are Objects: {x: xValue, y: yValue}. - * Rectangles are Objects: {x: xValue, y: yValue, width: widthValue, height: heightValue}. - * - * element is an optional unparented visible element (style.display != "none" AND style.visibility != "hidden"). - * If the element is absent/undefined, it must have been set with the element(x) setter before the show() method invocation. - */ -WebInspector.Popup = function(element) -{ - if (element) - this.element = element; - this._keyHandler = this._keyEventHandler.bind(this); - this._mouseDownHandler = this._mouseDownEventHandler.bind(this); - this._visible = false; - this._autoHide = true; -} - -WebInspector.Popup.prototype = { - show: function() - { - if (this.visible) - return; - var ownerDocument = this._contentElement.ownerDocument; - if (!ownerDocument) - return; - - this._glasspaneElement = ownerDocument.createElement("div"); - this._glasspaneElement.className = "popup-glasspane"; - ownerDocument.body.appendChild(this._glasspaneElement); - - this._contentElement.positionAt(0, 0); - this._contentElement.removeStyleClass("hidden"); - ownerDocument.body.appendChild(this._contentElement); - - this.positionElement(); - this._visible = true; - ownerDocument.addEventListener("keydown", this._keyHandler, false); - ownerDocument.addEventListener("mousedown", this._mouseDownHandler, false); - }, - - hide: function() - { - if (this.visible) { - this._visible = false; - this._contentElement.ownerDocument.removeEventListener("keydown", this._keyHandler, false); - this._contentElement.ownerDocument.removeEventListener("mousedown", this._mouseDownHandler, false); - this._glasspaneElement.parentElement.removeChild(this._glasspaneElement); - this._contentElement.parentElement.removeChild(this._contentElement); - } - }, - - get visible() - { - return this._visible; - }, - - set element(x) - { - this._checkNotVisible(); - this._contentElement = x; - this._contentElement.addStyleClass("hidden"); - }, - - get element() - { - return this._contentElement; - }, - - positionElement: function() - { - var element = this._contentElement; - var anchorElement = this._anchorElement; - - var targetDocument = element.ownerDocument; - var targetDocumentBody = targetDocument.body; - var targetDocumentElement = targetDocument.documentElement; - var clippingBox = {x: 0, y: 0, width: targetDocumentElement.clientWidth, height: targetDocumentElement.clientHeight}; - var parentElement = element.offsetParent || element.parentElement; - - var anchorPosition = {x: anchorElement.totalOffsetLeft, y: anchorElement.totalOffsetTop}; - - // FIXME(apavlov@chromium.org): Translate anchorPosition to the element.ownerDocument frame when https://bugs.webkit.org/show_bug.cgi?id=28913 is fixed. - var anchorBox = {x: anchorPosition.x, y: anchorPosition.y, width: anchorElement.offsetWidth, height: anchorElement.offsetHeight}; - var elementBox = {x: element.totalOffsetLeft, y: element.totalOffsetTop, width: element.offsetWidth, height: element.offsetHeight}; - var newElementPosition = {x: 0, y: 0}; - - if (anchorBox.y - elementBox.height >= clippingBox.y) - newElementPosition.y = anchorBox.y - elementBox.height; - else - newElementPosition.y = Math.min(anchorBox.y + anchorBox.height, Math.max(clippingBox.y, clippingBox.y + clippingBox.height - elementBox.height)); - - if (anchorBox.x + elementBox.height <= clippingBox.x + clippingBox.height) - newElementPosition.x = anchorBox.x; - else - newElementPosition.x = Math.max(clippingBox.x, clippingBox.x + clippingBox.height - elementBox.height); - element.positionAt(newElementPosition.x, newElementPosition.y); - }, - - set anchor(x) - { - this._checkNotVisible(); - this._anchorElement = x; - }, - - get anchor() - { - return this._anchorElement; - }, - - set autoHide(x) - { - this._autoHide = x; - }, - - _checkNotVisible: function() - { - if (this.visible) - throw new Error("The popup must not be visible."); - }, - - _keyEventHandler: function(event) - { - // Escape hides the popup. - if (event.keyIdentifier == "U+001B") { - this.hide(); - event.preventDefault(); - event.handled = true; - } - }, - - _mouseDownEventHandler: function(event) - { - if (this._autoHide && event.originalTarget === this._glasspaneElement) - this.hide(); - } -} diff --git a/WebCore/inspector/front-end/PropertiesSidebarPane.js b/WebCore/inspector/front-end/PropertiesSidebarPane.js index 857d9a7..9df6448 100644 --- a/WebCore/inspector/front-end/PropertiesSidebarPane.js +++ b/WebCore/inspector/front-end/PropertiesSidebarPane.js @@ -48,12 +48,14 @@ WebInspector.PropertiesSidebarPane.prototype = { body.removeChildren(); self.sections = []; + var path = []; // Get array of prototype user-friendly names. for (var i = 0; i < prototypes.length; ++i) { - var prototype = new WebInspector.ObjectProxy(node.injectedScriptId, node.id, [], i); + var prototype = new WebInspector.ObjectProxy(node.injectedScriptId, node.id, path.slice()); var section = new WebInspector.ObjectPropertiesSection(prototype, prototypes[i], WebInspector.UIString("Prototype")); self.sections.push(section); body.appendChild(section.element); + path.push("__proto__"); } }; InjectedScriptAccess.get(node.injectedScriptId).getPrototypes(node.id, callback); diff --git a/WebCore/inspector/front-end/ResourcesPanel.js b/WebCore/inspector/front-end/ResourcesPanel.js index 40a380c..19325bb 100644 --- a/WebCore/inspector/front-end/ResourcesPanel.js +++ b/WebCore/inspector/front-end/ResourcesPanel.js @@ -706,6 +706,11 @@ WebInspector.ResourcesPanel.prototype = { get _resources() { return this.items; + }, + + searchIteratesOverViews: function() + { + return true; } } diff --git a/WebCore/inspector/front-end/Section.js b/WebCore/inspector/front-end/Section.js index 394f86d..7710192 100644 --- a/WebCore/inspector/front-end/Section.js +++ b/WebCore/inspector/front-end/Section.js @@ -31,6 +31,7 @@ WebInspector.Section = function(title, subtitle) { this.element = document.createElement("div"); this.element.className = "section"; + this.element.sectionForTest = this; this.headerElement = document.createElement("div"); this.headerElement.className = "header"; diff --git a/WebCore/inspector/front-end/SourceFrame.js b/WebCore/inspector/front-end/SourceFrame.js index 0f90700..799628e 100644 --- a/WebCore/inspector/front-end/SourceFrame.js +++ b/WebCore/inspector/front-end/SourceFrame.js @@ -45,6 +45,7 @@ WebInspector.SourceFrame = function(parentElement, addBreakpointDelegate, remove this._addBreakpointDelegate = addBreakpointDelegate; this._removeBreakpointDelegate = removeBreakpointDelegate; + this._popoverObjectGroup = "popover"; } WebInspector.SourceFrame.prototype = { @@ -53,6 +54,9 @@ WebInspector.SourceFrame.prototype = { { this._visible = visible; this._createViewerIfNeeded(); + if (!visible && this._textViewer) + this._textViewer.freeCachedElements(); + }, get executionLine() @@ -157,6 +161,8 @@ WebInspector.SourceFrame.prototype = { element.addEventListener("keydown", this._keyDown.bind(this), true); element.addEventListener("contextmenu", this._contextMenu.bind(this), true); element.addEventListener("mousedown", this._mouseDown.bind(this), true); + element.addEventListener("mousemove", this._mouseMove.bind(this), true); + element.addEventListener("scroll", this._scroll.bind(this), true); this._parentElement.appendChild(element); this._needsProgramCounterImage = true; @@ -193,14 +199,7 @@ WebInspector.SourceFrame.prototype = { var ranges = []; // First do case-insensitive search. - var regex = ""; - for (var i = 0; i < query.length; ++i) { - var char = query.charAt(i); - if (char === "]") - char = "\\]"; - regex += "[" + char + "]"; - } - var regexObject = new RegExp(regex, "i"); + var regexObject = createSearchRegex(query); this._collectRegexMatches(regexObject, ranges); // Then try regex search if user knows the / / hint. @@ -427,8 +426,15 @@ WebInspector.SourceFrame.prototype = { contextMenu.show(event); }, + _scroll: function(event) + { + this._hidePopup(); + }, + _mouseDown: function(event) { + this._resetHoverTimer(); + this._hidePopup(); if (event.button != 0 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return; if (event.target.className !== "webkit-line-number") @@ -445,6 +451,164 @@ WebInspector.SourceFrame.prototype = { event.preventDefault(); }, + _mouseMove: function(event) + { + // Pretend that nothing has happened. + if (this._hoverElement === event.target) + return; + + this._resetHoverTimer(); + + // User has 500ms to reach the popup. + if (this._popup) { + var self = this; + function doHide() + { + self._hidePopup(); + delete self._hidePopupTimer; + } + this._hidePopupTimer = setTimeout(doHide, 500); + } + + this._hoverElement = event.target; + + // Now that cleanup routines are set up above, leave this in case we are not on a break. + if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused) + return; + + // We are interested in identifiers and "this" keyword. + if (this._hoverElement.hasStyleClass("webkit-javascript-keyword")) { + if (this._hoverElement.textContent !== "this") + return; + } else if (!this._hoverElement.hasStyleClass("webkit-javascript-ident")) + return; + + const toolTipDelay = 1500; + this._hoverTimer = setTimeout(this._mouseHover.bind(this, this._hoverElement), toolTipDelay); + }, + + _resetHoverTimer: function() + { + if (this._hoverTimer) { + clearTimeout(this._hoverTimer); + delete this._hoverTimer; + } + }, + + _hidePopup: function() + { + if (this._popup) { + this._popup.hide(); + delete this._popup; + InspectorBackend.releaseWrapperObjectGroup(0, this._popoverObjectGroup); + } + }, + + _mouseHover: function(element) + { + delete this._hoverTimer; + + if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused) + return; + + var lineRow = element.enclosingNodeOrSelfWithNodeName("tr"); + if (!lineRow) + return; + + // Find text offset of the hovered node (iterate over text nodes until we hit ours). + var offset = 0; + var node = lineRow.lastChild.traverseNextTextNode(lineRow.lastChild); + while (node && node !== element.firstChild) { + offset += node.nodeValue.length; + node = node.traverseNextTextNode(lineRow.lastChild); + } + + // Imagine that the line is "foo(A.B.C.D)" and we hit C. Following code goes through following steps: + // "foo(A.B.C" -> "C.B.A(oof" -> "C.B.A" -> "A.B.C" (target eval expression). + var lineNumber = lineRow.lineNumber; + var prefix = this._textModel.line(lineNumber).substring(0, offset + element.textContent.length); + var reversedPrefix = prefix.split("").reverse().join(""); + var match = /[a-zA-Z\x80-\xFF\_$0-9.]+/.exec(reversedPrefix); + if (!match) + return; + var expression = match[0].split("").reverse().join(""); + this._showPopup(element, expression); + }, + + _showPopup: function(element, expression) + { + function killHidePopupTimer() + { + if (this._hidePopupTimer) { + clearTimeout(this._hidePopupTimer); + delete this._hidePopupTimer; + + // We know that we reached the popup, but we might have moved over other elements. + // Discard pending command. + this._resetHoverTimer(); + } + } + + function showTextPopup(text) + { + if (!WebInspector.panels.scripts.paused) + return; + + var popupContentElement = document.createElement("span"); + popupContentElement.className = "monospace"; + popupContentElement.style.whiteSpace = "pre"; + popupContentElement.textContent = text; + this._popup = new WebInspector.Popover(popupContentElement); + this._popup.show(element); + popupContentElement.addEventListener("mousemove", killHidePopupTimer.bind(this), true); + } + + function showObjectPopup(result) + { + if (!WebInspector.panels.scripts.paused) + return; + + var popupContentElement = null; + if (result.type !== "object" && result.type !== "node" && result.type !== "array") { + popupContentElement = document.createElement("span"); + popupContentElement.className = "monospace"; + popupContentElement.style.whiteSpace = "pre"; + popupContentElement.textContent = result.description; + this._popup = new WebInspector.Popover(popupContentElement); + this._popup.show(element); + } else { + var popupContentElement = document.createElement("div"); + + var titleElement = document.createElement("div"); + titleElement.className = "source-frame-popover-title monospace"; + titleElement.textContent = result.description; + popupContentElement.appendChild(titleElement); + + var section = new WebInspector.ObjectPropertiesSection(result, "", null, false); + section.expanded = true; + section.element.addStyleClass("source-frame-popover-tree"); + section.headerElement.addStyleClass("hidden"); + popupContentElement.appendChild(section.element); + + this._popup = new WebInspector.Popover(popupContentElement); + const popupWidth = 300; + const popupHeight = 250; + this._popup.show(element, popupWidth, popupHeight); + } + popupContentElement.addEventListener("mousemove", killHidePopupTimer.bind(this), true); + } + + function evaluateCallback(result, exception) + { + if (exception) + return; + if (!WebInspector.panels.scripts.paused) + return; + showObjectPopup.call(this, result); + } + WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, this._popoverObjectGroup, evaluateCallback.bind(this)); + }, + _editBreakpointCondition: function(breakpoint) { this._showBreakpointConditionPopup(breakpoint.line); @@ -662,4 +826,5 @@ WebInspector.SourceFrame.prototype = { } } + WebInspector.SourceFrame.prototype.__proto__ = WebInspector.Object.prototype; diff --git a/WebCore/inspector/front-end/SourceHTMLTokenizer.js b/WebCore/inspector/front-end/SourceHTMLTokenizer.js index 8856ff5..3c9bd8c 100644 --- a/WebCore/inspector/front-end/SourceHTMLTokenizer.js +++ b/WebCore/inspector/front-end/SourceHTMLTokenizer.js @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 on Tue Feb 2 00:44:38 2010 */ +/* Generated by re2c 0.13.5 on Mon Feb 15 19:30:21 2010 */ /* * Copyright (C) 2009 Google Inc. All rights reserved. * @@ -413,6 +413,12 @@ case 66: ++cursor; this.setLexCondition(this._lexConditions.TAG); { + if (this._parseCondition & this._parseConditions.SCRIPT) { + // Do not tokenize script tag contents, keep lexer state although processing "<". + this.setLexCondition(this._lexConditions.INITIAL); + this.tokenType = null; + return cursor; + } this.tokenType = "html-tag"; this._parseCondition = this._parseConditions.SCRIPT; this._setExpectingAttribute(); diff --git a/WebCore/inspector/front-end/SourceHTMLTokenizer.re2js b/WebCore/inspector/front-end/SourceHTMLTokenizer.re2js index 89c535a..cfa8834 100644 --- a/WebCore/inspector/front-end/SourceHTMLTokenizer.re2js +++ b/WebCore/inspector/front-end/SourceHTMLTokenizer.re2js @@ -174,6 +174,12 @@ WebInspector.SourceHTMLTokenizer.prototype = { <INITIAL> ScriptStart => TAG { + if (this._parseCondition & this._parseConditions.SCRIPT) { + // Do not tokenize script tag contents, keep lexer state although processing "<". + this.setLexCondition(this._lexConditions.INITIAL); + this.tokenType = null; + return cursor; + } this.tokenType = "html-tag"; this._parseCondition = this._parseConditions.SCRIPT; this._setExpectingAttribute(); diff --git a/WebCore/inspector/front-end/SourceJavaScriptTokenizer.js b/WebCore/inspector/front-end/SourceJavaScriptTokenizer.js index 816023f..75abeee 100644 --- a/WebCore/inspector/front-end/SourceJavaScriptTokenizer.js +++ b/WebCore/inspector/front-end/SourceJavaScriptTokenizer.js @@ -49,7 +49,7 @@ WebInspector.SourceJavaScriptTokenizer = function() "null", "true", "false", "break", "case", "catch", "const", "default", "finally", "for", "instanceof", "new", "var", "continue", "function", "return", "void", "delete", "if", "this", "do", "while", "else", "in", "switch", "throw", "try", "typeof", "debugger", - "class", "enum", "export", "extends", "import", "super", "get", "set" + "class", "enum", "export", "extends", "import", "super", "get", "set", "with" ].keySet(); this._lexConditions = { diff --git a/WebCore/inspector/front-end/SourceJavaScriptTokenizer.re2js b/WebCore/inspector/front-end/SourceJavaScriptTokenizer.re2js index 8630ccb..053c82f 100644 --- a/WebCore/inspector/front-end/SourceJavaScriptTokenizer.re2js +++ b/WebCore/inspector/front-end/SourceJavaScriptTokenizer.re2js @@ -48,7 +48,7 @@ WebInspector.SourceJavaScriptTokenizer = function() "null", "true", "false", "break", "case", "catch", "const", "default", "finally", "for", "instanceof", "new", "var", "continue", "function", "return", "void", "delete", "if", "this", "do", "while", "else", "in", "switch", "throw", "try", "typeof", "debugger", - "class", "enum", "export", "extends", "import", "super", "get", "set" + "class", "enum", "export", "extends", "import", "super", "get", "set", "with" ].keySet(); this._lexConditions = { diff --git a/WebCore/inspector/front-end/SourceTokenizer.js b/WebCore/inspector/front-end/SourceTokenizer.js index 1192383..d498028 100644 --- a/WebCore/inspector/front-end/SourceTokenizer.js +++ b/WebCore/inspector/front-end/SourceTokenizer.js @@ -74,10 +74,11 @@ WebInspector.SourceTokenizer.prototype = { WebInspector.SourceTokenizer.Registry = function() { this._tokenizers = {}; this._tokenizerConstructors = { - "text/css": WebInspector.SourceCSSTokenizer, - "text/html": WebInspector.SourceHTMLTokenizer, - "text/javascript": WebInspector.SourceJavaScriptTokenizer, - "application/x-javascript": WebInspector.SourceJavaScriptTokenizer + "text/css": "SourceCSSTokenizer", + "text/html": "SourceHTMLTokenizer", + "text/javascript": "SourceJavaScriptTokenizer", + "application/javascript": "SourceJavaScriptTokenizer", + "application/x-javascript": "SourceJavaScriptTokenizer" }; } @@ -93,9 +94,10 @@ WebInspector.SourceTokenizer.Registry.prototype = { { if (!this._tokenizerConstructors[mimeType]) return null; - var tokenizer = this._tokenizers[mimeType]; + var tokenizerClass = this._tokenizerConstructors[mimeType]; + var tokenizer = this._tokenizers[tokenizerClass]; if (!tokenizer) { - tokenizer = new this._tokenizerConstructors[mimeType](); + tokenizer = new WebInspector[tokenizerClass](); this._tokenizers[mimeType] = tokenizer; } return tokenizer; diff --git a/WebCore/inspector/front-end/TextEditorHighlighter.js b/WebCore/inspector/front-end/TextEditorHighlighter.js index c73e036..cf0b590 100644 --- a/WebCore/inspector/front-end/TextEditorHighlighter.js +++ b/WebCore/inspector/front-end/TextEditorHighlighter.js @@ -32,36 +32,8 @@ WebInspector.TextEditorHighlighter = function(textModel, damageCallback) { this._textModel = textModel; - - this._styles = []; - - this._styles["css-comment"] = "rgb(0, 116, 0)"; - this._styles["css-params"] = "rgb(7, 144, 154)"; - this._styles["css-string"] = "rgb(7, 144, 154)"; - this._styles["css-keyword"] = "rgb(7, 144, 154)"; - this._styles["css-number"] = "rgb(50, 0, 255)"; - this._styles["css-property"] = "rgb(200, 0, 0)"; - this._styles["css-at-rule"] = "rgb(200, 0, 0)"; - this._styles["css-selector"] = "rgb(0, 0, 0)"; - this._styles["css-important"] = "rgb(200, 0, 180)"; - - /* Keep this in sync with inspector.css and view-source.css */ - this._styles["html-tag"] = "rgb(136, 18, 128)"; - this._styles["html-attribute-name"] = "rgb(153, 69, 0)"; - this._styles["html-attribute-value"] = "rgb(26, 26, 166)"; - this._styles["html-comment"] = "rgb(35, 110, 37)"; - this._styles["html-doctype"] = "rgb(192, 192, 192)"; - this._styles["html-external-link"] = "#00e"; - this._styles["html-resource-link"] = "#00e"; - - this._styles["javascript-comment"] = "rgb(0, 116, 0)"; - this._styles["javascript-string"] = "rgb(196, 26, 22)"; - this._styles["javascript-regexp"] = "rgb(196, 26, 22)"; - this._styles["javascript-keyword"] = "rgb(170, 13, 145)"; - this._styles["javascript-number"] = "rgb(28, 0, 207)"; - - this.mimeType = "text/html"; - this._damageCallback = damageCallback; + this._tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/html"); + this._damageCallback = damageCallback; } WebInspector.TextEditorHighlighter.prototype = { @@ -190,7 +162,7 @@ WebInspector.TextEditorHighlighter.prototype = { var newColumn = this._tokenizer.nextToken(column); var tokenType = this._tokenizer.tokenType; if (tokenType) - attributes[column] = { length: newColumn - column, tokenType: tokenType, style: this._styles[tokenType] }; + attributes[column] = { length: newColumn - column, tokenType: tokenType }; column = newColumn; } while (column < line.length) } diff --git a/WebCore/inspector/front-end/TextViewer.js b/WebCore/inspector/front-end/TextViewer.js index 096464f..9be6a00 100644 --- a/WebCore/inspector/front-end/TextViewer.js +++ b/WebCore/inspector/front-end/TextViewer.js @@ -50,6 +50,9 @@ WebInspector.TextViewer = function(textModel, platform, url) this._defaultChunkSize = 50; this._paintCoalescingLevel = 0; + + this.freeCachedElements(); + this._buildChunks(); } WebInspector.TextViewer.prototype = { @@ -96,7 +99,10 @@ WebInspector.TextViewer.prototype = { this._rangeToMark = range; this.revealLine(range.startLine); this._paintLines(range.startLine, range.startLine + 1); + if (this._markedRangeElement) + this._markedRangeElement.scrollIntoViewIfNeeded(); } + delete this._markedRangeElement; }, highlightLine: function(lineNumber) @@ -111,14 +117,20 @@ WebInspector.TextViewer.prototype = { chunk.addDecoration("webkit-highlighted-line"); }, + freeCachedElements: function() + { + this._cachedSpans = []; + this._cachedTextNodes = []; + this._cachedRows = []; + }, + _buildChunks: function() { this._linesContainerElement.removeChildren(); - var paintLinesCallback = this._paintLines.bind(this); this._textChunks = []; for (var i = 0; i < this._textModel.linesCount; i += this._defaultChunkSize) { - var chunk = new WebInspector.TextChunk(this._textModel, i, i + this._defaultChunkSize, paintLinesCallback); + var chunk = new WebInspector.TextChunk(this, i, i + this._defaultChunkSize); this._textChunks.push(chunk); this._linesContainerElement.appendChild(chunk.element); } @@ -140,23 +152,22 @@ WebInspector.TextViewer.prototype = { oldChunk.expanded = false; var insertIndex = oldChunk.chunkNumber + 1; - var paintLinesCallback = this._paintLines.bind(this); // Prefix chunk. if (lineNumber > oldChunk.startLine) { - var prefixChunk = new WebInspector.TextChunk(this._textModel, oldChunk.startLine, lineNumber, paintLinesCallback); + var prefixChunk = new WebInspector.TextChunk(this, oldChunk.startLine, lineNumber); this._textChunks.splice(insertIndex++, 0, prefixChunk); this._linesContainerElement.insertBefore(prefixChunk.element, oldChunk.element); } // Line chunk. - var lineChunk = new WebInspector.TextChunk(this._textModel, lineNumber, lineNumber + 1, paintLinesCallback); + var lineChunk = new WebInspector.TextChunk(this, lineNumber, lineNumber + 1); this._textChunks.splice(insertIndex++, 0, lineChunk); this._linesContainerElement.insertBefore(lineChunk.element, oldChunk.element); // Suffix chunk. if (oldChunk.startLine + oldChunk.linesCount > lineNumber + 1) { - var suffixChunk = new WebInspector.TextChunk(this._textModel, lineNumber + 1, oldChunk.startLine + oldChunk.linesCount, paintLinesCallback); + var suffixChunk = new WebInspector.TextChunk(this, lineNumber + 1, oldChunk.startLine + oldChunk.linesCount); this._textChunks.splice(insertIndex, 0, suffixChunk); this._linesContainerElement.insertBefore(suffixChunk.element, oldChunk.element); } @@ -185,7 +196,11 @@ WebInspector.TextViewer.prototype = { _scroll: function() { - this._repaintAll(); + var scrollTop = this.element.scrollTop; + setTimeout(function() { + if (scrollTop === this.element.scrollTop) + this._repaintAll(); + }.bind(this), 50); }, beginUpdates: function(enabled) @@ -320,7 +335,7 @@ WebInspector.TextViewer.prototype = { if (!highlighterState) { if (this._rangeToMark && this._rangeToMark.startLine === lineNumber) - this._markRange(element, line, this._rangeToMark.startColumn, this._rangeToMark.endColumn); + this._markedRangeElement = highlightSearchResult(element, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn); return; } @@ -330,30 +345,53 @@ WebInspector.TextViewer.prototype = { for (var j = 0; j < line.length;) { if (j > 1000) { // This line is too long - do not waste cycles on minified js highlighting. + plainTextStart = j; break; } var attribute = highlighterState && highlighterState.attributes[j]; - if (!attribute || !attribute.style) { + if (!attribute || !attribute.tokenType) { if (plainTextStart === -1) plainTextStart = j; j++; } else { if (plainTextStart !== -1) { - element.appendChild(document.createTextNode(line.substring(plainTextStart, j))); + this._appendTextNode(element, line.substring(plainTextStart, j)); plainTextStart = -1; } - element.appendChild(this._createSpan(line.substring(j, j + attribute.length), attribute.tokenType)); + this._appendSpan(element, line.substring(j, j + attribute.length), attribute.tokenType); j += attribute.length; } } if (plainTextStart !== -1) - element.appendChild(document.createTextNode(line.substring(plainTextStart, line.length))); + this._appendTextNode(element, line.substring(plainTextStart, line.length)); if (this._rangeToMark && this._rangeToMark.startLine === lineNumber) - this._markRange(element, line, this._rangeToMark.startColumn, this._rangeToMark.endColumn); + this._markedRangeElement = highlightSearchResult(element, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn); if (lineRow.decorationsElement) element.appendChild(lineRow.decorationsElement); }, + _releaseLinesHighlight: function(fromLine, toLine) + { + for (var i = fromLine; i < toLine; ++i) { + var lineRow = this._textModel.getAttribute(i, "line-row"); + if (!lineRow) + continue; + var element = lineRow.lastChild; + if ("spans" in element) { + var spans = element.spans; + for (var j = 0; j < spans.length; ++j) + this._cachedSpans.push(spans[j]); + delete element.spans; + } + if ("textNodes" in element) { + var textNodes = element.textNodes; + for (var j = 0; j < textNodes.length; ++j) + this._cachedTextNodes.push(textNodes[j]); + delete element.textNodes; + } + } + }, + _getSelection: function() { var selection = window.getSelection(); @@ -447,15 +485,33 @@ WebInspector.TextViewer.prototype = { return { line: lineRow.lineNumber, column: column }; }, - _createSpan: function(content, className) + _appendSpan: function(element, content, className) { - if (className === "html-resource-link" || className === "html-external-link") - return this._createLink(content, className === "html-external-link"); + if (className === "html-resource-link" || className === "html-external-link") { + element.appendChild(this._createLink(content, className === "html-external-link")); + return; + } - var span = document.createElement("span"); + var span = this._cachedSpans.pop() || document.createElement("span"); span.className = "webkit-" + className; - span.appendChild(document.createTextNode(content)); - return span; + span.textContent = content; + element.appendChild(span); + if (!("spans" in element)) + element.spans = []; + element.spans.push(span); + }, + + _appendTextNode: function(element, text) + { + var textNode = this._cachedTextNodes.pop(); + if (textNode) { + textNode.nodeValue = text; + } else + textNode = document.createTextNode(text); + element.appendChild(textNode); + if (!("textNodes" in element)) + element.textNodes = []; + element.textNodes.push(textNode); }, _createLink: function(content, isExternal) @@ -484,58 +540,19 @@ WebInspector.TextViewer.prototype = { return WebInspector.completeURL(this._url, hrefValue); }, - _markRange: function(element, lineText, startOffset, endOffset) - { - var markNode = document.createElement("span"); - markNode.className = "webkit-markup"; - markNode.textContent = lineText.substring(startOffset, endOffset); - - var markLength = endOffset - startOffset; - var boundary = element.rangeBoundaryForOffset(startOffset); - var textNode = boundary.container; - var text = textNode.textContent; - - if (boundary.offset + markLength < text.length) { - // Selection belong to a single split mode. - textNode.textContent = text.substring(boundary.offset + markLength); - textNode.parentElement.insertBefore(markNode, textNode); - var prefixNode = document.createTextNode(text.substring(0, boundary.offset)); - textNode.parentElement.insertBefore(prefixNode, markNode); - return; - } - - var parentElement = textNode.parentElement; - var anchorElement = textNode.nextSibling; - - markLength -= text.length - boundary.offset; - textNode.textContent = text.substring(0, boundary.offset); - textNode = textNode.traverseNextTextNode(element); - - while (textNode) { - var text = textNode.textContent; - if (markLength < text.length) { - textNode.textContent = text.substring(markLength); - break; - } - - markLength -= text.length; - textNode.textContent = ""; - textNode = textNode.traverseNextTextNode(element); - } - - parentElement.insertBefore(markNode, anchorElement); - }, - resize: function() { this._repaintAll(); } } -WebInspector.TextChunk = function(textModel, startLine, endLine, paintLinesCallback) +var cachedSpans = []; + +WebInspector.TextChunk = function(textViewer, startLine, endLine) { + this._textViewer = textViewer; this.element = document.createElement("tr"); - this._textModel = textModel; + this._textModel = textViewer._textModel; this.element.chunk = this; this.element.lineNumber = startLine; @@ -545,7 +562,6 @@ WebInspector.TextChunk = function(textModel, startLine, endLine, paintLinesCallb this._lineNumberElement = document.createElement("td"); this._lineNumberElement.className = "webkit-line-number"; - this._lineNumberElement.textContent = this._lineNumberText(this.startLine); this.element.appendChild(this._lineNumberElement); this._lineContentElement = document.createElement("td"); @@ -554,11 +570,14 @@ WebInspector.TextChunk = function(textModel, startLine, endLine, paintLinesCallb this._expanded = false; + var lineNumbers = []; var lines = []; - for (var i = this.startLine; i < this.startLine + this.linesCount; ++i) + for (var i = startLine; i < endLine; ++i) { + lineNumbers.push(i + 1); lines.push(this._textModel.line(i)); + } + this._lineNumberElement.textContent = lineNumbers.join("\n"); this._lineContentElement.textContent = lines.join("\n"); - this._paintLines = paintLinesCallback; } WebInspector.TextChunk.prototype = { @@ -601,40 +620,30 @@ WebInspector.TextChunk.prototype = { if (this.linesCount === 1) { this._textModel.setAttribute(this.startLine, "line-row", this.element); if (expanded) - this._paintLines(this.startLine, this.startLine + 1); + this._textViewer._paintLines(this.startLine, this.startLine + 1); return; } if (expanded) { var parentElement = this.element.parentElement; for (var i = this.startLine; i < this.startLine + this.linesCount; ++i) { - var lineRow = document.createElement("tr"); - lineRow.lineNumber = i; - - var lineNumberElement = document.createElement("td"); - lineNumberElement.className = "webkit-line-number"; - lineNumberElement.textContent = this._lineNumberText(i); - lineRow.appendChild(lineNumberElement); - - var lineContentElement = document.createElement("td"); - lineContentElement.className = "webkit-line-content"; - lineContentElement.textContent = this._textModel.line(i); - lineRow.appendChild(lineContentElement); - + var lineRow = this._createRow(i); this._textModel.setAttribute(i, "line-row", lineRow); parentElement.insertBefore(lineRow, this.element); } parentElement.removeChild(this.element); - this._paintLines(this.startLine, this.startLine + this.linesCount); + this._textViewer._paintLines(this.startLine, this.startLine + this.linesCount); } else { var firstLine = this._textModel.getAttribute(this.startLine, "line-row"); var parentElement = firstLine.parentElement; + this._textViewer._releaseLinesHighlight(this.startLine, this.startLine + this.linesCount); parentElement.insertBefore(this.element, firstLine); for (var i = this.startLine; i < this.startLine + this.linesCount; ++i) { var lineRow = this._textModel.getAttribute(i, "line-row"); this._textModel.removeAttribute(i, "line-row"); + this._textViewer._cachedRows.push(lineRow); parentElement.removeChild(lineRow); } } @@ -652,15 +661,28 @@ WebInspector.TextChunk.prototype = { return result; }, - _lineNumberText: function(lineNumber) + _createRow: function(lineNumber) { - var totalDigits = Math.ceil(Math.log(this._textModel.linesCount + 1) / Math.log(10)); - var digits = Math.ceil(Math.log(lineNumber + 2) / Math.log(10)); + var cachedRows = this._textViewer._cachedRows; + if (cachedRows.length) { + var lineRow = cachedRows[cachedRows.length - 1]; + cachedRows.length--; + var lineNumberElement = lineRow.firstChild; + var lineContentElement = lineRow.lastChild; + } else { + var lineRow = document.createElement("tr"); - var text = ""; - for (var i = digits; i < totalDigits; ++i) - text += " "; - text += lineNumber + 1; - return text; + var lineNumberElement = document.createElement("td"); + lineNumberElement.className = "webkit-line-number"; + lineRow.appendChild(lineNumberElement); + + var lineContentElement = document.createElement("td"); + lineContentElement.className = "webkit-line-content"; + lineRow.appendChild(lineContentElement); + } + lineRow.lineNumber = lineNumber; + lineNumberElement.textContent = lineNumber + 1; + lineContentElement.textContent = this._textModel.line(lineNumber); + return lineRow; } } diff --git a/WebCore/inspector/front-end/WebKit.qrc b/WebCore/inspector/front-end/WebKit.qrc index efa2bfc..73309d1 100644 --- a/WebCore/inspector/front-end/WebKit.qrc +++ b/WebCore/inspector/front-end/WebKit.qrc @@ -45,7 +45,7 @@ <file>Panel.js</file> <file>PanelEnablerView.js</file> <file>Placard.js</file> - <file>Popup.js</file> + <file>Popover.js</file> <file>ProfileDataGridTree.js</file> <file>ProfilesPanel.js</file> <file>ProfileView.js</file> @@ -91,6 +91,7 @@ <file>audits.css</file> <file>inspector.css</file> <file>inspectorSyntaxHighlight.css</file> + <file>popover.css</file> <file>textViewer.css</file> <file>Images/back.png</file> <file>Images/checker.png</file> @@ -125,6 +126,7 @@ <file>Images/excludeButtonGlyph.png</file> <file>Images/focusButtonGlyph.png</file> <file>Images/forward.png</file> + <file>Images/gearButtonGlyph.png</file> <file>Images/glossyHeader.png</file> <file>Images/glossyHeaderPressed.png</file> <file>Images/glossyHeaderSelected.png</file> @@ -142,6 +144,8 @@ <file>Images/paneSettingsButtons.png</file> <file>Images/pauseOnExceptionButtonGlyph.png</file> <file>Images/percentButtonGlyph.png</file> + <file>Images/popoverArrows.png</file> + <file>Images/popoverBackground.png</file> <file>Images/profileGroupIcon.png</file> <file>Images/profileIcon.png</file> <file>Images/profilesIcon.png</file> @@ -185,6 +189,12 @@ <file>Images/statusbarResizerVertical.png</file> <file>Images/storageIcon.png</file> <file>Images/successGreenDot.png</file> + <file>Images/thumbActiveHoriz.png</file> + <file>Images/thumbActiveVert.png</file> + <file>Images/thumbHoriz.png</file> + <file>Images/thumbVert.png</file> + <file>Images/thumbHoverHoriz.png</file> + <file>Images/thumbHoverVert.png</file> <file>Images/timelineBarBlue.png</file> <file>Images/timelineBarGray.png</file> <file>Images/timelineBarGreen.png</file> @@ -210,6 +220,8 @@ <file>Images/timelinePillRed.png</file> <file>Images/timelinePillYellow.png</file> <file>Images/toolbarItemSelected.png</file> + <file>Images/trackHoriz.png</file> + <file>Images/trackVert.png</file> <file>Images/treeDownTriangleBlack.png</file> <file>Images/treeDownTriangleWhite.png</file> <file>Images/treeRightTriangleBlack.png</file> diff --git a/WebCore/inspector/front-end/inspector.css b/WebCore/inspector/front-end/inspector.css index 53f1e4b..76b31fc 100644 --- a/WebCore/inspector/front-end/inspector.css +++ b/WebCore/inspector/front-end/inspector.css @@ -29,8 +29,11 @@ body { cursor: default; - height: 100%; - width: 100%; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; overflow: hidden; font-family: Lucida Grande, sans-serif; font-size: 10px; @@ -1348,7 +1351,6 @@ body.inactive .placard.selected { margin: 0; padding: 2px 6px 3px; list-style: none; - background-color: white; min-height: 18px; } @@ -1577,6 +1579,10 @@ li.editing .swatch, li.editing .enabled-button, li.editing-sub-part .delete-but color: rgb(100, 100, 100); } +.section .properties .value.error { + color: red; +} + .section .properties .number, .event-properties .number { color: blue; } @@ -2245,7 +2251,7 @@ body.inactive .data-grid th.sort-ascending, body.inactive .data-grid th.sort-des margin: 0 0 5px 20px; } -.panel-enabler-view button:not(.status-bar-item), .pane button { +.panel-enabler-view button:not(.status-bar-item), .pane button, button.show-all-nodes { color: rgb(6, 6, 6); background-color: transparent; border: 1px solid rgb(165, 165, 165); @@ -2262,6 +2268,13 @@ body.inactive .data-grid th.sort-ascending, body.inactive .data-grid th.sort-des height: 24px; } +button.show-all-nodes { + font-size: 13px; + margin: 0; + padding: 0 20px; + height: 20px; +} + .panel-enabler-view.welcome { z-index: auto; } @@ -2293,12 +2306,12 @@ body.inactive .data-grid th.sort-ascending, body.inactive .data-grid th.sort-des padding: 2px 9px; } -.panel-enabler-view button:active:not(.status-bar-item), .pane button:active { +.panel-enabler-view button:active:not(.status-bar-item), .pane button:active, button.show-all-nodes:active { background-color: rgb(215, 215, 215); background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(194, 194, 194)), to(rgb(239, 239, 239))); } -body.inactive .panel-enabler-view button:not(.status-bar-item), .panel-enabler-view button:disabled:not(.status-bar-item), body.inactive .pane button, .pane button:disabled { +body.inactive .panel-enabler-view button:not(.status-bar-item), .panel-enabler-view button:disabled:not(.status-bar-item), body.inactive .pane button, .pane button:disabled, body.inactive button.show-all-nodes { color: rgb(130, 130, 130); border-color: rgb(212, 212, 212); background-color: rgb(239, 239, 239); @@ -3801,3 +3814,21 @@ ol.breakpoint-list { outline: none !important; -webkit-user-modify: read-write; } + +.source-frame-popover-title { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + font-weight: bold; + padding-left: 18px; +} + +.source-frame-popover-tree { + border-top: 1px solid rgb(190, 190, 190); + overflow: auto; + position: absolute; + top: 15px; + bottom: 0; + left: 0; + right: 0; +} diff --git a/WebCore/inspector/front-end/inspector.html b/WebCore/inspector/front-end/inspector.html index 4ddd10e..85633b5 100644 --- a/WebCore/inspector/front-end/inspector.html +++ b/WebCore/inspector/front-end/inspector.html @@ -30,9 +30,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <link rel="stylesheet" type="text/css" href="audits.css"> - <link rel="stylesheet" type="text/css" href="textViewer.css"> <link rel="stylesheet" type="text/css" href="inspector.css"> <link rel="stylesheet" type="text/css" href="inspectorSyntaxHighlight.css"> + <link rel="stylesheet" type="text/css" href="popover.css"> + <link rel="stylesheet" type="text/css" href="textViewer.css"> <script type="text/javascript" src="utilities.js"></script> <script type="text/javascript" src="treeoutline.js"></script> <script type="text/javascript" src="inspector.js"></script> @@ -43,7 +44,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="ContextMenu.js"></script> <script type="text/javascript" src="KeyboardShortcut.js"></script> <script type="text/javascript" src="TextPrompt.js"></script> - <script type="text/javascript" src="Popup.js"></script> + <script type="text/javascript" src="Popover.js"></script> <script type="text/javascript" src="Placard.js"></script> <script type="text/javascript" src="View.js"></script> <script type="text/javascript" src="Callback.js"></script> diff --git a/WebCore/inspector/front-end/inspector.js b/WebCore/inspector/front-end/inspector.js index 77d3f42..8bcdf63 100644 --- a/WebCore/inspector/front-end/inspector.js +++ b/WebCore/inspector/front-end/inspector.js @@ -686,9 +686,7 @@ WebInspector.documentKeyDown = function(event) var isFindKey = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey; if (isFindKey) { - var searchField = document.getElementById("search"); - searchField.focus(); - searchField.select(); + WebInspector.focusSearchField(); event.preventDefault(); } @@ -878,6 +876,13 @@ WebInspector.updateSearchLabel = function() } } +WebInspector.focusSearchField = function() +{ + var searchField = document.getElementById("search"); + searchField.focus(); + searchField.select(); +} + WebInspector.toggleAttach = function() { this.attached = !this.attached; @@ -1337,7 +1342,7 @@ WebInspector.log = function(message) WebInspector.log.repeatCount = repeatCount; // ConsoleMessage expects a proxy object - message = new WebInspector.ObjectProxy(null, null, [], 0, message, false); + message = new WebInspector.ObjectProxy(null, null, [], message, false); // post the message var msg = new WebInspector.ConsoleMessage( diff --git a/WebCore/inspector/front-end/inspectorSyntaxHighlight.css b/WebCore/inspector/front-end/inspectorSyntaxHighlight.css index 1292f00..0965a5c 100644 --- a/WebCore/inspector/front-end/inspectorSyntaxHighlight.css +++ b/WebCore/inspector/front-end/inspectorSyntaxHighlight.css @@ -26,29 +26,29 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - .webkit-css-comment { - color: rgb(0, 116, 0); - } +.webkit-css-comment { + color: rgb(0, 116, 0); +} - .webkit-css-url, .webkit-css-color, .webkit-css-string, .webkit-css-keyword { - color: rgb(7, 144, 154); +.webkit-css-url, .webkit-css-color, .webkit-css-string, .webkit-css-keyword { + color: rgb(7, 144, 154); } - .webkit-css-number { - color: rgb(50, 0, 255); - } +.webkit-css-number { + color: rgb(50, 0, 255); +} - .webkit-css-property, .webkit-css-at-rule { - color: rgb(200, 0, 0); - } +.webkit-css-property, .webkit-css-at-rule { + color: rgb(200, 0, 0); +} - .webkit-css-selector { - rgb(0, 0, 0); - } +.webkit-css-selector { + color: black; +} - .webkit-css-important { - color: rgb(200, 0, 180); - } +.webkit-css-important { + color: rgb(200, 0, 180); +} .webkit-javascript-comment { color: rgb(0, 116, 0); @@ -66,6 +66,10 @@ color: rgb(196, 26, 22); } +.webkit-javascript-ident { + color: black; +} + .webkit-html-comment { /* Keep this in sync with view-source.css (.webkit-html-comment) */ color: rgb(35, 110, 37); diff --git a/WebCore/inspector/front-end/popover.css b/WebCore/inspector/front-end/popover.css new file mode 100644 index 0000000..ae6f610 --- /dev/null +++ b/WebCore/inspector/front-end/popover.css @@ -0,0 +1,200 @@ +.popover { + position: absolute; + -webkit-border-image: url(Images/popoverBackground.png) 25 25 25 25; + border-width: 25px; + z-index: 100; + pointer-events: none; +} + +.popover .content { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + pointer-events: auto; + overflow: auto; +} + +.popover .arrow { + position: absolute; + background-image: url(Images/popoverArrows.png); + width: 19px; + height: 19px; + margin-left: 15px; + margin-top: -25px; + top: 0; + left: 0; +} + +.popover.top-left-arrow .arrow { + /* The default is top-left, no styles needed. */ +} + +.popover.top-right-arrow .arrow { + right: 25px; + left: auto; +} + +.popover.bottom-left-arrow .arrow { + top: auto; + bottom: 0; + margin-top: 0; + margin-bottom: -25px; + background-position: 0 -19px; +} + +.popover.bottom-right-arrow .arrow { + right: 15px; + left: auto; + top: auto; + bottom: 0; + margin-top: 0; + margin-bottom: -25px; + background-position: 0 -19px; +} + +.popover.left-top-arrow .arrow { + top: 0; + margin-top: 15px; + margin-left: -25px; + background-position: 0 -38px; +} + +.popover.left-bottom-arrow .arrow { + top: auto; + bottom: 0; + margin-bottom: 15px; + margin-left: -25px; + background-position: 0 -38px; +} + +.popover.right-top-arrow .arrow { + right: 0; + left: auto; + top: 0; + margin-top: 15px; + margin-right: -25px; + background-position: 0 -57px; +} + +.popover.right-bottom-arrow .arrow { + right: 0; + left: auto; + top: auto; + bottom: 0; + margin-bottom: 15px; + margin-right: -25px; + background-position: 0 -57px; +} + +.popover ::-webkit-scrollbar { + width: 11px; + height: 11px; +} + +.popover ::-webkit-scrollbar-corner { + display: none; +} + +.popover ::-webkit-resizer { + display: none; +} + +/* Horizontal Scrollbar Styles */ + +.popover ::-webkit-scrollbar:horizontal:corner-present { + border-right-width: 0; +} + +.popover ::-webkit-scrollbar-thumb:horizontal { + -webkit-border-image: url(Images/thumbHoriz.png) 0 11 0 11; + border-color: transparent; + border-width: 0 11px; + min-width: 20px; +} + +.popover ::-webkit-scrollbar-thumb:horizontal:hover { + -webkit-border-image: url(Images/thumbHoverHoriz.png) 0 11 0 11; +} + +.popover ::-webkit-scrollbar-thumb:horizontal:active { + -webkit-border-image: url(Images/thumbActiveHoriz.png) 0 11 0 11; +} + +.popover ::-webkit-scrollbar-track-piece:horizontal:start { + margin-left: 5px; +} + +.popover ::-webkit-scrollbar-track-piece:horizontal:end { + margin-right: 5px; +} + +.popover ::-webkit-scrollbar-track-piece:horizontal:end:corner-present { + margin-right: 4px; +} + +.popover ::-webkit-scrollbar-track-piece:horizontal:decrement { + -webkit-border-image: url(Images/trackHoriz.png) 0 11 0 11; + border-color: transparent; + border-width: 0 0 0 11px; +} + +.popover ::-webkit-scrollbar-track-piece:horizontal:increment { + -webkit-border-image: url(Images/trackHoriz.png) 0 11 0 11; + border-color: transparent; + border-width: 0 11px 0 0; +} + +/* Vertical Scrollbar Styles */ + + +.popover ::-webkit-scrollbar:vertical:corner-present { + border-bottom-width: 0; +} + +.popover ::-webkit-scrollbar-thumb:vertical { + -webkit-border-image: url(Images/thumbVert.png) 11 0 11 0; + border-color: transparent; + border-width: 11px 0; + min-height: 20px; +} + +.popover ::-webkit-scrollbar-thumb:vertical:hover { + -webkit-border-image: url(Images/thumbHoverVert.png) 11 0 11 0; +} + +.popover ::-webkit-scrollbar-thumb:vertical:active { + -webkit-border-image: url(Images/thumbActiveVert.png) 11 0 11 0; +} + + +.popover ::-webkit-scrollbar-track-piece:vertical:start { + margin-top: 5px; +} + +.popover ::-webkit-scrollbar-track-piece:vertical:end { + margin-bottom: 5px; +} + +.popover ::-webkit-scrollbar-track-piece:vertical:end:corner-present { + margin-bottom: 4px; +} + +.popover ::-webkit-scrollbar-track-piece:vertical:decrement { + -webkit-border-image: url(Images/trackVert.png) 11 0 11 0; + border-color: transparent; + border-width: 11px 0 0 0; +} + +.popover ::-webkit-scrollbar-track-piece:vertical:increment { + -webkit-border-image: url(Images/trackVert.png) 11 0 11 0; + border-color: transparent; + border-width: 0 0 11px 0; +} + +/* Forced Scrollbar Mode Styles */ + +.popover ::-webkit-scrollbar-button { + display: none; +} diff --git a/WebCore/inspector/front-end/textViewer.css b/WebCore/inspector/front-end/textViewer.css index af079bc..1447dfd 100644 --- a/WebCore/inspector/front-end/textViewer.css +++ b/WebCore/inspector/front-end/textViewer.css @@ -4,14 +4,13 @@ left:0; right:0; bottom:0; - white-space: pre-wrap; + white-space: pre; overflow: auto; } .text-editor-lines { border: 0; width: 100%; - vertical-align: baseline; -webkit-border-horizontal-spacing: 0; -webkit-border-vertical-spacing: 0; -webkit-user-select: text; @@ -63,21 +62,20 @@ .webkit-line-number { color: rgb(128, 128, 128); text-align: right; - white-space: pre; word-break: normal; -webkit-user-select: none; background-color: rgb(240, 240, 240); border-right: 1px solid rgb(187, 187, 187) !important; padding-left: 2px; padding-right: 2px; - vertical-align: top; background-repeat: no-repeat; background-position: right 1px; + vertical-align: top; } .webkit-line-content { - white-space: pre-wrap; padding-left: 2px; + vertical-align: top; } .webkit-execution-line .webkit-line-number { @@ -130,13 +128,14 @@ outline: 1px solid rgb(64, 115, 244); } -.webkit-markup { +.webkit-search-result { -webkit-border-radius: 4px; - padding: 2px 1px 2px 3px; - margin-left: -4px; - margin-top: -2px; + padding: 2px 2px 2px 3px; + margin: -2px -2px -2px -3px; + opacity: 0.8; -webkit-box-shadow: rgba(0, 0, 0, .5) 3px 3px 4px; background-color: rgb(241, 234, 0); + color: black; } .webkit-highlighted-line .webkit-line-content { diff --git a/WebCore/inspector/front-end/utilities.js b/WebCore/inspector/front-end/utilities.js index 60d3b45..f30ab9f 100644 --- a/WebCore/inspector/front-end/utilities.js +++ b/WebCore/inspector/front-end/utilities.js @@ -271,7 +271,7 @@ Element.prototype.__defineGetter__("totalOffsetLeft", function() { var total = 0; for (var element = this; element; element = element.offsetParent) - total += element.offsetLeft; + total += element.offsetLeft + (this !== element ? element.clientLeft : 0); return total; }); @@ -279,7 +279,7 @@ Element.prototype.__defineGetter__("totalOffsetTop", function() { var total = 0; for (var element = this; element; element = element.offsetParent) - total += element.offsetTop; + total += element.offsetTop + (this !== element ? element.clientTop : 0); return total; }); @@ -850,3 +850,60 @@ function isEnterKey(event) { // Check if in IME. return event.keyCode !== 229 && event.keyIdentifier === "Enter"; } + + +function highlightSearchResult(element, offset, length) +{ + var lineText = element.textContent; + var endOffset = offset + length; + var highlightNode = document.createElement("span"); + highlightNode.className = "webkit-search-result"; + highlightNode.textContent = lineText.substring(offset, endOffset); + + var boundary = element.rangeBoundaryForOffset(offset); + var textNode = boundary.container; + var text = textNode.textContent; + + if (boundary.offset + length < text.length) { + // Selection belong to a single split mode. + textNode.textContent = text.substring(boundary.offset + length); + textNode.parentElement.insertBefore(highlightNode, textNode); + var prefixNode = document.createTextNode(text.substring(0, boundary.offset)); + textNode.parentElement.insertBefore(prefixNode, highlightNode); + return highlightNode; + } + + var parentElement = textNode.parentElement; + var anchorElement = textNode.nextSibling; + + length -= text.length - boundary.offset; + textNode.textContent = text.substring(0, boundary.offset); + textNode = textNode.traverseNextTextNode(element); + + while (textNode) { + var text = textNode.textContent; + if (length < text.length) { + textNode.textContent = text.substring(length); + break; + } + + length -= text.length; + textNode.textContent = ""; + textNode = textNode.traverseNextTextNode(element); + } + + parentElement.insertBefore(highlightNode, anchorElement); + return highlightNode; +} + +function createSearchRegex(query) +{ + var regex = ""; + for (var i = 0; i < query.length; ++i) { + var char = query.charAt(i); + if (char === "]") + char = "\\]"; + regex += "[" + char + "]"; + } + return new RegExp(regex, "i"); +} diff --git a/WebCore/loader/EmptyClients.h b/WebCore/loader/EmptyClients.h index 5b24bd3..6004b55 100644 --- a/WebCore/loader/EmptyClients.h +++ b/WebCore/loader/EmptyClients.h @@ -150,6 +150,7 @@ public: #endif virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>) { } + virtual void iconForFiles(const Vector<String>&, PassRefPtr<FileChooser>) { } virtual void formStateDidChange(const Node*) { } @@ -301,6 +302,7 @@ public: virtual void didDisplayInsecureContent() { } virtual void didRunInsecureContent(SecurityOrigin*) { } virtual PassRefPtr<Frame> createFrame(const KURL&, const String&, HTMLFrameOwnerElement*, const String&, bool, int, int) { return 0; } + virtual void didTransferChildFrameToNewDocument() { } virtual PassRefPtr<Widget> createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool) { return 0; } virtual PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL&, const Vector<String>&, const Vector<String>&) { return 0; } diff --git a/WebCore/loader/FrameLoader.cpp b/WebCore/loader/FrameLoader.cpp index 514f98a..d28dc50 100644 --- a/WebCore/loader/FrameLoader.cpp +++ b/WebCore/loader/FrameLoader.cpp @@ -480,7 +480,9 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F #endif String targetOrBaseTarget = target.isEmpty() ? m_frame->document()->baseTarget() : target; - Frame* targetFrame = findFrameForNavigation(targetOrBaseTarget); + Frame* targetFrame = m_frame->tree()->find(targetOrBaseTarget); + if (!shouldAllowNavigation(targetFrame)) + return; if (!targetFrame) { targetFrame = m_frame; frameRequest.setFrameName(targetOrBaseTarget); diff --git a/WebCore/loader/FrameLoaderClient.h b/WebCore/loader/FrameLoaderClient.h index 2668958..4f78805 100644 --- a/WebCore/loader/FrameLoaderClient.h +++ b/WebCore/loader/FrameLoaderClient.h @@ -219,6 +219,7 @@ namespace WebCore { virtual PassRefPtr<Frame> createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) = 0; + virtual void didTransferChildFrameToNewDocument() = 0; virtual PassRefPtr<Widget> createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool loadManually) = 0; virtual void redirectDataToPlugin(Widget* pluginWidget) = 0; diff --git a/WebCore/loader/HistoryController.cpp b/WebCore/loader/HistoryController.cpp index 43c9979..55b68dc 100644 --- a/WebCore/loader/HistoryController.cpp +++ b/WebCore/loader/HistoryController.cpp @@ -109,6 +109,10 @@ void HistoryController::updateBackForwardListForFragmentScroll() // Since the document isn't changed as a result of a fragment scroll, we should // preserve the DocumentSequenceNumber of the previous item. + if (!m_previousItem) + return; + + ASSERT(m_currentItem); m_currentItem->setDocumentSequenceNumber(m_previousItem->documentSequenceNumber()); } diff --git a/WebCore/loader/ImageLoader.cpp b/WebCore/loader/ImageLoader.cpp index c61d133..929b28a 100644 --- a/WebCore/loader/ImageLoader.cpp +++ b/WebCore/loader/ImageLoader.cpp @@ -230,7 +230,7 @@ void ImageLoader::updateRenderer() // is a complete image. This prevents flickering in the case where a dynamic // change is happening between two images. CachedImage* cachedImage = imageRenderer->cachedImage(); - if (m_image != cachedImage && (m_imageComplete || !imageRenderer->cachedImage())) + if (m_image != cachedImage && (m_imageComplete || !cachedImage)) imageRenderer->setCachedImage(m_image.get()); } } diff --git a/WebCore/loader/ProgressTracker.cpp b/WebCore/loader/ProgressTracker.cpp index 0c9f2fb..458de68 100644 --- a/WebCore/loader/ProgressTracker.cpp +++ b/WebCore/loader/ProgressTracker.cpp @@ -26,10 +26,12 @@ #include "config.h" #include "ProgressTracker.h" +#include "CString.h" #include "DocumentLoader.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameLoaderClient.h" +#include "Logging.h" #include "ResourceResponse.h" #include <wtf/CurrentTime.h> @@ -97,7 +99,7 @@ void ProgressTracker::reset() void ProgressTracker::progressStarted(Frame* frame) { - // LOG (Progress, "frame %p(%@), _private->numProgressTrackedFrames %d, _private->originatingProgressFrame %p", frame, [frame name], _private->numProgressTrackedFrames, _private->originatingProgressFrame); + LOG(Progress, "Progress started (%p) - frame %p(\"%s\"), value %f, tracked frames %d, originating frame %p", this, frame, frame->tree()->name().string().utf8().data(), m_progressValue, m_numProgressTrackedFrames, m_originatingProgressFrame.get()); frame->loader()->client()->willChangeEstimatedProgress(); @@ -115,7 +117,7 @@ void ProgressTracker::progressStarted(Frame* frame) void ProgressTracker::progressCompleted(Frame* frame) { - // LOG (Progress, "frame %p(%@), _private->numProgressTrackedFrames %d, _private->originatingProgressFrame %p", frame, [frame name], _private->numProgressTrackedFrames, _private->originatingProgressFrame); + LOG(Progress, "Progress completed (%p) - frame %p(\"%s\"), value %f, tracked frames %d, originating frame %p", this, frame, frame->tree()->name().string().utf8().data(), m_progressValue, m_numProgressTrackedFrames, m_originatingProgressFrame.get()); if (m_numProgressTrackedFrames <= 0) return; @@ -132,7 +134,7 @@ void ProgressTracker::progressCompleted(Frame* frame) void ProgressTracker::finalProgressComplete() { - // LOG (Progress, ""); + LOG(Progress, "Final progress complete (%p)", this); RefPtr<Frame> frame = m_originatingProgressFrame.release(); @@ -151,7 +153,7 @@ void ProgressTracker::finalProgressComplete() void ProgressTracker::incrementProgress(unsigned long identifier, const ResourceResponse& response) { - // LOG (Progress, "_private->numProgressTrackedFrames %d, _private->originatingProgressFrame %p", _private->numProgressTrackedFrames, _private->originatingProgressFrame); + LOG(Progress, "Progress incremented (%p) - value %f, tracked frames %d, originating frame %p", this, m_progressValue, m_numProgressTrackedFrames, m_originatingProgressFrame.get()); if (m_numProgressTrackedFrames <= 0) return; @@ -214,7 +216,7 @@ void ProgressTracker::incrementProgress(unsigned long identifier, const char*, i double now = currentTime(); double notifiedProgressTimeDelta = now - m_lastNotifiedProgressTime; - // LOG (Progress, "_private->progressValue %g, _private->numProgressTrackedFrames %d", _private->progressValue, _private->numProgressTrackedFrames); + LOG(Progress, "Progress incremented (%p) - value %f, tracked frames %d", this, m_progressValue, m_numProgressTrackedFrames); double notificationProgressDelta = m_progressValue - m_lastNotifiedProgressValue; if ((notificationProgressDelta >= m_progressNotificationInterval || notifiedProgressTimeDelta >= m_progressNotificationTimeInterval) && diff --git a/WebCore/manual-tests/match-marker-rects.html b/WebCore/manual-tests/match-marker-rects.html new file mode 100644 index 0000000..d650965 --- /dev/null +++ b/WebCore/manual-tests/match-marker-rects.html @@ -0,0 +1,33 @@ +<style> + div { + height: 50px; + width: 110px; + margin: 10px 0; + padding: 10px; + border: solid black; + font-size: 25px; + } + + div.columns { + -webkit-columns: 2; + -webkit-column-gap: 10px; + } + + div.scroll { + overflow-y: scroll; + } +</style> +<p> + In Safari, choose Edit > Find > Find, and type the strings “xyz” + and “123”. The white “holes” in the Find overlay + should line up with the matching text below. +</p> +<div class="columns"> + <br>xyz +</div> +<div class="scroll" id="scroll"> + <br><br>123<br><br> +</div> +<script> + document.getElementById("scroll").scrollTop = 100; +</script> diff --git a/WebCore/manual-tests/media-elements/video-replaces-poster.html b/WebCore/manual-tests/media-elements/video-replaces-poster.html new file mode 100644 index 0000000..8d852aa --- /dev/null +++ b/WebCore/manual-tests/media-elements/video-replaces-poster.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> + <head> + </head> + <body> + <p>Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=34965">https://bugs.webkit.org/show_bug.cgi?id=34965</a><br> + Disable accelerated compositing and reload this test. You should see the test video + start playing.</p> + + <video width="480" height="270" type="video/mp4" + src="../../../LayoutTests/media/content/test.mp4" + poster="../../../LayoutTests/media/content/abe.png" autoplay> + </video> + </body> +</html> diff --git a/WebCore/manual-tests/video-rtsp.html b/WebCore/manual-tests/video-rtsp.html new file mode 100644 index 0000000..4fff987 --- /dev/null +++ b/WebCore/manual-tests/video-rtsp.html @@ -0,0 +1,11 @@ +<html> +<head> +<title>RTSP playback test</title> +</head> +<body> +<video with=640 height=352 autoplay controls src="rtsp://a2047.v1411b.c1411.g.vq.akamaistream.net/5/2047/1411/2_h264_650/1a1a1ae454c430950065de4cbb2f94c226950c7ae655b61a48a91475e243acda3dac194879adde0f/wwdc_2006_2_650.mov"></video> +<p>Test that QuickTime file with RTSP URL loads.<p> +<script>start()</script> +<pre id="console"></pre> +</body> +</html> diff --git a/WebCore/page/Chrome.cpp b/WebCore/page/Chrome.cpp index d3b46ad..cb7f6bf 100644 --- a/WebCore/page/Chrome.cpp +++ b/WebCore/page/Chrome.cpp @@ -427,6 +427,11 @@ void Chrome::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> fileChooser) m_client->runOpenPanel(frame, fileChooser); } +void Chrome::iconForFiles(const Vector<String>& filenames, PassRefPtr<FileChooser> fileChooser) +{ + m_client->iconForFiles(filenames, fileChooser); +} + bool Chrome::setCursor(PlatformCursorHandle cursor) { return m_client->setCursor(cursor); diff --git a/WebCore/page/Chrome.h b/WebCore/page/Chrome.h index 3039b90..9227f87 100644 --- a/WebCore/page/Chrome.h +++ b/WebCore/page/Chrome.h @@ -136,6 +136,7 @@ namespace WebCore { void cancelGeolocationPermissionRequestForFrame(Frame*); void runOpenPanel(Frame*, PassRefPtr<FileChooser>); + void iconForFiles(const Vector<String>&, PassRefPtr<FileChooser>); bool setCursor(PlatformCursorHandle); diff --git a/WebCore/page/ChromeClient.h b/WebCore/page/ChromeClient.h index 1615f3a..1b8b734 100644 --- a/WebCore/page/ChromeClient.h +++ b/WebCore/page/ChromeClient.h @@ -190,6 +190,9 @@ namespace WebCore { virtual void cancelGeolocationPermissionRequestForFrame(Frame*) = 0; virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>) = 0; + // Asynchronous request to load an icon for specified filenames. + // This is called only if Icon::createIconForFiles() returns 0. + virtual void iconForFiles(const Vector<String>&, PassRefPtr<FileChooser>) = 0; virtual bool setCursor(PlatformCursorHandle) = 0; diff --git a/WebCore/page/DOMTimer.cpp b/WebCore/page/DOMTimer.cpp index 8971bb7..72dc9ac 100644 --- a/WebCore/page/DOMTimer.cpp +++ b/WebCore/page/DOMTimer.cpp @@ -43,7 +43,7 @@ double DOMTimer::s_minTimerInterval = 0.010; // 10 milliseconds static int timerNestingLevel = 0; -DOMTimer::DOMTimer(ScriptExecutionContext* context, ScheduledAction* action, int timeout, bool singleShot) +DOMTimer::DOMTimer(ScriptExecutionContext* context, PassOwnPtr<ScheduledAction> action, int timeout, bool singleShot) : ActiveDOMObject(context, this) , m_action(action) , m_nextFireInterval(0) @@ -82,7 +82,7 @@ DOMTimer::~DOMTimer() scriptExecutionContext()->removeTimeout(m_timeoutId); } -int DOMTimer::install(ScriptExecutionContext* context, ScheduledAction* action, int timeout, bool singleShot) +int DOMTimer::install(ScriptExecutionContext* context, PassOwnPtr<ScheduledAction> action, int timeout, bool singleShot) { // DOMTimer constructor links the new timer into a list of ActiveDOMObjects held by the 'context'. // The timer is deleted when context is deleted (DOMTimer::contextDestroyed) or explicitly via DOMTimer::removeById(), diff --git a/WebCore/page/DOMTimer.h b/WebCore/page/DOMTimer.h index 460430f..da38178 100644 --- a/WebCore/page/DOMTimer.h +++ b/WebCore/page/DOMTimer.h @@ -28,20 +28,21 @@ #define DOMTimer_h #include "ActiveDOMObject.h" +#include "ScheduledAction.h" #include "Timer.h" #include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> namespace WebCore { class InspectorTimelineAgent; - class ScheduledAction; class DOMTimer : public TimerBase, public ActiveDOMObject { public: virtual ~DOMTimer(); // Creates a new timer owned by specified ScriptExecutionContext, starts it // and returns its Id. - static int install(ScriptExecutionContext*, ScheduledAction*, int timeout, bool singleShot); + static int install(ScriptExecutionContext*, PassOwnPtr<ScheduledAction>, int timeout, bool singleShot); static void removeById(ScriptExecutionContext*, int timeoutId); // ActiveDOMObject @@ -59,7 +60,7 @@ namespace WebCore { static void setMinTimerInterval(double value) { s_minTimerInterval = value; } private: - DOMTimer(ScriptExecutionContext*, ScheduledAction*, int timeout, bool singleShot); + DOMTimer(ScriptExecutionContext*, PassOwnPtr<ScheduledAction>, int timeout, bool singleShot); virtual void fired(); int m_timeoutId; diff --git a/WebCore/page/DOMWindow.cpp b/WebCore/page/DOMWindow.cpp index 2f0f84f..6af22c3 100644 --- a/WebCore/page/DOMWindow.cpp +++ b/WebCore/page/DOMWindow.cpp @@ -1252,7 +1252,7 @@ void DOMWindow::resizeTo(float width, float height) const page->chrome()->setWindowRect(fr); } -int DOMWindow::setTimeout(ScheduledAction* action, int timeout, ExceptionCode& ec) +int DOMWindow::setTimeout(PassOwnPtr<ScheduledAction> action, int timeout, ExceptionCode& ec) { ScriptExecutionContext* context = scriptExecutionContext(); if (!context) { @@ -1270,7 +1270,7 @@ void DOMWindow::clearTimeout(int timeoutId) DOMTimer::removeById(context, timeoutId); } -int DOMWindow::setInterval(ScheduledAction* action, int timeout, ExceptionCode& ec) +int DOMWindow::setInterval(PassOwnPtr<ScheduledAction> action, int timeout, ExceptionCode& ec) { ScriptExecutionContext* context = scriptExecutionContext(); if (!context) { diff --git a/WebCore/page/DOMWindow.h b/WebCore/page/DOMWindow.h index dc1e68c..4452dbb 100644 --- a/WebCore/page/DOMWindow.h +++ b/WebCore/page/DOMWindow.h @@ -237,9 +237,9 @@ namespace WebCore { void resizeTo(float width, float height) const; // Timers - int setTimeout(ScheduledAction*, int timeout, ExceptionCode&); + int setTimeout(PassOwnPtr<ScheduledAction>, int timeout, ExceptionCode&); void clearTimeout(int timeoutId); - int setInterval(ScheduledAction*, int timeout, ExceptionCode&); + int setInterval(PassOwnPtr<ScheduledAction>, int timeout, ExceptionCode&); void clearInterval(int timeoutId); // Events diff --git a/WebCore/page/DragController.cpp b/WebCore/page/DragController.cpp index c9769df..18e3195 100644 --- a/WebCore/page/DragController.cpp +++ b/WebCore/page/DragController.cpp @@ -556,14 +556,9 @@ static CachedImage* getCachedImage(Element* element) static Image* getImage(Element* element) { ASSERT(element); - RenderObject* renderer = element->renderer(); - if (!renderer || !renderer->isImage()) - return 0; - - RenderImage* image = toRenderImage(renderer); - if (image->cachedImage() && !image->cachedImage()->errorOccurred()) - return image->cachedImage()->image(); - return 0; + CachedImage* cachedImage = getCachedImage(element); + return (cachedImage && !cachedImage->errorOccurred()) ? + cachedImage->image() : 0; } static void prepareClipboardForImageDrag(Frame* src, Clipboard* clipboard, Element* node, const KURL& linkURL, const KURL& imageURL, const String& label) diff --git a/WebCore/page/Frame.cpp b/WebCore/page/Frame.cpp index 947cb06..87c9733 100644 --- a/WebCore/page/Frame.cpp +++ b/WebCore/page/Frame.cpp @@ -674,10 +674,6 @@ bool Frame::shouldApplyTextZoom() const { if (m_zoomFactor == 1.0f || !isZoomFactorTextOnly()) return false; -#if ENABLE(SVG) - if (m_doc->isSVGDocument()) - return false; -#endif return true; } @@ -685,10 +681,6 @@ bool Frame::shouldApplyPageZoom() const { if (m_zoomFactor == 1.0f || isZoomFactorTextOnly()) return false; -#if ENABLE(SVG) - if (m_doc->isSVGDocument()) - return false; -#endif return true; } @@ -698,16 +690,13 @@ void Frame::setZoomFactor(float percent, bool isTextOnly) return; #if ENABLE(SVG) - // SVG doesn't care if the zoom factor is text only. It will always apply a - // zoom to the whole SVG. + // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents. + // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification. if (m_doc->isSVGDocument()) { if (!static_cast<SVGDocument*>(m_doc.get())->zoomAndPanEnabled()) return; - m_zoomFactor = percent; - m_page->settings()->setZoomsTextOnly(true); // We do this to avoid doing any scaling of CSS pixels, since the SVG has its own notion of zoom. if (m_doc->renderer()) - m_doc->renderer()->repaint(); - return; + m_doc->renderer()->setNeedsLayout(true); } #endif @@ -1631,6 +1620,54 @@ void Frame::disconnectOwnerElement() m_ownerElement = 0; } +// The frame is moved in DOM, potentially to another page. +void Frame::transferChildFrameToNewDocument() +{ + ASSERT(m_ownerElement); + Frame* newParent = m_ownerElement->document()->frame(); + bool didTransfer = false; + + // Switch page. + Page* newPage = newParent ? newParent->page() : 0; + if (m_page != newPage) { + if (page()->focusController()->focusedFrame() == this) + page()->focusController()->setFocusedFrame(0); + + if (m_page) + m_page->decrementFrameCount(); + + m_page = newPage; + + if (newPage) + newPage->incrementFrameCount(); + + didTransfer = true; + } + + // Update the frame tree. + Frame* oldParent = tree()->parent(); + if (oldParent != newParent) { + if (oldParent) + oldParent->tree()->removeChild(this); + if (newParent) { + newParent->tree()->appendChild(this); + m_ownerElement->setName(); + } + didTransfer = true; + } + + // Avoid unnecessary calls to client and frame subtree if the frame ended + // up on the same page and under the same parent frame. + if (didTransfer) { + // Let external clients update themselves. + loader()->client()->didTransferChildFrameToNewDocument(); + + // Do the same for all the children. + for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling()) + child->transferChildFrameToNewDocument(); + } +} + String Frame::documentTypeString() const { if (DocumentType* doctype = document()->doctype()) diff --git a/WebCore/page/Frame.h b/WebCore/page/Frame.h index 33bb435..26d1efa 100644 --- a/WebCore/page/Frame.h +++ b/WebCore/page/Frame.h @@ -76,6 +76,8 @@ namespace WebCore { Page* page() const; void detachFromPage(); + void transferChildFrameToNewDocument(); + HTMLFrameOwnerElement* ownerElement() const; void pageDestroyed(); diff --git a/WebCore/page/FrameView.cpp b/WebCore/page/FrameView.cpp index fb078a9..356ada2 100644 --- a/WebCore/page/FrameView.cpp +++ b/WebCore/page/FrameView.cpp @@ -496,6 +496,19 @@ bool FrameView::syncCompositingStateRecursive() #endif } +bool FrameView::isSoftwareRenderable() const +{ +#if USE(ACCELERATED_COMPOSITING) + RenderView* view = m_frame->contentRenderer(); + if (!view) + return true; + + return !view->compositor()->has3DContent(); +#else + return true; +#endif +} + void FrameView::didMoveOnscreen() { RenderView* view = m_frame->contentRenderer(); @@ -1795,7 +1808,12 @@ void FrameView::setPaintBehavior(PaintBehavior behavior) { m_paintBehavior = behavior; } - + +PaintBehavior FrameView::paintBehavior() const +{ + return m_paintBehavior; +} + bool FrameView::isPainting() const { return m_isPainting; diff --git a/WebCore/page/FrameView.h b/WebCore/page/FrameView.h index b27ffd8..1d5a312 100644 --- a/WebCore/page/FrameView.h +++ b/WebCore/page/FrameView.h @@ -106,6 +106,10 @@ public: // Returns true if the sync was completed. bool syncCompositingStateRecursive(); + // Returns true when a paint with the PaintBehaviorFlattenCompositingLayers flag set gives + // a faithful representation of the content. + bool isSoftwareRenderable() const; + void didMoveOnscreen(); void willMoveOffscreen(); @@ -170,7 +174,7 @@ public: virtual void paintContents(GraphicsContext*, const IntRect& damageRect); void setPaintBehavior(PaintBehavior); - PaintBehavior paintBehavior() const { return m_paintBehavior; } + PaintBehavior paintBehavior() const; bool isPainting() const; void setNodeToDraw(Node*); diff --git a/WebCore/page/Geolocation.h b/WebCore/page/Geolocation.h index b30deac..358e4a3 100644 --- a/WebCore/page/Geolocation.h +++ b/WebCore/page/Geolocation.h @@ -85,10 +85,13 @@ public: void setShouldClearCache(bool shouldClearCache) { m_shouldClearCache = shouldClearCache; } bool shouldClearCache() const { return m_shouldClearCache; } + Frame* frame() const { return m_frame; } #if ENABLE(CLIENT_BASED_GEOLOCATION) void setPosition(GeolocationPosition*); void setError(GeolocationError*); +#else + GeolocationService* getGeolocationService() const { return m_service.get(); } #endif private: diff --git a/WebCore/page/MediaCanStartListener.h b/WebCore/page/MediaCanStartListener.h new file mode 100644 index 0000000..317babf --- /dev/null +++ b/WebCore/page/MediaCanStartListener.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MediaCanStartListener_h +#define MediaCanStartListener_h + +namespace WebCore { + +class MediaCanStartListener { +public: + virtual void mediaCanStart() = 0; +protected: + virtual ~MediaCanStartListener() { } +}; + +} + +#endif diff --git a/WebCore/page/Page.cpp b/WebCore/page/Page.cpp index a3e89b5..d348d73 100644 --- a/WebCore/page/Page.cpp +++ b/WebCore/page/Page.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All Rights Reserved. * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * * This library is free software; you can redistribute it and/or @@ -46,6 +46,7 @@ #include "InspectorController.h" #include "InspectorTimelineAgent.h" #include "Logging.h" +#include "MediaCanStartListener.h" #include "Navigator.h" #include "NetworkStateNotifier.h" #include "PageGroup.h" @@ -159,7 +160,7 @@ Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, Edi , m_debugger(0) , m_customHTMLTokenizerTimeDelay(-1) , m_customHTMLTokenizerChunkSize(-1) - , m_canStartPlugins(true) + , m_canStartMedia(true) { #if !ENABLE(CONTEXT_MENUS) UNUSED_PARAM(contextMenuClient); @@ -413,17 +414,37 @@ PluginData* Page::pluginData() const return m_pluginData.get(); } -void Page::addUnstartedPlugin(PluginView* view) +void Page::addMediaCanStartListener(MediaCanStartListener* listener) { - ASSERT(!m_canStartPlugins); - m_unstartedPlugins.add(view); + ASSERT(!m_canStartMedia); + ASSERT(!m_mediaCanStartListeners.contains(listener)); + m_mediaCanStartListeners.add(listener); } -void Page::removeUnstartedPlugin(PluginView* view) +void Page::removeMediaCanStartListener(MediaCanStartListener* listener) { - ASSERT(!m_canStartPlugins); - ASSERT(m_unstartedPlugins.contains(view)); - m_unstartedPlugins.remove(view); + ASSERT(!m_canStartMedia); + ASSERT(m_mediaCanStartListeners.contains(listener)); + m_mediaCanStartListeners.remove(listener); +} + +void Page::setCanStartMedia(bool canStartMedia) +{ + if (m_canStartMedia == canStartMedia) + return; + + m_canStartMedia = canStartMedia; + + if (!m_canStartMedia || m_mediaCanStartListeners.isEmpty()) + return; + + Vector<MediaCanStartListener*> listeners; + copyToVector(m_mediaCanStartListeners, listeners); + m_mediaCanStartListeners.clear(); + + size_t size = listeners.size(); + for (size_t i = 0; i < size; ++i) + listeners[i]->mediaCanStart(); } static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag) diff --git a/WebCore/page/Page.h b/WebCore/page/Page.h index 1417c87..04a545c 100644 --- a/WebCore/page/Page.h +++ b/WebCore/page/Page.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * * This library is free software; you can redistribute it and/or @@ -59,26 +59,27 @@ namespace WebCore { class InspectorClient; class InspectorController; class InspectorTimelineAgent; + class MediaCanStartListener; class Node; class PageGroup; class PluginData; class PluginHalter; class PluginHalterClient; - class PluginView; class ProgressTracker; class RenderTheme; class VisibleSelection; class SelectionController; class Settings; + #if ENABLE(DOM_STORAGE) class StorageNamespace; #endif -#if ENABLE(WML) - class WMLPageState; -#endif #if ENABLE(NOTIFICATIONS) class NotificationPresenter; #endif +#if ENABLE(WML) + class WMLPageState; +#endif typedef uint64_t LinkHash; @@ -96,10 +97,10 @@ namespace WebCore { static void refreshPlugins(bool reload); PluginData* pluginData() const; - void setCanStartPlugins(bool); - bool canStartPlugins() const { return m_canStartPlugins; } - void addUnstartedPlugin(PluginView*); - void removeUnstartedPlugin(PluginView*); + void setCanStartMedia(bool); + bool canStartMedia() const { return m_canStartMedia; } + void addMediaCanStartListener(MediaCanStartListener*); + void removeMediaCanStartListener(MediaCanStartListener*); EditorClient* editorClient() const { return m_editorClient; } @@ -310,8 +311,8 @@ namespace WebCore { double m_customHTMLTokenizerTimeDelay; int m_customHTMLTokenizerChunkSize; - bool m_canStartPlugins; - HashSet<PluginView*> m_unstartedPlugins; + bool m_canStartMedia; + HashSet<MediaCanStartListener*> m_mediaCanStartListeners; OwnPtr<PluginHalter> m_pluginHalter; diff --git a/WebCore/page/SecurityOrigin.cpp b/WebCore/page/SecurityOrigin.cpp index af63637..fe6efbd 100644 --- a/WebCore/page/SecurityOrigin.cpp +++ b/WebCore/page/SecurityOrigin.cpp @@ -286,6 +286,11 @@ void SecurityOrigin::grantUniversalAccess() m_universalAccess = true; } +void SecurityOrigin::makeUnique() +{ + m_isUnique = true; +} + bool SecurityOrigin::isLocal() const { return shouldTreatURLSchemeAsLocal(m_protocol); diff --git a/WebCore/page/SecurityOrigin.h b/WebCore/page/SecurityOrigin.h index b441474..c96bb83 100644 --- a/WebCore/page/SecurityOrigin.h +++ b/WebCore/page/SecurityOrigin.h @@ -138,6 +138,9 @@ public: // addition, the SandboxOrigin flag is inherited by iframes. bool isUnique() const { return m_isUnique; } + // Marks an origin as being unique. + void makeUnique(); + // Convert this SecurityOrigin into a string. The string // representation of a SecurityOrigin is similar to a URL, except it // lacks a path component. The string representation does not encode diff --git a/WebCore/page/Settings.cpp b/WebCore/page/Settings.cpp index c495a23..c59bdd0 100644 --- a/WebCore/page/Settings.cpp +++ b/WebCore/page/Settings.cpp @@ -87,6 +87,7 @@ Settings::Settings(Page* page) , m_isJavaScriptEnabled(false) , m_isWebSecurityEnabled(true) , m_allowUniversalAccessFromFileURLs(true) + , m_allowFileAccessFromFileURLs(true) , m_javaScriptCanOpenWindowsAutomatically(false) , m_shouldPrintBackgrounds(false) , m_textAreasAreResizable(false) @@ -265,6 +266,11 @@ void Settings::setAllowUniversalAccessFromFileURLs(bool allowUniversalAccessFrom m_allowUniversalAccessFromFileURLs = allowUniversalAccessFromFileURLs; } +void Settings::setAllowFileAccessFromFileURLs(bool allowFileAccessFromFileURLs) +{ + m_allowFileAccessFromFileURLs = allowFileAccessFromFileURLs; +} + void Settings::setJavaEnabled(bool isJavaEnabled) { m_isJavaEnabled = isJavaEnabled; diff --git a/WebCore/page/Settings.h b/WebCore/page/Settings.h index 652c13d..44b4642 100644 --- a/WebCore/page/Settings.h +++ b/WebCore/page/Settings.h @@ -135,6 +135,9 @@ namespace WebCore { void setAllowUniversalAccessFromFileURLs(bool); bool allowUniversalAccessFromFileURLs() const { return m_allowUniversalAccessFromFileURLs; } + void setAllowFileAccessFromFileURLs(bool); + bool allowFileAccessFromFileURLs() const { return m_allowFileAccessFromFileURLs; } + void setJavaScriptCanOpenWindowsAutomatically(bool); bool javaScriptCanOpenWindowsAutomatically() const { return m_javaScriptCanOpenWindowsAutomatically; } @@ -423,6 +426,7 @@ namespace WebCore { bool m_isJavaScriptEnabled : 1; bool m_isWebSecurityEnabled : 1; bool m_allowUniversalAccessFromFileURLs: 1; + bool m_allowFileAccessFromFileURLs: 1; bool m_javaScriptCanOpenWindowsAutomatically : 1; bool m_shouldPrintBackgrounds : 1; bool m_textAreasAreResizable : 1; diff --git a/WebCore/page/win/PageWin.cpp b/WebCore/page/win/PageWin.cpp index 5d7450c..3ef7728 100644 --- a/WebCore/page/win/PageWin.cpp +++ b/WebCore/page/win/PageWin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,37 +26,8 @@ #include "config.h" #include "Page.h" -#include "Frame.h" -#include "FrameLoaderClient.h" -#include "FrameView.h" -#include "FloatRect.h" -#include "PluginView.h" -#include <windows.h> - namespace WebCore { HINSTANCE Page::s_instanceHandle = 0; -void Page::setCanStartPlugins(bool canStartPlugins) -{ - if (m_canStartPlugins == canStartPlugins) - return; - - m_canStartPlugins = canStartPlugins; - - if (!m_canStartPlugins || m_unstartedPlugins.isEmpty()) - return; - - Vector<PluginView*> unstartedPlugins; - copyToVector(m_unstartedPlugins, unstartedPlugins); - m_unstartedPlugins.clear(); - - for (size_t i = 0; i < unstartedPlugins.size(); ++i) { - if (unstartedPlugins[i]->start()) - continue; - unstartedPlugins[i]->parentFrame()->loader()->client()->dispatchDidFailToStartPlugin(unstartedPlugins[i]); - } -} - } // namespace WebCore - diff --git a/WebCore/platform/FileChooser.cpp b/WebCore/platform/FileChooser.cpp index 9fad392..a2d4770 100644 --- a/WebCore/platform/FileChooser.cpp +++ b/WebCore/platform/FileChooser.cpp @@ -39,9 +39,9 @@ FileChooserClient::~FileChooserClient() inline FileChooser::FileChooser(FileChooserClient* client, const Vector<String>& initialFilenames) : m_client(client) - , m_icon(Icon::createIconForFiles(initialFilenames)) { m_filenames = initialFilenames; + loadIcon(); } PassRefPtr<FileChooser> FileChooser::create(FileChooserClient* client, const Vector<String>& initialFilenames) @@ -71,9 +71,24 @@ void FileChooser::chooseFiles(const Vector<String>& filenames) if (m_filenames == filenames) return; m_filenames = filenames; - m_icon = Icon::createIconForFiles(filenames); + loadIcon(); if (m_client) m_client->valueChanged(); } +void FileChooser::loadIcon() +{ + m_icon = Icon::createIconForFiles(m_filenames); + // If synchronous icon loading failed, try asynchronous loading. + if (!m_icon && m_filenames.size() && m_client) + m_client->iconForFiles(m_filenames); +} + +void FileChooser::iconLoaded(PassRefPtr<Icon> icon) +{ + m_icon = icon; + if (m_icon && m_client) + m_client->repaint(); +} + } diff --git a/WebCore/platform/FileChooser.h b/WebCore/platform/FileChooser.h index 0764a6a..e7feb3e 100644 --- a/WebCore/platform/FileChooser.h +++ b/WebCore/platform/FileChooser.h @@ -41,8 +41,10 @@ class Icon; class FileChooserClient { public: virtual void valueChanged() = 0; + virtual void repaint() = 0; virtual bool allowsMultipleFiles() = 0; virtual String acceptTypes() = 0; + virtual void iconForFiles(const Vector<String>&) = 0; virtual ~FileChooserClient(); }; @@ -63,13 +65,16 @@ public: void chooseFile(const String& path); void chooseFiles(const Vector<String>& paths); - + // Called when FileChooserClient finishes to load an icon requested by iconForFiles(). + void iconLoaded(PassRefPtr<Icon>); + bool allowsMultipleFiles() const { return m_client ? m_client->allowsMultipleFiles() : false; } // Acceptable MIME types. It's an 'accept' attribute value of the corresponding INPUT element. String acceptTypes() const { return m_client ? m_client->acceptTypes() : String(); } private: FileChooser(FileChooserClient*, const Vector<String>& initialFilenames); + void loadIcon(); FileChooserClient* m_client; Vector<String> m_filenames; diff --git a/WebCore/platform/GeolocationService.cpp b/WebCore/platform/GeolocationService.cpp index be9553b..7e1f755 100644 --- a/WebCore/platform/GeolocationService.cpp +++ b/WebCore/platform/GeolocationService.cpp @@ -25,12 +25,13 @@ #include "config.h" #include "GeolocationService.h" -#include "Geoposition.h" + #include "GeolocationServiceMock.h" +#include "Geoposition.h" #include "PositionError.h" -#include <wtf/CurrentTime.h> #include <wtf/Assertions.h> +#include <wtf/CurrentTime.h> namespace WebCore { diff --git a/WebCore/platform/GeolocationService.h b/WebCore/platform/GeolocationService.h index f991f67..363865d 100644 --- a/WebCore/platform/GeolocationService.h +++ b/WebCore/platform/GeolocationService.h @@ -20,7 +20,7 @@ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GeolocationService_h @@ -46,7 +46,7 @@ class GeolocationService : public Noncopyable { public: static GeolocationService* create(GeolocationServiceClient*); virtual ~GeolocationService() { } - + #if PLATFORM(ANDROID) // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082 virtual bool startUpdating(PositionOptions*, bool suspend) { return false; } @@ -54,7 +54,7 @@ public: virtual bool startUpdating(PositionOptions*) { return false; } #endif virtual void stopUpdating() { } - + virtual void suspend() { } virtual void resume() { } @@ -68,6 +68,7 @@ public: protected: GeolocationService(GeolocationServiceClient*); + GeolocationServiceClient* geolocationServiceClient() const { return m_geolocationServiceClient; } private: GeolocationServiceClient* m_geolocationServiceClient; diff --git a/WebCore/platform/Logging.cpp b/WebCore/platform/Logging.cpp index f3c6f1c..2358d41 100644 --- a/WebCore/platform/Logging.cpp +++ b/WebCore/platform/Logging.cpp @@ -59,6 +59,7 @@ WTFLogChannel LogMedia = { 0x01000000, "WebCoreLogLevel", WTFLogChan WTFLogChannel LogPlugins = { 0x02000000, "WebCoreLogLevel", WTFLogChannelOff }; WTFLogChannel LogArchives = { 0x04000000, "WebCoreLogLevel", WTFLogChannelOff }; +WTFLogChannel LogProgress = { 0x08000000, "WebCoreLogLevel", WTFLogChannelOff }; WTFLogChannel* getChannelFromName(const String& channelName) { @@ -110,6 +111,9 @@ WTFLogChannel* getChannelFromName(const String& channelName) if (equalIgnoringCase(channelName, String("PopupBlocking"))) return &LogPopupBlocking; + if (equalIgnoringCase(channelName, String("Progress"))) + return &LogProgress; + if (equalIgnoringCase(channelName, String("SpellingAndGrammar"))) return &LogSpellingAndGrammar; diff --git a/WebCore/platform/Logging.h b/WebCore/platform/Logging.h index 5c958fe..a3dfe62 100644 --- a/WebCore/platform/Logging.h +++ b/WebCore/platform/Logging.h @@ -57,6 +57,7 @@ namespace WebCore { extern WTFLogChannel LogMedia; extern WTFLogChannel LogPlugins; extern WTFLogChannel LogArchives; + extern WTFLogChannel LogProgress; void InitializeLoggingChannelsIfNecessary(); WTFLogChannel* getChannelFromName(const String& channelName); diff --git a/WebCore/platform/PlatformKeyboardEvent.h b/WebCore/platform/PlatformKeyboardEvent.h index 2b94cce..b2dfe03 100644 --- a/WebCore/platform/PlatformKeyboardEvent.h +++ b/WebCore/platform/PlatformKeyboardEvent.h @@ -63,6 +63,12 @@ class wxKeyEvent; class BMessage; #endif +#if PLATFORM(BREWMP) +typedef unsigned short uint16; +typedef unsigned long int uint32; +#define AEEEvent uint16 +#endif + namespace WebCore { class PlatformKeyboardEvent : public FastAllocBase { @@ -164,6 +170,10 @@ namespace WebCore { PlatformKeyboardEvent(BMessage*); #endif +#if PLATFORM(BREWMP) + PlatformKeyboardEvent(AEEEvent, uint16, uint32, Type); +#endif + #if PLATFORM(WIN) || PLATFORM(CHROMIUM) bool isSystemKey() const { return m_isSystemKey; } #endif diff --git a/WebCore/platform/brew/PlatformKeyboardEventBrew.cpp b/WebCore/platform/brew/PlatformKeyboardEventBrew.cpp new file mode 100644 index 0000000..758d15c --- /dev/null +++ b/WebCore/platform/brew/PlatformKeyboardEventBrew.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2010 Company 100, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PlatformKeyboardEvent.h" + +#include "KeyboardCodes.h" +#include "NotImplemented.h" + +#include <AEEEvent.h> +#include <AEEStdDef.h> +#include <AEEVCodes.h> + +namespace WebCore { + +static String keyIdentifierForBrewKeyCode(int16 keyCode) +{ + switch (keyCode) { + case AVK_LALT: + case AVK_RALT: + return "Alt"; + case AVK_LCTRL: + case AVK_RCTRL: + return "Control"; + case AVK_LSHIFT: + case AVK_RSHIFT: + return "Shift"; + case AVK_CAPLK: + return "CapsLock"; + case AVK_FUNCTION1: + return "F1"; + case AVK_FUNCTION2: + return "F2"; + case AVK_FUNCTION3: + return "F3"; + case AVK_FUNCTION4: + return "F4"; + case AVK_FUNCTION5: + return "F5"; + case AVK_FUNCTION6: + return "F6"; + case AVK_FUNCTION7: + return "F7"; + case AVK_FUNCTION8: + return "F8"; + case AVK_FUNCTION9: + return "F9"; + case AVK_FUNCTION10: + return "F10"; + case AVK_FUNCTION11: + return "F11"; + case AVK_FUNCTION12: + return "F12"; + case AVK_PRSCRN: + return "PrintScreen"; + case AVK_LEFT: + return "Left"; + case AVK_RIGHT: + return "Right"; + case AVK_UP: + return "Up"; + case AVK_DOWN: + return "Down"; + case AVK_TXINSERT: + return "Insert"; + case AVK_ENTER: + return "Enter"; + case AVK_TXHOME: + return "Home"; + case AVK_TXDELETE: + // Standard says that DEL becomes U+007F. + return "U+007F"; + case AVK_TXEND: + return "End"; + case AVK_TXPGUP: + return "PageUp"; + case AVK_TXPGDOWN: + return "PageDown"; + default: + return String::format("U+%04X", toASCIIUpper(keyCode)); + } +} + +static int windowsKeyCodeForKeyEvent(uint16 code) +{ + switch (code) { + case AVK_A: + return VK_BACK; // (08) BACKSPACE key + case AVK_ENTER: + return VK_RETURN; // (0D) Return key + case AVK_SPACE: + return VK_SPACE; // (20) SPACEBAR + case AVK_TXPGUP: + return VK_PRIOR; // (21) PAGE UP key + case AVK_TXPGDOWN: + return VK_NEXT; // (22) PAGE DOWN key + case AVK_TXEND: + return VK_END; // (23) END key + case AVK_TXHOME: + return VK_HOME; // (24) HOME key + case AVK_LEFT: + return VK_LEFT; // (25) LEFT ARROW key + case AVK_UP: + return VK_UP; // (26) UP ARROW key + case AVK_RIGHT: + return VK_RIGHT; // (27) RIGHT ARROW key + case AVK_DOWN: + return VK_DOWN; // (28) DOWN ARROW key + case AVK_TXINSERT: + return VK_INSERT; // (2D) INS key + case AVK_TXDELETE: + return VK_DELETE; // (2E) DEL key + default: + return 0; + } +} + +static inline String singleCharacterString(UChar c) +{ + return String(&c, 1); +} + +PlatformKeyboardEvent::PlatformKeyboardEvent(AEEEvent event, uint16 code, uint32 modifiers, Type type) + : m_type(type) + , m_text((type == Char) ? singleCharacterString(code) : String()) + , m_unmodifiedText((type == Char) ? singleCharacterString(code) : String()) + , m_keyIdentifier((type == Char) ? String() : keyIdentifierForBrewKeyCode(code)) + , m_autoRepeat(modifiers & KB_AUTOREPEAT) + , m_windowsVirtualKeyCode((type == RawKeyDown || type == KeyUp) ? windowsKeyCodeForKeyEvent(code) : 0) + , m_nativeVirtualKeyCode(code) + , m_isKeypad(false) + , m_shiftKey(modifiers & (KB_LSHIFT | KB_RSHIFT)) + , m_ctrlKey(modifiers & (KB_LCTRL | KB_RCTRL)) + , m_altKey(modifiers & (KB_LALT | KB_RALT)) + , m_metaKey(false) +{ +} + +void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool) +{ + // No KeyDown events on BREW to disambiguate. + ASSERT_NOT_REACHED(); +} + +bool PlatformKeyboardEvent::currentCapsLockState() +{ + notImplemented(); + return false; +} + +} // namespace WebCore + diff --git a/WebCore/platform/brew/SystemTimeBrew.cpp b/WebCore/platform/brew/SystemTimeBrew.cpp new file mode 100644 index 0000000..c1e39fb --- /dev/null +++ b/WebCore/platform/brew/SystemTimeBrew.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2010 Company 100. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "SystemTime.h" + +#include <float.h> + +namespace WebCore { + +float userIdleTime() +{ + // return an arbitrarily high userIdleTime so that releasing pages from the page cache isn't postponed + return FLT_MAX; +} + +} + diff --git a/WebCore/platform/chromium/ChromiumBridge.h b/WebCore/platform/chromium/ChromiumBridge.h index 83f9c81..5a085be 100644 --- a/WebCore/platform/chromium/ChromiumBridge.h +++ b/WebCore/platform/chromium/ChromiumBridge.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, Google Inc. All rights reserved. + * Copyright (c) 2010, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -53,6 +53,8 @@ namespace WebCore { class Cursor; class Document; class Frame; + class GeolocationServiceBridge; + class GeolocationServiceChromium; class GraphicsContext; class Image; class IntRect; @@ -83,12 +85,12 @@ namespace WebCore { static void clipboardWriteImage(NativeImagePtr, const KURL&, const String&); // Cookies ------------------------------------------------------------ - static void setCookies(const KURL& url, const KURL& firstPartyForCookies, const String& value); - static String cookies(const KURL& url, const KURL& firstPartyForCookies); - static String cookieRequestHeaderFieldValue(const KURL& url, const KURL& firstPartyForCookies); - static bool rawCookies(const KURL& url, const KURL& firstPartyForCookies, Vector<Cookie>*); - static void deleteCookie(const KURL& url, const String& cookieName); - static bool cookiesEnabled(const KURL& url, const KURL& firstPartyForCookies); + static void setCookies(const Document*, const KURL&, const String& value); + static String cookies(const Document*, const KURL&); + static String cookieRequestHeaderFieldValue(const Document*, const KURL&); + static bool rawCookies(const Document*, const KURL& url, Vector<Cookie>&); + static void deleteCookie(const Document*, const KURL& url, const String& cookieName); + static bool cookiesEnabled(const Document*); // DNS ---------------------------------------------------------------- static void prefetchDNS(const String& hostname); @@ -117,6 +119,9 @@ namespace WebCore { // Forms -------------------------------------------------------------- static void notifyFormStateChanged(const Document*); + // Geolocation -------------------------------------------------------- + static GeolocationServiceBridge* createGeolocationServiceBridge(GeolocationServiceChromium*); + // HTML5 DB ----------------------------------------------------------- #if ENABLE(DATABASE) // Returns a handle to the DB file and ooptionally a handle to its containing directory diff --git a/WebCore/platform/chromium/ChromiumDataObject.cpp b/WebCore/platform/chromium/ChromiumDataObject.cpp index 695da9f..77a5f0f 100644 --- a/WebCore/platform/chromium/ChromiumDataObject.cpp +++ b/WebCore/platform/chromium/ChromiumDataObject.cpp @@ -37,7 +37,6 @@ void ChromiumDataObject::clear() { url = KURL(); urlTitle = ""; - downloadURL = KURL(); downloadMetadata = ""; fileExtension = ""; filenames.clear(); @@ -52,7 +51,6 @@ void ChromiumDataObject::clear() bool ChromiumDataObject::hasData() const { return !url.isEmpty() - || !downloadURL.isEmpty() || !downloadMetadata.isEmpty() || !fileExtension.isEmpty() || !filenames.isEmpty() @@ -64,7 +62,6 @@ bool ChromiumDataObject::hasData() const ChromiumDataObject::ChromiumDataObject(const ChromiumDataObject& other) : url(other.url) , urlTitle(other.urlTitle) - , downloadURL(other.downloadURL) , downloadMetadata(other.downloadMetadata) , fileExtension(other.fileExtension) , filenames(other.filenames) diff --git a/WebCore/platform/chromium/ChromiumDataObject.h b/WebCore/platform/chromium/ChromiumDataObject.h index 186a1a0..5fae3e3 100644 --- a/WebCore/platform/chromium/ChromiumDataObject.h +++ b/WebCore/platform/chromium/ChromiumDataObject.h @@ -59,7 +59,6 @@ namespace WebCore { KURL url; String urlTitle; - KURL downloadURL; String downloadMetadata; String fileExtension; diff --git a/WebCore/platform/chromium/ClipboardChromium.cpp b/WebCore/platform/chromium/ClipboardChromium.cpp index 933d839..a1f60a6 100644 --- a/WebCore/platform/chromium/ClipboardChromium.cpp +++ b/WebCore/platform/chromium/ClipboardChromium.cpp @@ -161,9 +161,6 @@ bool ClipboardChromium::setData(const String& type, const String& data) if (winType == ClipboardDataTypeDownloadURL) { m_dataObject->downloadMetadata = data; - KURL url = KURL(ParsedURLString, data); - if (url.isValid()) - m_dataObject->downloadURL = url; return true; } diff --git a/WebCore/platform/chromium/GeolocationServiceChromium.cpp b/WebCore/platform/chromium/GeolocationServiceChromium.cpp index 65886b0..4e00908 100644 --- a/WebCore/platform/chromium/GeolocationServiceChromium.cpp +++ b/WebCore/platform/chromium/GeolocationServiceChromium.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Google Inc. All rights reserved. + * Copyright (c) 2010, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,27 +29,79 @@ */ #include "config.h" -#include "GeolocationService.h" +#include "GeolocationServiceChromium.h" + +#include "ChromiumBridge.h" namespace WebCore { -class GeolocationServiceChromium : public GeolocationService { -public: - GeolocationServiceChromium(GeolocationServiceClient* c) - : GeolocationService(c) - { - } - // FIXME: Implement. https://bugs.webkit.org/show_bug.cgi?id=32068 -}; +GeolocationServiceChromium::GeolocationServiceChromium(GeolocationServiceClient* c) + : GeolocationService(c), + m_geolocation(reinterpret_cast<Geolocation*>(c)), + m_geolocationServiceBridge(ChromiumBridge::createGeolocationServiceBridge(this)), + m_lastPosition(Geoposition::create(Coordinates::create(0.0, 0.0, false, 0.0, 0.0, false, 0.0, false, 0.0, false, 0.0), 0)), + m_lastError(PositionError::create(PositionError::POSITION_UNAVAILABLE, "")) +{ +} + +void GeolocationServiceChromium::setIsAllowed(bool allowed) +{ + m_geolocation->setIsAllowed(allowed); +} + +void GeolocationServiceChromium::setLastPosition(double latitude, double longitude, bool providesAltitude, double altitude, double accuracy, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed, long long timestamp) +{ + m_lastPosition = Geoposition::create(Coordinates::create(latitude, longitude, providesAltitude, altitude, accuracy, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed), timestamp); + positionChanged(); +} + +void GeolocationServiceChromium::setLastError(int errorCode, const String& message) +{ + m_lastError = PositionError::create(static_cast<PositionError::ErrorCode>(errorCode), message); + errorOccurred(); +} + +Frame* GeolocationServiceChromium::frame() +{ + return m_geolocation->frame(); +} + +bool GeolocationServiceChromium::startUpdating(PositionOptions* options) +{ + return m_geolocationServiceBridge->startUpdating(options); +} + +void GeolocationServiceChromium::stopUpdating() +{ + return m_geolocationServiceBridge->stopUpdating(); +} + +void GeolocationServiceChromium::suspend() +{ + return m_geolocationServiceBridge->suspend(); +} + +void GeolocationServiceChromium::resume() +{ + return m_geolocationServiceBridge->resume(); +} + +Geoposition* GeolocationServiceChromium::lastPosition() const +{ + return m_lastPosition.get(); +} + +PositionError* GeolocationServiceChromium::lastError() const +{ + return m_lastError.get(); +} -// This guard is the counterpart of the one in WebCore/platform/GeolocationService.cpp -#if ENABLE(GEOLOCATION) -static GeolocationService* createGeolocationService(GeolocationServiceClient* c) +static GeolocationService* createGeolocationServiceChromium(GeolocationServiceClient* c) { return new GeolocationServiceChromium(c); } -GeolocationService::FactoryFunction* GeolocationService::s_factoryFunction = &createGeolocationService; -#endif +// Sets up the factory function for GeolocationService. +GeolocationService::FactoryFunction* GeolocationService::s_factoryFunction = &createGeolocationServiceChromium; } // namespace WebCore diff --git a/WebCore/platform/chromium/GeolocationServiceChromium.h b/WebCore/platform/chromium/GeolocationServiceChromium.h new file mode 100644 index 0000000..e32de8b --- /dev/null +++ b/WebCore/platform/chromium/GeolocationServiceChromium.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2010, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GeolocationServiceChromium_h +#define GeolocationServiceChromium_h + +#include "Geolocation.h" +#include "GeolocationService.h" +#include "Geoposition.h" +#include "PlatformString.h" +#include "PositionError.h" + +namespace WebCore { + +// Provides an interface for GeolocationServiceChromium to call into the embedder. +class GeolocationServiceBridge { +public: + // Called by GeolocationServiceChromium. + virtual bool startUpdating(PositionOptions*) = 0; + virtual void stopUpdating() = 0; + virtual void suspend() = 0; + virtual void resume() = 0; + + // Called by the embedder, to identify this bridge. + virtual int getBridgeId() const = 0; +}; + +// This class extends GeolocationService, and uses GeolocationServiceBridge to +// call into the embedder, as well as provides a few extra methods so that the +// embedder can notify permission, position, error, etc. +class GeolocationServiceChromium : public GeolocationService { +public: + explicit GeolocationServiceChromium(GeolocationServiceClient*); + + GeolocationServiceBridge* geolocationServiceBridge() const { return m_geolocationServiceBridge.get(); } + void setIsAllowed(bool allowed); + void setLastPosition(double latitude, double longitude, bool providesAltitude, double altitude, double accuracy, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed, long long timestamp); + void setLastError(int errorCode, const String& message); + Frame* frame(); + + // From GeolocationService. + virtual bool startUpdating(PositionOptions*); + virtual void stopUpdating(); + virtual void suspend(); + virtual void resume(); + virtual Geoposition* lastPosition() const; + virtual PositionError* lastError() const; + +private: + Geolocation* m_geolocation; + OwnPtr<GeolocationServiceBridge> m_geolocationServiceBridge; + RefPtr<Geoposition> m_lastPosition; + RefPtr<PositionError> m_lastError; +}; + +} // namespace WebCore + +#endif // GeolocationServiceChromium_h diff --git a/WebCore/platform/chromium/PasteboardChromium.cpp b/WebCore/platform/chromium/PasteboardChromium.cpp index d4f9a27..6904050 100644 --- a/WebCore/platform/chromium/PasteboardChromium.cpp +++ b/WebCore/platform/chromium/PasteboardChromium.cpp @@ -125,7 +125,8 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String& title) ASSERT(node->renderer()->isImage()); RenderImage* renderer = toRenderImage(node->renderer()); CachedImage* cachedImage = renderer->cachedImage(); - ASSERT(cachedImage); + if (!cachedImage || cachedImage->errorOccurred()) + return; Image* image = cachedImage->image(); ASSERT(image); diff --git a/WebCore/platform/graphics/BitmapImage.cpp b/WebCore/platform/graphics/BitmapImage.cpp index 0b94efb..0cd3907 100644 --- a/WebCore/platform/graphics/BitmapImage.cpp +++ b/WebCore/platform/graphics/BitmapImage.cpp @@ -270,6 +270,18 @@ void BitmapImage::startAnimation(bool catchUpIfNecessary) if (m_frameTimer || !shouldAnimate() || frameCount() <= 1) return; + // Don't advance the animation to an incomplete frame. + size_t nextFrame = (m_currentFrame + 1) % frameCount(); + if (!m_allDataReceived && !frameIsCompleteAtIndex(nextFrame)) + return; + + // Don't advance past the last frame if we haven't decoded the whole image + // yet and our repetition count is potentially unset. The repetition count + // in a GIF can potentially come after all the rest of the image data, so + // wait on it. + if (!m_allDataReceived && repetitionCount(false) == cAnimationLoopOnce && m_currentFrame >= (frameCount() - 1)) + return; + // Determine time for next frame to start. By ignoring paint and timer lag // in this calculation, we make the animation appear to run at its desired // rate regardless of how fast it's being repainted. @@ -288,18 +300,6 @@ void BitmapImage::startAnimation(bool catchUpIfNecessary) m_desiredFrameStartTime = time + currentDuration; } - // Don't advance the animation to an incomplete frame. - size_t nextFrame = (m_currentFrame + 1) % frameCount(); - if (!m_allDataReceived && !frameIsCompleteAtIndex(nextFrame)) - return; - - // Don't advance past the last frame if we haven't decoded the whole image - // yet and our repetition count is potentially unset. The repetition count - // in a GIF can potentially come after all the rest of the image data, so - // wait on it. - if (!m_allDataReceived && repetitionCount(false) == cAnimationLoopOnce && m_currentFrame >= (frameCount() - 1)) - return; - // The image may load more slowly than it's supposed to animate, so that by // the time we reach the end of the first repetition, we're well behind. // Clamp the desired frame start time in this case, so that we don't skip diff --git a/WebCore/platform/graphics/FloatRect.h b/WebCore/platform/graphics/FloatRect.h index 74a6293..b265121 100644 --- a/WebCore/platform/graphics/FloatRect.h +++ b/WebCore/platform/graphics/FloatRect.h @@ -99,6 +99,8 @@ public: float right() const { return x() + width(); } float bottom() const { return y() + height(); } + FloatPoint center() const { return FloatPoint(x() + width() / 2, y() + height() / 2); } + void move(const FloatSize& delta) { m_location += delta; } void move(float dx, float dy) { m_location.move(dx, dy); } diff --git a/WebCore/platform/graphics/Gradient.h b/WebCore/platform/graphics/Gradient.h index e1be1fe..0efd3bf 100644 --- a/WebCore/platform/graphics/Gradient.h +++ b/WebCore/platform/graphics/Gradient.h @@ -37,7 +37,9 @@ #if PLATFORM(CG) -#ifdef BUILDING_ON_TIGER +#define USE_CG_SHADING defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) + +#if USE_CG_SHADING typedef struct CGShading* CGShadingRef; typedef CGShadingRef PlatformGradient; #else diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp new file mode 100644 index 0000000..3eb9818 --- /dev/null +++ b/WebCore/platform/graphics/GraphicsContext3D.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "GraphicsContext3D.h" + +#include "Image.h" + +namespace WebCore { + +bool GraphicsContext3D::extractImageData(Image* image, + bool flipY, + bool premultiplyAlpha, + Vector<uint8_t>& imageData, + unsigned int* format, + unsigned int* internalFormat) +{ + if (!image) + return false; + AlphaOp alphaOp = kAlphaDoNothing; + bool hasAlphaChannel = true; + if (!getImageData(image, imageData, premultiplyAlpha, + &hasAlphaChannel, &alphaOp, format)) + return false; + processImageData(imageData.data(), + image->width(), + image->height(), + flipY, + alphaOp); + *internalFormat = (hasAlphaChannel ? RGBA : RGB); + return true; +} + +void GraphicsContext3D::processImageData(uint8_t* imageData, + unsigned width, + unsigned height, + bool flipVertically, + AlphaOp alphaOp) +{ + switch (alphaOp) { + case kAlphaDoPremultiply: + premultiplyAlpha(imageData, width * height); + break; + case kAlphaDoUnmultiply: + unmultiplyAlpha(imageData, width * height); + break; + default: + break; + } + + if (flipVertically && width && height) { + int rowBytes = width * 4; + uint8_t* tempRow = new uint8_t[rowBytes]; + for (unsigned i = 0; i < height / 2; i++) { + uint8_t* lowRow = imageData + (rowBytes * i); + uint8_t* highRow = imageData + (rowBytes * (height - i - 1)); + memcpy(tempRow, lowRow, rowBytes); + memcpy(lowRow, highRow, rowBytes); + memcpy(highRow, tempRow, rowBytes); + } + delete[] tempRow; + } +} + +// Premultiply alpha into color channels. +void GraphicsContext3D::premultiplyAlpha(unsigned char* rgbaData, int numPixels) +{ + for (int j = 0; j < numPixels; j++) { + float r = rgbaData[4*j+0] / 255.0f; + float g = rgbaData[4*j+1] / 255.0f; + float b = rgbaData[4*j+2] / 255.0f; + float a = rgbaData[4*j+3] / 255.0f; + rgbaData[4*j+0] = (unsigned char) (r * a * 255.0f); + rgbaData[4*j+1] = (unsigned char) (g * a * 255.0f); + rgbaData[4*j+2] = (unsigned char) (b * a * 255.0f); + } +} + +// Remove premultiplied alpha from color channels. +// FIXME: this is lossy. Must retrieve original values from HTMLImageElement. +void GraphicsContext3D::unmultiplyAlpha(unsigned char* rgbaData, int numPixels) +{ + for (int j = 0; j < numPixels; j++) { + float r = rgbaData[4*j+0] / 255.0f; + float g = rgbaData[4*j+1] / 255.0f; + float b = rgbaData[4*j+2] / 255.0f; + float a = rgbaData[4*j+3] / 255.0f; + if (a > 0.0f) { + r /= a; + g /= a; + b /= a; + r = (r > 1.0f) ? 1.0f : r; + g = (g > 1.0f) ? 1.0f : g; + b = (b > 1.0f) ? 1.0f : b; + rgbaData[4*j+0] = (unsigned char) (r * 255.0f); + rgbaData[4*j+1] = (unsigned char) (g * 255.0f); + rgbaData[4*j+2] = (unsigned char) (b * 255.0f); + } + } +} + +} // namespace WebCore + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index b7be8fc..0a41dc6 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.h +++ b/WebCore/platform/graphics/GraphicsContext3D.h @@ -419,6 +419,43 @@ namespace WebCore { // like GL_FLOAT, GL_INT, etc. int sizeInBytes(int type); + //---------------------------------------------------------------------- + // Helpers for texture uploading. + // + + // Extracts the contents of the given Image into the passed + // Vector, obeying the flipY and premultiplyAlpha flags. + // Returns the applicable OpenGL format and internalFormat for + // the subsequent glTexImage2D or glTexSubImage2D call. + // Returns true upon success. + bool extractImageData(Image* image, + bool flipY, + bool premultiplyAlpha, + Vector<uint8_t>& imageData, + unsigned int* format, + unsigned int* internalFormat); + + // Processes the given image data in preparation for uploading + // via texImage2D or texSubImage2D. The input data must be in + // 4-component format with the alpha channel last (i.e., RGBA + // or BGRA), tightly packed, with no space between rows. + + enum AlphaOp { + kAlphaDoNothing = 0, + kAlphaDoPremultiply = 1, + kAlphaDoUnmultiply = 2 + }; + + void processImageData(uint8_t* imageData, + unsigned width, + unsigned height, + bool flipVertically, + AlphaOp alphaOp); + + //---------------------------------------------------------------------- + // Entry points for WebGL. + // + void activeTexture(unsigned long texture); void attachShader(WebGLProgram* program, WebGLShader* shader); void bindAttribLocation(WebGLProgram*, unsigned long index, const String& name); @@ -624,6 +661,34 @@ namespace WebCore { private: GraphicsContext3D(Attributes attrs); + // Helpers for texture uploading. + void premultiplyAlpha(unsigned char* rgbaData, int numPixels); + void unmultiplyAlpha(uint8_t* imageData, int numPixels); + + // Each platform must provide an implementation of this method. + // + // Gets the data for the given Image into outputVector, + // without doing any processing of the data (vertical flip or + // otherwise). + // + // premultiplyAlpha indicates whether the user will eventually + // want the alpha channel multiplied into the color channels. + // + // The out parameter hasAlphaChannel indicates whether the + // image actually had an alpha channel. + // + // The out parameter neededAlphaOp should be passed to a + // subsequent call of processImageData. + // + // The out parameter format should be passed to subsequent + // invocations of texImage2D and texSubImage2D. + bool getImageData(Image* image, + Vector<uint8_t>& outputVector, + bool premultiplyAlpha, + bool* hasAlphaChannel, + AlphaOp* neededAlphaOp, + unsigned int* format); + int m_currentWidth, m_currentHeight; #if PLATFORM(MAC) diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h index 844301e..a097620 100644 --- a/WebCore/platform/graphics/GraphicsLayer.h +++ b/WebCore/platform/graphics/GraphicsLayer.h @@ -74,7 +74,7 @@ class FloatPoint3D; class GraphicsContext; class Image; class TextStream; -class TimingFunction; +struct TimingFunction; // Base class for animation values (also used for transitions). Here to // represent values for properties being animated via the GraphicsLayer, diff --git a/WebCore/platform/graphics/Icon.h b/WebCore/platform/graphics/Icon.h index d7d694a..e9f2dc7 100644 --- a/WebCore/platform/graphics/Icon.h +++ b/WebCore/platform/graphics/Icon.h @@ -51,6 +51,8 @@ class String; class Icon : public RefCounted<Icon> { public: + // Deprecated. This function will be removed. + // FIXME: Remove it when all implementations are moved to ChromeClient::iconForFiles(). static PassRefPtr<Icon> createIconForFiles(const Vector<String>& filenames); ~Icon(); diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp index 2b09885..8a9a264 100644 --- a/WebCore/platform/graphics/MediaPlayer.cpp +++ b/WebCore/platform/graphics/MediaPlayer.cpp @@ -69,6 +69,9 @@ public: virtual void pause() { } virtual PlatformMedia platformMedia() const { return NoPlatformMedia; } +#if USE(ACCELERATED_COMPOSITING) + virtual PlatformLayer* platformLayer() const { return 0; } +#endif virtual IntSize naturalSize() const { return IntSize(0, 0); } @@ -364,6 +367,13 @@ PlatformMedia MediaPlayer::platformMedia() const return m_private->platformMedia(); } +#if USE(ACCELERATED_COMPOSITING) +PlatformLayer* MediaPlayer::platformLayer() const +{ + return m_private->platformLayer(); +} +#endif + MediaPlayer::NetworkState MediaPlayer::networkState() { return m_private->networkState(); diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h index 40ed8ae..1ca4576 100644 --- a/WebCore/platform/graphics/MediaPlayer.h +++ b/WebCore/platform/graphics/MediaPlayer.h @@ -39,6 +39,10 @@ #include <wtf/Noncopyable.h> #include <wtf/PassOwnPtr.h> +#if USE(ACCELERATED_COMPOSITING) +#include "GraphicsLayer.h" +#endif + #ifdef __OBJC__ @class QTMovie; #else @@ -67,10 +71,6 @@ class MediaPlayerPrivateInterface; class String; class TimeRanges; -#if USE(ACCELERATED_COMPOSITING) -class GraphicsLayer; -#endif - class MediaPlayerClient { public: virtual ~MediaPlayerClient() { } @@ -112,8 +112,9 @@ public: // whether the rendering system can accelerate the display of this MediaPlayer. virtual bool mediaPlayerRenderingCanBeAccelerated(MediaPlayer*) { return false; } - // return the GraphicsLayer that will host the presentation for this MediaPlayer. - virtual GraphicsLayer* mediaPlayerGraphicsLayer(MediaPlayer*) { return 0; } + // called when the media player's rendering mode changed, which indicates a change in the + // availability of the platformLayer(). + virtual void mediaPlayerRenderingModeChanged(MediaPlayer*) { } #endif }; @@ -135,6 +136,9 @@ public: bool supportsFullscreen() const; bool supportsSave() const; PlatformMedia platformMedia() const; +#if USE(ACCELERATED_COMPOSITING) + PlatformLayer* platformLayer() const; +#endif IntSize naturalSize(); bool hasVideo() const; diff --git a/WebCore/platform/graphics/MediaPlayerPrivate.h b/WebCore/platform/graphics/MediaPlayerPrivate.h index 3b7c4d4..3bb8475 100644 --- a/WebCore/platform/graphics/MediaPlayerPrivate.h +++ b/WebCore/platform/graphics/MediaPlayerPrivate.h @@ -45,6 +45,9 @@ public: virtual void prepareToPlay() { } virtual PlatformMedia platformMedia() const { return NoPlatformMedia; } +#if USE(ACCELERATED_COMPOSITING) + virtual PlatformLayer* platformLayer() const { return 0; } +#endif virtual void play() = 0; virtual void pause() = 0; diff --git a/WebCore/platform/graphics/cg/GradientCG.cpp b/WebCore/platform/graphics/cg/GradientCG.cpp index e9b5de7..9c91700 100644 --- a/WebCore/platform/graphics/cg/GradientCG.cpp +++ b/WebCore/platform/graphics/cg/GradientCG.cpp @@ -36,7 +36,7 @@ namespace WebCore { void Gradient::platformDestroy() { -#ifdef BUILDING_ON_TIGER +#if USE_CG_SHADING CGShadingRelease(m_gradient); #else CGGradientRelease(m_gradient); @@ -44,7 +44,7 @@ void Gradient::platformDestroy() m_gradient = 0; } -#ifdef BUILDING_ON_TIGER +#if USE_CG_SHADING static void gradientCallback(void* info, const CGFloat* in, CGFloat* out) { float r, g, b, a; @@ -114,7 +114,7 @@ void Gradient::fill(GraphicsContext* context, const FloatRect& rect) void Gradient::paint(GraphicsContext* context) { -#ifdef BUILDING_ON_TIGER +#if USE_CG_SHADING CGContextDrawShading(context->platformContext(), platformGradient()); #else CGGradientDrawingOptions extendOptions = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation; diff --git a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp new file mode 100644 index 0000000..c6a8f83 --- /dev/null +++ b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "GraphicsContext3D.h" + +#include "Image.h" + +#include <CoreGraphics/CGBitmapContext.h> +#include <CoreGraphics/CGContext.h> +#include <CoreGraphics/CGImage.h> + +namespace WebCore { + +bool GraphicsContext3D::getImageData(Image* image, + Vector<uint8_t>& outputVector, + bool premultiplyAlpha, + bool* hasAlphaChannel, + AlphaOp* neededAlphaOp, + unsigned int* format) +{ + if (!image) + return false; + CGImageRef cgImage = image->nativeImageForCurrentFrame(); + if (!cgImage) + return false; + int width = CGImageGetWidth(cgImage); + int height = CGImageGetHeight(cgImage); + int rowBytes = width * 4; + CGImageAlphaInfo info = CGImageGetAlphaInfo(cgImage); + *hasAlphaChannel = (info != kCGImageAlphaNone + && info != kCGImageAlphaNoneSkipLast + && info != kCGImageAlphaNoneSkipFirst); + if (!premultiplyAlpha && *hasAlphaChannel) + // FIXME: must fetch the image data before the premultiplication step + *neededAlphaOp = kAlphaDoUnmultiply; + *format = RGBA; + outputVector.resize(height * rowBytes); + // Try to reuse the color space from the image to preserve its colors. + // Some images use a color space (such as indexed) unsupported by the bitmap context. + CGColorSpaceRef colorSpace = CGImageGetColorSpace(cgImage); + bool releaseColorSpace = false; + CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace); + switch (colorSpaceModel) { + case kCGColorSpaceModelMonochrome: + case kCGColorSpaceModelRGB: + case kCGColorSpaceModelCMYK: + case kCGColorSpaceModelLab: + case kCGColorSpaceModelDeviceN: + break; + default: + colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear); + releaseColorSpace = true; + break; + } + CGContextRef tmpContext = CGBitmapContextCreate(outputVector.data(), + width, height, 8, rowBytes, + colorSpace, + kCGImageAlphaPremultipliedLast); + if (releaseColorSpace) + CGColorSpaceRelease(colorSpace); + if (!tmpContext) + return false; + CGContextSetBlendMode(tmpContext, kCGBlendModeCopy); + CGContextDrawImage(tmpContext, + CGRectMake(0, 0, static_cast<CGFloat>(width), static_cast<CGFloat>(height)), + cgImage); + CGContextRelease(tmpContext); + return true; +} + + +} // namespace WebCore + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp b/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp index e2c47c1..e71f66a 100644 --- a/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp @@ -134,7 +134,8 @@ static bool fillBMPGlyphs(unsigned offset, // Copy the output to the GlyphPage bool haveGlyphs = false; int invalidGlyph = 0xFFFF; - if (!isVistaOrNewer() && !(tm.tmPitchAndFamily & TMPF_TRUETYPE)) + const DWORD cffTableTag = 0x20464643; // 4-byte identifier for OpenType CFF table ('CFF '). + if (!isVistaOrNewer() && !(tm.tmPitchAndFamily & TMPF_TRUETYPE) && (GetFontData(dc, cffTableTag, 0, 0, 0) == GDI_ERROR)) invalidGlyph = 0x1F; Glyph spaceGlyph = 0; // Glyph for a space. Lazily filled. diff --git a/WebCore/platform/graphics/gtk/IconGtk.cpp b/WebCore/platform/graphics/gtk/IconGtk.cpp index 3563a59..71b897e 100644 --- a/WebCore/platform/graphics/gtk/IconGtk.cpp +++ b/WebCore/platform/graphics/gtk/IconGtk.cpp @@ -87,6 +87,7 @@ static String lookupIconName(String MIMEType) return GTK_STOCK_FILE; } +// FIXME: Move the code to ChromeClient::iconForFiles(). PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames) { if (filenames.isEmpty()) diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp index 1866c36..e1c9fd2 100644 --- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp +++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp @@ -3,6 +3,7 @@ * Copyright (C) 2007 Collabora Ltd. All rights reserved. * Copyright (C) 2007 Alp Toker <alp@atoker.com> * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org> + * Copyright (C) 2009, 2010 Igalia S.L * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -52,20 +53,44 @@ #include <gst/video/video.h> #include <limits> #include <math.h> -#include <webkit/webkitwebview.h> #include <wtf/gtk/GOwnPtr.h> +// GstPlayFlags flags from playbin2. It is the policy of GStreamer to +// not publicly expose element-specific enums. That's why this +// GstPlayFlags enum has been copied here. +typedef enum { + GST_PLAY_FLAG_VIDEO = 0x00000001, + GST_PLAY_FLAG_AUDIO = 0x00000002, + GST_PLAY_FLAG_TEXT = 0x00000004, + GST_PLAY_FLAG_VIS = 0x00000008, + GST_PLAY_FLAG_SOFT_VOLUME = 0x00000010, + GST_PLAY_FLAG_NATIVE_AUDIO = 0x00000020, + GST_PLAY_FLAG_NATIVE_VIDEO = 0x00000040, + GST_PLAY_FLAG_DOWNLOAD = 0x00000080, + GST_PLAY_FLAG_BUFFERING = 0x000000100 +} GstPlayFlags; + using namespace std; namespace WebCore { +static int greatestCommonDivisor(int a, int b) +{ + while (b) { + int temp = a; + a = b; + b = temp % b; + } + + return ABS(a); +} + gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data) { GOwnPtr<GError> err; GOwnPtr<gchar> debug; MediaPlayer::NetworkState error; MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data); - gint percent = 0; bool issueError = true; bool attemptNextLocation = false; @@ -115,8 +140,7 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo mp->updateStates(); break; case GST_MESSAGE_BUFFERING: - gst_message_parse_buffering(message, &percent); - LOG_VERBOSE(Media, "Buffering %d", percent); + mp->processBufferingStats(message); break; case GST_MESSAGE_DURATION: LOG_VERBOSE(Media, "Duration changed"); @@ -174,6 +198,12 @@ gboolean notifyMuteIdleCallback(gpointer data) return FALSE; } +gboolean bufferingTimeoutCallback(gpointer data) +{ + MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data); + return mp->queryBufferingStats(); +} + static float playbackPosition(GstElement* playbin) { @@ -278,14 +308,24 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) , m_playbackRate(1) , m_errorOccured(false) , m_volumeIdleId(0) - , m_mediaDuration(0.0) + , m_mediaDuration(0) , m_muteIdleId(0) + , m_startedBuffering(false) + , m_fillTimeoutId(0) + , m_maxTimeLoaded(0) + , m_fillStatus(0) { - doGstInit(); + if (doGstInit()) + createGSTPlayBin(); } MediaPlayerPrivate::~MediaPlayerPrivate() { + if (m_fillTimeoutId) { + g_source_remove(m_fillTimeoutId); + m_fillTimeoutId = 0; + } + if (m_volumeIdleId) { g_source_remove(m_volumeIdleId); m_volumeIdleId = 0; @@ -338,7 +378,7 @@ void MediaPlayerPrivate::load(const String& url) m_player->readyStateChanged(); } - createGSTPlayBin(url); + g_object_set(m_playBin, "uri", url.utf8().data(), NULL); pause(); } @@ -422,9 +462,6 @@ void MediaPlayerPrivate::seek(float time) if (!m_playBin) return; - if (m_isStreaming) - return; - if (m_errorOccured) return; @@ -473,30 +510,60 @@ IntSize MediaPlayerPrivate::naturalSize() const if (!hasVideo()) return IntSize(); + GstPad* pad = gst_element_get_static_pad(m_videoSink, "sink"); + if (!pad) + return IntSize(); + + int width = 0, height = 0; + GstCaps* caps = GST_PAD_CAPS(pad); + int pixelAspectRatioNumerator, pixelAspectRatioDenominator; + int displayWidth, displayHeight, displayAspectRatioGCD; + int originalWidth = 0, originalHeight = 0; + // TODO: handle possible clean aperture data. See // https://bugzilla.gnome.org/show_bug.cgi?id=596571 // TODO: handle possible transformation matrix. See // https://bugzilla.gnome.org/show_bug.cgi?id=596326 - int width = 0, height = 0; - if (GstPad* pad = gst_element_get_static_pad(m_videoSink, "sink")) { - GstCaps* caps = GST_PAD_CAPS(pad); - gfloat pixelAspectRatio; - gint pixelAspectRatioNumerator, pixelAspectRatioDenominator; - - if (!GST_IS_CAPS(caps) || !gst_caps_is_fixed(caps) - || !gst_video_format_parse_caps(caps, 0, &width, &height) - || !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator, - &pixelAspectRatioDenominator)) { - gst_object_unref(GST_OBJECT(pad)); - return IntSize(); - } - pixelAspectRatio = (gfloat) pixelAspectRatioNumerator / (gfloat) pixelAspectRatioDenominator; - width *= pixelAspectRatio; - height /= pixelAspectRatio; + // Get the video PAR and original size. + if (!GST_IS_CAPS(caps) || !gst_caps_is_fixed(caps) + || !gst_video_format_parse_caps(caps, 0, &originalWidth, &originalHeight) + || !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator, + &pixelAspectRatioDenominator)) { gst_object_unref(GST_OBJECT(pad)); + return IntSize(); } + gst_object_unref(GST_OBJECT(pad)); + + LOG_VERBOSE(Media, "Original video size: %dx%d", originalWidth, originalHeight); + LOG_VERBOSE(Media, "Pixel aspect ratio: %d/%d", pixelAspectRatioNumerator, pixelAspectRatioDenominator); + + // Calculate DAR based on PAR and video size. + displayWidth = originalWidth * pixelAspectRatioNumerator; + displayHeight = originalHeight * pixelAspectRatioDenominator; + + // Divide display width and height by their GCD to avoid possible overflows. + displayAspectRatioGCD = greatestCommonDivisor(displayWidth, displayHeight); + displayWidth /= displayAspectRatioGCD; + displayHeight /= displayAspectRatioGCD; + + // Apply DAR to original video size. This is the same behavior as in xvimagesink's setcaps function. + if (!(originalHeight % displayHeight)) { + LOG_VERBOSE(Media, "Keeping video original height"); + width = gst_util_uint64_scale_int(originalHeight, displayWidth, displayHeight); + height = originalHeight; + } else if (!(originalWidth % displayWidth)) { + LOG_VERBOSE(Media, "Keeping video original width"); + height = gst_util_uint64_scale_int(originalWidth, displayHeight, displayWidth); + width = originalWidth; + } else { + LOG_VERBOSE(Media, "Approximating while keeping original video height"); + width = gst_util_uint64_scale_int(originalHeight, displayWidth, displayHeight); + height = originalHeight; + } + + LOG_VERBOSE(Media, "Natural size: %dx%d", width, height); return IntSize(width, height); } @@ -610,16 +677,79 @@ PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const return timeRanges.release(); } +void MediaPlayerPrivate::processBufferingStats(GstMessage* message) +{ + GstBufferingMode mode; + + gst_message_parse_buffering_stats(message, &mode, 0, 0, 0); + if (mode != GST_BUFFERING_DOWNLOAD) + return; + + if (!m_startedBuffering) { + m_startedBuffering = true; + + if (m_fillTimeoutId > 0) + g_source_remove(m_fillTimeoutId); + + m_fillTimeoutId = g_timeout_add(200, (GSourceFunc) bufferingTimeoutCallback, this); + } +} + +bool MediaPlayerPrivate::queryBufferingStats() +{ + GstQuery* query = gst_query_new_buffering(GST_FORMAT_PERCENT); + + if (!gst_element_query(m_playBin, query)) { + gst_query_unref(query); + return TRUE; + } + + gint64 start, stop; + + gst_query_parse_buffering_range(query, 0, &start, &stop, 0); + gst_query_unref(query); + + if (stop != -1) + m_fillStatus = 100.0 * stop / GST_FORMAT_PERCENT_MAX; + else + m_fillStatus = 100.0; + + LOG_VERBOSE(Media, "Download buffer filled up to %f%%", m_fillStatus); + + if (!m_mediaDuration) + durationChanged(); + + // Update maxTimeLoaded only if the media duration is + // available. Otherwise we can't compute it. + if (m_mediaDuration) { + m_maxTimeLoaded = static_cast<float>((m_fillStatus * m_mediaDuration) / 100.0); + LOG_VERBOSE(Media, "Updated maxTimeLoaded: %f", m_maxTimeLoaded); + } + + if (m_fillStatus != 100.0) { + updateStates(); + return TRUE; + } + + // Media is now fully loaded. It will play even if network + // connection is cut. Buffering is done, remove the fill source + // from the main loop. + m_fillTimeoutId = 0; + m_startedBuffering = false; + updateStates(); + return FALSE; +} + float MediaPlayerPrivate::maxTimeSeekable() const { if (m_errorOccured) return 0.0; - // TODO LOG_VERBOSE(Media, "maxTimeSeekable"); - if (m_isStreaming) - return numeric_limits<float>::infinity(); // infinite duration means live stream + if (isinf(duration())) + return 0.0; + return maxTimeLoaded(); } @@ -628,29 +758,28 @@ float MediaPlayerPrivate::maxTimeLoaded() const if (m_errorOccured) return 0.0; - // TODO - LOG_VERBOSE(Media, "maxTimeLoaded"); - notImplemented(); - return duration(); + float loaded = m_maxTimeLoaded; + if (!loaded && !m_fillTimeoutId) + loaded = duration(); + LOG_VERBOSE(Media, "maxTimeLoaded: %f", loaded); + return loaded; } unsigned MediaPlayerPrivate::bytesLoaded() const { - notImplemented(); - LOG_VERBOSE(Media, "bytesLoaded"); - /*if (!m_playBin) + if (!m_playBin) return 0; - float dur = duration(); - float maxTime = maxTimeLoaded(); - if (!dur) - return 0;*/ - return 1; // totalBytes() * maxTime / dur; + if (!m_mediaDuration) + return 0; + + unsigned loaded = totalBytes() * maxTimeLoaded() / m_mediaDuration; + LOG_VERBOSE(Media, "bytesLoaded: %d", loaded); + return loaded; } unsigned MediaPlayerPrivate::totalBytes() const { - LOG_VERBOSE(Media, "totalBytes"); if (!m_source) return 0; @@ -660,6 +789,7 @@ unsigned MediaPlayerPrivate::totalBytes() const GstFormat fmt = GST_FORMAT_BYTES; gint64 length = 0; gst_element_query_duration(m_source, &fmt, &length); + LOG_VERBOSE(Media, "totalBytes %" G_GINT64_FORMAT, length); return length; } @@ -710,6 +840,7 @@ void MediaPlayerPrivate::updateStates() if (state == GST_STATE_PLAYING) { m_readyState = MediaPlayer::HaveEnoughData; m_paused = false; + m_startedPlaying = true; if (!m_mediaDuration) { float newDuration = duration(); if (!isinf(newDuration)) @@ -718,6 +849,28 @@ void MediaPlayerPrivate::updateStates() } else m_paused = true; + // Is on-disk buffering in progress? + if (m_fillTimeoutId) { + m_networkState = MediaPlayer::Loading; + // Buffering has just started, we should now have enough + // data to restart playback if it was internally paused by + // GStreamer. + if (m_paused && !m_startedPlaying) + gst_element_set_state(m_playBin, GST_STATE_PLAYING); + } + + if (maxTimeLoaded() == duration()) { + m_networkState = MediaPlayer::Loaded; + if (state == GST_STATE_READY) + m_readyState = MediaPlayer::HaveNothing; + else if (state == GST_STATE_PAUSED) + m_readyState = MediaPlayer::HaveEnoughData; + } else + if (state == GST_STATE_READY) + m_readyState = MediaPlayer::HaveNothing; + else if (m_paused) + m_readyState = currentTime() < maxTimeLoaded() ? MediaPlayer::HaveFutureData : MediaPlayer::HaveCurrentData; + if (m_changingRate) { m_player->rateChanged(); m_changingRate = false; @@ -728,14 +881,24 @@ void MediaPlayerPrivate::updateStates() m_seeking = false; } - m_networkState = MediaPlayer::Loaded; break; case GST_STATE_CHANGE_ASYNC: LOG_VERBOSE(Media, "Async: State: %s, pending: %s", gst_element_state_get_name(state), gst_element_state_get_name(pending)); // Change in progress - return; + + if (!m_isStreaming) + return; + + // Resume playback if a seek was performed in a live pipeline. + if (m_seeking) { + shouldUpdateAfterSeek = true; + m_seeking = false; + if (m_paused) + gst_element_set_state(m_playBin, GST_STATE_PLAYING); + } + break; case GST_STATE_CHANGE_FAILURE: LOG_VERBOSE(Media, "Failure: State: %s, pending: %s", gst_element_state_get_name(state), @@ -749,8 +912,25 @@ void MediaPlayerPrivate::updateStates() if (state == GST_STATE_READY) m_readyState = MediaPlayer::HaveNothing; - else if (state == GST_STATE_PAUSED) - m_readyState = MediaPlayer::HaveCurrentData; + else if (state == GST_STATE_PAUSED) { + m_readyState = MediaPlayer::HaveEnoughData; + m_paused = true; + // Live pipelines go in PAUSED without prerolling. + m_isStreaming = true; + } else if (state == GST_STATE_PLAYING) { + m_startedPlaying = true; + m_paused = false; + } + + if (m_paused && !m_startedPlaying) + gst_element_set_state(m_playBin, GST_STATE_PLAYING); + + if (m_seeking) { + shouldUpdateAfterSeek = true; + m_seeking = false; + if (m_paused) + gst_element_set_state(m_playBin, GST_STATE_PLAYING); + } m_networkState = MediaPlayer::Loading; break; @@ -898,8 +1078,11 @@ void MediaPlayerPrivate::didEnd() // not always 0. So to not confuse the HTMLMediaElement we // synchronize position and duration values. float now = currentTime(); - if (now > 0) + if (now > 0) { m_mediaDuration = now; + m_player->durationChanged(); + } + gst_element_set_state(m_playBin, GST_STATE_PAUSED); timeChanged(); @@ -1150,7 +1333,19 @@ bool MediaPlayerPrivate::supportsFullscreen() const return true; } -void MediaPlayerPrivate::createGSTPlayBin(String url) +void MediaPlayerPrivate::setAutobuffer(bool autoBuffer) +{ + ASSERT(m_playBin); + + GstPlayFlags flags; + g_object_get(m_playBin, "flags", &flags, NULL); + if (autoBuffer) + g_object_set(m_playBin, "flags", flags | GST_PLAY_FLAG_DOWNLOAD, NULL); + else + g_object_set(m_playBin, "flags", flags & ~GST_PLAY_FLAG_DOWNLOAD, NULL); +} + +void MediaPlayerPrivate::createGSTPlayBin() { ASSERT(!m_playBin); m_playBin = gst_element_factory_make("playbin2", "play"); @@ -1160,8 +1355,6 @@ void MediaPlayerPrivate::createGSTPlayBin(String url) g_signal_connect(bus, "message", G_CALLBACK(mediaPlayerPrivateMessageCallback), this); gst_object_unref(bus); - g_object_set(m_playBin, "uri", url.utf8().data(), NULL); - g_signal_connect(m_playBin, "notify::volume", G_CALLBACK(mediaPlayerPrivateVolumeChangedCallback), this); g_signal_connect(m_playBin, "notify::source", G_CALLBACK(mediaPlayerPrivateSourceChangedCallback), this); g_signal_connect(m_playBin, "notify::mute", G_CALLBACK(mediaPlayerPrivateMuteChangedCallback), this); @@ -1180,7 +1373,7 @@ void MediaPlayerPrivate::createGSTPlayBin(String url) } else { m_fpsSink = 0; g_object_set(m_playBin, "video-sink", m_videoSink, NULL); - LOG(Media, "Can't display FPS statistics, you need gst-plugins-bad >= 0.10.18"); + LOG_VERBOSE(Media, "Can't display FPS statistics, you need gst-plugins-bad >= 0.10.18"); } } else g_object_set(m_playBin, "video-sink", m_videoSink, NULL); diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h index 34257ca..e19b686 100644 --- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h +++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h @@ -2,6 +2,7 @@ * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Collabora Ltd. All rights reserved. * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * Copyright (C) 2009, 2010 Igalia S.L * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -86,6 +87,9 @@ class MediaPlayerPrivate : public MediaPlayerPrivateInterface { void muteChanged(); void muteChangedCallback(); + void setAutobuffer(bool); + bool queryBufferingStats(); + MediaPlayer::NetworkState networkState() const; MediaPlayer::ReadyState readyState() const; @@ -128,9 +132,11 @@ class MediaPlayerPrivate : public MediaPlayerPrivateInterface { float maxTimeLoaded() const; void startEndPointTimerIfNeeded(); - void createGSTPlayBin(String url); + void createGSTPlayBin(); bool changePipelineState(GstState state); + void processBufferingStats(GstMessage* message); + private: MediaPlayer* m_player; GstElement* m_playBin; @@ -157,6 +163,10 @@ class MediaPlayerPrivate : public MediaPlayerPrivateInterface { guint m_volumeIdleId; gfloat m_mediaDuration; guint m_muteIdleId; + bool m_startedBuffering; + guint m_fillTimeoutId; + float m_maxTimeLoaded; + gdouble m_fillStatus; }; } diff --git a/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.cpp b/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.cpp index 390c0ec..74a7852 100644 --- a/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.cpp +++ b/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk> + * Copyright (C) 2009, 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -79,6 +79,10 @@ struct _WebKitWebSrcPrivate { gchar* iradioGenre; gchar* iradioUrl; gchar* iradioTitle; + + // TRUE if appsrc's version is >= 0.10.27, see + // https://bugzilla.gnome.org/show_bug.cgi?id=609423 + gboolean haveAppSrc27; }; enum { @@ -109,7 +113,7 @@ static void webKitWebSrcNeedDataCb(GstAppSrc* appsrc, guint length, gpointer use static void webKitWebSrcEnoughDataCb(GstAppSrc* appsrc, gpointer userData); static gboolean webKitWebSrcSeekDataCb(GstAppSrc* appsrc, guint64 offset, gpointer userData); -static void webKitWebSrcStop(WebKitWebSrc* src, bool resetRequestedOffset); +static void webKitWebSrcStop(WebKitWebSrc* src, bool seeking); static GstAppSrcCallbacks appsrcCallbacks = { webKitWebSrcNeedDataCb, @@ -222,6 +226,9 @@ static void webkit_web_src_init(WebKitWebSrc* src, return; } + GstElementFactory* factory = GST_ELEMENT_FACTORY(GST_ELEMENT_GET_CLASS(priv->appsrc)->elementfactory); + priv->haveAppSrc27 = gst_plugin_feature_check_version(GST_PLUGIN_FEATURE(factory), 0, 10, 27); + gst_bin_add(GST_BIN(src), GST_ELEMENT(priv->appsrc)); targetpad = gst_element_get_static_pad(GST_ELEMENT(priv->appsrc), "src"); @@ -238,7 +245,20 @@ static void webkit_web_src_init(WebKitWebSrc* src, // GStreamer to handle. gst_app_src_set_max_bytes(priv->appsrc, 512 * 1024); - webKitWebSrcStop(src, true); + // Emit the need-data signal if the queue contains less + // than 20% of data. Without this the need-data signal + // is emitted when the queue is empty, we then dispatch + // the soup message unpausing to the main loop and from + // there unpause the soup message. This already takes + // quite some time and libsoup even needs some more time + // to actually provide data again. If we do all this + // already if the queue is 20% empty, it's much more + // likely that libsoup already provides new data before + // the queue is really empty. + if (priv->haveAppSrc27) + g_object_set(priv->appsrc, "min-percent", 20, NULL); + + webKitWebSrcStop(src, false); } static void webKitWebSrcFinalize(GObject* object) @@ -296,7 +316,7 @@ static void webKitWebSrcGetProperty(GObject* object, guint propID, GValue* value } -static void webKitWebSrcStop(WebKitWebSrc* src, bool resetRequestedOffset) +static void webKitWebSrcStop(WebKitWebSrc* src, bool seeking) { WebKitWebSrcPrivate* priv = src->priv; @@ -335,15 +355,19 @@ static void webKitWebSrcStop(WebKitWebSrc* src, bool resetRequestedOffset) g_free(priv->iradioTitle); priv->iradioTitle = 0; - if (priv->appsrc) + if (priv->appsrc) { gst_app_src_set_caps(priv->appsrc, 0); + if (!seeking) + gst_app_src_set_size(priv->appsrc, -1); + } priv->offset = 0; - priv->size = 0; priv->seekable = FALSE; - if (resetRequestedOffset) + if (!seeking) { + priv->size = 0; priv->requestedOffset = 0; + } GST_DEBUG_OBJECT(src, "Stopped request"); } @@ -434,7 +458,7 @@ static GstStateChangeReturn webKitWebSrcChangeState(GstElement* element, GstStat break; case GST_STATE_CHANGE_PAUSED_TO_READY: GST_DEBUG_OBJECT(src, "PAUSED->READY"); - webKitWebSrcStop(src, true); + webKitWebSrcStop(src, false); break; default: break; @@ -558,7 +582,7 @@ static void webKitWebSrcEnoughDataCb(GstAppSrc* appsrc, gpointer userData) static gboolean webKitWebSrcSeekMainCb(WebKitWebSrc* src) { - webKitWebSrcStop(src, false); + webKitWebSrcStop(src, true); webKitWebSrcStart(src); return FALSE; @@ -617,7 +641,8 @@ void StreamingClient::didReceiveResponse(ResourceHandle*, const ResourceResponse // If we seeked we need 206 == PARTIAL_CONTENT if (priv->requestedOffset && response.httpStatusCode() != 206) { GST_ELEMENT_ERROR(m_src, RESOURCE, READ, (0), (0)); - webKitWebSrcStop(m_src, true); + gst_app_src_end_of_stream(priv->appsrc); + webKitWebSrcStop(m_src, false); return; } @@ -625,6 +650,12 @@ void StreamingClient::didReceiveResponse(ResourceHandle*, const ResourceResponse if (length > 0) { length += priv->requestedOffset; gst_app_src_set_size(priv->appsrc, length); + if (!priv->haveAppSrc27) { + gst_segment_set_duration(&GST_BASE_SRC(priv->appsrc)->segment, GST_FORMAT_BYTES, length); + gst_element_post_message(GST_ELEMENT(priv->appsrc), + gst_message_new_duration(GST_OBJECT(priv->appsrc), + GST_FORMAT_BYTES, length)); + } } priv->size = length >= 0 ? length : 0; diff --git a/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.h b/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.h index 045e7d7..ae19640 100644 --- a/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.h +++ b/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk> + * Copyright (C) 2009,2010 Sebastian Dröge <sebastian.droege@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp index 99ad130..096cdbd 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp @@ -1126,31 +1126,6 @@ long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long return reinterpret_cast<long>(pointer); } -// Returned pointer must be freed by fastFree() -static bool imageToTexture(Image* image, GLubyte*& buffer, size_t& width, size_t& height) -{ - if (!image) - return false; - - CGImageRef textureImage = image->getCGImageRef(); - if (!textureImage) - return false; - - width = CGImageGetWidth(textureImage); - height = CGImageGetHeight(textureImage); - - buffer = (GLubyte*) fastMalloc(width * height * 4); - if (!buffer) - return false; - - CGContextRef textureContext = CGBitmapContextCreate(buffer, width, height, 8, width * 4, - CGImageGetColorSpace(textureImage), kCGImageAlphaPremultipliedLast); - CGContextSetBlendMode(textureContext, kCGBlendModeCopy); - CGContextDrawImage(textureContext, CGRectMake(0, 0, (CGFloat)width, (CGFloat)height), textureImage); - CGContextRelease(textureContext); - return true; -} - int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels) { // FIXME: Need to do bounds checking on the buffer here. @@ -1160,20 +1135,12 @@ int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned inte int GraphicsContext3D::texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha) { - // FIXME: need to support flipY and premultiplyAlpha - UNUSED_PARAM(flipY); - UNUSED_PARAM(premultiplyAlpha); - ASSERT(image); - ensureContext(m_contextObj); - GLubyte* buffer; - size_t width; - size_t height; - if (!imageToTexture(image, buffer, width, height)) + Vector<uint8_t> imageData; + unsigned int format, internalFormat; + if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) return -1; - - ::glTexImage2D(target, level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - fastFree(buffer); + ::glTexImage2D(target, level, internalFormat, image->width(), image->height(), 0, format, GL_UNSIGNED_BYTE, imageData.data()); return 0; } @@ -1188,20 +1155,12 @@ int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned x int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, Image* image, bool flipY, bool premultiplyAlpha) { // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size - // FIXME: need to support flipY and premultiplyAlpha - UNUSED_PARAM(flipY); - UNUSED_PARAM(premultiplyAlpha); - ASSERT(image); - ensureContext(m_contextObj); - GLubyte* buffer; - size_t width; - size_t height; - if (!imageToTexture(image, buffer, width, height)) + Vector<uint8_t> imageData; + unsigned int format, internalFormat; + if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) return -1; - - ::glTexSubImage2D(target, level, xoff, yoff, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - fastFree(buffer); + ::glTexSubImage2D(target, level, xoff, yoff, image->width(), image->height(), format, GL_UNSIGNED_BYTE, imageData.data()); return 0; } diff --git a/WebCore/platform/graphics/mac/IconMac.mm b/WebCore/platform/graphics/mac/IconMac.mm index aee7234..bc8c312 100644 --- a/WebCore/platform/graphics/mac/IconMac.mm +++ b/WebCore/platform/graphics/mac/IconMac.mm @@ -39,6 +39,7 @@ Icon::~Icon() { } +// FIXME: Move the code to ChromeClient::iconForFiles(). PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames) { if (filenames.isEmpty()) diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h index e9f64be..355aa68 100644 --- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h +++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h @@ -78,6 +78,9 @@ private: static bool isAvailable(); PlatformMedia platformMedia() const; +#if USE(ACCELERATED_COMPOSITING) + PlatformLayer* platformLayer() const; +#endif IntSize naturalSize() const; bool hasVideo() const; diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm index dd87bb5..2b90f7a 100644 --- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm +++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm @@ -445,12 +445,7 @@ void MediaPlayerPrivate::createQTMovieLayer() #ifndef NDEBUG [(CALayer *)m_qtVideoLayer.get() setName:@"Video layer"]; #endif - - // Hang the video layer from the render layer, if we have one yet. If not, we'll do this - // later via acceleratedRenderingStateChanged(). - GraphicsLayer* videoGraphicsLayer = m_player->mediaPlayerClient()->mediaPlayerGraphicsLayer(m_player); - if (videoGraphicsLayer) - videoGraphicsLayer->setContentsToMedia(m_qtVideoLayer.get()); + // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration(). } #endif } @@ -522,6 +517,11 @@ void MediaPlayerPrivate::setUpVideoRendering() createQTMovieLayer(); break; } + +#if USE(ACCELERATED_COMPOSITING) + if (currentMode == MediaRenderingMovieLayer || preferredMode == MediaRenderingMovieLayer) + m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player); +#endif } void MediaPlayerPrivate::tearDownVideoRendering() @@ -576,6 +576,13 @@ PlatformMedia MediaPlayerPrivate::platformMedia() const return plaftformMedia; } +#if USE(ACCELERATED_COMPOSITING) +PlatformLayer* MediaPlayerPrivate::platformLayer() const +{ + return m_qtVideoLayer.get(); +} +#endif + void MediaPlayerPrivate::play() { if (!metaDataAvailable()) @@ -1406,12 +1413,6 @@ void MediaPlayerPrivate::acceleratedRenderingStateChanged() { // Set up or change the rendering path if necessary. setUpVideoRendering(); - - if (currentRenderingMode() == MediaRenderingMovieLayer) { - GraphicsLayer* videoGraphicsLayer = m_player->mediaPlayerClient()->mediaPlayerGraphicsLayer(m_player); - if (videoGraphicsLayer) - videoGraphicsLayer->setContentsToMedia(m_qtVideoLayer.get()); - } } #endif diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index ef7c58f..09947d8 100644 --- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -273,37 +273,54 @@ void SimpleFontData::platformInit() } else m_xHeight = [m_platformData.font() xHeight]; } + +static CFDataRef copyFontTableForTag(FontPlatformData platformData, FourCharCode tableName) +{ +#ifdef BUILDING_ON_TIGER + ATSFontRef atsFont = FMGetATSFontRefFromFont(platformData.m_atsuFontID); + + ByteCount tableSize; + if (ATSFontGetTable(atsFont, tableName, 0, 0, NULL, &tableSize) != noErr) + return 0; + + CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, tableSize); + if (!data) + return 0; + + CFDataIncreaseLength(data, tableSize); + if (ATSFontGetTable(atsFont, tableName, 0, tableSize, CFDataGetMutableBytePtr(data), &tableSize) != noErr) { + CFRelease(data); + return 0; + } + + return data; +#else + return CGFontCopyTableForTag(platformData.cgFont(), tableName); +#endif +} void SimpleFontData::platformCharWidthInit() { - m_avgCharWidth = 0.f; - - // Calculate avgCharWidth according to http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6OS2.html - // We can try grabbing it out of the OS/2 table or via ATSFontGetHorizontalMetrics, but - // ATSFontGetHorizontalMetrics never seems to return a non-zero value and the OS/2 table - // contains zero for a large number of fonts. - GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page(); - if (glyphPageZero) { - static int weights[] = { 64, 14, 27, 35, 100, 20, 14, 42, 63, 3, 6, 35, 20, 56, 56, 17, 4, 49, 56, 71, 31, 10, 18, 3, 18, 2, 166 }; - int numGlyphs = 27; - ASSERT(numGlyphs == sizeof(weights) / sizeof(int)); - // Compute the weighted sum of the space character and the lowercase letters in the Latin alphabet. - float sum = 0.f; - int totalWeight = 0; - for (int i = 0; i < numGlyphs; i++) { - Glyph glyph = glyphPageZero->glyphDataForCharacter((i < 26 ? i + 'a' : ' ')).glyph; - if (glyph) { - totalWeight += weights[i]; - sum += widthForGlyph(glyph) * weights[i]; - } - } - if (sum > 0.f && totalWeight > 0) - m_avgCharWidth = sum / totalWeight; + m_avgCharWidth = 0; + m_maxCharWidth = 0; + + RetainPtr<CFDataRef> os2Table(AdoptCF, copyFontTableForTag(m_platformData, 'OS/2')); + if (os2Table && CFDataGetLength(os2Table.get()) >= 4) { + const UInt8* os2 = CFDataGetBytePtr(os2Table.get()); + SInt16 os2AvgCharWidth = os2[2] * 256 + os2[3]; + m_avgCharWidth = scaleEmToUnits(os2AvgCharWidth, m_unitsPerEm) * m_platformData.m_size; } - m_maxCharWidth = 0.f; - if (m_platformData.font()) - m_maxCharWidth = [m_platformData.font() maximumAdvancement].width; + RetainPtr<CFDataRef> headTable(AdoptCF, copyFontTableForTag(m_platformData, 'head')); + if (headTable && CFDataGetLength(headTable.get()) >= 42) { + const UInt8* head = CFDataGetBytePtr(headTable.get()); + ushort uxMin = head[36] * 256 + head[37]; + ushort uxMax = head[40] * 256 + head[41]; + SInt16 xMin = static_cast<SInt16>(uxMin); + SInt16 xMax = static_cast<SInt16>(uxMax); + float diff = static_cast<float>(xMax - xMin); + m_maxCharWidth = scaleEmToUnits(diff, m_unitsPerEm) * m_platformData.m_size; + } // Fallback to a cross-platform estimate, which will populate these values if they are non-positive. initCharWidths(); diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 105d866..8bcda2e 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -219,6 +219,7 @@ public: QStack<TransparencyLayer*> layers; QPainter* redirect; + // reuse this brush for solid color (to prevent expensive QBrush construction) QBrush solidColor; InterpolationQuality imageInterpolationQuality; @@ -760,11 +761,30 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint&, int, b FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect) { - QRectF rect(frect); - rect = m_data->p()->deviceMatrix().mapRect(rect); + // It is not enough just to round to pixels in device space. The rotation part of the + // affine transform matrix to device space can mess with this conversion if we have a + // rotating image like the hands of the world clock widget. We just need the scale, so + // we get the affine transform matrix and extract the scale. + QPainter* painter = platformContext(); + QTransform deviceTransform = painter->deviceTransform(); + if (deviceTransform.isIdentity()) + return frect; - QRect result = rect.toRect(); //round it - return FloatRect(QRectF(result)); + qreal deviceScaleX = sqrtf(deviceTransform.m11() * deviceTransform.m11() + deviceTransform.m12() * deviceTransform.m12()); + qreal deviceScaleY = sqrtf(deviceTransform.m21() * deviceTransform.m21() + deviceTransform.m22() * deviceTransform.m22()); + + QPoint deviceOrigin(frect.x() * deviceScaleX, frect.y() * deviceScaleY); + QPoint deviceLowerRight(frect.right() * deviceScaleX, frect.bottom() * deviceScaleY); + + // Don't let the height or width round to 0 unless either was originally 0 + if (deviceOrigin.y() == deviceLowerRight.y() && frect.height()) + deviceLowerRight.setY(deviceLowerRight.y() + 1); + if (deviceOrigin.x() == deviceLowerRight.x() && frect.width()) + deviceLowerRight.setX(deviceLowerRight.x() + 1); + + FloatPoint roundedOrigin = FloatPoint(deviceOrigin.x() / deviceScaleX, deviceOrigin.y() / deviceScaleY); + FloatPoint roundedLowerRight = FloatPoint(deviceLowerRight.x() / deviceScaleX, deviceLowerRight.y() / deviceScaleY); + return FloatRect(roundedOrigin, roundedLowerRight - roundedOrigin); } void GraphicsContext::setPlatformShadow(const IntSize& size, int, const Color&, ColorSpace) @@ -1112,7 +1132,8 @@ void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colo return; QPainter* p = m_data->p(); QPen newPen(p->pen()); - newPen.setColor(color); + m_data->solidColor.setColor(color); + newPen.setBrush(m_data->solidColor); p->setPen(newPen); } diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp index 11f7384..0fd0f1a 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp @@ -136,7 +136,9 @@ public: virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*); // we manage transforms ourselves because transform-origin acts differently in webkit and in Qt - void setBaseTransform(const QTransform&); + void setBaseTransform(const TransformationMatrix&); + QTransform computeTransform(const TransformationMatrix& baseTransform) const; + void updateTransform(); // let the compositor-API tell us which properties were changed void notifyChange(ChangeMask); @@ -145,7 +147,7 @@ public: // this is called indirectly from ChromeClientQt::setNeedsOneShotDrawingSynchronization // (meaning the sync would happen together with the next draw) // or ChromeClientQt::scheduleCompositingLayerSync (meaning the sync will happen ASAP) - void flushChanges(bool recursive = true); + void flushChanges(bool recursive = true, bool forceTransformUpdate = false); // optimization: when we have an animation running on an element with no contents, that has child-elements with contents, // ALL of them have to have ItemCoordinateCache and not DeviceCoordinateCache @@ -166,7 +168,7 @@ signals: public: GraphicsLayerQt* m_layer; - QTransform m_baseTransform; + TransformationMatrix m_baseTransform; bool m_transformAnimationRunning; bool m_opacityAnimationRunning; QWeakPointer<MaskEffectQt> m_maskEffect; @@ -237,7 +239,10 @@ GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer) { // we use graphics-view for compositing, not for interactivity setAcceptedMouseButtons(Qt::NoButton); - setEnabled(false); + // we need to have the item enabled, or else wheel events are not + // passed to the parent class implementation of wheelEvent, where + // they are ignored and passed to the item below. + setEnabled(true); // we'll set the cache when we know what's going on setCacheMode(NoCache); @@ -280,18 +285,54 @@ void GraphicsLayerQtImpl::adjustCachingRecursively(bool animationIsRunning) } } -void GraphicsLayerQtImpl::setBaseTransform(const QTransform& transform) +void GraphicsLayerQtImpl::updateTransform() +{ + setBaseTransform(isTransformAnimationRunning() ? m_baseTransform : m_layer->transform()); +} + +void GraphicsLayerQtImpl::setBaseTransform(const TransformationMatrix& baseTransform) +{ + m_baseTransform = baseTransform; + setTransform(computeTransform(baseTransform)); +} + +QTransform GraphicsLayerQtImpl::computeTransform(const TransformationMatrix& baseTransform) const { if (!m_layer) - return; + return baseTransform; + + TransformationMatrix computedTransform; + + // The origin for childrenTransform is always the center of the ancestor which contains the childrenTransform. + // this has to do with how WebCore implements -webkit-perspective and -webkit-perspective-origin, which are the CSS + // attribute that call setChildrenTransform + QPointF offset = -pos() - boundingRect().bottomRight() / 2; + const GraphicsLayerQtImpl* ancestor = this; + while ((ancestor = qobject_cast<GraphicsLayerQtImpl*>(ancestor->parentObject()))) { + if (!ancestor->m_state.childrenTransform.isIdentity()) { + offset += ancestor->boundingRect().bottomRight() / 2; + computedTransform + .translate(offset.x(), offset.y()) + .multLeft(ancestor->m_state.childrenTransform) + .translate(-offset.x(), -offset.y()); + break; + } + offset -= ancestor->pos(); + } + + computedTransform.multLeft(baseTransform); + // webkit has relative-to-size originPoint, graphics-view has a pixel originPoint, here we convert // we have to manage this ourselves because QGraphicsView's transformOrigin is incompatible - const qreal x = m_layer->anchorPoint().x() * m_layer->size().width(); - const qreal y = m_layer->anchorPoint().y() * m_layer->size().height(); - setTransform(QTransform::fromTranslate(x, y)); - setTransform(transform, true); - translate(-x, -y); - m_baseTransform = transform; + const qreal originX = m_state.anchorPoint.x() * m_size.width(); + const qreal originY = m_state.anchorPoint.y() * m_size.height(); + computedTransform = TransformationMatrix() + .translate(originX, originY) + .multiply(computedTransform) + .translate(-originX, -originY); + + // now we project to 2D + return QTransform(computedTransform); } bool GraphicsLayerQtImpl::isTransformAnimationRunning() const @@ -357,7 +398,7 @@ void GraphicsLayerQtImpl::notifyChange(ChangeMask changeMask) m_layer->client()->notifySyncRequired(m_layer); } -void GraphicsLayerQtImpl::flushChanges(bool recursive) +void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform) { // this is the bulk of the work. understanding what the compositor is trying to achieve, // what graphics-view can do, and trying to find a sane common-grounds @@ -425,12 +466,15 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive) } } - if (m_changeMask & (TransformChange | AnchorPointChange | SizeChange)) { - // since we convert a percentage-based origin-point to a pixel-based one, - // the anchor-point, transform and size from WebCore all affect the one - // that we give Qt - if (m_state.transform != m_layer->transform() || m_state.anchorPoint != m_layer->anchorPoint() || m_state.size != m_layer->size()) - setBaseTransform(m_layer->transform()); + // FIXME: this is a hack, due to a probable QGraphicsScene bug when rapidly modifying the perspective + // but without this line we get graphic artifacts + if ((m_changeMask & ChildrenTransformChange) && m_state.childrenTransform != m_layer->childrenTransform()) + scene()->update(); + + if (m_changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange)) { + // due to the differences between the way WebCore handles transforms and the way Qt handles transforms, + // all these elements affect the transforms of all the descendants. + forceUpdateTransform = true; } if (m_changeMask & (ContentChange | DrawsContentChange | MaskLayerChange)) { @@ -439,8 +483,6 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive) update(); setFlag(ItemHasNoContents, false); - // we only use ItemUsesExtendedStyleOption for HTML content - pixmap can be handled better with regular clipping - setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false); break; case ColorContentType: @@ -524,6 +566,7 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive) m_state.drawsContent = m_layer->drawsContent(); m_state.contentsOpaque = m_layer->contentsOpaque(); m_state.backfaceVisibility = m_layer->backfaceVisibility(); + m_state.childrenTransform = m_layer->childrenTransform(); m_currentContent.pixmap = m_pendingContent.pixmap; m_currentContent.contentType = m_pendingContent.contentType; m_currentContent.backgroundColor = m_pendingContent.backgroundColor; @@ -534,6 +577,9 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive) afterLayerChanges: + if (forceUpdateTransform) + updateTransform(); + if (!recursive) return; @@ -544,7 +590,7 @@ afterLayerChanges: for (QList<QGraphicsItem*>::const_iterator it = children.begin(); it != children.end(); ++it) { if (QGraphicsItem* item = *it) if (GraphicsLayerQtImpl* layer = qobject_cast<GraphicsLayerQtImpl*>(item->toGraphicsObject())) - layer->flushChanges(true); + layer->flushChanges(true, forceUpdateTransform); } } @@ -1013,7 +1059,7 @@ public: // this came up during the compositing/animation LayoutTests // when the animation dies, the transform has to go back to default if (m_layer) - m_layer.data()->setBaseTransform(m_layer.data()->m_layer->transform()); + m_layer.data()->updateTransform(); } // the idea is that we let WebCore manage the transform-operations diff --git a/WebCore/platform/graphics/qt/IconQt.cpp b/WebCore/platform/graphics/qt/IconQt.cpp index a9870fc..eb09eda 100644 --- a/WebCore/platform/graphics/qt/IconQt.cpp +++ b/WebCore/platform/graphics/qt/IconQt.cpp @@ -40,6 +40,7 @@ Icon::~Icon() { } +// FIXME: Move the code to ChromeClient::iconForFiles(). PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames) { if (filenames.isEmpty()) diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp index 234f78b..18e7f08 100644 --- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp +++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp @@ -102,7 +102,7 @@ size_t ImageDecoderQt::frameCount() // Fixup for Qt decoders... imageCount() is wrong // and jumpToNextImage does not work either... so // we will have to parse everything... - if (imageCount == 0) + if (!imageCount) forceLoadEverything(); else m_frameBufferCache.resize(imageCount); @@ -132,13 +132,13 @@ RGBA32Buffer* ImageDecoderQt::frameBufferAtIndex(size_t index) // In case the ImageDecoderQt got recreated we don't know // yet how many images we are going to have and need to // find that out now. - int count = m_frameBufferCache.size(); - if (!m_failed && count == 0) { + size_t count = m_frameBufferCache.size(); + if (!m_failed && !count) { internalDecodeSize(); count = frameCount(); } - if (index >= static_cast<size_t>(count)) + if (index >= count) return 0; RGBA32Buffer& frame = m_frameBufferCache[index]; @@ -215,7 +215,7 @@ void ImageDecoderQt::forceLoadEverything() do { m_frameBufferCache.resize(++imageCount); internalHandleCurrentImage(imageCount - 1); - } while(!m_failed); + } while (!m_failed); // If we failed decoding the first image we actually // have no images and need to keep m_failed set to diff --git a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp new file mode 100644 index 0000000..cd86e6d --- /dev/null +++ b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(3D_CANVAS) + +#include "GraphicsContext3D.h" + +#include "Image.h" +#include "NativeImageSkia.h" + +namespace WebCore { + +bool GraphicsContext3D::getImageData(Image* image, + Vector<uint8_t>& outputVector, + bool premultiplyAlpha, + bool* hasAlphaChannel, + AlphaOp* neededAlphaOp, + unsigned int* format) +{ + if (!image) + return false; + NativeImageSkia* skiaImage = image->nativeImageForCurrentFrame(); + if (!skiaImage) + return false; + SkBitmap::Config skiaConfig = skiaImage->config(); + // FIXME: must support more image configurations. + if (skiaConfig != SkBitmap::kARGB_8888_Config) + return false; + SkBitmap& skiaImageRef = *skiaImage; + SkAutoLockPixels lock(skiaImageRef); + int width = skiaImage->width(); + int height = skiaImage->height(); + int rowBytes = skiaImage->rowBytes(); + ASSERT(rowBytes == width * 4); + uint8_t* pixels = reinterpret_cast<uint8_t*>(skiaImage->getPixels()); + outputVector.resize(rowBytes * height); + memcpy(outputVector.data(), pixels, rowBytes * height); + *hasAlphaChannel = true; + if (!premultiplyAlpha) + // FIXME: must fetch the image data before the premultiplication step + *neededAlphaOp = kAlphaDoUnmultiply; + // FIXME: remove this dependency on desktop OpenGL + *format = 0x80E1; // GL_BGRA + return true; +} + +} // namespace WebCore + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index 92a1870..e0f6f5d 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp @@ -344,15 +344,6 @@ void PlatformContextSkia::setupPaintForFilling(SkPaint* paint) const paint->setShader(m_state->m_fillShader); } -static SkScalar scalarBound(SkScalar v, SkScalar min, SkScalar max) -{ - if (v < min) - return min; - if (v > max) - return max; - return v; -} - float PlatformContextSkia::setupPaintForStroking(SkPaint* paint, SkRect* rect, int length) const { setupPaintCommon(paint); @@ -361,13 +352,10 @@ float PlatformContextSkia::setupPaintForStroking(SkPaint* paint, SkRect* rect, i paint->setColor(m_state->applyAlpha(m_state->m_strokeColor)); paint->setShader(m_state->m_strokeShader); paint->setStyle(SkPaint::kStroke_Style); - // The limits here (512 and 256) were made up but are hopefully large - // enough to be reasonable. They are, empirically, small enough not to - // cause overflows in Skia. - paint->setStrokeWidth(scalarBound(SkFloatToScalar(width), 0, 512)); + paint->setStrokeWidth(SkFloatToScalar(width)); paint->setStrokeCap(m_state->m_lineCap); paint->setStrokeJoin(m_state->m_lineJoin); - paint->setStrokeMiter(scalarBound(SkFloatToScalar(m_state->m_miterLimit), 0, 256)); + paint->setStrokeMiter(SkFloatToScalar(m_state->m_miterLimit)); if (m_state->m_dash) paint->setPathEffect(m_state->m_dash); diff --git a/WebCore/platform/graphics/win/IconWin.cpp b/WebCore/platform/graphics/win/IconWin.cpp index 56b46de..cc9343a 100644 --- a/WebCore/platform/graphics/win/IconWin.cpp +++ b/WebCore/platform/graphics/win/IconWin.cpp @@ -47,6 +47,7 @@ Icon::~Icon() DestroyIcon(m_hIcon); } +// FIXME: Move the code to ChromeClient::iconForFiles(). PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames) { if (filenames.isEmpty()) diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp index b2fe069..1df73a7 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp @@ -108,6 +108,13 @@ PlatformMedia MediaPlayerPrivate::platformMedia() const return p; } +#if USE(ACCELERATED_COMPOSITING) +PlatformLayer* MediaPlayerPrivate::platformLayer() const +{ + return m_qtVideoLayer->platformLayer(); +} +#endif + class TaskTimer : TimerBase { public: static void initialize(); @@ -745,6 +752,11 @@ void MediaPlayerPrivate::setUpVideoRendering() if (preferredMode == MediaRenderingMovieLayer) createLayerForMovie(); + +#if USE(ACCELERATED_COMPOSITING) + if (currentMode == MediaRenderingMovieLayer || preferredMode == MediaRenderingMovieLayer) + m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player); +#endif } void MediaPlayerPrivate::tearDownVideoRendering() @@ -810,11 +822,6 @@ void MediaPlayerPrivate::createLayerForMovie() if (!m_qtMovie || m_qtVideoLayer) return; - // Do nothing if the parent layer hasn't been set up yet. - GraphicsLayer* videoGraphicsLayer = m_player->mediaPlayerClient()->mediaPlayerGraphicsLayer(m_player); - if (!videoGraphicsLayer) - return; - // Create a GraphicsLayer that won't be inserted directly into the render tree, but will used // as a wrapper for a WKCACFLayer which gets inserted as the content layer of the video // renderer's GraphicsLayer. @@ -829,9 +836,7 @@ void MediaPlayerPrivate::createLayerForMovie() #ifndef NDEBUG m_qtVideoLayer->setName("Video layer"); #endif - - // Hang the video layer from the render layer. - videoGraphicsLayer->setContentsToMedia(m_qtVideoLayer->platformLayer()); + // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration(). #endif } @@ -858,7 +863,7 @@ void MediaPlayerPrivate::acceleratedRenderingStateChanged() void MediaPlayerPrivate::notifySyncRequired(const GraphicsLayer*) { - GraphicsLayerCACF* videoGraphicsLayer = static_cast<GraphicsLayerCACF*>(m_player->mediaPlayerClient()->mediaPlayerGraphicsLayer(m_player)); + GraphicsLayerCACF* videoGraphicsLayer = static_cast<GraphicsLayerCACF*>(m_qtVideoLayer.get()); if (videoGraphicsLayer) videoGraphicsLayer->notifySyncRequired(); } diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h index d58f44f..029a520 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h @@ -76,6 +76,9 @@ private: virtual bool supportsFullscreen() const; virtual PlatformMedia platformMedia() const; +#if USE(ACCELERATED_COMPOSITING) + PlatformLayer* platformLayer() const; +#endif IntSize naturalSize() const; bool hasVideo() const; diff --git a/WebCore/platform/gtk/PasteboardGtk.cpp b/WebCore/platform/gtk/PasteboardGtk.cpp index 0b4d356..5c7d9a7 100644 --- a/WebCore/platform/gtk/PasteboardGtk.cpp +++ b/WebCore/platform/gtk/PasteboardGtk.cpp @@ -134,7 +134,8 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String&) ASSERT(node && node->renderer() && node->renderer()->isImage()); RenderImage* renderer = toRenderImage(node->renderer()); CachedImage* cachedImage = renderer->cachedImage(); - ASSERT(cachedImage); + if (!cachedImage || cachedImage->errorOccurred()) + return; Image* image = cachedImage->image(); ASSERT(image); diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp index 727788a..e19e2fa 100644 --- a/WebCore/platform/gtk/RenderThemeGtk.cpp +++ b/WebCore/platform/gtk/RenderThemeGtk.cpp @@ -27,9 +27,11 @@ #include "AffineTransform.h" #include "CString.h" #include "GOwnPtr.h" +#include "Gradient.h" #include "GraphicsContext.h" #include "HTMLMediaElement.h" #include "HTMLNames.h" +#include "MediaControlElements.h" #include "NotImplemented.h" #include "RenderBox.h" #include "RenderObject.h" @@ -686,9 +688,46 @@ bool RenderThemeGtk::paintMediaSeekForwardButton(RenderObject* o, const RenderOb bool RenderThemeGtk::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { - paintInfo.context->fillRect(FloatRect(r), m_panelColor, DeviceColorSpace); - paintInfo.context->fillRect(FloatRect(IntRect(r.x(), r.y() + (r.height() - m_mediaSliderHeight) / 2, - r.width(), m_mediaSliderHeight)), m_sliderColor, DeviceColorSpace); + GraphicsContext* context = paintInfo.context; + + context->fillRect(FloatRect(r), m_panelColor, DeviceColorSpace); + context->fillRect(FloatRect(IntRect(r.x(), r.y() + (r.height() - m_mediaSliderHeight) / 2, + r.width(), m_mediaSliderHeight)), m_sliderColor, DeviceColorSpace); + + RenderStyle* style = o->style(); + HTMLMediaElement* mediaElement = toParentMediaElement(o); + + if (!mediaElement) + return false; + + // Draw the buffered ranges. This code is highly inspired from + // Chrome. + // FIXME: Draw multiple ranges if there are multiple buffered + // ranges. The current implementation of the player is always + // buffering a single range anyway. + IntRect bufferedRect = r; + bufferedRect.inflate(-style->borderLeftWidth()); + bufferedRect.setWidth((bufferedRect.width() * mediaElement->percentLoaded())); + + // Don't bother drawing an empty area. + if (bufferedRect.isEmpty()) + return false; + + IntPoint sliderTopLeft = bufferedRect.location(); + IntPoint sliderTopRight = sliderTopLeft; + sliderTopRight.move(0, bufferedRect.height()); + + RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderTopRight); + Color startColor = m_panelColor; + gradient->addColorStop(0.0, startColor); + gradient->addColorStop(1.0, Color(startColor.red() / 2, startColor.green() / 2, startColor.blue() / 2, startColor.alpha())); + + context->save(); + context->setStrokeStyle(NoStroke); + context->setFillGradient(gradient); + context->fillRect(bufferedRect); + context->restore(); + return false; } diff --git a/WebCore/platform/gtk/WidgetGtk.cpp b/WebCore/platform/gtk/WidgetGtk.cpp index 53c10f1..834c21a 100644 --- a/WebCore/platform/gtk/WidgetGtk.cpp +++ b/WebCore/platform/gtk/WidgetGtk.cpp @@ -82,16 +82,18 @@ void Widget::setCursor(const Cursor& cursor) void Widget::show() { - if (!platformWidget()) - return; - gtk_widget_show(platformWidget()); + setSelfVisible(true); + + if (isParentVisible() && platformWidget()) + gtk_widget_show(platformWidget()); } void Widget::hide() { - if (!platformWidget()) - return; - gtk_widget_hide(platformWidget()); + setSelfVisible(false); + + if (isParentVisible() && platformWidget()) + gtk_widget_hide(platformWidget()); } void Widget::paint(GraphicsContext* context, const IntRect& rect) diff --git a/WebCore/platform/haiku/FileSystemHaiku.cpp b/WebCore/platform/haiku/FileSystemHaiku.cpp index 7400cd1..3d9161a 100644 --- a/WebCore/platform/haiku/FileSystemHaiku.cpp +++ b/WebCore/platform/haiku/FileSystemHaiku.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * All rights reserved. * @@ -29,9 +30,14 @@ #include "FileSystem.h" #include "CString.h" +#include "NotImplemented.h" #include "PlatformString.h" -#include "NotImplemented.h" +#include <Directory.h> +#include <Entry.h> +#include <File.h> +#include <FindDirectory.h> +#include <Path.h> namespace WebCore { @@ -43,8 +49,11 @@ CString fileSystemRepresentation(const String& string) String homeDirectoryPath() { - notImplemented(); - return String(); + BPath path; + if (find_directory(B_USER_DIRECTORY, &path) != B_OK) + return String(); + + return String(path.Path()); } CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle) @@ -74,7 +83,10 @@ bool unloadModule(PlatformModule) Vector<String> listDirectory(const String& path, const String& filter) { Vector<String> entries; - notImplemented(); + BDirectory directory(path.utf8().data()); + entry_ref ref; + while (directory.GetNextRef(&ref) == B_OK) + entries.append(ref.name); return entries; } diff --git a/WebCore/platform/image-decoders/ImageDecoder.cpp b/WebCore/platform/image-decoders/ImageDecoder.cpp index ed13048..86bcb45 100644 --- a/WebCore/platform/image-decoders/ImageDecoder.cpp +++ b/WebCore/platform/image-decoders/ImageDecoder.cpp @@ -58,30 +58,24 @@ static unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const // TODO: Find a better fix. ImageDecoder* ImageDecoder::create(const SharedBuffer& data) { - // We need at least 4 bytes to figure out what kind of image we're dealing with. + // We need at least 4 bytes to figure out what kind of image we're dealing + // with. static const unsigned maxMarkerLength = 4; char contents[maxMarkerLength]; unsigned length = copyFromSharedBuffer(contents, maxMarkerLength, data, 0); if (length < maxMarkerLength) return 0; - const unsigned char* uContents = reinterpret_cast<const unsigned char*>(contents); - // GIFs begin with GIF8(7 or 9). if (strncmp(contents, "GIF8", 4) == 0) return new GIFImageDecoder(); // Test for PNG. - if (uContents[0]==0x89 && - uContents[1]==0x50 && - uContents[2]==0x4E && - uContents[3]==0x47) + if (!memcmp(contents, "\x89\x50\x4E\x47", 4)) return new PNGImageDecoder(); // JPEG - if (uContents[0]==0xFF && - uContents[1]==0xD8 && - uContents[2]==0xFF) + if (!memcmp(contents, "\xFF\xD8\xFF", 3)) return new JPEGImageDecoder(); // BMP @@ -90,8 +84,7 @@ ImageDecoder* ImageDecoder::create(const SharedBuffer& data) // ICOs always begin with a 2-byte 0 followed by a 2-byte 1. // CURs begin with 2-byte 0 followed by 2-byte 2. - if (!memcmp(contents, "\000\000\001\000", 4) || - !memcmp(contents, "\000\000\002\000", 4)) + if (!memcmp(contents, "\x00\x00\x01\x00", 4) || !memcmp(contents, "\x00\x00\x02\x00", 4)) return new ICOImageDecoder(); // Give up. We don't know what the heck this is. @@ -109,14 +102,27 @@ RGBA32Buffer::RGBA32Buffer() { } +RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other) +{ + if (this == &other) + return *this; + + copyBitmapData(other); + setRect(other.rect()); + setStatus(other.status()); + setDuration(other.duration()); + setDisposalMethod(other.disposalMethod()); + return *this; +} + void RGBA32Buffer::clear() { m_bytes.clear(); m_status = FrameEmpty; - // NOTE: Do not reset other members here; clearFrameBufferCache() - // calls this to free the bitmap data, but other functions like - // initFrameBuffer() and frameComplete() may still need to read - // other metadata out of this frame later. + // NOTE: Do not reset other members here; clearFrameBufferCache() calls this + // to free the bitmap data, but other functions like initFrameBuffer() and + // frameComplete() may still need to read other metadata out of this frame + // later. } void RGBA32Buffer::zeroFill() @@ -137,8 +143,8 @@ void RGBA32Buffer::copyBitmapData(const RGBA32Buffer& other) bool RGBA32Buffer::setSize(int newWidth, int newHeight) { - // NOTE: This has no way to check for allocation failure if the - // requested size was too big... + // NOTE: This has no way to check for allocation failure if the requested + // size was too big... m_bytes.resize(newWidth * newHeight); m_size = IntSize(newWidth, newHeight); @@ -163,19 +169,6 @@ void RGBA32Buffer::setStatus(FrameStatus status) m_status = status; } -RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other) -{ - if (this == &other) - return *this; - - copyBitmapData(other); - setRect(other.rect()); - setStatus(other.status()); - setDuration(other.duration()); - setDisposalMethod(other.disposalMethod()); - return *this; -} - int RGBA32Buffer::width() const { return m_size.width(); @@ -200,13 +193,11 @@ inline void fillScaledValues(Vector<int>& scaledValues, double scaleRate, int le { double inflateRate = 1. / scaleRate; scaledValues.reserveCapacity(static_cast<int>(length * scaleRate + 0.5)); - for (int scaledIndex = 0;;) { + for (int scaledIndex = 0; ; ++scaledIndex) { int index = static_cast<int>(scaledIndex * inflateRate + 0.5); - if (index < length) { - scaledValues.append(index); - ++scaledIndex; - } else + if (index >= length) break; + scaledValues.append(index); } } diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h index 8d27072..002395b 100644 --- a/WebCore/platform/image-decoders/ImageDecoder.h +++ b/WebCore/platform/image-decoders/ImageDecoder.h @@ -46,18 +46,21 @@ namespace WebCore { - // The RGBA32Buffer object represents the decoded image data in RGBA32 format. This buffer is what all - // decoders write a single frame into. Frames are then instantiated for drawing by being handed this buffer. + // The RGBA32Buffer object represents the decoded image data in RGBA32 + // format. This buffer is what all decoders write a single frame into. + // Frames are then instantiated for drawing by being handed this buffer. class RGBA32Buffer { public: enum FrameStatus { FrameEmpty, FramePartial, FrameComplete }; enum FrameDisposalMethod { - // If you change the numeric values of these, make sure you audit all - // users, as some users may cast raw values to/from these constants. - DisposeNotSpecified, // Leave frame in framebuffer - DisposeKeep, // Leave frame in framebuffer - DisposeOverwriteBgcolor, // Clear frame to transparent - DisposeOverwritePrevious, // Clear frame to previous framebuffer contents + // If you change the numeric values of these, make sure you audit + // all users, as some users may cast raw values to/from these + // constants. + DisposeNotSpecified, // Leave frame in framebuffer + DisposeKeep, // Leave frame in framebuffer + DisposeOverwriteBgcolor, // Clear frame to transparent + DisposeOverwritePrevious, // Clear frame to previous framebuffer + // contents }; #if PLATFORM(SKIA) || PLATFORM(QT) typedef uint32_t PixelData; @@ -67,15 +70,11 @@ namespace WebCore { RGBA32Buffer(); - // For backends which refcount their data, this constructor doesn't need - // to create a new copy of the image data, only increase the ref count. - // - // This exists because ImageDecoder keeps a Vector<RGBA32Buffer>, and - // Vector requires this constructor. - RGBA32Buffer(const RGBA32Buffer& other) - { - operator=(other); - } + RGBA32Buffer(const RGBA32Buffer& other) { operator=(other); } + + // For backends which refcount their data, this operator doesn't need to + // create a new copy of the image data, only increase the ref count. + RGBA32Buffer& operator=(const RGBA32Buffer& other); // Deletes the pixel data entirely; used by ImageDecoder to save memory // when we no longer need to display a frame and only need its metadata. @@ -142,8 +141,6 @@ namespace WebCore { #endif private: - RGBA32Buffer& operator=(const RGBA32Buffer& other); - int width() const; int height() const; @@ -188,26 +185,33 @@ namespace WebCore { Vector<PixelData> m_bytes; IntSize m_size; // The size of the buffer. This should be the // same as ImageDecoder::m_size. - bool m_hasAlpha; // Whether or not any of the pixels in the buffer have transparency. + bool m_hasAlpha; // Whether or not any of the pixels in the buffer + // have transparency. #endif - IntRect m_rect; // The rect of the original specified frame within the overall buffer. - // This will always just be the entire buffer except for GIF frames - // whose original rect was smaller than the overall image size. - FrameStatus m_status; // Whether or not this frame is completely finished decoding. + IntRect m_rect; // The rect of the original specified frame within + // the overall buffer. This will always just be + // the entire buffer except for GIF frames whose + // original rect was smaller than the overall + // image size. + FrameStatus m_status; // Whether or not this frame is completely + // finished decoding. unsigned m_duration; // The animation delay. FrameDisposalMethod m_disposalMethod; - // What to do with this frame's data when initializing the next frame. + // What to do with this frame's data when + // initializing the next frame. }; - // The ImageDecoder class represents a base class for specific image format decoders - // (e.g., GIF, JPG, PNG, ICO) to derive from. All decoders decode into RGBA32 format - // and the base class manages the RGBA32 frame cache. + // The ImageDecoder class represents a base class for specific image format + // decoders (e.g., GIF, JPG, PNG, ICO) to derive from. All decoders decode + // into RGBA32 format and the base class manages the RGBA32 frame cache. + // + // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to write + // directly to scaled output buffers by down sampling. Call + // setMaxNumPixels() to specify the biggest size that decoded images can + // have. Image decoders will deflate those images that are bigger than + // m_maxNumPixels. (Not supported by all image decoders yet) class ImageDecoder : public Noncopyable { public: - // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to write directly to - // scaled output buffers by down sampling. Call setMaxNumPixels() to specify the - // biggest size that decoded images can have. Image decoders will deflate those - // images that are bigger than m_maxNumPixels. (Not supported by all image decoders yet) ImageDecoder() : m_scaled(false) , m_failed(false) @@ -224,21 +228,22 @@ namespace WebCore { // needing to write a dedicated setData() implementation. static ImageDecoder* create(const SharedBuffer& data); - // The the filename extension usually associated with an undecoded image of this type. + // The the filename extension usually associated with an undecoded image + // of this type. virtual String filenameExtension() const = 0; - // All specific decoder plugins must do something with the data they are given. bool isAllDataReceived() const { return m_isAllDataReceived; } + virtual void setData(SharedBuffer* data, bool allDataReceived) { m_data = data; m_isAllDataReceived = allDataReceived; } - // Whether or not the size information has been decoded yet. This default - // implementation just returns true if the size has been set and we have not - // seen a failure. Decoders may want to override this to lazily decode - // enough of the image to get the size. + // Whether or not the size information has been decoded yet. This + // default implementation just returns true if the size has been set and + // we have not seen a failure. Decoders may want to override this to + // lazily decode enough of the image to get the size. virtual bool isSizeAvailable() { return !m_failed && m_sizeAvailable; @@ -266,10 +271,10 @@ namespace WebCore { return size(); } - // Called by the image decoders to set their decoded size, this also check - // the size for validity. It will return true if the size was set, or false - // if there is an error. On error, the m_failed flag will be set and the - // caller should immediately stop decoding. + // Called by the image decoders to set their decoded size, this also + // checks the size for validity. It will return true if the size was + // set, or false if there is an error. On error, the m_failed flag will + // be set and the caller should immediately stop decoding. virtual bool setSize(unsigned width, unsigned height) { if (isOverSize(width, height)) { @@ -281,29 +286,30 @@ namespace WebCore { return true; } - // The total number of frames for the image. Classes that support multiple frames - // will scan the image data for the answer if they need to (without necessarily - // decoding all of the individual frames). + // The total number of frames for the image. Classes that support + // multiple frames will scan the image data for the answer if they need + // to (without necessarily decoding all of the individual frames). virtual size_t frameCount() { return 1; } // The number of repetitions to perform for an animation loop. virtual int repetitionCount() const { return cAnimationNone; } - // Called to obtain the RGBA32Buffer full of decoded data for rendering. The - // decoder plugin will decode as much of the frame as it can before handing - // back the buffer. + // Called to obtain the RGBA32Buffer full of decoded data for rendering. + // The decoder plugin will decode as much of the frame as it can before + // handing back the buffer. virtual RGBA32Buffer* frameBufferAtIndex(size_t) = 0; - // Whether or not the underlying image format even supports alpha transparency. + // Whether or not the underlying image format even supports alpha + // transparency. virtual bool supportsAlpha() const { return true; } bool failed() const { return m_failed; } void setFailed() { m_failed = true; } // Wipe out frames in the frame buffer cache before |clearBeforeFrame|, - // assuming this can be done without breaking decoding. Different decoders - // place different restrictions on what frames are safe to destroy, so this - // is left to them to implement. + // assuming this can be done without breaking decoding. Different + // decoders place different restrictions on what frames are safe to + // destroy, so this is left to them to implement. // For convenience's sake, we provide a default (empty) implementation, // since in practice only GIFs will ever use this. virtual void clearFrameBufferCache(size_t clearBeforeFrame) { } diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp index de0690f..fb9f9f2 100644 --- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp +++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp @@ -41,9 +41,7 @@ namespace WebCore { static const size_t sizeOfFileHeader = 14; BMPImageDecoder::BMPImageDecoder() - : ImageDecoder() - , m_allDataReceived(false) - , m_decodedOffset(0) + : m_decodedOffset(0) { } @@ -53,7 +51,6 @@ void BMPImageDecoder::setData(SharedBuffer* data, bool allDataReceived) return; ImageDecoder::setData(data, allDataReceived); - m_allDataReceived = allDataReceived; if (m_reader) m_reader->setData(data); } @@ -61,7 +58,7 @@ void BMPImageDecoder::setData(SharedBuffer* data, bool allDataReceived) bool BMPImageDecoder::isSizeAvailable() { if (!ImageDecoder::isSizeAvailable() && !failed()) - decodeWithCheckForDataEnded(true); + decode(true); return ImageDecoder::isSizeAvailable(); } @@ -76,31 +73,29 @@ RGBA32Buffer* BMPImageDecoder::frameBufferAtIndex(size_t index) RGBA32Buffer* buffer = &m_frameBufferCache.first(); if (buffer->status() != RGBA32Buffer::FrameComplete && !failed()) - decodeWithCheckForDataEnded(false); + decode(false); return buffer; } -void BMPImageDecoder::decodeWithCheckForDataEnded(bool onlySize) +void BMPImageDecoder::decode(bool onlySize) { if (failed()) return; // If we couldn't decode the image but we've received all the data, decoding // has failed. - if (!decode(onlySize) && m_allDataReceived) + if (!decodeHelper(onlySize) && isAllDataReceived()) setFailed(); } -bool BMPImageDecoder::decode(bool onlySize) +bool BMPImageDecoder::decodeHelper(bool onlySize) { size_t imgDataOffset = 0; - if ((m_decodedOffset < sizeOfFileHeader) - && !processFileHeader(&imgDataOffset)) + if ((m_decodedOffset < sizeOfFileHeader) && !processFileHeader(&imgDataOffset)) return false; if (!m_reader) { - m_reader.set(new BMPImageReader(this, m_decodedOffset, imgDataOffset, - false)); + m_reader.set(new BMPImageReader(this, m_decodedOffset, imgDataOffset, false)); m_reader->setData(m_data.get()); } @@ -118,8 +113,7 @@ bool BMPImageDecoder::processFileHeader(size_t* imgDataOffset) ASSERT(!m_decodedOffset); if (m_data->size() < sizeOfFileHeader) return false; - const uint16_t fileType = - (m_data->data()[0] << 8) | static_cast<uint8_t>(m_data->data()[1]); + const uint16_t fileType = (m_data->data()[0] << 8) | static_cast<uint8_t>(m_data->data()[1]); *imgDataOffset = readUint32(10); m_decodedOffset = sizeOfFileHeader; diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h index c793585..15be0a2 100644 --- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h +++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h @@ -50,29 +50,23 @@ namespace WebCore { private: inline uint32_t readUint32(int offset) const { - return BMPImageReader::readUint32(m_data.get(), - m_decodedOffset + offset); + return BMPImageReader::readUint32(m_data.get(), m_decodedOffset + offset); } // Decodes the image. If |onlySize| is true, stops decoding after // calculating the image size. If decoding fails but there is no more // data coming, sets the "decode failure" flag. - void decodeWithCheckForDataEnded(bool onlySize); + void decode(bool onlySize); // Decodes the image. If |onlySize| is true, stops decoding after // calculating the image size. Returns whether decoding succeeded. - // NOTE: Used internally by decodeWithCheckForDataEnded(). Other people - // should not call this. - bool decode(bool onlySize); + bool decodeHelper(bool onlySize); // Processes the file header at the beginning of the data. Sets // |*imgDataOffset| based on the header contents. Returns true if the // file header could be decoded. bool processFileHeader(size_t* imgDataOffset); - // True if we've seen all the data. - bool m_allDataReceived; - // An index into |m_data| representing how much we've already decoded. // Note that this only tracks data _this_ class decodes; once the // BMPImageReader takes over this will not be updated further. diff --git a/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp b/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp index 1936d81..2f3bffa 100644 --- a/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp +++ b/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp @@ -33,10 +33,7 @@ namespace WebCore { -BMPImageReader::BMPImageReader(ImageDecoder* parent, - size_t decodedAndHeaderOffset, - size_t imgDataOffset, - bool usesAndMask) +BMPImageReader::BMPImageReader(ImageDecoder* parent, size_t decodedAndHeaderOffset, size_t imgDataOffset, bool usesAndMask) : m_parent(parent) , m_buffer(0) , m_decodedOffset(decodedAndHeaderOffset) @@ -63,8 +60,7 @@ bool BMPImageReader::decodeBMP(bool onlySize) return false; // Read and process info header. - if ((m_decodedOffset < (m_headerOffset + m_infoHeader.biSize)) - && !processInfoHeader()) + if ((m_decodedOffset < (m_headerOffset + m_infoHeader.biSize)) && !processInfoHeader()) return false; // processInfoHeader() set the size, so if that's all we needed, we're done. @@ -82,8 +78,7 @@ bool BMPImageReader::decodeBMP(bool onlySize) // Initialize the framebuffer if needed. ASSERT(m_buffer); // Parent should set this before asking us to decode! if (m_buffer->status() == RGBA32Buffer::FrameEmpty) { - if (!m_buffer->setSize(m_parent->size().width(), - m_parent->size().height())) + if (!m_buffer->setSize(m_parent->size().width(), m_parent->size().height())) return setFailed(); // Unable to allocate. m_buffer->setStatus(RGBA32Buffer::FramePartial); // setSize() calls eraseARGB(), which resets the alpha flag, so we force @@ -100,9 +95,7 @@ bool BMPImageReader::decodeBMP(bool onlySize) // Decode the data. if ((m_andMaskState != Decoding) && !pastEndOfImage(0)) { - if ((m_infoHeader.biCompression == RLE4) - || (m_infoHeader.biCompression == RLE8) - || (m_infoHeader.biCompression == RLE24)) { + if ((m_infoHeader.biCompression == RLE4) || (m_infoHeader.biCompression == RLE8) || (m_infoHeader.biCompression == RLE24)) { if (!processRLEData()) return false; } else if (!processNonRLEData(false, 0)) @@ -133,8 +126,7 @@ bool BMPImageReader::readInfoHeaderSize() { // Get size of info header. ASSERT(m_decodedOffset == m_headerOffset); - if ((m_decodedOffset > m_data->size()) - || ((m_data->size() - m_decodedOffset) < 4)) + if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset) < 4)) return false; m_infoHeader.biSize = readUint32(0); // Don't increment m_decodedOffset here, it just makes the code in @@ -143,9 +135,7 @@ bool BMPImageReader::readInfoHeaderSize() // Don't allow the header to overflow (which would be harmless here, but // problematic or at least confusing in other places), or to overrun the // image data. - if (((m_headerOffset + m_infoHeader.biSize) < m_headerOffset) - || (m_imgDataOffset - && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize)))) + if (((m_headerOffset + m_infoHeader.biSize) < m_headerOffset) || (m_imgDataOffset && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize)))) return setFailed(); // See if this is a header size we understand: @@ -156,9 +146,7 @@ bool BMPImageReader::readInfoHeaderSize() else if ((m_infoHeader.biSize == 40) || isWindowsV4Plus()) ; // OS/2 2.x: any multiple of 4 between 16 and 64, inclusive, or 42 or 46 - else if ((m_infoHeader.biSize >= 16) && (m_infoHeader.biSize <= 64) - && (((m_infoHeader.biSize & 3) == 0) || (m_infoHeader.biSize == 42) - || (m_infoHeader.biSize == 46))) + else if ((m_infoHeader.biSize >= 16) && (m_infoHeader.biSize <= 64) && (!(m_infoHeader.biSize & 3) || (m_infoHeader.biSize == 42) || (m_infoHeader.biSize == 46))) m_isOS22x = true; else return setFailed(); @@ -170,9 +158,7 @@ bool BMPImageReader::processInfoHeader() { // Read info header. ASSERT(m_decodedOffset == m_headerOffset); - if ((m_decodedOffset > m_data->size()) - || ((m_data->size() - m_decodedOffset) < m_infoHeader.biSize) - || !readInfoHeader()) + if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset) < m_infoHeader.biSize) || !readInfoHeader()) return false; m_decodedOffset += m_infoHeader.biSize; @@ -188,11 +174,9 @@ bool BMPImageReader::processInfoHeader() // colors", so set it to the maximum number of colors for this bit depth. // Also do this for bitmaps that put too large a value here. if (m_infoHeader.biBitCount < 16) { - const uint32_t maxColors = - static_cast<uint32_t>(1) << m_infoHeader.biBitCount; - if ((m_infoHeader.biClrUsed == 0) - || (m_infoHeader.biClrUsed > maxColors)) - m_infoHeader.biClrUsed = maxColors; + const uint32_t maxColors = static_cast<uint32_t>(1) << m_infoHeader.biBitCount; + if (!m_infoHeader.biClrUsed || (m_infoHeader.biClrUsed > maxColors)) + m_infoHeader.biClrUsed = maxColors; } // For any bitmaps that set their BitCount to the wrong value, reset the @@ -206,7 +190,7 @@ bool BMPImageReader::processInfoHeader() // Tell caller what still needs to be processed. if (m_infoHeader.biBitCount >= 16) m_needToProcessBitmasks = true; - else if (m_infoHeader.biBitCount > 0) + else if (m_infoHeader.biBitCount) m_needToProcessColorTable = true; return true; @@ -246,8 +230,7 @@ bool BMPImageReader::readInfoHeader() } else if (biCompression > 5) return setFailed(); // Some type we don't understand. else - m_infoHeader.biCompression = - static_cast<CompressionType>(biCompression); + m_infoHeader.biCompression = static_cast<CompressionType>(biCompression); } // Read colors used, if present. @@ -288,7 +271,7 @@ bool BMPImageReader::isInfoHeaderValid() const { // Non-positive widths/heights are invalid. (We've already flipped the // sign of the height for top-down bitmaps.) - if ((m_infoHeader.biWidth <= 0) || (m_infoHeader.biHeight == 0)) + if ((m_infoHeader.biWidth <= 0) || !m_infoHeader.biHeight) return false; // Only Windows V3+ has top-down bitmaps. @@ -296,16 +279,10 @@ bool BMPImageReader::isInfoHeaderValid() const return false; // Only bit depths of 1, 4, 8, or 24 are universally supported. - if ((m_infoHeader.biBitCount != 1) && (m_infoHeader.biBitCount != 4) - && (m_infoHeader.biBitCount != 8) - && (m_infoHeader.biBitCount != 24)) { + if ((m_infoHeader.biBitCount != 1) && (m_infoHeader.biBitCount != 4) && (m_infoHeader.biBitCount != 8) && (m_infoHeader.biBitCount != 24)) { // Windows V3+ additionally supports bit depths of 0 (for embedded // JPEG/PNG images), 16, and 32. - if (m_isOS21x || m_isOS22x) - return false; - if ((m_infoHeader.biBitCount != 0) - && (m_infoHeader.biBitCount != 16) - && (m_infoHeader.biBitCount != 32)) + if (m_isOS21x || m_isOS22x || (m_infoHeader.biBitCount && (m_infoHeader.biBitCount != 16) && (m_infoHeader.biBitCount != 32))) return false; } @@ -314,7 +291,7 @@ bool BMPImageReader::isInfoHeaderValid() const // some compression types. switch (m_infoHeader.biCompression) { case RGB: - if (m_infoHeader.biBitCount == 0) + if (!m_infoHeader.biBitCount) return false; break; @@ -323,46 +300,38 @@ bool BMPImageReader::isInfoHeaderValid() const // Compression = RLE4" (which means "4 bit, but with a 2-color table"), // so also allow the paletted RLE compression types to have too low a // bit count; we'll correct this later. - if (m_infoHeader.biBitCount == 0 || m_infoHeader.biBitCount > 8) + if (!m_infoHeader.biBitCount || (m_infoHeader.biBitCount > 8)) return false; break; case RLE4: // See comments in RLE8. - if (m_infoHeader.biBitCount == 0 || m_infoHeader.biBitCount > 4) + if (!m_infoHeader.biBitCount || (m_infoHeader.biBitCount > 4)) return false; break; case BITFIELDS: // Only valid for Windows V3+. - if (m_isOS21x || m_isOS22x) - return false; - if ((m_infoHeader.biBitCount != 16) && (m_infoHeader.biBitCount != 32)) + if (m_isOS21x || m_isOS22x || ((m_infoHeader.biBitCount != 16) && (m_infoHeader.biBitCount != 32))) return false; break; case JPEG: case PNG: // Only valid for Windows V3+. - if (m_isOS21x || m_isOS22x) - return false; - if (m_infoHeader.biBitCount != 0) + if (m_isOS21x || m_isOS22x || m_infoHeader.biBitCount) return false; break; case HUFFMAN1D: // Only valid for OS/2 2.x. - if (!m_isOS22x) - return false; - if (m_infoHeader.biBitCount != 1) + if (!m_isOS22x || (m_infoHeader.biBitCount != 1)) return false; break; case RLE24: // Only valid for OS/2 2.x. - if (!m_isOS22x) - return false; - if (m_infoHeader.biBitCount != 24) + if (!m_isOS22x || (m_infoHeader.biBitCount != 24)) return false; break; @@ -374,8 +343,7 @@ bool BMPImageReader::isInfoHeaderValid() const } // Top-down bitmaps cannot be compressed; they must be RGB or BITFIELDS. - if (m_isTopDown && (m_infoHeader.biCompression != RGB) - && (m_infoHeader.biCompression != BITFIELDS)) + if (m_isTopDown && (m_infoHeader.biCompression != RGB) && (m_infoHeader.biCompression != BITFIELDS)) return false; // Reject the following valid bitmap types that we don't currently bother @@ -385,13 +353,11 @@ bool BMPImageReader::isInfoHeaderValid() const // * Bitmaps larger than 2^16 pixels in either dimension (Windows // probably doesn't draw these well anyway, and the decoded data would // take a lot of memory). - if ((m_infoHeader.biWidth >= (1 << 16)) - || (m_infoHeader.biHeight >= (1 << 16))) + if ((m_infoHeader.biWidth >= (1 << 16)) || (m_infoHeader.biHeight >= (1 << 16))) return false; // * Windows V3+ JPEG-in-BMP and PNG-in-BMP bitmaps (supposedly not found // in the wild, only used to send data to printers?). - if ((m_infoHeader.biCompression == JPEG) - || (m_infoHeader.biCompression == PNG)) + if ((m_infoHeader.biCompression == JPEG) || (m_infoHeader.biCompression == PNG)) return false; // * OS/2 2.x Huffman-encoded monochrome bitmaps (see // http://www.fileformat.info/mirror/egff/ch09_05.htm , re: "G31D" @@ -413,11 +379,8 @@ bool BMPImageReader::processBitmasks() // 16 bits: MSB <- xRRRRRGG GGGBBBBB -> LSB // 24/32 bits: MSB <- [AAAAAAAA] RRRRRRRR GGGGGGGG BBBBBBBB -> LSB const int numBits = (m_infoHeader.biBitCount == 16) ? 5 : 8; - for (int i = 0; i <= 2; ++i) { - m_bitMasks[i] = - ((static_cast<uint32_t>(1) << (numBits * (3 - i))) - 1) ^ - ((static_cast<uint32_t>(1) << (numBits * (2 - i))) - 1); - } + for (int i = 0; i <= 2; ++i) + m_bitMasks[i] = ((static_cast<uint32_t>(1) << (numBits * (3 - i))) - 1) ^ ((static_cast<uint32_t>(1) << (numBits * (2 - i))) - 1); // For Windows V4+ 32-bit RGB, don't overwrite the alpha mask from the // header (see note in readInfoHeader()). @@ -431,10 +394,7 @@ bool BMPImageReader::processBitmasks() // Fail if we don't have enough file space for the bitmasks. static const size_t SIZEOF_BITMASKS = 12; - if (((m_headerOffset + m_infoHeader.biSize + SIZEOF_BITMASKS) < - (m_headerOffset + m_infoHeader.biSize)) - || (m_imgDataOffset && (m_imgDataOffset < - (m_headerOffset + m_infoHeader.biSize + SIZEOF_BITMASKS)))) + if (((m_headerOffset + m_infoHeader.biSize + SIZEOF_BITMASKS) < (m_headerOffset + m_infoHeader.biSize)) || (m_imgDataOffset && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize + SIZEOF_BITMASKS)))) return setFailed(); // Read bitmasks. @@ -461,8 +421,7 @@ bool BMPImageReader::processBitmasks() // specify a bogus alpha channel in bits that don't exist in the pixel // data (for example, bits 25-31 in a 24-bit RGB format). if (m_infoHeader.biBitCount < 32) - m_bitMasks[i] &= - ((static_cast<uint32_t>(1) << m_infoHeader.biBitCount) - 1); + m_bitMasks[i] &= ((static_cast<uint32_t>(1) << m_infoHeader.biBitCount) - 1); // For empty masks (common on the alpha channel, especially after the // trimming above), quickly clear the shifts and continue, to avoid an @@ -507,15 +466,11 @@ bool BMPImageReader::processColorTable() m_tableSizeInBytes = m_infoHeader.biClrUsed * (m_isOS21x ? 3 : 4); // Fail if we don't have enough file space for the color table. - if (((m_headerOffset + m_infoHeader.biSize + m_tableSizeInBytes) < - (m_headerOffset + m_infoHeader.biSize)) - || (m_imgDataOffset && (m_imgDataOffset < - (m_headerOffset + m_infoHeader.biSize + m_tableSizeInBytes)))) + if (((m_headerOffset + m_infoHeader.biSize + m_tableSizeInBytes) < (m_headerOffset + m_infoHeader.biSize)) || (m_imgDataOffset && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize + m_tableSizeInBytes)))) return setFailed(); // Read color table. - if ((m_decodedOffset > m_data->size()) - || ((m_data->size() - m_decodedOffset) < m_tableSizeInBytes)) + if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset) < m_tableSizeInBytes)) return false; m_colorTable.resize(m_infoHeader.biClrUsed); for (size_t i = 0; i < m_infoHeader.biClrUsed; ++i) { @@ -573,7 +528,7 @@ bool BMPImageReader::processRLEData() // the image. const uint8_t count = m_data->data()[m_decodedOffset]; const uint8_t code = m_data->data()[m_decodedOffset + 1]; - if (((count != 0) || (code != 1)) && pastEndOfImage(0)) + if ((count || (code != 1)) && pastEndOfImage(0)) return setFailed(); // Decode. @@ -590,10 +545,7 @@ bool BMPImageReader::processRLEData() case 1: // Magic token: EOF // Skip any remaining pixels in the image. - if ((m_coord.x() < m_parent->size().width()) - || (m_isTopDown - ? (m_coord.y() < (m_parent->size().height() - 1)) - : (m_coord.y() > 0))) + if ((m_coord.x() < m_parent->size().width()) || (m_isTopDown ? (m_coord.y() < (m_parent->size().height() - 1)) : (m_coord.y() > 0))) m_buffer->setHasAlpha(true); return true; @@ -607,10 +559,9 @@ bool BMPImageReader::processRLEData() // past the end of the image. const uint8_t dx = m_data->data()[m_decodedOffset + 2]; const uint8_t dy = m_data->data()[m_decodedOffset + 3]; - if ((dx != 0) || (dy != 0)) + if (dx || dy) m_buffer->setHasAlpha(true); - if (((m_coord.x() + dx) > m_parent->size().width()) || - pastEndOfImage(dy)) + if (((m_coord.x() + dx) > m_parent->size().width()) || pastEndOfImage(dy)) return setFailed(); // Skip intervening pixels. @@ -637,8 +588,7 @@ bool BMPImageReader::processRLEData() // The following color data is repeated for |count| total pixels. // Strangely, some BMPs seem to specify excessively large counts // here; ignore pixels past the end of the row. - const int endX = - std::min(m_coord.x() + count, m_parent->size().width()); + const int endX = std::min(m_coord.x() + count, m_parent->size().width()); if (m_infoHeader.biCompression == RLE24) { // Bail if there isn't enough data. @@ -646,8 +596,7 @@ bool BMPImageReader::processRLEData() return false; // One BGR triple that we copy |count| times. - fillRGBA(endX, m_data->data()[m_decodedOffset + 3], - m_data->data()[m_decodedOffset + 2], code, 0xff); + fillRGBA(endX, m_data->data()[m_decodedOffset + 3], m_data->data()[m_decodedOffset + 2], code, 0xff); m_decodedOffset += 4; } else { // RLE8 has one color index that gets repeated; RLE4 has two @@ -658,8 +607,7 @@ bool BMPImageReader::processRLEData() colorIndexes[0] = (colorIndexes[0] >> 4) & 0xf; colorIndexes[1] &= 0xf; } - if ((colorIndexes[0] >= m_infoHeader.biClrUsed) - || (colorIndexes[1] >= m_infoHeader.biClrUsed)) + if ((colorIndexes[0] >= m_infoHeader.biClrUsed) || (colorIndexes[1] >= m_infoHeader.biClrUsed)) return setFailed(); for (int which = 0; m_coord.x() < endX; ) { setI(colorIndexes[which]); @@ -689,9 +637,7 @@ bool BMPImageReader::processNonRLEData(bool inRLE, int numPixels) // requires. const size_t pixelsPerByte = 8 / m_infoHeader.biBitCount; const size_t bytesPerPixel = m_infoHeader.biBitCount / 8; - const size_t unpaddedNumBytes = (m_infoHeader.biBitCount < 16) - ? ((numPixels + pixelsPerByte - 1) / pixelsPerByte) - : (numPixels * bytesPerPixel); + const size_t unpaddedNumBytes = (m_infoHeader.biBitCount < 16) ? ((numPixels + pixelsPerByte - 1) / pixelsPerByte) : (numPixels * bytesPerPixel); // RLE runs are zero-padded at the end to a multiple of 16 bits. Non-RLE // data is in rows and is zero-padded to a multiple of 32 bits. const size_t alignBits = inRLE ? 1 : 3; @@ -711,10 +657,8 @@ bool BMPImageReader::processNonRLEData(bool inRLE, int numPixels) const uint8_t mask = (1 << m_infoHeader.biBitCount) - 1; for (size_t byte = 0; byte < unpaddedNumBytes; ++byte) { uint8_t pixelData = m_data->data()[m_decodedOffset + byte]; - for (size_t pixel = 0; - (pixel < pixelsPerByte) && (m_coord.x() < endX); ++pixel) { - const size_t colorIndex = - (pixelData >> (8 - m_infoHeader.biBitCount)) & mask; + for (size_t pixel = 0; (pixel < pixelsPerByte) && (m_coord.x() < endX); ++pixel) { + const size_t colorIndex = (pixelData >> (8 - m_infoHeader.biBitCount)) & mask; if (m_andMaskState == Decoding) { // There's no way to accurately represent an AND + XOR // operation as an RGBA image, so where the AND values @@ -749,7 +693,7 @@ bool BMPImageReader::processNonRLEData(bool inRLE, int numPixels) // images where all alpha values are 255; opaque images are // faster to draw. int alpha = getAlpha(pixel); - if (!m_seenNonZeroAlphaPixel && (alpha == 0)) { + if (!m_seenNonZeroAlphaPixel && !alpha) { m_seenZeroAlphaPixel = true; alpha = 255; } else { diff --git a/WebCore/platform/image-decoders/bmp/BMPImageReader.h b/WebCore/platform/image-decoders/bmp/BMPImageReader.h index 3536e3b..a30a721 100644 --- a/WebCore/platform/image-decoders/bmp/BMPImageReader.h +++ b/WebCore/platform/image-decoders/bmp/BMPImageReader.h @@ -57,8 +57,7 @@ namespace WebCore { uint32_t result; memcpy(&result, &data->data()[offset], 4); #if CPU(BIG_ENDIAN) - result = ((result & 0xff) << 24) | ((result & 0xff00) << 8) | - ((result & 0xff0000) >> 8) | ((result & 0xff000000) >> 24); + result = ((result & 0xff) << 24) | ((result & 0xff00) << 8) | ((result & 0xff0000) >> 8) | ((result & 0xff000000) >> 24); #endif return result; } @@ -67,10 +66,7 @@ namespace WebCore { // |startOffset| points to the start of the BMP within the file. // |buffer| points at an empty RGBA32Buffer that we'll initialize and // fill with decoded data. - BMPImageReader(ImageDecoder* parent, - size_t decodedAndHeaderOffset, - size_t imgDataOffset, - bool usesAndMask); + BMPImageReader(ImageDecoder* parent, size_t decodedAndHeaderOffset, size_t imgDataOffset, bool usesAndMask); void setBuffer(RGBA32Buffer* buffer) { m_buffer = buffer; } void setData(SharedBuffer* data) { m_data = data; } @@ -179,9 +175,7 @@ namespace WebCore { // image", so downwards for m_isTopDown images and upwards otherwise. inline bool pastEndOfImage(int numRows) { - return m_isTopDown - ? ((m_coord.y() + numRows) >= m_parent->size().height()) - : ((m_coord.y() - numRows) < 0); + return m_isTopDown ? ((m_coord.y() + numRows) >= m_parent->size().height()) : ((m_coord.y() - numRows) < 0); } // Returns the pixel data for the current X coordinate in a uint32_t. @@ -203,8 +197,7 @@ namespace WebCore { uint32_t pixel; memcpy(&pixel, &m_data->data()[m_decodedOffset + offset], 3); #if CPU(BIG_ENDIAN) - pixel = ((pixel & 0xff00) << 8) | ((pixel & 0xff0000) >> 8) | - ((pixel & 0xff000000) >> 24); + pixel = ((pixel & 0xff00) << 8) | ((pixel & 0xff0000) >> 8) | ((pixel & 0xff000000) >> 24); #endif return pixel; } @@ -222,17 +215,13 @@ namespace WebCore { // in the given pixel data. inline unsigned getComponent(uint32_t pixel, int component) const { - return ((pixel & m_bitMasks[component]) >> - m_bitShiftsRight[component]) << m_bitShiftsLeft[component]; + return ((pixel & m_bitMasks[component]) >> m_bitShiftsRight[component]) << m_bitShiftsLeft[component]; } inline unsigned getAlpha(uint32_t pixel) const { // For images without alpha, return alpha of 0xff. - if (m_bitMasks[3] == 0) - return 0xff; - - return getComponent(pixel, 3); + return m_bitMasks[3] ? getComponent(pixel, 3) : 0xff; } // Sets the current pixel to the color given by |colorIndex|. This also @@ -240,9 +229,7 @@ namespace WebCore { // right by one. inline void setI(size_t colorIndex) { - setRGBA(m_colorTable[colorIndex].rgbRed, - m_colorTable[colorIndex].rgbGreen, - m_colorTable[colorIndex].rgbBlue, 0xff); + setRGBA(m_colorTable[colorIndex].rgbRed, m_colorTable[colorIndex].rgbGreen, m_colorTable[colorIndex].rgbBlue, 0xff); } // Like setI(), but with the individual component values specified. @@ -251,8 +238,7 @@ namespace WebCore { unsigned blue, unsigned alpha) { - m_buffer->setRGBA(m_coord.x(), m_coord.y(), red, green, blue, - alpha); + m_buffer->setRGBA(m_coord.x(), m_coord.y(), red, green, blue, alpha); m_coord.move(1, 0); } diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp index 1124bd2..807d57c 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp +++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp @@ -30,7 +30,7 @@ namespace WebCore { GIFImageDecoder::GIFImageDecoder() - : m_frameCountValid(true) + : m_alreadyScannedThisDataForFrameCount(true) , m_repetitionCount(cAnimationLoopOnce) , m_readOffset(0) { @@ -40,56 +40,45 @@ GIFImageDecoder::~GIFImageDecoder() { } -// Take the data and store it. void GIFImageDecoder::setData(SharedBuffer* data, bool allDataReceived) { if (m_failed) return; - // Cache our new data. ImageDecoder::setData(data, allDataReceived); - // Our frame count is now unknown. - m_frameCountValid = false; + // We need to rescan the frame count, as the new data may have changed it. + m_alreadyScannedThisDataForFrameCount = false; - // Create the GIF reader. if (!m_reader && !m_failed) m_reader.set(new GIFImageReader(this)); } -// Whether or not the size information has been decoded yet. bool GIFImageDecoder::isSizeAvailable() { if (!ImageDecoder::isSizeAvailable() && !failed() && m_reader) - decode(GIFSizeQuery, 0); + decode(0, GIFSizeQuery); return ImageDecoder::isSizeAvailable(); } -// The total number of frames for the image. Will scan the image data for the answer -// (without necessarily decoding all of the individual frames). size_t GIFImageDecoder::frameCount() { - // If the decoder had an earlier error, we will just return what we had decoded - // so far. - if (!m_frameCountValid) { - // FIXME: Scanning all the data has O(n^2) behavior if the data were to come in really - // slowly. Might be interesting to try to clone our existing read session to preserve - // state, but for now we just crawl all the data. Note that this is no worse than what - // ImageIO does on Mac right now (it also crawls all the data again). + if (!m_alreadyScannedThisDataForFrameCount) { + // FIXME: Scanning all the data has O(n^2) behavior if the data were to + // come in really slowly. Might be interesting to try to clone our + // existing read session to preserve state, but for now we just crawl + // all the data. Note that this is no worse than what ImageIO does on + // Mac right now (it also crawls all the data again). GIFImageReader reader(0); - // This function may fail, but we want to keep any partial data it may - // have decoded, so don't mark it is invalid. If there is an overflow - // or some serious error, m_failed will have gotten set for us. reader.read((const unsigned char*)m_data->data(), m_data->size(), GIFFrameCountQuery, static_cast<unsigned>(-1)); - m_frameCountValid = true; + m_alreadyScannedThisDataForFrameCount = true; m_frameBufferCache.resize(reader.images_count); } return m_frameBufferCache.size(); } -// The number of repetitions to perform for an animation loop. int GIFImageDecoder::repetitionCount() const { // This value can arrive at any point in the image data stream. Most GIFs @@ -120,7 +109,7 @@ RGBA32Buffer* GIFImageDecoder::frameBufferAtIndex(size_t index) RGBA32Buffer& frame = m_frameBufferCache[index]; if (frame.status() != RGBA32Buffer::FrameComplete && m_reader) - decode(GIFFullQuery, index + 1); // Decode this frame. + decode(index + 1, GIFFullQuery); // Decode this frame. return &frame; } @@ -174,23 +163,11 @@ void GIFImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame) } } -// Feed data to the GIF reader. -void GIFImageDecoder::decode(GIFQuery query, unsigned haltAtFrame) -{ - if (m_failed) - return; - - m_failed = !m_reader->read((const unsigned char*)m_data->data() + m_readOffset, m_data->size() - m_readOffset, query, haltAtFrame); - - if (m_failed) - m_reader.clear(); -} - -// Callbacks from the GIF reader. bool GIFImageDecoder::sizeNowAvailable(unsigned width, unsigned height) { if (!setSize(width, height)) return false; + prepareScaleDataIfNecessary(); return true; } @@ -200,94 +177,7 @@ void GIFImageDecoder::decodingHalted(unsigned bytesLeft) m_readOffset = m_data->size() - bytesLeft; } -bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) -{ - // Initialize the frame rect in our buffer. - const GIFFrameReader* frameReader = m_reader->frame_reader; - IntRect frameRect(frameReader->x_offset, frameReader->y_offset, frameReader->width, frameReader->height); - - // Make sure the frameRect doesn't extend past the bottom-right of the buffer. - if (frameRect.right() > size().width()) - frameRect.setWidth(size().width() - frameReader->x_offset); - if (frameRect.bottom() > size().height()) - frameRect.setHeight(size().height() - frameReader->y_offset); - - RGBA32Buffer* const buffer = &m_frameBufferCache[frameIndex]; - int left = upperBoundScaledX(frameRect.x()); - int right = lowerBoundScaledX(frameRect.right(), left); - int top = upperBoundScaledY(frameRect.y()); - int bottom = lowerBoundScaledY(frameRect.bottom(), top); - buffer->setRect(IntRect(left, top, right - left, bottom - top)); - - if (frameIndex == 0) { - // This is the first frame, so we're not relying on any previous data. - if (!buffer->setSize(scaledSize().width(), scaledSize().height())) { - m_failed = true; - return false; - } - } else { - // The starting state for this frame depends on the previous frame's - // disposal method. - // - // Frames that use the DisposeOverwritePrevious method are effectively - // no-ops in terms of changing the starting state of a frame compared to - // the starting state of the previous frame, so skip over them. (If the - // first frame specifies this method, it will get treated like - // DisposeOverwriteBgcolor below and reset to a completely empty image.) - const RGBA32Buffer* prevBuffer = &m_frameBufferCache[--frameIndex]; - RGBA32Buffer::FrameDisposalMethod prevMethod = - prevBuffer->disposalMethod(); - while ((frameIndex > 0) - && (prevMethod == RGBA32Buffer::DisposeOverwritePrevious)) { - prevBuffer = &m_frameBufferCache[--frameIndex]; - prevMethod = prevBuffer->disposalMethod(); - } - ASSERT(prevBuffer->status() == RGBA32Buffer::FrameComplete); - - if ((prevMethod == RGBA32Buffer::DisposeNotSpecified) || - (prevMethod == RGBA32Buffer::DisposeKeep)) { - // Preserve the last frame as the starting state for this frame. - buffer->copyBitmapData(*prevBuffer); - } else { - // We want to clear the previous frame to transparent, without - // affecting pixels in the image outside of the frame. - const IntRect& prevRect = prevBuffer->rect(); - const IntSize& bufferSize = scaledSize(); - if ((frameIndex == 0) - || prevRect.contains(IntRect(IntPoint(), bufferSize))) { - // Clearing the first frame, or a frame the size of the whole - // image, results in a completely empty image. - if (!buffer->setSize(bufferSize.width(), bufferSize.height())) { - m_failed = true; - return false; - } - } else { - // Copy the whole previous buffer, then clear just its frame. - buffer->copyBitmapData(*prevBuffer); - for (int y = prevRect.y(); y < prevRect.bottom(); ++y) { - for (int x = prevRect.x(); x < prevRect.right(); ++x) - buffer->setRGBA(x, y, 0, 0, 0, 0); - } - if ((prevRect.width() > 0) && (prevRect.height() > 0)) - buffer->setHasAlpha(true); - } - } - } - - // Update our status to be partially complete. - buffer->setStatus(RGBA32Buffer::FramePartial); - - // Reset the alpha pixel tracker for this frame. - m_currentBufferSawAlpha = false; - return true; -} - -bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, - unsigned char* rowBuffer, - unsigned char* rowEnd, - unsigned rowNumber, - unsigned repeatCount, - bool writeTransparentPixels) +bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, unsigned repeatCount, bool writeTransparentPixels) { const GIFFrameReader* frameReader = m_reader->frame_reader; // The pixel data and coordinates supplied to us are relative to the frame's @@ -365,7 +255,7 @@ void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, // resulting buffer was non-transparent, and we can setHasAlpha(false). if (buffer.rect().contains(IntRect(IntPoint(), scaledSize()))) buffer.setHasAlpha(false); - else if (frameIndex > 0) { + else if (frameIndex) { // Tricky case. This frame does not have alpha only if everywhere // outside its rect doesn't have alpha. To know whether this is // true, we check the start state of the frame -- if it doesn't have @@ -375,8 +265,7 @@ void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, // don't affect the start state of this frame) the same way we do in // initFrameBuffer(). const RGBA32Buffer* prevBuffer = &m_frameBufferCache[--frameIndex]; - while ((frameIndex > 0) - && (prevBuffer->disposalMethod() == RGBA32Buffer::DisposeOverwritePrevious)) + while (frameIndex && (prevBuffer->disposalMethod() == RGBA32Buffer::DisposeOverwritePrevious)) prevBuffer = &m_frameBufferCache[--frameIndex]; // Now, if we're at a DisposeNotSpecified or DisposeKeep frame, then @@ -387,8 +276,7 @@ void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, // The only remaining case is a DisposeOverwriteBgcolor frame. If // it had no alpha, and its rect is contained in the current frame's // rect, we know the current frame has no alpha. - if ((prevBuffer->disposalMethod() == RGBA32Buffer::DisposeOverwriteBgcolor) - && !prevBuffer->hasAlpha() && buffer.rect().contains(prevBuffer->rect())) + if ((prevBuffer->disposalMethod() == RGBA32Buffer::DisposeOverwriteBgcolor) && !prevBuffer->hasAlpha() && buffer.rect().contains(prevBuffer->rect())) buffer.setHasAlpha(false); } } @@ -401,4 +289,93 @@ void GIFImageDecoder::gifComplete() m_reader.clear(); } +void GIFImageDecoder::decode(unsigned haltAtFrame, GIFQuery query) +{ + if (m_failed) + return; + + m_failed = !m_reader->read((const unsigned char*)m_data->data() + m_readOffset, m_data->size() - m_readOffset, query, haltAtFrame); + + if (m_failed) + m_reader.clear(); +} + +bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) +{ + // Initialize the frame rect in our buffer. + const GIFFrameReader* frameReader = m_reader->frame_reader; + IntRect frameRect(frameReader->x_offset, frameReader->y_offset, frameReader->width, frameReader->height); + + // Make sure the frameRect doesn't extend outside the buffer. + if (frameRect.right() > size().width()) + frameRect.setWidth(size().width() - frameReader->x_offset); + if (frameRect.bottom() > size().height()) + frameRect.setHeight(size().height() - frameReader->y_offset); + + RGBA32Buffer* const buffer = &m_frameBufferCache[frameIndex]; + int left = upperBoundScaledX(frameRect.x()); + int right = lowerBoundScaledX(frameRect.right(), left); + int top = upperBoundScaledY(frameRect.y()); + int bottom = lowerBoundScaledY(frameRect.bottom(), top); + buffer->setRect(IntRect(left, top, right - left, bottom - top)); + + if (!frameIndex) { + // This is the first frame, so we're not relying on any previous data. + if (!buffer->setSize(scaledSize().width(), scaledSize().height())) { + m_failed = true; + return false; + } + } else { + // The starting state for this frame depends on the previous frame's + // disposal method. + // + // Frames that use the DisposeOverwritePrevious method are effectively + // no-ops in terms of changing the starting state of a frame compared to + // the starting state of the previous frame, so skip over them. (If the + // first frame specifies this method, it will get treated like + // DisposeOverwriteBgcolor below and reset to a completely empty image.) + const RGBA32Buffer* prevBuffer = &m_frameBufferCache[--frameIndex]; + RGBA32Buffer::FrameDisposalMethod prevMethod = prevBuffer->disposalMethod(); + while (frameIndex && (prevMethod == RGBA32Buffer::DisposeOverwritePrevious)) { + prevBuffer = &m_frameBufferCache[--frameIndex]; + prevMethod = prevBuffer->disposalMethod(); + } + ASSERT(prevBuffer->status() == RGBA32Buffer::FrameComplete); + + if ((prevMethod == RGBA32Buffer::DisposeNotSpecified) || (prevMethod == RGBA32Buffer::DisposeKeep)) { + // Preserve the last frame as the starting state for this frame. + buffer->copyBitmapData(*prevBuffer); + } else { + // We want to clear the previous frame to transparent, without + // affecting pixels in the image outside of the frame. + const IntRect& prevRect = prevBuffer->rect(); + const IntSize& bufferSize = scaledSize(); + if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) { + // Clearing the first frame, or a frame the size of the whole + // image, results in a completely empty image. + if (!buffer->setSize(bufferSize.width(), bufferSize.height())) { + m_failed = true; + return false; + } + } else { + // Copy the whole previous buffer, then clear just its frame. + buffer->copyBitmapData(*prevBuffer); + for (int y = prevRect.y(); y < prevRect.bottom(); ++y) { + for (int x = prevRect.x(); x < prevRect.right(); ++x) + buffer->setRGBA(x, y, 0, 0, 0, 0); + } + if ((prevRect.width() > 0) && (prevRect.height() > 0)) + buffer->setHasAlpha(true); + } + } + } + + // Update our status to be partially complete. + buffer->setStatus(RGBA32Buffer::FramePartial); + + // Reset the alpha pixel tracker for this frame. + m_currentBufferSawAlpha = false; + return true; +} + } // namespace WebCore diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h index 011ca96..0aa5387 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h +++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h @@ -37,48 +37,38 @@ namespace WebCore { class GIFImageDecoder : public ImageDecoder { public: GIFImageDecoder(); - ~GIFImageDecoder(); + virtual ~GIFImageDecoder(); - virtual String filenameExtension() const { return "gif"; } + enum GIFQuery { GIFFullQuery, GIFSizeQuery, GIFFrameCountQuery }; - // Take the data and store it. + // ImageDecoder + virtual String filenameExtension() const { return "gif"; } virtual void setData(SharedBuffer* data, bool allDataReceived); - - // Whether or not the size information has been decoded yet. virtual bool isSizeAvailable(); - - // The total number of frames for the image. Will scan the image data for the answer - // (without necessarily decoding all of the individual frames). virtual size_t frameCount(); - - // The number of repetitions to perform for an animation loop. virtual int repetitionCount() const; - virtual RGBA32Buffer* frameBufferAtIndex(size_t index); - virtual void clearFrameBufferCache(size_t clearBeforeFrame); - virtual unsigned frameDurationAtIndex(size_t index) { return 0; } - - enum GIFQuery { GIFFullQuery, GIFSizeQuery, GIFFrameCountQuery }; - - void decode(GIFQuery, unsigned haltAtFrame); - // Callbacks from the GIF reader. bool sizeNowAvailable(unsigned width, unsigned height); void decodingHalted(unsigned bytesLeft); - bool haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, - unsigned repeatCount, bool writeTransparentPixels); + bool haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, unsigned repeatCount, bool writeTransparentPixels); void frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod); void gifComplete(); private: - // Called to initialize the frame buffer with the given index, based on the - // previous frame's disposal method. Returns true on success. On failure, - // this will mark the image as failed. + // If the query is GIFFullQuery, decodes the image up to (but not + // including) |haltAtFrame|. Otherwise, decodes as much as is needed to + // answer the query, ignoring bitmap data. + void decode(unsigned haltAtFrame, GIFQuery); + + // Called to initialize the frame buffer with the given index, based on + // the previous frame's disposal method. Returns true on success. On + // failure, this will mark the image as failed. bool initFrameBuffer(unsigned frameIndex); - bool m_frameCountValid; + bool m_alreadyScannedThisDataForFrameCount; bool m_currentBufferSawAlpha; mutable int m_repetitionCount; OwnPtr<GIFImageReader> m_reader; diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp index ffb1310..755a48d 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp +++ b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp @@ -290,7 +290,7 @@ bool GIFImageReader::do_lzw(const unsigned char *q) /* Check for explicit end-of-stream code */ if (code == (clear_code + 1)) { /* end-of-stream should only appear after all image data */ - return rows_remaining == 0; + return !rows_remaining; } if (oldcode == -1) { @@ -494,11 +494,11 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, /* All GIF files begin with "GIF87a" or "GIF89a" */ case gif_type: { - if (!strncmp((char*)q, "GIF89a", 6)) { + if (!strncmp((char*)q, "GIF89a", 6)) version = 89; - } else if (!strncmp((char*)q, "GIF87a", 6)) { + else if (!strncmp((char*)q, "GIF87a", 6)) version = 87; - } else { + else { state = gif_error; break; } @@ -712,9 +712,10 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, // and doesn't do anything, as our streaming/buffering takes care of it all... // See: http://semmix.pl/color/exgraf/eeg24.htm GETN(1, gif_netscape_extension_block); - } else - state = gif_error; // 0,3-7 are yet to be defined netscape - // extension codes + } else { + // 0,3-7 are yet to be defined netscape extension codes + state = gif_error; + } break; } @@ -893,8 +894,7 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, // CALLBACK: The frame is now complete. if (clientptr && frame_reader) - clientptr->frameComplete(images_decoded - 1, frame_reader->delay_time, - frame_reader->disposal_method); + clientptr->frameComplete(images_decoded - 1, frame_reader->delay_time, frame_reader->disposal_method); /* Clear state from this image */ if (frame_reader) { @@ -919,7 +919,6 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, // Handle general errors case gif_error: - // nsGIFDecoder2::EndGIF(gs->clientptr, gs->loop_count); return false; // We shouldn't ever get here. diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.h b/WebCore/platform/image-decoders/gif/GIFImageReader.h index 14c2fb4..5982827 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageReader.h +++ b/WebCore/platform/image-decoders/gif/GIFImageReader.h @@ -194,10 +194,6 @@ struct GIFImageReader { } ~GIFImageReader() { - close(); - } - - void close() { delete []global_colormap; global_colormap = 0; delete frame_reader; diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp index a0ec4f7..1a202bc 100644 --- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp +++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp @@ -45,9 +45,11 @@ static const size_t sizeOfDirectory = 6; static const size_t sizeOfDirEntry = 16; ICOImageDecoder::ICOImageDecoder() - : ImageDecoder() - , m_allDataReceived(false) - , m_decodedOffset(0) + : m_decodedOffset(0) +{ +} + +ICOImageDecoder::~ICOImageDecoder() { } @@ -57,10 +59,8 @@ void ICOImageDecoder::setData(SharedBuffer* data, bool allDataReceived) return; ImageDecoder::setData(data, allDataReceived); - m_allDataReceived = allDataReceived; - for (BMPReaders::iterator i(m_bmpReaders.begin()); - i != m_bmpReaders.end(); ++i) { + for (BMPReaders::iterator i(m_bmpReaders.begin()); i != m_bmpReaders.end(); ++i) { if (*i) (*i)->setData(data); } @@ -71,7 +71,7 @@ void ICOImageDecoder::setData(SharedBuffer* data, bool allDataReceived) bool ICOImageDecoder::isSizeAvailable() { if (!ImageDecoder::isSizeAvailable()) - decodeWithCheckForDataEnded(0, true); + decode(0, true); return ImageDecoder::isSizeAvailable(); } @@ -83,8 +83,7 @@ IntSize ICOImageDecoder::size() const IntSize ICOImageDecoder::frameSizeAtIndex(size_t index) const { - return (index && (index < m_dirEntries.size())) ? - m_dirEntries[index].m_size : size(); + return (index && (index < m_dirEntries.size())) ? m_dirEntries[index].m_size : size(); } bool ICOImageDecoder::setSize(unsigned width, unsigned height) @@ -101,7 +100,7 @@ bool ICOImageDecoder::setSize(unsigned width, unsigned height) size_t ICOImageDecoder::frameCount() { - decodeWithCheckForDataEnded(0, true); + decode(0, true); if (m_frameBufferCache.isEmpty()) m_frameBufferCache.resize(m_dirEntries.size()); // CAUTION: We must not resize m_frameBufferCache again after this, as @@ -116,40 +115,19 @@ RGBA32Buffer* ICOImageDecoder::frameBufferAtIndex(size_t index) if (index >= frameCount()) return 0; - // Determine the image type, and if this is a BMP, decode. - decodeWithCheckForDataEnded(index, false); - - // PNGs decode into their own framebuffers, so only use our internal cache - // for non-PNGs (BMP or unknown). - if (!m_pngDecoders[index]) - return &m_frameBufferCache[index]; - - // Fail if the size the PNGImageDecoder calculated does not match the size - // in the directory. - if (m_pngDecoders[index]->isSizeAvailable()) { - const IntSize pngSize(m_pngDecoders[index]->size()); - const IconDirectoryEntry& dirEntry = m_dirEntries[index]; - if (pngSize != dirEntry.m_size) { - setFailed(); - m_pngDecoders[index]->setFailed(); - } - } - - return m_pngDecoders[index]->frameBufferAtIndex(0); + RGBA32Buffer* buffer = &m_frameBufferCache[index]; + if (buffer->status() != RGBA32Buffer::FrameComplete) + decode(index, false); + return buffer; } // static -bool ICOImageDecoder::compareEntries(const IconDirectoryEntry& a, - const IconDirectoryEntry& b) +bool ICOImageDecoder::compareEntries(const IconDirectoryEntry& a, const IconDirectoryEntry& b) { - // Larger icons are better. + // Larger icons are better. After that, higher bit-depth icons are better. const int aEntryArea = a.m_size.width() * a.m_size.height(); const int bEntryArea = b.m_size.width() * b.m_size.height(); - if (aEntryArea != bEntryArea) - return (aEntryArea > bEntryArea); - - // Higher bit-depth icons are better. - return (a.m_bitCount > b.m_bitCount); + return (aEntryArea == bEntryArea) ? (a.m_bitCount > b.m_bitCount) : (aEntryArea > bEntryArea); } void ICOImageDecoder::setDataForPNGDecoderAtIndex(size_t index) @@ -161,21 +139,18 @@ void ICOImageDecoder::setDataForPNGDecoderAtIndex(size_t index) // Copy out PNG data to a separate vector and send to the PNG decoder. // FIXME: Save this copy by making the PNG decoder able to take an // optional offset. - RefPtr<SharedBuffer> pngData( - SharedBuffer::create(&m_data->data()[dirEntry.m_imageOffset], - m_data->size() - dirEntry.m_imageOffset)); - m_pngDecoders[index]->setData(pngData.get(), m_allDataReceived); + RefPtr<SharedBuffer> pngData(SharedBuffer::create(&m_data->data()[dirEntry.m_imageOffset], m_data->size() - dirEntry.m_imageOffset)); + m_pngDecoders[index]->setData(pngData.get(), isAllDataReceived()); } -void ICOImageDecoder::decodeWithCheckForDataEnded(size_t index, bool onlySize) +void ICOImageDecoder::decode(size_t index, bool onlySize) { if (failed()) return; // If we couldn't decode the image but we've received all the data, decoding // has failed. - if ((!decodeDirectory() || (!onlySize && !decodeAtIndex(index))) - && m_allDataReceived) + if ((!decodeDirectory() || (!onlySize && !decodeAtIndex(index))) && isAllDataReceived()) setFailed(); } @@ -186,45 +161,47 @@ bool ICOImageDecoder::decodeDirectory() return false; // Read and process directory entries. - return (m_decodedOffset >= - (sizeOfDirectory + (m_dirEntries.size() * sizeOfDirEntry))) - || processDirectoryEntries(); + return (m_decodedOffset >= (sizeOfDirectory + (m_dirEntries.size() * sizeOfDirEntry))) || processDirectoryEntries(); } bool ICOImageDecoder::decodeAtIndex(size_t index) { ASSERT(index < m_dirEntries.size()); const IconDirectoryEntry& dirEntry = m_dirEntries[index]; - if (!m_bmpReaders[index] && !m_pngDecoders[index]) { - // Image type unknown. - const ImageType imageType = imageTypeAtIndex(index); - if (imageType == BMP) { + const ImageType imageType = imageTypeAtIndex(index); + if (imageType == Unknown) + return false; // Not enough data to determine image type yet. + + if (imageType == BMP) { + if (!m_bmpReaders[index]) { // We need to have already sized m_frameBufferCache before this, and // we must not resize it again later (see caution in frameCount()). ASSERT(m_frameBufferCache.size() == m_dirEntries.size()); - m_bmpReaders[index].set( - new BMPImageReader(this, dirEntry.m_imageOffset, 0, true)); + m_bmpReaders[index].set(new BMPImageReader(this, dirEntry.m_imageOffset, 0, true)); m_bmpReaders[index]->setData(m_data.get()); m_bmpReaders[index]->setBuffer(&m_frameBufferCache[index]); - } else if (imageType == PNG) { - m_pngDecoders[index].set(new PNGImageDecoder()); - setDataForPNGDecoderAtIndex(index); - } else { - // Not enough data to determine image type yet. - return false; } - } - - if (m_bmpReaders[index]) { m_frameSize = dirEntry.m_size; bool result = m_bmpReaders[index]->decodeBMP(false); m_frameSize = IntSize(); return result; } - // For PNGs, we're now done; further decoding will happen when calling - // frameBufferAtIndex() on the PNG decoder. - return true; + if (!m_pngDecoders[index]) { + m_pngDecoders[index].set(new PNGImageDecoder()); + setDataForPNGDecoderAtIndex(index); + } + // Fail if the size the PNGImageDecoder calculated does not match the size + // in the directory. + if (m_pngDecoders[index]->isSizeAvailable() && (m_pngDecoders[index]->size() != dirEntry.m_size)) { + setFailed(); + return false; + } + m_frameBufferCache[index] = *m_pngDecoders[index]->frameBufferAtIndex(0); + if (!m_pngDecoders[index]->failed()) + return true; + setFailed(); + return false; } bool ICOImageDecoder::processDirectory() @@ -259,18 +236,14 @@ bool ICOImageDecoder::processDirectoryEntries() { // Read directory entries. ASSERT(m_decodedOffset == sizeOfDirectory); - if ((m_decodedOffset > m_data->size()) - || ((m_data->size() - m_decodedOffset) < - (m_dirEntries.size() * sizeOfDirEntry))) + if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset) < (m_dirEntries.size() * sizeOfDirEntry))) return false; - for (IconDirectoryEntries::iterator i(m_dirEntries.begin()); - i != m_dirEntries.end(); ++i) + for (IconDirectoryEntries::iterator i(m_dirEntries.begin()); i != m_dirEntries.end(); ++i) *i = readDirectoryEntry(); // Updates m_decodedOffset. // Make sure the specified image offsets are past the end of the directory // entries. - for (IconDirectoryEntries::iterator i(m_dirEntries.begin()); - i != m_dirEntries.end(); ++i) { + for (IconDirectoryEntries::iterator i(m_dirEntries.begin()); i != m_dirEntries.end(); ++i) { if (i->m_imageOffset < m_decodedOffset) { setFailed(); return false; @@ -309,8 +282,7 @@ ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry() // this isn't quite what the bitmap info header says later, as we only use // this value to determine which icon entry is best. if (!entry.m_bitCount) { - int colorCount = - static_cast<uint8_t>(m_data->data()[m_decodedOffset + 2]); + int colorCount = static_cast<uint8_t>(m_data->data()[m_decodedOffset + 2]); if (!colorCount) colorCount = 256; // Vague in the spec, needed by real-world icons. for (--colorCount; colorCount; colorCount >>= 1) diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h index 6117e06..c1f29c9 100644 --- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h +++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h @@ -41,6 +41,7 @@ namespace WebCore { class ICOImageDecoder : public ImageDecoder { public: ICOImageDecoder(); + virtual ~ICOImageDecoder(); // ImageDecoder virtual String filenameExtension() const { return "ico"; } @@ -67,19 +68,16 @@ namespace WebCore { // Returns true if |a| is a preferable icon entry to |b|. // Larger sizes, or greater bitdepths at the same size, are preferable. - static bool compareEntries(const IconDirectoryEntry& a, - const IconDirectoryEntry& b); + static bool compareEntries(const IconDirectoryEntry& a, const IconDirectoryEntry& b); inline uint16_t readUint16(int offset) const { - return BMPImageReader::readUint16(m_data.get(), - m_decodedOffset + offset); + return BMPImageReader::readUint16(m_data.get(), m_decodedOffset + offset); } inline uint32_t readUint32(int offset) const { - return BMPImageReader::readUint32(m_data.get(), - m_decodedOffset + offset); + return BMPImageReader::readUint32(m_data.get(), m_decodedOffset + offset); } // If the desired PNGImageDecoder exists, gives it the appropriate data. @@ -88,12 +86,7 @@ namespace WebCore { // Decodes the entry at |index|. If |onlySize| is true, stops decoding // after calculating the image size. If decoding fails but there is no // more data coming, sets the "decode failure" flag. - // - // NOTE: If the desired entry is a PNG, this doesn't actually trigger - // decoding, it merely ensures the decoder is created and ready to - // decode. The caller will then call a function on the PNGImageDecoder - // that actually triggers decoding. - void decodeWithCheckForDataEnded(size_t index, bool onlySize); + void decode(size_t index, bool onlySize); // Decodes the directory and directory entries at the beginning of the // data, and initializes members. Returns true if all decoding @@ -120,9 +113,6 @@ namespace WebCore { // if the type could be determined. ImageType imageTypeAtIndex(size_t); - // True if we've seen all the data. - bool m_allDataReceived; - // An index into |m_data| representing how much we've already decoded. // Note that this only tracks data _this_ class decodes; once the // BMPImageReader takes over this will not be updated further. diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp index aaa9047..9ed20b6 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp @@ -59,18 +59,17 @@ extern "C" { namespace WebCore { struct decoder_error_mgr { - struct jpeg_error_mgr pub; /* "public" fields for IJG library*/ - jmp_buf setjmp_buffer; /* For handling catastropic errors */ + struct jpeg_error_mgr pub; // "public" fields for IJG library + jmp_buf setjmp_buffer; // For handling catastropic errors }; enum jstate { - JPEG_HEADER, /* Reading JFIF headers */ + JPEG_HEADER, // Reading JFIF headers JPEG_START_DECOMPRESS, - JPEG_DECOMPRESS_PROGRESSIVE, /* Output progressive pixels */ - JPEG_DECOMPRESS_SEQUENTIAL, /* Output sequential pixels */ + JPEG_DECOMPRESS_PROGRESSIVE, // Output progressive pixels + JPEG_DECOMPRESS_SEQUENTIAL, // Output sequential pixels JPEG_DONE, - JPEG_SINK_NON_JPEG_TRAILER, /* Some image files have a */ - /* non-JPEG trailer */ + JPEG_SINK_NON_JPEG_TRAILER, // Some image files have a non-JPEG trailer JPEG_ERROR }; @@ -80,14 +79,12 @@ void skip_input_data(j_decompress_ptr jd, long num_bytes); void term_source(j_decompress_ptr jd); void error_exit(j_common_ptr cinfo); -/* - * Implementation of a JPEG src object that understands our state machine - */ +// Implementation of a JPEG src object that understands our state machine struct decoder_source_mgr { - /* public fields; must be first in this struct! */ - struct jpeg_source_mgr pub; + // public fields; must be first in this struct! + struct jpeg_source_mgr pub; - JPEGImageReader *decoder; + JPEGImageReader* decoder; }; class JPEGImageReader @@ -102,11 +99,11 @@ public: { memset(&m_info, 0, sizeof(jpeg_decompress_struct)); - /* We set up the normal JPEG error routines, then override error_exit. */ + // We set up the normal JPEG error routines, then override error_exit. m_info.err = jpeg_std_error(&m_err.pub); m_err.pub.error_exit = error_exit; - /* Allocate and initialize JPEG decompression object */ + // Allocate and initialize JPEG decompression object. jpeg_create_decompress(&m_info); decoder_source_mgr* src = 0; @@ -120,7 +117,7 @@ public: m_info.src = (jpeg_source_mgr*)src; - /* Set up callback functions. */ + // Set up callback functions. src->pub.init_source = init_source; src->pub.fill_input_buffer = fill_input_buffer; src->pub.skip_input_data = skip_input_data; @@ -148,22 +145,20 @@ public: long bytesToSkip = std::min(num_bytes, (long)src->pub.bytes_in_buffer); src->pub.bytes_in_buffer -= (size_t)bytesToSkip; src->pub.next_input_byte += bytesToSkip; - - if (num_bytes > bytesToSkip) - m_bytesToSkip = (size_t)(num_bytes - bytesToSkip); - else - m_bytesToSkip = 0; + + m_bytesToSkip = std::max(num_bytes - bytesToSkip, static_cast<long>(0)); } - bool decode(const Vector<char>& data, bool sizeOnly) { - m_decodingSizeOnly = sizeOnly; - + bool decode(const Vector<char>& data, bool onlySize) + { + m_decodingSizeOnly = onlySize; + unsigned newByteCount = data.size() - m_bufferLength; unsigned readOffset = m_bufferLength - m_info.src->bytes_in_buffer; m_info.src->bytes_in_buffer += newByteCount; m_info.src->next_input_byte = (JOCTET*)(data.data()) + readOffset; - + // If we still have bytes to skip, try to skip those now. if (m_bytesToSkip) skipBytes(m_bytesToSkip); @@ -178,172 +173,150 @@ public: } switch (m_state) { - case JPEG_HEADER: - { - /* Read file parameters with jpeg_read_header() */ - if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED) - return true; /* I/O suspension */ - - /* let libjpeg take care of gray->RGB and YCbCr->RGB conversions */ - switch (m_info.jpeg_color_space) { - case JCS_GRAYSCALE: - case JCS_RGB: - case JCS_YCbCr: - m_info.out_color_space = JCS_RGB; - break; - case JCS_CMYK: - case JCS_YCCK: - // jpeglib cannot convert these to rgb, but it can - // convert ycck to cmyk - m_info.out_color_space = JCS_CMYK; - break; - default: - m_state = JPEG_ERROR; - return false; - } - - /* - * Don't allocate a giant and superfluous memory buffer - * when the image is a sequential JPEG. - */ - m_info.buffered_image = jpeg_has_multiple_scans(&m_info); - - /* Used to set up image size so arrays can be allocated */ - jpeg_calc_output_dimensions(&m_info); - - /* - * Make a one-row-high sample array that will go away - * when done with image. Always make it big enough to - * hold an RGB row. Since this uses the IJG memory - * manager, it must be allocated before the call to - * jpeg_start_compress(). - */ - int row_stride = m_info.output_width * 4; // RGBA buffer + case JPEG_HEADER: + // Read file parameters with jpeg_read_header(). + if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED) + return true; // I/O suspension. + + // Let libjpeg take care of gray->RGB and YCbCr->RGB conversions. + switch (m_info.jpeg_color_space) { + case JCS_GRAYSCALE: + case JCS_RGB: + case JCS_YCbCr: + m_info.out_color_space = JCS_RGB; + break; + case JCS_CMYK: + case JCS_YCCK: + // jpeglib cannot convert these to rgb, but it can convert ycck + // to cmyk. + m_info.out_color_space = JCS_CMYK; + break; + default: + m_state = JPEG_ERROR; + return false; + } + // Don't allocate a giant and superfluous memory buffer when the + // image is a sequential JPEG. + m_info.buffered_image = jpeg_has_multiple_scans(&m_info); - m_samples = (*m_info.mem->alloc_sarray)((j_common_ptr) &m_info, - JPOOL_IMAGE, - row_stride, 1); + // Used to set up image size so arrays can be allocated. + jpeg_calc_output_dimensions(&m_info); - m_state = JPEG_START_DECOMPRESS; + // Make a one-row-high sample array that will go away when done with + // image. Always make it big enough to hold an RGB row. Since this + // uses the IJG memory manager, it must be allocated before the call + // to jpeg_start_compress(). + m_samples = (*m_info.mem->alloc_sarray)((j_common_ptr) &m_info, JPOOL_IMAGE, m_info.output_width * 4, 1); - // We can fill in the size now that the header is available. - if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) { - m_state = JPEG_ERROR; - return false; - } + m_state = JPEG_START_DECOMPRESS; - if (m_decodingSizeOnly) { - // We can stop here. - // Reduce our buffer length and available data. - m_bufferLength -= m_info.src->bytes_in_buffer; - m_info.src->bytes_in_buffer = 0; - return true; - } + // We can fill in the size now that the header is available. + if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) { + m_state = JPEG_ERROR; + return false; } - case JPEG_START_DECOMPRESS: - { - /* Set parameters for decompression */ - /* FIXME -- Should reset dct_method and dither mode - * for final pass of progressive JPEG - */ - m_info.dct_method = JDCT_ISLOW; - m_info.dither_mode = JDITHER_FS; - m_info.do_fancy_upsampling = true; - m_info.enable_2pass_quant = false; - m_info.do_block_smoothing = true; - - /* Start decompressor */ - if (!jpeg_start_decompress(&m_info)) - return true; /* I/O suspension */ - - /* If this is a progressive JPEG ... */ - m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JPEG_DECOMPRESS_SEQUENTIAL; + if (m_decodingSizeOnly) { + // We can stop here. Reduce our buffer length and available + // data. + m_bufferLength -= m_info.src->bytes_in_buffer; + m_info.src->bytes_in_buffer = 0; + return true; } - - case JPEG_DECOMPRESS_SEQUENTIAL: - { - if (m_state == JPEG_DECOMPRESS_SEQUENTIAL) { - - if (!m_decoder->outputScanlines()) - return true; /* I/O suspension */ - - /* If we've completed image output ... */ - ASSERT(m_info.output_scanline == m_info.output_height); - m_state = JPEG_DONE; - } + // FALL THROUGH + + case JPEG_START_DECOMPRESS: + // Set parameters for decompression. + // FIXME -- Should reset dct_method and dither mode for final pass + // of progressive JPEG. + m_info.dct_method = JDCT_ISLOW; + m_info.dither_mode = JDITHER_FS; + m_info.do_fancy_upsampling = true; + m_info.enable_2pass_quant = false; + m_info.do_block_smoothing = true; + + // Start decompressor. + if (!jpeg_start_decompress(&m_info)) + return true; // I/O suspension. + + // If this is a progressive JPEG ... + m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JPEG_DECOMPRESS_SEQUENTIAL; + // FALL THROUGH + + case JPEG_DECOMPRESS_SEQUENTIAL: + if (m_state == JPEG_DECOMPRESS_SEQUENTIAL) { + + if (!m_decoder->outputScanlines()) + return true; // I/O suspension. + + // If we've completed image output... + ASSERT(m_info.output_scanline == m_info.output_height); + m_state = JPEG_DONE; } + // FALL THROUGH + + case JPEG_DECOMPRESS_PROGRESSIVE: + if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) { + int status; + do { + status = jpeg_consume_input(&m_info); + } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_EOI)); + + for (;;) { + if (!m_info.output_scanline) { + int scan = m_info.input_scan_number; + + // If we haven't displayed anything yet + // (output_scan_number == 0) and we have enough data for + // a complete scan, force output of the last full scan. + if (!m_info.output_scan_number && (scan > 1) && (status != JPEG_REACHED_EOI)) + --scan; + + if (!jpeg_start_output(&m_info, scan)) + return true; // I/O suspension. + } + + if (m_info.output_scanline == 0xffffff) + m_info.output_scanline = 0; - case JPEG_DECOMPRESS_PROGRESSIVE: - { - if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) { - int status; - do { - status = jpeg_consume_input(&m_info); - } while ((status != JPEG_SUSPENDED) && - (status != JPEG_REACHED_EOI)); - - for (;;) { - if (m_info.output_scanline == 0) { - int scan = m_info.input_scan_number; - - /* if we haven't displayed anything yet (output_scan_number==0) - and we have enough data for a complete scan, force output - of the last full scan */ - if ((m_info.output_scan_number == 0) && - (scan > 1) && - (status != JPEG_REACHED_EOI)) - scan--; - - if (!jpeg_start_output(&m_info, scan)) - return true; /* I/O suspension */ - } - - if (m_info.output_scanline == 0xffffff) - m_info.output_scanline = 0; - - if (!m_decoder->outputScanlines()) { - if (m_info.output_scanline == 0) - /* didn't manage to read any lines - flag so we don't call - jpeg_start_output() multiple times for the same scan */ - m_info.output_scanline = 0xffffff; - return true; /* I/O suspension */ - } - - if (m_info.output_scanline == m_info.output_height) { - if (!jpeg_finish_output(&m_info)) - return true; /* I/O suspension */ - - if (jpeg_input_complete(&m_info) && - (m_info.input_scan_number == m_info.output_scan_number)) - break; - - m_info.output_scanline = 0; - } + if (!m_decoder->outputScanlines()) { + if (!m_info.output_scanline) + // Didn't manage to read any lines - flag so we + // don't call jpeg_start_output() multiple times for + // the same scan. + m_info.output_scanline = 0xffffff; + return true; // I/O suspension. } - m_state = JPEG_DONE; - } - } + if (m_info.output_scanline == m_info.output_height) { + if (!jpeg_finish_output(&m_info)) + return true; // I/O suspension. - case JPEG_DONE: - { - /* Finish decompression */ - if (!jpeg_finish_decompress(&m_info)) - return true; /* I/O suspension */ + if (jpeg_input_complete(&m_info) && (m_info.input_scan_number == m_info.output_scan_number)) + break; - m_state = JPEG_SINK_NON_JPEG_TRAILER; + m_info.output_scanline = 0; + } + } - /* we're done */ - break; + m_state = JPEG_DONE; } - - case JPEG_SINK_NON_JPEG_TRAILER: - break; + // FALL THROUGH - case JPEG_ERROR: - break; + case JPEG_DONE: + // Finish decompression. + if (!jpeg_finish_decompress(&m_info)) + return true; // I/O suspension. + + m_state = JPEG_SINK_NON_JPEG_TRAILER; + break; + + case JPEG_SINK_NON_JPEG_TRAILER: + break; + + case JPEG_ERROR: + break; } return true; @@ -367,10 +340,10 @@ private: JSAMPARRAY m_samples; }; -/* Override the standard error method in the IJG JPEG decoder code. */ +// Override the standard error method in the IJG JPEG decoder code. void error_exit(j_common_ptr cinfo) { - /* Return control to the setjmp point. */ + // Return control to the setjmp point. decoder_error_mgr *err = (decoder_error_mgr *) cinfo->err; longjmp(err->setjmp_buffer, -1); } @@ -388,12 +361,12 @@ void skip_input_data(j_decompress_ptr jd, long num_bytes) boolean fill_input_buffer(j_decompress_ptr jd) { // Our decode step always sets things up properly, so if this method is ever - // called, then we have hit the end of the buffer. A return value of FALSE indicates - // that we have no data to supply yet. + // called, then we have hit the end of the buffer. A return value of false + // indicates that we have no data to supply yet. return false; } -void term_source (j_decompress_ptr jd) +void term_source(j_decompress_ptr jd) { decoder_source_mgr *src = (decoder_source_mgr *)jd->src; src->decoder->decoder()->jpegComplete(); @@ -407,21 +380,17 @@ JPEGImageDecoder::~JPEGImageDecoder() { } -// Take the data and store it. void JPEGImageDecoder::setData(SharedBuffer* data, bool allDataReceived) { if (m_failed) return; - // Cache our new data. ImageDecoder::setData(data, allDataReceived); - // Create the JPEG reader. if (!m_reader && !m_failed) m_reader.set(new JPEGImageReader(this)); } -// Whether or not the size information has been decoded yet. bool JPEGImageDecoder::isSizeAvailable() { if (!ImageDecoder::isSizeAvailable() && !failed() && m_reader) @@ -434,6 +403,7 @@ bool JPEGImageDecoder::setSize(unsigned width, unsigned height) { if (!ImageDecoder::setSize(width, height)) return false; + prepareScaleDataIfNecessary(); return true; } @@ -448,23 +418,10 @@ RGBA32Buffer* JPEGImageDecoder::frameBufferAtIndex(size_t index) RGBA32Buffer& frame = m_frameBufferCache[0]; if (frame.status() != RGBA32Buffer::FrameComplete && m_reader) - // Decode this frame. - decode(); + decode(false); return &frame; } -// Feed data to the JPEG reader. -void JPEGImageDecoder::decode(bool sizeOnly) -{ - if (m_failed) - return; - - m_failed = !m_reader->decode(m_data->buffer(), sizeOnly); - - if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) - m_reader.clear(); -} - bool JPEGImageDecoder::outputScanlines() { if (m_frameBufferCache.isEmpty()) @@ -531,9 +488,20 @@ void JPEGImageDecoder::jpegComplete() if (m_frameBufferCache.isEmpty()) return; - // Hand back an appropriately sized buffer, even if the image ended up being empty. - RGBA32Buffer& buffer = m_frameBufferCache[0]; - buffer.setStatus(RGBA32Buffer::FrameComplete); + // Hand back an appropriately sized buffer, even if the image ended up being + // empty. + m_frameBufferCache[0].setStatus(RGBA32Buffer::FrameComplete); +} + +void JPEGImageDecoder::decode(bool onlySize) +{ + if (m_failed) + return; + + m_failed = !m_reader->decode(m_data->buffer(), onlySize); + + if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) + m_reader.clear(); } } diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h index d8bfd70..2a95dbe 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h @@ -38,28 +38,24 @@ namespace WebCore { class JPEGImageDecoder : public ImageDecoder { public: JPEGImageDecoder(); - ~JPEGImageDecoder(); + virtual ~JPEGImageDecoder(); + // ImageDecoder virtual String filenameExtension() const { return "jpg"; } - - // Take the data and store it. virtual void setData(SharedBuffer* data, bool allDataReceived); - - // Whether or not the size information has been decoded yet. virtual bool isSizeAvailable(); - virtual bool setSize(unsigned width, unsigned height); - virtual RGBA32Buffer* frameBufferAtIndex(size_t index); - virtual bool supportsAlpha() const { return false; } - void decode(bool sizeOnly = false); - bool outputScanlines(); void jpegComplete(); private: + // Decodes the image. If |onlySize| is true, stops decoding after + // calculating the image size. + void decode(bool onlySize); + OwnPtr<JPEGImageReader> m_reader; }; diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp index 35c8af0..36f818f 100644 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp @@ -52,21 +52,41 @@ const double cInverseGamma = 0.45455; const unsigned long cMaxPNGSize = 1000000UL; // Called if the decoding of the image fails. -static void PNGAPI decodingFailed(png_structp png_ptr, png_const_charp error_msg); +static void PNGAPI decodingFailed(png_structp png, png_const_charp) +{ + static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->decodingFailed(); + longjmp(png->jmpbuf, 1); +} -// Callbacks given to the read struct. The first is for warnings (we want to treat a particular warning -// as an error, which is why we have to register this callback. -static void PNGAPI decodingWarning(png_structp png_ptr, png_const_charp warning_msg); +// Callbacks given to the read struct. The first is for warnings (we want to +// treat a particular warning as an error, which is why we have to register this +// callback). +static void PNGAPI decodingWarning(png_structp png, png_const_charp warningMsg) +{ + // Mozilla did this, so we will too. + // Convert a tRNS warning to be an error (see + // http://bugzilla.mozilla.org/show_bug.cgi?id=251381 ) + if (!strncmp(warningMsg, "Missing PLTE before tRNS", 24)) + png_error(png, warningMsg); +} // Called when we have obtained the header information (including the size). -static void PNGAPI headerAvailable(png_structp png_ptr, png_infop info_ptr); +static void PNGAPI headerAvailable(png_structp png, png_infop) +{ + static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->headerAvailable(); +} // Called when a row is ready. -static void PNGAPI rowAvailable(png_structp png_ptr, png_bytep new_row, - png_uint_32 row_num, int pass); +static void PNGAPI rowAvailable(png_structp png, png_bytep rowBuffer, png_uint_32 rowIndex, int interlacePass) +{ + static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->rowAvailable(rowBuffer, rowIndex, interlacePass); +} // Called when we have completely finished decoding the image. -static void PNGAPI pngComplete(png_structp png_ptr, png_infop info_ptr); +static void PNGAPI pngComplete(png_structp png, png_infop) +{ + static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->pngComplete(); +} class PNGImageReader { @@ -75,7 +95,7 @@ public: : m_readOffset(0) , m_decodingSizeOnly(false) , m_interlaceBuffer(0) - , m_hasAlpha(0) + , m_hasAlpha(false) , m_hasFinishedDecoding(false) , m_currentBufferSize(0) { @@ -89,10 +109,12 @@ public: close(); } - void close() { + void close() + { if (m_png && m_info) - png_destroy_read_struct(&m_png, &m_info, 0); // Will zero the pointers. - delete []m_interlaceBuffer; + // This will zero the pointers. + png_destroy_read_struct(&m_png, &m_info, 0); + delete[] m_interlaceBuffer; m_interlaceBuffer = 0; m_readOffset = 0; m_hasFinishedDecoding = false; @@ -106,7 +128,7 @@ public: { m_decodingSizeOnly = sizeOnly; - // We need to do the setjmp here. Otherwise bad things will happen + // We need to do the setjmp here. Otherwise bad things will happen. if (setjmp(m_png->jmpbuf)) { close(); return; @@ -134,9 +156,7 @@ public: void setReadOffset(unsigned offset) { m_readOffset = offset; } void setHasAlpha(bool b) { m_hasAlpha = b; } - void createInterlaceBuffer(int size) { - m_interlaceBuffer = new png_byte[size]; - } + void createInterlaceBuffer(int size) { m_interlaceBuffer = new png_byte[size]; } private: unsigned m_readOffset; @@ -157,21 +177,16 @@ PNGImageDecoder::~PNGImageDecoder() { } -// Take the data and store it. void PNGImageDecoder::setData(SharedBuffer* data, bool allDataReceived) { if (m_failed) return; - // Cache our new data. ImageDecoder::setData(data, allDataReceived); - // Create the PNG reader. if (!m_reader && !m_failed) m_reader.set(new PNGImageReader(this)); } - -// Whether or not the size information has been decoded yet. bool PNGImageDecoder::isSizeAvailable() { if (!ImageDecoder::isSizeAvailable() && !failed() && m_reader) @@ -191,41 +206,10 @@ RGBA32Buffer* PNGImageDecoder::frameBufferAtIndex(size_t index) RGBA32Buffer& frame = m_frameBufferCache[0]; if (frame.status() != RGBA32Buffer::FrameComplete && m_reader) // Decode this frame. - decode(); + decode(false); return &frame; } -// Feed data to the PNG reader. -void PNGImageDecoder::decode(bool sizeOnly) -{ - if (m_failed) - return; - - m_reader->decode(*m_data, sizeOnly); - - if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) - m_reader.clear(); -} - -void decodingFailed(png_structp png, png_const_charp errorMsg) -{ - static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->decodingFailed(); - longjmp(png->jmpbuf, 1); -} - -void decodingWarning(png_structp png, png_const_charp warningMsg) -{ - // Mozilla did this, so we will too. - // Convert a tRNS warning to be an error (documented in bugzilla.mozilla.org bug #251381) - if (!strncmp(warningMsg, "Missing PLTE before tRNS", 24)) - png_error(png, warningMsg); -} - -void headerAvailable(png_structp png, png_infop info) -{ - static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->headerAvailable(); -} - void PNGImageDecoder::decodingFailed() { m_failed = true; @@ -256,14 +240,12 @@ void PNGImageDecoder::headerAvailable() } int bitDepth, colorType, interlaceType, compressionType, filterType, channels; - png_get_IHDR(png, info, &width, &height, &bitDepth, &colorType, - &interlaceType, &compressionType, &filterType); + png_get_IHDR(png, info, &width, &height, &bitDepth, &colorType, &interlaceType, &compressionType, &filterType); // The options we set here match what Mozilla does. // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA. - if (colorType == PNG_COLOR_TYPE_PALETTE || - (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8)) + if (colorType == PNG_COLOR_TYPE_PALETTE || (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8)) png_set_expand(png); png_bytep trns = 0; @@ -276,8 +258,7 @@ void PNGImageDecoder::headerAvailable() if (bitDepth == 16) png_set_strip_16(png); - if (colorType == PNG_COLOR_TYPE_GRAY || - colorType == PNG_COLOR_TYPE_GRAY_ALPHA) + if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); // Deal with gamma and keep it under our control. @@ -288,15 +269,14 @@ void PNGImageDecoder::headerAvailable() png_set_gAMA(png, info, gamma); } png_set_gamma(png, cDefaultGamma, gamma); - } - else + } else png_set_gamma(png, cDefaultGamma, cInverseGamma); // Tell libpng to send us rows for interlaced pngs. if (interlaceType == PNG_INTERLACE_ADAM7) png_set_interlace_handling(png); - // Update our info now + // Update our info now. png_read_update_info(png, info); channels = png_get_channels(png, info); ASSERT(channels == 3 || channels == 4); @@ -310,12 +290,6 @@ void PNGImageDecoder::headerAvailable() } } -void rowAvailable(png_structp png, png_bytep rowBuffer, - png_uint_32 rowIndex, int interlacePass) -{ - static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->rowAvailable(rowBuffer, rowIndex, interlacePass); -} - void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int interlacePass) { if (m_frameBufferCache.isEmpty()) @@ -339,36 +313,36 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, m_reader->createInterlaceBuffer((m_reader->hasAlpha() ? 4 : 3) * size().width() * size().height()); } - if (rowBuffer == 0) + if (!rowBuffer) return; - /* libpng comments (pasted in here to explain what follows) - * - * this function is called for every row in the image. If the - * image is interlacing, and you turned on the interlace handler, - * this function will be called for every row in every pass. - * Some of these rows will not be changed from the previous pass. - * When the row is not changed, the new_row variable will be NULL. - * The rows and passes are called in order, so you don't really - * need the row_num and pass, but I'm supplying them because it - * may make your life easier. - * - * For the non-NULL rows of interlaced images, you must call - * png_progressive_combine_row() passing in the row and the - * old row. You can call this function for NULL rows (it will - * just return) and for non-interlaced images (it just does the - * memcpy for you) if it will make the code easier. Thus, you - * can just do this for all cases: - * - * png_progressive_combine_row(png_ptr, old_row, new_row); - * - * where old_row is what was displayed for previous rows. Note - * that the first pass (pass == 0 really) will completely cover - * the old row, so the rows do not have to be initialized. After - * the first pass (and only for interlaced images), you will have - * to pass the current row, and the function will combine the - * old row and the new row. - */ + // libpng comments (pasted in here to explain what follows) + /* + * this function is called for every row in the image. If the + * image is interlacing, and you turned on the interlace handler, + * this function will be called for every row in every pass. + * Some of these rows will not be changed from the previous pass. + * When the row is not changed, the new_row variable will be NULL. + * The rows and passes are called in order, so you don't really + * need the row_num and pass, but I'm supplying them because it + * may make your life easier. + * + * For the non-NULL rows of interlaced images, you must call + * png_progressive_combine_row() passing in the row and the + * old row. You can call this function for NULL rows (it will + * just return) and for non-interlaced images (it just does the + * memcpy for you) if it will make the code easier. Thus, you + * can just do this for all cases: + * + * png_progressive_combine_row(png_ptr, old_row, new_row); + * + * where old_row is what was displayed for previous rows. Note + * that the first pass (pass == 0 really) will completely cover + * the old row, so the rows do not have to be initialized. After + * the first pass (and only for interlaced images), you will have + * to pass the current row, and the function will combine the + * old row and the new row. + */ png_structp png = m_reader->pngPtr(); bool hasAlpha = m_reader->hasAlpha(); @@ -378,8 +352,7 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, if (interlaceBuffer) { row = interlaceBuffer + (rowIndex * colorChannels * size().width()); png_progressive_combine_row(png, row, rowBuffer); - } - else + } else row = rowBuffer; // Copy the data into our buffer. @@ -388,7 +361,7 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, if (destY < 0) return; bool sawAlpha = buffer.hasAlpha(); - for (int x = 0; x < width; x++) { + for (int x = 0; x < width; ++x) { png_bytep pixel = row + (m_scaled ? m_scaledColumns[x] : x) * colorChannels; unsigned alpha = hasAlpha ? pixel[3] : 255; buffer.setRGBA(x, destY, pixel[0], pixel[1], pixel[2], alpha); @@ -399,21 +372,23 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, } } -void pngComplete(png_structp png, png_infop info) -{ - static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->pngComplete(); -} - void PNGImageDecoder::pngComplete() { m_reader->setComplete(); - if (m_frameBufferCache.isEmpty()) + if (!m_frameBufferCache.isEmpty()) + m_frameBufferCache.first().setStatus(RGBA32Buffer::FrameComplete); +} + +void PNGImageDecoder::decode(bool onlySize) +{ + if (m_failed) return; - // Hand back an appropriately sized buffer, even if the image ended up being empty. - RGBA32Buffer& buffer = m_frameBufferCache[0]; - buffer.setStatus(RGBA32Buffer::FrameComplete); + m_reader->decode(*m_data, onlySize); + + if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) + m_reader.clear(); } } // namespace WebCore diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.h b/WebCore/platform/image-decoders/png/PNGImageDecoder.h index 07a0b3a..ba0e19a 100644 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.h +++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.h @@ -37,20 +37,14 @@ namespace WebCore { class PNGImageDecoder : public ImageDecoder { public: PNGImageDecoder(); - ~PNGImageDecoder(); + virtual ~PNGImageDecoder(); + // ImageDecoder virtual String filenameExtension() const { return "png"; } - - // Take the data and store it. virtual void setData(SharedBuffer* data, bool allDataReceived); - - // Whether or not the size information has been decoded yet. virtual bool isSizeAvailable(); - virtual RGBA32Buffer* frameBufferAtIndex(size_t index); - void decode(bool sizeOnly = false); - // Callbacks from libpng void decodingFailed(); void headerAvailable(); @@ -58,6 +52,10 @@ namespace WebCore { void pngComplete(); private: + // Decodes the image. If |onlySize| is true, stops decoding after + // calculating the image size. + void decode(bool onlySize); + OwnPtr<PNGImageReader> m_reader; }; diff --git a/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp b/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp index d3218cd..b2e5e17 100644 --- a/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp +++ b/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp @@ -42,12 +42,17 @@ RGBA32Buffer::RGBA32Buffer() { } -// The image must not have format 8888 pre multiplied... -void RGBA32Buffer::setDecodedImage(const QImage& image) +RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other) { - m_image = image; - m_size = image.size(); - m_hasAlpha = image.hasAlphaChannel(); + if (this == &other) + return *this; + + copyBitmapData(other); + setRect(other.rect()); + setStatus(other.status()); + setDuration(other.duration()); + setDisposalMethod(other.disposalMethod()); + return *this; } void RGBA32Buffer::clear() @@ -115,17 +120,12 @@ void RGBA32Buffer::setStatus(FrameStatus status) m_status = status; } -RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other) +// The image must not have format 8888 pre multiplied... +void RGBA32Buffer::setDecodedImage(const QImage& image) { - if (this == &other) - return *this; - - copyBitmapData(other); - setRect(other.rect()); - setStatus(other.status()); - setDuration(other.duration()); - setDisposalMethod(other.disposalMethod()); - return *this; + m_image = image; + m_size = image.size(); + m_hasAlpha = image.hasAlphaChannel(); } int RGBA32Buffer::width() const diff --git a/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp b/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp index 543eca8..928524a 100644 --- a/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp +++ b/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp @@ -39,6 +39,22 @@ RGBA32Buffer::RGBA32Buffer() { } +RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other) +{ + if (this == &other) + return *this; + + m_bitmap = other.m_bitmap; + // Keep the pixels locked since we will be writing directly into the + // bitmap throughout this object's lifetime. + m_bitmap.lockPixels(); + setRect(other.rect()); + setStatus(other.status()); + setDuration(other.duration()); + setDisposalMethod(other.disposalMethod()); + return *this; +} + void RGBA32Buffer::clear() { m_bitmap.reset(); @@ -105,22 +121,6 @@ void RGBA32Buffer::setStatus(FrameStatus status) m_bitmap.setDataComplete(); // Tell the bitmap it's done. } -RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other) -{ - if (this == &other) - return *this; - - m_bitmap = other.m_bitmap; - // Keep the pixels locked since we will be writing directly into the - // bitmap throughout this object's lifetime. - m_bitmap.lockPixels(); - setRect(other.rect()); - setStatus(other.status()); - setDuration(other.duration()); - setDisposalMethod(other.disposalMethod()); - return *this; -} - int RGBA32Buffer::width() const { return m_bitmap.width(); diff --git a/WebCore/platform/mac/PasteboardMac.mm b/WebCore/platform/mac/PasteboardMac.mm index 690637a..086b272 100644 --- a/WebCore/platform/mac/PasteboardMac.mm +++ b/WebCore/platform/mac/PasteboardMac.mm @@ -300,9 +300,7 @@ void Pasteboard::writeImage(Node* node, const KURL& url, const String& title) ASSERT(node->renderer() && node->renderer()->isImage()); RenderImage* renderer = toRenderImage(node->renderer()); CachedImage* cachedImage = renderer->cachedImage(); - ASSERT(cachedImage); - - if (cachedImage->errorOccurred()) + if (!cachedImage || cachedImage->errorOccurred()) return; NSArray* types = writableTypesForImage(); diff --git a/WebCore/platform/network/brew/DNSBrew.cpp b/WebCore/platform/network/brew/DNSBrew.cpp new file mode 100644 index 0000000..ed1767a --- /dev/null +++ b/WebCore/platform/network/brew/DNSBrew.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2010 Company 100, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DNS.h" + +#include "NotImplemented.h" + +namespace WebCore { + +void prefetchDNS(const String& hostname) +{ + // DNS prefetching is not implemented because the maximum number of UDP + // sockets is quite small in most BREW devices. + notImplemented(); +} + +} diff --git a/WebCore/platform/network/chromium/CookieJarChromium.cpp b/WebCore/platform/network/chromium/CookieJarChromium.cpp index 41cf331..e17816a 100644 --- a/WebCore/platform/network/chromium/CookieJarChromium.cpp +++ b/WebCore/platform/network/chromium/CookieJarChromium.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Google Inc. All rights reserved. + * Copyright (c) 2010, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -39,46 +39,32 @@ namespace WebCore { void setCookies(Document* document, const KURL& url, const String& value) { - ChromiumBridge::setCookies(url, document->firstPartyForCookies(), value); + ChromiumBridge::setCookies(document, url, value); } String cookies(const Document* document, const KURL& url) { - return ChromiumBridge::cookies(url, document->firstPartyForCookies()); + return ChromiumBridge::cookies(document, url); } String cookieRequestHeaderFieldValue(const Document* document, const KURL& url) { - // FIXME: move in ChromiumBridge? - Vector<Cookie> cookies; - getRawCookies(document, url, cookies); - String cookieLine; - // FIXME: Set $Version=v; - for (size_t i = 0; i < cookies.size(); i++) { - Cookie cookie = cookies[i]; - if (i > 0) - cookieLine += "; "; - if (!cookie.name.isEmpty()) - cookieLine += cookie.name + "="; - cookieLine += cookie.value; - // FIXME: set $Path, $Domain, ... - } - return cookieLine; + return ChromiumBridge::cookieRequestHeaderFieldValue(document, url); } bool cookiesEnabled(const Document* document) { - return ChromiumBridge::cookiesEnabled(document->cookieURL(), document->firstPartyForCookies()); + return ChromiumBridge::cookiesEnabled(document); } bool getRawCookies(const Document* document, const KURL& url, Vector<Cookie>& rawCookies) { - return ChromiumBridge::rawCookies(url, document->firstPartyForCookies(), &rawCookies); + return ChromiumBridge::rawCookies(document, url, rawCookies); } -void deleteCookie(const Document*, const KURL& url, const String& cookieName) +void deleteCookie(const Document* document, const KURL& url, const String& cookieName) { - return ChromiumBridge::deleteCookie(url, cookieName); + return ChromiumBridge::deleteCookie(document, url, cookieName); } } // namespace WebCore diff --git a/WebCore/platform/network/chromium/ResourceRequest.cpp b/WebCore/platform/network/chromium/ResourceRequest.cpp index 5b27c1b..016bd34 100644 --- a/WebCore/platform/network/chromium/ResourceRequest.cpp +++ b/WebCore/platform/network/chromium/ResourceRequest.cpp @@ -31,7 +31,10 @@ namespace WebCore { // This is used by the loader to control the number of issued parallel load requests. unsigned initializeMaximumHTTPConnectionCountPerHost() { - return 6; + // The chromium network stack already handles limiting the number of + // parallel requests per host, so there's no need to do it here. Therefore, + // this is set to a high value that should never be hit in practice. + return 10000; } } // namespace WebCore diff --git a/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/WebCore/platform/network/soup/ResourceHandleSoup.cpp index ee8e7aa..4c59d34 100644 --- a/WebCore/platform/network/soup/ResourceHandleSoup.cpp +++ b/WebCore/platform/network/soup/ResourceHandleSoup.cpp @@ -380,6 +380,7 @@ static gboolean parseDataUrl(gpointer callback_data) String charset = extractCharsetFromMediaType(mediaType); ResourceResponse response; + response.setURL(handle->request().url()); response.setMimeType(mimeType); if (isBase64) { @@ -387,7 +388,10 @@ static gboolean parseDataUrl(gpointer callback_data) response.setTextEncodingName(charset); client->didReceiveResponse(handle, response); - if (d->m_cancelled) + // The load may be cancelled, and the client may be destroyed + // by any of the client reporting calls, so we check, and bail + // out in either of those cases. + if (!handle->client() || d->m_cancelled) return false; // Use the GLib Base64, since WebCore's decoder isn't @@ -404,16 +408,16 @@ static gboolean parseDataUrl(gpointer callback_data) response.setTextEncodingName("UTF-16"); client->didReceiveResponse(handle, response); - if (d->m_cancelled) + if (!handle->client() || d->m_cancelled) return false; if (data.length() > 0) client->didReceiveData(handle, reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0); - - if (d->m_cancelled) - return false; } + if (!handle->client() || d->m_cancelled) + return false; + client->didFinishLoading(handle); return false; @@ -565,6 +569,11 @@ static bool startHttp(ResourceHandle* handle) // balanced by a deref() in finishedCallback, which should always run handle->ref(); + // Make sure we have an Accept header for subresources; some sites + // want this to serve some of their subresources + if (!soup_message_headers_get_one(d->m_msg->request_headers, "Accept")) + soup_message_headers_append(d->m_msg->request_headers, "Accept", "*/*"); + // Balanced in ResourceHandleInternal's destructor; we need to // keep our own ref, because after queueing the message, the // session owns the initial reference. diff --git a/WebCore/platform/qt/PasteboardQt.cpp b/WebCore/platform/qt/PasteboardQt.cpp index 44c9eec..70ec546 100644 --- a/WebCore/platform/qt/PasteboardQt.cpp +++ b/WebCore/platform/qt/PasteboardQt.cpp @@ -151,7 +151,8 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String&) #ifndef QT_NO_CLIPBOARD CachedImage* cachedImage = toRenderImage(node->renderer())->cachedImage(); - ASSERT(cachedImage); + if (!cachedImage || cachedImage->errorOccurred()) + return; Image* image = cachedImage->image(); ASSERT(image); diff --git a/WebCore/platform/text/AtomicString.cpp b/WebCore/platform/text/AtomicString.cpp index 64c03cb..19821c0 100644 --- a/WebCore/platform/text/AtomicString.cpp +++ b/WebCore/platform/text/AtomicString.cpp @@ -248,7 +248,7 @@ PassRefPtr<StringImpl> AtomicString::add(const JSC::Identifier& identifier) return 0; UString::Rep* string = identifier.ustring().rep(); - unsigned length = string->size(); + unsigned length = string->length(); if (!length) return StringImpl::empty(); @@ -265,7 +265,7 @@ PassRefPtr<StringImpl> AtomicString::add(const JSC::UString& ustring) return 0; UString::Rep* string = ustring.rep(); - unsigned length = string->size(); + unsigned length = string->length(); if (!length) return StringImpl::empty(); @@ -282,7 +282,7 @@ AtomicStringImpl* AtomicString::find(const JSC::Identifier& identifier) return 0; UString::Rep* string = identifier.ustring().rep(); - unsigned length = string->size(); + unsigned length = string->length(); if (!length) return static_cast<AtomicStringImpl*>(StringImpl::empty()); diff --git a/WebCore/platform/text/StringImpl.cpp b/WebCore/platform/text/StringImpl.cpp index db6152d..3704c4e 100644 --- a/WebCore/platform/text/StringImpl.cpp +++ b/WebCore/platform/text/StringImpl.cpp @@ -52,36 +52,12 @@ static inline UChar* newUCharVector(unsigned n) return static_cast<UChar*>(fastMalloc(sizeof(UChar) * n)); } -static inline void deleteUCharVector(const UChar* p) -{ - fastFree(const_cast<UChar*>(p)); -} - -// Some of the factory methods create buffers using fastMalloc. -// We must ensure that all allocations of StringImpl are allocated using -// fastMalloc so that we don't have mis-matched frees. We accomplish -// this by overriding the new and delete operators. -void* StringImpl::operator new(size_t size, void* address) -{ - if (address) - return address; // Allocating using an internal buffer - return fastMalloc(size); -} - -void* StringImpl::operator new(size_t size) -{ - return fastMalloc(size); -} - -void StringImpl::operator delete(void* address) -{ - fastFree(address); -} - // This constructor is used only to create the empty string. StringImpl::StringImpl() : m_data(0) + , m_sharedBuffer(0) , m_length(0) + , m_refCountAndFlags(s_refCountIncrement | BufferInternal) , m_hash(0) { // Ensure that the hash is computed so that AtomicStringHash can call existingHash() @@ -90,35 +66,55 @@ StringImpl::StringImpl() hash(); } +inline StringImpl::StringImpl(unsigned length) + : m_data(reinterpret_cast<const UChar*>(this + 1)) + , m_sharedBuffer(0) + , m_length(length) + , m_refCountAndFlags(s_refCountIncrement | BufferInternal) + , m_hash(0) +{ + ASSERT(m_data); + ASSERT(m_length); +} + inline StringImpl::StringImpl(const UChar* characters, unsigned length) : m_data(characters) + , m_sharedBuffer(0) , m_length(length) + , m_refCountAndFlags(s_refCountIncrement | BufferOwned) , m_hash(0) { - ASSERT(characters); - ASSERT(length); - ASSERT(!bufferIsInternal()); + ASSERT(m_data); + ASSERT(m_length); } -inline StringImpl::StringImpl(unsigned length) - : m_data(reinterpret_cast<const UChar*>(this + 1)) +inline StringImpl::StringImpl(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer) + : m_data(characters) + , m_sharedBuffer(sharedBuffer.releaseRef()) , m_length(length) + , m_refCountAndFlags(s_refCountIncrement | BufferShared) , m_hash(0) { - ASSERT(length); - ASSERT(bufferIsInternal()); + ASSERT(m_data); + ASSERT(m_length); } StringImpl::~StringImpl() { if (inTable()) AtomicString::remove(this); - if (!bufferIsInternal()) { - SharedUChar* sharedBuffer = m_sharedBufferAndFlags.get(); - if (sharedBuffer) - sharedBuffer->deref(); - else - deleteUCharVector(m_data); + + BufferOwnership ownership = bufferOwnership(); + if (ownership != BufferInternal) { + if (ownership == BufferOwned) { + ASSERT(!m_sharedBuffer); + ASSERT(m_data); + fastFree(const_cast<UChar*>(m_data)); + } else { + ASSERT(ownership == BufferShared); + ASSERT(m_sharedBuffer); + m_sharedBuffer->deref(); + } } } @@ -976,13 +972,8 @@ PassRefPtr<StringImpl> StringImpl::create(const char* string) #if USE(JSC) PassRefPtr<StringImpl> StringImpl::create(const JSC::UString& str) { - SharedUChar* sharedBuffer = const_cast<JSC::UString*>(&str)->rep()->sharedBuffer(); - if (sharedBuffer) { - PassRefPtr<StringImpl> impl = adoptRef(new StringImpl(str.data(), str.size())); - sharedBuffer->ref(); - impl->m_sharedBufferAndFlags.set(sharedBuffer); - return impl; - } + if (SharedUChar* sharedBuffer = const_cast<JSC::UString*>(&str)->rep()->sharedBuffer()) + return adoptRef(new StringImpl(str.data(), str.size(), sharedBuffer)); return StringImpl::create(str.data(), str.size()); } @@ -1007,7 +998,7 @@ PassRefPtr<StringImpl> StringImpl::createWithTerminatingNullCharacter(const Stri data[length] = 0; terminatedString->m_length--; terminatedString->m_hash = string.m_hash; - terminatedString->m_sharedBufferAndFlags.setFlag(HasTerminatingNullCharacter); + terminatedString->m_refCountAndFlags |= s_refCountFlagHasTerminatingNullCharacter; return terminatedString.release(); } @@ -1021,12 +1012,8 @@ PassRefPtr<StringImpl> StringImpl::threadsafeCopy() const PassRefPtr<StringImpl> StringImpl::crossThreadString() { - SharedUChar* shared = sharedBuffer(); - if (shared) { - RefPtr<StringImpl> impl = adoptRef(new StringImpl(m_data, m_length)); - impl->m_sharedBufferAndFlags.set(shared->crossThreadCopy().releaseRef()); - return impl.release(); - } + if (SharedUChar* sharedBuffer = this->sharedBuffer()) + return adoptRef(new StringImpl(m_data, m_length, sharedBuffer->crossThreadCopy())); // If no shared buffer is available, create a copy. return threadsafeCopy(); @@ -1034,13 +1021,23 @@ PassRefPtr<StringImpl> StringImpl::crossThreadString() StringImpl::SharedUChar* StringImpl::sharedBuffer() { - if (m_length < minLengthToShare || bufferIsInternal()) + if (m_length < minLengthToShare) return 0; - if (!m_sharedBufferAndFlags.get()) - m_sharedBufferAndFlags.set(SharedUChar::create(new OwnFastMallocPtr<UChar>(const_cast<UChar*>(m_data))).releaseRef()); - return m_sharedBufferAndFlags.get(); -} + BufferOwnership ownership = bufferOwnership(); + if (ownership == BufferInternal) + return 0; + + if (ownership == BufferOwned) { + ASSERT(!m_sharedBuffer); + m_sharedBuffer = SharedUChar::create(new OwnFastMallocPtr<UChar>(const_cast<UChar*>(m_data))).releaseRef(); + m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared; + } + + ASSERT(bufferOwnership() == BufferShared); + ASSERT(m_sharedBuffer); + return m_sharedBuffer; +} } // namespace WebCore diff --git a/WebCore/platform/text/StringImpl.h b/WebCore/platform/text/StringImpl.h index 21f936d..65848bb 100644 --- a/WebCore/platform/text/StringImpl.h +++ b/WebCore/platform/text/StringImpl.h @@ -26,8 +26,8 @@ #include <limits.h> #include <wtf/ASCIICType.h> #include <wtf/CrossThreadRefCounted.h> +#include <wtf/Noncopyable.h> #include <wtf/OwnFastMallocPtr.h> -#include <wtf/PtrAndFlags.h> #include <wtf/RefCounted.h> #include <wtf/StringHashFunctions.h> #include <wtf/Vector.h> @@ -58,25 +58,33 @@ enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive }; typedef bool (*CharacterMatchFunctionPtr)(UChar); -class StringImpl : public RefCounted<StringImpl> { +class StringImpl : public Noncopyable { friend struct CStringTranslator; friend struct HashAndCharactersTranslator; friend struct UCharBufferTranslator; private: friend class ThreadGlobalData; - StringImpl(); - - // This constructor adopts the UChar* without copying the buffer. - StringImpl(const UChar*, unsigned length); - // This constructor assumes that 'this' was allocated with a UChar buffer of size 'length' at the end. + enum BufferOwnership { + BufferInternal, + BufferOwned, + BufferShared, + }; + + typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar; + + // Used to create the empty string (""), automatically hashes. + StringImpl(); + // Create a StringImpl with internal storage (BufferInternal) StringImpl(unsigned length); + // Create a StringImpl adopting ownership of the provided buffer (BufferOwned) + StringImpl(const UChar*, unsigned length); + // Create a StringImpl using a shared buffer (BufferShared) + StringImpl(const UChar*, unsigned length, PassRefPtr<SharedUChar>); // For use only by AtomicString's XXXTranslator helpers. void setHash(unsigned hash) { ASSERT(!m_hash); m_hash = hash; } - typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar; - public: ~StringImpl(); @@ -99,16 +107,20 @@ public: const UChar* characters() { return m_data; } unsigned length() { return m_length; } - bool hasTerminatingNullCharacter() const { return m_sharedBufferAndFlags.isFlagSet(HasTerminatingNullCharacter); } + bool hasTerminatingNullCharacter() const { return m_refCountAndFlags & s_refCountFlagHasTerminatingNullCharacter; } - bool inTable() const { return m_sharedBufferAndFlags.isFlagSet(InTable); } - void setInTable() { return m_sharedBufferAndFlags.setFlag(InTable); } + bool inTable() const { return m_refCountAndFlags & s_refCountFlagInTable; } + void setInTable() { m_refCountAndFlags |= s_refCountFlagInTable; } unsigned hash() { if (m_hash == 0) m_hash = computeHash(m_data, m_length); return m_hash; } unsigned existingHash() const { ASSERT(m_hash); return m_hash; } inline static unsigned computeHash(const UChar* data, unsigned length) { return WTF::stringHash(data, length); } inline static unsigned computeHash(const char* data) { return WTF::stringHash(data); } - + + StringImpl* ref() { m_refCountAndFlags += s_refCountIncrement; return this; } + ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) delete this; } + ALWAYS_INLINE bool hasOneRef() const { return (m_refCountAndFlags & s_refCountMask) == s_refCountIncrement; } + // Returns a StringImpl suitable for use on another thread. PassRefPtr<StringImpl> crossThreadString(); // Makes a deep copy. Helpful only if you need to use a String on another thread @@ -178,31 +190,27 @@ public: operator NSString*(); #endif - void operator delete(void*); - private: - // Allocation from a custom buffer is only allowed internally to avoid - // mismatched allocators. Callers should use create(). - void* operator new(size_t size); - void* operator new(size_t size, void* address); + using Noncopyable::operator new; + void* operator new(size_t, void* inPlace) { ASSERT(inPlace); return inPlace; } static PassRefPtr<StringImpl> createStrippingNullCharactersSlowCase(const UChar*, unsigned length); // The StringImpl struct and its data may be allocated within a single heap block. // In this case, the m_data pointer is an "internal buffer", and does not need to be deallocated. - bool bufferIsInternal() { return m_data == reinterpret_cast<const UChar*>(this + 1); } + BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); } - enum StringImplFlags { - HasTerminatingNullCharacter, - InTable, - }; + static const unsigned s_refCountMask = 0xFFFFFFF0; + static const unsigned s_refCountIncrement = 0x10; + static const unsigned s_refCountFlagHasTerminatingNullCharacter = 0x8; + static const unsigned s_refCountFlagInTable = 0x4; + static const unsigned s_refCountMaskBufferOwnership = 0x3; const UChar* m_data; + SharedUChar* m_sharedBuffer; unsigned m_length; + unsigned m_refCountAndFlags; mutable unsigned m_hash; - PtrAndFlags<SharedUChar, StringImplFlags> m_sharedBufferAndFlags; - // There is a fictitious variable-length UChar array at the end, which is used - // as the internal buffer by the createUninitialized and create methods. }; bool equal(StringImpl*, StringImpl*); diff --git a/WebCore/platform/win/PasteboardWin.cpp b/WebCore/platform/win/PasteboardWin.cpp index d09769a..ffafd02 100644 --- a/WebCore/platform/win/PasteboardWin.cpp +++ b/WebCore/platform/win/PasteboardWin.cpp @@ -205,7 +205,8 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String&) ASSERT(node && node->renderer() && node->renderer()->isImage()); RenderImage* renderer = toRenderImage(node->renderer()); CachedImage* cachedImage = renderer->cachedImage(); - ASSERT(cachedImage); + if (!cachedImage || cachedImage->errorOccurred()) + return; Image* image = cachedImage->image(); ASSERT(image); diff --git a/WebCore/plugins/PluginDatabase.cpp b/WebCore/plugins/PluginDatabase.cpp index 96e8aba..703ac87 100644 --- a/WebCore/plugins/PluginDatabase.cpp +++ b/WebCore/plugins/PluginDatabase.cpp @@ -262,8 +262,9 @@ PluginPackage* PluginDatabase::findPlugin(const KURL& url, String& mimeType) if (extensionPos != -1) { String extension = filename.substring(extensionPos + 1); - mimeType = MIMETypeForExtension(extension); - plugin = pluginForMIMEType(mimeType); + String mimeTypeForExtension = MIMETypeForExtension(extension); + if (plugin = pluginForMIMEType(mimeTypeForExtension)) + mimeType = mimeTypeForExtension; } } } diff --git a/WebCore/plugins/PluginPackage.cpp b/WebCore/plugins/PluginPackage.cpp index 9c12663..5949546 100644 --- a/WebCore/plugins/PluginPackage.cpp +++ b/WebCore/plugins/PluginPackage.cpp @@ -259,7 +259,7 @@ void PluginPackage::initializeBrowserFuncs() { memset(&m_browserFuncs, 0, sizeof(m_browserFuncs)); m_browserFuncs.size = sizeof(m_browserFuncs); - m_browserFuncs.version = NP_VERSION_MINOR; + m_browserFuncs.version = NPVersion(); m_browserFuncs.geturl = NPN_GetURL; m_browserFuncs.posturl = NPN_PostURL; diff --git a/WebCore/plugins/PluginPackage.h b/WebCore/plugins/PluginPackage.h index a3937f1..aa2d272 100644 --- a/WebCore/plugins/PluginPackage.h +++ b/WebCore/plugins/PluginPackage.h @@ -55,6 +55,7 @@ namespace WebCore { const String& path() const { return m_path; } const String& fileName() const { return m_fileName; } const String& parentDirectory() const { return m_parentDirectory; } + uint16 NPVersion() const; time_t lastModified() const { return m_lastModified; } const MIMEToDescriptionsMap& mimeToDescriptions() const { return m_mimeToDescriptions; } diff --git a/WebCore/plugins/PluginView.cpp b/WebCore/plugins/PluginView.cpp index aadf0d2..ba8d231 100644 --- a/WebCore/plugins/PluginView.cpp +++ b/WebCore/plugins/PluginView.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * Copyright (C) 2008 Collabora Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,38 +32,39 @@ #include "Document.h" #include "DocumentLoader.h" #include "Element.h" +#include "FocusController.h" +#include "Frame.h" #include "FrameLoader.h" +#include "FrameLoaderClient.h" #include "FrameTree.h" -#include "Frame.h" #include "FrameView.h" #include "GraphicsContext.h" -#include "Image.h" #include "HTMLNames.h" #include "HTMLPlugInElement.h" +#include "Image.h" #include "KeyboardEvent.h" #include "MIMETypeRegistry.h" #include "MouseEvent.h" #include "NotImplemented.h" #include "Page.h" -#include "FocusController.h" #include "PlatformMouseEvent.h" -#if OS(WINDOWS) && ENABLE(NETSCAPE_PLUGIN_API) -#include "PluginMessageThrottlerWin.h" -#endif -#include "PluginPackage.h" -#include "ScriptController.h" -#include "ScriptValue.h" -#include "SecurityOrigin.h" #include "PluginDatabase.h" #include "PluginDebug.h" #include "PluginMainThreadScheduler.h" #include "PluginPackage.h" #include "RenderBox.h" #include "RenderObject.h" -#include "npruntime_impl.h" +#include "ScriptController.h" +#include "ScriptValue.h" +#include "SecurityOrigin.h" #include "Settings.h" +#include "npruntime_impl.h" #include <wtf/ASCIICType.h> +#if OS(WINDOWS) && ENABLE(NETSCAPE_PLUGIN_API) +#include "PluginMessageThrottlerWin.h" +#endif + #if defined(ANDROID_PLUGINS) #include "TouchEvent.h" #endif @@ -71,8 +72,8 @@ // ANDROID // TODO: Upstream to webkit.org #if USE(JSC) -#include "JSDOMWindow.h" #include "JSDOMBinding.h" +#include "JSDOMWindow.h" #include "c_instance.h" #include "runtime_root.h" #include <runtime/JSLock.h> @@ -221,8 +222,8 @@ bool PluginView::startOrAddToUnstartedList() // We only delay starting the plug-in if we're going to kick off the load // ourselves. Otherwise, the loader will try to deliver data before we've // started the plug-in. - if (!m_loadManually && !m_parentFrame->page()->canStartPlugins()) { - m_parentFrame->page()->addUnstartedPlugin(this); + if (!m_loadManually && !m_parentFrame->page()->canStartMedia()) { + m_parentFrame->page()->addMediaCanStartListener(this); m_isWaitingToStart = true; return true; } @@ -291,6 +292,13 @@ bool PluginView::start() return true; } +void PluginView::mediaCanStart() +{ + ASSERT(!m_isStarted); + if (!start()) + parentFrame()->loader()->client()->dispatchDidFailToStartPlugin(this); +} + PluginView::~PluginView() { LOG(Plugins, "PluginView::~PluginView()"); @@ -329,7 +337,7 @@ void PluginView::removeFromUnstartedListIfNecessary() if (!m_parentFrame->page()) return; - m_parentFrame->page()->removeUnstartedPlugin(this); + m_parentFrame->page()->removeMediaCanStartListener(this); } void PluginView::stop() diff --git a/WebCore/plugins/PluginView.h b/WebCore/plugins/PluginView.h index f14eb3d..3f0b49d 100644 --- a/WebCore/plugins/PluginView.h +++ b/WebCore/plugins/PluginView.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * Copyright (C) 2008 Collabora Ltd. All rights reserved. * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in> * @@ -26,15 +26,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PluginView_H -#define PluginView_H +#ifndef PluginView_h +#define PluginView_h #include "CString.h" #include "FrameLoadRequest.h" #include "HaltablePlugin.h" #include "IntRect.h" -#include "KURL.h" -#include "PlatformString.h" +#include "MediaCanStartListener.h" #include "PluginStream.h" #include "ResourceRequest.h" #include "Timer.h" @@ -128,7 +127,7 @@ namespace WebCore { virtual void didFail(const ResourceError&) = 0; }; - class PluginView : public Widget, private PluginStreamClient, public PluginManualLoader, private HaltablePlugin { + class PluginView : public Widget, private PluginStreamClient, public PluginManualLoader, private HaltablePlugin, private MediaCanStartListener { public: static PassRefPtr<PluginView> create(Frame* parentFrame, const IntSize&, Element*, const KURL&, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually); virtual ~PluginView(); @@ -264,6 +263,8 @@ namespace WebCore { void invalidateWindowlessPluginRect(const IntRect&); + virtual void mediaCanStart(); + #if OS(WINDOWS) && ENABLE(NETSCAPE_PLUGIN_API) void paintWindowedPluginIntoContext(GraphicsContext*, const IntRect&); static HDC WINAPI hookedBeginPaint(HWND, PAINTSTRUCT*); diff --git a/WebCore/plugins/android/PluginPackageAndroid.cpp b/WebCore/plugins/android/PluginPackageAndroid.cpp index ff672f4..5c3a25a 100644 --- a/WebCore/plugins/android/PluginPackageAndroid.cpp +++ b/WebCore/plugins/android/PluginPackageAndroid.cpp @@ -407,6 +407,11 @@ bool PluginPackage::equal(const PluginPackage& a, const PluginPackage& b) return true; } +uint16 PluginPackage::NPVersion() const +{ + return NP_VERSION_MINOR; +} + } // namespace WebCore #endif diff --git a/WebCore/plugins/gtk/PluginPackageGtk.cpp b/WebCore/plugins/gtk/PluginPackageGtk.cpp index bcbd519..271a4a8 100644 --- a/WebCore/plugins/gtk/PluginPackageGtk.cpp +++ b/WebCore/plugins/gtk/PluginPackageGtk.cpp @@ -29,9 +29,11 @@ #include "config.h" #include "PluginPackage.h" +#include <gio/gio.h> #include <stdio.h> #include "CString.h" +#include "GOwnPtr.h" #include "MIMETypeRegistry.h" #include "NotImplemented.h" #include "npruntime_impl.h" @@ -105,7 +107,16 @@ bool PluginPackage::load() return true; } - m_module = g_module_open((m_path.utf8()).data(), G_MODULE_BIND_LOCAL); + GOwnPtr<gchar> finalPath(g_strdup(m_path.utf8().data())); + while (g_file_test(finalPath.get(), G_FILE_TEST_IS_SYMLINK)) { + GOwnPtr<GFile> file(g_file_new_for_path(finalPath.get())); + GOwnPtr<gchar> linkPath(g_file_read_link(finalPath.get(), 0)); + + GOwnPtr<GFile> resolvedFile(g_file_resolve_relative_path(file.get(), linkPath.get())); + finalPath.set(g_file_get_path(resolvedFile.get())); + } + + m_module = g_module_open(finalPath.get(), G_MODULE_BIND_LOCAL); if (!m_module) { LOG(Plugins,"Module Load Failed :%s, Error:%s\n", (m_path.utf8()).data(), g_module_error()); @@ -146,4 +157,8 @@ abort: return false; } +uint16 PluginPackage::NPVersion() const +{ + return NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL; +} } diff --git a/WebCore/plugins/gtk/PluginViewGtk.cpp b/WebCore/plugins/gtk/PluginViewGtk.cpp index 6d992fb..222584c 100644 --- a/WebCore/plugins/gtk/PluginViewGtk.cpp +++ b/WebCore/plugins/gtk/PluginViewGtk.cpp @@ -158,29 +158,19 @@ void PluginView::updatePluginWidget() void PluginView::setFocus() { - if (platformPluginWidget()) - gtk_widget_grab_focus(platformPluginWidget()); - + ASSERT(platformPluginWidget() == platformWidget()); Widget::setFocus(); } void PluginView::show() { - setSelfVisible(true); - - if (isParentVisible() && platformPluginWidget()) - gtk_widget_show(platformPluginWidget()); - + ASSERT(platformPluginWidget() == platformWidget()); Widget::show(); } void PluginView::hide() { - setSelfVisible(false); - - if (isParentVisible() && platformPluginWidget()) - gtk_widget_hide(platformPluginWidget()); - + ASSERT(platformPluginWidget() == platformWidget()); Widget::hide(); } diff --git a/WebCore/plugins/mac/PluginPackageMac.cpp b/WebCore/plugins/mac/PluginPackageMac.cpp index 4aef3a0..be69242 100644 --- a/WebCore/plugins/mac/PluginPackageMac.cpp +++ b/WebCore/plugins/mac/PluginPackageMac.cpp @@ -302,6 +302,10 @@ abort: return false; } +uint16 PluginPackage::NPVersion() const +{ + return NP_VERSION_MINOR; +} } // namespace WebCore #else diff --git a/WebCore/plugins/qt/PluginPackageQt.cpp b/WebCore/plugins/qt/PluginPackageQt.cpp index 8119924..74deaf6 100644 --- a/WebCore/plugins/qt/PluginPackageQt.cpp +++ b/WebCore/plugins/qt/PluginPackageQt.cpp @@ -143,4 +143,8 @@ abort: return false; } +uint16 PluginPackage::NPVersion() const +{ + return NP_VERSION_MINOR; +} } diff --git a/WebCore/plugins/symbian/PluginPackageSymbian.cpp b/WebCore/plugins/symbian/PluginPackageSymbian.cpp index d5c7533..44f8152 100644 --- a/WebCore/plugins/symbian/PluginPackageSymbian.cpp +++ b/WebCore/plugins/symbian/PluginPackageSymbian.cpp @@ -173,5 +173,10 @@ void PluginPackage::unload() delete m_pluginLoader; m_pluginLoader = 0; } + +uint16 PluginPackage::NPVersion() const +{ + return NP_VERSION_MINOR; +} } diff --git a/WebCore/plugins/win/PluginPackageWin.cpp b/WebCore/plugins/win/PluginPackageWin.cpp index 233b10c..203fb60 100644 --- a/WebCore/plugins/win/PluginPackageWin.cpp +++ b/WebCore/plugins/win/PluginPackageWin.cpp @@ -335,4 +335,8 @@ bool PluginPackage::equal(const PluginPackage& a, const PluginPackage& b) return true; } +uint16 PluginPackage::NPVersion() const +{ + return NP_VERSION_MINOR; +} } diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index b7e6de2..9f17b0c 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -808,7 +808,7 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, co // Always compute and store the rect associated with this marker. The computed rect is in absolute coordinates. IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, IntPoint(m_x, y), h, sPos, ePos)); - markerRect = root()->block()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); + markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); renderer()->document()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); // Optionally highlight the text @@ -837,7 +837,7 @@ void InlineTextBox::computeRectForReplacementMarker(int /*tx*/, int /*ty*/, cons // Compute and store the rect associated with this marker. IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, startPoint, h, sPos, ePos)); - markerRect = root()->block()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); + markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox(); renderer()->document()->setRenderedRectForMarker(renderer()->node(), marker, markerRect); } diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index eabb054..62e177d 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -1687,6 +1687,16 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty) return; } + // Check for page-break-inside: avoid, and it it's set, break and bail. + if (isPrinting && !childrenInline() && child->style()->pageBreakInside() == PBAVOID + && inRootBlockContext() + && ty + child->y() > paintInfo.rect.y() + && ty + child->y() < paintInfo.rect.bottom() + && ty + child->y() + child->height() > paintInfo.rect.bottom()) { + view()->setBestTruncatedAt(ty + child->y(), this, true); + return; + } + if (!child->hasSelfPaintingLayer() && !child->isFloating()) child->paint(info, tx, ty); @@ -1984,6 +1994,7 @@ void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty) if (!hasLayer()) { FloatRect localBounds(gapRectsBounds); gapRectsBounds = localToContainerQuad(localBounds, layer->renderer()).enclosingBoundingBox(); + gapRectsBounds.move(layer->scrolledContentOffset()); } layer->addBlockSelectionGapsBounds(gapRectsBounds); } @@ -3897,6 +3908,31 @@ void RenderBlock::adjustRectForColumns(IntRect& r) const r = result; } +void RenderBlock::adjustForColumns(IntSize& offset, const IntPoint& point) const +{ + if (!hasColumns()) + return; + + // FIXME: This is incorrect for right-to-left columns. + + Vector<IntRect>& columnRects = *this->columnRects(); + + int gapWidth = columnGap(); + int xOffset = 0; + int yOffset = 0; + size_t columnCount = columnRects.size(); + for (size_t i = 0; i < columnCount; ++i) { + IntRect columnRect = columnRects[i]; + if (point.y() < columnRect.bottom() + yOffset) { + offset.expand(xOffset, -yOffset); + return; + } + + xOffset += columnRect.width() + gapWidth; + yOffset += columnRect.height(); + } +} + void RenderBlock::calcPrefWidths() { ASSERT(prefWidthsDirty()); diff --git a/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h index d1d105a..c1f8dde 100644 --- a/WebCore/rendering/RenderBlock.h +++ b/WebCore/rendering/RenderBlock.h @@ -128,6 +128,7 @@ public: void clearTruncation(); void adjustRectForColumns(IntRect&) const; + virtual void adjustForColumns(IntSize&, const IntPoint&) const; void addContinuationWithOutline(RenderInline*); diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index 92c3d99..66a88e2 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -980,7 +980,7 @@ void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool } else fixed |= isFixedPos; - IntSize containerOffset = offsetFromContainer(o); + IntSize containerOffset = offsetFromContainer(o, roundedIntPoint(transformState.mappedPoint())); bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D()); if (useTransforms && shouldUseTransformFromContainer(o)) { @@ -1021,7 +1021,7 @@ void RenderBox::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, Transfor o->mapAbsoluteToLocalPoint(fixed, useTransforms, transformState); - IntSize containerOffset = offsetFromContainer(o); + IntSize containerOffset = offsetFromContainer(o, IntPoint()); bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D()); if (useTransforms && shouldUseTransformFromContainer(o)) { @@ -1032,7 +1032,7 @@ void RenderBox::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, Transfor transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); } -IntSize RenderBox::offsetFromContainer(RenderObject* o) const +IntSize RenderBox::offsetFromContainer(RenderObject* o, const IntPoint& point) const { ASSERT(o == container()); @@ -1041,14 +1041,9 @@ IntSize RenderBox::offsetFromContainer(RenderObject* o) const offset += relativePositionOffset(); if (!isInline() || isReplaced()) { - RenderBlock* cb; - if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition - && (cb = toRenderBlock(o))->hasColumns()) { - IntRect rect(x(), y(), 1, 1); - cb->adjustRectForColumns(rect); - offset.expand(rect.x(), rect.y()); - } else - offset.expand(x(), y()); + if (style()->position() != AbsolutePosition && style()->position() != FixedPosition) + o->adjustForColumns(offset, IntPoint(point.x() + x(), point.y() + y())); + offset.expand(x(), y()); } if (o->hasOverflowClip()) diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h index 401a46d..2ee368d 100644 --- a/WebCore/rendering/RenderBox.h +++ b/WebCore/rendering/RenderBox.h @@ -173,7 +173,7 @@ public: int overrideHeight() const; virtual void setOverrideSize(int); - virtual IntSize offsetFromContainer(RenderObject*) const; + virtual IntSize offsetFromContainer(RenderObject*, const IntPoint&) const; int calcBorderBoxWidth(int width) const; int calcBorderBoxHeight(int height) const; diff --git a/WebCore/rendering/RenderFileUploadControl.cpp b/WebCore/rendering/RenderFileUploadControl.cpp index 59cbacf..a31442a 100644 --- a/WebCore/rendering/RenderFileUploadControl.cpp +++ b/WebCore/rendering/RenderFileUploadControl.cpp @@ -114,15 +114,27 @@ String RenderFileUploadControl::acceptTypes() return static_cast<HTMLInputElement*>(node())->accept(); } +void RenderFileUploadControl::iconForFiles(const Vector<String>& filenames) +{ + if (Chrome* chromePointer = chrome()) + chromePointer->iconForFiles(filenames, m_fileChooser); +} + void RenderFileUploadControl::click() { + if (Chrome* chromePointer = chrome()) + chromePointer->runOpenPanel(node()->document()->frame(), m_fileChooser); +} + +Chrome* RenderFileUploadControl::chrome() const +{ Frame* frame = node()->document()->frame(); if (!frame) - return; + return 0; Page* page = frame->page(); if (!page) - return; - page->chrome()->runOpenPanel(frame, m_fileChooser); + return 0; + return page->chrome(); } void RenderFileUploadControl::updateFromElement() diff --git a/WebCore/rendering/RenderFileUploadControl.h b/WebCore/rendering/RenderFileUploadControl.h index dcdce4d..454041a 100644 --- a/WebCore/rendering/RenderFileUploadControl.h +++ b/WebCore/rendering/RenderFileUploadControl.h @@ -26,6 +26,7 @@ namespace WebCore { +class Chrome; class HTMLInputElement; // Each RenderFileUploadControl contains a RenderButton (for opening the file chooser), and @@ -41,16 +42,11 @@ public: void click(); - void valueChanged(); - void receiveDroppedFiles(const Vector<String>&); String buttonValue(); String fileTextValue() const; - bool allowsMultipleFiles(); - String acceptTypes(); - private: virtual const char* renderName() const { return "RenderFileUploadControl"; } @@ -60,6 +56,14 @@ private: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); + // FileChooserClient methods. + void valueChanged(); + void repaint() { RenderBlock::repaint(); } + bool allowsMultipleFiles(); + String acceptTypes(); + void iconForFiles(const Vector<String>&); + + Chrome* chrome() const; int maxFilenameWidth() const; PassRefPtr<RenderStyle> createButtonStyle(const RenderStyle* parentStyle) const; diff --git a/WebCore/rendering/RenderForeignObject.cpp b/WebCore/rendering/RenderForeignObject.cpp index 5bb4439..aa28ff0 100644 --- a/WebCore/rendering/RenderForeignObject.cpp +++ b/WebCore/rendering/RenderForeignObject.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Apple Computer, Inc. * Copyright (C) 2009 Google, Inc. + * Copyright (C) Research In Motion Limited 2010. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -27,9 +28,9 @@ #include "GraphicsContext.h" #include "RenderView.h" #include "SVGForeignObjectElement.h" -#include "SVGLength.h" #include "SVGRenderSupport.h" -#include "SVGTransformList.h" +#include "SVGSVGElement.h" +#include "TransformState.h" namespace WebCore { @@ -38,22 +39,18 @@ RenderForeignObject::RenderForeignObject(SVGForeignObjectElement* node) { } -FloatPoint RenderForeignObject::translationForAttributes() const -{ - SVGForeignObjectElement* foreign = static_cast<SVGForeignObjectElement*>(node()); - return FloatPoint(foreign->x().value(foreign), foreign->y().value(foreign)); -} - void RenderForeignObject::paint(PaintInfo& paintInfo, int, int) { if (paintInfo.context->paintingDisabled()) return; - // Copy the paint info so that modifications to the damage rect do not affect callers - PaintInfo childPaintInfo = paintInfo; + PaintInfo childPaintInfo(paintInfo); childPaintInfo.context->save(); - applyTransformToPaintInfo(childPaintInfo, localToParentTransform()); - childPaintInfo.context->clip(clipRect(0, 0)); + + applyTransformToPaintInfo(childPaintInfo, localTransform()); + + if (SVGRenderBase::isOverflowHidden(this)) + childPaintInfo.context->clip(m_viewport); float opacity = style()->opacity(); if (opacity < 1.0f) @@ -67,32 +64,33 @@ void RenderForeignObject::paint(PaintInfo& paintInfo, int, int) childPaintInfo.context->restore(); } -FloatRect RenderForeignObject::objectBoundingBox() const +IntRect RenderForeignObject::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) { - return borderBoxRect(); + return SVGRenderBase::clippedOverflowRectForRepaint(this, repaintContainer); } -FloatRect RenderForeignObject::repaintRectInLocalCoordinates() const +void RenderForeignObject::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& repaintRect, bool fixed) { - // HACK: to maintain historical LayoutTest results for now. - // RenderForeignObject is a RenderBlock (not a RenderSVGModelObject) so this - // should not affect repaint correctness. But it should really be: - // return borderBoxRect(); - return FloatRect(); + SVGRenderBase::computeRectForRepaint(this, repaintContainer, repaintRect, fixed); } -void RenderForeignObject::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed) +const AffineTransform& RenderForeignObject::localToParentTransform() const { - rect = localToParentTransform().mapRect(rect); - style()->svgStyle()->inflateForShadow(rect); - RenderBlock::computeRectForRepaint(repaintContainer, rect, fixed); + m_localToParentTransform = localTransform(); + m_localToParentTransform.translate(m_viewport.x(), m_viewport.y()); + return m_localToParentTransform; } -const AffineTransform& RenderForeignObject::localToParentTransform() const +void RenderForeignObject::calcWidth() { - FloatPoint attributeTranslation(translationForAttributes()); - m_localToParentTransform = localTransform().translateRight(attributeTranslation.x(), attributeTranslation.y()); - return m_localToParentTransform; + // FIXME: Investigate in size rounding issues + setWidth(static_cast<int>(roundf(m_viewport.width()))); +} + +void RenderForeignObject::calcHeight() +{ + // FIXME: Investigate in size rounding issues + setHeight(static_cast<int>(roundf(m_viewport.height()))); } void RenderForeignObject::layout() @@ -101,18 +99,36 @@ void RenderForeignObject::layout() ASSERT(!view()->layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree. LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); - m_localTransform = static_cast<SVGForeignObjectElement*>(node())->animatedLocalTransform(); + SVGForeignObjectElement* foreign = static_cast<SVGForeignObjectElement*>(node()); + m_localTransform = foreign->animatedLocalTransform(); + + // Cache viewport boundaries + FloatPoint viewportLocation(foreign->x().value(foreign), foreign->y().value(foreign)); + m_viewport = FloatRect(viewportLocation, FloatSize(foreign->width().value(foreign), foreign->height().value(foreign))); + + // Set box origin to the foreignObject x/y translation, so positioned objects in XHTML content get correct + // positions. A regular RenderBoxModelObject would pull this information from RenderStyle - in SVG those + // properties are ignored for non <svg> elements, so we mimic what happens when specifying them through CSS. + + // FIXME: Investigate in location rounding issues - only affects RenderForeignObject & RenderSVGText + setLocation(roundedIntPoint(viewportLocation)); RenderBlock::layout(); - repainter.repaintAfterLayout(); + repainter.repaintAfterLayout(); setNeedsLayout(false); } bool RenderForeignObject::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { - FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent); - return RenderBlock::nodeAtPoint(request, result, static_cast<int>(localPoint.x()), static_cast<int>(localPoint.y()), 0, 0, hitTestAction); + FloatPoint localPoint = localTransform().inverse().mapPoint(pointInParent); + + // Early exit if local point is not contained in clipped viewport area + if (SVGRenderBase::isOverflowHidden(this) && !m_viewport.contains(localPoint)) + return false; + + IntPoint roundedLocalPoint = roundedIntPoint(localPoint); + return RenderBlock::nodeAtPoint(request, result, roundedLocalPoint.x(), roundedLocalPoint.y(), 0, 0, hitTestAction); } bool RenderForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction) @@ -121,11 +137,14 @@ bool RenderForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, int return false; } -void RenderForeignObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed , bool useTransforms, TransformState& transformState) const +void RenderForeignObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState) const { + // When crawling up the hierachy starting from foreignObject child content, useTransforms may not be set to true. + if (!useTransforms) + useTransforms = true; SVGRenderBase::mapLocalToContainer(this, repaintContainer, fixed, useTransforms, transformState); } -} // namespace WebCore +} -#endif // ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT) +#endif diff --git a/WebCore/rendering/RenderForeignObject.h b/WebCore/rendering/RenderForeignObject.h index f32069c..bb6b555 100644 --- a/WebCore/rendering/RenderForeignObject.h +++ b/WebCore/rendering/RenderForeignObject.h @@ -21,8 +21,8 @@ #ifndef RenderForeignObject_h #define RenderForeignObject_h -#if ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT) +#if ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT) #include "AffineTransform.h" #include "FloatPoint.h" #include "RenderSVGBlock.h" @@ -39,15 +39,15 @@ public: virtual void paint(PaintInfo&, int parentX, int parentY); - virtual const AffineTransform& localToParentTransform() const; - + virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); + virtual bool requiresLayer() const { return false; } virtual void layout(); - virtual FloatRect objectBoundingBox() const; - virtual FloatRect strokeBoundingBox() const { return borderBoxRect(); } - virtual FloatRect repaintRectInLocalCoordinates() const; + virtual FloatRect objectBoundingBox() const { return m_viewport; } + virtual FloatRect strokeBoundingBox() const { return m_viewport; } + virtual FloatRect repaintRectInLocalCoordinates() const { return m_viewport; } virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); @@ -56,15 +56,18 @@ public: virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed , bool useTransforms, TransformState& transformState) const; private: - FloatPoint translationForAttributes() const; + virtual void calcWidth(); + virtual void calcHeight(); + virtual const AffineTransform& localToParentTransform() const; virtual AffineTransform localTransform() const { return m_localTransform; } + FloatRect m_viewport; AffineTransform m_localTransform; mutable AffineTransform m_localToParentTransform; }; -} // namespace WebCore +} -#endif // ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT) -#endif // RenderForeignObject_h +#endif +#endif diff --git a/WebCore/rendering/RenderInline.cpp b/WebCore/rendering/RenderInline.cpp index 9571751..d254835 100644 --- a/WebCore/rendering/RenderInline.cpp +++ b/WebCore/rendering/RenderInline.cpp @@ -710,7 +710,7 @@ void RenderInline::computeRectForRepaint(RenderBoxModelObject* repaintContainer, o->computeRectForRepaint(repaintContainer, rect, fixed); } -IntSize RenderInline::offsetFromContainer(RenderObject* container) const +IntSize RenderInline::offsetFromContainer(RenderObject* container, const IntPoint& point) const { ASSERT(container == this->container()); @@ -718,13 +718,7 @@ IntSize RenderInline::offsetFromContainer(RenderObject* container) const if (isRelPositioned()) offset += relativePositionOffset(); - if (!isInline() || isReplaced()) { - RenderBlock* cb; - if (container->isBlockFlow() && (cb = toRenderBlock(container))->hasColumns()) { - IntRect rect(0, 0, 1, 1); - cb->adjustRectForColumns(rect); - } - } + container->adjustForColumns(offset, point); if (container->hasOverflowClip()) offset -= toRenderBox(container)->layer()->scrolledContentOffset(); @@ -753,7 +747,7 @@ void RenderInline::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b if (!o) return; - IntSize containerOffset = offsetFromContainer(o); + IntSize containerOffset = offsetFromContainer(o, roundedIntPoint(transformState.mappedPoint())); bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D()); if (useTransforms && shouldUseTransformFromContainer(o)) { @@ -785,7 +779,7 @@ void RenderInline::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, Trans o->mapAbsoluteToLocalPoint(fixed, useTransforms, transformState); - IntSize containerOffset = offsetFromContainer(o); + IntSize containerOffset = offsetFromContainer(o, IntPoint()); bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D()); if (useTransforms && shouldUseTransformFromContainer(o)) { diff --git a/WebCore/rendering/RenderInline.h b/WebCore/rendering/RenderInline.h index d35aa85..7fcb516 100644 --- a/WebCore/rendering/RenderInline.h +++ b/WebCore/rendering/RenderInline.h @@ -44,7 +44,7 @@ public: virtual void absoluteRects(Vector<IntRect>&, int tx, int ty); virtual void absoluteQuads(Vector<FloatQuad>&); - virtual IntSize offsetFromContainer(RenderObject*) const; + virtual IntSize offsetFromContainer(RenderObject*, const IntPoint&) const; IntRect linesBoundingBox() const; IntRect linesVisibleOverflowBoundingBox() const; diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index 6dbb413..03a1e75 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -1227,7 +1227,9 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai #if USE(ACCELERATED_COMPOSITING) if (compositor()->inCompositingMode()) { - if (RenderLayer* compositingAncestor = ancestorCompositingLayer()) { + // Our stacking context is guaranteed to contain all of our descendants that may need + // repositioning, so update compositing layers from there. + if (RenderLayer* compositingAncestor = stackingContext()->enclosingCompositingLayer()) { bool isUpdateRoot = true; compositingAncestor->backing()->updateAfterLayout(RenderLayerBacking::AllDescendants, isUpdateRoot); } diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index 3f60557..f637e3c 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -38,6 +38,7 @@ #include "GraphicsLayer.h" #include "HTMLCanvasElement.h" #include "HTMLElement.h" +#include "HTMLMediaElement.h" #include "HTMLNames.h" #include "InspectorTimelineAgent.h" #include "KeyframeList.h" @@ -215,9 +216,14 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration() PluginWidget* pluginWidget = static_cast<PluginWidget*>(toRenderEmbeddedObject(renderer())->widget()); m_graphicsLayer->setContentsToMedia(pluginWidget->platformLayer()); } - +#if ENABLE(VIDEO) + else if (renderer()->isVideo()) { + HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(renderer()->node()); + m_graphicsLayer->setContentsToMedia(mediaElement->platformLayer()); + } +#endif #if ENABLE(3D_CANVAS) - if (is3DCanvas(renderer())) { + else if (is3DCanvas(renderer())) { HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer()->node()); WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(canvas->renderingContext()); if (context->graphicsContext3D()->platformGraphicsContext3D()) diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp index 1d1e7c2..e70de96 100644 --- a/WebCore/rendering/RenderObject.cpp +++ b/WebCore/rendering/RenderObject.cpp @@ -69,6 +69,7 @@ #endif #if ENABLE(SVG) +#include "RenderSVGResource.h" #include "SVGRenderSupport.h" #endif @@ -1765,6 +1766,11 @@ void RenderObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, b if (!o) return; + IntSize columnOffset; + o->adjustForColumns(columnOffset, roundedIntPoint(transformState.mappedPoint())); + if (!columnOffset.isZero()) + transformState.move(columnOffset); + if (o->hasOverflowClip()) transformState.move(-toRenderBox(o)->layer()->scrolledContentOffset()); @@ -1821,18 +1827,23 @@ void RenderObject::getTransformFromContainer(const RenderObject* containerObject FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, RenderBoxModelObject* repaintContainer, bool fixed) const { - TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint(), &localQuad); + // Track the point at the center of the quad's bounding box. As mapLocalToContainer() calls offsetFromContainer(), + // it will use that point as the reference point to decide which column's transform to apply in multiple-column blocks. + TransformState transformState(TransformState::ApplyTransformDirection, localQuad.boundingBox().center(), &localQuad); mapLocalToContainer(repaintContainer, fixed, true, transformState); transformState.flatten(); return transformState.lastPlanarQuad(); } -IntSize RenderObject::offsetFromContainer(RenderObject* o) const +IntSize RenderObject::offsetFromContainer(RenderObject* o, const IntPoint& point) const { ASSERT(o == container()); IntSize offset; + + o->adjustForColumns(offset, point); + if (o->hasOverflowClip()) offset -= toRenderBox(o)->layer()->scrolledContentOffset(); @@ -1842,6 +1853,7 @@ IntSize RenderObject::offsetFromContainer(RenderObject* o) const IntSize RenderObject::offsetFromAncestorContainer(RenderObject* container) const { IntSize offset; + IntPoint referencePoint; const RenderObject* currContainer = this; do { RenderObject* nextContainer = currContainer->container(); @@ -1849,7 +1861,9 @@ IntSize RenderObject::offsetFromAncestorContainer(RenderObject* container) const if (!nextContainer) break; ASSERT(!currContainer->hasTransform()); - offset += currContainer->offsetFromContainer(nextContainer); + IntSize currentOffset = currContainer->offsetFromContainer(nextContainer, referencePoint); + offset += currentOffset; + referencePoint.move(currentOffset); currContainer = nextContainer; } while (currContainer != container); @@ -2520,6 +2534,12 @@ const SVGRenderBase* RenderObject::toSVGRenderBase() const return 0; } +RenderSVGResource* RenderObject::toRenderSVGResource() +{ + ASSERT_NOT_REACHED(); + return 0; +} + FloatRect RenderObject::objectBoundingBox() const { ASSERT_NOT_REACHED(); diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h index 6764818..791d4d0 100644 --- a/WebCore/rendering/RenderObject.h +++ b/WebCore/rendering/RenderObject.h @@ -54,6 +54,7 @@ class RenderTheme; class TransformState; class VisiblePosition; #if ENABLE(SVG) +class RenderSVGResource; class SVGRenderBase; #endif @@ -332,8 +333,10 @@ public: virtual bool isSVGText() const { return false; } virtual bool isSVGImage() const { return false; } virtual bool isSVGForeignObject() const { return false; } + virtual bool isSVGResource() const { return false; } virtual const SVGRenderBase* toSVGRenderBase() const; + virtual RenderSVGResource* toRenderSVGResource(); // Per SVG 1.1 objectBoundingBox ignores clipping, masking, filter effects, opacity and stroke-width. // This is used for all computation of objectBoundingBox relative units and by SVGLocateable::getBBox(). @@ -562,8 +565,9 @@ public: // Convert a local quad into the coordinate system of container, taking transforms into account. FloatQuad localToContainerQuad(const FloatQuad&, RenderBoxModelObject* repaintContainer, bool fixed = false) const; - // Return the offset from the container() renderer (excluding transforms) - virtual IntSize offsetFromContainer(RenderObject*) const; + // Return the offset from the container() renderer (excluding transforms). In multi-column layout, + // different offsets apply at different points, so return the offset that applies to the given point. + virtual IntSize offsetFromContainer(RenderObject*, const IntPoint&) const; // Return the offset from an object up the container() chain. Asserts that none of the intermediate objects have transforms. IntSize offsetFromAncestorContainer(RenderObject*) const; @@ -642,6 +646,10 @@ public: // that rect in the coordinate space of repaintContainer. virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); + // If multiple-column layout results in applying an offset to the given point, add the same + // offset to the given size. + virtual void adjustForColumns(IntSize&, const IntPoint&) const { } + virtual unsigned int length() const { return 1; } bool isFloatingOrPositioned() const { return (isFloating() || isPositioned()); } diff --git a/WebCore/rendering/RenderPath.cpp b/WebCore/rendering/RenderPath.cpp index 7dbde42..bcedd38 100644 --- a/WebCore/rendering/RenderPath.cpp +++ b/WebCore/rendering/RenderPath.cpp @@ -34,9 +34,7 @@ #include "StrokeStyleApplier.h" #include "SVGPaintServer.h" #include "SVGRenderSupport.h" -#include "SVGResourceFilter.h" #include "SVGResourceMarker.h" -#include "SVGResourceMasker.h" #include "SVGStyledTransformableElement.h" #include "SVGTransformList.h" #include "SVGURIReference.h" diff --git a/WebCore/rendering/RenderRuby.cpp b/WebCore/rendering/RenderRuby.cpp index f13e2b4..4ab9d73 100644 --- a/WebCore/rendering/RenderRuby.cpp +++ b/WebCore/rendering/RenderRuby.cpp @@ -194,4 +194,4 @@ void RenderRubyAsBlock::removeChild(RenderObject* child) } // namespace WebCore -#endif +#endif // ENABLE(RUBY) diff --git a/WebCore/rendering/RenderRubyBase.cpp b/WebCore/rendering/RenderRubyBase.cpp index 65f9bc0..9b2dc9e 100644 --- a/WebCore/rendering/RenderRubyBase.cpp +++ b/WebCore/rendering/RenderRubyBase.cpp @@ -187,4 +187,4 @@ void RenderRubyBase::mergeBlockChildren(RenderRubyBase* toBase, RenderObject* fr } // namespace WebCore -#endif +#endif // ENABLE(RUBY) diff --git a/WebCore/rendering/RenderRubyRun.cpp b/WebCore/rendering/RenderRubyRun.cpp index 61be455..d91c625 100644 --- a/WebCore/rendering/RenderRubyRun.cpp +++ b/WebCore/rendering/RenderRubyRun.cpp @@ -225,4 +225,4 @@ RenderRubyRun* RenderRubyRun::staticCreateRubyRun(const RenderObject* parentRuby } // namespace WebCore -#endif +#endif // ENABLE(RUBY) diff --git a/WebCore/rendering/RenderRubyText.cpp b/WebCore/rendering/RenderRubyText.cpp index 1cf2b9e..12e8fea 100644 --- a/WebCore/rendering/RenderRubyText.cpp +++ b/WebCore/rendering/RenderRubyText.cpp @@ -51,4 +51,4 @@ bool RenderRubyText::isChildAllowed(RenderObject* child, RenderStyle*) const } // namespace WebCore -#endif +#endif // ENABLE(RUBY) diff --git a/WebCore/rendering/RenderSVGBlock.cpp b/WebCore/rendering/RenderSVGBlock.cpp index f065c44..99725d6 100644 --- a/WebCore/rendering/RenderSVGBlock.cpp +++ b/WebCore/rendering/RenderSVGBlock.cpp @@ -1,8 +1,7 @@ /* - * This file is part of the WebKit project. - * * Copyright (C) 2006 Apple Computer, Inc. - * (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -40,9 +39,7 @@ void RenderSVGBlock::setStyle(PassRefPtr<RenderStyle> style) RefPtr<RenderStyle> useStyle = style; // SVG text layout code expects us to be a block-level style element. - if (useStyle->display() == NONE) - setChildrenInline(false); - else if (useStyle->isDisplayInlineType()) { + if (useStyle->isDisplayInlineType()) { RefPtr<RenderStyle> newStyle = RenderStyle::create(); newStyle->inheritFrom(useStyle.get()); newStyle->setDisplay(BLOCK); @@ -50,14 +47,27 @@ void RenderSVGBlock::setStyle(PassRefPtr<RenderStyle> style) } RenderBlock::setStyle(useStyle.release()); - setReplaced(false); +} + +void RenderSVGBlock::updateBoxModelInfoFromStyle() +{ + RenderBlock::updateBoxModelInfoFromStyle(); - //FIXME: Once overflow rules are supported by SVG we should - //probably map the CSS overflow rules rather than just ignoring - //them + // RenderSVGlock, used by Render(SVGText|ForeignObject), is not allowed to call setHasOverflowClip(true). + // RenderBlock assumes a layer to be present when the overflow clip functionality is requested. Both + // Render(SVGText|ForeignObject) return 'false' on 'requiresLayer'. Fine for RenderSVGText. + // + // If we want to support overflow rules for <foreignObject> we can choose between two solutions: + // a) make RenderForeignObject require layers and SVG layer aware + // b) reactor overflow logic out of RenderLayer (as suggested by dhyatt), which is a large task + // + // Until this is resolved, disable overflow support. Opera/FF don't support it as well at the moment (Feb 2010). + // + // Note: This does NOT affect overflow handling on outer/inner <svg> elements - this is handled + // manually by RenderSVGRoot - which owns the documents enclosing root layer and thus works fine. setHasOverflowClip(false); } } -#endif // ENABLE(SVG) +#endif diff --git a/WebCore/rendering/RenderSVGBlock.h b/WebCore/rendering/RenderSVGBlock.h index 0b0d107..19cac62 100644 --- a/WebCore/rendering/RenderSVGBlock.h +++ b/WebCore/rendering/RenderSVGBlock.h @@ -1,6 +1,4 @@ /* - * This file is part of the WebKit project. - * * Copyright (C) 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or @@ -22,8 +20,8 @@ #ifndef RenderSVGBlock_h #define RenderSVGBlock_h -#if ENABLE(SVG) +#if ENABLE(SVG) #include "RenderBlock.h" #include "SVGRenderSupport.h" @@ -39,8 +37,9 @@ public: private: virtual void setStyle(PassRefPtr<RenderStyle>); + virtual void updateBoxModelInfoFromStyle(); }; } -#endif // ENABLE(SVG) -#endif // !RenderSVGBlock_h +#endif +#endif diff --git a/WebCore/rendering/RenderSVGImage.cpp b/WebCore/rendering/RenderSVGImage.cpp index 96eeaf9..6fb9501 100644 --- a/WebCore/rendering/RenderSVGImage.cpp +++ b/WebCore/rendering/RenderSVGImage.cpp @@ -37,9 +37,6 @@ #include "SVGLength.h" #include "SVGPreserveAspectRatio.h" #include "SVGRenderSupport.h" -#include "SVGResourceClipper.h" -#include "SVGResourceFilter.h" -#include "SVGResourceMasker.h" namespace WebCore { @@ -103,6 +100,12 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, int, int) paintInfo.context->restore(); } +void RenderSVGImage::destroy() +{ + SVGRenderBase::deregisterFromResources(this); + RenderImage::destroy(); +} + bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest&, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { // We only draw in the forground phase, so we only hit-test then. diff --git a/WebCore/rendering/RenderSVGImage.h b/WebCore/rendering/RenderSVGImage.h index 8ed9146..f48b9dd 100644 --- a/WebCore/rendering/RenderSVGImage.h +++ b/WebCore/rendering/RenderSVGImage.h @@ -32,48 +32,50 @@ namespace WebCore { - class SVGImageElement; +class SVGImageElement; - class RenderSVGImage : public RenderImage, protected SVGRenderBase { - public: - RenderSVGImage(SVGImageElement*); +class RenderSVGImage : public RenderImage, protected SVGRenderBase { +public: + RenderSVGImage(SVGImageElement*); - private: - virtual const SVGRenderBase* toSVGRenderBase() const { return this; } - virtual const char* renderName() const { return "RenderSVGImage"; } - virtual bool isSVGImage() const { return true; } +private: + virtual const SVGRenderBase* toSVGRenderBase() const { return this; } + virtual const char* renderName() const { return "RenderSVGImage"; } + virtual bool isSVGImage() const { return true; } - virtual const AffineTransform& localToParentTransform() const { return m_localTransform; } + virtual const AffineTransform& localToParentTransform() const { return m_localTransform; } - virtual FloatRect objectBoundingBox() const; - virtual FloatRect strokeBoundingBox() const { return m_localBounds; } - virtual FloatRect repaintRectInLocalCoordinates() const; + virtual FloatRect objectBoundingBox() const; + virtual FloatRect strokeBoundingBox() const { return m_localBounds; } + virtual FloatRect repaintRectInLocalCoordinates() const; - virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); - virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); + virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); + virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); - virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const; + virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const; - virtual void absoluteRects(Vector<IntRect>&, int tx, int ty); - virtual void absoluteQuads(Vector<FloatQuad>&); - virtual void addFocusRingRects(Vector<IntRect>&, int tx, int ty); + virtual void absoluteRects(Vector<IntRect>&, int tx, int ty); + virtual void absoluteQuads(Vector<FloatQuad>&); + virtual void addFocusRingRects(Vector<IntRect>&, int tx, int ty); - virtual void imageChanged(WrappedImagePtr, const IntRect* = 0); - - virtual void layout(); - virtual void paint(PaintInfo&, int parentX, int parentY); + virtual void imageChanged(WrappedImagePtr, const IntRect* = 0); + + virtual void layout(); + virtual void paint(PaintInfo&, int parentX, int parentY); - virtual bool requiresLayer() const { return false; } + virtual void destroy(); - virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); - virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); + virtual bool requiresLayer() const { return false; } - virtual AffineTransform localTransform() const { return m_localTransform; } + virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction); + virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); - AffineTransform m_localTransform; - FloatRect m_localBounds; - mutable FloatRect m_cachedLocalRepaintRect; - }; + virtual AffineTransform localTransform() const { return m_localTransform; } + + AffineTransform m_localTransform; + FloatRect m_localBounds; + mutable FloatRect m_cachedLocalRepaintRect; +}; } // namespace WebCore diff --git a/WebCore/rendering/RenderSVGInlineText.h b/WebCore/rendering/RenderSVGInlineText.h index e9c5d6e..b475067 100644 --- a/WebCore/rendering/RenderSVGInlineText.h +++ b/WebCore/rendering/RenderSVGInlineText.h @@ -39,6 +39,10 @@ private: virtual void styleDidChange(StyleDifference, const RenderStyle*); + // FIXME: We need objectBoundingBox for DRT results and filters at the moment. + // This should be fixed to give back the objectBoundingBox of the text root. + virtual FloatRect objectBoundingBox() const { return FloatRect(); } + virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty); virtual void absoluteQuads(Vector<FloatQuad>&); diff --git a/WebCore/rendering/RenderSVGModelObject.cpp b/WebCore/rendering/RenderSVGModelObject.cpp index 3fab5a6..c163dc6 100644 --- a/WebCore/rendering/RenderSVGModelObject.cpp +++ b/WebCore/rendering/RenderSVGModelObject.cpp @@ -38,10 +38,6 @@ #include "RenderView.h" #include "SVGStyledElement.h" -#if ENABLE(FILTERS) -#include "SVGResourceFilter.h" -#endif - namespace WebCore { RenderSVGModelObject::RenderSVGModelObject(SVGStyledElement* node) @@ -86,6 +82,12 @@ void RenderSVGModelObject::absoluteQuads(Vector<FloatQuad>& quads) quads.append(absoluteClippedOverflowRect()); } +void RenderSVGModelObject::destroy() +{ + deregisterFromResources(this); + RenderObject::destroy(); +} + bool RenderSVGModelObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction) { ASSERT_NOT_REACHED(); diff --git a/WebCore/rendering/RenderSVGModelObject.h b/WebCore/rendering/RenderSVGModelObject.h index 4c50734..c04c590 100644 --- a/WebCore/rendering/RenderSVGModelObject.h +++ b/WebCore/rendering/RenderSVGModelObject.h @@ -60,6 +60,8 @@ public: virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty); virtual void absoluteQuads(Vector<FloatQuad>&); + virtual void destroy(); + virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const; private: diff --git a/WebCore/rendering/RenderSVGResource.h b/WebCore/rendering/RenderSVGResource.h new file mode 100644 index 0000000..38c6c09 --- /dev/null +++ b/WebCore/rendering/RenderSVGResource.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderSVGResource_h +#define RenderSVGResource_h + +#if ENABLE(SVG) +#include "FloatRect.h" +#include "RenderSVGHiddenContainer.h" + +namespace WebCore { + +enum RenderSVGResourceType { + MaskerResourceType +}; + +class RenderSVGResource : public RenderSVGHiddenContainer { +public: + RenderSVGResource(SVGStyledElement* node) : RenderSVGHiddenContainer(node) { } + + template<class Renderer> + Renderer* cast() + { + if (Renderer::s_resourceType == resourceType()) + return static_cast<Renderer*>(this); + + return 0; + } + + virtual RenderSVGResource* toRenderSVGResource() { return this; } + virtual bool isSVGResource() const { return true; } + virtual bool drawsContents() { return false; } + + virtual void invalidateClients() = 0; + virtual void invalidateClient(RenderObject*) = 0; + + virtual bool applyResource(RenderObject*, GraphicsContext*) = 0; + virtual FloatRect resourceBoundingBox(const FloatRect&) const = 0; + + virtual RenderSVGResourceType resourceType() const = 0; +}; + +template<typename Renderer> +Renderer* getRenderSVGResourceById(Document* document, const AtomicString& id) +{ + if (id.isEmpty()) + return 0; + + Element* element = document->getElementById(id); + if (!element || !element->isSVGElement()) + return 0; + + RenderObject* renderer = element->renderer(); + if (!renderer) + return 0; + + RenderSVGResource* renderResource = renderer->toRenderSVGResource(); + if (!renderResource) + return 0; + + return renderResource->cast<Renderer>(); +} + +} + +#endif +#endif diff --git a/WebCore/rendering/RenderSVGResourceMasker.cpp b/WebCore/rendering/RenderSVGResourceMasker.cpp new file mode 100644 index 0000000..2923c6e --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceMasker.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "RenderSVGResourceMasker.h" + +#include "AffineTransform.h" +#include "CanvasPixelArray.h" +#include "Element.h" +#include "FloatPoint.h" +#include "FloatRect.h" +#include "GraphicsContext.h" +#include "Image.h" +#include "ImageBuffer.h" +#include "ImageData.h" +#include "IntRect.h" +#include "SVGElement.h" +#include "SVGMaskElement.h" +#include "SVGStyledElement.h" +#include "SVGUnitTypes.h" +#include <wtf/Vector.h> + +namespace WebCore { + +RenderSVGResourceType RenderSVGResourceMasker::s_resourceType = MaskerResourceType; + +RenderSVGResourceMasker::RenderSVGResourceMasker(SVGStyledElement* node) + : RenderSVGResource(node) +{ +} + +RenderSVGResourceMasker::~RenderSVGResourceMasker() +{ + deleteAllValues(m_masker); + m_masker.clear(); +} + +void RenderSVGResourceMasker::invalidateClients() +{ + HashMap<RenderObject*, MaskerData*>::const_iterator end = m_masker.end(); + for (HashMap<RenderObject*, MaskerData*>::const_iterator it = m_masker.begin(); it != end; ++it) + it->first->setNeedsLayout(true); + deleteAllValues(m_masker); + m_masker.clear(); +} + +void RenderSVGResourceMasker::invalidateClient(RenderObject* object) +{ + ASSERT(object); + + // FIXME: The HashMap should always contain the object on calling invalidateClient. A race condition + // during the parsing can causes a call of invalidateClient right before the call of applyResource. + // We return earlier for the moment. This bug should be fixed in: + // https://bugs.webkit.org/show_bug.cgi?id=35181 + if (!m_masker.contains(object)) + return; + + delete m_masker.take(object); +} + +bool RenderSVGResourceMasker::applyResource(RenderObject* object, GraphicsContext* context) +{ + ASSERT(object); + ASSERT(context); + + if (!m_masker.contains(object)) + m_masker.set(object, new MaskerData); + + MaskerData* maskerData = m_masker.get(object); + if (!maskerData->maskImage && !maskerData->emptyMask) { + SVGMaskElement* maskElement = static_cast<SVGMaskElement*>(node()); + if (!maskElement) + return false; + + createMaskImage(maskerData, maskElement, object); + } + + if (!maskerData->maskImage) + return false; + + context->clipToImageBuffer(maskerData->maskRect, maskerData->maskImage.get()); + return true; +} + +FloatRect RenderSVGResourceMasker::resourceBoundingBox(const FloatRect& objectBoundingBox) const +{ + if (SVGMaskElement* element = static_cast<SVGMaskElement*>(node())) + return element->maskBoundingBox(objectBoundingBox); + + return FloatRect(); +} + +void RenderSVGResourceMasker::createMaskImage(MaskerData* maskerData, const SVGMaskElement* maskElement, RenderObject* object) +{ + FloatRect objectBoundingBox = object->objectBoundingBox(); + + // Mask rect clipped with clippingBoundingBox and filterBoundingBox as long as they are present. + maskerData->maskRect = object->repaintRectInLocalCoordinates(); + if (maskerData->maskRect.isEmpty()) { + maskerData->emptyMask = true; + return; + } + + // Calculate the smallest rect for the mask ImageBuffer. + FloatRect repaintRect; + Vector<RenderObject*> rendererList; + for (Node* node = maskElement->firstChild(); node; node = node->nextSibling()) { + RenderObject* renderer = node->renderer(); + if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !renderer) + continue; + + rendererList.append(renderer); + repaintRect.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates())); + } + + AffineTransform contextTransform; + // We need to scale repaintRect for objectBoundingBox to get the drawing area. + if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { + contextTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); + FloatPoint contextAdjustment = repaintRect.location(); + repaintRect = contextTransform.mapRect(repaintRect); + repaintRect.move(objectBoundingBox.x(), objectBoundingBox.y()); + contextTransform.translate(-contextAdjustment.x(), -contextAdjustment.y()); + } + repaintRect.intersect(maskerData->maskRect); + maskerData->maskRect = repaintRect; + IntRect maskImageRect = enclosingIntRect(maskerData->maskRect); + + maskImageRect.setLocation(IntPoint()); + + // Don't create ImageBuffers with image size of 0 + if (!maskImageRect.width() || !maskImageRect.height()) { + maskerData->emptyMask = true; + return; + } + + // FIXME: This changes color space to linearRGB, the default color space + // for masking operations in SVG. We need a switch for the other color-space + // attribute values sRGB, inherit and auto. + maskerData->maskImage = ImageBuffer::create(maskImageRect.size(), LinearRGB); + if (!maskerData->maskImage) + return; + + GraphicsContext* maskImageContext = maskerData->maskImage->context(); + ASSERT(maskImageContext); + + maskImageContext->save(); + + if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) + maskImageContext->translate(-maskerData->maskRect.x(), -maskerData->maskRect.y()); + maskImageContext->concatCTM(contextTransform); + + // draw the content into the ImageBuffer + Vector<RenderObject*>::iterator end = rendererList.end(); + for (Vector<RenderObject*>::iterator it = rendererList.begin(); it != end; it++) + renderSubtreeToImage(maskerData->maskImage.get(), *it); + + maskImageContext->restore(); + + // create the luminance mask + RefPtr<ImageData> imageData(maskerData->maskImage->getUnmultipliedImageData(maskImageRect)); + CanvasPixelArray* srcPixelArray(imageData->data()); + + for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset += 4) { + unsigned char a = srcPixelArray->get(pixelOffset + 3); + if (!a) + continue; + unsigned char r = srcPixelArray->get(pixelOffset); + unsigned char g = srcPixelArray->get(pixelOffset + 1); + unsigned char b = srcPixelArray->get(pixelOffset + 2); + + double luma = (r * 0.2125 + g * 0.7154 + b * 0.0721) * ((double)a / 255.0); + srcPixelArray->set(pixelOffset + 3, luma); + } + + maskerData->maskImage->putUnmultipliedImageData(imageData.get(), maskImageRect, IntPoint()); +} + +} diff --git a/WebCore/rendering/RenderSVGResourceMasker.h b/WebCore/rendering/RenderSVGResourceMasker.h new file mode 100644 index 0000000..6c73c84 --- /dev/null +++ b/WebCore/rendering/RenderSVGResourceMasker.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderSVGResourceMasker_h +#define RenderSVGResourceMasker_h + +#if ENABLE(SVG) +#include "FloatRect.h" +#include "GraphicsContext.h" +#include "ImageBuffer.h" +#include "IntSize.h" +#include "RenderSVGResource.h" +#include "SVGMaskElement.h" +#include "SVGUnitTypes.h" + +#include <wtf/HashMap.h> +#include <wtf/OwnPtr.h> + +namespace WebCore { + +struct MaskerData { + MaskerData(FloatRect rect = FloatRect(), bool emptyObject = false) + : maskRect(rect) + , emptyMask(emptyObject) + { + } + + OwnPtr<ImageBuffer> maskImage; + FloatRect maskRect; + bool emptyMask; +}; + +class RenderSVGResourceMasker : public RenderSVGResource { + +public: + RenderSVGResourceMasker(SVGStyledElement*); + virtual ~RenderSVGResourceMasker(); + + virtual const char* renderName() const { return "RenderSVGResourceMasker"; } + + virtual void invalidateClients(); + virtual void invalidateClient(RenderObject*); + + virtual bool applyResource(RenderObject*, GraphicsContext*); + virtual FloatRect resourceBoundingBox(const FloatRect&) const; + + SVGUnitTypes::SVGUnitType maskUnits() const { return toUnitType(static_cast<SVGMaskElement*>(node())->maskUnits()); } + SVGUnitTypes::SVGUnitType maskContentUnits() const { return toUnitType(static_cast<SVGMaskElement*>(node())->maskContentUnits()); } + + virtual RenderSVGResourceType resourceType() const { return s_resourceType; } + static RenderSVGResourceType s_resourceType; + +private: + void createMaskImage(MaskerData*, const SVGMaskElement*, RenderObject*); + + HashMap<RenderObject*, MaskerData*> m_masker; +}; + +} + +#endif +#endif diff --git a/WebCore/rendering/RenderSVGRoot.cpp b/WebCore/rendering/RenderSVGRoot.cpp index 74172fc..51bf3e7 100644 --- a/WebCore/rendering/RenderSVGRoot.cpp +++ b/WebCore/rendering/RenderSVGRoot.cpp @@ -77,6 +77,28 @@ void RenderSVGRoot::calcPrefWidths() setPrefWidthsDirty(false); } +int RenderSVGRoot::calcReplacedWidth(bool includeMaxWidth) const +{ + int replacedWidth = RenderBox::calcReplacedWidth(includeMaxWidth); + if (!style()->width().isPercent()) + return replacedWidth; + + // FIXME: Investigate in size rounding issues + SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); + return static_cast<int>(roundf(replacedWidth * svg->currentScale())); +} + +int RenderSVGRoot::calcReplacedHeight() const +{ + int replacedHeight = RenderBox::calcReplacedHeight(); + if (!style()->height().isPercent()) + return replacedHeight; + + // FIXME: Investigate in size rounding issues + SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); + return static_cast<int>(roundf(replacedHeight * svg->currentScale())); +} + void RenderSVGRoot::layout() { ASSERT(needsLayout()); @@ -84,22 +106,19 @@ void RenderSVGRoot::layout() // Arbitrary affine transforms are incompatible with LayoutState. view()->disableLayoutState(); - LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout()); + bool needsLayout = selfNeedsLayout(); + LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && needsLayout); - int oldWidth = width(); + IntSize oldSize(width(), height()); calcWidth(); - - int oldHeight = height(); calcHeight(); - SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); - setWidth(static_cast<int>(width() * svg->currentScale())); - setHeight(static_cast<int>(height() * svg->currentScale())); calcViewport(); // RenderSVGRoot needs to take special care to propagate window size changes to the children, // if the outermost <svg> is using relative x/y/width/height values. Hence the additonal parameters. - layoutChildren(this, selfNeedsLayout() || (svg->hasRelativeValues() && (width() != oldWidth || height() != oldHeight))); + SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); + layoutChildren(this, needsLayout || (svg->hasRelativeValues() && oldSize != size())); repainter.repaintAfterLayout(); view()->enableLayoutState(); @@ -123,7 +142,7 @@ void RenderSVGRoot::paint(PaintInfo& paintInfo, int parentX, int parentY) return; IntPoint parentOriginInContainer(parentX, parentY); - IntPoint borderBoxOriginInContainer = parentOriginInContainer + IntSize(x(), y()); + IntPoint borderBoxOriginInContainer = parentOriginInContainer + parentOriginToBorderBox(); if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)) paintBoxDecorations(paintInfo, borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y()); @@ -166,6 +185,12 @@ void RenderSVGRoot::paint(PaintInfo& paintInfo, int parentX, int parentY) paintOutline(paintInfo.context, borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y(), width(), height(), style()); } +void RenderSVGRoot::destroy() +{ + deregisterFromResources(this); + RenderBox::destroy(); +} + void RenderSVGRoot::calcViewport() { SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); @@ -177,15 +202,16 @@ void RenderSVGRoot::calcViewport() // In the normal case of <svg> being stand-alone or in a CSSBoxModel object we use // RenderBox::width()/height() (which pulls data from RenderStyle) m_viewportSize = FloatSize(width(), height()); - } else { - // In the SVGImage case grab the SVGLength values off of SVGSVGElement and use - // the special relativeWidthValue accessors which respect the specified containerSize - SVGLength width = svg->width(); - SVGLength height = svg->height(); - float viewportWidth = (width.unitType() == LengthTypePercentage) ? svg->relativeWidthValue() : width.value(svg); - float viewportHeight = (height.unitType() == LengthTypePercentage) ? svg->relativeHeightValue() : height.value(svg); - m_viewportSize = FloatSize(viewportWidth, viewportHeight); + return; } + + // In the SVGImage case grab the SVGLength values off of SVGSVGElement and use + // the special relativeWidthValue accessors which respect the specified containerSize + // FIXME: Check how SVGImage + zooming is supposed to be handled? + SVGLength width = svg->width(); + SVGLength height = svg->height(); + m_viewportSize = FloatSize(width.unitType() == LengthTypePercentage ? svg->relativeWidthValue() : width.value(svg), + height.unitType() == LengthTypePercentage ? svg->relativeHeightValue() : height.value(svg)); } // RenderBox methods will expect coordinates w/o any transforms in coordinates @@ -195,9 +221,9 @@ AffineTransform RenderSVGRoot::localToBorderBoxTransform() const IntSize borderAndPadding = borderOriginToContentBox(); SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); float scale = svg->currentScale(); - AffineTransform ctm(scale, 0, 0, scale, borderAndPadding.width(), borderAndPadding.height()); - ctm.translate(svg->currentTranslate().x(), svg->currentTranslate().y()); - return svg->viewBoxToViewTransform(width(), height()) * ctm; + FloatPoint translate = svg->currentTranslate(); + AffineTransform ctm(scale, 0, 0, scale, borderAndPadding.width() + translate.x(), borderAndPadding.height() + translate.y()); + return svg->viewBoxToViewTransform(width() / scale, height() / scale) * ctm; } IntSize RenderSVGRoot::parentOriginToBorderBox() const diff --git a/WebCore/rendering/RenderSVGRoot.h b/WebCore/rendering/RenderSVGRoot.h index 8ad5e40..53c1298 100644 --- a/WebCore/rendering/RenderSVGRoot.h +++ b/WebCore/rendering/RenderSVGRoot.h @@ -50,10 +50,13 @@ private: virtual int lineHeight(bool b, bool isRootLineBox = false) const; virtual int baselinePosition(bool b, bool isRootLineBox = false) const; virtual void calcPrefWidths(); - + virtual int calcReplacedWidth(bool includeMaxWidth = true) const; + virtual int calcReplacedHeight() const; virtual void layout(); virtual void paint(PaintInfo&, int parentX, int parentY); + virtual void destroy(); + virtual const AffineTransform& localToParentTransform() const; bool fillContains(const FloatPoint&) const; diff --git a/WebCore/rendering/RenderSVGText.cpp b/WebCore/rendering/RenderSVGText.cpp index e332c85..b8b9553 100644 --- a/WebCore/rendering/RenderSVGText.cpp +++ b/WebCore/rendering/RenderSVGText.cpp @@ -108,6 +108,12 @@ bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResul return false; } +void RenderSVGText::destroy() +{ + deregisterFromResources(this); + RenderSVGBlock::destroy(); +} + bool RenderSVGText::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction) { ASSERT_NOT_REACHED(); diff --git a/WebCore/rendering/RenderSVGText.h b/WebCore/rendering/RenderSVGText.h index 9ae96a0..ab4b09b 100644 --- a/WebCore/rendering/RenderSVGText.h +++ b/WebCore/rendering/RenderSVGText.h @@ -53,6 +53,8 @@ private: virtual bool requiresLayer() const { return false; } virtual void layout(); + virtual void destroy(); + virtual void absoluteRects(Vector<IntRect>&, int tx, int ty); virtual void absoluteQuads(Vector<FloatQuad>&); diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp index 7398a2f..344f4ab 100644 --- a/WebCore/rendering/RenderSlider.cpp +++ b/WebCore/rendering/RenderSlider.cpp @@ -107,7 +107,7 @@ double SliderRange::clampValue(double value) double SliderRange::valueFromElement(HTMLInputElement* element, bool* wasClamped) { double oldValue; - bool parseSuccess = HTMLInputElement::formStringToDouble(element->value(), &oldValue); + bool parseSuccess = HTMLInputElement::parseToDoubleForNumberType(element->value(), &oldValue); if (!parseSuccess) oldValue = (minimum + maximum) / 2; double newValue = clampValue(oldValue); @@ -383,7 +383,7 @@ void RenderSlider::updateFromElement() bool clamped; double value = range.valueFromElement(element, &clamped); if (clamped) - element->setValueFromRenderer(HTMLInputElement::formStringFromDouble(value)); + element->setValueFromRenderer(HTMLInputElement::serializeForNumberType(value)); // Layout will take care of the thumb's size and position. if (!m_thumb) { @@ -439,7 +439,7 @@ void RenderSlider::setValueForPosition(int position) if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart) fraction = 1 - fraction; double value = range.clampValue(range.valueFromProportion(fraction)); - element->setValueFromRenderer(HTMLInputElement::formStringFromDouble(value)); + element->setValueFromRenderer(HTMLInputElement::serializeForNumberType(value)); // Also update the position if appropriate. if (position != currentPosition()) { diff --git a/WebCore/rendering/RenderTableCell.cpp b/WebCore/rendering/RenderTableCell.cpp index d97ae6e..de71796 100644 --- a/WebCore/rendering/RenderTableCell.cpp +++ b/WebCore/rendering/RenderTableCell.cpp @@ -168,11 +168,11 @@ void RenderTableCell::setOverrideSize(int size) RenderBlock::setOverrideSize(size); } -IntSize RenderTableCell::offsetFromContainer(RenderObject* o) const +IntSize RenderTableCell::offsetFromContainer(RenderObject* o, const IntPoint& point) const { ASSERT(o == container()); - IntSize offset = RenderBlock::offsetFromContainer(o); + IntSize offset = RenderBlock::offsetFromContainer(o, point); if (parent()) offset.expand(-parentBox()->x(), -parentBox()->y()); diff --git a/WebCore/rendering/RenderTableCell.h b/WebCore/rendering/RenderTableCell.h index 0f8580d..a5a1edd 100644 --- a/WebCore/rendering/RenderTableCell.h +++ b/WebCore/rendering/RenderTableCell.h @@ -126,7 +126,7 @@ private: virtual void paintBoxDecorations(PaintInfo&, int tx, int ty); virtual void paintMask(PaintInfo&, int tx, int ty); - virtual IntSize offsetFromContainer(RenderObject*) const; + virtual IntSize offsetFromContainer(RenderObject*, const IntPoint&) const; virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp index 2e696a9..4653273 100644 --- a/WebCore/rendering/RenderText.cpp +++ b/WebCore/rendering/RenderText.cpp @@ -230,27 +230,32 @@ void RenderText::absoluteRectsForRange(Vector<IntRect>& rects, unsigned start, u start = min(start, static_cast<unsigned>(INT_MAX)); end = min(end, static_cast<unsigned>(INT_MAX)); - FloatPoint absPos = localToAbsolute(FloatPoint()); - for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { // Note: box->end() returns the index of the last character, not the index past it if (start <= box->start() && box->end() < end) { - IntRect r = IntRect(absPos.x() + box->x(), absPos.y() + box->y(), box->width(), box->height()); + IntRect r = IntRect(box->x(), box->y(), box->width(), box->height()); if (useSelectionHeight) { - IntRect selectionRect = box->selectionRect(absPos.x(), absPos.y(), start, end); + IntRect selectionRect = box->selectionRect(0, 0, start, end); r.setHeight(selectionRect.height()); r.setY(selectionRect.y()); } + FloatPoint origin = localToAbsolute(r.location()); + r.setX(origin.x()); + r.setY(origin.y()); rects.append(r); } else { unsigned realEnd = min(box->end() + 1, end); - IntRect r = box->selectionRect(absPos.x(), absPos.y(), start, realEnd); + IntRect r = box->selectionRect(0, 0, start, realEnd); if (!r.isEmpty()) { if (!useSelectionHeight) { // change the height and y position because selectionRect uses selection-specific values r.setHeight(box->height()); - r.setY(absPos.y() + box->y()); + r.setY(box->y()); } + FloatPoint origin = localToAbsolute(r.location()); + localToAbsolute(origin); + r.setX(origin.x()); + r.setY(origin.y()); rects.append(r); } } diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index c0ba070..d18940b 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -459,6 +459,78 @@ IntRect RenderTextControl::controlClipRect(int tx, int ty) const return clipRect; } +static const char* fontFamiliesWithInvalidCharWidth[] = { + "American Typewriter", + "Arial Hebrew", + "Chalkboard", + "Cochin", + "Corsiva Hebrew", + "Courier", + "Euphemia UCAS", + "Geneva", + "Gill Sans", + "Hei", + "Helvetica", + "Hoefler Text", + "InaiMathi", + "Kai", + "Lucida Grande", + "Marker Felt", + "Monaco", + "Mshtakan", + "New Peninim MT", + "Osaka", + "Raanana", + "STHeiti", + "Symbol", + "Times", + "Apple Braille", + "Apple LiGothic", + "Apple LiSung", + "Apple Symbols", + "AppleGothic", + "AppleMyungjo", + "#GungSeo", + "#HeadLineA", + "#PCMyungjo", + "#PilGi", +}; + +// For font families where any of the fonts don't have a valid entry in the OS/2 table +// for avgCharWidth, fallback to the legacy webkit behavior of getting the avgCharWidth +// from the width of a '0'. This only seems to apply to a fixed number of Mac fonts, +// but, in order to get similar rendering across platforms, we do this check for +// all platforms. +bool RenderTextControl::hasValidAvgCharWidth(AtomicString family) +{ + static HashSet<AtomicString>* fontFamiliesWithInvalidCharWidthMap = 0; + + if (!fontFamiliesWithInvalidCharWidthMap) { + fontFamiliesWithInvalidCharWidthMap = new HashSet<AtomicString>; + + for (unsigned i = 0; i < sizeof(fontFamiliesWithInvalidCharWidth) / sizeof(fontFamiliesWithInvalidCharWidth[0]); i++) + fontFamiliesWithInvalidCharWidthMap->add(AtomicString(fontFamiliesWithInvalidCharWidth[i])); + } + + return !fontFamiliesWithInvalidCharWidthMap->contains(family); +} + +float RenderTextControl::getAvgCharWidth(AtomicString family) +{ + if (hasValidAvgCharWidth(family)) + return roundf(style()->font().primaryFont()->avgCharWidth()); + + const UChar ch = '0'; + return style()->font().floatWidth(TextRun(&ch, 1, false, 0, 0, false, false, false)); +} + +float RenderTextControl::scaleEmToUnits(int x) const +{ + // This matches the unitsPerEm value for MS Shell Dlg and Courier New from the "head" font table. + float unitsPerEm = 2048.0f; + return roundf(style()->font().size() * x / unitsPerEm); +} + void RenderTextControl::calcPrefWidths() { ASSERT(prefWidthsDirty()); @@ -470,8 +542,8 @@ void RenderTextControl::calcPrefWidths() m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value()); else { // Use average character width. Matches IE. - float charWidth = style()->font().primaryFont()->avgCharWidth(); - m_maxPrefWidth = preferredContentWidth(charWidth) + m_innerText->renderBox()->paddingLeft() + m_innerText->renderBox()->paddingRight(); + AtomicString family = style()->font().family().family(); + m_maxPrefWidth = preferredContentWidth(getAvgCharWidth(family)) + m_innerText->renderBox()->paddingLeft() + m_innerText->renderBox()->paddingRight(); } if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) { diff --git a/WebCore/rendering/RenderTextControl.h b/WebCore/rendering/RenderTextControl.h index d1f3749..2fc8edc 100644 --- a/WebCore/rendering/RenderTextControl.h +++ b/WebCore/rendering/RenderTextControl.h @@ -74,6 +74,10 @@ protected: int textBlockWidth() const; int textBlockHeight() const; + float scaleEmToUnits(int x) const; + + static bool hasValidAvgCharWidth(AtomicString family); + virtual float getAvgCharWidth(AtomicString family); virtual int preferredContentWidth(float charWidth) const = 0; virtual void adjustControlHeightBasedOnLineHeight(int lineHeight) = 0; virtual void cacheSelection(int start, int end) = 0; diff --git a/WebCore/rendering/RenderTextControlMultiLine.cpp b/WebCore/rendering/RenderTextControlMultiLine.cpp index 0b4c7a7..9fbde3a 100644 --- a/WebCore/rendering/RenderTextControlMultiLine.cpp +++ b/WebCore/rendering/RenderTextControlMultiLine.cpp @@ -80,6 +80,17 @@ void RenderTextControlMultiLine::forwardEvent(Event* event) RenderTextControl::forwardEvent(event); } +float RenderTextControlMultiLine::getAvgCharWidth(AtomicString family) +{ + // Since Lucida Grande is the default font, we want this to match the width + // of Courier New, the default font for textareas in IE, Firefox and Safari Win. + // 1229 is the avgCharWidth value in the OS/2 table for Courier New. + if (family == AtomicString("Lucida Grande")) + return scaleEmToUnits(1229); + + return RenderTextControl::getAvgCharWidth(family); +} + int RenderTextControlMultiLine::preferredContentWidth(float charWidth) const { int factor = static_cast<HTMLTextAreaElement*>(node())->cols(); diff --git a/WebCore/rendering/RenderTextControlMultiLine.h b/WebCore/rendering/RenderTextControlMultiLine.h index 3371a8f..fbca308 100644 --- a/WebCore/rendering/RenderTextControlMultiLine.h +++ b/WebCore/rendering/RenderTextControlMultiLine.h @@ -40,6 +40,7 @@ private: virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); + virtual float getAvgCharWidth(AtomicString family); virtual int preferredContentWidth(float charWidth) const; virtual void adjustControlHeightBasedOnLineHeight(int lineHeight); virtual int baselinePosition(bool firstLine, bool isRootLineBox) const; diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp index b68f004..4edd203 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.cpp +++ b/WebCore/rendering/RenderTextControlSingleLine.cpp @@ -385,7 +385,19 @@ int RenderTextControlSingleLine::textBlockWidth() const return width; } + +float RenderTextControlSingleLine::getAvgCharWidth(AtomicString family) +{ + // Since Lucida Grande is the default font, we want this to match the width + // of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and + // IE for some encodings (in IE, the default font is encoding specific). + // 901 is the avgCharWidth value in the OS/2 table for MS Shell Dlg. + if (family == AtomicString("Lucida Grande")) + return scaleEmToUnits(901); + return RenderTextControl::getAvgCharWidth(family); +} + int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const { int factor = inputElement()->size(); @@ -394,8 +406,20 @@ int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const int result = static_cast<int>(ceilf(charWidth * factor)); + float maxCharWidth = 0.f; + AtomicString family = style()->font().family().family(); + // Since Lucida Grande is the default font, we want this to match the width + // of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and + // IE for some encodings (in IE, the default font is encoding specific). + // 4027 is the (xMax - xMin) value in the "head" font table for MS Shell Dlg. + if (family == AtomicString("Lucida Grande")) + maxCharWidth = scaleEmToUnits(4027); + else if (hasValidAvgCharWidth(family)) + maxCharWidth = roundf(style()->font().primaryFont()->maxCharWidth()); + // For text inputs, IE adds some extra width. - result += style()->font().primaryFont()->maxCharWidth() - charWidth; + if (maxCharWidth > 0.f) + result += maxCharWidth - charWidth; if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) result += resultsRenderer->borderLeft() + resultsRenderer->borderRight() + diff --git a/WebCore/rendering/RenderTextControlSingleLine.h b/WebCore/rendering/RenderTextControlSingleLine.h index e30ff0d..aa1f1e3 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.h +++ b/WebCore/rendering/RenderTextControlSingleLine.h @@ -75,6 +75,7 @@ private: virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f, Node** stopNode = 0); int textBlockWidth() const; + virtual float getAvgCharWidth(AtomicString family); virtual int preferredContentWidth(float charWidth) const; virtual void adjustControlHeightBasedOnLineHeight(int lineHeight); diff --git a/WebCore/rendering/RenderThemeChromiumMac.mm b/WebCore/rendering/RenderThemeChromiumMac.mm index e274b05..03aab1c 100644 --- a/WebCore/rendering/RenderThemeChromiumMac.mm +++ b/WebCore/rendering/RenderThemeChromiumMac.mm @@ -572,7 +572,7 @@ FloatRect RenderThemeChromiumMac::convertToPaintingRect(const RenderObject* inpu const RenderObject* renderer = partRenderer; while (renderer && renderer != inputRenderer) { RenderObject* containingRenderer = renderer->container(); - offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer); + offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer, IntPoint()); renderer = containingRenderer; } // If the input renderer was not a container, something went wrong diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm index ddb538b..b6ce93d 100644 --- a/WebCore/rendering/RenderThemeMac.mm +++ b/WebCore/rendering/RenderThemeMac.mm @@ -520,7 +520,7 @@ FloatRect RenderThemeMac::convertToPaintingRect(const RenderObject* inputRendere const RenderObject* renderer = partRenderer; while (renderer && renderer != inputRenderer) { RenderObject* containingRenderer = renderer->container(); - offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer); + offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer, IntPoint()); renderer = containingRenderer; } // If the input renderer was not a container, something went wrong diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp index ca4d9d1..164a656 100644 --- a/WebCore/rendering/RenderTreeAsText.cpp +++ b/WebCore/rendering/RenderTreeAsText.cpp @@ -395,6 +395,10 @@ void write(TextStream& ts, const RenderObject& o, int indent) write(ts, *toRenderPath(&o), indent); return; } + if (o.isSVGResource()) { + writeSVGResource(ts, o, indent); + return; + } if (o.isSVGContainer()) { writeSVGContainer(ts, o, indent); return; diff --git a/WebCore/rendering/RenderVideo.cpp b/WebCore/rendering/RenderVideo.cpp index 813f2ef..13d6f60 100644 --- a/WebCore/rendering/RenderVideo.cpp +++ b/WebCore/rendering/RenderVideo.cpp @@ -275,14 +275,6 @@ void RenderVideo::acceleratedRenderingStateChanged() if (p) p->acceleratedRenderingStateChanged(); } - -GraphicsLayer* RenderVideo::videoGraphicsLayer() const -{ - if (hasLayer() && layer()->isComposited()) - return layer()->backing()->graphicsLayer(); - - return 0; -} #endif // USE(ACCELERATED_COMPOSITING) } // namespace WebCore diff --git a/WebCore/rendering/RenderVideo.h b/WebCore/rendering/RenderVideo.h index 3ca5328..16c846d 100644 --- a/WebCore/rendering/RenderVideo.h +++ b/WebCore/rendering/RenderVideo.h @@ -34,9 +34,6 @@ namespace WebCore { class HTMLMediaElement; class HTMLVideoElement; -#if USE(ACCELERATED_COMPOSITING) -class GraphicsLayer; -#endif class RenderVideo : public RenderMedia { public: @@ -49,7 +46,6 @@ public: #if USE(ACCELERATED_COMPOSITING) bool supportsAcceleratedRendering() const; void acceleratedRenderingStateChanged(); - GraphicsLayer* videoGraphicsLayer() const; #endif private: diff --git a/WebCore/rendering/SVGCharacterLayoutInfo.h b/WebCore/rendering/SVGCharacterLayoutInfo.h index f80c79c..f0d1fa4 100644 --- a/WebCore/rendering/SVGCharacterLayoutInfo.h +++ b/WebCore/rendering/SVGCharacterLayoutInfo.h @@ -297,13 +297,6 @@ struct SVGTextChunkWalkerBase { // Followings methods are only used for painting text chunks virtual void start(InlineBox*) = 0; virtual void end(InlineBox*) = 0; - - virtual bool setupBackground(InlineBox*) = 0; - virtual bool setupFill(InlineBox*) = 0; - virtual bool setupFillSelection(InlineBox*) = 0; - virtual bool setupStroke(InlineBox*) = 0; - virtual bool setupStrokeSelection(InlineBox*) = 0; - virtual bool setupForeground(InlineBox*) = 0; }; template<typename CallbackClass> @@ -319,31 +312,14 @@ public: typedef void (CallbackClass::*SVGTextChunkStartCallback)(InlineBox* box); typedef void (CallbackClass::*SVGTextChunkEndCallback)(InlineBox* box); - typedef bool (CallbackClass::*SVGTextChunkSetupBackgroundCallback)(InlineBox* box); - typedef bool (CallbackClass::*SVGTextChunkSetupFillCallback)(InlineBox* box); - typedef bool (CallbackClass::*SVGTextChunkSetupStrokeCallback)(InlineBox* box); - typedef bool (CallbackClass::*SVGTextChunkSetupForegroundCallback)(InlineBox* box); - - SVGTextChunkWalker(CallbackClass* object, + SVGTextChunkWalker(CallbackClass* object, SVGTextChunkWalkerCallback walker, SVGTextChunkStartCallback start = 0, - SVGTextChunkEndCallback end = 0, - SVGTextChunkSetupBackgroundCallback background = 0, - SVGTextChunkSetupFillCallback fill = 0, - SVGTextChunkSetupFillCallback fillSelection = 0, - SVGTextChunkSetupStrokeCallback stroke = 0, - SVGTextChunkSetupStrokeCallback strokeSelection = 0, - SVGTextChunkSetupForegroundCallback foreground = 0) + SVGTextChunkEndCallback end = 0) : m_object(object) , m_walkerCallback(walker) , m_startCallback(start) , m_endCallback(end) - , m_setupBackgroundCallback(background) - , m_setupFillCallback(fill) - , m_setupFillSelectionCallback(fillSelection) - , m_setupStrokeCallback(stroke) - , m_setupStrokeSelectionCallback(strokeSelection) - , m_setupForegroundCallback(foreground) { ASSERT(object); ASSERT(walker); @@ -372,71 +348,11 @@ public: ASSERT_NOT_REACHED(); } - virtual bool setupBackground(InlineBox* box) - { - if (m_setupBackgroundCallback) - return (*m_object.*m_setupBackgroundCallback)(box); - - ASSERT_NOT_REACHED(); - return false; - } - - virtual bool setupFill(InlineBox* box) - { - if (m_setupFillCallback) - return (*m_object.*m_setupFillCallback)(box); - - ASSERT_NOT_REACHED(); - return false; - } - - virtual bool setupFillSelection(InlineBox* box) - { - if (m_setupFillSelectionCallback) - return (*m_object.*m_setupFillSelectionCallback)(box); - - ASSERT_NOT_REACHED(); - return false; - } - - virtual bool setupStroke(InlineBox* box) - { - if (m_setupStrokeCallback) - return (*m_object.*m_setupStrokeCallback)(box); - - ASSERT_NOT_REACHED(); - return false; - } - - virtual bool setupStrokeSelection(InlineBox* box) - { - if (m_setupStrokeSelectionCallback) - return (*m_object.*m_setupStrokeSelectionCallback)(box); - - ASSERT_NOT_REACHED(); - return false; - } - - virtual bool setupForeground(InlineBox* box) - { - if (m_setupForegroundCallback) - return (*m_object.*m_setupForegroundCallback)(box); - - ASSERT_NOT_REACHED(); - return false; - } - private: CallbackClass* m_object; SVGTextChunkWalkerCallback m_walkerCallback; SVGTextChunkStartCallback m_startCallback; SVGTextChunkEndCallback m_endCallback; - SVGTextChunkSetupBackgroundCallback m_setupBackgroundCallback; - SVGTextChunkSetupFillCallback m_setupFillCallback; - SVGTextChunkSetupFillCallback m_setupFillSelectionCallback; - SVGTextChunkSetupStrokeCallback m_setupStrokeCallback; - SVGTextChunkSetupStrokeCallback m_setupStrokeSelectionCallback; - SVGTextChunkSetupForegroundCallback m_setupForegroundCallback; }; struct SVGTextChunkLayoutInfo { diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp index 079a36e..dc1b3c1 100644 --- a/WebCore/rendering/SVGRenderSupport.cpp +++ b/WebCore/rendering/SVGRenderSupport.cpp @@ -28,13 +28,15 @@ #include "SVGRenderSupport.h" #include "AffineTransform.h" +#include "Document.h" #include "ImageBuffer.h" #include "RenderObject.h" #include "RenderSVGContainer.h" +#include "RenderSVGResource.h" +#include "RenderSVGResourceMasker.h" #include "RenderView.h" #include "SVGResourceClipper.h" #include "SVGResourceFilter.h" -#include "SVGResourceMasker.h" #include "SVGStyledElement.h" #include "SVGURIReference.h" #include "TransformState.h" @@ -127,17 +129,14 @@ bool SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject filter = newFilter; #endif - SVGResourceClipper* clipper = getClipperById(document, clipperId, object); - SVGResourceMasker* masker = getMaskerById(document, maskerId, object); - - if (masker) { - masker->addClient(styledElement); - if (!masker->applyMask(paintInfo.context, object)) + // apply Masker + if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(document, maskerId)) { + if (!masker->applyResource(object, paintInfo.context)) return false; } else if (!maskerId.isEmpty()) svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); - if (clipper) { + if (SVGResourceClipper* clipper = getClipperById(document, clipperId, object)) { clipper->addClient(styledElement); clipper->applyClip(paintInfo.context, object->objectBoundingBox()); } else if (!clipperId.isEmpty()) @@ -297,13 +296,19 @@ FloatRect SVGRenderBase::clipperBoundingBoxForRenderer(const RenderObject* objec FloatRect SVGRenderBase::maskerBoundingBoxForRenderer(const RenderObject* object) const { - SVGResourceMasker* masker = getMaskerById(object->document(), object->style()->svgStyle()->maskElement(), object); - if (masker) - return masker->maskerBoundingBox(object->objectBoundingBox()); + if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object->document(), object->style()->svgStyle()->maskElement())) + return masker->resourceBoundingBox(object->objectBoundingBox()); return FloatRect(); } +void SVGRenderBase::deregisterFromResources(RenderObject* object) +{ + // We only have a renderer for masker at the moment. + if (RenderSVGResourceMasker* resource = getRenderSVGResourceById<RenderSVGResourceMasker>(object->document(), object->style()->svgStyle()->maskElement())) + resource->invalidateClient(object); +} + void applyTransformToPaintInfo(RenderObject::PaintInfo& paintInfo, const AffineTransform& localToAncestorTransform) { if (localToAncestorTransform.isIdentity()) diff --git a/WebCore/rendering/SVGRenderSupport.h b/WebCore/rendering/SVGRenderSupport.h index cf75365..427ff1f 100644 --- a/WebCore/rendering/SVGRenderSupport.h +++ b/WebCore/rendering/SVGRenderSupport.h @@ -26,61 +26,65 @@ #if ENABLE(SVG) #include "RenderObject.h" +#include "SVGElement.h" +#include "SVGStyledElement.h" namespace WebCore { - class SVGResourceFilter; - class ImageBuffer; +class SVGResourceFilter; +class ImageBuffer; - // SVGRendererBase is an abstract base class which all SVG renderers inherit - // from in order to share SVG renderer code. - // FIXME: This code can all move into RenderSVGModelObject once - // all SVG renderers inherit from RenderSVGModelObject. - class SVGRenderBase { - public: - virtual ~SVGRenderBase(); +// SVGRendererBase is an abstract base class which all SVG renderers inherit +// from in order to share SVG renderer code. +// FIXME: This code can all move into RenderSVGModelObject once +// all SVG renderers inherit from RenderSVGModelObject. +class SVGRenderBase { +public: + virtual ~SVGRenderBase(); - virtual const SVGRenderBase* toSVGRenderBase() const { return this; } + virtual const SVGRenderBase* toSVGRenderBase() const { return this; } - // FIXME: These are only public for SVGRootInlineBox. - // It's unclear if these should be exposed or not. SVGRootInlineBox may - // pass the wrong RenderObject* and boundingBox to these functions. - static bool prepareToRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, const FloatRect& boundingBox, SVGResourceFilter*&, SVGResourceFilter* rootFilter = 0); - static void finishRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, SVGResourceFilter*&, GraphicsContext* savedContext); + // FIXME: These are only public for SVGRootInlineBox. + // It's unclear if these should be exposed or not. SVGRootInlineBox may + // pass the wrong RenderObject* and boundingBox to these functions. + static bool prepareToRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, const FloatRect& boundingBox, SVGResourceFilter*&, SVGResourceFilter* rootFilter = 0); + static void finishRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, SVGResourceFilter*&, GraphicsContext* savedContext); - // Layout all children of the passed render object - static void layoutChildren(RenderObject*, bool selfNeedsLayout); + // Layout all children of the passed render object + static void layoutChildren(RenderObject*, bool selfNeedsLayout); - // Helper function determining wheter overflow is hidden - static bool isOverflowHidden(const RenderObject*); + // Helper function determining wheter overflow is hidden + static bool isOverflowHidden(const RenderObject*); - virtual FloatRect strokeBoundingBox() const { return FloatRect(); } - virtual FloatRect markerBoundingBox() const { return FloatRect(); } + virtual FloatRect strokeBoundingBox() const { return FloatRect(); } + virtual FloatRect markerBoundingBox() const { return FloatRect(); } - // returns the bounding box of filter, clipper, marker and masker (or the empty rect if no filter) in local coordinates - FloatRect filterBoundingBoxForRenderer(const RenderObject*) const; - FloatRect clipperBoundingBoxForRenderer(const RenderObject*) const; - FloatRect maskerBoundingBoxForRenderer(const RenderObject*) const; + // returns the bounding box of filter, clipper, marker and masker (or the empty rect if no filter) in local coordinates + FloatRect filterBoundingBoxForRenderer(const RenderObject*) const; + FloatRect clipperBoundingBoxForRenderer(const RenderObject*) const; + FloatRect maskerBoundingBoxForRenderer(const RenderObject*) const; - protected: - static IntRect clippedOverflowRectForRepaint(RenderObject*, RenderBoxModelObject* repaintContainer); - static void computeRectForRepaint(RenderObject*, RenderBoxModelObject* repaintContainer, IntRect&, bool fixed); +protected: + static IntRect clippedOverflowRectForRepaint(RenderObject*, RenderBoxModelObject* repaintContainer); + static void computeRectForRepaint(RenderObject*, RenderBoxModelObject* repaintContainer, IntRect&, bool fixed); - static void mapLocalToContainer(const RenderObject*, RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&); + static void mapLocalToContainer(const RenderObject*, RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&); - // Used to share the "walk all the children" logic between objectBoundingBox - // and repaintRectInLocalCoordinates in RenderSVGRoot and RenderSVGContainer - static FloatRect computeContainerBoundingBox(const RenderObject* container, bool includeAllPaintedContent); - }; + // Used to share the "walk all the children" logic between objectBoundingBox + // and repaintRectInLocalCoordinates in RenderSVGRoot and RenderSVGContainer + static FloatRect computeContainerBoundingBox(const RenderObject* container, bool includeAllPaintedContent); - // FIXME: This should move to RenderObject or PaintInfo - // Used for transforming the GraphicsContext and damage rect before passing PaintInfo to child renderers. - void applyTransformToPaintInfo(RenderObject::PaintInfo&, const AffineTransform& localToChildTransform); + static void deregisterFromResources(RenderObject*); +}; - // This offers a way to render parts of a WebKit rendering tree into a ImageBuffer. - void renderSubtreeToImage(ImageBuffer*, RenderObject*); +// FIXME: This should move to RenderObject or PaintInfo +// Used for transforming the GraphicsContext and damage rect before passing PaintInfo to child renderers. +void applyTransformToPaintInfo(RenderObject::PaintInfo&, const AffineTransform& localToChildTransform); - void clampImageBufferSizeToViewport(FrameView*, IntSize& imageBufferSize); +// This offers a way to render parts of a WebKit rendering tree into a ImageBuffer. +void renderSubtreeToImage(ImageBuffer*, RenderObject*); + +void clampImageBufferSizeToViewport(FrameView*, IntSize& imageBufferSize); } // namespace WebCore #endif // ENABLE(SVG) diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp index aff718f..f892144 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.cpp +++ b/WebCore/rendering/SVGRenderTreeAsText.cpp @@ -38,6 +38,7 @@ #include "RenderPath.h" #include "RenderSVGContainer.h" #include "RenderSVGInlineText.h" +#include "RenderSVGResourceMasker.h" #include "RenderSVGRoot.h" #include "RenderSVGText.h" #include "RenderTreeAsText.h" @@ -195,6 +196,23 @@ TextStream& operator<<(TextStream& ts, const AffineTransform& transform) return ts; } +static TextStream& operator<<(TextStream& ts, const SVGUnitTypes::SVGUnitType& unitType) +{ + switch (unitType) { + case SVGUnitTypes::SVG_UNIT_TYPE_UNKNOWN: + ts << "unknown"; + break; + case SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE: + ts << "userSpaceOnUse"; + break; + case SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX: + ts << "objectBoundingBox"; + break; + } + + return ts; +} + TextStream& operator<<(TextStream& ts, const Color& c) { return ts << c.name(); @@ -464,11 +482,33 @@ static void writeChildren(TextStream& ts, const RenderObject& object, int indent write(ts, *child, indent + 1); } +void writeSVGResource(TextStream& ts, const RenderObject& object, int indent) +{ + writeStandardPrefix(ts, object, indent); + + Element* element = static_cast<Element*>(object.node()); + const AtomicString& id = element->getIDAttribute(); + writeNameAndQuotedValue(ts, "id", id); + + RenderSVGResource* resource = const_cast<RenderObject&>(object).toRenderSVGResource(); + if (resource->resourceType() == MaskerResourceType) { + RenderSVGResourceMasker* masker = static_cast<RenderSVGResourceMasker*>(resource); + ASSERT(masker); + writeNameValuePair(ts, "maskUnits", masker->maskUnits()); + writeNameValuePair(ts, "maskContentUnits", masker->maskContentUnits()); + } + + // FIXME: Handle other RenderSVGResource* classes here, after converting them from SVGResource*. + ts << "\n"; + writeChildren(ts, object, indent); +} + void writeSVGContainer(TextStream& ts, const RenderObject& container, int indent) { writeStandardPrefix(ts, container, indent); writePositionAndStyle(ts, container); ts << "\n"; + writeResources(ts, container, indent); writeChildren(ts, container, indent); } @@ -484,6 +524,7 @@ void writeSVGText(TextStream& ts, const RenderBlock& text, int indent) writeStandardPrefix(ts, text, indent); writeRenderSVGTextBox(ts, text); ts << "\n"; + writeResources(ts, text, indent); writeChildren(ts, text, indent); } @@ -493,20 +534,41 @@ void writeSVGInlineText(TextStream& ts, const RenderText& text, int indent) // Why not just linesBoundingBox()? ts << " " << FloatRect(text.firstRunOrigin(), text.linesBoundingBox().size()) << "\n"; + writeResources(ts, text, indent); writeSVGInlineTextBoxes(ts, text, indent); } +void writeSVGImage(TextStream& ts, const RenderImage& image, int indent) +{ + writeStandardPrefix(ts, image, indent); + writePositionAndStyle(ts, image); + ts << "\n"; + writeResources(ts, image, indent); +} + void write(TextStream& ts, const RenderPath& path, int indent) { writeStandardPrefix(ts, path, indent); ts << path << "\n"; + writeResources(ts, path, indent); } -void writeSVGImage(TextStream& ts, const RenderImage& image, int indent) +void writeResources(TextStream& ts, const RenderObject& object, int indent) { - writeStandardPrefix(ts, image, indent); - writePositionAndStyle(ts, image); - ts << "\n"; + const RenderStyle* style = object.style(); + const SVGRenderStyle* svgStyle = style->svgStyle(); + + if (!svgStyle->maskElement().isEmpty()) { + if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object.document(), svgStyle->maskElement())) { + writeIndent(ts, indent); + ts << " "; + writeNameAndQuotedValue(ts, "masker", svgStyle->maskElement()); + ts << " "; + writeStandardPrefix(ts, *masker, 0); + ts << " " << masker->resourceBoundingBox(object.objectBoundingBox()) << "\n"; + } + } + // FIXME: Handle other RenderSVGResource* classes here, after converting them from SVGResource*. } void writeRenderResources(TextStream& ts, Node* parent) diff --git a/WebCore/rendering/SVGRenderTreeAsText.h b/WebCore/rendering/SVGRenderTreeAsText.h index 13fc475..905652b 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.h +++ b/WebCore/rendering/SVGRenderTreeAsText.h @@ -46,14 +46,17 @@ namespace WebCore { class RenderSVGRoot; class RenderText; class AffineTransform; + class SVGUnitTypes; // functions used by the main RenderTreeAsText code void write(TextStream&, const RenderPath&, int indent); void write(TextStream&, const RenderSVGRoot&, int indent); +void writeSVGResource(TextStream&, const RenderObject&, int indent); void writeSVGContainer(TextStream&, const RenderObject&, int indent); void writeSVGImage(TextStream&, const RenderImage&, int indent); void writeSVGInlineText(TextStream&, const RenderText&, int indent); void writeSVGText(TextStream&, const RenderBlock&, int indent); +void writeResources(TextStream&, const RenderObject&, int indent); void writeRenderResources(TextStream&, Node* parent); diff --git a/WebCore/rendering/SVGRootInlineBox.cpp b/WebCore/rendering/SVGRootInlineBox.cpp index d0dd4a8..03b9db4 100644 --- a/WebCore/rendering/SVGRootInlineBox.cpp +++ b/WebCore/rendering/SVGRootInlineBox.cpp @@ -363,10 +363,10 @@ struct SVGRootInlineBoxPaintWalker { ASSERT(!m_chunkStarted); } - bool mayHaveSelection(InlineBox* box) const + bool mayHaveSelection(SVGInlineTextBox* box) const { int selectionStart = 0, selectionEnd = 0; - box->renderer()->selectionStartEnd(selectionStart, selectionEnd); + box->selectionStartEnd(selectionStart, selectionEnd); return selectionStart < selectionEnd; } @@ -436,13 +436,13 @@ struct SVGRootInlineBoxPaintWalker { m_paintInfo.rect = m_savedInfo.rect; } - bool chunkSetupBackgroundCallback(InlineBox* /*box*/) + bool setupBackground(SVGInlineTextBox* /*box*/) { m_textPaintInfo.subphase = SVGTextPaintSubphaseBackground; return true; } - bool chunkSetupFillCallback(InlineBox* box) + bool setupFill(SVGInlineTextBox* box) { InlineFlowBox* flowBox = box->parent(); @@ -464,7 +464,7 @@ struct SVGRootInlineBoxPaintWalker { return false; } - bool chunkSetupFillSelectionCallback(InlineBox* box) + bool setupFillSelection(SVGInlineTextBox* box) { InlineFlowBox* flowBox = box->parent(); @@ -492,7 +492,7 @@ struct SVGRootInlineBoxPaintWalker { return false; } - bool chunkSetupStrokeCallback(InlineBox* box) + bool setupStroke(SVGInlineTextBox* box) { InlineFlowBox* flowBox = box->parent(); @@ -516,7 +516,7 @@ struct SVGRootInlineBoxPaintWalker { return false; } - bool chunkSetupStrokeSelectionCallback(InlineBox* box) + bool setupStrokeSelection(SVGInlineTextBox* box) { InlineFlowBox* flowBox = box->parent(); @@ -545,7 +545,7 @@ struct SVGRootInlineBoxPaintWalker { return false; } - bool chunkSetupForegroundCallback(InlineBox* /*box*/) + bool setupForeground(SVGInlineTextBox* /*box*/) { teardownFillPaintServer(); teardownStrokePaintServer(); @@ -576,6 +576,28 @@ struct SVGRootInlineBoxPaintWalker { void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm, const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end) { + if (setupBackground(textBox)) + paintChunk(textBox, startOffset, chunkCtm, start, end); + + if (setupFill(textBox)) + paintChunk(textBox, startOffset, chunkCtm, start, end); + + if (setupFillSelection(textBox)) + paintChunk(textBox, startOffset, chunkCtm, start, end); + + if (setupStroke(textBox)) + paintChunk(textBox, startOffset, chunkCtm, start, end); + + if (setupStrokeSelection(textBox)) + paintChunk(textBox, startOffset, chunkCtm, start, end); + + if (setupForeground(textBox)) + paintChunk(textBox, startOffset, chunkCtm, start, end); + } + + void paintChunk(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm, + const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end) + { RenderText* text = textBox->textRenderer(); ASSERT(text); @@ -679,13 +701,7 @@ void SVGRootInlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) SVGTextChunkWalker<SVGRootInlineBoxPaintWalker> walker(&walkerCallback, &SVGRootInlineBoxPaintWalker::chunkPortionCallback, &SVGRootInlineBoxPaintWalker::chunkStartCallback, - &SVGRootInlineBoxPaintWalker::chunkEndCallback, - &SVGRootInlineBoxPaintWalker::chunkSetupBackgroundCallback, - &SVGRootInlineBoxPaintWalker::chunkSetupFillCallback, - &SVGRootInlineBoxPaintWalker::chunkSetupFillSelectionCallback, - &SVGRootInlineBoxPaintWalker::chunkSetupStrokeCallback, - &SVGRootInlineBoxPaintWalker::chunkSetupStrokeSelectionCallback, - &SVGRootInlineBoxPaintWalker::chunkSetupForegroundCallback); + &SVGRootInlineBoxPaintWalker::chunkEndCallback); walkTextChunks(&walker); } @@ -1777,28 +1793,7 @@ void SVGRootInlineBox::walkTextChunks(SVGTextChunkWalkerBase* walker, const SVGI ASSERT(itCharEnd <= curChunk.end); // Process this chunk portion - if (textBox) - (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); - else { - if (walker->setupBackground(range.box)) - (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); - - if (walker->setupFill(range.box)) - (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); - - if (walker->setupFillSelection(range.box)) - (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); - - if (walker->setupStroke(range.box)) - (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); - - if (walker->setupStrokeSelection(range.box)) - (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); - - if (walker->setupForeground(range.box)) - (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); - - } + (*walker)(rangeTextBox, range.startOffset, curChunk.ctm, itCharBegin, itCharEnd); chunkOffset += length; diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp index 0952557..712344f 100644 --- a/WebCore/rendering/style/RenderStyle.cpp +++ b/WebCore/rendering/style/RenderStyle.cpp @@ -192,6 +192,11 @@ static inline int pseudoBit(PseudoId pseudo) return 1 << (pseudo - 1); } +bool RenderStyle::hasAnyPublicPseudoStyles() const +{ + return PUBLIC_PSEUDOID_MASK & noninherited_flags._pseudoBits; +} + bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const { ASSERT(pseudo > NOPSEUDO); diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h index 696a2b7..c7db254 100644 --- a/WebCore/rendering/style/RenderStyle.h +++ b/WebCore/rendering/style/RenderStyle.h @@ -350,6 +350,7 @@ public: bool isStyleAvailable() const; + bool hasAnyPublicPseudoStyles() const; bool hasPseudoStyle(PseudoId pseudo) const; void setHasPseudoStyle(PseudoId pseudo); diff --git a/WebCore/rendering/style/RenderStyleConstants.h b/WebCore/rendering/style/RenderStyleConstants.h index 01862f6..4abbc1c 100644 --- a/WebCore/rendering/style/RenderStyleConstants.h +++ b/WebCore/rendering/style/RenderStyleConstants.h @@ -66,6 +66,7 @@ enum StyleDifferenceContextSensitiveProperty { // Static pseudo styles. Dynamic ones are produced on the fly. enum PseudoId { + // The order must be NOP ID, public IDs, and then internal IDs. NOPSEUDO, FIRST_LINE, FIRST_LETTER, BEFORE, AFTER, SELECTION, FIRST_LINE_INHERITED, SCROLLBAR, FILE_UPLOAD_BUTTON, INPUT_PLACEHOLDER, SLIDER_THUMB, SEARCH_CANCEL_BUTTON, SEARCH_DECORATION, SEARCH_RESULTS_DECORATION, SEARCH_RESULTS_BUTTON, MEDIA_CONTROLS_PANEL, MEDIA_CONTROLS_PLAY_BUTTON, MEDIA_CONTROLS_MUTE_BUTTON, MEDIA_CONTROLS_TIMELINE, MEDIA_CONTROLS_TIMELINE_CONTAINER, @@ -75,7 +76,9 @@ enum PseudoId { MEDIA_CONTROLS_STATUS_DISPLAY, SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER, INPUT_LIST_BUTTON, INNER_SPIN_BUTTON, OUTER_SPIN_BUTTON, - FIRST_INTERNAL_PSEUDOID = FILE_UPLOAD_BUTTON + FIRST_PUBLIC_PSEUDOID = FIRST_LINE, + FIRST_INTERNAL_PSEUDOID = FILE_UPLOAD_BUTTON, + PUBLIC_PSEUDOID_MASK = ((1 << FIRST_INTERNAL_PSEUDOID) - 1) & ~((1 << FIRST_PUBLIC_PSEUDOID) - 1) }; // These have been defined in the order of their precedence for border-collapsing. Do diff --git a/WebCore/storage/DatabaseAuthorizer.cpp b/WebCore/storage/DatabaseAuthorizer.cpp index d87d4d9..6b6b147 100644 --- a/WebCore/storage/DatabaseAuthorizer.cpp +++ b/WebCore/storage/DatabaseAuthorizer.cpp @@ -263,21 +263,29 @@ int DatabaseAuthorizer::dropTempView(const String&) return (m_readOnly && m_securityEnabled ? SQLAuthDeny : SQLAuthAllow); } -int DatabaseAuthorizer::createVTable(const String&, const String&) +int DatabaseAuthorizer::createVTable(const String& tableName, const String& moduleName) { if (m_readOnly && m_securityEnabled) return SQLAuthDeny; + // fts2 is used in Chromium + if (moduleName != "fts2") + return SQLAuthDeny; + m_lastActionChangedDatabase = true; - return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow; + return denyBasedOnTableName(tableName); } -int DatabaseAuthorizer::dropVTable(const String&, const String&) +int DatabaseAuthorizer::dropVTable(const String& tableName, const String& moduleName) { if (m_readOnly && m_securityEnabled) return SQLAuthDeny; - return m_securityEnabled ? SQLAuthDeny : SQLAuthAllow; + // fts2 is used in Chromium + if (moduleName != "fts2") + return SQLAuthDeny; + + return denyBasedOnTableName(tableName); } int DatabaseAuthorizer::allowDelete(const String& tableName) diff --git a/WebCore/storage/OriginUsageRecord.cpp b/WebCore/storage/OriginUsageRecord.cpp index 684df53..8128a1b 100644 --- a/WebCore/storage/OriginUsageRecord.cpp +++ b/WebCore/storage/OriginUsageRecord.cpp @@ -42,8 +42,8 @@ OriginUsageRecord::OriginUsageRecord() void OriginUsageRecord::addDatabase(const String& identifier, const String& fullPath) { ASSERT(!m_databaseMap.contains(identifier)); - ASSERT_ARG(identifier, identifier.impl()->refCount() == 1); - ASSERT_ARG(fullPath, fullPath.impl()->refCount() == 1); + ASSERT_ARG(identifier, identifier.impl()->hasOneRef()); + ASSERT_ARG(fullPath, fullPath.impl()->hasOneRef()); m_databaseMap.set(identifier, DatabaseEntry(fullPath)); m_unknownSet.add(identifier); @@ -63,7 +63,7 @@ void OriginUsageRecord::removeDatabase(const String& identifier) void OriginUsageRecord::markDatabase(const String& identifier) { ASSERT(m_databaseMap.contains(identifier)); - ASSERT_ARG(identifier, identifier.impl()->refCount() == 1); + ASSERT_ARG(identifier, identifier.impl()->hasOneRef()); m_unknownSet.add(identifier); m_cachedDiskUsageIsValid = false; diff --git a/WebCore/svg/SVGForeignObjectElement.cpp b/WebCore/svg/SVGForeignObjectElement.cpp index e9118ef..d28e2a4 100644 --- a/WebCore/svg/SVGForeignObjectElement.cpp +++ b/WebCore/svg/SVGForeignObjectElement.cpp @@ -72,82 +72,21 @@ void SVGForeignObjectElement::parseMappedAttribute(MappedAttribute* attr) } } -// TODO: Move this function in some SVG*Element base class, as SVGSVGElement / SVGImageElement will need the same logic! - -// This function mimics addCSSProperty and StyledElement::attributeChanged. -// In HTML code, you'd always call addCSSProperty from your derived parseMappedAttribute() -// function - though in SVG code we need to move this logic into svgAttributeChanged, in -// order to support SVG DOM changes (which don't use the parseMappedAttribute/attributeChanged). -// If we'd ignore SVG DOM, we could use _exactly_ the same logic as HTML. -static inline void addCSSPropertyAndNotifyAttributeMap(StyledElement* element, const QualifiedName& name, int cssProperty, const String& value) -{ - ASSERT(element); - - if (!element) - return; - - NamedMappedAttrMap* attrs = element->mappedAttributes(); - ASSERT(attrs); - - if (!attrs) - return; - - Attribute* attr = attrs->getAttributeItem(name); - if (!attr || !attr->isMappedAttribute()) - return; - - MappedAttribute* mappedAttr = static_cast<MappedAttribute*>(attr); - - // This logic is only meant to be used for entries that have to be parsed and are mapped to eNone. Assert that. - MappedAttributeEntry entry; - bool needToParse = element->mapToEntry(mappedAttr->name(), entry); - - ASSERT(needToParse); - ASSERT(entry == eNone); - - if (!needToParse || entry != eNone) - return; - - if (mappedAttr->decl()) { - mappedAttr->setDecl(0); - attrs->declRemoved(); - } - - element->setNeedsStyleRecalc(); - element->addCSSProperty(mappedAttr, cssProperty, value); - - if (CSSMappedAttributeDeclaration* decl = mappedAttr->decl()) { - // Add the decl to the table in the appropriate spot. - element->setMappedAttributeDecl(entry, mappedAttr, decl); - - decl->setMappedState(entry, mappedAttr->name(), mappedAttr->value()); - decl->setParent(0); - decl->setNode(0); - - attrs->declAdded(); - } -} - void SVGForeignObjectElement::svgAttributeChanged(const QualifiedName& attrName) { SVGStyledTransformableElement::svgAttributeChanged(attrName); - if (attrName == SVGNames::widthAttr) { - addCSSPropertyAndNotifyAttributeMap(this, attrName, CSSPropertyWidth, width().valueAsString()); - return; - } else if (attrName == SVGNames::heightAttr) { - addCSSPropertyAndNotifyAttributeMap(this, attrName, CSSPropertyHeight, height().valueAsString()); - return; - } - if (!renderer()) return; - if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr || - SVGTests::isKnownAttribute(attrName) || - SVGLangSpace::isKnownAttribute(attrName) || - SVGExternalResourcesRequired::isKnownAttribute(attrName) || - SVGStyledTransformableElement::isKnownAttribute(attrName)) + if (attrName == SVGNames::xAttr + || attrName == SVGNames::yAttr + || attrName == SVGNames::widthAttr + || attrName == SVGNames::heightAttr + || SVGTests::isKnownAttribute(attrName) + || SVGLangSpace::isKnownAttribute(attrName) + || SVGExternalResourcesRequired::isKnownAttribute(attrName) + || SVGStyledTransformableElement::isKnownAttribute(attrName)) renderer()->setNeedsLayout(true); } @@ -190,6 +129,6 @@ bool SVGForeignObjectElement::childShouldCreateRenderer(Node* child) const return StyledElement::childShouldCreateRenderer(child); } -} // namespace WebCore +} -#endif // ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT) +#endif diff --git a/WebCore/svg/SVGLength.cpp b/WebCore/svg/SVGLength.cpp index 2884507..e342acf 100644 --- a/WebCore/svg/SVGLength.cpp +++ b/WebCore/svg/SVGLength.cpp @@ -280,15 +280,16 @@ float SVGLength::PercentageOfViewport(float value, const SVGElement* context, SV float width = 0.0f, height = 0.0f; SVGElement* viewportElement = context->viewportElement(); + // PercentageOfViewport() is used to resolve all relative-positioned values within a SVG document (fragment) Document* doc = context->document(); if (doc->documentElement() == context) { - // We have to ask the canvas for the full "canvas size"... - RenderView* view = toRenderView(doc->renderer()); - if (view && view->frameView()) { - width = view->frameView()->visibleWidth(); // TODO: recheck! - height = view->frameView()->visibleHeight(); // TODO: recheck! + // Resolve value against outermost <svg> element + if (RenderView* view = toRenderView(doc->renderer())) { + width = view->viewWidth(); + height = view->viewHeight(); } } else if (viewportElement && viewportElement->isSVG()) { + // Resolve value against nearest viewport element (common case: inner <svg> elements) const SVGSVGElement* svg = static_cast<const SVGSVGElement*>(viewportElement); if (svg->hasAttribute(SVGNames::viewBoxAttr)) { width = svg->viewBox().width(); @@ -298,6 +299,7 @@ float SVGLength::PercentageOfViewport(float value, const SVGElement* context, SV height = svg->height().value(svg); } } else if (context->parent() && !context->parent()->isSVGElement()) { + // Resolve value against enclosing non-SVG RenderBox if (RenderObject* renderer = context->renderer()) { if (renderer->isBox()) { RenderBox* box = toRenderBox(renderer); @@ -319,6 +321,4 @@ float SVGLength::PercentageOfViewport(float value, const SVGElement* context, SV } -#endif // ENABLE(SVG) - -// vim:ts=4:noet +#endif diff --git a/WebCore/svg/SVGMaskElement.cpp b/WebCore/svg/SVGMaskElement.cpp index 86d1062..67b0a98 100644 --- a/WebCore/svg/SVGMaskElement.cpp +++ b/WebCore/svg/SVGMaskElement.cpp @@ -3,6 +3,7 @@ 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> 2005 Alexander Kellett <lypanov@kde.org> 2009 Dirk Schulze <krit@webkit.org> + Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -25,23 +26,13 @@ #if ENABLE(SVG) #include "SVGMaskElement.h" -#include "CanvasPixelArray.h" #include "CSSStyleSelector.h" -#include "GraphicsContext.h" -#include "Image.h" -#include "ImageBuffer.h" -#include "ImageData.h" #include "MappedAttribute.h" -#include "RenderObject.h" -#include "RenderSVGContainer.h" +#include "RenderSVGResourceMasker.h" #include "SVGLength.h" #include "SVGNames.h" #include "SVGRenderSupport.h" #include "SVGUnitTypes.h" -#include <math.h> -#include <wtf/MathExtras.h> -#include <wtf/OwnPtr.h> -#include <wtf/Vector.h> using namespace std; @@ -167,122 +158,9 @@ FloatRect SVGMaskElement::maskBoundingBox(const FloatRect& objectBoundingBox) co return maskBBox; } -PassOwnPtr<ImageBuffer> SVGMaskElement::drawMaskerContent(const RenderObject* object, FloatRect& maskDestRect, bool& emptyMask) const -{ - FloatRect objectBoundingBox = object->objectBoundingBox(); - - // Mask rect clipped with clippingBoundingBox and filterBoundingBox as long as they are present. - maskDestRect = object->repaintRectInLocalCoordinates(); - if (maskDestRect.isEmpty()) { - emptyMask = true; - return 0; - } - - // Calculate the smallest rect for the mask ImageBuffer. - FloatRect repaintRect; - Vector<RenderObject*> rendererList; - for (Node* node = firstChild(); node; node = node->nextSibling()) { - if (!node->isSVGElement() || !static_cast<SVGElement*>(node)->isStyled() || !node->renderer()) - continue; - - rendererList.append(node->renderer()); - repaintRect.unite(node->renderer()->localToParentTransform().mapRect(node->renderer()->repaintRectInLocalCoordinates())); - } - - AffineTransform contextTransform; - // We need to scale repaintRect for objectBoundingBox to get the drawing area. - if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { - contextTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); - FloatPoint contextAdjustment = repaintRect.location(); - repaintRect = contextTransform.mapRect(repaintRect); - repaintRect.move(objectBoundingBox.x(), objectBoundingBox.y()); - contextTransform.translate(-contextAdjustment.x(), -contextAdjustment.y()); - } - repaintRect.intersect(maskDestRect); - maskDestRect = repaintRect; - IntRect maskImageRect = enclosingIntRect(maskDestRect); - - maskImageRect.setLocation(IntPoint()); - - // Don't create ImageBuffers with image size of 0 - if (!maskImageRect.width() || !maskImageRect.height()) { - emptyMask = true; - return 0; - } - - // FIXME: This changes color space to linearRGB, the default color space - // for masking operations in SVG. We need a switch for the other color-space - // attribute values sRGB, inherit and auto. - OwnPtr<ImageBuffer> maskImage = ImageBuffer::create(maskImageRect.size(), LinearRGB); - if (!maskImage) - return 0; - - GraphicsContext* maskImageContext = maskImage->context(); - ASSERT(maskImageContext); - - maskImageContext->save(); - - if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) - maskImageContext->translate(-maskDestRect.x(), -maskDestRect.y()); - maskImageContext->concatCTM(contextTransform); - - // draw the content into the ImageBuffer - Vector<RenderObject*>::iterator end = rendererList.end(); - for (Vector<RenderObject*>::iterator it = rendererList.begin(); it != end; it++) - renderSubtreeToImage(maskImage.get(), *it); - - - maskImageContext->restore(); - - // create the luminance mask - RefPtr<ImageData> imageData(maskImage->getUnmultipliedImageData(maskImageRect)); - CanvasPixelArray* srcPixelArray(imageData->data()); - - for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset += 4) { - unsigned char a = srcPixelArray->get(pixelOffset + 3); - if (!a) - continue; - unsigned char r = srcPixelArray->get(pixelOffset); - unsigned char g = srcPixelArray->get(pixelOffset + 1); - unsigned char b = srcPixelArray->get(pixelOffset + 2); - - double luma = (r * 0.2125 + g * 0.7154 + b * 0.0721) * ((double)a / 255.0); - srcPixelArray->set(pixelOffset + 3, luma); - } - - maskImage->putUnmultipliedImageData(imageData.get(), maskImageRect, IntPoint()); - - return maskImage.release(); -} - RenderObject* SVGMaskElement::createRenderer(RenderArena* arena, RenderStyle*) { - RenderSVGContainer* maskContainer = new (arena) RenderSVGContainer(this); - maskContainer->setDrawsContents(false); - return maskContainer; -} - -SVGResource* SVGMaskElement::canvasResource(const RenderObject* object) -{ - ASSERT(object); - - if (m_masker.contains(object)) - return m_masker.get(object).get(); - - RefPtr<SVGResourceMasker> masker = SVGResourceMasker::create(this); - SVGResourceMasker* maskerPtr = masker.get(); - m_masker.set(object, masker.release()); - - return maskerPtr; -} - -void SVGMaskElement::invalidateCanvasResources() -{ - // Don't call through to the base class since the base class will just - // invalidate one item in the HashMap. - HashMap<const RenderObject*, RefPtr<SVGResourceMasker> >::const_iterator end = m_masker.end(); - for (HashMap<const RenderObject*, RefPtr<SVGResourceMasker> >::const_iterator it = m_masker.begin(); it != end; ++it) - it->second->invalidate(); + return new (arena) RenderSVGResourceMasker(this); } } diff --git a/WebCore/svg/SVGMaskElement.h b/WebCore/svg/SVGMaskElement.h index 005fa4f..7730e37 100644 --- a/WebCore/svg/SVGMaskElement.h +++ b/WebCore/svg/SVGMaskElement.h @@ -22,19 +22,15 @@ #if ENABLE(SVG) #include "RenderObject.h" -#include "SVGResourceMasker.h" #include "SVGExternalResourcesRequired.h" #include "SVGLangSpace.h" #include "SVGStyledLocatableElement.h" #include "SVGTests.h" #include "SVGURIReference.h" -#include <wtf/HashMap.h> -#include <wtf/PassOwnPtr.h> namespace WebCore { class SVGLength; - class SVGResourceMasker; class SVGMaskElement : public SVGStyledLocatableElement, public SVGURIReference, @@ -53,9 +49,6 @@ namespace WebCore { virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); - virtual SVGResource* canvasResource(const RenderObject*); - - PassOwnPtr<ImageBuffer> drawMaskerContent(const RenderObject*, FloatRect& maskRect, bool& emptyMask) const; private: DECLARE_ANIMATED_PROPERTY(SVGMaskElement, SVGNames::maskUnitsAttr, int, MaskUnits, maskUnits) @@ -70,13 +63,9 @@ namespace WebCore { // SVGExternalResourcesRequired DECLARE_ANIMATED_PROPERTY(SVGMaskElement, SVGNames::externalResourcesRequiredAttr, bool, ExternalResourcesRequired, externalResourcesRequired) - - virtual void invalidateCanvasResources(); - - HashMap<const RenderObject*, RefPtr<SVGResourceMasker> > m_masker; }; -} // namespace WebCore +} -#endif // ENABLE(SVG) +#endif #endif diff --git a/WebCore/svg/SVGSVGElement.cpp b/WebCore/svg/SVGSVGElement.cpp index cfe1615..ff24c4f 100644 --- a/WebCore/svg/SVGSVGElement.cpp +++ b/WebCore/svg/SVGSVGElement.cpp @@ -187,16 +187,19 @@ SVGViewSpec* SVGSVGElement::currentView() const float SVGSVGElement::currentScale() const { - if (document() && parentNode() == document()) - return document()->frame() ? document()->frame()->zoomFactor() : 1; + // Only the page zoom factor is relevant for SVG + if (Frame* frame = document()->frame()) + return frame->pageZoomFactor(); return m_scale; } void SVGSVGElement::setCurrentScale(float scale) { - if (document() && parentNode() == document()) { - if (document()->frame()) - document()->frame()->setZoomFactor(scale, true); + if (Frame* frame = document()->frame()) { + // Calling setCurrentScale() on the outermost <svg> element in a standalone SVG document + // is allowed to change the page zoom factor, influencing the document size, scrollbars etc. + if (parentNode() == document()) + frame->setZoomFactor(scale, false); return; } diff --git a/WebCore/svg/SVGStyledElement.cpp b/WebCore/svg/SVGStyledElement.cpp index be1ba9c..ff94c7d 100644 --- a/WebCore/svg/SVGStyledElement.cpp +++ b/WebCore/svg/SVGStyledElement.cpp @@ -32,6 +32,8 @@ #include "MappedAttribute.h" #include "PlatformString.h" #include "RenderObject.h" +#include "RenderSVGResource.h" +#include "RenderSVGResourceMasker.h" #include "SVGElement.h" #include "SVGElementInstance.h" #include "SVGElementRareData.h" @@ -39,7 +41,6 @@ #include "SVGRenderStyle.h" #include "SVGResourceClipper.h" #include "SVGResourceFilter.h" -#include "SVGResourceMasker.h" #include "SVGSVGElement.h" #include <wtf/Assertions.h> @@ -234,9 +235,8 @@ void SVGStyledElement::invalidateResources() filter->invalidate(); #endif - SVGResourceMasker* masker = getMaskerById(document, svgStyle->maskElement(), object); - if (masker) - masker->invalidate(); + if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(document, svgStyle->maskElement())) + masker->invalidateClient(object); SVGResourceClipper* clipper = getClipperById(document, svgStyle->clipPath(), object); if (clipper) @@ -260,7 +260,15 @@ void SVGStyledElement::invalidateResourcesInAncestorChain() const void SVGStyledElement::invalidateCanvasResources() { - if (SVGResource* resource = canvasResource(renderer())) + RenderObject* object = renderer(); + if (!object) + return; + + if (object->isSVGResource()) + object->toRenderSVGResource()->invalidateClients(); + + // The following lines will be removed soon, once all resources are handled by renderers. + if (SVGResource* resource = canvasResource(object)) resource->invalidate(); } diff --git a/WebCore/svg/SVGStyledElement.h b/WebCore/svg/SVGStyledElement.h index aec3e75..9645db4 100644 --- a/WebCore/svg/SVGStyledElement.h +++ b/WebCore/svg/SVGStyledElement.h @@ -71,7 +71,7 @@ namespace WebCore { protected: static int cssPropertyIdForSVGAttributeName(const QualifiedName&); - virtual void invalidateCanvasResources(); + void invalidateCanvasResources(); private: DECLARE_ANIMATED_PROPERTY(SVGStyledElement, HTMLNames::classAttr, String, ClassName, className) diff --git a/WebCore/svg/SVGUnitTypes.h b/WebCore/svg/SVGUnitTypes.h index b639f29..86d49b4 100644 --- a/WebCore/svg/SVGUnitTypes.h +++ b/WebCore/svg/SVGUnitTypes.h @@ -38,9 +38,9 @@ private: SVGUnitTypes() { } }; -} // namespace WebCore +static inline SVGUnitTypes::SVGUnitType toUnitType(int type) { return static_cast<SVGUnitTypes::SVGUnitType>(type); } -#endif // ENABLE(SVG) -#endif // SVGUnitTypes_h +} -// vim:ts=4:noet +#endif +#endif diff --git a/WebCore/svg/graphics/SVGImage.cpp b/WebCore/svg/graphics/SVGImage.cpp index 348df4f..febfce8 100644 --- a/WebCore/svg/graphics/SVGImage.cpp +++ b/WebCore/svg/graphics/SVGImage.cpp @@ -215,7 +215,7 @@ NativeImagePtr SVGImage::nativeImageForCurrentFrame() m_frameCache = ImageBuffer::create(size()); if (!m_frameCache) // failed to allocate image return 0; - renderSubtreeToImage(m_frameCache.get(), m_page->mainFrame()->contentRenderer()); + draw(m_frameCache->context(), rect(), rect(), DeviceColorSpace, CompositeSourceOver); } return m_frameCache->image()->nativeImageForCurrentFrame(); } diff --git a/WebCore/svg/graphics/SVGResource.h b/WebCore/svg/graphics/SVGResource.h index 8f303b5..b231b89 100644 --- a/WebCore/svg/graphics/SVGResource.h +++ b/WebCore/svg/graphics/SVGResource.h @@ -45,10 +45,9 @@ namespace WebCore { enum SVGResourceType { // Painting mode ClipperResourceType = 0, - MarkerResourceType, ImageResourceType, FilterResourceType, - MaskerResourceType, + MarkerResourceType, PaintServerResourceType, // For resource tracking we need to know how many types of resource there are @@ -78,7 +77,6 @@ namespace WebCore { bool isFilter() const { return resourceType() == FilterResourceType; } bool isClipper() const { return resourceType() == ClipperResourceType; } bool isMarker() const { return resourceType() == MarkerResourceType; } - bool isMasker() const { return resourceType() == MaskerResourceType; } virtual TextStream& externalRepresentation(TextStream&) const; diff --git a/WebCore/svg/graphics/SVGResourceMasker.cpp b/WebCore/svg/graphics/SVGResourceMasker.cpp deleted file mode 100644 index 18bc71a..0000000 --- a/WebCore/svg/graphics/SVGResourceMasker.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> - * 2009 Dirk Schulze <krit@webkit.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(SVG) -#include "SVGResourceMasker.h" - -#include "CanvasPixelArray.h" -#include "Image.h" -#include "ImageBuffer.h" -#include "ImageData.h" -#include "GraphicsContext.h" -#include "RenderObject.h" -#include "SVGMaskElement.h" -#include "SVGRenderSupport.h" -#include "SVGRenderStyle.h" -#include "TextStream.h" - -using namespace std; - -namespace WebCore { - -SVGResourceMasker::SVGResourceMasker(const SVGMaskElement* ownerElement) - : SVGResource() - , m_ownerElement(ownerElement) - , m_emptyMask(false) -{ -} - -SVGResourceMasker::~SVGResourceMasker() -{ -} - -void SVGResourceMasker::invalidate() -{ - SVGResource::invalidate(); - m_mask.clear(); - m_emptyMask = false; -} - -FloatRect SVGResourceMasker::maskerBoundingBox(const FloatRect& objectBoundingBox) const -{ - return m_ownerElement->maskBoundingBox(objectBoundingBox); -} - -bool SVGResourceMasker::applyMask(GraphicsContext* context, const RenderObject* object) -{ - if (!m_mask && !m_emptyMask) - m_mask = m_ownerElement->drawMaskerContent(object, m_maskRect, m_emptyMask); - - if (!m_mask) - return false; - - context->clipToImageBuffer(m_maskRect, m_mask.get()); - return true; -} - -TextStream& SVGResourceMasker::externalRepresentation(TextStream& ts) const -{ - ts << "[type=MASKER]"; - return ts; -} - -SVGResourceMasker* getMaskerById(Document* document, const AtomicString& id, const RenderObject* object) -{ - SVGResource* resource = getResourceById(document, id, object); - if (resource && resource->isMasker()) - return static_cast<SVGResourceMasker*>(resource); - - return 0; -} - -} // namespace WebCore - -#endif diff --git a/WebCore/svg/graphics/SVGResourceMasker.h b/WebCore/svg/graphics/SVGResourceMasker.h deleted file mode 100644 index 27364c2..0000000 --- a/WebCore/svg/graphics/SVGResourceMasker.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SVGResourceMasker_h -#define SVGResourceMasker_h - -#if ENABLE(SVG) - -#include "GraphicsContext.h" -#include "RenderObject.h" -#include "SVGMaskElement.h" -#include "SVGResource.h" - -#include <memory> - -#include <wtf/OwnPtr.h> -#include <wtf/PassRefPtr.h> - -namespace WebCore { - - class FloatRect; - class ImageBuffer; - class SVGMaskElement; - - class SVGResourceMasker : public SVGResource { - public: - static PassRefPtr<SVGResourceMasker> create(const SVGMaskElement* ownerElement) { return adoptRef(new SVGResourceMasker(ownerElement)); } - virtual ~SVGResourceMasker(); - - virtual void invalidate(); - - virtual SVGResourceType resourceType() const { return MaskerResourceType; } - virtual TextStream& externalRepresentation(TextStream&) const; - - FloatRect maskerBoundingBox(const FloatRect&) const; - bool applyMask(GraphicsContext*, const RenderObject*); - - private: - SVGResourceMasker(const SVGMaskElement*); - - const SVGMaskElement* m_ownerElement; - - OwnPtr<ImageBuffer> m_mask; - FloatRect m_maskRect; - bool m_emptyMask; - }; - - SVGResourceMasker* getMaskerById(Document*, const AtomicString&, const RenderObject* object); - -} // namespace WebCore - -#endif - -#endif // SVGResourceMasker_h diff --git a/WebCore/websockets/WebSocket.cpp b/WebCore/websockets/WebSocket.cpp index 5a64b71..cd5528b 100644 --- a/WebCore/websockets/WebSocket.cpp +++ b/WebCore/websockets/WebSocket.cpp @@ -164,7 +164,7 @@ bool WebSocket::send(const String& message, ExceptionCode& ec) } // No exception is raised if the connection was once established but has subsequently been closed. if (m_state == CLOSED) { - m_bufferedAmountAfterClose += message.utf8().length() + 2; // 2 for framing + m_bufferedAmountAfterClose += message.utf8().length() + 2; // 2 for frameing return false; } // FIXME: check message is valid utf8. diff --git a/WebCore/websockets/WebSocketChannel.cpp b/WebCore/websockets/WebSocketChannel.cpp index 2ab133c..7b87bf3 100644 --- a/WebCore/websockets/WebSocketChannel.cpp +++ b/WebCore/websockets/WebSocketChannel.cpp @@ -164,6 +164,8 @@ void WebSocketChannel::didReceiveData(SocketStreamHandle* handle, const char* da // FIXME: handle set-cookie2. LOG(Network, "WebSocketChannel %p connected", this); m_client->didConnect(); + if (!m_client) + return; break; default: LOG(Network, "WebSocketChannel %p connection failed", this); @@ -209,6 +211,8 @@ void WebSocketChannel::didReceiveData(SocketStreamHandle* handle, const char* da if (p < end && *p == '\xff') { if (frameByte == 0x00) m_client->didReceiveMessage(String::fromUTF8(msgStart, p - msgStart)); + if (!m_client) + return; ++p; nextFrame = p; } diff --git a/WebCore/workers/WorkerThread.cpp b/WebCore/workers/WorkerThread.cpp index fbeb95b..4e3ffa1 100644 --- a/WebCore/workers/WorkerThread.cpp +++ b/WebCore/workers/WorkerThread.cpp @@ -189,6 +189,10 @@ public: workerContext->stopDatabases(&cleanupSync); workerContext->stopActiveDOMObjects(); + + // Event listeners would keep DOMWrapperWorld objects alive for too long. Also, they have references to JS objects, + // which become dangling once Heap is destroyed. + workerContext->removeAllEventListeners(); workerContext->clearScript(); // We wait for the database thread to clean up all its stuff so that we |