blob: 0dab0a98e6e9b13c5b7ef5ea3e4f39431f219dbb [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/paint/FileUploadControlPainter.h"
#include "core/layout/LayoutButton.h"
#include "core/layout/LayoutFileUploadControl.h"
#include "core/layout/TextRunConstructor.h"
#include "core/paint/LayoutObjectDrawingRecorder.h"
#include "core/paint/PaintInfo.h"
#include "platform/graphics/paint/ClipRecorder.h"
#include "wtf/Optional.h"
namespace blink {
const int buttonShadowHeight = 2;
void FileUploadControlPainter::paintObject(const PaintInfo& paintInfo,
const LayoutPoint& paintOffset) {
if (m_layoutFileUploadControl.style()->visibility() != EVisibility::Visible)
return;
// Push a clip.
Optional<ClipRecorder> clipRecorder;
if (paintInfo.phase == PaintPhaseForeground ||
paintInfo.phase == PaintPhaseDescendantBlockBackgroundsOnly) {
IntRect clipRect = enclosingIntRect(LayoutRect(
LayoutPoint(paintOffset.x() + m_layoutFileUploadControl.borderLeft(),
paintOffset.y() + m_layoutFileUploadControl.borderTop()),
m_layoutFileUploadControl.size() +
LayoutSize(0, -m_layoutFileUploadControl.borderWidth() +
buttonShadowHeight)));
if (clipRect.isEmpty())
return;
clipRecorder.emplace(paintInfo.context, m_layoutFileUploadControl,
DisplayItem::kClipFileUploadControlRect, clipRect);
}
if (paintInfo.phase == PaintPhaseForeground &&
!LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(
paintInfo.context, m_layoutFileUploadControl, paintInfo.phase)) {
const String& displayedFilename = m_layoutFileUploadControl.fileTextValue();
const Font& font = m_layoutFileUploadControl.style()->font();
TextRun textRun = constructTextRun(
font, displayedFilename, m_layoutFileUploadControl.styleRef(),
RespectDirection | RespectDirectionOverride);
textRun.setExpansionBehavior(TextRun::AllowTrailingExpansion);
// Determine where the filename should be placed
LayoutUnit contentLeft = paintOffset.x() +
m_layoutFileUploadControl.borderLeft() +
m_layoutFileUploadControl.paddingLeft();
Node* button = m_layoutFileUploadControl.uploadButton();
if (!button)
return;
int buttonWidth = (button && button->layoutBox())
? button->layoutBox()->pixelSnappedWidth()
: 0;
LayoutUnit buttonAndSpacingWidth(
buttonWidth + LayoutFileUploadControl::afterButtonSpacing);
float textWidth = font.width(textRun);
LayoutUnit textX;
if (m_layoutFileUploadControl.style()->isLeftToRightDirection())
textX = contentLeft + buttonAndSpacingWidth;
else
textX =
LayoutUnit(contentLeft + m_layoutFileUploadControl.contentWidth() -
buttonAndSpacingWidth - textWidth);
LayoutUnit textY;
// We want to match the button's baseline
// FIXME: Make this work with transforms.
if (LayoutButton* buttonLayoutObject =
toLayoutButton(button->layoutObject()))
textY = paintOffset.y() + m_layoutFileUploadControl.borderTop() +
m_layoutFileUploadControl.paddingTop() +
buttonLayoutObject->baselinePosition(AlphabeticBaseline, true,
HorizontalLine,
PositionOnContainingLine);
else
textY = LayoutUnit(m_layoutFileUploadControl.baselinePosition(
AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine));
TextRunPaintInfo textRunPaintInfo(textRun);
const SimpleFontData* fontData =
m_layoutFileUploadControl.style()->font().primaryFont();
if (!fontData)
return;
// FIXME: Shouldn't these offsets be rounded? crbug.com/350474
textRunPaintInfo.bounds = FloatRect(
textX.toFloat(), textY.toFloat() - fontData->getFontMetrics().ascent(),
textWidth, fontData->getFontMetrics().height());
// Draw the filename.
LayoutObjectDrawingRecorder recorder(
paintInfo.context, m_layoutFileUploadControl, paintInfo.phase,
textRunPaintInfo.bounds);
paintInfo.context.setFillColor(
m_layoutFileUploadControl.resolveColor(CSSPropertyColor));
paintInfo.context.drawBidiText(
font, textRunPaintInfo,
FloatPoint(roundToInt(textX), roundToInt(textY)));
}
// Paint the children.
m_layoutFileUploadControl.LayoutBlockFlow::paintObject(paintInfo,
paintOffset);
}
} // namespace blink