[iOS] Upstream WebCore/rendering changes
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 6 Dec 2013 19:59:38 +0000 (19:59 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 6 Dec 2013 19:59:38 +0000 (19:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=125239

Reviewed by Simon Fraser.

* WebCore.xcodeproj/project.pbxproj:
* rendering/InlineBox.cpp:
(WebCore::InlineBox::previousOnLineExists): Added.
* rendering/InlineBox.h:
* rendering/InlineTextBox.cpp:
(WebCore::InlineTextBox::paintCompositionBackground): Modified to query RenderStyle
on iOS for the composition fill color. Added FIXME to make this platform-independent.
(WebCore::InlineTextBox::paintDecoration): Added iOS-specific decoration code.
(WebCore::lineStyleForMarkerType):
(WebCore::InlineTextBox::paintDocumentMarkers): Added iOS-specific code. Also, added
FIXME to make this code platform-independent.
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::paint): Ditto.
(WebCore::positionForPointRespectingEditingBoundaries): Added iOS-specific code.
* rendering/RenderBlock.h: Changed access control of logical{Left, Right}SelectionOffset()
from private to protected so that these methods can be used from RenderImage::collectSelectionRects().
* rendering/RenderBox.cpp:
(WebCore::RenderBox::borderRadii): Added.
(WebCore::RenderBox::paintBoxDecorations): Added iOS-specific workaround. See <rdar://problem/6209763>
for more details.
(WebCore::RenderBox::computeRectForRepaint): Added iOS-specific code.
(WebCore::customContainingBlockWidth): Added; guarded by PLATFORM(IOS).
(WebCore::customContainingBlockHeight): Added; guarded by PLATFORM(IOS).
(WebCore::customContainingBlockLogicalWidth): Added; guarded by PLATFORM(IOS).
(WebCore::customContainingBlockLogicalHeight): Added; guarded by PLATFORM(IOS).
(WebCore::customContainingBlockAvailableLogicalHeight): Added; guarded by PLATFORM(IOS).
(WebCore::RenderBox::availableLogicalHeightUsing): Added iOS-specific code; calls customContainingBlockAvailableLogicalHeight().
(WebCore::RenderBox::containingBlockLogicalWidthForPositioned): Added iOS-specific code; calls customContainingBlockLogicalWidth().
(WebCore::RenderBox::containingBlockLogicalHeightForPositioned): Added iOS-specific code; calls customContainingBlockLogicalHeight().
(WebCore::RenderBox::layoutOverflowRectForPropagation): Added iOS-specific code.
* rendering/RenderBox.h:
* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::stickyPositionOffset): Use FrameView::customFixedPositionLayoutRect()
instead of FrameView::viewportConstrainedVisibleContentRect().
* rendering/RenderButton.cpp:
(WebCore::RenderButton::layout): Added; iOS-specific. Includes FIXME comment.
See <rdar://problem/7675493> for more details.
* rendering/RenderElement.cpp:
(WebCore::RenderElement::styleWillChange): Added iOS-specific code.
(WebCore::RenderElement::styleDidChange): Modified to only call areCursorsEqual() and
EventHandler::scheduleCursorUpdate() on a non-iOS port.
* rendering/RenderEmbeddedObject.cpp:
(WebCore::RenderEmbeddedObject::allowsAcceleratedCompositing): Added iOS-specific code.
(WebCore::RenderEmbeddedObject::setPluginUnavailabilityReason): This method has an empty implementation for iOS.
(WebCore::RenderEmbeddedObject::setPluginUnavailabilityReasonWithDescription): Ditto.
* rendering/RenderFileUploadControl.cpp:
(WebCore::nodeHeight):
(WebCore::RenderFileUploadControl::maxFilenameWidth): Added iOS-specific code.
(WebCore::RenderFileUploadControl::paintObject): Ditto.
(WebCore::RenderFileUploadControl::fileTextValue): Ditto.
* rendering/RenderFrameSet.cpp:
(WebCore::RenderFrameSet::positionFrames): Ditto; Also added FIXME comment as this code may not
be specific to iOS.
* rendering/RenderIFrame.h: Added iOS-specific workaround to RenderObject::renderName(). Added
FIXME comment to determine whether this workaround is still applicable.
* rendering/RenderImage.cpp:
(WebCore::RenderImage::collectSelectionRects): Added; guarded by PLATFORM(IOS).
(WebCore::RenderImage::paintAreaElementFocusRing): This method has an empty implementation for iOS.
* rendering/RenderImage.h:
* rendering/RenderInline.cpp:
(WebCore::RenderInline::absoluteQuadsForSelection): Added; guarded by PLATFORM(IOS).
* rendering/RenderInline.h:
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::RenderLayer): Added iOS-specific member initialization.
(WebCore::RenderLayer::~RenderLayer): Added iOS-specific code.
(WebCore::RenderLayer::willBeDestroyed): Added; iOS-specific.
(WebCore::RenderLayer::hasAcceleratedTouchScrolling): Ditto.
(WebCore::RenderLayer::handleTouchEvent): Ditto.
(WebCore::RenderLayer::registerAsTouchEventListenerForScrolling): Ditto.
(WebCore::RenderLayer::unregisterAsTouchEventListenerForScrolling): Ditto.
(WebCore::RenderLayer::updateNeedsCompositedScrolling): Added iOS-specific code as we use UIKit
to composite our scroll bars.
(WebCore::RenderLayer::scrollTo): Added iOS-specific code.
(WebCore::RenderLayer::scrollRectToVisible): Ditto.
(WebCore::RenderLayer::styleChanged): Modified to make use of the passed StyleDifference on iOS.
(WebCore::RenderLayer::visibleContentRect): Added; iOS-specific.
(WebCore::RenderLayer::didStartScroll): Ditto.
(WebCore::RenderLayer::didEndScroll): Ditto.
(WebCore::RenderLayer::didUpdateScroll): Ditto.
(WebCore::RenderLayer::invalidateScrollbarRect): Added iOS-specific code.
(WebCore::RenderLayer::invalidateScrollCornerRect): Ditto.
(WebCore::RenderLayer::verticalScrollbarWidth): Ditto.
(WebCore::RenderLayer::horizontalScrollbarHeight): Ditto.
(WebCore::RenderLayer::updateScrollableAreaSet): Ditto.
(WebCore::RenderLayer::updateScrollInfoAfterLayout): Add iOS-specific workaround with FIXME. See
<rdar://problem/15579797> for more details.
(WebCore::RenderLayer::paintOverflowControls): Added iOS-specific code.
(WebCore::RenderLayer::calculateClipRects): Ditto.
* rendering/RenderLayer.h:
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::createPrimaryGraphicsLayer): Modified to not apply page scale on iOS
as we apply a page scale at a different time in the code.
(WebCore::RenderLayerBacking::layerWillBeDestroyed): Added; guarded by PLATFORM(IOS).
(WebCore::layerOrAncestorIsTransformedOrScrolling): Added iOS-specific variant with FIXME comment.
(WebCore::RenderLayerBacking::shouldClipCompositedBounds): Added iOS-specific code.
(WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): Ditto.
(WebCore::RenderLayerBacking::updateGraphicsLayerGeometry): Ditto.
(WebCore::RenderLayerBacking::registerScrollingLayers): Ditto.
(WebCore::RenderLayerBacking::updateScrollingLayers): Ditto.
(WebCore::RenderLayerBacking::containsPaintedContent): Call RenderLayer::hasBoxDecorationsOrBackground()
when building on iOS Simulator.
(WebCore::RenderLayerBacking::parentForSublayers): Added iOS-specific code and FIXME comment.
(WebCore::RenderLayerBacking::paintsIntoWindow): Opt-into coordinated graphics code path.
(WebCore::RenderLayerBacking::setContentsNeedDisplayInRect): Added iOS-specific code.
(WebCore::RenderLayerBacking::paintIntoLayer): Compile-out ASSERT_NOT_REACHED for iOS and added FIXME comment.
* rendering/RenderLayerBacking.h:
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::scheduleLayerFlush): Added iOS-specific code.
(WebCore::RenderLayerCompositor::chromeClient): Added; guarded by PLATFORM(IOS).
(WebCore::RenderLayerCompositor::flushPendingLayerChanges): Added iOS-specific code.
(WebCore::scrollbarHasDisplayNone): Added; iOS-specific.
(WebCore::updateScrollingLayerWithClient): Ditto.
(WebCore::RenderLayerCompositor::updateCustomLayersAfterFlush): Ditto.
(WebCore::RenderLayerCompositor::didFlushChangesForLayer): Added iOS-specific code.
(WebCore::RenderLayerCompositor::didChangeVisibleRect): Ditto.
(WebCore::RenderLayerCompositor::addToOverlapMap): Don't apply page scale factor on iOS. We apply
the page scale factor at a different time in the code. Also, added FIXME comment.
(WebCore::RenderLayerCompositor::computeCompositingRequirements): Added iOS-specific workaround.
See <rdar://problem/8348337> for more details.
(WebCore::RenderLayerCompositor::setIsInWindow): Use non-Mac code path for iOS.
(WebCore::RenderLayerCompositor::allowsIndependentlyCompositedFrames): Added iOS-specific code.
(WebCore::RenderLayerCompositor::requiresCompositingLayer): Ditto.
(WebCore::RenderLayerCompositor::requiresOwnBackingStore): Ditto.
(WebCore::RenderLayerCompositor::reasonsForCompositing): Ditto.
(WebCore::RenderLayerCompositor::requiresCompositingForAnimation): Opt-into calling
AnimationController::isRunningAnimationOnRenderer() on iOS.
(WebCore::RenderLayerCompositor::requiresCompositingForScrolling): Added; guarded by PLATFORM(IOS).
(WebCore::isStickyInAcceleratedScrollingLayerOrViewport): Added iOS-specific code.
(WebCore::isViewportConstrainedFixedOrStickyLayer): Ditto.
(WebCore::RenderLayerCompositor::requiresCompositingForPosition): Use FrameView::customFixedPositionLayoutRect()
instead of FrameView::viewportConstrainedVisibleContentRect().
(WebCore::RenderLayerCompositor::contentsScaleMultiplierForNewTiles): Ditto.
(WebCore::RenderLayerCompositor::ensureRootLayer): Ditto.
(WebCore::RenderLayerCompositor::computeFixedViewportConstraints): Use FrameView::customFixedPositionLayoutRect()
instead of FrameView::viewportConstrainedVisibleContentRect().
(WebCore::RenderLayerCompositor::computeStickyViewportConstraints): Ditto.
(WebCore::RenderLayerCompositor::registerOrUpdateViewportConstrainedLayer): This method has an empty implementation for iOS
as we batch update viewport-constrained layers in the iOS-specific method, RenderLayerCompositor::updateCustomLayersAfterFlush().
(WebCore::RenderLayerCompositor::unregisterViewportConstrainedLayer): Ditto.
(WebCore::RenderLayerCompositor::registerAllViewportConstrainedLayers): Added; guarded by PLATFORM(IOS).
(WebCore::RenderLayerCompositor::unregisterAllViewportConstrainedLayers): Ditto.
(WebCore::RenderLayerCompositor::registerAllScrollingLayers): Ditto.
(WebCore::RenderLayerCompositor::unregisterAllScrollingLayers): Ditto.
(WebCore::RenderLayerCompositor::scrollingLayerAddedOrUpdated): Ditto.
(WebCore::RenderLayerCompositor::scrollingLayerRemoved): Ditto.
(WebCore::RenderLayerCompositor::startInitialLayerFlushTimerIfNeeded): Ditto.
* rendering/RenderLayerCompositor.h:
* rendering/RenderLayerFilterInfo.h: Added iOS-specific Clang workaround to ignore
an unused private field.
* rendering/RenderMenuList.cpp:
(WebCore::selectedOptionCount): Added; guarded by PLATFORM(IOS).
(WebCore::RenderMenuList::RenderMenuList): On iOS we don't make use of RenderMenuList::m_popupIsVisible.
(WebCore::RenderMenuList::~RenderMenuList): On iOS we don't make use of RenderMenuList::m_popup.
(WebCore::RenderMenuList::adjustInnerStyle): Add iOS-specific code.
(RenderMenuList::updateFromElement): On iOS we don't make use of RenderMenuList::m_popup.
(RenderMenuList::setTextFromOption): Add iOS-specific code.
(RenderMenuList::showPopup): Define RenderMenuList::showPopup() to ASSERT_NOT_REACHED() on iOS as
we don't make use of RenderMenuList::m_popup.
(RenderMenuList::hidePopup): This method has an empty implementation for iOS as we don't make use
of RenderMenuList::m_popup.
(RenderMenuList::popupDidHide): This method has an empty implementation for iOS as we don't make use
of RenderMenuList::m_popupIsVisible.
* rendering/RenderMenuList.h:
* rendering/RenderObject.cpp:
(WebCore::RenderObject::columnNumberForOffset): Added; guarded by PLATFORM(IOS). Also, added a FIXME comment to
make this function return an unsigned integer instead of a signed integer.
(WebCore::RenderObject::collectSelectionRects): Added; guarded by PLATFORM(IOS).
(WebCore::RenderObject::destroy): Added iOS-specific code.
(WebCore::RenderObject::innerLineHeight): Added.
(WebCore::RenderObject::willRenderImage): Added iOS-specific code.
* rendering/RenderObject.h: Change the access control of RenderObject::drawLineForBoxSide() from protected to
public so that it can be used from RenderThemeIOS::adjustMenuListButtonStyle().
(WebCore::RenderObject::absoluteQuadsForSelection):
* rendering/RenderScrollbar.h: Change the access control of RenderScrollbar::getScrollbarPseudoStyle() from
private to public so that it can be used from the iOS-specific static function, scrollbarHasDisplayNone,
defined in RenderLayerCompositor.cpp.
* rendering/RenderSearchField.cpp:
(WebCore::RenderSearchField::itemText): Added iOS-specific code.
* rendering/RenderText.cpp:
(WebCore::RenderText::collectSelectionRects): Added; guarded by PLATFORM(IOS).
(WebCore::RenderText::setTextInternal): Added iOS-specific code.
* rendering/RenderText.h:
* rendering/RenderTextControl.cpp:
(WebCore::RenderTextControl::adjustInnerTextStyle): Ditto.
(WebCore::RenderTextControl::canScroll): Added; guarded by PLATFORM(IOS).
(WebCore::RenderTextControl::innerLineHeight): Ditto.
* rendering/RenderTextControl.h:
* rendering/RenderTextControlMultiLine.cpp:
(WebCore::RenderTextControlMultiLine::getAvgCharWidth): Compile-out code when building for iOS.
(WebCore::RenderTextControlMultiLine::createInnerTextStyle): Added iOS-specific code.
* rendering/RenderTextControlSingleLine.cpp:
(WebCore::RenderTextControlSingleLine::layout): Ditto.
(WebCore::RenderTextControlSingleLine::getAvgCharWidth): Compile-out code when building for iOS.
(WebCore::RenderTextControlSingleLine::preferredContentLogicalWidth): Ditto.
* rendering/RenderTextLineBoxes.cpp:
(WebCore::lineDirectionPointFitsInBox): Ditto.
(WebCore::RenderTextLineBoxes::positionForPoint): Added iOS-specific code.
* rendering/RenderTheme.cpp:
(WebCore::RenderTheme::paintBorderOnly): Ditto.
(WebCore::RenderTheme::paintDecorations): Modified to call the control-specific paint*Decorations().
* rendering/RenderTheme.h:
(WebCore::RenderTheme::paintCheckboxDecorations): Added.
(WebCore::RenderTheme::paintRadioDecorations): Added.
(WebCore::RenderTheme::paintButtonDecorations): Added.
(WebCore::RenderTheme::paintTextFieldDecorations): Added.
(WebCore::RenderTheme::paintTextAreaDecorations): Added.
(WebCore::RenderTheme::paintMenuListDecorations): Added.
(WebCore::RenderTheme::paintPushButtonDecorations): Added.
(WebCore::RenderTheme::paintSquareButtonDecorations): Added.
(WebCore::RenderTheme::paintFileUploadIconDecorations): Added.
(WebCore::RenderTheme::paintSliderThumbDecorations): Added.
(WebCore::RenderTheme::paintSearchFieldDecorations): Added.
* rendering/RenderThemeIOS.h: Added.
* rendering/RenderThemeIOS.mm: Added.
* rendering/RenderThemeMac.h: Don't compile the contents of this file when building for iOS.
* rendering/RenderThemeMac.mm: Ditto.
* rendering/RenderVideo.cpp:
(WebCore::RenderVideo::calculateIntrinsicSize): Compile-out code when building for iOS.
* rendering/RenderView.cpp:
(WebCore::RenderView::availableLogicalHeight): Add iOS-specific workaround. See <rdar://problem/7166808>.
(WebCore::fixedPositionOffset): Added; used in iOS-specific code (e.g. RenderView::mapLocalToContainer()).
(WebCore::RenderView::mapLocalToContainer): Use WebCore::fixedPositionOffset() instead of
FrameView::scrollOffsetForFixedPosition().
(WebCore::RenderView::pushMappingToContainer): Ditto.
(WebCore::RenderView::mapAbsoluteToLocalPoint): Ditto.
(WebCore::RenderView::repaintViewRectangle): Ditto.
(WebCore::RenderView::computeRectForRepaint): Ditto.
(WebCore::isFixedPositionInViewport): Added; used in RenderView::hasCustomFixedPosition().
(WebCore::RenderView::hasCustomFixedPosition): Added; guarded by PLATFORM(IOS).
* rendering/RenderView.h:
* rendering/RenderWidget.cpp:
(WebCore::RenderWidget::willBeDestroyed): Added iOS-specific code.
* rendering/RootInlineBox.cpp:
(WebCore::RootInlineBox::ascentAndDescentForBox): Ditto.
* rendering/break_lines.cpp: Only include header <CoreServices/CoreServices.h> when building for Mac.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@160236 268f45cc-cd09-0410-ab3c-d52691b4dbfc

52 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/rendering/InlineBox.cpp
Source/WebCore/rendering/InlineBox.h
Source/WebCore/rendering/InlineTextBox.cpp
Source/WebCore/rendering/RenderBlock.cpp
Source/WebCore/rendering/RenderBlock.h
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderBox.h
Source/WebCore/rendering/RenderBoxModelObject.cpp
Source/WebCore/rendering/RenderButton.cpp
Source/WebCore/rendering/RenderElement.cpp
Source/WebCore/rendering/RenderEmbeddedObject.cpp
Source/WebCore/rendering/RenderFileUploadControl.cpp
Source/WebCore/rendering/RenderFrameSet.cpp
Source/WebCore/rendering/RenderIFrame.h
Source/WebCore/rendering/RenderImage.cpp
Source/WebCore/rendering/RenderImage.h
Source/WebCore/rendering/RenderInline.cpp
Source/WebCore/rendering/RenderInline.h
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayer.h
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderLayerBacking.h
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/RenderLayerCompositor.h
Source/WebCore/rendering/RenderLayerFilterInfo.h
Source/WebCore/rendering/RenderMenuList.cpp
Source/WebCore/rendering/RenderMenuList.h
Source/WebCore/rendering/RenderObject.cpp
Source/WebCore/rendering/RenderObject.h
Source/WebCore/rendering/RenderScrollbar.h
Source/WebCore/rendering/RenderSearchField.cpp
Source/WebCore/rendering/RenderText.cpp
Source/WebCore/rendering/RenderText.h
Source/WebCore/rendering/RenderTextControl.cpp
Source/WebCore/rendering/RenderTextControl.h
Source/WebCore/rendering/RenderTextControlMultiLine.cpp
Source/WebCore/rendering/RenderTextControlSingleLine.cpp
Source/WebCore/rendering/RenderTextLineBoxes.cpp
Source/WebCore/rendering/RenderTheme.cpp
Source/WebCore/rendering/RenderTheme.h
Source/WebCore/rendering/RenderThemeIOS.h [new file with mode: 0644]
Source/WebCore/rendering/RenderThemeIOS.mm [new file with mode: 0644]
Source/WebCore/rendering/RenderThemeMac.h
Source/WebCore/rendering/RenderThemeMac.mm
Source/WebCore/rendering/RenderVideo.cpp
Source/WebCore/rendering/RenderView.cpp
Source/WebCore/rendering/RenderView.h
Source/WebCore/rendering/RenderWidget.cpp
Source/WebCore/rendering/RootInlineBox.cpp
Source/WebCore/rendering/break_lines.cpp

index f2c7442..2b9989a 100644 (file)
@@ -1,3 +1,246 @@
+2013-12-06  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Upstream WebCore/rendering changes
+        https://bugs.webkit.org/show_bug.cgi?id=125239
+
+        Reviewed by Simon Fraser.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * rendering/InlineBox.cpp:
+        (WebCore::InlineBox::previousOnLineExists): Added.
+        * rendering/InlineBox.h:
+        * rendering/InlineTextBox.cpp:
+        (WebCore::InlineTextBox::paintCompositionBackground): Modified to query RenderStyle
+        on iOS for the composition fill color. Added FIXME to make this platform-independent.
+        (WebCore::InlineTextBox::paintDecoration): Added iOS-specific decoration code.
+        (WebCore::lineStyleForMarkerType):
+        (WebCore::InlineTextBox::paintDocumentMarkers): Added iOS-specific code. Also, added
+        FIXME to make this code platform-independent.
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::paint): Ditto.
+        (WebCore::positionForPointRespectingEditingBoundaries): Added iOS-specific code.
+        * rendering/RenderBlock.h: Changed access control of logical{Left, Right}SelectionOffset()
+        from private to protected so that these methods can be used from RenderImage::collectSelectionRects().
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::borderRadii): Added.
+        (WebCore::RenderBox::paintBoxDecorations): Added iOS-specific workaround. See <rdar://problem/6209763>
+        for more details.
+        (WebCore::RenderBox::computeRectForRepaint): Added iOS-specific code. 
+        (WebCore::customContainingBlockWidth): Added; guarded by PLATFORM(IOS).
+        (WebCore::customContainingBlockHeight): Added; guarded by PLATFORM(IOS).
+        (WebCore::customContainingBlockLogicalWidth): Added; guarded by PLATFORM(IOS).
+        (WebCore::customContainingBlockLogicalHeight): Added; guarded by PLATFORM(IOS).
+        (WebCore::customContainingBlockAvailableLogicalHeight): Added; guarded by PLATFORM(IOS).
+        (WebCore::RenderBox::availableLogicalHeightUsing): Added iOS-specific code; calls customContainingBlockAvailableLogicalHeight().
+        (WebCore::RenderBox::containingBlockLogicalWidthForPositioned): Added iOS-specific code; calls customContainingBlockLogicalWidth().
+        (WebCore::RenderBox::containingBlockLogicalHeightForPositioned): Added iOS-specific code; calls customContainingBlockLogicalHeight().
+        (WebCore::RenderBox::layoutOverflowRectForPropagation): Added iOS-specific code.
+        * rendering/RenderBox.h:
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::stickyPositionOffset): Use FrameView::customFixedPositionLayoutRect()
+        instead of FrameView::viewportConstrainedVisibleContentRect().
+        * rendering/RenderButton.cpp:
+        (WebCore::RenderButton::layout): Added; iOS-specific. Includes FIXME comment.
+        See <rdar://problem/7675493> for more details.
+        * rendering/RenderElement.cpp:
+        (WebCore::RenderElement::styleWillChange): Added iOS-specific code.
+        (WebCore::RenderElement::styleDidChange): Modified to only call areCursorsEqual() and
+        EventHandler::scheduleCursorUpdate() on a non-iOS port.
+        * rendering/RenderEmbeddedObject.cpp:
+        (WebCore::RenderEmbeddedObject::allowsAcceleratedCompositing): Added iOS-specific code.
+        (WebCore::RenderEmbeddedObject::setPluginUnavailabilityReason): This method has an empty implementation for iOS.
+        (WebCore::RenderEmbeddedObject::setPluginUnavailabilityReasonWithDescription): Ditto.
+        * rendering/RenderFileUploadControl.cpp:
+        (WebCore::nodeHeight):
+        (WebCore::RenderFileUploadControl::maxFilenameWidth): Added iOS-specific code.
+        (WebCore::RenderFileUploadControl::paintObject): Ditto.
+        (WebCore::RenderFileUploadControl::fileTextValue): Ditto.
+        * rendering/RenderFrameSet.cpp:
+        (WebCore::RenderFrameSet::positionFrames): Ditto; Also added FIXME comment as this code may not
+        be specific to iOS.
+        * rendering/RenderIFrame.h: Added iOS-specific workaround to RenderObject::renderName(). Added
+        FIXME comment to determine whether this workaround is still applicable.
+        * rendering/RenderImage.cpp:
+        (WebCore::RenderImage::collectSelectionRects): Added; guarded by PLATFORM(IOS).
+        (WebCore::RenderImage::paintAreaElementFocusRing): This method has an empty implementation for iOS.
+        * rendering/RenderImage.h:
+        * rendering/RenderInline.cpp:
+        (WebCore::RenderInline::absoluteQuadsForSelection): Added; guarded by PLATFORM(IOS).
+        * rendering/RenderInline.h:
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::RenderLayer): Added iOS-specific member initialization.
+        (WebCore::RenderLayer::~RenderLayer): Added iOS-specific code.
+        (WebCore::RenderLayer::willBeDestroyed): Added; iOS-specific.
+        (WebCore::RenderLayer::hasAcceleratedTouchScrolling): Ditto.
+        (WebCore::RenderLayer::handleTouchEvent): Ditto.
+        (WebCore::RenderLayer::registerAsTouchEventListenerForScrolling): Ditto.
+        (WebCore::RenderLayer::unregisterAsTouchEventListenerForScrolling): Ditto.
+        (WebCore::RenderLayer::updateNeedsCompositedScrolling): Added iOS-specific code as we use UIKit
+        to composite our scroll bars.
+        (WebCore::RenderLayer::scrollTo): Added iOS-specific code.
+        (WebCore::RenderLayer::scrollRectToVisible): Ditto.
+        (WebCore::RenderLayer::styleChanged): Modified to make use of the passed StyleDifference on iOS.
+        (WebCore::RenderLayer::visibleContentRect): Added; iOS-specific.
+        (WebCore::RenderLayer::didStartScroll): Ditto.
+        (WebCore::RenderLayer::didEndScroll): Ditto.
+        (WebCore::RenderLayer::didUpdateScroll): Ditto.
+        (WebCore::RenderLayer::invalidateScrollbarRect): Added iOS-specific code.
+        (WebCore::RenderLayer::invalidateScrollCornerRect): Ditto.
+        (WebCore::RenderLayer::verticalScrollbarWidth): Ditto.
+        (WebCore::RenderLayer::horizontalScrollbarHeight): Ditto.
+        (WebCore::RenderLayer::updateScrollableAreaSet): Ditto.
+        (WebCore::RenderLayer::updateScrollInfoAfterLayout): Add iOS-specific workaround with FIXME. See
+        <rdar://problem/15579797> for more details.
+        (WebCore::RenderLayer::paintOverflowControls): Added iOS-specific code.
+        (WebCore::RenderLayer::calculateClipRects): Ditto.
+        * rendering/RenderLayer.h:
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::createPrimaryGraphicsLayer): Modified to not apply page scale on iOS
+        as we apply a page scale at a different time in the code.
+        (WebCore::RenderLayerBacking::layerWillBeDestroyed): Added; guarded by PLATFORM(IOS).
+        (WebCore::layerOrAncestorIsTransformedOrScrolling): Added iOS-specific variant with FIXME comment.
+        (WebCore::RenderLayerBacking::shouldClipCompositedBounds): Added iOS-specific code.
+        (WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): Ditto.
+        (WebCore::RenderLayerBacking::updateGraphicsLayerGeometry): Ditto.
+        (WebCore::RenderLayerBacking::registerScrollingLayers): Ditto.
+        (WebCore::RenderLayerBacking::updateScrollingLayers): Ditto.
+        (WebCore::RenderLayerBacking::containsPaintedContent): Call RenderLayer::hasBoxDecorationsOrBackground()
+        when building on iOS Simulator.
+        (WebCore::RenderLayerBacking::parentForSublayers): Added iOS-specific code and FIXME comment.
+        (WebCore::RenderLayerBacking::paintsIntoWindow): Opt-into coordinated graphics code path.
+        (WebCore::RenderLayerBacking::setContentsNeedDisplayInRect): Added iOS-specific code.
+        (WebCore::RenderLayerBacking::paintIntoLayer): Compile-out ASSERT_NOT_REACHED for iOS and added FIXME comment.
+        * rendering/RenderLayerBacking.h:
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::scheduleLayerFlush): Added iOS-specific code.
+        (WebCore::RenderLayerCompositor::chromeClient): Added; guarded by PLATFORM(IOS).
+        (WebCore::RenderLayerCompositor::flushPendingLayerChanges): Added iOS-specific code.
+        (WebCore::scrollbarHasDisplayNone): Added; iOS-specific.
+        (WebCore::updateScrollingLayerWithClient): Ditto.
+        (WebCore::RenderLayerCompositor::updateCustomLayersAfterFlush): Ditto.
+        (WebCore::RenderLayerCompositor::didFlushChangesForLayer): Added iOS-specific code.
+        (WebCore::RenderLayerCompositor::didChangeVisibleRect): Ditto.
+        (WebCore::RenderLayerCompositor::addToOverlapMap): Don't apply page scale factor on iOS. We apply
+        the page scale factor at a different time in the code. Also, added FIXME comment.
+        (WebCore::RenderLayerCompositor::computeCompositingRequirements): Added iOS-specific workaround.
+        See <rdar://problem/8348337> for more details.
+        (WebCore::RenderLayerCompositor::setIsInWindow): Use non-Mac code path for iOS.
+        (WebCore::RenderLayerCompositor::allowsIndependentlyCompositedFrames): Added iOS-specific code.
+        (WebCore::RenderLayerCompositor::requiresCompositingLayer): Ditto.
+        (WebCore::RenderLayerCompositor::requiresOwnBackingStore): Ditto.
+        (WebCore::RenderLayerCompositor::reasonsForCompositing): Ditto.
+        (WebCore::RenderLayerCompositor::requiresCompositingForAnimation): Opt-into calling
+        AnimationController::isRunningAnimationOnRenderer() on iOS.
+        (WebCore::RenderLayerCompositor::requiresCompositingForScrolling): Added; guarded by PLATFORM(IOS).
+        (WebCore::isStickyInAcceleratedScrollingLayerOrViewport): Added iOS-specific code.
+        (WebCore::isViewportConstrainedFixedOrStickyLayer): Ditto.
+        (WebCore::RenderLayerCompositor::requiresCompositingForPosition): Use FrameView::customFixedPositionLayoutRect()
+        instead of FrameView::viewportConstrainedVisibleContentRect().
+        (WebCore::RenderLayerCompositor::contentsScaleMultiplierForNewTiles): Ditto.
+        (WebCore::RenderLayerCompositor::ensureRootLayer): Ditto.
+        (WebCore::RenderLayerCompositor::computeFixedViewportConstraints): Use FrameView::customFixedPositionLayoutRect()
+        instead of FrameView::viewportConstrainedVisibleContentRect().
+        (WebCore::RenderLayerCompositor::computeStickyViewportConstraints): Ditto.
+        (WebCore::RenderLayerCompositor::registerOrUpdateViewportConstrainedLayer): This method has an empty implementation for iOS
+        as we batch update viewport-constrained layers in the iOS-specific method, RenderLayerCompositor::updateCustomLayersAfterFlush().
+        (WebCore::RenderLayerCompositor::unregisterViewportConstrainedLayer): Ditto.
+        (WebCore::RenderLayerCompositor::registerAllViewportConstrainedLayers): Added; guarded by PLATFORM(IOS).
+        (WebCore::RenderLayerCompositor::unregisterAllViewportConstrainedLayers): Ditto.
+        (WebCore::RenderLayerCompositor::registerAllScrollingLayers): Ditto.
+        (WebCore::RenderLayerCompositor::unregisterAllScrollingLayers): Ditto.
+        (WebCore::RenderLayerCompositor::scrollingLayerAddedOrUpdated): Ditto.
+        (WebCore::RenderLayerCompositor::scrollingLayerRemoved): Ditto.
+        (WebCore::RenderLayerCompositor::startInitialLayerFlushTimerIfNeeded): Ditto.
+        * rendering/RenderLayerCompositor.h:
+        * rendering/RenderLayerFilterInfo.h: Added iOS-specific Clang workaround to ignore
+        an unused private field.
+        * rendering/RenderMenuList.cpp:
+        (WebCore::selectedOptionCount): Added; guarded by PLATFORM(IOS).
+        (WebCore::RenderMenuList::RenderMenuList): On iOS we don't make use of RenderMenuList::m_popupIsVisible.
+        (WebCore::RenderMenuList::~RenderMenuList): On iOS we don't make use of RenderMenuList::m_popup.
+        (WebCore::RenderMenuList::adjustInnerStyle): Add iOS-specific code.
+        (RenderMenuList::updateFromElement): On iOS we don't make use of RenderMenuList::m_popup.
+        (RenderMenuList::setTextFromOption): Add iOS-specific code.
+        (RenderMenuList::showPopup): Define RenderMenuList::showPopup() to ASSERT_NOT_REACHED() on iOS as
+        we don't make use of RenderMenuList::m_popup.
+        (RenderMenuList::hidePopup): This method has an empty implementation for iOS as we don't make use
+        of RenderMenuList::m_popup.
+        (RenderMenuList::popupDidHide): This method has an empty implementation for iOS as we don't make use
+        of RenderMenuList::m_popupIsVisible.
+        * rendering/RenderMenuList.h:
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::columnNumberForOffset): Added; guarded by PLATFORM(IOS). Also, added a FIXME comment to
+        make this function return an unsigned integer instead of a signed integer.
+        (WebCore::RenderObject::collectSelectionRects): Added; guarded by PLATFORM(IOS).
+        (WebCore::RenderObject::destroy): Added iOS-specific code.
+        (WebCore::RenderObject::innerLineHeight): Added.
+        (WebCore::RenderObject::willRenderImage): Added iOS-specific code.
+        * rendering/RenderObject.h: Change the access control of RenderObject::drawLineForBoxSide() from protected to
+        public so that it can be used from RenderThemeIOS::adjustMenuListButtonStyle().
+        (WebCore::RenderObject::absoluteQuadsForSelection):
+        * rendering/RenderScrollbar.h: Change the access control of RenderScrollbar::getScrollbarPseudoStyle() from
+        private to public so that it can be used from the iOS-specific static function, scrollbarHasDisplayNone,
+        defined in RenderLayerCompositor.cpp.
+        * rendering/RenderSearchField.cpp:
+        (WebCore::RenderSearchField::itemText): Added iOS-specific code.
+        * rendering/RenderText.cpp:
+        (WebCore::RenderText::collectSelectionRects): Added; guarded by PLATFORM(IOS).
+        (WebCore::RenderText::setTextInternal): Added iOS-specific code.
+        * rendering/RenderText.h:
+        * rendering/RenderTextControl.cpp:
+        (WebCore::RenderTextControl::adjustInnerTextStyle): Ditto.
+        (WebCore::RenderTextControl::canScroll): Added; guarded by PLATFORM(IOS).
+        (WebCore::RenderTextControl::innerLineHeight): Ditto.
+        * rendering/RenderTextControl.h:
+        * rendering/RenderTextControlMultiLine.cpp:
+        (WebCore::RenderTextControlMultiLine::getAvgCharWidth): Compile-out code when building for iOS.
+        (WebCore::RenderTextControlMultiLine::createInnerTextStyle): Added iOS-specific code.
+        * rendering/RenderTextControlSingleLine.cpp:
+        (WebCore::RenderTextControlSingleLine::layout): Ditto.
+        (WebCore::RenderTextControlSingleLine::getAvgCharWidth): Compile-out code when building for iOS.
+        (WebCore::RenderTextControlSingleLine::preferredContentLogicalWidth): Ditto.
+        * rendering/RenderTextLineBoxes.cpp:
+        (WebCore::lineDirectionPointFitsInBox): Ditto.
+        (WebCore::RenderTextLineBoxes::positionForPoint): Added iOS-specific code.
+        * rendering/RenderTheme.cpp:
+        (WebCore::RenderTheme::paintBorderOnly): Ditto.
+        (WebCore::RenderTheme::paintDecorations): Modified to call the control-specific paint*Decorations().
+        * rendering/RenderTheme.h:
+        (WebCore::RenderTheme::paintCheckboxDecorations): Added.
+        (WebCore::RenderTheme::paintRadioDecorations): Added.
+        (WebCore::RenderTheme::paintButtonDecorations): Added.
+        (WebCore::RenderTheme::paintTextFieldDecorations): Added.
+        (WebCore::RenderTheme::paintTextAreaDecorations): Added.
+        (WebCore::RenderTheme::paintMenuListDecorations): Added.
+        (WebCore::RenderTheme::paintPushButtonDecorations): Added.
+        (WebCore::RenderTheme::paintSquareButtonDecorations): Added.
+        (WebCore::RenderTheme::paintFileUploadIconDecorations): Added.
+        (WebCore::RenderTheme::paintSliderThumbDecorations): Added.
+        (WebCore::RenderTheme::paintSearchFieldDecorations): Added.
+        * rendering/RenderThemeIOS.h: Added.
+        * rendering/RenderThemeIOS.mm: Added.
+        * rendering/RenderThemeMac.h: Don't compile the contents of this file when building for iOS.
+        * rendering/RenderThemeMac.mm: Ditto.
+        * rendering/RenderVideo.cpp:
+        (WebCore::RenderVideo::calculateIntrinsicSize): Compile-out code when building for iOS.
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::availableLogicalHeight): Add iOS-specific workaround. See <rdar://problem/7166808>.
+        (WebCore::fixedPositionOffset): Added; used in iOS-specific code (e.g. RenderView::mapLocalToContainer()).
+        (WebCore::RenderView::mapLocalToContainer): Use WebCore::fixedPositionOffset() instead of 
+        FrameView::scrollOffsetForFixedPosition().
+        (WebCore::RenderView::pushMappingToContainer): Ditto.
+        (WebCore::RenderView::mapAbsoluteToLocalPoint): Ditto.
+        (WebCore::RenderView::repaintViewRectangle): Ditto.
+        (WebCore::RenderView::computeRectForRepaint): Ditto.
+        (WebCore::isFixedPositionInViewport): Added; used in RenderView::hasCustomFixedPosition().
+        (WebCore::RenderView::hasCustomFixedPosition): Added; guarded by PLATFORM(IOS).
+        * rendering/RenderView.h:
+        * rendering/RenderWidget.cpp:
+        (WebCore::RenderWidget::willBeDestroyed): Added iOS-specific code.
+        * rendering/RootInlineBox.cpp:
+        (WebCore::RootInlineBox::ascentAndDescentForBox): Ditto.
+        * rendering/break_lines.cpp: Only include header <CoreServices/CoreServices.h> when building for Mac.
+
 2013-12-06  Zoltan Horvath  <zoltan@webkit.org>
 
         Clean up the includes of RenderBlock.h 
index 6f40197..6955bb4 100644 (file)
                CE7B2DB51586ABAD0098B3FA /* TextAlternativeWithRange.h in Headers */ = {isa = PBXBuildFile; fileRef = CE7B2DB11586ABAD0098B3FA /* TextAlternativeWithRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CE7B2DB61586ABAD0098B3FA /* TextAlternativeWithRange.mm in Sources */ = {isa = PBXBuildFile; fileRef = CE7B2DB21586ABAD0098B3FA /* TextAlternativeWithRange.mm */; };
                CE95208A1811B475007A5392 /* WebSafeIncrementalSweeperIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C4CB1D161A131200D214DA /* WebSafeIncrementalSweeperIOS.h */; };
+               FED13D520CEA949700D89466 /* RenderThemeIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = FED13D500CEA949700D89466 /* RenderThemeIOS.h */; };
+               C55C7BA11718AFBA001327E4 /* RenderThemeIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = C55C7BA01718AFBA001327E4 /* RenderThemeIOS.mm */; };
                CECADFC6153778FF00E37068 /* DictationAlternative.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CECADFC2153778FF00E37068 /* DictationAlternative.cpp */; };
                CECADFC7153778FF00E37068 /* DictationAlternative.h in Headers */ = {isa = PBXBuildFile; fileRef = CECADFC3153778FF00E37068 /* DictationAlternative.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CECADFC8153778FF00E37068 /* DictationCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CECADFC4153778FF00E37068 /* DictationCommand.cpp */; };
                CE7B2DB01586ABAD0098B3FA /* AlternativeTextUIController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AlternativeTextUIController.mm; path = mac/AlternativeTextUIController.mm; sourceTree = "<group>"; };
                CE7B2DB11586ABAD0098B3FA /* TextAlternativeWithRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TextAlternativeWithRange.h; path = mac/TextAlternativeWithRange.h; sourceTree = "<group>"; };
                CE7B2DB21586ABAD0098B3FA /* TextAlternativeWithRange.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = TextAlternativeWithRange.mm; path = mac/TextAlternativeWithRange.mm; sourceTree = "<group>"; };
+               FED13D500CEA949700D89466 /* RenderThemeIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderThemeIOS.h; sourceTree = "<group>"; };
+               C55C7BA01718AFBA001327E4 /* RenderThemeIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RenderThemeIOS.mm; sourceTree = "<group>"; };
                CECADFC2153778FF00E37068 /* DictationAlternative.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DictationAlternative.cpp; sourceTree = "<group>"; };
                CECADFC3153778FF00E37068 /* DictationAlternative.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DictationAlternative.h; sourceTree = "<group>"; };
                CECADFC4153778FF00E37068 /* DictationCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DictationCommand.cpp; sourceTree = "<group>"; };
                                86FF885F15DE3B8200BD6B28 /* RenderTextTrackCue.h */,
                                BCEA484A097D93020094C9E4 /* RenderTheme.cpp */,
                                BCEA484B097D93020094C9E4 /* RenderTheme.h */,
+                               FED13D500CEA949700D89466 /* RenderThemeIOS.h */,
+                               C55C7BA01718AFBA001327E4 /* RenderThemeIOS.mm */,
                                BCEA4848097D93020094C9E4 /* RenderThemeMac.h */,
                                BCEA4849097D93020094C9E4 /* RenderThemeMac.mm */,
                                93955A4203D72932008635CE /* RenderTreeAsText.cpp */,
                                439046DE12DA25E800AF80A2 /* RenderMathMLMath.h in Headers */,
                                439046E012DA25E800AF80A2 /* RenderMathMLOperator.h in Headers */,
                                439046E212DA25E800AF80A2 /* RenderMathMLRoot.h in Headers */,
+                               FED13D520CEA949700D89466 /* RenderThemeIOS.h in Headers */,
                                439046E412DA25E800AF80A2 /* RenderMathMLRow.h in Headers */,
                                439046E612DA25E800AF80A2 /* RenderMathMLSquareRoot.h in Headers */,
                                0783228518013ED800999E0C /* MediaStreamAudioSource.h in Headers */,
                                976D6C7B122B8A3D001FD1F7 /* WebKitBlobBuilder.cpp in Sources */,
                                150B923915F08DC400E10986 /* WebKitCSSArrayFunctionValue.cpp in Sources */,
                                A2E8AE3016A48E1C006BB3AA /* WebKitCSSFilterRule.cpp in Sources */,
+                               C55C7BA11718AFBA001327E4 /* RenderThemeIOS.mm in Sources */,
                                3106036F14327D2E00ABF4BA /* WebKitCSSFilterValue.cpp in Sources */,
                                31288E720E3005D6003619AE /* WebKitCSSKeyframeRule.cpp in Sources */,
                                31288E740E3005D6003619AE /* WebKitCSSKeyframesRule.cpp in Sources */,
index 511c695..35d17df 100644 (file)
@@ -193,6 +193,15 @@ bool InlineBox::nextOnLineExists() const
     return m_bitfields.nextOnLineExists();
 }
 
+bool InlineBox::previousOnLineExists() const
+{
+    if (!parent())
+        return false;
+    if (prevOnLine())
+        return true;
+    return parent()->previousOnLineExists();
+}
+
 InlineBox* InlineBox::nextLeafChild() const
 {
     InlineBox* leaf = 0;
index f652419..a6ce5de 100644 (file)
@@ -131,6 +131,7 @@ public:
         m_prev = prev;
     }
     bool nextOnLineExists() const;
+    bool previousOnLineExists() const;
 
     virtual bool isLeaf() const { return true; }
     
index a098f35..d1060eb 100644 (file)
@@ -716,7 +716,13 @@ void InlineTextBox::paintCompositionBackground(GraphicsContext* context, const F
 
     GraphicsContextStateSaver stateSaver(*context);
 
+#if !PLATFORM(IOS)
+    // FIXME: Is this color still applicable as of Mavericks? for non-Mac ports? We should
+    // be able to move this color information to RenderStyle.
     Color c = Color(225, 221, 85);
+#else
+    Color c = style.compositionFillColor();
+#endif
     
     updateGraphicsContext(*context, TextPaintStyle(c, style.colorSpace())); // Don't draw text at all!
 
@@ -1001,7 +1007,23 @@ void InlineTextBox::paintDecoration(GraphicsContext& context, const FloatPoint&
     
     // Use a special function for underlines to get the positioning exactly right.
     bool isPrinting = renderer().document().printing();
+#if !PLATFORM(IOS)
     context.setStrokeThickness(textDecorationThickness);
+#else
+    // On iOS we want to draw crisp decorations. The function drawLineForText takes the context's
+    // strokeThickness and renders that at device pixel scale (i.e. a strokeThickness of 1 will
+    // produce a 1 device pixel line, so thinner on retina than non-retina). We will also scale
+    // our thickness based on the size of the font. Since our default size is 16px we'll use that
+    // as a scale reference.
+    float pageScale = 1;
+    if (Page* page = renderer().frame().page())
+        pageScale = page->pageScaleFactor();
+
+    const float textDecorationBaseFontSize = 16;
+    float fontSizeScaling = renderer().style().fontSize() / textDecorationBaseFontSize;
+    float strokeThickness = roundf(textDecorationThickness * fontSizeScaling * pageScale);
+    context.setStrokeThickness(strokeThickness);
+#endif
 
     bool linesAreOpaque = !isPrinting && (!(decoration & TextDecorationUnderline) || underline.alpha() == 255) && (!(decoration & TextDecorationOverline) || overline.alpha() == 255) && (!(decoration & TextDecorationLineThrough) || linethrough.alpha() == 255);
 
@@ -1164,6 +1186,11 @@ static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentM
         return GraphicsContext::DocumentMarkerAutocorrectionReplacementLineStyle;
     case DocumentMarker::DictationAlternatives:
         return GraphicsContext::DocumentMarkerDictationAlternativesLineStyle;
+#if PLATFORM(IOS)
+    case DocumentMarker::DictationPhraseWithAlternatives:
+        // FIXME: Rename TextCheckingDictationPhraseWithAlternativesLineStyle and remove the PLATFORM(IOS)-guard.
+        return GraphicsContext::TextCheckingDictationPhraseWithAlternativesLineStyle;
+#endif
     default:
         ASSERT_NOT_REACHED();
         return GraphicsContext::DocumentMarkerSpellingLineStyle;
@@ -1304,6 +1331,10 @@ void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, const FloatPoint&
             case DocumentMarker::CorrectionIndicator:
             case DocumentMarker::Replacement:
             case DocumentMarker::DictationAlternatives:
+#if PLATFORM(IOS)
+            // FIXME: Remove the PLATFORM(IOS)-guard.
+            case DocumentMarker::DictationPhraseWithAlternatives:
+#endif
                 if (background)
                     continue;
                 break;
@@ -1334,6 +1365,12 @@ void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, const FloatPoint&
             case DocumentMarker::Grammar:
                 paintDocumentMarker(pt, boxOrigin, marker, style, font, true);
                 break;
+#if PLATFORM(IOS)
+            // FIXME: See <rdar://problem/8933352>. Also, remove the PLATFORM(IOS)-guard.
+            case DocumentMarker::DictationPhraseWithAlternatives:
+                paintDocumentMarker(pt, boxOrigin, marker, style, font, true);
+                break;
+#endif
             case DocumentMarker::TextMatch:
                 paintTextMatchMarker(pt, boxOrigin, marker, style, font);
                 break;
index 291a477..1ed5c9a 100644 (file)
@@ -2210,7 +2210,12 @@ void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
         flipForWritingMode(overflowBox);
         overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
         overflowBox.moveBy(adjustedPaintOffset);
-        if (!overflowBox.intersects(paintInfo.rect))
+        if (!overflowBox.intersects(paintInfo.rect)
+#if PLATFORM(IOS)
+            // FIXME: This may be applicable to non-iOS ports.
+            && (!hasLayer() || !layer()->isComposited())
+#endif
+        )
             return;
     }
 
@@ -3559,6 +3564,15 @@ VisiblePosition positionForPointRespectingEditingBoundaries(RenderBlock& parent,
     // If we can't find an ancestor to check editability on, or editability is unchanged, we recur like normal
     if (isEditingBoundary(ancestor, child))
         return child.positionForPoint(pointInChildCoordinates);
+    
+#if PLATFORM(IOS)
+    // On iOS we want to constrain VisiblePositions to the editable region closest to the input position, so
+    // we will allow descent from non-edtiable to editable content.
+    // FIXME: This constraining must be done at a higher level once we implement contentEditable. For now, if something
+    // is editable, the whole document will be.
+    if (childElement->isContentEditable() && !ancestor->element()->isContentEditable())
+        return child.positionForPoint(pointInChildCoordinates);
+#endif
 
     // Otherwise return before or after the child, depending on if the click was to the logical left or logical right of the child
     LayoutUnit childMiddle = parent.logicalWidthForChild(child) / 2;
index f7c50e1..122fa8b 100644 (file)
@@ -437,6 +437,9 @@ protected:
 
     void setDesiredColumnCountAndWidth(int, LayoutUnit);
 
+    LayoutUnit logicalLeftSelectionOffset(RenderBlock& rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches&);
+    LayoutUnit logicalRightSelectionOffset(RenderBlock& rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches&);
+
 public:
     virtual void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false);
     void clearLayoutOverflow();
@@ -557,9 +560,7 @@ private:
         LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
     LayoutRect blockSelectionGap(RenderBlock& rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
         LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const LogicalSelectionOffsetCaches&, const PaintInfo*);
-    LayoutUnit logicalLeftSelectionOffset(RenderBlock& rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches&);
-    LayoutUnit logicalRightSelectionOffset(RenderBlock& rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches&);
-    
+
     // FIXME-BLOCKFLOW: Remove virtualizaion when all callers have moved to RenderBlockFlow
     virtual void clipOutFloatingObjects(RenderBlock&, const PaintInfo*, const LayoutPoint&, const LayoutSize&) { };
     friend class LogicalSelectionOffsetCaches;
index a6e470e..cf6ec3e 100644 (file)
 #include "RenderLayerCompositor.h"
 #endif
 
+#if PLATFORM(IOS)
+#include "Settings.h"
+#endif
+
 namespace WebCore {
 
 using namespace HTMLNames;
@@ -596,6 +600,18 @@ LayoutUnit RenderBox::constrainContentBoxLogicalHeightByMinMax(LayoutUnit logica
     return std::max(logicalHeight, computeContentLogicalHeight(styleToUse.logicalMinHeight()));
 }
 
+RoundedRect::Radii RenderBox::borderRadii() const
+{
+    RenderStyle& style = this->style();
+    LayoutRect bounds = frameRect();
+
+    unsigned borderLeft = style.borderLeftWidth();
+    unsigned borderTop = style.borderTopWidth();
+    bounds.moveBy(LayoutPoint(borderLeft, borderTop));
+    bounds.contract(borderLeft + style.borderRightWidth(), borderTop + style.borderBottomWidth());
+    return style.getRoundedBorderFor(bounds).radii();
+}
+
 IntRect RenderBox::absoluteContentBox() const
 {
     // This is wrong with transforms and flipped writing modes.
@@ -1159,6 +1175,14 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& pai
     LayoutRect paintRect = borderBoxRectInRegion(paintInfo.renderRegion);
     paintRect.moveBy(paintOffset);
 
+#if PLATFORM(IOS)
+    // Workaround for <rdar://problem/6209763>. Force the painting bounds of checkboxes and radio controls to be square.
+    if (style().appearance() == CheckboxPart || style().appearance() == RadioPart) {
+        int width = std::min(paintRect.width(), paintRect.height());
+        int height = width;
+        paintRect = IntRect(paintRect.x(), paintRect.y() + (this->height() - height) / 2, width, height); // Vertically center the checkbox, like on desktop
+    }
+#endif
     BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context);
 
     // FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have
@@ -2109,9 +2133,15 @@ void RenderBox::computeRectForRepaint(const RenderLayerModelObject* repaintConta
     rect.setLocation(topLeft);
     if (o->hasOverflowClip()) {
         RenderBox* containerBox = toRenderBox(o);
+#if PLATFORM(IOS)
+        if (!containerBox->layer() || !containerBox->layer()->hasAcceleratedTouchScrolling()) {
+#endif
         containerBox->applyCachedClipAndScrollOffsetForRepaint(rect);
         if (rect.isEmpty())
             return;
+#if PLATFORM(IOS)
+        } 
+#endif
     }
 
     if (containerSkipped) {
@@ -2902,6 +2932,33 @@ LayoutUnit RenderBox::availableLogicalHeight(AvailableLogicalHeightType heightTy
     return constrainLogicalHeightByMinMax(availableLogicalHeightUsing(style().logicalHeight(), heightType));
 }
 
+#if PLATFORM(IOS)
+static inline int customContainingBlockWidth(const RenderView& view, const RenderBox& containingBlockBox)
+{
+    return view.frameView().customFixedPositionLayoutRect().width() - containingBlockBox.borderLeft() - containingBlockBox.borderRight() - containingBlockBox.verticalScrollbarWidth();
+}
+
+static inline int customContainingBlockHeight(const RenderView& view, const RenderBox& containingBlockBox)
+{
+    return view.frameView().customFixedPositionLayoutRect().height() - containingBlockBox.borderTop() - containingBlockBox.borderBottom() - containingBlockBox.horizontalScrollbarHeight();
+}
+
+static int customContainingBlockLogicalWidth(const RenderStyle& style, const RenderView& view, const RenderBox& containingBlockBox)
+{
+    return style.isHorizontalWritingMode() ? customContainingBlockWidth(view, containingBlockBox) : customContainingBlockHeight(view, containingBlockBox);
+}
+
+static int customContainingBlockLogicalHeight(const RenderStyle& style, const RenderView& view, const RenderBox& containingBlockBox)
+{
+    return style.isHorizontalWritingMode() ? customContainingBlockHeight(view, containingBlockBox) : customContainingBlockWidth(view, containingBlockBox);
+}
+
+static inline int customContainingBlockAvailableLogicalHeight(const RenderStyle& style, const RenderView& view)
+{
+    return style.isHorizontalWritingMode() ? view.frameView().customFixedPositionLayoutRect().height() : view.frameView().customFixedPositionLayoutRect().width();
+}
+#endif
+
 LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h, AvailableLogicalHeightType heightType) const
 {
     // We need to stop here, since we don't want to increase the height of the table
@@ -2914,9 +2971,21 @@ LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h, AvailableLogi
     }
 
     if (h.isPercent() && isOutOfFlowPositioned() && !isRenderFlowThread()) {
+#if PLATFORM(IOS)
+        RenderBlock* containingBlock = this->containingBlock();
+        // If we're fixed, and our container is the RenderView, use the custom fixed position rect for sizing.
+        if (containingBlock->isRenderView()) {
+            RenderView& view = toRenderView(*containingBlock);
+            if (view.hasCustomFixedPosition(*this))
+                return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(h, customContainingBlockAvailableLogicalHeight(containingBlock->style(), view)));
+        }
+
+        return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(h, containingBlock->availableLogicalHeight(heightType)));
+#else
         // FIXME: This is wrong if the containingBlock has a perpendicular writing mode.
         LayoutUnit availableHeight = containingBlockLogicalHeightForPositioned(containingBlock());
         return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(h, availableHeight));
+#endif
     }
 
     LayoutUnit heightIncludingScrollbar = computeContentAndScrollbarLogicalHeightUsing(h);
@@ -2981,8 +3050,15 @@ LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxMo
 
     if (containingBlock->isBox()) {
         RenderFlowThread* flowThread = flowThreadContainingBlock();
-        if (!flowThread)
+        if (!flowThread) {
+#if PLATFORM(IOS)
+            if (view().hasCustomFixedPosition(*this)) {
+                const RenderBox& containingBlockBox = toRenderBox(*containingBlock);
+                return customContainingBlockLogicalWidth(containingBlockBox.style(), &view(), containingBlockBox);
+            }
+#endif
             return toRenderBox(containingBlock)->clientLogicalWidth();
+        }
 
         if (containingBlock->isRenderNamedFlowThread() && style().position() == FixedPosition)
             return containingBlock->view().clientLogicalWidth();
@@ -3038,6 +3114,10 @@ LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxM
         return containingBlockLogicalWidthForPositioned(containingBlock, 0, false);
 
     if (containingBlock->isBox()) {
+#if PLATFORM(IOS)
+        if (view().hasCustomFixedPosition(*this))
+            return customContainingBlockLogicalHeight(style(), view(), toRenderBox(*containingBlock));
+#endif
         const RenderBlock* cb = toRenderBlock(containingBlock);
         LayoutUnit result = cb->clientLogicalHeight();
         RenderFlowThread* flowThread = flowThreadContainingBlock();
@@ -4460,7 +4540,11 @@ LayoutRect RenderBox::layoutOverflowRectForPropagation(RenderStyle* parentStyle)
         rect.unite(layoutOverflowRect());
 
     bool hasTransform = hasLayer() && layer()->transform();
+#if PLATFORM(IOS)
+    if (isInFlowPositioned() || (hasTransform && document().settings()->shouldTransformsAffectOverflow())) {
+#else
     if (isInFlowPositioned() || hasTransform) {
+#endif
         // If we are relatively positioned or if we have a transform, then we have to convert
         // this rectangle into physical coordinates, apply relative positioning and transforms
         // to it, and then convert it back.
index 50209ac..34a4941 100644 (file)
@@ -157,6 +157,8 @@ public:
     IntRect pixelSnappedBorderBoxRect() const { return IntRect(IntPoint(), m_frameRect.pixelSnappedSize()); }
     virtual IntRect borderBoundingBox() const OVERRIDE FINAL { return pixelSnappedBorderBoxRect(); }
 
+    RoundedRect::Radii borderRadii() const;
+
     // The content area of the box (excludes padding - and intrinsic padding for table cells, etc... - and border).
     LayoutRect contentBoxRect() const { return LayoutRect(borderLeft() + paddingLeft(), borderTop() + paddingTop(), contentWidth(), contentHeight()); }
     // The content box in absolute coords. Ignores transforms.
index cef743f..ed3dffd 100644 (file)
@@ -432,7 +432,11 @@ LayoutSize RenderBoxModelObject::stickyPositionOffset() const
         FloatPoint scrollOffset = FloatPoint() + enclosingClippingLayer->scrollOffset();
         constrainingRect.setLocation(scrollOffset);
     } else {
+#if PLATFORM(IOS)
+        LayoutRect viewportRect = view().frameView().customFixedPositionLayoutRect();
+#else
         LayoutRect viewportRect = view().frameView().viewportConstrainedVisibleContentRect();
+#endif
         float scale = view().frameView().frame().frameScaleFactor();
         viewportRect.scale(1 / scale);
         constrainingRect = viewportRect;
index 5722f1c..df31c26 100644 (file)
 #include "RenderTheme.h"
 #include "StyleInheritedData.h"
 
+#if PLATFORM(IOS)
+#include "RenderThemeIOS.h"
+#endif
+
 namespace WebCore {
 
 using namespace HTMLNames;
@@ -192,4 +196,14 @@ void RenderButton::timerFired(Timer<RenderButton>*)
     repaint();
 }
 
+#if PLATFORM(IOS)
+void RenderButton::layout()
+{
+    RenderFlexibleBox::layout();
+
+    // FIXME: We should not be adjusting styles during layout. See <rdar://problem/7675493>.
+    RenderThemeIOS::adjustRoundBorderRadius(style(), this);
+}
+#endif
+
 } // namespace WebCore
index c9ecb9f..5e56958 100644 (file)
@@ -846,6 +846,10 @@ void RenderElement::styleWillChange(StyleDifference diff, const RenderStyle& new
         if (visibilityChanged)
             document().setAnnotatedRegionsDirty(true);
 #endif
+#if PLATFORM(IOS) && ENABLE(TOUCH_EVENTS)
+        if (visibilityChanged)
+            document().dirtyTouchEventRects();
+#endif
         if (visibilityChanged) {
             if (AXObjectCache* cache = document().existingAXObjectCache())
                 cache->childrenChanged(parent());
@@ -923,6 +927,7 @@ void RenderElement::styleWillChange(StyleDifference diff, const RenderStyle& new
     }
 }
 
+#if !PLATFORM(IOS)
 static bool areNonIdenticalCursorListsEqual(const RenderStyle* a, const RenderStyle* b)
 {
     ASSERT(a->cursors() != b->cursors());
@@ -933,6 +938,7 @@ static inline bool areCursorsEqual(const RenderStyle* a, const RenderStyle* b)
 {
     return a->cursor() == b->cursor() && (a->cursors() == b->cursors() || areNonIdenticalCursorListsEqual(a, b));
 }
+#endif
 
 void RenderElement::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
 {
@@ -972,8 +978,10 @@ void RenderElement::styleDidChange(StyleDifference diff, const RenderStyle* oldS
     // Don't check for repaint here; we need to wait until the layer has been
     // updated by subclasses before we know if we have to repaint (in setStyle()).
 
+#if !PLATFORM(IOS)
     if (oldStyle && !areCursorsEqual(oldStyle, &style()))
         frame().eventHandler().scheduleCursorUpdate();
+#endif
 }
 
 void RenderElement::insertedIntoTree()
index b274683..2a9dbe5 100644 (file)
@@ -134,10 +134,16 @@ bool RenderEmbeddedObject::requiresLayer() const
 
 bool RenderEmbeddedObject::allowsAcceleratedCompositing() const
 {
+#if PLATFORM(IOS)
+    // The timing of layer creation is different on the phone, since the plugin can only be manipulated from the main thread.
+    return widget() && widget()->isPluginViewBase() && toPluginViewBase(widget())->willProvidePluginLayer();
+#else
     return widget() && widget()->isPluginViewBase() && toPluginViewBase(widget())->platformLayer();
+#endif
 }
 #endif
 
+#if !PLATFORM(IOS)
 static String unavailablePluginReplacementText(RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason)
 {
     switch (pluginUnavailabilityReason) {
@@ -154,6 +160,7 @@ static String unavailablePluginReplacementText(RenderEmbeddedObject::PluginUnava
     ASSERT_NOT_REACHED();
     return String();
 }
+#endif
 
 static bool shouldUnavailablePluginMessageBeButton(Document& document, RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason)
 {
@@ -163,11 +170,19 @@ static bool shouldUnavailablePluginMessageBeButton(Document& document, RenderEmb
 
 void RenderEmbeddedObject::setPluginUnavailabilityReason(PluginUnavailabilityReason pluginUnavailabilityReason)
 {
+#if PLATFORM(IOS)
+    UNUSED_PARAM(pluginUnavailabilityReason);
+#else
     setPluginUnavailabilityReasonWithDescription(pluginUnavailabilityReason, unavailablePluginReplacementText(pluginUnavailabilityReason));
+#endif
 }
 
 void RenderEmbeddedObject::setPluginUnavailabilityReasonWithDescription(PluginUnavailabilityReason pluginUnavailabilityReason, const String& description)
 {
+#if PLATFORM(IOS)
+    UNUSED_PARAM(pluginUnavailabilityReason);
+    UNUSED_PARAM(description);
+#else
     ASSERT(!m_isPluginUnavailable);
     m_isPluginUnavailable = true;
     m_pluginUnavailabilityReason = pluginUnavailabilityReason;
@@ -176,6 +191,7 @@ void RenderEmbeddedObject::setPluginUnavailabilityReasonWithDescription(PluginUn
         m_unavailablePluginReplacementText = unavailablePluginReplacementText(pluginUnavailabilityReason);
     else
         m_unavailablePluginReplacementText = description;
+#endif
 }
 
 void RenderEmbeddedObject::setUnavailablePluginIndicatorIsPressed(bool pressed)
index 19e9ea3..207df25 100644 (file)
 #include "VisiblePosition.h"
 #include <math.h>
 
+#if PLATFORM(IOS)
+#include "StringTruncator.h"
+#endif
+
 namespace WebCore {
 
 using namespace HTMLNames;
 
 const int afterButtonSpacing = 4;
+#if !PLATFORM(IOS)
 const int iconHeight = 16;
 const int iconWidth = 16;
 const int iconFilenameSpacing = 2;
 const int defaultWidthNumChars = 34;
+#else
+// On iOS the icon height matches the button height, to maximize the icon size.
+const int iconFilenameSpacing = afterButtonSpacing;
+const int defaultWidthNumChars = 38;
+#endif
 const int buttonShadowHeight = 2;
 
 RenderFileUploadControl::RenderFileUploadControl(HTMLInputElement& input, PassRef<RenderStyle> style)
@@ -93,8 +103,18 @@ static int nodeWidth(Node* node)
     return (node && node->renderBox()) ? node->renderBox()->pixelSnappedWidth() : 0;
 }
 
+#if PLATFORM(IOS)
+static int nodeHeight(Node* node)
+{
+    return (node && node->renderBox()) ? node->renderBox()->pixelSnappedHeight() : 0;
+}
+#endif
+
 int RenderFileUploadControl::maxFilenameWidth() const
 {
+#if PLATFORM(IOS)
+    int iconWidth = nodeHeight(uploadButton());
+#endif
     return std::max(0, contentBoxRect().pixelSnappedWidth() - nodeWidth(uploadButton()) - afterButtonSpacing
         - (inputElement().icon() ? iconWidth + iconFilenameSpacing : 0));
 }
@@ -121,6 +141,10 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoin
         TextRun textRun = constructTextRun(this, font, displayedFilename, style(), TextRun::AllowTrailingExpansion, RespectDirection | RespectDirectionOverride);
         textRun.disableRoundingHacks();
 
+#if PLATFORM(IOS)
+        int iconHeight = nodeHeight(uploadButton());
+        int iconWidth = iconHeight;
+#endif
         // Determine where the filename should be placed
         LayoutUnit contentLeft = paintOffset.x() + borderLeft() + paddingLeft();
         HTMLInputElement* button = uploadButton();
@@ -158,8 +182,17 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoin
             else
                 iconX = contentLeft + contentWidth() - buttonWidth - afterButtonSpacing - iconWidth;
 
+#if PLATFORM(IOS)
+            if (RenderButton* buttonRenderer = toRenderButton(button->renderer())) {
+                // Draw the file icon and decorations.
+                IntRect iconRect(iconX, iconY, iconWidth, iconHeight);
+                RenderTheme::FileUploadDecorations decorationsType = inputElement().files()->length() == 1 ? RenderTheme::SingleFile : RenderTheme::MultipleFiles;
+                theme()->paintFileUploadIconDecorations(this, buttonRenderer, paintInfo, iconRect, inputElement().icon(), decorationsType);
+            }
+#else
             // Draw the file icon
             inputElement().icon()->paint(paintInfo.context, IntRect(roundToInt(iconX), roundToInt(iconY), iconWidth, iconHeight));
+#endif
         }
     }
 
@@ -241,6 +274,10 @@ String RenderFileUploadControl::buttonValue()
 String RenderFileUploadControl::fileTextValue() const
 {
     ASSERT(inputElement().files());
+#if PLATFORM(IOS)
+    if (inputElement().files()->length())
+        return StringTruncator::rightTruncate(inputElement().displayString(), maxFilenameWidth(), style().font(), StringTruncator::EnableRoundingHacks);
+#endif
     return theme()->fileListNameForWidth(inputElement().files(), style().font(), maxFilenameWidth(), inputElement().multiple());
 }
     
index 1cf0719..416392f 100644 (file)
@@ -514,7 +514,12 @@ void RenderFrameSet::positionFrames()
             if (width != child->width() || height != child->height()) {
                 child->setWidth(width);
                 child->setHeight(height);
+#if PLATFORM(IOS)
+                // FIXME: Is this iOS-specific?
+                child->setNeedsLayout(MarkOnlyThis);
+#else
                 child->setNeedsLayout();
+#endif
                 child->layout();
             }
 
index ea85964..ae14368 100644 (file)
@@ -54,7 +54,12 @@ private:
 
     virtual bool isRenderIFrame() const OVERRIDE { return true; }
 
+#if PLATFORM(IOS)
+    // FIXME: Do we still need this workaround to avoid breaking layout tests?
+    virtual const char* renderName() const OVERRIDE { return "RenderPartObject"; }
+#else
     virtual const char* renderName() const OVERRIDE { return "RenderIFrame"; }
+#endif
 
     virtual bool requiresLayer() const OVERRIDE;
 
index b2ee317..79b5687 100644 (file)
 #include "SVGImage.h"
 #include <wtf/StackStats.h>
 
+#if PLATFORM(IOS)
+#include "LogicalSelectionOffsetCaches.h"
+#include "SelectionRect.h"
+#endif
+
 namespace WebCore {
 
+#if PLATFORM(IOS)
+// FIXME: This doesn't behave correctly for floating or positioned images, but WebCore doesn't handle those well
+// during selection creation yet anyway.
+// FIXME: We can't tell whether or not we contain the start or end of the selected Range using only the offsets
+// of the start and end, we need to know the whole Position.
+void RenderImage::collectSelectionRects(Vector<SelectionRect>& rects, unsigned, unsigned)
+{
+    RenderBlock* containingBlock = this->containingBlock();
+
+    IntRect imageRect;
+    // FIXME: It doesn't make sense to package line bounds into SelectionRects. We should find
+    // the right and left extent of the selection once for the entire selected Range, perhaps
+    // using the Range's common ancestor.
+    IntRect lineExtentRect;
+    bool isFirstOnLine = false;
+    bool isLastOnLine = false;
+
+    InlineBox* inlineBox = inlineBoxWrapper();
+    if (!inlineBox) {
+        // This is a block image.
+        imageRect = IntRect(0, 0, width(), height());
+        isFirstOnLine = true;
+        isLastOnLine = true;
+        lineExtentRect = imageRect;
+        if (containingBlock->isHorizontalWritingMode()) {
+            lineExtentRect.setX(containingBlock->x());
+            lineExtentRect.setWidth(containingBlock->width());
+        } else {
+            lineExtentRect.setY(containingBlock->y());
+            lineExtentRect.setHeight(containingBlock->height());
+        }
+    } else {
+        LayoutUnit selectionTop = !containingBlock->style().isFlippedBlocksWritingMode() ? inlineBox->root().selectionTop() - logicalTop() : logicalBottom() - inlineBox->root().selectionBottom();
+        imageRect = IntRect(0,  selectionTop, logicalWidth(), inlineBox->root().selectionHeight());
+        isFirstOnLine = !inlineBox->previousOnLineExists();
+        isLastOnLine = !inlineBox->nextOnLineExists();
+        LogicalSelectionOffsetCaches cache(*containingBlock);
+        LayoutUnit leftOffset = containingBlock->logicalLeftSelectionOffset(*containingBlock, inlineBox->logicalTop(), cache);
+        LayoutUnit rightOffset = containingBlock->logicalRightSelectionOffset(*containingBlock, inlineBox->logicalTop(), cache);
+        lineExtentRect = IntRect(leftOffset - logicalLeft(), imageRect.y(), rightOffset - leftOffset, imageRect.height());
+        if (!inlineBox->isHorizontal()) {
+            imageRect = imageRect.transposedRect();
+            lineExtentRect = lineExtentRect.transposedRect();
+        }
+    }
+
+    bool isFixed = false;
+    IntRect absoluteBounds = localToAbsoluteQuad(FloatRect(imageRect), false, &isFixed).enclosingBoundingBox();
+    IntRect lineExtentBounds = localToAbsoluteQuad(FloatRect(lineExtentRect)).enclosingBoundingBox();
+    if (!containingBlock->isHorizontalWritingMode())
+        lineExtentBounds = lineExtentBounds.transposedRect();
+
+    // FIXME: We should consider either making SelectionRect a struct or better organize its optional fields into
+    // an auxiliary struct to simplify its initialization.
+    rects.append(SelectionRect(absoluteBounds, containingBlock->style().direction(), lineExtentBounds.x(), lineExtentBounds.maxX(), lineExtentBounds.maxY(), 0, false /* line break */, isFirstOnLine, isLastOnLine, false /* contains start */, false /* contains end */, containingBlock->style().isHorizontalWritingMode(), isFixed, false /* ruby text */, columnNumberForOffset(absoluteBounds.x())));
+}
+#endif
+
 using namespace HTMLNames;
 
 RenderImage::RenderImage(Element& element, PassRef<RenderStyle> style)
@@ -462,6 +525,9 @@ void RenderImage::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
     
 void RenderImage::paintAreaElementFocusRing(PaintInfo& paintInfo)
 {
+#if PLATFORM(IOS)
+    UNUSED_PARAM(paintInfo);
+#else
     if (document().printing() || !frame().selection().isFocusedAndActive())
         return;
     
@@ -493,6 +559,7 @@ void RenderImage::paintAreaElementFocusRing(PaintInfo& paintInfo)
     paintInfo.context->drawFocusRing(path, outlineWidth,
         areaElementStyle->outlineOffset(),
         areaElementStyle->visitedDependentColor(CSSPropertyOutlineColor));
+#endif
 }
 
 void RenderImage::areaElementFocusChanged(HTMLAreaElement* element)
index c23a269..84dfc90 100644 (file)
@@ -56,6 +56,10 @@ public:
     void areaElementFocusChanged(HTMLAreaElement*);
 
     void highQualityRepaintTimerFired(Timer<RenderImage>*);
+    
+#if PLATFORM(IOS)
+    virtual void collectSelectionRects(Vector<SelectionRect>&, unsigned, unsigned) OVERRIDE;
+#endif
 
     void setIsGeneratedContent(bool generated = true) { m_isGeneratedContent = generated; }
 
index 29c5b73..66951e7 100644 (file)
@@ -697,6 +697,14 @@ void RenderInline::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
         continuation->absoluteQuads(quads, wasFixed);
 }
 
+#if PLATFORM(IOS)
+void RenderInline::absoluteQuadsForSelection(Vector<FloatQuad>& quads) const
+{
+    AbsoluteQuadsGeneratorContext context(this, quads);
+    generateLineBoxRects(context);
+}
+#endif
+
 LayoutUnit RenderInline::offsetLeft() const
 {
     LayoutPoint topLeft;
index 7d87816..63d1ced 100644 (file)
@@ -68,6 +68,10 @@ public:
     InlineBox* firstLineBoxIncludingCulling() const { return alwaysCreateLineBoxes() ? firstLineBox() : culledInlineFirstLineBox(); }
     InlineBox* lastLineBoxIncludingCulling() const { return alwaysCreateLineBoxes() ? lastLineBox() : culledInlineLastLineBox(); }
 
+#if PLATFORM(IOS)
+    virtual void absoluteQuadsForSelection(Vector<FloatQuad>& quads) const OVERRIDE;
+#endif
+
     virtual RenderBoxModelObject* virtualContinuation() const OVERRIDE FINAL { return continuation(); }
     RenderInline* inlineElementContinuation() const;
 
index 16a96bb..36f0ecc 100644 (file)
@@ -182,6 +182,12 @@ RenderLayer::RenderLayer(RenderLayerModelObject& rendererLayerModelObject)
     , m_indirectCompositingReason(NoIndirectCompositingReason)
     , m_viewportConstrainedNotCompositedReason(NoNotCompositedReason)
 #endif
+#if PLATFORM(IOS)
+    , m_adjustForIOSCaretWhenScrolling(false)
+    , m_registeredAsTouchEventListenerForScrolling(false)
+    , m_inUserScroll(false)
+    , m_requiresScrollBoundsOriginUpdate(false)
+#endif
     , m_containsDirtyOverlayScrollbars(false)
     , m_updatingMarqueePosition(false)
 #if !ASSERT_DISABLED
@@ -237,6 +243,9 @@ RenderLayer::~RenderLayer()
     renderer().view().frameView().removeScrollableArea(this);
 
     if (!renderer().documentBeingDestroyed()) {
+#if PLATFORM(IOS)
+        unregisterAsTouchEventListenerForScrolling();
+#endif
         if (Element* element = renderer().element())
             element->setSavedLayerScrollOffset(m_scrollOffset);
     }
@@ -1767,6 +1776,14 @@ void RenderLayer::beginTransparencyLayers(GraphicsContext* context, const Render
     }
 }
 
+#if PLATFORM(IOS)
+void RenderLayer::willBeDestroyed()
+{
+    if (RenderLayerBacking* layerBacking = backing())
+        layerBacking->layerWillBeDestroyed();
+}
+#endif
+
 void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
 {
     RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
@@ -2084,6 +2101,55 @@ void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutR
     rect.move(-delta.x(), -delta.y());
 }
 
+#if PLATFORM(IOS)
+bool RenderLayer::hasAcceleratedTouchScrolling() const
+{
+#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+    if (!scrollsOverflow())
+        return false;
+    
+    Settings* settings = renderer().document().settings();
+
+    // FIXME: settings should not be null at this point. If you find a reliable way to hit this assertion, please file a bug.
+    // See <rdar://problem/10266101>.
+    ASSERT(settings);
+
+    return renderer().style().useTouchOverflowScrolling() || (settings && settings->alwaysUseAcceleratedOverflowScroll());
+#else
+    return false;
+#endif
+}
+
+#if PLATFORM(IOS) && ENABLE(TOUCH_EVENTS)
+bool RenderLayer::handleTouchEvent(const PlatformTouchEvent& touchEvent)
+{
+    // If we have accelerated scrolling, let the scrolling be handled outside of WebKit.
+    if (hasAcceleratedTouchScrolling())
+        return false;
+
+    return ScrollableArea::handleTouchEvent(touchEvent);
+}
+#endif
+
+void RenderLayer::registerAsTouchEventListenerForScrolling()
+{
+    if (!renderer().element() || m_registeredAsTouchEventListenerForScrolling)
+        return;
+    
+    renderer().document().addTouchEventListener(renderer().element());
+    m_registeredAsTouchEventListenerForScrolling = true;
+}
+
+void RenderLayer::unregisterAsTouchEventListenerForScrolling()
+{
+    if (!renderer().element() || !m_registeredAsTouchEventListenerForScrolling)
+        return;
+
+    renderer().document().removeTouchEventListener(renderer().element());
+    m_registeredAsTouchEventListenerForScrolling = false;
+}
+#endif // PLATFORM(IOS)
+
 #if USE(ACCELERATED_COMPOSITING)
 
 bool RenderLayer::usesCompositedScrolling() const
@@ -2107,9 +2173,11 @@ void RenderLayer::updateNeedsCompositedScrolling()
             && canBeStackingContainer()
             && !hasOutOfFlowPositionedDescendant();
 
-#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+#if !PLATFORM(IOS) && ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
         m_needsCompositedScrolling = forceUseCompositedScrolling || renderer().style().useTouchOverflowScrolling();
 #else
+        // On iOS we don't want to opt into accelerated composited scrolling, which creates scroll bar
+        // layers in WebCore, because we use UIKit to composite our scroll bars.
         m_needsCompositedScrolling = forceUseCompositedScrolling;
 #endif
         // We gather a boolean value for use with Google UMA histograms to
@@ -2241,6 +2309,17 @@ void RenderLayer::scrollTo(int x, int y)
         // Ensure that the dimensions will be computed if they need to be (for overflow:hidden blocks).
         if (m_scrollDimensionsDirty)
             computeScrollDimensions();
+#if PLATFORM(IOS)
+        if (adjustForIOSCaretWhenScrolling()) {
+            int maxX = scrollWidth() - box->clientWidth();
+            if (x > maxX - caretWidth) {
+                x += caretWidth;
+                if (x <= caretWidth)
+                    x = 0;
+            } else if (x < m_scrollOffset.width() - caretWidth)
+                x -= caretWidth;
+        }
+#endif
     }
     
     // FIXME: Eventually, we will want to perform a blit.  For now never
@@ -2249,8 +2328,13 @@ void RenderLayer::scrollTo(int x, int y)
     // is either occluded by another layer or clipped by an enclosing
     // layer or contains fixed backgrounds, etc.).
     IntSize newScrollOffset = IntSize(x - scrollOrigin().x(), y - scrollOrigin().y());
-    if (m_scrollOffset == newScrollOffset)
+    if (m_scrollOffset == newScrollOffset) {
+#if PLATFORM(IOS)
+        if (m_requiresScrollBoundsOriginUpdate)
+            updateCompositingLayersAfterScroll();
+#endif
         return;
+}
     m_scrollOffset = newScrollOffset;
 
     InspectorInstrumentation::willScrollLayer(&renderer().frame());
@@ -2276,6 +2360,10 @@ void RenderLayer::scrollTo(int x, int y)
             // when that completes.
             updateCompositingLayersAfterScroll();
         }
+
+#if PLATFORM(IOS) && ENABLE(TOUCH_EVENTS)
+        renderer().document().dirtyTouchEventRects();
+#endif
     }
 
     Frame& frame = renderer().frame();
@@ -2296,7 +2384,11 @@ void RenderLayer::scrollTo(int x, int y)
 #endif
 
     // Just schedule a full repaint of our object.
+#if PLATFORM(IOS)
+    if (!hasAcceleratedTouchScrolling())
+#else
     if (requiresRepaint)
+#endif
         renderer().repaintUsingContainer(repaintContainer, pixelSnappedIntRect(m_repaintRect));
 
     // Schedule the scroll DOM event.
@@ -2386,10 +2478,15 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignm
                     parentLayer = 0;
             }
         } else {
+#if !PLATFORM(IOS)
             LayoutRect viewRect = frameView.visibleContentRect();
             LayoutRect visibleRectRelativeToDocument = viewRect;
             IntSize scrollOffsetRelativeToDocument = frameView.scrollOffsetRelativeToDocument();
             visibleRectRelativeToDocument.setLocation(IntPoint(scrollOffsetRelativeToDocument.width(), scrollOffsetRelativeToDocument.height()));
+#else
+            LayoutRect viewRect = frameView.actualVisibleContentRect();
+            LayoutRect visibleRectRelativeToDocument = viewRect;
+#endif
 
             LayoutRect r = getRectToExpose(viewRect, visibleRectRelativeToDocument, rect, alignX, alignY);
                 
@@ -2624,6 +2721,13 @@ IntRect RenderLayer::visibleContentRect(VisibleContentRectIncludesScrollbars scr
     if (scrollbarInclusion == IncludeScrollbars) {
         verticalScrollbarWidth = (verticalScrollbar() && !verticalScrollbar()->isOverlayScrollbar()) ? verticalScrollbar()->width() : 0;
         horizontalScrollbarHeight = (horizontalScrollbar() && !horizontalScrollbar()->isOverlayScrollbar()) ? horizontalScrollbar()->height() : 0;
+
+#if PLATFORM(IOS)
+        if (hasAcceleratedTouchScrolling()) {
+            verticalScrollbarWidth = 0;
+            horizontalScrollbarHeight = 0;
+        }
+#endif
     }
     
     return IntRect(IntPoint(scrollXOffset(), scrollYOffset()),
@@ -2761,6 +2865,27 @@ bool RenderLayer::shouldSuspendScrollAnimations() const
     return renderer().view().frameView().shouldSuspendScrollAnimations();
 }
 
+#if PLATFORM(IOS)
+void RenderLayer::didStartScroll()
+{
+    if (Page* page = renderer().frame().page())
+        page->chrome().client().didStartOverflowScroll();
+}
+
+void RenderLayer::didEndScroll()
+{
+    if (Page* page = renderer().frame().page())
+        page->chrome().client().didEndOverflowScroll();
+}
+    
+void RenderLayer::didUpdateScroll()
+{
+    // Send this notification when we scroll, since this is how we keep selection updated.
+    if (Page* page = renderer().frame().page())
+        page->chrome().client().didLayout(ChromeClient::Scroll);
+}
+#endif
+
 IntPoint RenderLayer::lastKnownMousePosition() const
 {
     return renderer().frame().eventHandler().lastKnownMousePosition();
@@ -2832,6 +2957,12 @@ IntSize RenderLayer::scrollbarOffset(const Scrollbar* scrollbar) const
 
 void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
 {
+#if PLATFORM(IOS)
+    // No need to invalidate scrollbars if we're using accelerated scrolling.
+    if (hasAcceleratedTouchScrolling())
+        return;
+#endif
+
 #if USE(ACCELERATED_COMPOSITING)
     if (scrollbar == m_vBar.get()) {
         if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
@@ -2863,6 +2994,12 @@ void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& r
 
 void RenderLayer::invalidateScrollCornerRect(const IntRect& rect)
 {
+#if PLATFORM(IOS)
+    // No need to invalidate the scroll corner if we're using accelerated scrolling.
+    if (hasAcceleratedTouchScrolling())
+        return;
+#endif
+
 #if USE(ACCELERATED_COMPOSITING)
     if (GraphicsLayer* layer = layerForScrollCorner()) {
         layer->setNeedsDisplayInRect(rect);
@@ -2984,6 +3121,12 @@ int RenderLayer::verticalScrollbarWidth(OverlayScrollbarSizeRelevancy relevancy)
 {
     if (!m_vBar || (m_vBar->isOverlayScrollbar() && (relevancy == IgnoreOverlayScrollbarSize || !m_vBar->shouldParticipateInHitTesting())))
         return 0;
+
+#if PLATFORM(IOS)
+    if (hasAcceleratedTouchScrolling()) 
+        return 0;
+#endif
+
     return m_vBar->width();
 }
 
@@ -2991,6 +3134,12 @@ int RenderLayer::horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevan
 {
     if (!m_hBar || (m_hBar->isOverlayScrollbar() && (relevancy == IgnoreOverlayScrollbarSize || !m_hBar->shouldParticipateInHitTesting())))
         return 0;
+
+#if PLATFORM(IOS)
+    if (hasAcceleratedTouchScrolling()) 
+        return 0;
+#endif
+
     return m_hBar->height();
 }
 
@@ -3219,8 +3368,18 @@ void RenderLayer::updateScrollInfoAfterLayout()
         // Layout may cause us to be at an invalid scroll position. In this case we need
         // to pull our scroll offsets back to the max (or push them up to the min).
         IntSize clampedScrollOffset = clampScrollOffset(scrollOffset());
+#if PLATFORM(IOS)
+        // FIXME: This looks wrong. The caret adjust mode should only be enabled on editing related entry points.
+        // This code was added to fix an issue where the text insertion point would always be drawn on the right edge
+        // of a text field whose content overflowed its bounds. See <rdar://problem/15579797> for more details.
+        setAdjustForIOSCaretWhenScrolling(true);
+#endif
         if (clampedScrollOffset != scrollOffset())
             scrollToOffset(clampedScrollOffset);
+
+#if PLATFORM(IOS)
+        setAdjustForIOSCaretWhenScrolling(false);
+#endif
     }
 
     updateScrollbarsAfterLayout();
@@ -3260,6 +3419,12 @@ void RenderLayer::paintOverflowControls(GraphicsContext* context, const IntPoint
     if (!renderer().hasOverflowClip())
         return;
 
+#if PLATFORM(IOS)
+    // Don't render (custom) scrollbars if we have accelerated scrolling.
+    if (hasAcceleratedTouchScrolling())
+        return;
+#endif
+
     // Overlay scrollbars paint in a second pass through the layer tree so that they will paint
     // on top of everything else. If this is the normal painting pass, paintingOverlayControls
     // will be false, and we should just tell the root layer that there are overlay scrollbars
@@ -5243,7 +5408,11 @@ void RenderLayer::calculateClipRects(const ClipRectsContext& clipRectsContext, C
         clipRects.setOverflowClipRect(clipRects.posClipRect());
     
     // Update the clip rects that will be passed to child layers.
+#if PLATFORM(IOS)
+    if (renderer().hasClipOrOverflowClip() && (clipRectsContext.respectOverflowClip == RespectOverflowClip || this != clipRectsContext.rootLayer)) {
+#else
     if ((renderer().hasOverflowClip() && (clipRectsContext.respectOverflowClip == RespectOverflowClip || this != clipRectsContext.rootLayer)) || renderer().hasClip()) {
+#endif
         // This layer establishes a clip of some kind.
 
         // This offset cannot use convertToLayerCoords, because sometimes our rootLayer may be across
@@ -6183,6 +6352,9 @@ bool RenderLayer::shouldBeNormalFlowOnly() const
 #if ENABLE(CSS_FILTERS)
         && !renderer().hasFilter()
 #endif
+#if PLATFORM(IOS)
+            && !hasAcceleratedTouchScrolling()
+#endif
 #if ENABLE(CSS_COMPOSITING)
         && !renderer().hasBlendMode()
 #endif
@@ -6397,7 +6569,7 @@ inline bool RenderLayer::needsCompositingLayersRebuiltForOverflow(const RenderSt
 
 #endif // USE(ACCELERATED_COMPOSITING)
 
-void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
+void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle)
 {
     bool isNormalFlowOnly = shouldBeNormalFlowOnly();
     if (isNormalFlowOnly != m_isNormalFlowOnly) {
@@ -6477,6 +6649,13 @@ void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
     }
 #endif
 
+#if PLATFORM(IOS) && ENABLE(TOUCH_EVENTS)
+    if (diff == StyleDifferenceRecompositeLayer || diff >= StyleDifferenceLayoutPositionedMovementOnly)
+        renderer().document().dirtyTouchEventRects();
+#else
+    UNUSED_PARAM(diff);
+#endif
+
 #if ENABLE(CSS_FILTERS)
     updateOrRemoveFilterEffectRenderer();
 #if USE(ACCELERATED_COMPOSITING)
@@ -6510,6 +6689,18 @@ void RenderLayer::updateScrollableAreaSet(bool hasOverflow)
         updateNeedsCompositedScrolling();
 #endif
     }
+
+#if PLATFORM(IOS)
+    if (addedOrRemoved) {
+        if (isScrollable && !hasAcceleratedTouchScrolling())
+            registerAsTouchEventListenerForScrolling();
+        else {
+            // We only need the touch listener for unaccelerated overflow scrolling, so if we became
+            // accelerated, remove ourselves as a touch event listener.
+            unregisterAsTouchEventListenerForScrolling();
+        }
+    }
+#endif
 }
 
 void RenderLayer::updateScrollCornerStyle()
index 142b56c..d58ee2a 100644 (file)
@@ -320,6 +320,10 @@ public:
     explicit RenderLayer(RenderLayerModelObject&);
     virtual ~RenderLayer();
 
+#if PLATFORM(IOS)
+    // Called before the renderer's widget (if any) has been nulled out.
+    void willBeDestroyed();
+#endif
     String name() const;
 
     RenderLayerModelObject& renderer() const { return m_renderer; }
@@ -420,6 +424,27 @@ public:
     virtual Scrollbar* verticalScrollbar() const OVERRIDE { return m_vBar.get(); }
     virtual ScrollableArea* enclosingScrollableArea() const OVERRIDE;
 
+#if PLATFORM(IOS)
+#if ENABLE(TOUCH_EVENTS)
+    virtual bool handleTouchEvent(const PlatformTouchEvent&) OVERRIDE;
+    virtual bool isTouchScrollable() const OVERRIDE { return true; }
+#endif
+    virtual bool isOverflowScroll() const OVERRIDE { return true; }
+    
+    virtual void didStartScroll() OVERRIDE;
+    virtual void didEndScroll() OVERRIDE;
+    virtual void didUpdateScroll() OVERRIDE;
+    virtual void setIsUserScroll(bool isUserScroll) OVERRIDE { m_inUserScroll = isUserScroll; }
+
+    bool isInUserScroll() const { return m_inUserScroll; }
+
+    bool requiresScrollBoundsOriginUpdate() const { return m_requiresScrollBoundsOriginUpdate; }
+    void setRequiresScrollBoundsOriginUpdate(bool requiresUpdate = true) { m_requiresScrollBoundsOriginUpdate = requiresUpdate; }
+
+    bool hasAcceleratedTouchScrolling() const;
+
+#endif
+
     int verticalScrollbarWidth(OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
     int horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
 
@@ -728,6 +753,11 @@ public:
     void setStaticInlinePosition(LayoutUnit position) { m_staticInlinePosition = position; }
     void setStaticBlockPosition(LayoutUnit position) { m_staticBlockPosition = position; }
 
+#if PLATFORM(IOS)
+    bool adjustForIOSCaretWhenScrolling() const { return m_adjustForIOSCaretWhenScrolling; }
+    void setAdjustForIOSCaretWhenScrolling(bool adjustForIOSCaretWhenScrolling) { m_adjustForIOSCaretWhenScrolling = adjustForIOSCaretWhenScrolling; }
+#endif
+
     bool hasTransform() const { return renderer().hasTransform(); }
     // Note that this transform has the transform-origin baked in.
     TransformationMatrix* transform() const { return m_transform.get(); }
@@ -1044,6 +1074,11 @@ private:
     virtual IntRect scrollableAreaBoundingBox() const OVERRIDE;
     virtual bool updatesScrollLayerPositionOnMainThread() const OVERRIDE { return true; }
 
+#if PLATFORM(IOS)
+    void registerAsTouchEventListenerForScrolling();
+    void unregisterAsTouchEventListenerForScrolling();
+#endif
+
     // Rectangle encompassing the scroll corner and resizer rect.
     IntRect scrollCornerAndResizerRect() const;
 
@@ -1204,6 +1239,13 @@ private:
     unsigned m_viewportConstrainedNotCompositedReason : 2;
 #endif
 
+#if PLATFORM(IOS)
+    bool m_adjustForIOSCaretWhenScrolling : 1;
+    bool m_registeredAsTouchEventListenerForScrolling : 1;
+    bool m_inUserScroll : 1;
+    bool m_requiresScrollBoundsOriginUpdate : 1;
+#endif
+
     bool m_containsDirtyOverlayScrollbars : 1;
     bool m_updatingMarqueePosition : 1;
 
index cea6ab9..73c6d5f 100644 (file)
@@ -312,8 +312,11 @@ void RenderLayerBacking::createPrimaryGraphicsLayer()
         m_childContainmentLayer = createGraphicsLayer("TiledBacking Flattening Layer");
 
     if (m_isMainFrameRenderViewLayer) {
+#if !PLATFORM(IOS)
+        // Page scale is applied above the RenderView on iOS.
         m_graphicsLayer->setContentsOpaque(true);
         m_graphicsLayer->setAppliesPageScale();
+#endif
     }
 
 #if PLATFORM(MAC) && USE(CA)
@@ -334,6 +337,18 @@ void RenderLayerBacking::createPrimaryGraphicsLayer()
 #endif
 }
 
+#if PLATFORM(IOS)
+void RenderLayerBacking::layerWillBeDestroyed()
+{
+    RenderObject& renderer = this->renderer();
+    if (renderer.isEmbeddedObject() && toRenderEmbeddedObject(renderer).allowsAcceleratedCompositing()) {
+        PluginViewBase* pluginViewBase = toPluginViewBase(toRenderWidget(renderer).widget());
+        if (pluginViewBase && m_graphicsLayer->contentsLayerForMedia())
+            pluginViewBase->detachPluginLayer();
+    }
+}
+#endif
+
 void RenderLayerBacking::destroyGraphicsLayers()
 {
     if (m_graphicsLayer) {
@@ -395,27 +410,48 @@ static bool hasNonZeroTransformOrigin(const RenderObject& renderer)
         || (style.transformOriginY().type() == Fixed && style.transformOriginY().value());
 }
 
+#if PLATFORM(IOS)
+// FIXME: We should merge the concept of RenderLayer::{hasAcceleratedTouchScrolling, needsCompositedScrolling}()
+// so that we can remove this iOS-specific variant.
+static bool layerOrAncestorIsTransformedOrScrolling(RenderLayer& layer)
+{
+    for (RenderLayer* curr = &layer; curr; curr = curr->parent()) {
+        if (curr->hasTransform() || curr->hasAcceleratedTouchScrolling())
+            return true;
+    }
+
+    return false;
+}
+#else
 static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer& layer)
 {
     for (RenderLayer* curr = &layer; curr; curr = curr->parent()) {
         if (curr->hasTransform() || curr->needsCompositedScrolling())
             return true;
     }
-    
+
     return false;
 }
-
+#endif
+    
 bool RenderLayerBacking::shouldClipCompositedBounds() const
 {
+#if !PLATFORM(IOS)
     // Scrollbar layers use this layer for relative positioning, so don't clip.
     if (layerForHorizontalScrollbar() || layerForVerticalScrollbar())
         return false;
+#endif
 
     if (m_usingTiledCacheLayer)
         return false;
 
+#if !PLATFORM(IOS)
     if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(m_owningLayer))
         return false;
+#else
+    if (layerOrAncestorIsTransformedOrScrolling(m_owningLayer))
+        return false;
+#endif
 
     if (m_owningLayer.isFlowThreadCollectingGraphicsLayersUnderRegions())
         return false;
@@ -516,9 +552,15 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
     
     bool needsDescendentsClippingLayer = compositor().clipsCompositingDescendants(m_owningLayer);
 
+#if PLATFORM(IOS)
+    // Our scrolling layer will clip.
+    if (m_owningLayer.hasAcceleratedTouchScrolling())
+        needsDescendentsClippingLayer = false;
+#else
     // Our scrolling layer will clip.
     if (m_owningLayer.needsCompositedScrolling())
         needsDescendentsClippingLayer = false;
+#endif // PLATFORM(IOS)
 
     if (updateAncestorClippingLayer(compositor().clippedByAncestor(m_owningLayer)))
         layerConfigChanged = true;
@@ -529,8 +571,13 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
     if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
         layerConfigChanged = true;
 
+#if PLATFORM(IOS)
+    if (updateScrollingLayers(m_owningLayer.hasAcceleratedTouchScrolling()))
+        layerConfigChanged = true;
+#else
     if (updateScrollingLayers(m_owningLayer.needsCompositedScrolling()))
         layerConfigChanged = true;
+#endif // PLATFORM(IOS)
 
     if (layerConfigChanged)
         updateInternalHierarchy();
@@ -562,8 +609,15 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
 
     if (renderer().isEmbeddedObject() && toRenderEmbeddedObject(&renderer())->allowsAcceleratedCompositing()) {
         PluginViewBase* pluginViewBase = toPluginViewBase(toRenderWidget(&renderer())->widget());
+#if PLATFORM(IOS)
+        if (pluginViewBase && !m_graphicsLayer->contentsLayerForMedia()) {
+            pluginViewBase->detachPluginLayer();
+            pluginViewBase->attachPluginLayer();
+        }
+#else
         if (!pluginViewBase->shouldNotAddLayer())
             m_graphicsLayer->setContentsToMedia(pluginViewBase->platformLayer());
+#endif
     }
 #if ENABLE(VIDEO)
     else if (renderer().isVideo()) {
@@ -669,6 +723,18 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
     else
         graphicsLayerParentLocation = renderer().view().documentRect().location();
 
+#if PLATFORM(IOS)
+    if (compAncestor && compAncestor->hasAcceleratedTouchScrolling()) {
+        RenderBox* renderBox = toRenderBox(&compAncestor->renderer());
+        IntRect paddingBox(renderBox->borderLeft(), renderBox->borderTop(),
+            renderBox->width() - renderBox->borderLeft() - renderBox->borderRight(),
+            renderBox->height() - renderBox->borderTop() - renderBox->borderBottom());
+
+        IntSize scrollOffset = compAncestor->scrolledContentOffset();
+        graphicsLayerParentLocation = paddingBox.location() - scrollOffset;
+    }
+#endif
+
     if (compAncestor && compAncestor->needsCompositedScrolling()) {
         RenderBox& renderBox = toRenderBox(compAncestor->renderer());
         IntSize scrollOffset = compAncestor->scrolledContentOffset();
@@ -822,6 +888,35 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
         m_scrollingLayer->setPosition(FloatPoint(paddingBox.location() - localCompositingBounds.location()));
 
         m_scrollingLayer->setSize(paddingBox.size());
+#if PLATFORM(IOS)
+        IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
+        m_scrollingLayer->setOffsetFromRenderer(IntPoint() - paddingBox.location());
+        bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
+
+        if (m_owningLayer.isInUserScroll()) {
+            // If scrolling is happening externally, we don't want to touch the layer bounds origin here because that will cause
+            // jitter. Set a flag to ensure that we sync up later.
+            m_owningLayer.setRequiresScrollBoundsOriginUpdate(true);
+        } else {
+            // Note that we implement the contents offset via the bounds origin on this layer, rather than a position on the sublayer.
+            m_scrollingLayer->setBoundsOrigin(FloatPoint(scrollOffset.width(), scrollOffset.height()));
+            m_owningLayer.setRequiresScrollBoundsOriginUpdate(false);
+        }
+        
+        IntSize scrollSize(m_owningLayer.scrollWidth(), m_owningLayer.scrollHeight());
+
+        m_scrollingContentsLayer->setPosition(FloatPoint());
+        
+        if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged)
+            m_scrollingContentsLayer->setNeedsDisplay();
+
+        m_scrollingContentsLayer->setSize(scrollSize);
+        // Scrolling the content layer does not need to trigger a repaint. The offset will be compensated away during painting.
+        // FIXME: The paint offset and the scroll offset should really be separate concepts.
+        m_scrollingContentsLayer->setOffsetFromRenderer(paddingBox.location() - IntPoint() - scrollOffset, GraphicsLayer::DontSetNeedsDisplay);
+        
+        compositor().scrollingLayerAddedOrUpdated(&m_owningLayer);
+#else
         m_scrollingContentsLayer->setPosition(FloatPoint(-scrollOffset.width(), -scrollOffset.height()));
 
         IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
@@ -840,6 +935,7 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
         m_scrollingContentsLayer->setSize(scrollSize);
         // FIXME: The paint offset and the scroll offset should really be separate concepts.
         m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
+#endif
 
         if (m_foregroundLayer) {
             m_foregroundLayer->setSize(m_scrollingContentsLayer->size());
@@ -909,6 +1005,9 @@ void RenderLayerBacking::updateDirectlyCompositedContents(bool isSimpleContainer
 
 void RenderLayerBacking::registerScrollingLayers()
 {
+#if PLATFORM(IOS)
+    compositor().updateViewportConstraintStatus(m_owningLayer);
+#else
     // Register fixed position layers and their containers with the scrolling coordinator.
     ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
     if (!scrollingCoordinator)
@@ -924,6 +1023,7 @@ void RenderLayerBacking::registerScrollingLayers()
     // layer as a container.
     bool isContainer = m_owningLayer.hasTransform() && !m_owningLayer.isRootLayer();
     scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(childForSuperlayers(), isContainer);
+#endif
 }
 
 void RenderLayerBacking::updateInternalHierarchy()
@@ -1320,8 +1420,16 @@ bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
             layerChanged = true;
             if (scrollingCoordinator)
                 scrollingCoordinator->scrollableAreaScrollLayerDidChange(&m_owningLayer);
+#if PLATFORM(IOS)
+            if (m_owningLayer.parent())
+                compositor().scrollingLayerAddedOrUpdated(&m_owningLayer);
+#endif
         }
     } else if (m_scrollingLayer) {
+#if PLATFORM(IOS)
+        if (!renderer().documentBeingDestroyed())
+            compositor().scrollingLayerRemoved(&m_owningLayer, m_scrollingLayer->platformLayer(), m_scrollingContentsLayer->platformLayer());
+#endif
         willDestroyLayer(m_scrollingLayer.get());
         willDestroyLayer(m_scrollingContentsLayer.get());
         m_scrollingLayer = nullptr;
@@ -1334,8 +1442,10 @@ bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
     if (layerChanged) {
         updateInternalHierarchy();
         m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
+#if !PLATFORM(IOS)
         m_graphicsLayer->setNeedsDisplay();
         compositor().scrollingLayerDidChange(m_owningLayer);
+#endif
     }
 
     return layerChanged;
@@ -1725,8 +1835,8 @@ bool RenderLayerBacking::containsPaintedContent(bool isSimpleContainer) const
     if (renderer().isVideo() && toRenderVideo(renderer()).shouldDisplayVideo())
         return m_owningLayer.hasBoxDecorationsOrBackground();
 #endif
-#if PLATFORM(MAC) && USE(CA)
-#elif ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
+#if PLATFORM(MAC) && !PLATFORM(IOS) && USE(CA)
+#elif ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) || PLATFORM(IOS_SIMULATOR)
     if (isAcceleratedCanvas(&renderer()))
         return m_owningLayer.hasBoxDecorationsOrBackground();
 #endif
@@ -1903,7 +2013,14 @@ GraphicsLayer* RenderLayerBacking::parentForSublayers() const
     if (m_scrollingContentsLayer)
         return m_scrollingContentsLayer.get();
 
+#if PLATFORM(IOS)
+    // FIXME: Can we remove this iOS-specific code path?
+    if (GraphicsLayer* clippingLayer = this->clippingLayer())
+        return clippingLayer;
+    return m_graphicsLayer.get();
+#else
     return m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
+#endif
 }
 
 GraphicsLayer* RenderLayerBacking::childForSuperlayers() const
@@ -1923,7 +2040,7 @@ bool RenderLayerBacking::paintsIntoWindow() const
         return false;
 
     if (m_owningLayer.isRootLayer()) {
-#if PLATFORM(BLACKBERRY) || USE(COORDINATED_GRAPHICS)
+#if PLATFORM(BLACKBERRY) || PLATFORM(IOS) || USE(COORDINATED_GRAPHICS)
         if (compositor().inForcedCompositingMode())
             return false;
 #endif
@@ -2016,6 +2133,10 @@ void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
     if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) {
         IntRect layerDirtyRect = r;
         layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer());
+#if PLATFORM(IOS)
+        // Account for the fact that RenderLayerBacking::updateGraphicsLayerGeometry() bakes scrollOffset into offsetFromRenderer on iOS.
+        layerDirtyRect.move(-m_owningLayer.scrollOffset());
+#endif
         m_scrollingContentsLayer->setNeedsDisplayInRect(layerDirtyRect);
     }
 }
@@ -2025,7 +2146,12 @@ void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, Grap
                     PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase)
 {
     if (paintsIntoWindow() || paintsIntoCompositedAncestor()) {
+#if !PLATFORM(IOS)
+        // FIXME: Looks like the CALayer tree is out of sync with the GraphicsLayer heirarchy
+        // when pages are restored from the PageCache.
+        // <rdar://problem/8712587> ASSERT: When Going Back to Page with Plugins in PageCache
         ASSERT_NOT_REACHED();
+#endif
         return;
     }
 
index 24a3afb..6179687 100644 (file)
@@ -60,6 +60,10 @@ public:
     explicit RenderLayerBacking(RenderLayer&);
     ~RenderLayerBacking();
 
+#if PLATFORM(IOS)
+    void layerWillBeDestroyed();
+#endif
+
     RenderLayer& owningLayer() const { return m_owningLayer; }
 
     enum UpdateAfterLayoutFlag {
index 1c6228c..2cb6719 100644 (file)
 #include <wtf/text/CString.h>
 #include <wtf/text/StringBuilder.h>
 
+#if PLATFORM(IOS)
+#include "Region.h"
+#include "RenderScrollbar.h"
+#include "TileCache.h"
+#endif
+
 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
 #include "HTMLAudioElement.h"
 #include "HTMLMediaElement.h"
@@ -88,7 +94,12 @@ namespace WebCore {
 
 static const int canvasAreaThresholdRequiringCompositing = 50 * 100;
 // During page loading delay layer flushes up to this many seconds to allow them coalesce, reducing workload.
+#if PLATFORM(IOS)
+static const double throttledLayerFlushInitialDelay = .5;
+static const double throttledLayerFlushDelay = 1.5;
+#else
 static const double throttledLayerFlushDelay = .5;
+#endif
 
 using namespace HTMLNames;
 
@@ -360,6 +371,11 @@ void RenderLayerCompositor::scheduleLayerFlush(bool canThrottle)
 {
     ASSERT(!m_flushingLayers);
 
+#if PLATFORM(IOS)
+    if (canThrottle)
+        startInitialLayerFlushTimerIfNeeded();
+#endif
+
     if (canThrottle && isThrottlingLayerFlushes()) {
         m_hasPendingLayerFlush = true;
         return;
@@ -367,6 +383,16 @@ void RenderLayerCompositor::scheduleLayerFlush(bool canThrottle)
     scheduleLayerFlushNow();
 }
 
+#if PLATFORM(IOS)
+ChromeClient* RenderLayerCompositor::chromeClient() const
+{
+    Page* page = m_renderView.frameView().frame().page();
+    if (!page)
+        return 0;
+    return &page->chrome().client();
+}
+#endif
+
 void RenderLayerCompositor::flushPendingLayerChanges(bool isFlushRoot)
 {
     // FrameView::flushCompositingStateIncludingSubframes() flushes each subframe,
@@ -377,6 +403,9 @@ void RenderLayerCompositor::flushPendingLayerChanges(bool isFlushRoot)
         return;
     
     if (rootLayerAttachment() == RootLayerUnattached) {
+#if PLATFORM(IOS)
+        startLayerFlushTimerIfNeeded();
+#endif
         m_shouldFlushOnReattach = true;
         return;
     }
@@ -388,26 +417,82 @@ void RenderLayerCompositor::flushPendingLayerChanges(bool isFlushRoot)
     m_flushingLayers = true;
 
     if (GraphicsLayer* rootLayer = rootGraphicsLayer()) {
+#if PLATFORM(IOS)
+        rootLayer->flushCompositingState(frameView.visibleExtentContentRect());
+#else
         // Having a m_clipLayer indicates that we're doing scrolling via GraphicsLayers.
         IntRect visibleRect = m_clipLayer ? IntRect(IntPoint(), frameView.contentsSize()) : frameView.visibleContentRect();
         rootLayer->flushCompositingState(visibleRect);
+#endif
     }
     
     ASSERT(m_flushingLayers);
     m_flushingLayers = false;
 
+#if PLATFORM(IOS)
+    updateCustomLayersAfterFlush();
+
+    ChromeClient* client = this->chromeClient();
+    if (client && isFlushRoot)
+        client->didFlushCompositingLayers();
+#else
     for (auto it = m_viewportConstrainedLayersNeedingUpdate.begin(), end = m_viewportConstrainedLayersNeedingUpdate.end(); it != end; ++it)
         registerOrUpdateViewportConstrainedLayer(**it);
     m_viewportConstrainedLayersNeedingUpdate.clear();
-
+#endif
     startLayerFlushTimerIfNeeded();
 }
 
+#if PLATFORM(IOS)
+static bool scrollbarHasDisplayNone(Scrollbar* scrollbar)
+{
+    if (!scrollbar || !scrollbar->isCustomScrollbar())
+        return false;
+
+    RefPtr<RenderStyle> scrollbarStyle = static_cast<RenderScrollbar*>(scrollbar)->getScrollbarPseudoStyle(ScrollbarBGPart, SCROLLBAR);
+    return scrollbarStyle && scrollbarStyle->display() == NONE;
+}
+
+// FIXME: Can we make |layer| const RenderLayer&?
+static void updateScrollingLayerWithClient(RenderLayer& layer, ChromeClient* client)
+{
+    if (!client)
+        return;
+
+    RenderLayerBacking* backing = layer->backing();
+    ASSERT(backing);
+
+    bool allowHorizontalScrollbar = !scrollbarHasDisplayNone(layer->horizontalScrollbar());
+    bool allowVerticalScrollbar = !scrollbarHasDisplayNone(layer->verticalScrollbar());
+    client->addOrUpdateScrollingLayer(layer->renderer().element(), backing->scrollingLayer()->platformLayer(), backing->scrollingContentsLayer()->platformLayer(),
+        IntSize(layer->scrollWidth(), layer->scrollHeight()), allowHorizontalScrollbar, allowVerticalScrollbar);
+}
+
+void RenderLayerCompositor::updateCustomLayersAfterFlush()
+{
+    registerAllViewportConstrainedLayers();
+
+    if (!m_scrollingLayersNeedingUpdate.isEmpty()) {
+        ChromeClient* chromeClient = this->chromeClient();
+
+        for (auto it = m_scrollingLayersNeedingUpdate.begin(), end = m_scrollingLayersNeedingUpdate.end(); it != end; ++it)
+            updateScrollingLayerWithClient(**it, chromeClient);
+        m_scrollingLayersNeedingUpdate.clear();
+    }
+    m_scrollingLayersNeedingUpdate.clear();
+}
+#endif
+
 void RenderLayerCompositor::didFlushChangesForLayer(RenderLayer& layer, const GraphicsLayer* graphicsLayer)
 {
     if (m_viewportConstrainedLayers.contains(&layer))
         m_viewportConstrainedLayersNeedingUpdate.add(&layer);
 
+#if PLATFORM(IOS)
+    if (m_scrollingLayers.contains(&layer))
+        m_scrollingLayersNeedingUpdate.add(&layer);
+#endif
+
     RenderLayerBacking* backing = layer.backing();
     if (backing->backgroundLayerPaintsFixedRootBackground() && graphicsLayer == backing->backgroundLayer())
         fixedRootBackgroundLayerChanged();
@@ -428,7 +513,12 @@ void RenderLayerCompositor::didChangeVisibleRect()
         return;
 
     const FrameView& frameView = m_renderView.frameView();
+
+#if PLATFORM(IOS)
+    IntRect visibleRect = frameView.visibleExtentContentRect();
+#else
     IntRect visibleRect = m_clipLayer ? IntRect(IntPoint(), frameView.contentsSize()) : frameView.visibleContentRect();
+#endif
     if (!rootLayer->visibleRectChangeRequiresFlush(visibleRect))
         return;
     scheduleLayerFlushNow();
@@ -877,9 +967,14 @@ void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer&
     }
 
     IntRect clipRect = pixelSnappedIntRect(layer.backgroundClipRect(RenderLayer::ClipRectsContext(&rootRenderLayer(), 0, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
+
+    // On iOS, pageScaleFactor() is not applied by RenderView, so we should not scale here.
+    // FIXME: Set Settings::delegatesPageScaling to true for iOS.
+#if !PLATFORM(IOS)
     const Settings& settings = m_renderView.frameView().frame().settings();
     if (!settings.delegatesPageScaling())
         clipRect.scale(pageScaleFactor());
+#endif
     clipRect.intersect(layerBounds);
     overlapMap.add(&layer, clipRect);
 }
@@ -1119,8 +1214,11 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestor
     // to be composited, then we can drop out of compositing mode altogether. However, don't drop out of compositing mode
     // if there are composited layers that we didn't hit in our traversal (e.g. because of visibility:hidden).
     if (layer.isRootLayer() && !childState.m_subtreeIsCompositing && !requiresCompositingLayer(layer) && !m_forceCompositingMode && !hasAnyAdditionalCompositedLayers(layer)) {
+        // Don't drop out of compositing on iOS, because we may flash. See <rdar://problem/8348337>.
+#if !PLATFORM(IOS)
         enableCompositingMode(false);
         willBeComposited = false;
+#endif
     }
     
     // If the layer is going into compositing mode, repaint its old location.
@@ -1699,11 +1797,19 @@ void RenderLayerCompositor::setIsInWindow(bool isInWindow)
 
         RootLayerAttachment attachment = shouldPropagateCompositingToEnclosingFrame() ? RootLayerAttachedViaEnclosingFrame : RootLayerAttachedViaChromeClient;
         attachRootLayer(attachment);
+#if PLATFORM(IOS)
+        registerAllViewportConstrainedLayers();
+        registerAllScrollingLayers();
+#endif
     } else {
         if (m_rootLayerAttachment == RootLayerUnattached)
             return;
 
         detachRootLayer();
+#if PLATFORM(IOS)
+        unregisterAllViewportConstrainedLayers();
+        unregisterAllScrollingLayers();
+#endif
     }
 }
 
@@ -1758,7 +1864,7 @@ bool RenderLayerCompositor::has3DContent() const
 
 bool RenderLayerCompositor::allowsIndependentlyCompositedFrames(const FrameView* view)
 {
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) && !PLATFORM(IOS)
     // frames are only independently composited in Mac pre-WebKit2.
     return view->platformWidget();
 #else
@@ -1832,6 +1938,9 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer& layer, R
         || requiresCompositingForAnimation(*renderer)
         || requiresCompositingForFilters(*renderer)
         || requiresCompositingForPosition(*renderer, *renderer->layer(), viewportConstrainedNotCompositedReason)
+#if PLATFORM(IOS)
+        || requiresCompositingForScrolling(*renderer)
+#endif
         || requiresCompositingForOverflowScrolling(*renderer->layer())
         || requiresCompositingForBlending(*renderer);
 }
@@ -1878,7 +1987,11 @@ bool RenderLayerCompositor::requiresOwnBackingStore(const RenderLayer& layer, co
         || renderer.isTransparent()
         || renderer.hasMask()
         || renderer.hasReflection()
-        || renderer.hasFilter())
+        || renderer.hasFilter()
+#if PLATFORM(IOS)
+        || requiresCompositingForScrolling(renderer)
+#endif
+        )
         return true;
         
     
@@ -1935,6 +2048,11 @@ CompositingReasons RenderLayerCompositor::reasonsForCompositing(const RenderLaye
     if (requiresCompositingForPosition(*renderer, *renderer->layer()))
         reasons |= renderer->style().position() == FixedPosition ? CompositingReasonPositionFixed : CompositingReasonPositionSticky;
 
+#if PLATFORM(IOS)
+    if (requiresCompositingForScrolling(*renderer))
+        reasons |= CompositingReasonOverflowScrollingTouch;
+#endif
+
     if (requiresCompositingForOverflowScrolling(*renderer->layer()))
         reasons |= CompositingReasonOverflowScrollingTouch;
 
@@ -2217,10 +2335,10 @@ bool RenderLayerCompositor::requiresCompositingForAnimation(RenderLayerModelObje
     return (animController.isRunningAnimationOnRenderer(&renderer, CSSPropertyOpacity)
             && (inCompositingMode() || (m_compositingTriggers & ChromeClient::AnimatedOpacityTrigger)))
 #if ENABLE(CSS_FILTERS)
-#if !PLATFORM(MAC) || (!PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080)
+#if PLATFORM(IOS) || !PLATFORM(MAC) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
             // <rdar://problem/10907251> - WebKit2 doesn't support CA animations of CI filters on Lion and below
             || animController.isRunningAnimationOnRenderer(&renderer, CSSPropertyWebkitFilter)
-#endif // !PLATFORM(MAC) || (!PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080)
+#endif // PLATFORM(IOS) || !PLATFORM(MAC) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
 #endif // CSS_FILTERS
             || animController.isRunningAnimationOnRenderer(&renderer, CSSPropertyWebkitTransform);
 }
@@ -2254,6 +2372,13 @@ bool RenderLayerCompositor::requiresCompositingForIndirectReason(RenderLayerMode
     return false;
 }
 
+#if PLATFORM(IOS)
+bool RenderLayerCompositor::requiresCompositingForScrolling(RenderLayerModelObject& renderer) const
+{
+    return renderer.hasLayer() && toRenderBoxModelObject(renderer).layer()->hasAcceleratedTouchScrolling();
+}
+#endif
+
 bool RenderLayerCompositor::requiresCompositingForFilters(RenderLayerModelObject& renderer) const
 {
 #if ENABLE(CSS_FILTERS)
@@ -2277,10 +2402,31 @@ bool RenderLayerCompositor::requiresCompositingForBlending(RenderLayerModelObjec
 #endif
 }
 
+#if PLATFORM(IOS)
+static bool isStickyInAcceleratedScrollingLayerOrViewport(const RenderLayer& layer, const RenderLayer** enclosingAcceleratedOverflowLayer = 0)
+{
+    ASSERT(layer.renderer().isStickyPositioned());
+
+    RenderLayer* enclosingOverflowLayer = layer.enclosingOverflowClipLayer(ExcludeSelf);
+    if (enclosingOverflowLayer && enclosingOverflowLayer->hasAcceleratedTouchScrolling()) {
+        if (enclosingAcceleratedOverflowLayer)
+            *enclosingAcceleratedOverflowLayer = enclosingOverflowLayer;
+        return true;
+    }
+
+    return !enclosingOverflowLayer;
+}
+#endif
+
 static bool isViewportConstrainedFixedOrStickyLayer(const RenderLayer& layer)
 {
+#if PLATFORM(IOS)
+    if (layer.renderer().isStickyPositioned())
+        return isStickyInAcceleratedScrollingLayerOrViewport(layer);
+#else
     if (layer.renderer().isStickyPositioned())
         return !layer.enclosingOverflowClipLayer(ExcludeSelf);
+#endif
 
     if (layer.renderer().style().position() != FixedPosition)
         return false;
@@ -2295,6 +2441,21 @@ static bool isViewportConstrainedFixedOrStickyLayer(const RenderLayer& layer)
 
 bool RenderLayerCompositor::requiresCompositingForPosition(RenderLayerModelObject& renderer, const RenderLayer& layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const
 {
+#if PLATFORM(IOS)
+    if (renderer.isStickyPositioned())
+        return true;
+
+    // position:fixed elements that create their own stacking context (e.g. have an explicit z-index,
+    // opacity, transform) can get their own composited layer. A stacking context is required otherwise
+    // z-index and clipping will be broken.
+    if (!(renderer.isOutOfFlowPositioned() && renderer.style().position() == FixedPosition))
+        return false;
+
+    if (!m_renderView.hasCustomFixedPosition(renderer, RenderView::CheckContainingBlock)) {
+        m_reevaluateCompositingAfterLayout = true;
+        return false;
+    }
+#else
     // position:fixed elements that create their own stacking context (e.g. have an explicit z-index,
     // opacity, transform) can get their own composited layer. A stacking context is required otherwise
     // z-index and clipping will be broken.
@@ -2317,6 +2478,7 @@ bool RenderLayerCompositor::requiresCompositingForPosition(RenderLayerModelObjec
 
     if (isSticky)
         return hasCoordinatedScrolling() && isViewportConstrainedFixedOrStickyLayer(layer);
+#endif
 
     auto container = renderer.container();
     // If the renderer is not hooked up yet then we have to wait until it is.
@@ -2347,7 +2509,11 @@ bool RenderLayerCompositor::requiresCompositingForPosition(RenderLayerModelObjec
     }
 
     // Fixed position elements that are invisible in the current view don't get their own layer.
+#if PLATFORM(IOS)
+    LayoutRect viewBounds = m_renderView.frameView().customFixedPositionLayoutRect();
+#else
     LayoutRect viewBounds = m_renderView.frameView().viewportConstrainedVisibleContentRect();
+#endif
     LayoutRect layerBounds = layer.calculateLayerBounds(&layer, 0, RenderLayer::UseLocalClipRectIfPossible | RenderLayer::IncludeLayerFilterOutsets | RenderLayer::UseFragmentBoxes
         | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask | RenderLayer::IncludeCompositedDescendants);
     // Map to m_renderView to ignore page scale.
@@ -2495,6 +2661,16 @@ float RenderLayerCompositor::pageScaleFactor() const
 
 float RenderLayerCompositor::contentsScaleMultiplierForNewTiles(const GraphicsLayer*) const
 {
+#if PLATFORM(IOS)
+    TileCache* tileCache = nullptr;
+    if (Page* page = this->page())
+        tileCache = page->mainFrame().view().tileCache();
+
+    if (!tileCache)
+        return 1;
+
+    return tileCache->tilingMode() == TileCache::Zooming ? 0.125 : 1;
+#endif
     return 1;
 }
 
@@ -2869,6 +3045,14 @@ void RenderLayerCompositor::ensureRootLayer()
         m_rootContentLayer->setSize(FloatSize(overflowRect.maxX(), overflowRect.maxY()));
         m_rootContentLayer->setPosition(FloatPoint());
 
+#if PLATFORM(IOS)
+        // Page scale is applied above this on iOS, so we'll just say that our root layer applies it.
+        Frame& frame = m_renderView.frameView().frame();
+        Page* page = frame.page();
+        if (page && &page->mainFrame() == &frame)
+            m_rootContentLayer->setAppliesPageScale();
+#endif
+
         // Need to clip to prevent transformed content showing outside this frame
         m_rootContentLayer->setMasksToBounds(true);
     }
@@ -3149,7 +3333,11 @@ FixedPositionViewportConstraints RenderLayerCompositor::computeFixedViewportCons
 {
     ASSERT(layer.isComposited());
 
+#if PLATFORM(IOS)
+    LayoutRect viewportRect = m_renderView.frameView().customFixedPositionLayoutRect();
+#else
     LayoutRect viewportRect = m_renderView.frameView().viewportConstrainedVisibleContentRect();
+#endif
 
     FixedPositionViewportConstraints constraints;
 
@@ -3185,10 +3373,17 @@ FixedPositionViewportConstraints RenderLayerCompositor::computeFixedViewportCons
 StickyPositionViewportConstraints RenderLayerCompositor::computeStickyViewportConstraints(RenderLayer& layer) const
 {
     ASSERT(layer.isComposited());
+#if !PLATFORM(IOS)
     // We should never get here for stickies constrained by an enclosing clipping layer.
+    // FIXME: Why does this assertion fail on iOS?
     ASSERT(!layer.enclosingOverflowClipLayer(ExcludeSelf));
+#endif
 
+#if PLATFORM(IOS)
+    LayoutRect viewportRect = m_renderView.frameView().customFixedPositionLayoutRect();
+#else
     LayoutRect viewportRect = m_renderView.frameView().viewportConstrainedVisibleContentRect();
+#endif
 
     RenderBoxModelObject& renderer = toRenderBoxModelObject(layer.renderer());
 
@@ -3203,6 +3398,7 @@ StickyPositionViewportConstraints RenderLayerCompositor::computeStickyViewportCo
     return constraints;
 }
 
+#if !PLATFORM(IOS)
 static RenderLayerBacking* nearestScrollingCoordinatorAncestor(RenderLayer& layer)
 {
     RenderLayer* ancestor = layer.parent();
@@ -3216,9 +3412,14 @@ static RenderLayerBacking* nearestScrollingCoordinatorAncestor(RenderLayer& laye
 
     return nullptr;
 }
+#endif
 
 void RenderLayerCompositor::registerOrUpdateViewportConstrainedLayer(RenderLayer& layer)
 {
+#if PLATFORM(IOS)
+    UNUSED_PARAM(layer);
+    // On iOS, we batch-update viewport-constrained layers in updateCustomLayersAfterFlush().
+#else
     // FIXME: We should support sticky position here! And we should eventuall support fixed/sticky elements
     // that are inside non-main frames once we get non-main frames scrolling with the ScrollingCoordinator.
     if (m_renderView.document().ownerElement())
@@ -3252,16 +3453,113 @@ void RenderLayerCompositor::registerOrUpdateViewportConstrainedLayer(RenderLayer
         scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeStickyViewportConstraints(layer), backing->graphicsLayer());
     else
         scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeFixedViewportConstraints(layer), backing->graphicsLayer());
+#endif
 }
 
 void RenderLayerCompositor::unregisterViewportConstrainedLayer(RenderLayer& layer)
 {
     ASSERT(m_viewportConstrainedLayers.contains(&layer));
-
+#if PLATFORM(IOS)
+    UNUSED_PARAM(layer);
+    // On iOS, we batch-update viewport-constrained layers in updateCustomLayersAfterFlush().
+#else
     if (RenderLayerBacking* backing = layer.backing())
         backing->detachFromScrollingCoordinator();
+#endif
 }
 
+#if PLATFORM(IOS)
+typedef HashMap<PlatformLayer*, std::unique_ptr<ViewportConstraints>> LayerMap;
+typedef HashMap<PlatformLayer*, PlatformLayer*> StickyContainerMap;
+
+void RenderLayerCompositor::registerAllViewportConstrainedLayers()
+{
+    // Only the main frame should register fixed/sticky layers.
+    if (m_renderView.document().ownerElement())
+        return;
+
+    LayerMap layerMap;
+    StickyContainerMap stickyContainerMap;
+
+    for (auto it = m_viewportConstrainedLayers.begin(), end = m_viewportConstrainedLayers.end(); it != end; ++it) {
+        RenderLayer& layer = **it;
+        ASSERT(layer.isComposited());
+
+        std::unique_ptr<ViewportConstraints> constraints;
+        if (layer.renderer().isStickyPositioned()) {
+            constraints = std::make_unique<ViewportConstraints>(new StickyPositionViewportConstraints(computeStickyViewportConstraints(layer)));
+            const RenderLayer* enclosingTouchScrollableLayer = nullptr;
+            if (isStickyInAcceleratedScrollingLayerOrViewport(layer, &enclosingTouchScrollableLayer) && enclosingTouchScrollableLayer) {
+                ASSERT(enclosingTouchScrollableLayer->isComposited());
+                stickyContainerMap.add(layer.backing()->graphicsLayer()->platformLayer(), enclosingTouchScrollableLayer->backing()->scrollingLayer()->platformLayer());
+            }
+        } else
+            constraints = std::make_unique<ViewportConstraints>(new FixedPositionViewportConstraints(computeFixedViewportConstraints(layer)));
+
+        layerMap.add(layer.backing()->graphicsLayer()->platformLayer(), constraints.release());
+    }
+    
+    if (ChromeClient* client = this->chromeClient())
+        client->updateViewportConstrainedLayers(layerMap, stickyContainerMap);
+}
+
+void RenderLayerCompositor::unregisterAllViewportConstrainedLayers()
+{
+    // Only the main frame should register fixed/sticky layers.
+    if (m_renderView.document().ownerElement())
+        return;
+
+    if (ChromeClient* client = this->chromeClient()) {
+        LayerMap layerMap;
+        StickyContainerMap stickyContainerMap;
+        client->updateViewportConstrainedLayers(layerMap, stickyContainerMap);
+    }
+}
+
+void RenderLayerCompositor::registerAllScrollingLayers()
+{
+    ChromeClient* client = this->chromeClient();
+    if (!client)
+        return;
+
+    for (auto it = m_scrollingLayers.begin(), end = m_scrollingLayers.end(); it != end; ++it)
+        updateScrollingLayerWithClient(**it, client);
+}
+
+void RenderLayerCompositor::unregisterAllScrollingLayers()
+{
+    ChromeClient* client = this->chromeClient();
+    if (!client)
+        return;
+
+    for (auto it = m_scrollingLayers.begin(), end = m_scrollingLayers.end(); it != end; ++it) {
+        RenderLayer& layer = **it;
+        RenderLayerBacking* backing = layer.backing();
+        ASSERT(backing);
+        client->removeScrollingLayer(layer.renderer().element(), backing->scrollingLayer()->platformLayer(), backing->scrollingContentsLayer()->platformLayer());
+    }
+}
+
+// Called when the size of the contentsLayer changes, and when the contentsLayer is replaced by another layer.
+void RenderLayerCompositor::scrollingLayerAddedOrUpdated(RenderLayer* layer)
+{
+    ASSERT(!m_renderView.document().inPageCache());
+    m_scrollingLayers.add(layer);
+}
+
+void RenderLayerCompositor::scrollingLayerRemoved(RenderLayer* layer, PlatformLayer* scrollingLayer, PlatformLayer* contentsLayer)
+{
+    m_scrollingLayersNeedingUpdate.remove(layer);
+    m_scrollingLayers.remove(layer);
+
+    if (m_renderView.document().inPageCache())
+        return;
+
+    if (ChromeClient* client = this->chromeClient())
+        client->removeScrollingLayer(layer->renderer().element(), scrollingLayer, contentsLayer);
+}
+#endif
+
 void RenderLayerCompositor::windowScreenDidChange(PlatformDisplayID displayID)
 {
     if (m_layerUpdater)
@@ -3327,6 +3625,17 @@ void RenderLayerCompositor::startLayerFlushTimerIfNeeded()
     m_layerFlushTimer.startOneShot(throttledLayerFlushDelay);
 }
 
+#if PLATFORM(IOS)
+void RenderLayerCompositor::startInitialLayerFlushTimerIfNeeded()
+{
+    if (!m_layerFlushThrottlingEnabled)
+        return;
+    if (m_layerFlushTimer.isActive())
+        return;
+    m_layerFlushTimer.startOneShot(throttledLayerFlushInitialDelay);
+}
+#endif
+
 void RenderLayerCompositor::layerFlushTimerFired(Timer<RenderLayerCompositor>*)
 {
     if (!m_hasPendingLayerFlush)
index 93493c2..2616a76 100644 (file)
@@ -273,6 +273,16 @@ public:
     void updateViewportConstraintStatus(RenderLayer&);
     void removeViewportConstrainedLayer(RenderLayer&);
 
+#if PLATFORM(IOS)
+    void registerAllViewportConstrainedLayers();
+    void unregisterAllViewportConstrainedLayers();
+
+    void scrollingLayerAddedOrUpdated(RenderLayer*);
+    void scrollingLayerRemoved(RenderLayer*, PlatformLayer* scrollingLayer, PlatformLayer* contentsLayer);
+
+    void registerAllScrollingLayers();
+    void unregisterAllScrollingLayers();
+#endif
     void resetTrackedRepaintRects();
     void setTracksRepaints(bool);
 
@@ -383,6 +393,16 @@ private:
     bool requiresCompositingForOverflowScrolling(const RenderLayer&) const;
     bool requiresCompositingForIndirectReason(RenderLayerModelObject&, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason&) const;
 
+#if PLATFORM(IOS)
+    bool requiresCompositingForScrolling(RenderLayerModelObject&) const;
+
+    void updateCustomLayersAfterFlush();
+
+    ChromeClient* chromeClient() const;
+
+    void startInitialLayerFlushTimerIfNeeded();
+#endif
+
     void addViewportConstrainedLayer(RenderLayer&);
     void registerOrUpdateViewportConstrainedLayer(RenderLayer&);
     void unregisterViewportConstrainedLayer(RenderLayer&);
@@ -450,6 +470,10 @@ private:
     std::unique_ptr<GraphicsLayer> m_clipLayer;
     std::unique_ptr<GraphicsLayer> m_scrollLayer;
 
+#if PLATFORM(IOS)
+    HashSet<RenderLayer*> m_scrollingLayers;
+    HashSet<RenderLayer*> m_scrollingLayersNeedingUpdate;
+#endif
     HashSet<RenderLayer*> m_viewportConstrainedLayers;
     HashSet<RenderLayer*> m_viewportConstrainedLayersNeedingUpdate;
 
index d257e39..e95f3bf 100644 (file)
@@ -89,7 +89,16 @@ private:
 
     static HashMap<const RenderLayer*, OwnPtr<FilterInfo>>& map();
 
+#if PLATFORM(IOS)
+#pragma clang diagnostic push
+#if defined(__has_warning) && __has_warning("-Wunused-private-field")
+#pragma clang diagnostic ignored "-Wunused-private-field"
+#endif
+#endif
     RenderLayer& m_layer;
+#if PLATFORM(IOS)
+#pragma clang diagnostic pop
+#endif
 
     RefPtr<FilterEffectRenderer> m_renderer;
     LayoutRect m_dirtySourceRect;
index 134ba9f..b612b5a 100644 (file)
 #include "TextRun.h"
 #include <math.h>
 
+#if PLATFORM(IOS)
+#include "LocalizedStrings.h"
+#endif
+
 namespace WebCore {
 
 using namespace HTMLNames;
 
+#if PLATFORM(IOS)
+static size_t selectedOptionCount(const RenderMenuList& renderMenuList)
+{
+    const Vector<HTMLElement*>& listItems = renderMenuList.selectElement().listItems();
+    size_t numberOfItems = listItems.size();
+
+    size_t count = 0;
+    for (size_t i = 0; i < numberOfItems; ++i) {
+        if (listItems[i]->hasTagName(optionTag) && toHTMLOptionElement(listItems[i])->selected())
+            ++count;
+    }
+    return count;
+}
+#endif
+
 RenderMenuList::RenderMenuList(HTMLSelectElement& element, PassRef<RenderStyle> style)
     : RenderFlexibleBox(element, std::move(style))
     , m_buttonText(nullptr)
@@ -59,15 +78,19 @@ RenderMenuList::RenderMenuList(HTMLSelectElement& element, PassRef<RenderStyle>
     , m_needsOptionsWidthUpdate(true)
     , m_optionsWidth(0)
     , m_lastActiveIndex(-1)
+#if !PLATFORM(IOS)
     , m_popupIsVisible(false)
+#endif
 {
 }
 
 RenderMenuList::~RenderMenuList()
 {
+#if !PLATFORM(IOS)
     if (m_popup)
         m_popup->disconnectClient();
     m_popup = 0;
+#endif
 }
 
 bool RenderMenuList::canBeReplacedWithInlineRunIn() const
@@ -118,6 +141,26 @@ void RenderMenuList::adjustInnerStyle()
         innerStyle.setTextAlign(LEFT);
         TextDirection direction = (m_buttonText && m_buttonText->text()->defaultWritingDirection() == U_RIGHT_TO_LEFT) ? RTL : LTR;
         innerStyle.setDirection(direction);
+#if PLATFORM(IOS)
+    } else if (document().page()->chrome().selectItemAlignmentFollowsMenuWritingDirection()) {
+        innerStyle.setTextAlign(style().direction() == LTR ? LEFT : RIGHT);
+        TextDirection direction;
+        EUnicodeBidi unicodeBidi;
+        if (multiple() && selectedOptionCount(*this) != 1) {
+            direction = (m_buttonText && m_buttonText->text()->defaultWritingDirection() == U_RIGHT_TO_LEFT) ? RTL : LTR;
+            unicodeBidi = UBNormal;
+        } else if (m_optionStyle) {
+            direction = m_optionStyle->direction();
+            unicodeBidi = m_optionStyle->unicodeBidi();
+        } else {
+            direction = style().direction();
+            unicodeBidi = style().unicodeBidi();
+        }
+
+        innerStyle.setDirection(direction);
+        innerStyle.setUnicodeBidi(unicodeBidi);
+    }
+#else
     } else if (m_optionStyle && document().page()->chrome().selectItemAlignmentFollowsMenuWritingDirection()) {
         if ((m_optionStyle->direction() != innerStyle.direction() || m_optionStyle->unicodeBidi() != innerStyle.unicodeBidi()))
             m_innerBlock->setNeedsLayoutAndPrefWidthsRecalc();
@@ -125,6 +168,7 @@ void RenderMenuList::adjustInnerStyle()
         innerStyle.setDirection(m_optionStyle->direction());
         innerStyle.setUnicodeBidi(m_optionStyle->unicodeBidi());
     }
+#endif // !PLATFORM(IOS)
 }
 
 HTMLSelectElement& RenderMenuList::selectElement() const
@@ -207,9 +251,11 @@ void RenderMenuList::updateFromElement()
         m_needsOptionsWidthUpdate = false;
     }
 
+#if !PLATFORM(IOS)
     if (m_popupIsVisible)
         m_popup->updateFromElement();
     else
+#endif
         setTextFromOption(selectElement().selectedIndex());
 }
 
@@ -228,6 +274,14 @@ void RenderMenuList::setTextFromOption(int optionIndex)
         }
     }
 
+#if PLATFORM(IOS)
+    if (multiple()) {
+        size_t count = selectedOptionCount(*this);
+        if (count != 1)
+            text = htmlSelectMultipleItems(count);
+    }
+#endif
+
     setText(text.stripWhiteSpace());
     didUpdateActiveOption(optionIndex);
 }
@@ -302,6 +356,13 @@ void RenderMenuList::computePreferredLogicalWidths()
     setPreferredLogicalWidthsDirty(false);
 }
 
+#if PLATFORM(IOS)
+NO_RETURN_DUE_TO_ASSERT
+void RenderMenuList::showPopup()
+{
+    ASSERT_NOT_REACHED();
+}
+#else
 void RenderMenuList::showPopup()
 {
     if (m_popupIsVisible)
@@ -325,11 +386,14 @@ void RenderMenuList::showPopup()
     absBounds.setLocation(roundedIntPoint(absTopLeft));
     m_popup->show(absBounds, &view().frameView(), selectElement().optionToListIndex(selectElement().selectedIndex()));
 }
+#endif
 
 void RenderMenuList::hidePopup()
 {
+#if !PLATFORM(IOS)
     if (m_popup)
         m_popup->hide();
+#endif
 }
 
 void RenderMenuList::valueChanged(unsigned listIndex, bool fireOnChange)
@@ -564,7 +628,9 @@ int RenderMenuList::selectedIndex() const
 
 void RenderMenuList::popupDidHide()
 {
+#if !PLATFORM(IOS)
     m_popupIsVisible = false;
+#endif
 }
 
 bool RenderMenuList::itemIsSeparator(unsigned listIndex) const
index 36734a3..b2b1752 100644 (file)
@@ -48,7 +48,9 @@ public:
 
     HTMLSelectElement& selectElement() const;
 
+#if !PLATFORM(IOS)
     bool popupIsVisible() const { return m_popupIsVisible; }
+#endif
     void showPopup();
     void hidePopup();
 
@@ -145,8 +147,10 @@ private:
 
     RefPtr<RenderStyle> m_optionStyle;
 
+#if !PLATFORM(IOS)
     RefPtr<PopupMenu> m_popup;
     bool m_popupIsVisible;
+#endif
 };
 
 template<> inline bool isRendererOfType<const RenderMenuList>(const RenderObject& renderer) { return renderer.isMenuList(); }
index 49c9f7b..f36634a 100644 (file)
 #include "SVGRenderSupport.h"
 #endif
 
+#if PLATFORM(IOS)
+#include "SelectionRect.h"
+#endif
+
 namespace WebCore {
 
 using namespace HTMLNames;
@@ -1127,6 +1131,57 @@ void RenderObject::paintOutline(PaintInfo& paintInfo, const LayoutRect& paintRec
         graphicsContext->endTransparencyLayer();
 }
 
+// FIXME: Make this return an unsigned integer?
+int RenderObject::columnNumberForOffset(int offset)
+{
+    int columnNumber = 0;
+    RenderBlock* containingBlock = this->containingBlock();
+    RenderView& view = containingBlock->view();
+    const Pagination& pagination = view.frameView().frame().page()->pagination();
+    if (pagination.mode == Pagination::Unpaginated)
+        return columnNumber;
+
+    ColumnInfo* columnInfo = view.columnInfo();
+    if (columnInfo && columnInfo->progressionAxis() == ColumnInfo::BlockAxis) {
+        if (!columnInfo->progressionIsReversed())
+            columnNumber = (pagination.pageLength + pagination.gap - offset) / (pagination.pageLength + pagination.gap);
+        else
+            columnNumber = offset / (pagination.pageLength + pagination.gap);
+    }
+    return columnNumber;
+}
+
+#if PLATFORM(IOS)
+// This function is similar in spirit to RenderText::absoluteRectsForRange, but returns rectangles
+// which are annotated with additional state which helps iOS draw selections in its unique way.
+// No annotations are added in this class.
+// FIXME: Move to RenderText with absoluteRectsForRange()?
+void RenderObject::collectSelectionRects(Vector<SelectionRect>& rects, unsigned start, unsigned end)
+{
+    Vector<FloatQuad> quads;
+
+    if (!firstChildSlow()) {
+        // FIXME: WebKit's position for an empty span after a BR is incorrect, so we can't trust 
+        // quads for them. We don't need selection rects for those anyway though, since they 
+        // are just empty containers. See <https://bugs.webkit.org/show_bug.cgi?id=49358>.
+        RenderObject* previous = previousSibling();
+        Node* node = this->node();
+        if (!previous || !previous->isBR() || !node || !node->isContainerNode() || !isInline()) {
+            // For inline elements we don't use absoluteQuads, since it takes into account continuations and leads to wrong results.
+            absoluteQuadsForSelection(quads);
+        }
+    } else {
+        unsigned offset = start;
+        for (RenderObject* child = childAt(start); child && offset < end; child = child->nextSibling(), ++offset)
+            child->absoluteQuads(quads);
+    }
+
+    unsigned numberOfQuads = quads.size();
+    for (unsigned i = 0; i < numberOfQuads; ++i)
+        rects.append(SelectionRect(quads[i].enclosingBoundingBox(), isHorizontalWritingMode(), columnNumberForOffset(quads[i].enclosingBoundingBox().x())));
+}
+#endif
+
 IntRect RenderObject::absoluteBoundingBoxRect(bool useTransforms) const
 {
     if (useTransforms) {
@@ -2093,6 +2148,11 @@ void RenderObject::destroyAndCleanupAnonymousWrappers()
 
 void RenderObject::destroy()
 {
+#if PLATFORM(IOS)
+    if (hasLayer())
+        toRenderBoxModelObject(this)->layer()->willBeDestroyed();
+#endif
+
     willBeDestroyed();
     delete this;
 }
@@ -2167,6 +2227,11 @@ bool RenderObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitT
     return false;
 }
 
+int RenderObject::innerLineHeight() const
+{
+    return style().computedLineHeight();
+}
+
 RenderStyle* RenderObject::getCachedPseudoStyle(PseudoId pseudo, RenderStyle* parentStyle) const
 {
     if (pseudo < FIRST_INTERNAL_PSEUDOID && !style().hasPseudoStyle(pseudo))
@@ -2343,9 +2408,14 @@ bool RenderObject::willRenderImage(CachedImage*)
     if (style().visibility() != VISIBLE)
         return false;
 
+#if PLATFORM(IOS)
+    if (document().frame()->timersPaused())
+        return false;
+#else
     // We will not render a new image when Active DOM is suspended
     if (document().activeDOMObjectsAreSuspended())
         return false;
+#endif
 
     // If we're not in a window (i.e., we're dormant from being put in the b/f cache or in a background tab)
     // then we don't want to render either.
index 9bf5cfb..35ac1f1 100644 (file)
@@ -65,6 +65,9 @@ class VisiblePosition;
 #if ENABLE(SVG)
 class RenderSVGResourceContainer;
 #endif
+#if PLATFORM(IOS)
+class SelectionRect;
+#endif
 
 struct PaintInfo;
 
@@ -108,7 +111,11 @@ enum MapCoordinatesMode {
 };
 typedef unsigned MapCoordinatesFlags;
 
+#if PLATFORM(IOS)
+const int caretWidth = 2; // This value should be kept in sync with UIKit. See <rdar://problem/15580601>.
+#else
 const int caretWidth = 1;
+#endif
 
 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(DRAGGABLE_REGION)
 struct AnnotatedRegionValue {
@@ -653,7 +660,11 @@ public:
     void setHasLayer(bool b = true) { m_bitfields.setHasLayer(b); }
     void setHasTransform(bool b = true) { m_bitfields.setHasTransform(b); }
     void setHasReflection(bool b = true) { m_bitfields.setHasReflection(b); }
-    
+
+    // Hook so that RenderTextControl can return the line height of its inner renderer.
+    // For other renderers, the value is the same as lineHeight(false).
+    virtual int innerLineHeight() const;
+
     // used for element state updates that cannot be fixed with a
     // repaint and do not need a relayout
     virtual void updateFromElement() { }
@@ -707,7 +718,12 @@ public:
     virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const;
     // Return the offset from an object up the container() chain. Asserts that none of the intermediate objects have transforms.
     LayoutSize offsetFromAncestorContainer(RenderObject*) const;
-    
+
+#if PLATFORM(IOS)
+    virtual void collectSelectionRects(Vector<SelectionRect>&, unsigned startOffset = 0, unsigned endOffset = std::numeric_limits<unsigned>::max());
+    virtual void absoluteQuadsForSelection(Vector<FloatQuad>& quads) const { absoluteQuads(quads); }
+#endif
+
     virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint&) const { }
 
     // FIXME: useTransforms should go away eventually
@@ -905,9 +921,10 @@ public:
 
     RespectImageOrientationEnum shouldRespectImageOrientation() const;
 
-protected:
     void drawLineForBoxSide(GraphicsContext*, int x1, int y1, int x2, int y2, BoxSide,
                             Color, EBorderStyle, int adjbw1, int adjbw2, bool antialias = false);
+protected:
+    int columnNumberForOffset(int offset);
 
     void paintFocusRing(PaintInfo&, const LayoutPoint&, RenderStyle*);
     void paintOutline(PaintInfo&, const LayoutRect&);
index 6afa654..548d59d 100644 (file)
@@ -58,6 +58,8 @@ public:
 
     float opacity();
 
+    PassRefPtr<RenderStyle> getScrollbarPseudoStyle(ScrollbarPart, PseudoId);
+
 private:
     RenderScrollbar(ScrollableArea*, ScrollbarOrientation, Element*, Frame*);
 
@@ -75,7 +77,6 @@ private:
 
     void updateScrollbarParts(bool destroy = false);
 
-    PassRefPtr<RenderStyle> getScrollbarPseudoStyle(ScrollbarPart, PseudoId);
     void updateScrollbarPart(ScrollbarPart, bool destroy = false);
 
     // This Scrollbar(Widget) may outlive the DOM which created it (during tear down),
index 804b75b..14b4c65 100644 (file)
@@ -218,6 +218,7 @@ void RenderSearchField::valueChanged(unsigned listIndex, bool fireEvents)
 
 String RenderSearchField::itemText(unsigned listIndex) const
 {
+#if !PLATFORM(IOS)
     int size = listSize();
     if (size == 1) {
         ASSERT(!listIndex);
@@ -225,10 +226,13 @@ String RenderSearchField::itemText(unsigned listIndex) const
     }
     if (!listIndex)
         return searchMenuRecentSearchesText();
+#endif
     if (itemIsSeparator(listIndex))
         return String();
+#if !PLATFORM(IOS)
     if (static_cast<int>(listIndex) == (size - 1))
         return searchMenuClearRecentSearchesText();
+#endif
     return m_recentSearches[listIndex - 1];
 }
 
index 170e33d..d12b760 100644 (file)
 #include <wtf/text/StringBuffer.h>
 #include <wtf/unicode/CharacterNames.h>
 
+#if PLATFORM(IOS)
+#include "Document.h"
+#include "EditorClient.h"
+#include "LogicalSelectionOffsetCaches.h"
+#include "Page.h"
+#include "SelectionRect.h"
+#endif
+
 using namespace WTF;
 using namespace Unicode;
 
@@ -300,6 +308,83 @@ Vector<IntRect> RenderText::absoluteRectsForRange(unsigned start, unsigned end,
     return m_lineBoxes.absoluteRectsForRange(*this, start, end, useSelectionHeight, wasFixed);
 }
 
+#if PLATFORM(IOS)
+// This function is similar in spirit to addLineBoxRects, but returns rectangles
+// which are annotated with additional state which helps the iPhone draw selections in its unique way.
+// Full annotations are added in this class.
+void RenderText::collectSelectionRects(Vector<SelectionRect>& rects, unsigned start, unsigned end)
+{
+    // FIXME: Work around signed/unsigned issues. This function takes unsigneds, and is often passed UINT_MAX
+    // to mean "all the way to the end". InlineTextBox coordinates are unsigneds, so changing this 
+    // function to take ints causes various internal mismatches. But selectionRect takes ints, and 
+    // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect to take unsigneds, but 
+    // that would cause many ripple effects, so for now we'll just clamp our unsigned parameters to INT_MAX.
+    ASSERT(end == std::numeric_limits<unsigned>::max() || end <= std::numeric_limits<int>::max());
+    ASSERT(start <= std::numeric_limits<int>::max());
+    start = std::min(start, static_cast<unsigned>(std::numeric_limits<int>::max()));
+    end = std::min(end, static_cast<unsigned>(std::numeric_limits<int>::max()));
+
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
+        LayoutRect rect;
+        // Note, box->end() returns the index of the last character, not the index past it.
+        if (start <= box->start() && box->end() < end)
+            rect = box->localSelectionRect(start, end);
+        else {
+            unsigned realEnd = std::min(box->end() + 1, end);
+            rect = box->localSelectionRect(start, realEnd);
+            if (rect.isEmpty())
+                continue;
+        }
+
+        if (box->root().isFirstAfterPageBreak()) {
+            if (box->isHorizontal())
+                rect.shiftYEdgeTo(box->root().lineTopWithLeading());
+            else
+                rect.shiftXEdgeTo(box->root().lineTopWithLeading());
+        }
+
+        RenderBlock* containingBlock = this->containingBlock();
+        // Map rect, extended left to leftOffset, and right to rightOffset, through transforms to get minX and maxX.
+        LogicalSelectionOffsetCaches cache(*containingBlock);
+        LayoutUnit leftOffset = containingBlock->logicalLeftSelectionOffset(*containingBlock, box->logicalTop(), cache);
+        LayoutUnit rightOffset = containingBlock->logicalRightSelectionOffset(*containingBlock, box->logicalTop(), cache);
+        LayoutRect extentsRect = rect;
+        if (box->isHorizontal()) {
+            extentsRect.setX(leftOffset);
+            extentsRect.setWidth(rightOffset - leftOffset);
+        } else {
+            extentsRect.setY(leftOffset);
+            extentsRect.setHeight(rightOffset - leftOffset);
+        }
+        extentsRect = localToAbsoluteQuad(FloatRect(extentsRect)).enclosingBoundingBox();
+        if (!box->isHorizontal())
+            extentsRect = extentsRect.transposedRect();
+        bool isFirstOnLine = !box->previousOnLineExists();
+        bool isLastOnLine = !box->nextOnLineExists();
+        if (containingBlock->isRubyBase() || containingBlock->isRubyText())
+            isLastOnLine = !containingBlock->containingBlock()->inlineBoxWrapper()->nextOnLineExists();
+
+        bool containsStart = box->start() <= start && box->end() + 1 >= start;
+        bool containsEnd = box->start() <= end && box->end() + 1 >= end;
+
+        bool isFixed = false;
+        IntRect absRect = localToAbsoluteQuad(FloatRect(rect), false, &isFixed).enclosingBoundingBox();
+        bool boxIsHorizontal = !box->isSVGInlineTextBox() ? box->isHorizontal() : !style().svgStyle().isVerticalWritingMode();
+        // If the containing block is an inline element, we want to check the inlineBoxWrapper orientation
+        // to determine the orientation of the block. In this case we also use the inlineBoxWrapper to
+        // determine if the element is the last on the line.
+        if (containingBlock->inlineBoxWrapper()) {
+            if (containingBlock->inlineBoxWrapper()->isHorizontal() != boxIsHorizontal) {
+                boxIsHorizontal = containingBlock->inlineBoxWrapper()->isHorizontal();
+                isLastOnLine = !containingBlock->inlineBoxWrapper()->nextOnLineExists();
+            }
+        }
+
+        rects.append(SelectionRect(absRect, box->direction(), extentsRect.x(), extentsRect.maxX(), extentsRect.maxY(), 0, box->isLineBreak(), isFirstOnLine, isLastOnLine, containsStart, containsEnd, boxIsHorizontal, isFixed, containingBlock->isRubyText(), columnNumberForOffset(absRect.x())));
+    }
+}
+#endif
+
 Vector<FloatQuad> RenderText::absoluteQuadsClippedToEllipsis() const
 {
     if (auto layout = simpleLineLayout()) {
@@ -953,13 +1038,25 @@ void RenderText::setTextInternal(const String& text)
     case TSNONE:
         break;
     case TSCIRCLE:
+#if PLATFORM(IOS)
+        secureText(blackCircle);
+#else
         secureText(whiteBullet);
+#endif
         break;
     case TSDISC:
+#if PLATFORM(IOS)
+        secureText(blackCircle);
+#else
         secureText(bullet);
+#endif
         break;
     case TSSQUARE:
+#if PLATFORM(IOS)
+        secureText(blackCircle);
+#else
         secureText(blackSquare);
+#endif
     }
 
     ASSERT(!m_text.isNull());
index 9ca316f..0ea2bf1 100644 (file)
@@ -64,6 +64,9 @@ public:
 
     virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE FINAL;
     Vector<IntRect> absoluteRectsForRange(unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false, bool* wasFixed = nullptr) const;
+#if PLATFORM(IOS)
+    virtual void collectSelectionRects(Vector<SelectionRect>&, unsigned startOffset = 0, unsigned endOffset = std::numeric_limits<unsigned>::max()) OVERRIDE;
+#endif
 
     virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE FINAL;
     Vector<FloatQuad> absoluteQuadsForRange(unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false, bool* wasFixed = nullptr) const;
index 8fcbaa2..96c5d20 100644 (file)
@@ -92,6 +92,31 @@ void RenderTextControl::adjustInnerTextStyle(const RenderStyle* startStyle, Rend
     bool disabled = updateUserModifyProperty(textFormControlElement(), textBlockStyle);
     if (disabled)
         textBlockStyle->setColor(theme()->disabledTextColor(textBlockStyle->visitedDependentColor(CSSPropertyColor), startStyle->visitedDependentColor(CSSPropertyBackgroundColor)));
+#if PLATFORM(IOS)
+    if (textBlockStyle->textSecurity() != TSNONE && !textBlockStyle->isLeftToRightDirection()) {
+        // Preserve the alignment but force the direction to LTR so that the last-typed, unmasked character
+        // (which cannot have RTL directionality) will appear to the right of the masked characters. See <rdar://problem/7024375>.
+        
+        switch (textBlockStyle->textAlign()) {
+        case TASTART:
+        case JUSTIFY:
+            textBlockStyle->setTextAlign(RIGHT);
+            break;
+        case TAEND:
+            textBlockStyle->setTextAlign(LEFT);
+            break;
+        case LEFT:
+        case RIGHT:
+        case CENTER:
+        case WEBKIT_LEFT:
+        case WEBKIT_RIGHT:
+        case WEBKIT_CENTER:
+            break;
+        }
+
+        textBlockStyle->setDirection(LTR);
+    }
+#endif
 }
 
 int RenderTextControl::textBlockLogicalHeight() const
@@ -303,6 +328,22 @@ RenderObject* RenderTextControl::layoutSpecialExcludedChild(bool relayoutChildre
     return placeholderRenderer;
 }
 
+#if PLATFORM(IOS)
+bool RenderTextControl::canScroll() const
+{
+    Element* innerText = innerTextElement();
+    return innerText && innerText->renderer() && innerText->renderer()->hasOverflowClip();
+}
+
+int RenderTextControl::innerLineHeight() const
+{
+    Element* innerText = innerTextElement();
+    if (innerText && innerText->renderer())
+        return innerText->renderer()->style().computedLineHeight();
+    return style().computedLineHeight();
+}
+#endif
+
 bool RenderTextControl::canBeReplacedWithInlineRunIn() const
 {
     return false;
index 7c38a21..9363c01 100644 (file)
@@ -37,6 +37,13 @@ public:
     HTMLTextFormControlElement& textFormControlElement() const;
     virtual PassRef<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const = 0;
 
+#if PLATFORM(IOS)
+    bool canScroll() const;
+
+    // Returns the line height of the inner renderer.
+    virtual int innerLineHeight() const OVERRIDE;
+#endif
+
 protected:
     RenderTextControl(HTMLTextFormControlElement&, PassRef<RenderStyle>);
 
index 0eb554a..fa8d8a8 100644 (file)
@@ -61,11 +61,13 @@ bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitT
 
 float RenderTextControlMultiLine::getAvgCharWidth(AtomicString family)
 {
+#if !PLATFORM(IOS)
     // 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 == "Lucida Grande")
         return scaleEmToUnits(1229);
+#endif
 
     return RenderTextControl::getAvgCharWidth(family);
 }
@@ -91,6 +93,13 @@ PassRef<RenderStyle> RenderTextControlMultiLine::createInnerTextStyle(const Rend
     textBlockStyle.get().inheritFrom(startStyle);
     adjustInnerTextStyle(startStyle, &textBlockStyle.get());
     textBlockStyle.get().setDisplay(BLOCK);
+
+#if PLATFORM(IOS)
+    // We're adding three extra pixels of padding to line textareas up with text fields.  
+    textBlockStyle.get().setPaddingLeft(Length(3, Fixed));
+    textBlockStyle.get().setPaddingRight(Length(3, Fixed));
+#endif
+
     return textBlockStyle;
 }
 
index f1550c7..03d2ce8 100644 (file)
 #include "TextControlInnerElements.h"
 #include <wtf/StackStats.h>
 
+#if PLATFORM(IOS)
+#include "RenderThemeIOS.h"
+#endif
+
 namespace WebCore {
 
 using namespace HTMLNames;
@@ -211,6 +215,12 @@ void RenderTextControlSingleLine::layout()
         if (neededLayout)
             computeOverflow(clientLogicalBottom());
     }
+
+#if PLATFORM(IOS)
+    // FIXME: We should not be adjusting styles during layout. <rdar://problem/7675493>
+    if (inputElement().isSearchField())
+        RenderThemeIOS::adjustRoundBorderRadius(style(), this);
+#endif
 }
 
 bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
@@ -298,12 +308,14 @@ LayoutRect RenderTextControlSingleLine::controlClipRect(const LayoutPoint& addit
 
 float RenderTextControlSingleLine::getAvgCharWidth(AtomicString family)
 {
+#if !PLATFORM(IOS)
     // 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 == "Lucida Grande")
         return scaleEmToUnits(901);
+#endif
 
     return RenderTextControl::getAvgCharWidth(family);
 }
@@ -318,6 +330,8 @@ LayoutUnit RenderTextControlSingleLine::preferredContentLogicalWidth(float charW
     LayoutUnit result = static_cast<LayoutUnit>(ceiledLayoutUnit(charWidth * factor));
 
     float maxCharWidth = 0.f;
+
+#if !PLATFORM(IOS)
     const AtomicString& family = style().font().firstFamily();
     // 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
@@ -327,6 +341,7 @@ LayoutUnit RenderTextControlSingleLine::preferredContentLogicalWidth(float charW
         maxCharWidth = scaleEmToUnits(4027);
     else if (hasValidAvgCharWidth(family))
         maxCharWidth = roundf(style().font().primaryFont()->maxCharWidth());
+#endif
 
     // For text inputs, IE adds some extra width.
     if (maxCharWidth > 0.f)
index be6276a..968a082 100644 (file)
@@ -271,12 +271,14 @@ static bool lineDirectionPointFitsInBox(int pointLineDirection, const InlineText
         return true;
     }
 
+#if !PLATFORM(IOS)
     // and the x coordinate is to the left of the right edge of this box
     // check to see if position goes in this box
     if (pointLineDirection < box.logicalRight()) {
         shouldAffinityBeDownstream = UpstreamIfPositionIsNotAtStart;
         return true;
     }
+#endif
 
     // box is first on line
     // and the x coordinate is to the left of the first text box left edge
@@ -406,6 +408,13 @@ VisiblePosition RenderTextLineBoxes::positionForPoint(const RenderText& renderer
 
             if (pointBlockDirection < bottom || (blocksAreFlipped && pointBlockDirection == bottom)) {
                 ShouldAffinityBeDownstream shouldAffinityBeDownstream;
+#if PLATFORM(IOS)
+                if (pointLineDirection != box->logicalLeft() && point.x() < box->x() + box->logicalWidth()) {
+                    int half = box->x() + box->logicalWidth() / 2;
+                    EAffinity affinity = point.x() < half ? DOWNSTREAM : VP_UPSTREAM_IF_POSSIBLE;
+                    return renderer.createVisiblePosition(box->offsetForPosition(pointLineDirection) + box->start(), affinity);
+                }
+#endif
                 if (lineDirectionPointFitsInBox(pointLineDirection, *box, shouldAffinityBeDownstream))
                     return createVisiblePositionAfterAdjustingOffsetForBiDi(*box, box->offsetForPosition(pointLineDirection), shouldAffinityBeDownstream);
             }
index ae1b728..90d6562 100644 (file)
@@ -397,6 +397,10 @@ bool RenderTheme::paintBorderOnly(RenderObject* o, const PaintInfo& paintInfo, c
     if (paintInfo.context->paintingDisabled())
         return false;
 
+#if PLATFORM(IOS)
+    UNUSED_PARAM(r);
+    return o->style().appearance() != NoControlPart;
+#else
     // Call the appropriate paint method based off the appearance value.
     switch (o->style().appearance()) {
     case TextFieldPart:
@@ -440,6 +444,7 @@ bool RenderTheme::paintBorderOnly(RenderObject* o, const PaintInfo& paintInfo, c
     }
 
     return false;
+#endif
 }
 
 bool RenderTheme::paintDecorations(RenderObject* renderer, const PaintInfo& paintInfo, const IntRect& rect)
@@ -452,15 +457,26 @@ bool RenderTheme::paintDecorations(RenderObject* renderer, const PaintInfo& pain
     case MenulistButtonPart:
         return paintMenuListButtonDecorations(renderer, paintInfo, rect);
     case TextFieldPart:
+        return paintTextFieldDecorations(renderer, paintInfo, rect);
     case TextAreaPart:
-    case ListboxPart:
+        return paintTextAreaDecorations(renderer, paintInfo, rect);
     case CheckboxPart:
+        return paintCheckboxDecorations(renderer, paintInfo, rect);
     case RadioPart:
+        return paintRadioDecorations(renderer, paintInfo, rect);
     case PushButtonPart:
+        return paintPushButtonDecorations(renderer, paintInfo, rect);
     case SquareButtonPart:
-    case DefaultButtonPart:
+        return paintSquareButtonDecorations(renderer, paintInfo, rect);
     case ButtonPart:
+        return paintButtonDecorations(renderer, paintInfo, rect);
     case MenulistPart:
+        return paintMenuListDecorations(renderer, paintInfo, rect);
+    case SliderThumbHorizontalPart:
+    case SliderThumbVerticalPart:
+        return paintSliderThumbDecorations(renderer, paintInfo, rect);
+    case SearchFieldPart:
+        return paintSearchFieldDecorations(renderer, paintInfo, rect);
 #if ENABLE(METER_ELEMENT)
     case MeterPart:
     case RelevancyLevelIndicatorPart:
@@ -473,9 +489,8 @@ bool RenderTheme::paintDecorations(RenderObject* renderer, const PaintInfo& pain
 #endif
     case SliderHorizontalPart:
     case SliderVerticalPart:
-    case SliderThumbHorizontalPart:
-    case SliderThumbVerticalPart:
-    case SearchFieldPart:
+    case ListboxPart:
+    case DefaultButtonPart:
     case SearchFieldCancelButtonPart:
     case SearchFieldDecorationPart:
     case SearchFieldResultsDecorationPart:
index a014084..9123cf2 100644 (file)
@@ -39,6 +39,7 @@ class CSSStyleSheet;
 class Element;
 class FileList;
 class HTMLInputElement;
+class Icon;
 class PopupMenu;
 class RenderMenuList;
 #if ENABLE(METER_ELEMENT)
@@ -271,18 +272,31 @@ protected:
     virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
 #endif
 
+    virtual bool paintCheckboxDecorations(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintRadioDecorations(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintButtonDecorations(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+
     virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
     virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintTextFieldDecorations(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
 
     virtual void adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const;
     virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintTextAreaDecorations(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
 
     virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
     virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMenuListDecorations(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
 
     virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
     virtual bool paintMenuListButtonDecorations(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
 
+    virtual bool paintPushButtonDecorations(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintSquareButtonDecorations(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+
+    enum FileUploadDecorations { SingleFile, MultipleFiles };
+    virtual bool paintFileUploadIconDecorations(RenderObject* /*inputRenderer*/, RenderObject* /*buttonRenderer*/, const PaintInfo&, const IntRect&, Icon*, FileUploadDecorations) { return true; }
+    
 #if ENABLE(METER_ELEMENT)
     virtual void adjustMeterStyle(StyleResolver*, RenderStyle*, Element*) const;
     virtual bool paintMeter(RenderObject*, const PaintInfo&, const IntRect&);
@@ -303,9 +317,11 @@ protected:
 
     virtual void adjustSliderThumbStyle(StyleResolver*, RenderStyle*, Element*) const;
     virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintSliderThumbDecorations(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
 
     virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
     virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintSearchFieldDecorations(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
 
     virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
     virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
diff --git a/Source/WebCore/rendering/RenderThemeIOS.h b/Source/WebCore/rendering/RenderThemeIOS.h
new file mode 100644 (file)
index 0000000..62e5e40
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008 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. 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 INC. OR ITS 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 RenderThemeIOS_h
+#define RenderThemeIOS_h
+
+#if PLATFORM(IOS)
+
+#include "RenderTheme.h"
+
+namespace WebCore {
+    
+class RenderStyle;
+class GraphicsContext;
+    
+class RenderThemeIOS : public RenderTheme {
+public:
+    static PassRefPtr<RenderTheme> create();
+
+    virtual int popupInternalPaddingRight(RenderStyle*) const OVERRIDE;
+
+    static void adjustRoundBorderRadius(RenderStyle&, RenderBox*);
+
+    virtual void systemFont(CSSValueID, FontDescription&) const OVERRIDE;
+
+    static CFStringRef contentSizeCategory();
+
+protected:
+    virtual int baselinePosition(const RenderObject*) const OVERRIDE;
+
+    virtual bool isControlStyled(const RenderStyle*, const BorderData&, const FillLayer& background, const Color& backgroundColor) const OVERRIDE;
+
+    // Methods for each appearance value.
+    virtual void adjustCheckboxStyle(StyleResolver*, RenderStyle*, Element*) const OVERRIDE;
+    virtual bool paintCheckboxDecorations(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+
+    virtual void adjustRadioStyle(StyleResolver*, RenderStyle*, Element*) const OVERRIDE;
+    virtual bool paintRadioDecorations(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+
+    virtual void adjustButtonStyle(StyleResolver*, RenderStyle*, Element*) const OVERRIDE;
+    virtual bool paintButtonDecorations(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+    virtual bool paintPushButtonDecorations(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+    virtual void setButtonSize(RenderStyle*) const OVERRIDE;
+
+    virtual bool paintFileUploadIconDecorations(RenderObject* inputRenderer, RenderObject* buttonRenderer, const PaintInfo&, const IntRect&, Icon*, FileUploadDecorations) OVERRIDE;
+
+    virtual bool paintTextFieldDecorations(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+    virtual bool paintTextAreaDecorations(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+
+    virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const OVERRIDE;
+    virtual bool paintMenuListButtonDecorations(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+
+    virtual void adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const OVERRIDE;
+    virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+
+    virtual void adjustSliderThumbSize(RenderStyle*, Element*) const OVERRIDE;
+    virtual bool paintSliderThumbDecorations(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+
+#if ENABLE(PROGRESS_ELEMENT)
+    // Returns the repeat interval of the animation for the progress bar.
+    virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const OVERRIDE;
+    // Returns the duration of the animation for the progress bar.
+    virtual double animationDurationForProgressBar(RenderProgress*) const OVERRIDE;
+
+    virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+#endif
+
+#if ENABLE(DATALIST_ELEMENT)
+    virtual IntSize sliderTickSize() const OVERRIDE;
+    virtual int sliderTickOffsetFromTrackCenter() const OVERRIDE;
+#endif
+
+    virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const OVERRIDE;
+    virtual bool paintSearchFieldDecorations(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+
+    virtual Color platformActiveSelectionBackgroundColor() const OVERRIDE;
+    virtual Color platformInactiveSelectionBackgroundColor() const OVERRIDE;
+
+#if ENABLE(TOUCH_EVENTS)
+    virtual Color platformTapHighlightColor() const OVERRIDE { return 0x4D1A1A1A; }
+#endif
+
+    virtual bool shouldShowPlaceholderWhenFocused() const OVERRIDE;
+    virtual bool shouldHaveSpinButton(HTMLInputElement*) const OVERRIDE;
+
+#if ENABLE(VIDEO)
+    virtual String mediaControlsStyleSheet() OVERRIDE;
+    virtual String mediaControlsScript() OVERRIDE;
+#endif
+
+private:
+    RenderThemeIOS();
+    virtual ~RenderThemeIOS() { }
+
+    const Color& shadowColor() const;
+    FloatRect addRoundedBorderClip(RenderObject* box, GraphicsContext*, const IntRect&);
+};
+
+}
+
+#endif // PLATFORM(IOS)
+#endif // RenderThemeIOS_h
diff --git a/Source/WebCore/rendering/RenderThemeIOS.mm b/Source/WebCore/rendering/RenderThemeIOS.mm
new file mode 100644 (file)
index 0000000..e93a9a3
--- /dev/null
@@ -0,0 +1,1217 @@
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008 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. 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 INC. OR ITS 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.
+ */
+
+#import "config.h"
+
+#if PLATFORM(IOS)
+
+#import "CSSPrimitiveValue.h"
+#import "CSSValueKeywords.h"
+#import "DateComponents.h"
+#import "Document.h"
+#import "Font.h"
+#import "FontCache.h"
+#import "Frame.h"
+#import "FrameView.h"
+#import "Gradient.h"
+#import "GraphicsContext.h"
+#import "GraphicsContextCG.h"
+#import "HTMLInputElement.h"
+#import "HTMLNames.h"
+#import "HTMLSelectElement.h"
+#import "Icon.h"
+#import "NodeRenderStyle.h"
+#import "Page.h"
+#import "PlatformLocale.h"
+#import "PaintInfo.h"
+#import "RenderObject.h"
+#import "RenderStyle.h"
+#import "RenderThemeIOS.h"
+#import "RenderView.h"
+#import "SoftLinking.h"
+#import "UserAgentScripts.h"
+#import "UserAgentStyleSheets.h"
+#import "WebCoreThreadRun.h"
+#import <CoreGraphics/CGPathPrivate.h>
+#import <CoreText/CTFontDescriptorPriv.h>
+#import <objc/runtime.h>
+#import <wtf/NeverDestroyed.h>
+#import <wtf/RefPtr.h>
+#import <wtf/StdLibExtras.h>
+
+#if ENABLE(PROGRESS_ELEMENT)
+#import "RenderProgress.h"
+#endif
+
+@interface UIApplication
++ (UIApplication *)sharedApplication;
+@property(nonatomic,copy) NSString *preferredContentSizeCategory;
+@end
+
+SOFT_LINK_FRAMEWORK(UIKit)
+SOFT_LINK_CLASS(UIKit, UIApplication)
+SOFT_LINK_CONSTANT(UIKit, UIContentSizeCategoryDidChangeNotification, CFStringRef)
+#define UIContentSizeCategoryDidChangeNotification getUIContentSizeCategoryDidChangeNotification()
+
+namespace WebCore {
+
+const float ControlBaseHeight = 20;
+const float ControlBaseFontSize = 11;
+
+struct IOSGradient {
+    float* start; // points to static float[4]
+    float* end; // points to static float[4]
+    IOSGradient(float start[4], float end[4])
+        : start(start)
+        , end(end)
+    {
+    }
+};
+
+typedef IOSGradient* IOSGradientRef;
+
+enum Interpolation
+{
+    LinearInterpolation,
+    ExponentialInterpolation
+};
+
+static void interpolateLinearGradient(void *info, const CGFloat *inData, CGFloat *outData)
+{
+    IOSGradientRef gradient = static_cast<IOSGradientRef>(info);
+    float alpha = inData[0];
+    float inverse = 1.0f - alpha;
+
+    outData[0] = inverse * gradient->start[0] + alpha * gradient->end[0];
+    outData[1] = inverse * gradient->start[1] + alpha * gradient->end[1];
+    outData[2] = inverse * gradient->start[2] + alpha * gradient->end[2];
+    outData[3] = inverse * gradient->start[3] + alpha * gradient->end[3];
+}
+
+static void interpolateExponentialGradient(void *info, const CGFloat *inData, CGFloat *outData)
+{
+    IOSGradientRef gradient = static_cast<IOSGradientRef>(info);
+    float a = inData[0];
+    for (int paintInfo = 0; paintInfo < 4; ++paintInfo) {
+        float end = logf(std::max(gradient->end[paintInfo], 0.01f));
+        float start = logf(std::max(gradient->start[paintInfo], 0.01f));
+        outData[paintInfo] = expf(start - (end + start) * a);
+    }
+}
+
+static CGFunctionRef getSharedFunctionRef(IOSGradientRef gradient, Interpolation interpolation)
+{
+    CGFunctionRef function = nullptr;
+
+    static HashMap<IOSGradientRef, CGFunctionRef>* linearFunctionRefs;
+    static HashMap<IOSGradientRef, CGFunctionRef>* exponentialFunctionRefs;;
+
+    if (interpolation == LinearInterpolation) {
+        if (!linearFunctionRefs)
+            linearFunctionRefs = new HashMap<IOSGradientRef, CGFunctionRef>;
+        else
+            function = linearFunctionRefs->get(gradient);
+    
+        if (!function) {
+            static struct CGFunctionCallbacks linearFunctionCallbacks =  { 0, interpolateLinearGradient, 0 };
+            linearFunctionRefs->set(gradient, function = CGFunctionCreate(gradient, 1, nullptr, 4, nullptr, &linearFunctionCallbacks));
+        }
+
+        return function;
+    }
+
+    if (!exponentialFunctionRefs)
+        exponentialFunctionRefs = new HashMap<IOSGradientRef, CGFunctionRef>;
+    else
+        function = exponentialFunctionRefs->get(gradient);
+
+    if (!function) {
+        static struct CGFunctionCallbacks exponentialFunctionCallbacks =  { 0, interpolateExponentialGradient, 0 };
+        exponentialFunctionRefs->set(gradient, function = CGFunctionCreate(gradient, 1, 0, 4, 0, &exponentialFunctionCallbacks));
+    }
+
+    return function;
+}
+
+static void drawAxialGradient(CGContextRef context, IOSGradientRef gradient, const FloatPoint& startPoint, const FloatPoint& stopPoint, Interpolation interpolation)
+{
+    RetainPtr<CGShadingRef> shading = adoptCF(CGShadingCreateAxial(deviceRGBColorSpaceRef(), startPoint, stopPoint, getSharedFunctionRef(gradient, interpolation), false, false));
+    CGContextDrawShading(context, shading.get());
+}
+
+static void drawRadialGradient(CGContextRef context, IOSGradientRef gradient, const FloatPoint& startPoint, float startRadius, const FloatPoint& stopPoint, float stopRadius, Interpolation interpolation)
+{
+    RetainPtr<CGShadingRef> shading = adoptCF(CGShadingCreateRadial(deviceRGBColorSpaceRef(), startPoint, startRadius, stopPoint, stopRadius, getSharedFunctionRef(gradient, interpolation), false, false));
+    CGContextDrawShading(context, shading.get());
+}
+
+enum IOSGradientType {
+    InsetGradient,
+    ShineGradient,
+    ShadeGradient,
+    ConvexGradient,
+    ConcaveGradient,
+    SliderTrackGradient,
+    ReadonlySliderTrackGradient,
+    SliderThumbOpaquePressedGradient,
+};
+
+static IOSGradientRef getInsetGradient()
+{
+    static float end[4] = { 0 / 255.0, 0 / 255.0, 0 / 255.0, 0 };
+    static float start[4] = { 0 / 255.0, 0 / 255.0, 0 / 255.0, 0.2 };
+    static NeverDestroyed<IOSGradient> gradient(start, end);
+    return &gradient.get();
+}
+
+static IOSGradientRef getShineGradient()
+{
+    static float end[4] = { 1, 1, 1, 0.8 };
+    static float start[4] = { 1, 1, 1, 0 };
+    static NeverDestroyed<IOSGradient> gradient(start, end);
+    return &gradient.get();
+}
+
+static IOSGradientRef getShadeGradient()
+{
+    static float end[4] = { 178 / 255.0, 178 / 255.0, 178 / 255.0, 0.65 };
+    static float start[4] = { 252 / 255.0, 252 / 255.0, 252 / 255.0, 0.65 };
+    static NeverDestroyed<IOSGradient> gradient(start, end);
+    return &gradient.get();
+}
+
+static IOSGradientRef getConvexGradient()
+{
+    static float end[4] = { 255 / 255.0, 255 / 255.0, 255 / 255.0, 0.05 };
+    static float start[4] = { 255 / 255.0, 255 / 255.0, 255 / 255.0, 0.43 };
+    static NeverDestroyed<IOSGradient> gradient(start, end);
+    return &gradient.get();
+}
+
+static IOSGradientRef getConcaveGradient()
+{
+    static float end[4] = { 255 / 255.0, 255 / 255.0, 255 / 255.0, 0.46 };
+    static float start[4] = { 255 / 255.0, 255 / 255.0, 255 / 255.0, 0 };
+    static NeverDestroyed<IOSGradient> gradient(start, end);
+    return &gradient.get();
+}
+
+static IOSGradientRef getSliderTrackGradient()
+{
+    static float end[4] = { 132 / 255.0, 132 / 255.0, 132 / 255.0, 1 };
+    static float start[4] = { 74 / 255.0, 77 / 255.0, 80 / 255.0, 1 };
+    static NeverDestroyed<IOSGradient> gradient(start, end);
+    return &gradient.get();
+}
+
+static IOSGradientRef getReadonlySliderTrackGradient()
+{
+    static float end[4] = { 132 / 255.0, 132 / 255.0, 132 / 255.0, 0.4 };
+    static float start[4] = { 74 / 255.0, 77 / 255.0, 80 /255.0, 0.4 };
+    static NeverDestroyed<IOSGradient> gradient(start, end);
+    return &gradient.get();
+}
+
+static IOSGradientRef getSliderThumbOpaquePressedGradient()
+{
+    static float end[4] = { 144 / 255.0, 144 / 255.0, 144 / 255.0, 1};
+    static float start[4] = { 55 / 255.0, 55 / 255.0, 55 / 255.0, 1 };
+    static NeverDestroyed<IOSGradient> gradient(start, end);
+    return &gradient.get();
+}
+
+static IOSGradientRef gradientWithName(IOSGradientType gradientType)
+{
+    switch (gradientType) {
+    case InsetGradient:
+        return getInsetGradient();
+    case ShineGradient:
+        return getShineGradient();
+    case ShadeGradient:
+        return getShadeGradient();
+    case ConvexGradient:
+        return getConvexGradient();
+    case ConcaveGradient:
+        return getConcaveGradient();
+    case SliderTrackGradient:
+        return getSliderTrackGradient();
+    case ReadonlySliderTrackGradient:
+        return getReadonlySliderTrackGradient();
+    case SliderThumbOpaquePressedGradient:
+        return getSliderThumbOpaquePressedGradient();
+    }
+    ASSERT_NOT_REACHED();
+    return nullptr;
+}
+
+static void contentSizeCategoryDidChange(CFNotificationCenterRef, void*, CFStringRef name, const void*, CFDictionaryRef)
+{
+    ASSERT_UNUSED(name, CFEqual(name, UIContentSizeCategoryDidChangeNotification));
+    WebThreadRun(^{
+        Page::updateStyleForAllPagesAfterGlobalChangeInEnvironment();
+    });
+}
+
+RenderThemeIOS::RenderThemeIOS()
+{
+    CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), this, contentSizeCategoryDidChange, UIContentSizeCategoryDidChangeNotification, 0, CFNotificationSuspensionBehaviorDeliverImmediately);
+}
+
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page*)
+{
+    static RenderTheme* renderTheme = RenderThemeIOS::create().leakRef();
+    return renderTheme;
+}
+
+PassRefPtr<RenderTheme> RenderThemeIOS::create()
+{
+    return adoptRef(new RenderThemeIOS);
+}
+
+CFStringRef RenderThemeIOS::contentSizeCategory()
+{
+    return (CFStringRef)[[getUIApplicationClass() sharedApplication] preferredContentSizeCategory];
+}
+
+const Color& RenderThemeIOS::shadowColor() const
+{
+    static Color color(0.0f, 0.0f, 0.0f, 0.7f);
+    return color;
+}
+
+FloatRect RenderThemeIOS::addRoundedBorderClip(RenderObject* box, GraphicsContext* context, const IntRect& rect)
+{
+    // To fix inner border bleeding issues <rdar://problem/9812507>, we clip to the outer border and assert that
+    // the border is opaque or transparent, unless we're checked because checked radio/checkboxes show no bleeding.
+    RenderStyle& style = box->style();
+    RoundedRect border = isChecked(box) ? style.getRoundedInnerBorderFor(rect) : style.getRoundedBorderFor(rect);
+
+    if (border.isRounded())
+        context->clipRoundedRect(border);
+    else
+        context->clip(border.rect());
+
+    if (isChecked(box)) {
+        ASSERT(style.visitedDependentColor(CSSPropertyBorderTopColor).alpha() % 255 == 0);
+        ASSERT(style.visitedDependentColor(CSSPropertyBorderRightColor).alpha() % 255 == 0);
+        ASSERT(style.visitedDependentColor(CSSPropertyBorderBottomColor).alpha() % 255 == 0);
+        ASSERT(style.visitedDependentColor(CSSPropertyBorderLeftColor).alpha() % 255 == 0);
+    }
+
+    return border.rect();
+}
+
+void RenderThemeIOS::adjustCheckboxStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+    if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+        return;
+
+    Length length = Length(static_cast<int>(ceilf(std::max(style->fontSize(), 10))), Fixed);
+    
+    style->setWidth(length);
+    style->setHeight(length);
+}
+
+static CGPoint shortened(CGPoint start, CGPoint end, float width)
+{
+    float x = end.x - start.x;
+    float y = end.y - start.y;
+    float ratio = width / sqrtf(x * x + y * y);
+    return CGPointMake(start.x + x * ratio, start.y + y * ratio);
+}
+
+bool RenderThemeIOS::paintCheckboxDecorations(RenderObject* box, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+    FloatRect clip = addRoundedBorderClip(box, paintInfo.context, rect);
+
+    float width = clip.width();
+    float height = clip.height();
+
+    CGContextRef cgContext = paintInfo.context->platformContext();
+    if (isChecked(box)) {
+        drawAxialGradient(cgContext, gradientWithName(ConcaveGradient), clip.location(), FloatPoint(clip.x(), clip.maxY()), LinearInterpolation);
+
+        static float thicknessRatio = 2 / 14.0;
+        static CGSize size = { 14.0f, 14.0f };
+        static CGPoint pathRatios[3] = {
+            { 2.5f / size.width, 7.5f / size.height },
+            { 5.5f / size.width, 10.5f / size.height },
+            { 11.5f / size.width, 2.5f / size.height }
+        };
+
+        float lineWidth = std::min(width, height) * 2.0f * thicknessRatio;
+
+        CGPoint line[3] = {
+            CGPointMake(clip.x() + width * pathRatios[0].x, clip.y() + height * pathRatios[0].y),
+            CGPointMake(clip.x() + width * pathRatios[1].x, clip.y() + height * pathRatios[1].y),
+            CGPointMake(clip.x() + width * pathRatios[2].x, clip.y() + height * pathRatios[2].y)
+        };
+        CGPoint shadow[3] = {
+            shortened(line[0], line[1], lineWidth / 4.0f),
+            line[1],
+            shortened(line[2], line[1], lineWidth / 4.0f)
+        };
+
+        paintInfo.context->setStrokeThickness(lineWidth);
+        paintInfo.context->setStrokeColor(Color(0.0f, 0.0f, 0.0f, 0.7f), ColorSpaceDeviceRGB);
+
+        paintInfo.context->drawJoinedLines(shadow, 3, true, kCGLineCapSquare);
+
+        paintInfo.context->setStrokeThickness(std::min(clip.width(), clip.height()) * thicknessRatio);
+        paintInfo.context->setStrokeColor(Color(1.0f, 1.0f, 1.0f, 240 / 255.0f), ColorSpaceDeviceRGB);
+
+        paintInfo.context->drawJoinedLines(line, 3, true);
+    } else {
+        FloatPoint bottomCenter(clip.x() + clip.width() / 2.0f, clip.maxY());
+        drawAxialGradient(cgContext, gradientWithName(ShadeGradient), clip.location(), FloatPoint(clip.x(), clip.maxY()), LinearInterpolation);
+        drawRadialGradient(cgContext, gradientWithName(ShineGradient), bottomCenter, 0, bottomCenter, sqrtf((width * width) / 4.0f + height * height), ExponentialInterpolation);
+    }
+
+    return false;
+}
+
+int RenderThemeIOS::baselinePosition(const RenderObject* renderer) const
+{
+    if (!renderer->isBox())
+        return 0;
+
+    const RenderBox* box = toRenderBox(renderer);
+
+    if (box->style().appearance() == CheckboxPart || box->style().appearance() == RadioPart)
+        return box->marginTop() + box->height() - 2; // The baseline is 2px up from the bottom of the checkbox/radio in AppKit.
+    if (box->style().appearance() == MenulistPart)
+        return box->marginTop() + box->height() - 5; // This is to match AppKit. There might be a better way to calculate this though.
+    return RenderTheme::baselinePosition(box);
+}
+
+bool RenderThemeIOS::isControlStyled(const RenderStyle* style, const BorderData& border, const FillLayer& background, const Color& backgroundColor) const
+{
+    // Buttons and MenulistButtons are styled if they contain a background image.
+    if (style->appearance() == PushButtonPart || style->appearance() == MenulistButtonPart)
+        return !style->visitedDependentColor(CSSPropertyBackgroundColor).alpha() || style->backgroundLayers()->hasImage();
+
+    if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart)
+        return *style->backgroundLayers() != background;
+
+    return RenderTheme::isControlStyled(style, border, background, backgroundColor);
+}
+
+void RenderThemeIOS::adjustRadioStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+    if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+        return;
+
+    Length length = Length(static_cast<int>(ceilf(std::max(style->fontSize(), 10))), Fixed);
+    style->setWidth(length);
+    style->setHeight(length);
+    style->setBorderRadius(IntSize(length.value() / 2.0f, length.value() / 2.0f));
+}
+
+bool RenderThemeIOS::paintRadioDecorations(RenderObject* box, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+    FloatRect clip = addRoundedBorderClip(box, paintInfo.context, rect);
+
+    CGContextRef cgContext = paintInfo.context->platformContext();
+    if (isChecked(box)) {
+        drawAxialGradient(cgContext, gradientWithName(ConcaveGradient), clip.location(), FloatPoint(clip.x(), clip.maxY()), LinearInterpolation);
+
+        // The inner circle is 6 / 14 the size of the surrounding circle, 
+        // leaving 8 / 14 around it. (8 / 14) / 2 = 2 / 7.
+
+        static float InnerInverseRatio = 2 / 7.0;
+
+        clip.inflateX(-clip.width() * InnerInverseRatio);
+        clip.inflateY(-clip.height() * InnerInverseRatio);
+
+        paintInfo.context->drawRaisedEllipse(clip, Color::white, ColorSpaceDeviceRGB, shadowColor(), ColorSpaceDeviceRGB);
+
+        FloatSize radius(clip.width() / 2.0f, clip.height() / 2.0f);
+        paintInfo.context->clipRoundedRect(clip, radius, radius, radius, radius);
+    }
+    FloatPoint bottomCenter(clip.x() + clip.width() / 2.0, clip.maxY());
+    drawAxialGradient(cgContext, gradientWithName(ShadeGradient), clip.location(), FloatPoint(clip.x(), clip.maxY()), LinearInterpolation);
+    drawRadialGradient(cgContext, gradientWithName(ShineGradient), bottomCenter, 0, bottomCenter, std::max(clip.width(), clip.height()), ExponentialInterpolation);
+    return false;
+}
+
+bool RenderThemeIOS::paintTextFieldDecorations(RenderObject* box, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    RenderStyle& style = box->style();
+    IntPoint point(rect.x() + style.borderLeftWidth(), rect.y() + style.borderTopWidth());
+
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+    paintInfo.context->clipRoundedRect(style.getRoundedBorderFor(r));
+
+    // This gradient gets drawn black when printing.
+    // Do not draw the gradient if there is no visible top border.
+    bool topBorderIsInvisible = !style.hasBorder() || !style.borderTopWidth() || style.borderTopIsTransparent();
+    if (!box->view().printing() && !topBorderIsInvisible)
+        drawAxialGradient(paintInfo.context->platformContext(), gradientWithName(InsetGradient), point, FloatPoint(CGPointMake(point.x(), point.y() + 3.0f)), LinearInterpolation);
+    return false;
+}
+
+bool RenderThemeIOS::paintTextAreaDecorations(RenderObject* renderer, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return paintTextFieldDecorations(renderer, paintInfo, rect);
+}
+
+const int MenuListMinHeight = 15;
+
+const float MenuListBaseHeight = 20;
+const float MenuListBaseFontSize = 11;
+
+const float MenuListArrowWidth = 7;
+const float MenuListArrowHeight = 6;
+const float MenuListButtonPaddingRight = 19;
+
+int RenderThemeIOS::popupInternalPaddingRight(RenderStyle* style) const
+{
+    if (style->appearance() == MenulistButtonPart)
+        return MenuListButtonPaddingRight + style->borderTopWidth();
+    return 0;
+}
+
+void RenderThemeIOS::adjustRoundBorderRadius(RenderStyle& style, RenderBox* box)
+{
+    if (style.appearance() == NoControlPart || style.backgroundLayers()->hasImage())
+        return;
+
+    // FIXME: We should not be relying on border radius for the appearance of our controls <rdar://problem/7675493>
+    Length radiusWidth(static_cast<int>(std::min(box->width(), box->height()) / 2.0), Fixed);
+    Length radiusHeight(static_cast<int>(box->height() / 2.0), Fixed);
+    style.setBorderRadius(LengthSize(radiusWidth, radiusHeight));
+}
+
+static void applyCommonButtonPaddingToStyle(RenderStyle* style, Element* element)
+{
+    Document& document = element->document();
+    RefPtr<CSSPrimitiveValue> emSize = CSSPrimitiveValue::create(0.5, CSSPrimitiveValue::CSS_EMS);
+    int pixels = emSize->computeLength<int>(style, document.renderStyle(), document.frame()->pageZoomFactor());
+    style->setPaddingBox(LengthBox(0, pixels, 0, pixels));
+}
+
+static void adjustSelectListButtonStyle(RenderStyle* style, Element* element)
+{
+    // Enforce "padding: 0 0.5em".
+    applyCommonButtonPaddingToStyle(style, element);
+
+    // Enforce "line-height: normal".
+    style->setLineHeight(Length(-100.0, Percent));
+}
+
+static void adjustInputElementButtonStyle(RenderStyle* style, HTMLInputElement* inputElement)
+{
+    // Always Enforce "padding: 0 0.5em".
+    applyCommonButtonPaddingToStyle(style, inputElement);
+
+    // Don't adjust the style if the width is specified.
+    if (style->width().isFixed() && style->width().value() > 0)
+        return;
+
+    // Don't adjust for unsupported date input types.
+    DateComponents::Type dateType = inputElement->dateType();
+    if (dateType == DateComponents::Invalid || dateType == DateComponents::Week)
+        return;
+
+    // Enforce the width and set the box-sizing to content-box to not conflict with the padding.
+    Font font = style->font();
+    float maximumWidth = inputElement->locale().maximumWidthForDateType(dateType, font);
+    if (maximumWidth > 0) {    
+        int width = static_cast<int>(maximumWidth + MenuListButtonPaddingRight);
+        style->setWidth(Length(width, Fixed));
+        style->setBoxSizing(CONTENT_BOX);
+    }
+}
+
+void RenderThemeIOS::adjustMenuListButtonStyle(StyleResolver*, RenderStyle* style, Element* element) const
+{
+    // Set the min-height to be at least MenuListMinHeight.
+    if (style->height().isAuto())
+        style->setMinHeight(Length(std::max(MenuListMinHeight, static_cast<int>(MenuListBaseHeight / MenuListBaseFontSize * style->fontDescription().computedSize())), Fixed));
+    else
+        style->setMinHeight(Length(MenuListMinHeight, Fixed));
+
+    // Enforce some default styles in the case that this is a non-multiple <select> element,
+    // or a date input. We don't force these if this is just an element with
+    // "-webkit-appearance: menulist-button".
+    if (element->hasTagName(HTMLNames::selectTag) && !element->hasAttribute(HTMLNames::multipleAttr))
+        adjustSelectListButtonStyle(style, element);
+    else if (element->hasTagName(HTMLNames::inputTag)) {
+        HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(element);
+        adjustInputElementButtonStyle(style, inputElement);
+    }
+}
+
+bool RenderThemeIOS::paintMenuListButtonDecorations(RenderObject* box, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    RenderStyle& style = box->style();
+    float borderTopWidth = style.borderTopWidth();
+    FloatRect clip(rect.x() + style.borderLeftWidth(), rect.y() + style.borderTopWidth(), rect.width() - style.borderLeftWidth() - style.borderRightWidth(), rect.height() - style.borderTopWidth() - style.borderBottomWidth());
+    CGContextRef cgContext = paintInfo.context->platformContext();
+
+    float adjustLeft = 0.5;
+    float adjustRight = 0.5;
+    float adjustTop = 0.5;
+    float adjustBottom = 0.5;
+
+    // Paint left-hand title portion.
+    {
+        FloatRect titleClip(clip.x() - adjustLeft, clip.y() - adjustTop, clip.width() - MenuListButtonPaddingRight + adjustLeft, clip.height() + adjustTop + adjustBottom);
+
+        GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+        paintInfo.context->clipRoundedRect(titleClip, 
+            FloatSize(valueForLength(style.borderTopLeftRadius().width(), rect.width()) - style.borderLeftWidth(), valueForLength(style.borderTopLeftRadius().height(), rect.height()) - style.borderTopWidth()), FloatSize(0, 0),
+            FloatSize(valueForLength(style.borderBottomLeftRadius().width(), rect.width()) - style.borderLeftWidth(), valueForLength(style.borderBottomLeftRadius().height(), rect.height()) - style.borderBottomWidth()), FloatSize(0, 0));
+
+        drawAxialGradient(cgContext, gradientWithName(ShadeGradient), titleClip.location(), FloatPoint(titleClip.x(), titleClip.maxY()), LinearInterpolation);
+        drawAxialGradient(cgContext, gradientWithName(ShineGradient), FloatPoint(titleClip.x(), titleClip.maxY()), titleClip.location(), ExponentialInterpolation);
+    }
+
+    // Draw the separator after the initial padding.
+
+    float separator = clip.maxX() - MenuListButtonPaddingRight;
+
+    box->drawLineForBoxSide(paintInfo.context, separator - borderTopWidth, clip.y(), separator, clip.maxY(), BSRight, style.visitedDependentColor(CSSPropertyBorderTopColor), style.borderTopStyle(), 0, 0);
+
+    FloatRect buttonClip(separator - adjustTop, clip.y() - adjustTop, MenuListButtonPaddingRight + adjustTop + adjustRight, clip.height() + adjustTop + adjustBottom);
+
+    // Now paint the button portion.
+    {
+        GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+        paintInfo.context->clipRoundedRect(buttonClip, 
+            FloatSize(0, 0), FloatSize(valueForLength(style.borderTopRightRadius().width(), rect.width()) - style.borderRightWidth(), valueForLength(style.borderTopRightRadius().height(), rect.height()) - style.borderTopWidth()),
+            FloatSize(0, 0), FloatSize(valueForLength(style.borderBottomRightRadius().width(), rect.width()) - style.borderRightWidth(), valueForLength(style.borderBottomRightRadius().height(), rect.height()) - style.borderBottomWidth()));
+
+        paintInfo.context->fillRect(buttonClip, style.visitedDependentColor(CSSPropertyBorderTopColor), style.colorSpace());
+
+        drawAxialGradient(cgContext, gradientWithName(isFocused(box) && !isReadOnlyControl(box) ? ConcaveGradient : ConvexGradient), buttonClip.location(), FloatPoint(buttonClip.x(), buttonClip.maxY()), LinearInterpolation);
+    }
+
+    // Paint Indicators.
+
+    if (box->isMenuList() && toHTMLSelectElement(box->node())->multiple()) {
+        int size = 2;
+        int count = 3;
+        int padding = 3;
+
+        IntRect ellipse(buttonClip.x() + (buttonClip.width() - count * (size + padding) + padding) / 2.0, buttonClip.maxY() - 10.0, size, size);
+
+        for (int i = 0; i < count; ++i) {
+            paintInfo.context->drawRaisedEllipse(ellipse, Color::white, ColorSpaceDeviceRGB, Color(0.0f, 0.0f, 0.0f, 0.5f), ColorSpaceDeviceRGB);
+            ellipse.move(size + padding, 0);
+        }
+    }  else {
+        float centerX = floorf(buttonClip.x() + buttonClip.width() / 2.0) - 0.5;
+        float centerY = floorf(buttonClip.y() + buttonClip.height() * 3.0 / 8.0);
+
+        FloatPoint arrow[3];
+        FloatPoint shadow[3];
+
+        arrow[0] = FloatPoint(centerX - MenuListArrowWidth / 2.0, centerY);
+        arrow[1] = FloatPoint(centerX + MenuListArrowWidth / 2.0, centerY);
+        arrow[2] = FloatPoint(centerX, centerY + MenuListArrowHeight);
+
+        shadow[0] = FloatPoint(arrow[0].x(), arrow[0].y() + 1.0f);
+        shadow[1] = FloatPoint(arrow[1].x(), arrow[1].y() + 1.0f);
+        shadow[2] = FloatPoint(arrow[2].x(), arrow[2].y() + 1.0f);
+
+        float opacity = isReadOnlyControl(box) ? 0.2 : 0.5;
+        paintInfo.context->setStrokeColor(Color(0.0f, 0.0f, 0.0f, opacity), ColorSpaceDeviceRGB);
+        paintInfo.context->setFillColor(Color(0.0f, 0.0f, 0.0f, opacity), ColorSpaceDeviceRGB);
+        paintInfo.context->drawConvexPolygon(3, shadow, true);
+
+        paintInfo.context->setStrokeColor(Color::white, ColorSpaceDeviceRGB);
+        paintInfo.context->setFillColor(Color::white, ColorSpaceDeviceRGB);
+        paintInfo.context->drawConvexPolygon(3, arrow, true);
+    }
+
+    return false;
+}
+
+const CGFloat kTrackThickness = 4.0;
+const CGFloat kTrackRadius = kTrackThickness / 2.0;
+const int kDefaultSliderThumbSize = 16;
+
+void RenderThemeIOS::adjustSliderTrackStyle(StyleResolver* selector, RenderStyle* style, Element* element) const
+{
+    RenderTheme::adjustSliderTrackStyle(selector, style, element);
+
+    // FIXME: We should not be relying on border radius for the appearance of our controls <rdar://problem/7675493>
+    Length radiusWidth(static_cast<int>(kTrackRadius), Fixed);
+    Length radiusHeight(static_cast<int>(kTrackRadius), Fixed);
+    style->setBorderRadius(LengthSize(radiusWidth, radiusHeight));
+}
+
+bool RenderThemeIOS::paintSliderTrack(RenderObject* box, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    IntRect trackClip = rect;
+    RenderStyle& style = box->style();
+
+    bool isHorizontal = true;
+    switch (style.appearance()) {
+    case SliderHorizontalPart:
+        isHorizontal = true;
+        // Inset slightly so the thumb covers the edge.
+        if (trackClip.width() > 2) {
+            trackClip.setWidth(trackClip.width() - 2);
+            trackClip.setX(trackClip.x() + 1);
+        }
+        trackClip.setHeight(static_cast<int>(kTrackThickness));
+        trackClip.setY(rect.y() + rect.height() / 2 - kTrackThickness / 2);
+        break;
+    case SliderVerticalPart:
+        isHorizontal = false;
+        // Inset slightly so the thumb covers the edge.
+        if (trackClip.height() > 2) {
+            trackClip.setHeight(trackClip.height() - 2);
+            trackClip.setY(trackClip.y() + 1);
+        }
+        trackClip.setWidth(kTrackThickness);
+        trackClip.setX(rect.x() + rect.width() / 2 - kTrackThickness / 2);
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+
+    ASSERT(trackClip.width() >= 0);
+    ASSERT(trackClip.height() >= 0);
+    CGFloat cornerWidth = trackClip.width() < kTrackThickness ? trackClip.width() / 2.0f : kTrackRadius;
+    CGFloat cornerHeight = trackClip.height() < kTrackThickness ? trackClip.height() / 2.0f : kTrackRadius;
+
+    bool readonly = isReadOnlyControl(box);
+
+#if ENABLE(DATALIST_ELEMENT)
+    paintSliderTicks(box, paintInfo, trackClip);
+#endif
+
+    // Draw the track gradient.
+    {
+        GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+        IntSize cornerSize(cornerWidth, cornerHeight);
+        RoundedRect innerBorder(trackClip, cornerSize, cornerSize, cornerSize, cornerSize);
+        paintInfo.context->clipRoundedRect(innerBorder);
+
+        CGContextRef cgContext = paintInfo.context->platformContext();
+        IOSGradientRef gradient = readonly ? gradientWithName(ReadonlySliderTrackGradient) : gradientWithName(SliderTrackGradient);
+        if (isHorizontal)
+            drawAxialGradient(cgContext, gradient, trackClip.location(), FloatPoint(trackClip.x(), trackClip.maxY()), LinearInterpolation);
+        else
+            drawAxialGradient(cgContext, gradient, trackClip.location(), FloatPoint(trackClip.maxX(), trackClip.y()), LinearInterpolation);
+    }
+
+    // Draw the track border.
+    {
+        GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+        CGContextRef cgContext = paintInfo.context->platformContext();
+        if (readonly)
+            paintInfo.context->setStrokeColor(Color(178, 178, 178), ColorSpaceDeviceRGB);
+        else
+            paintInfo.context->setStrokeColor(Color(76, 76, 76), ColorSpaceDeviceRGB);
+
+        RetainPtr<CGMutablePathRef> roundedRectPath = adoptCF(CGPathCreateMutable());
+        CGPathAddRoundedRect(roundedRectPath.get(), 0, trackClip, cornerWidth, cornerHeight);
+        CGContextAddPath(cgContext, roundedRectPath.get());
+        CGContextSetLineWidth(cgContext, 1);
+        CGContextStrokePath(cgContext);
+    }
+
+    return false;
+}
+
+void RenderThemeIOS::adjustSliderThumbSize(RenderStyle* style, Element*) const
+{
+    if (style->appearance() != SliderThumbHorizontalPart && style->appearance() != SliderThumbVerticalPart)
+        return;
+
+    // Enforce "border-radius: 50%".
+    Length length(50.0f, Percent);
+    style->setBorderRadius(LengthSize(length, length));
+
+    // Enforce a 16x16 size if no size is provided.
+    if (style->width().isIntrinsicOrAuto() || style->height().isAuto()) {
+        Length length = Length(kDefaultSliderThumbSize, Fixed);
+        style->setWidth(length);
+        style->setHeight(length);
+    }
+}
+
+bool RenderThemeIOS::paintSliderThumbDecorations(RenderObject* box, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+    FloatRect clip = addRoundedBorderClip(box, paintInfo.context, rect);
+
+    CGContextRef cgContext = paintInfo.context->platformContext();
+    FloatPoint bottomCenter(clip.x() + clip.width() / 2.0f, clip.maxY());
+    if (isPressed(box))
+        drawAxialGradient(cgContext, gradientWithName(SliderThumbOpaquePressedGradient), clip.location(), FloatPoint(clip.x(), clip.maxY()), LinearInterpolation);
+    else {
+        drawAxialGradient(cgContext, gradientWithName(ShadeGradient), clip.location(), FloatPoint(clip.x(), clip.maxY()), LinearInterpolation);
+        drawRadialGradient(cgContext, gradientWithName(ShineGradient), bottomCenter, 0.0f, bottomCenter, std::max(clip.width(), clip.height()), ExponentialInterpolation);
+    }
+
+    return false;
+}
+
+#if ENABLE(PROGRESS_ELEMENT)
+double RenderThemeIOS::animationRepeatIntervalForProgressBar(RenderProgress*) const
+{
+    return 0;
+}
+
+double RenderThemeIOS::animationDurationForProgressBar(RenderProgress*) const
+{
+    return 0;
+}
+
+bool RenderThemeIOS::paintProgressBar(RenderObject* renderer, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    if (!renderer->isProgress())
+        return true;
+
+    const int progressBarHeight = 9;
+    const float verticalOffset = (rect.height() - progressBarHeight) / 2.0;
+
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+    if (rect.width() < 10 || rect.height() < 9) {
+        // The rect is smaller than the standard progress bar. We clip to the element's rect to avoid
+        // leaking pixels outside the repaint rect.
+        paintInfo.context->clip(rect);
+    }
+
+    // 1) Draw the progress bar track.
+    // 1.1) Draw the white background with grey gradient border.
+    GraphicsContext* context = paintInfo.context;
+    context->setStrokeThickness(0.68);
+    context->setStrokeStyle(SolidStroke);
+
+    const float verticalRenderingPosition = rect.y() + verticalOffset;
+    RefPtr<Gradient> strokeGradient = Gradient::create(FloatPoint(rect.x(), verticalRenderingPosition), FloatPoint(rect.x(), verticalRenderingPosition + progressBarHeight - 1));
+    strokeGradient->addColorStop(0.0, Color(0x8d, 0x8d, 0x8d));
+    strokeGradient->addColorStop(0.45, Color(0xee, 0xee, 0xee));
+    strokeGradient->addColorStop(0.55, Color(0xee, 0xee, 0xee));
+    strokeGradient->addColorStop(1.0, Color(0x8d, 0x8d, 0x8d));
+    context->setStrokeGradient(strokeGradient.release());
+
+    ColorSpace colorSpace = renderer->style().colorSpace();
+    context->setFillColor(Color(255, 255, 255), colorSpace);
+
+    Path trackPath;
+    FloatRect trackRect(rect.x() + 0.25, verticalRenderingPosition + 0.25, rect.width() - 0.5, progressBarHeight - 0.5);
+    FloatSize roundedCornerRadius(5, 4);
+    trackPath.addRoundedRect(trackRect, roundedCornerRadius);
+    context->drawPath(trackPath);
+
+    // 1.2) Draw top gradient on the upper half. It is supposed to overlay the fill from the background and darker the stroked path.
+    FloatRect border(rect.x(), rect.y() + verticalOffset, rect.width(), progressBarHeight);
+    paintInfo.context->clipRoundedRect(border, roundedCornerRadius, roundedCornerRadius, roundedCornerRadius, roundedCornerRadius);
+
+    float upperGradientHeight = progressBarHeight / 2.;
+    RefPtr<Gradient> upperGradient = Gradient::create(FloatPoint(rect.x(), verticalRenderingPosition + 0.5), FloatPoint(rect.x(), verticalRenderingPosition + upperGradientHeight - 1.5));
+    upperGradient->addColorStop(0.0, Color(133, 133, 133, 188));
+    upperGradient->addColorStop(1.0, Color(18, 18, 18, 51));
+    context->setFillGradient(upperGradient.release());
+
+    context->fillRect(FloatRect(rect.x(), verticalRenderingPosition, rect.width(), upperGradientHeight));
+
+    RenderProgress* renderProgress = toRenderProgress(renderer);
+    if (renderProgress->isDeterminate()) {
+        // 2) Draw the progress bar.
+        double position = clampTo(renderProgress->position(), 0.0, 1.0);
+        double barWidth = position * rect.width();
+        RefPtr<Gradient> barGradient = Gradient::create(FloatPoint(rect.x(), verticalRenderingPosition + 0.5), FloatPoint(rect.x(), verticalRenderingPosition + progressBarHeight - 1));
+        barGradient->addColorStop(0.0, Color(195, 217, 247));
+        barGradient->addColorStop(0.45, Color(118, 164, 228));
+        barGradient->addColorStop(0.49, Color(118, 164, 228));
+        barGradient->addColorStop(0.51, Color(36, 114, 210));
+        barGradient->addColorStop(0.55, Color(36, 114, 210));
+        barGradient->addColorStop(1.0, Color(57, 142, 244));
+        context->setFillGradient(barGradient.release());
+
+        RefPtr<Gradient> barStrokeGradient = Gradient::create(FloatPoint(rect.x(), verticalRenderingPosition), FloatPoint(rect.x(), verticalRenderingPosition + progressBarHeight - 1));
+        barStrokeGradient->addColorStop(0.0, Color(95, 107, 183));
+        barStrokeGradient->addColorStop(0.5, Color(66, 106, 174, 240));
+        barStrokeGradient->addColorStop(1.0, Color(38, 104, 166));
+        context->setStrokeGradient(barStrokeGradient.release());
+
+        Path barPath;
+        int left = rect.x();
+        if (!renderProgress->style().isLeftToRightDirection())
+            left = rect.maxX() - barWidth;
+        FloatRect barRect(left + 0.25, verticalRenderingPosition + 0.25, std::max(barWidth - 0.5, 0.0), progressBarHeight - 0.5);
+        barPath.addRoundedRect(barRect, roundedCornerRadius);
+        context->drawPath(barPath);
+    }
+
+    return false;
+}
+#endif // ENABLE(PROGRESS_ELEMENT)
+
+#if ENABLE(DATALIST_ELEMENT)
+IntSize RenderThemeIOS::sliderTickSize() const
+{
+    // FIXME: <rdar://problem/12271791> MERGEBOT: Correct values for slider tick of <input type="range"> elements (requires ENABLE_DATALIST_ELEMENT)
+    return IntSize(1, 3);
+}
+
+int RenderThemeIOS::sliderTickOffsetFromTrackCenter() const
+{
+    // FIXME: <rdar://problem/12271791> MERGEBOT: Correct values for slider tick of <input type="range"> elements (requires ENABLE_DATALIST_ELEMENT)
+    return -9;
+}
+#endif
+
+void RenderThemeIOS::adjustSearchFieldStyle(StyleResolver* selector, RenderStyle* style, Element* element) const
+{
+    RenderTheme::adjustSearchFieldStyle(selector, style, element);
+
+    if (!element)
+        return;
+
+    if (!style->hasBorder())
+        return;
+
+    RenderBox* box = element->renderBox();
+    if (!box)
+        return;
+
+    adjustRoundBorderRadius(*style, box);
+}
+
+bool RenderThemeIOS::paintSearchFieldDecorations(RenderObject* box, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return paintTextFieldDecorations(box, paintInfo, rect);
+}
+
+void RenderThemeIOS::adjustButtonStyle(StyleResolver* selector, RenderStyle* style, Element* element) const
+{
+    RenderTheme::adjustButtonStyle(selector, style, element);
+
+    // Set padding: 0 1.0em; on buttons.
+    // CSSPrimitiveValue::computeLengthInt only needs the element's style to calculate em lengths.
+    // Since the element might not be in a document, just pass nullptr for the root element style.
+    RefPtr<CSSPrimitiveValue> emSize = CSSPrimitiveValue::create(1.0, CSSPrimitiveValue::CSS_EMS);
+    int pixels = emSize->computeLength<int>(style, nullptr);
+    style->setPaddingBox(LengthBox(0, pixels, 0, pixels));
+
+    if (!element)
+        return;
+
+    RenderBox* box = element->renderBox();
+    if (!box)
+        return;
+
+    adjustRoundBorderRadius(*style, box);
+}
+
+bool RenderThemeIOS::paintButtonDecorations(RenderObject* box, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return paintPushButtonDecorations(box, paintInfo, rect);
+}
+
+bool RenderThemeIOS::paintPushButtonDecorations(RenderObject* box, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+    FloatRect clip = addRoundedBorderClip(box, paintInfo.context, rect);
+
+    CGContextRef cgContext = paintInfo.context->platformContext();
+    if (box->style().visitedDependentColor(CSSPropertyBackgroundColor).isDark())
+        drawAxialGradient(cgContext, gradientWithName(ConvexGradient), clip.location(), FloatPoint(clip.x(), clip.maxY()), LinearInterpolation);
+    else {
+        drawAxialGradient(cgContext, gradientWithName(ShadeGradient), clip.location(), FloatPoint(clip.x(), clip.maxY()), LinearInterpolation);
+        drawAxialGradient(cgContext, gradientWithName(ShineGradient), FloatPoint(clip.x(), clip.maxY()), clip.location(), ExponentialInterpolation);
+    }
+    return false;
+}
+
+void RenderThemeIOS::setButtonSize(RenderStyle* style) const
+{
+    // If the width and height are both specified, then we have nothing to do.
+    if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+        return;
+
+    // Use the font size to determine the intrinsic width of the control.
+    style->setHeight(Length(static_cast<int>(ControlBaseHeight / ControlBaseFontSize * style->fontDescription().computedSize()), Fixed));
+}
+
+const int kThumbnailBorderStrokeWidth = 1;
+const int kThumbnailBorderCornerRadius = 1;
+const int kVisibleBackgroundImageWidth = 1;
+const int kMultipleThumbnailShrinkSize = 2;
+
+bool RenderThemeIOS::paintFileUploadIconDecorations(RenderObject*, RenderObject* buttonRenderer, const PaintInfo& paintInfo, const IntRect& rect, Icon* icon, FileUploadDecorations fileUploadDecorations)
+{
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+    IntSize cornerSize(kThumbnailBorderCornerRadius, kThumbnailBorderCornerRadius);
+    Color pictureFrameColor = buttonRenderer ? buttonRenderer->style().visitedDependentColor(CSSPropertyBorderTopColor) : Color(76.0f, 76.0f, 76.0f);
+
+    IntRect thumbnailPictureFrameRect = rect;
+    IntRect thumbnailRect = rect;
+    thumbnailRect.contract(2 * kThumbnailBorderStrokeWidth, 2 * kThumbnailBorderStrokeWidth);
+    thumbnailRect.move(kThumbnailBorderStrokeWidth, kThumbnailBorderStrokeWidth);
+
+    if (fileUploadDecorations == MultipleFiles) {
+        // Smaller thumbnails for multiple selection appearance.
+        thumbnailPictureFrameRect.contract(kMultipleThumbnailShrinkSize, kMultipleThumbnailShrinkSize);
+        thumbnailRect.contract(kMultipleThumbnailShrinkSize, kMultipleThumbnailShrinkSize);
+
+        // Background picture frame and simple background icon with a gradient matching the button.
+        Color backgroundImageColor = buttonRenderer ? Color(buttonRenderer->style().visitedDependentColor(CSSPropertyBackgroundColor).rgb()) : Color(206.0f, 206.0f, 206.0f);
+        paintInfo.context->fillRoundedRect(thumbnailPictureFrameRect, cornerSize, cornerSize, cornerSize, cornerSize, pictureFrameColor, ColorSpaceDeviceRGB);
+        paintInfo.context->fillRect(thumbnailRect, backgroundImageColor, ColorSpaceDeviceRGB);
+        {
+            GraphicsContextStateSaver stateSaver2(*paintInfo.context);
+            CGContextRef cgContext = paintInfo.context->platformContext();
+            paintInfo.context->clip(thumbnailRect);
+            if (backgroundImageColor.isDark())
+                drawAxialGradient(cgContext, gradientWithName(ConvexGradient), thumbnailRect.location(), FloatPoint(thumbnailRect.x(), thumbnailRect.maxY()), LinearInterpolation);
+            else {
+                drawAxialGradient(cgContext, gradientWithName(ShadeGradient), thumbnailRect.location(), FloatPoint(thumbnailRect.x(), thumbnailRect.maxY()), LinearInterpolation);
+                drawAxialGradient(cgContext, gradientWithName(ShineGradient), FloatPoint(thumbnailRect.x(), thumbnailRect.maxY()), thumbnailRect.location(), ExponentialInterpolation);
+            }
+        }
+
+        // Move the rects for the Foreground picture frame and icon.
+        int inset = kVisibleBackgroundImageWidth + kThumbnailBorderStrokeWidth;
+        thumbnailPictureFrameRect.move(inset, inset);
+        thumbnailRect.move(inset, inset);
+    }
+
+    // Foreground picture frame and icon.
+    paintInfo.context->fillRoundedRect(thumbnailPictureFrameRect, cornerSize, cornerSize, cornerSize, cornerSize, pictureFrameColor, ColorSpaceDeviceRGB);
+    icon->paint(paintInfo.context, thumbnailRect);
+
+    return false;
+}
+    
+Color RenderThemeIOS::platformActiveSelectionBackgroundColor() const
+{
+    return Color::transparent;
+}
+
+Color RenderThemeIOS::platformInactiveSelectionBackgroundColor() const
+{
+    return Color::transparent;
+}
+
+bool RenderThemeIOS::shouldShowPlaceholderWhenFocused() const
+{
+    return true;
+}
+
+bool RenderThemeIOS::shouldHaveSpinButton(HTMLInputElement*) const
+{
+    return false;
+}
+
+static FontWeight fromCTFontWeight(float fontWeight)
+{
+    if (fontWeight <= -0.8)
+        return FontWeight100;
+    else if (fontWeight <= -0.4)
+        return FontWeight200;
+    else if (fontWeight <= -0.2)
+        return FontWeight300;
+    else if (fontWeight <= 0.0)
+        return FontWeight400;
+    else if (fontWeight <= 0.2)
+        return FontWeight500;
+    else if (fontWeight <= 0.3)
+        return FontWeight600;
+    else if (fontWeight <= 0.4)
+        return FontWeight700;
+    else if (fontWeight <= 0.6)
+        return FontWeight800;
+    else if (fontWeight <= 0.8)
+        return FontWeight900;
+
+    return FontWeightNormal;
+}
+
+void RenderThemeIOS::systemFont(CSSValueID valueID, FontDescription& fontDescription) const
+{
+    static NeverDestroyed<FontDescription> systemFont;
+    static NeverDestroyed<FontDescription> headlineFont;
+    static NeverDestroyed<FontDescription> bodyFont;
+    static NeverDestroyed<FontDescription> subheadlineFont;
+    static NeverDestroyed<FontDescription> footnoteFont;
+    static NeverDestroyed<FontDescription> caption1Font;
+    static NeverDestroyed<FontDescription> caption2Font;
+    static NeverDestroyed<FontDescription> shortHeadlineFont;
+    static NeverDestroyed<FontDescription> shortBodyFont;
+    static NeverDestroyed<FontDescription> shortSubheadlineFont;
+    static NeverDestroyed<FontDescription> shortFootnoteFont;
+    static NeverDestroyed<FontDescription> shortCaption1Font;
+    static NeverDestroyed<FontDescription> tallBodyFont;
+
+    static CFStringRef userTextSize = contentSizeCategory();
+
+    if (userTextSize != contentSizeCategory()) {
+        userTextSize = contentSizeCategory();
+
+        headlineFont.setIsAbsoluteSize(false);
+        bodyFont.setIsAbsoluteSize(false);
+        subheadlineFont.setIsAbsoluteSize(false);
+        footnoteFont.setIsAbsoluteSize(false);
+        caption1Font.setIsAbsoluteSize(false);
+        caption2Font.setIsAbsoluteSize(false);
+        shortHeadlineFont.setIsAbsoluteSize(false);
+        shortBodyFont.setIsAbsoluteSize(false);
+        shortSubheadlineFont.setIsAbsoluteSize(false);
+        shortFootnoteFont.setIsAbsoluteSize(false);
+        shortCaption1Font.setIsAbsoluteSize(false);
+        tallBodyFont.setIsAbsoluteSize(false);
+    }
+
+    FontDescription* cachedDesc;
+    RetainPtr<CTFontDescriptorRef> fontDescriptor;
+    CFStringRef textStyle;
+    switch (valueID) {
+    case CSSValueAppleSystemHeadline:
+        cachedDesc = &headlineFont;
+        textStyle = kCTUIFontTextStyleHeadline;
+        if (!headlineFont.isAbsoluteSize())
+            fontDescriptor = adoptCF(CTFontDescriptorCreateWithTextStyle(textStyle, userTextSize, 0));
+        break;
+    case CSSValueAppleSystemBody:
+        cachedDesc = &bodyFont;
+        textStyle = kCTUIFontTextStyleBody;
+        if (!bodyFont.isAbsoluteSize())
+            fontDescriptor = adoptCF(CTFontDescriptorCreateWithTextStyle(textStyle, userTextSize, 0));
+        break;
+    case CSSValueAppleSystemSubheadline:
+        cachedDesc = &subheadlineFont;
+        textStyle = kCTUIFontTextStyleSubhead;
+        if (!subheadlineFont.isAbsoluteSize())
+            fontDescriptor = adoptCF(CTFontDescriptorCreateWithTextStyle(textStyle, userTextSize, 0));
+        break;
+    case CSSValueAppleSystemFootnote:
+        cachedDesc = &footnoteFont;
+        textStyle = kCTUIFontTextStyleFootnote;
+        if (!footnoteFont.isAbsoluteSize())
+            fontDescriptor = adoptCF(CTFontDescriptorCreateWithTextStyle(textStyle, userTextSize, 0));
+        break;
+    case CSSValueAppleSystemCaption1:
+        cachedDesc = &caption1Font;
+        textStyle = kCTUIFontTextStyleCaption1;
+        if (!caption1Font.isAbsoluteSize())
+            fontDescriptor = adoptCF(CTFontDescriptorCreateWithTextStyle(textStyle, userTextSize, 0));
+        break;
+    case CSSValueAppleSystemCaption2:
+        cachedDesc = &caption2Font;
+        textStyle = kCTUIFontTextStyleCaption2;
+        if (!caption2Font.isAbsoluteSize())
+            fontDescriptor = adoptCF(CTFontDescriptorCreateWithTextStyle(textStyle, userTextSize, 0));
+        break;
+
+    // Short version.
+    case CSSValueAppleSystemShortHeadline:
+        cachedDesc = &shortHeadlineFont;
+        textStyle = kCTUIFontTextStyleShortHeadline;
+        if (!shortHeadlineFont.isAbsoluteSize())
+            fontDescriptor = adoptCF(CTFontDescriptorCreateWithTextStyle(textStyle, userTextSize, 0));
+        break;
+    case CSSValueAppleSystemShortBody:
+        cachedDesc = &shortBodyFont;
+        textStyle = kCTUIFontTextStyleShortBody;
+        if (!shortBodyFont.isAbsoluteSize())
+            fontDescriptor = adoptCF(CTFontDescriptorCreateWithTextStyle(textStyle, userTextSize, 0));
+        break;
+    case CSSValueAppleSystemShortSubheadline:
+        cachedDesc = &shortSubheadlineFont;
+        textStyle = kCTUIFontTextStyleShortSubhead;
+        if (!shortSubheadlineFont.isAbsoluteSize())
+            fontDescriptor = adoptCF(CTFontDescriptorCreateWithTextStyle(textStyle, userTextSize, 0));
+        break;
+    case CSSValueAppleSystemShortFootnote:
+        cachedDesc = &shortFootnoteFont;
+        textStyle = kCTUIFontTextStyleShortFootnote;
+        if (!shortFootnoteFont.isAbsoluteSize())
+            fontDescriptor = adoptCF(CTFontDescriptorCreateWithTextStyle(textStyle, userTextSize, 0));
+        break;
+    case CSSValueAppleSystemShortCaption1:
+        cachedDesc = &shortCaption1Font;
+        textStyle = kCTUIFontTextStyleShortCaption1;
+        if (!shortCaption1Font.isAbsoluteSize())
+            fontDescriptor = adoptCF(CTFontDescriptorCreateWithTextStyle(textStyle, userTextSize, 0));
+        break;
+
+    // Tall version.
+    case CSSValueAppleSystemTallBody:
+        cachedDesc = &tallBodyFont;
+        textStyle = kCTUIFontTextStyleTallBody;
+        if (!tallBodyFont.isAbsoluteSize())
+            fontDescriptor = adoptCF(CTFontDescriptorCreateWithTextStyle(textStyle, userTextSize, 0));
+        break;
+
+    default:
+        textStyle = kCTFontDescriptorTextStyleEmphasized;
+        cachedDesc = &systemFont;
+        if (!systemFont.isAbsoluteSize())
+            fontDescriptor = adoptCF(CTFontDescriptorCreateForUIType(kCTFontSystemFontType, 0, nullptr));
+    }
+
+    if (fontDescriptor) {
+        RetainPtr<CTFontRef> font = adoptCF(CTFontCreateWithFontDescriptor(fontDescriptor.get(), 0, nullptr));
+        cachedDesc->setIsAbsoluteSize(true);
+        cachedDesc->setGenericFamily(FontDescription::NoFamily);
+        cachedDesc->setOneFamily(textStyle);
+        cachedDesc->setSpecifiedSize(CTFontGetSize(font.get()));
+        cachedDesc->setWeight(fromCTFontWeight(FontCache::weightOfCTFont(font.get())));
+        cachedDesc->setItalic(0);
+    }
+    fontDescription = *cachedDesc;
+}
+
+#if ENABLE(VIDEO)
+String RenderThemeIOS::mediaControlsStyleSheet()
+{
+#if ENABLE(MEDIA_CONTROLS_SCRIPT)
+    return String(mediaControlsiOSUserAgentStyleSheet, sizeof(mediaControlsiOSUserAgentStyleSheet));
+#else
+    return emptyString();
+#endif
+}
+
+String RenderThemeIOS::mediaControlsScript()
+{
+#if ENABLE(MEDIA_CONTROLS_SCRIPT)
+    return String(mediaControlsAppleJavaScript, sizeof(mediaControlsAppleJavaScript));
+#else
+    return emptyString();
+#endif
+}
+#endif // ENABLE(VIDEO)
+
+}
+
+#endif //PLATFORM(IOS)
index 2b9a6ad..e2519c3 100644 (file)
@@ -19,6 +19,7 @@
  * Boston, MA 02110-1301, USA.
  *
  */
+#if !PLATFORM(IOS)
 
 #ifndef RenderThemeMac_h
 #define RenderThemeMac_h
@@ -235,3 +236,5 @@ private:
 } // namespace WebCore
 
 #endif // RenderThemeMac_h
+
+#endif // !PLATFORM(IOS)
index 915a0a9..2c5d8ad 100644 (file)
@@ -16,6 +16,7 @@
  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301, USA.
  */
+#if !PLATFORM(IOS)
 
 #import "config.h"
 #import "RenderThemeMac.h"
@@ -1933,3 +1934,5 @@ String RenderThemeMac::fileListNameForWidth(const FileList* fileList, const Font
 
 
 } // namespace WebCore
+
+#endif // !PLATFORM(IOS)
index e31c46f..fe7d3ea 100644 (file)
@@ -116,11 +116,13 @@ LayoutSize RenderVideo::calculateIntrinsicSize()
     if (videoElement().shouldDisplayPosterImage() && !m_cachedImageSize.isEmpty() && !imageResource()->errorOccurred())
         return m_cachedImageSize;
 
+#if !PLATFORM(IOS)
     // When the natural size of the video is unavailable, we use the provided
     // width and height attributes of the video element as the intrinsic size until
     // better values become available.
     if (videoElement().hasAttribute(widthAttr) && videoElement().hasAttribute(heightAttr))
         return LayoutSize(videoElement().width(), videoElement().height());
+#endif
 
     // <video> in standalone media documents should not use the default 300x150
     // size since they also have audio-only files. By setting the intrinsic
index 7b93f03..7e56fc2 100644 (file)
@@ -137,6 +137,11 @@ LayoutUnit RenderView::availableLogicalHeight(AvailableLogicalHeightType) const
     // If we have columns, then the available logical height is reduced to the column height.
     if (hasColumns())
         return columnInfo()->columnHeight();
+#if PLATFORM(IOS)
+    // Workaround for <rdar://problem/7166808>.
+    if (document().isPluginDocument() && frameView().useFixedLayout())
+        return frameView().fixedLayoutSize().height();
+#endif
     return isHorizontalWritingMode() ? frameView().visibleHeight() : frameView().visibleWidth();
 }
 
@@ -363,6 +368,13 @@ LayoutUnit RenderView::pageOrViewLogicalHeight() const
     return viewLogicalHeight();
 }
 
+#if PLATFORM(IOS)
+static inline LayoutSize fixedPositionOffset(const FrameView& frameView)
+{
+    return frameView.useCustomFixedPositionLayoutRect() ? (frameView.customFixedPositionLayoutRect().location() - LayoutPoint()) : frameView->scrollOffset();
+}
+#endif
+
 void RenderView::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
 {
     // If a container was specified, and was not 0 or the RenderView,
@@ -377,7 +389,11 @@ void RenderView::mapLocalToContainer(const RenderLayerModelObject* repaintContai
     }
     
     if (mode & IsFixed)
+#if PLATFORM(IOS)
+        transformState.move(fixedPositionOffset(m_frameView));
+#else
         transformState.move(frameView().scrollOffsetForFixedPosition());
+#endif
 }
 
 const RenderObject* RenderView::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
@@ -386,7 +402,11 @@ const RenderObject* RenderView::pushMappingToContainer(const RenderLayerModelObj
     // then we should have found it by now.
     ASSERT_ARG(ancestorToStopAt, !ancestorToStopAt || ancestorToStopAt == this);
 
+#if PLATFORM(IOS)
+    LayoutSize scrollOffset = fixedPositionOffset(frameView());
+#else
     LayoutSize scrollOffset = frameView().scrollOffsetForFixedPosition();
+#endif
 
     if (!ancestorToStopAt && shouldUseTransformFromContainer(0)) {
         TransformationMatrix t;
@@ -401,7 +421,11 @@ const RenderObject* RenderView::pushMappingToContainer(const RenderLayerModelObj
 void RenderView::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
 {
     if (mode & IsFixed)
+#if PLATFORM(IOS)
+        transformState.move(fixedPositionOffset(frameView()));
+#else
         transformState.move(frameView().scrollOffsetForFixedPosition());
+#endif
 
     if (mode & UseTransforms && shouldUseTransformFromContainer(0)) {
         TransformationMatrix t;
@@ -572,7 +596,12 @@ void RenderView::repaintViewRectangle(const LayoutRect& ur, bool immediate) cons
         frameView().repaintContentRectangle(pixelSnappedIntRect(ur), immediate);
     else if (RenderBox* obj = elt->renderBox()) {
         LayoutRect vr = viewRect();
+#if PLATFORM(IOS)
+        // Don't clip using the visible rect since clipping is handled at a higher level on iPhone.
+        LayoutRect r = ur;
+#else
         LayoutRect r = intersection(ur, vr);
+#endif
         
         // Subtract out the contentsX and contentsY offsets to get our coords within the viewing
         // rectangle.
@@ -636,8 +665,13 @@ void RenderView::computeRectForRepaint(const RenderLayerModelObject* repaintCont
             rect.setX(viewWidth() - rect.maxX());
     }
 
-    if (fixed)
+    if (fixed) {
+#if PLATFORM(IOS)
+        rect.move(fixedPositionOffset(frameView()));
+#else
         rect.move(frameView().scrollOffsetForFixedPosition());
+#endif
+    }
         
     // Apply our transform if we have one (because of full page zooming).
     if (!repaintContainer && layer() && layer()->transform())
@@ -1156,6 +1190,24 @@ FlowThreadController& RenderView::flowThreadController()
     return *m_flowThreadController;
 }
 
+#if PLATFORM(IOS)
+static bool isFixedPositionInViewport(const RenderObject& renderer, const RenderObject* container)
+{
+    return (renderer.style().position() == FixedPosition) && renderer.container() == container;
+}
+
+bool RenderView::hasCustomFixedPosition(const RenderObject& renderer, ContainingBlockCheck checkContainer) const
+{
+    if (!frameView().useCustomFixedPositionLayoutRect())
+        return false;
+
+    if (checkContainer == CheckContainingBlock)
+        return isFixedPositionInViewport(renderer, this);
+
+    return renderer.style().position() == FixedPosition;
+}
+#endif
+
 void RenderView::pushLayoutStateForCurrentFlowThread(const RenderObject& object)
 {
     if (!m_flowThreadController)
index e2b2842..6f3bb7d 100644 (file)
@@ -204,6 +204,11 @@ public:
 
     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
 
+#if PLATFORM(IOS)
+    enum ContainingBlockCheck { CheckContainingBlock, DontCheckContainingBlock };
+    bool hasCustomFixedPosition(const RenderObject&, ContainingBlockCheck = CheckContainingBlock) const;
+#endif
+
     IntervalArena* intervalArena();
 
     IntSize viewportSize() const;
index fc2095d..1afd916 100644 (file)
@@ -91,6 +91,11 @@ RenderWidget::RenderWidget(HTMLFrameOwnerElement& element, PassRef<RenderStyle>
 
 void RenderWidget::willBeDestroyed()
 {
+#if PLATFORM(IOS)
+    if (hasLayer())
+        layer()->willBeDestroyed();
+#endif
+
     if (AXObjectCache* cache = document().existingAXObjectCache()) {
         cache->childrenChanged(this->parent());
         cache->remove(this);
index 18d7389..4f9e92b 100644 (file)
@@ -846,7 +846,11 @@ void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallb
     bool setUsedFontWithLeading = false;
 
     const RenderStyle& boxLineStyle = box->lineStyle();
+#if PLATFORM(IOS)
+    if (usedFonts && !usedFonts->isEmpty() && (includeFont || (boxLineStyle.lineHeight().isNegative() && includeLeading)) && !box->renderer().document().settings()->alwaysUseBaselineOfPrimaryFont()) {
+#else
     if (usedFonts && !usedFonts->isEmpty() && (includeFont || (boxLineStyle.lineHeight().isNegative() && includeLeading))) {
+#endif
         usedFonts->append(boxLineStyle.font().primaryFont());
         for (size_t i = 0; i < usedFonts->size(); ++i) {
             const FontMetrics& fontMetrics = usedFonts->at(i)->fontMetrics();
index 593feef..704dffe 100644 (file)
@@ -32,7 +32,7 @@
 #include <wtf/StdLibExtras.h>
 #include <wtf/unicode/CharacterNames.h>
 
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) && !PLATFORM(IOS)
 #include <CoreServices/CoreServices.h>
 #endif