diff options
author | Konstantin Tokarev <annulen@yandex.ru> | 2016-08-25 19:20:41 +0300 |
---|---|---|
committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-02-02 12:30:55 +0000 |
commit | 6882a04fb36642862b11efe514251d32070c3d65 (patch) | |
tree | b7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebCore/rendering/RenderFileUploadControl.cpp | |
parent | ab6df191029eeeb0b0f16f127d553265659f739e (diff) | |
download | qtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz |
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f
Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/WebCore/rendering/RenderFileUploadControl.cpp')
-rw-r--r-- | Source/WebCore/rendering/RenderFileUploadControl.cpp | 140 |
1 files changed, 83 insertions, 57 deletions
diff --git a/Source/WebCore/rendering/RenderFileUploadControl.cpp b/Source/WebCore/rendering/RenderFileUploadControl.cpp index 6113cef0c..4f364192e 100644 --- a/Source/WebCore/rendering/RenderFileUploadControl.cpp +++ b/Source/WebCore/rendering/RenderFileUploadControl.cpp @@ -21,9 +21,8 @@ #include "config.h" #include "RenderFileUploadControl.h" -#include "ElementShadow.h" #include "FileList.h" -#include "Font.h" +#include "FontCascade.h" #include "GraphicsContext.h" #include "HTMLInputElement.h" #include "HTMLNames.h" @@ -38,22 +37,30 @@ #include "VisiblePosition.h" #include <math.h> -using namespace std; +#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) - : RenderBlock(input) - , m_canReceiveDroppedFiles(input->canReceiveDroppedFiles()) +RenderFileUploadControl::RenderFileUploadControl(HTMLInputElement& input, Ref<RenderStyle>&& style) + : RenderBlockFlow(input, WTFMove(style)) + , m_canReceiveDroppedFiles(input.canReceiveDroppedFiles()) { } @@ -61,18 +68,17 @@ RenderFileUploadControl::~RenderFileUploadControl() { } -bool RenderFileUploadControl::canBeReplacedWithInlineRunIn() const +HTMLInputElement& RenderFileUploadControl::inputElement() const { - return false; + return downcast<HTMLInputElement>(nodeForNonAnonymous()); } void RenderFileUploadControl::updateFromElement() { - HTMLInputElement* input = toHTMLInputElement(node()); - ASSERT(input->isFileUpload()); + ASSERT(inputElement().isFileUpload()); if (HTMLInputElement* button = uploadButton()) { - bool newCanReceiveDroppedFilesState = input->canReceiveDroppedFiles(); + bool newCanReceiveDroppedFilesState = inputElement().canReceiveDroppedFiles(); if (m_canReceiveDroppedFiles != newCanReceiveDroppedFilesState) { m_canReceiveDroppedFiles = newCanReceiveDroppedFilesState; button->setActive(newCanReceiveDroppedFilesState); @@ -81,7 +87,7 @@ void RenderFileUploadControl::updateFromElement() // This only supports clearing out the files, but that's OK because for // security reasons that's the only change the DOM is allowed to make. - FileList* files = input->files(); + FileList* files = inputElement().files(); ASSERT(files); if (files && files->isEmpty()) repaint(); @@ -89,50 +95,61 @@ void RenderFileUploadControl::updateFromElement() static int nodeWidth(Node* node) { - return (node && node->renderBox()) ? node->renderBox()->pixelSnappedWidth() : 0; + return (node && node->renderBox()) ? roundToInt(node->renderBox()->size().width()) : 0; } +#if PLATFORM(IOS) +static int nodeHeight(Node* node) +{ + return (node && node->renderBox()) ? roundToInt(node->renderBox()->size().height()) : 0; +} +#endif + int RenderFileUploadControl::maxFilenameWidth() const { - HTMLInputElement* input = toHTMLInputElement(node()); - return max(0, contentBoxRect().pixelSnappedWidth() - nodeWidth(uploadButton()) - afterButtonSpacing - - (input->icon() ? iconWidth + iconFilenameSpacing : 0)); +#if PLATFORM(IOS) + int iconWidth = nodeHeight(uploadButton()); +#endif + return std::max(0, snappedIntRect(contentBoxRect()).width() - nodeWidth(uploadButton()) - afterButtonSpacing + - (inputElement().icon() ? iconWidth + iconFilenameSpacing : 0)); } void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { - if (style()->visibility() != VISIBLE) + if (style().visibility() != VISIBLE) return; // Push a clip. - GraphicsContextStateSaver stateSaver(*paintInfo.context, false); + GraphicsContextStateSaver stateSaver(paintInfo.context(), false); if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) { IntRect clipRect = enclosingIntRect(LayoutRect(paintOffset.x() + borderLeft(), paintOffset.y() + borderTop(), width() - borderLeft() - borderRight(), height() - borderBottom() - borderTop() + buttonShadowHeight)); if (clipRect.isEmpty()) return; stateSaver.save(); - paintInfo.context->clip(clipRect); + paintInfo.context().clip(clipRect); } if (paintInfo.phase == PaintPhaseForeground) { const String& displayedFilename = fileTextValue(); - const Font& font = style()->font(); - TextRun textRun = constructTextRun(this, font, displayedFilename, style(), TextRun::AllowTrailingExpansion, RespectDirection | RespectDirectionOverride); - textRun.disableRoundingHacks(); + const FontCascade& font = style().fontCascade(); + TextRun textRun = constructTextRun(this, font, displayedFilename, style(), AllowTrailingExpansion, RespectDirection | RespectDirectionOverride); +#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(); if (!button) return; - HTMLInputElement* input = toHTMLInputElement(node()); LayoutUnit buttonWidth = nodeWidth(button); LayoutUnit buttonAndIconWidth = buttonWidth + afterButtonSpacing - + (input->icon() ? iconWidth + iconFilenameSpacing : 0); + + (inputElement().icon() ? iconWidth + iconFilenameSpacing : 0); LayoutUnit textX; - if (style()->isLeftToRightDirection()) + if (style().isLeftToRightDirection()) textX = contentLeft + buttonAndIconWidth; else textX = contentLeft + contentWidth() - buttonAndIconWidth - font.width(textRun); @@ -140,32 +157,41 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoin LayoutUnit textY = 0; // We want to match the button's baseline // FIXME: Make this work with transforms. - if (RenderButton* buttonRenderer = toRenderButton(button->renderer())) + if (RenderButton* buttonRenderer = downcast<RenderButton>(button->renderer())) textY = paintOffset.y() + borderTop() + paddingTop() + buttonRenderer->baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine); else textY = baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine); - paintInfo.context->setFillColor(style()->visitedDependentColor(CSSPropertyColor), style()->colorSpace()); + paintInfo.context().setFillColor(style().visitedDependentColor(CSSPropertyColor)); // Draw the filename - paintInfo.context->drawBidiText(font, textRun, IntPoint(roundToInt(textX), roundToInt(textY))); + paintInfo.context().drawBidiText(font, textRun, IntPoint(roundToInt(textX), roundToInt(textY))); - if (input->icon()) { + if (inputElement().icon()) { // Determine where the icon should be placed LayoutUnit iconY = paintOffset.y() + borderTop() + paddingTop() + (contentHeight() - iconHeight) / 2; LayoutUnit iconX; - if (style()->isLeftToRightDirection()) + if (style().isLeftToRightDirection()) iconX = contentLeft + buttonWidth + afterButtonSpacing; else iconX = contentLeft + contentWidth() - buttonWidth - afterButtonSpacing - iconWidth; +#if PLATFORM(IOS) + if (RenderButton* buttonRenderer = downcast<RenderButton>(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 - input->icon()->paint(paintInfo.context, IntRect(roundToInt(iconX), roundToInt(iconY), iconWidth, iconHeight)); + inputElement().icon()->paint(paintInfo.context(), IntRect(roundToInt(iconX), roundToInt(iconY), iconWidth, iconHeight)); +#endif } } // Paint the children. - RenderBlock::paintObject(paintInfo, paintOffset); + RenderBlockFlow::paintObject(paintInfo, paintOffset); } void RenderFileUploadControl::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const @@ -174,19 +200,19 @@ void RenderFileUploadControl::computeIntrinsicLogicalWidths(LayoutUnit& minLogic // (using "0" as the nominal character). const UChar character = '0'; const String characterAsString = String(&character, 1); - const Font& font = style()->font(); + const FontCascade& font = style().fontCascade(); // FIXME: Remove the need for this const_cast by making constructTextRun take a const RenderObject*. RenderFileUploadControl* renderer = const_cast<RenderFileUploadControl*>(this); - float minDefaultLabelWidth = defaultWidthNumChars * font.width(constructTextRun(renderer, font, characterAsString, style(), TextRun::AllowTrailingExpansion)); + float minDefaultLabelWidth = defaultWidthNumChars * font.width(constructTextRun(renderer, font, characterAsString, style(), AllowTrailingExpansion)); - const String label = theme()->fileListDefaultLabel(node()->toInputElement()->multiple()); - float defaultLabelWidth = font.width(constructTextRun(renderer, font, label, style(), TextRun::AllowTrailingExpansion)); + const String label = theme().fileListDefaultLabel(inputElement().multiple()); + float defaultLabelWidth = font.width(constructTextRun(renderer, font, label, style(), AllowTrailingExpansion)); if (HTMLInputElement* button = uploadButton()) if (RenderObject* buttonRenderer = button->renderer()) defaultLabelWidth += buttonRenderer->maxPreferredLogicalWidth() + afterButtonSpacing; - maxLogicalWidth = static_cast<int>(ceilf(max(minDefaultLabelWidth, defaultLabelWidth))); + maxLogicalWidth = static_cast<int>(ceilf(std::max(minDefaultLabelWidth, defaultLabelWidth))); - if (!style()->width().isPercent()) + if (!style().width().isPercentOrCalculated()) minLogicalWidth = maxLogicalWidth; } @@ -197,41 +223,38 @@ void RenderFileUploadControl::computePreferredLogicalWidths() m_minPreferredLogicalWidth = 0; m_maxPreferredLogicalWidth = 0; - if (style()->width().isFixed() && style()->width().value() > 0) - m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value()); + if (style().width().isFixed() && style().width().value() > 0) + m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style().width().value()); else computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth); - if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) { - m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value())); - m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value())); + if (style().minWidth().isFixed() && style().minWidth().value() > 0) { + m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style().minWidth().value())); + m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style().minWidth().value())); } - if (style()->maxWidth().isFixed()) { - m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value())); - m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value())); + if (style().maxWidth().isFixed()) { + m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style().maxWidth().value())); + m_minPreferredLogicalWidth = std::min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style().maxWidth().value())); } - int toAdd = borderAndPaddingWidth(); + int toAdd = horizontalBorderAndPaddingExtent(); m_minPreferredLogicalWidth += toAdd; m_maxPreferredLogicalWidth += toAdd; setPreferredLogicalWidthsDirty(false); } -VisiblePosition RenderFileUploadControl::positionForPoint(const LayoutPoint&) +VisiblePosition RenderFileUploadControl::positionForPoint(const LayoutPoint&, const RenderRegion*) { return VisiblePosition(); } HTMLInputElement* RenderFileUploadControl::uploadButton() const { - HTMLInputElement* input = toHTMLInputElement(node()); - - ASSERT(input->shadow()); - - Node* buttonNode = input->shadow()->shadowRoot()->firstChild(); - return buttonNode && buttonNode->isHTMLElement() && isHTMLInputElement(buttonNode) ? toHTMLInputElement(buttonNode) : 0; + ASSERT(inputElement().shadowRoot()); + Node* buttonNode = inputElement().shadowRoot()->firstChild(); + return is<HTMLInputElement>(buttonNode) ? downcast<HTMLInputElement>(buttonNode) : nullptr; } String RenderFileUploadControl::buttonValue() @@ -244,9 +267,12 @@ String RenderFileUploadControl::buttonValue() String RenderFileUploadControl::fileTextValue() const { - HTMLInputElement* input = toHTMLInputElement(node()); - ASSERT(input->files()); - return theme()->fileListNameForWidth(input->files(), style()->font(), maxFilenameWidth(), input->multiple()); + ASSERT(inputElement().files()); +#if PLATFORM(IOS) + if (inputElement().files()->length()) + return StringTruncator::rightTruncate(inputElement().displayString(), maxFilenameWidth(), style().fontCascade()); +#endif + return theme().fileListNameForWidth(inputElement().files(), style().fontCascade(), maxFilenameWidth(), inputElement().multiple()); } } // namespace WebCore |