summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/RenderFileUploadControl.cpp
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebCore/rendering/RenderFileUploadControl.cpp
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
downloadqtwebkit-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.cpp140
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