FloatPoint SVGPathBlender::blendAnimatedFloatPoint(const FloatPoint& fromPoint, const FloatPoint& toPoint) { if (m_fromMode == m_toMode) return blendFloatPoint(fromPoint, toPoint, m_progress); // Transform toPoint to the coordinate mode of fromPoint FloatPoint animatedPoint = toPoint; if (m_fromMode == AbsoluteCoordinates) animatedPoint += m_toCurrentPoint; else animatedPoint.move(-m_toCurrentPoint.x(), -m_toCurrentPoint.y()); animatedPoint = blendFloatPoint(fromPoint, animatedPoint, m_progress); if (m_isInFirstHalfOfAnimation) return animatedPoint; // Transform the animated point to the coordinate mode, needed for the current progress. FloatPoint currentPoint = blendFloatPoint(m_fromCurrentPoint, m_toCurrentPoint, m_progress); if (m_toMode == AbsoluteCoordinates) return animatedPoint + currentPoint; animatedPoint.move(-currentPoint.x(), -currentPoint.y()); return animatedPoint; }
TransformationMatrix SVGSVGElement::getScreenCTM() const { document()->updateLayoutIgnorePendingStylesheets(); FloatPoint rootLocation; if (RenderObject* renderer = this->renderer()) { if (isOutermostSVG()) { // FIXME: This doesn't work correctly with CSS transforms. FloatPoint point; if (renderer->parent()) point = renderer->localToAbsolute(point, true); rootLocation.move(point.x(), point.y()); } else rootLocation.move(x().value(this), y().value(this)); } TransformationMatrix mat = SVGStyledLocatableElement::getScreenCTM(); mat.translate(rootLocation.x(), rootLocation.y()); if (attributes()->getAttributeItem(SVGNames::viewBoxAttr)) { TransformationMatrix viewBox = viewBoxToViewTransform(width().value(this), height().value(this)); mat = viewBox * mat; } return mat; }
FloatPoint SVGPathBlender::BlendState::blendAnimatedFloatPoint( const FloatPoint& fromPoint, const FloatPoint& toPoint) { if (m_typesAreEqual) return blendAnimatedFloatPointSameCoordinates(fromPoint, toPoint); // Transform toPoint to the coordinate mode of fromPoint FloatPoint animatedPoint = toPoint; if (m_fromIsAbsolute) animatedPoint += m_toCurrentPoint; else animatedPoint.move(-m_toCurrentPoint.x(), -m_toCurrentPoint.y()); animatedPoint = blendFloatPoint(fromPoint, animatedPoint, m_progress); // If we're in the first half of the animation, we should use the type of the // from segment. if (m_isInFirstHalfOfAnimation) return animatedPoint; // Transform the animated point to the coordinate mode, needed for the current // progress. FloatPoint currentPoint = blendFloatPoint(m_fromCurrentPoint, m_toCurrentPoint, m_progress); if (!m_fromIsAbsolute) return animatedPoint + currentPoint; animatedPoint.move(-currentPoint.x(), -currentPoint.y()); return animatedPoint; }
void SVGGlyphToPathTranslator::advance() { do { if (m_glyph) { float advance = m_glyphBuffer.advanceAt(m_index).width(); if (m_isVerticalText) m_currentPoint.move(0, advance); else m_currentPoint.move(advance, 0); } ++m_index; if (m_index >= m_stoppingPoint || !m_glyphBuffer.fontDataAt(m_index)->isSVGFont()) break; m_glyph = m_glyphBuffer.glyphAt(m_index); if (!m_glyph) continue; m_svgGlyph = m_fontElement.svgGlyphForGlyph(m_glyph); ASSERT(!m_svgGlyph.isPartOfLigature); ASSERT(m_svgGlyph.tableEntry == m_glyph); SVGGlyphElement::inheritUnspecifiedAttributes(m_svgGlyph, &m_svgFontData); } while ((!m_glyph || m_svgGlyph.pathData.isEmpty()) && m_index < m_stoppingPoint); if (containsMorePaths() && m_isVerticalText) { m_glyphOrigin.setX(m_svgGlyph.verticalOriginX * m_scale); m_glyphOrigin.setY(m_svgGlyph.verticalOriginY * m_scale); } }
Optional<FloatPoint> RenderCombineText::computeTextOrigin(const FloatRect& boxRect) const { if (!m_isCombined) return Nullopt; // Visually center m_combinedTextWidth/Ascent/Descent within boxRect FloatPoint result = boxRect.minXMaxYCorner(); FloatSize combinedTextSize(m_combinedTextWidth, m_combinedTextAscent + m_combinedTextDescent); result.move((boxRect.size().transposedSize() - combinedTextSize) / 2); result.move(0, m_combinedTextAscent); return result; }
void RenderWidget::updateWidgetPosition() { if (!m_widget) return; // FIXME: This doesn't work correctly with transforms. FloatPoint absPos = localToAbsolute(); absPos.move(borderLeft() + paddingLeft(), borderTop() + paddingTop()); int w = width() - borderLeft() - borderRight() - paddingLeft() - paddingRight(); int h = height() - borderTop() - borderBottom() - paddingTop() - paddingBottom(); IntRect newBounds(absPos.x(), absPos.y(), w, h); IntRect oldBounds(m_widget->frameRect()); if (newBounds != oldBounds) { // The widget changed positions. Update the frame geometry. if (checkForRepaintDuringLayout()) { RenderView* v = view(); if (!v->printing()) { // FIXME: do container-relative repaint v->repaintRectangleInViewAndCompositedLayers(oldBounds); v->repaintRectangleInViewAndCompositedLayers(newBounds); } } RenderArena* arena = ref(); element()->ref(); m_widget->setFrameRect(newBounds); element()->deref(); deref(arena); } }
FloatPoint VisualViewport::rootFrameToViewport( const FloatPoint& pointInRootFrame) const { FloatPoint pointInViewport = pointInRootFrame; pointInViewport.move(-getScrollOffset()); pointInViewport.scale(scale(), scale()); return pointInViewport; }
FloatPoint VisualViewport::viewportToRootFrame( const FloatPoint& pointInViewport) const { FloatPoint pointInRootFrame = pointInViewport; pointInRootFrame.scale(1 / scale(), 1 / scale()); pointInRootFrame.move(getScrollOffset()); return pointInRootFrame; }
FloatPoint VisualViewport::viewportCSSPixelsToRootFrame( const FloatPoint& point) const { // Note, this is in CSS Pixels so we don't apply scale. FloatPoint pointInRootFrame = point; pointInRootFrame.move(getScrollOffset()); return pointInRootFrame; }
void RenderWidget::updateWidgetPosition() { if (!m_widget) return; // FIXME: This doesn't work correctly with transforms. FloatPoint absPos = localToAbsolute(); absPos.move(borderLeft() + paddingLeft(), borderTop() + paddingTop()); int w = width() - borderLeft() - borderRight() - paddingLeft() - paddingRight(); int h = height() - borderTop() - borderBottom() - paddingTop() - paddingBottom(); IntRect newBounds(absPos.x(), absPos.y(), w, h); IntRect oldBounds(m_widget->frameRect()); bool boundsChanged = newBounds != oldBounds; if (boundsChanged) { RenderArena* arena = ref(); node()->ref(); m_widget->setFrameRect(newBounds); node()->deref(); deref(arena); } // if the frame bounds got changed, or if view needs layout (possibly indicating // content size is wrong) we have to do a layout to set the right widget size if (m_widget->isFrameView()) { FrameView* frameView = static_cast<FrameView*>(m_widget.get()); if (boundsChanged || frameView->needsLayout()) frameView->layout(); } }
void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom) { GraphicsContext* context = paintInfo.context; RenderStyle* style = renderer().style(isFirstLineStyle()); const Font& font = style->font(); FloatPoint boxOrigin = locationIncludingFlipping(); boxOrigin.moveBy(FloatPoint(paintOffset)); if (!isHorizontal()) boxOrigin.move(0, -virtualLogicalHeight()); FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), virtualLogicalHeight())); GraphicsContextStateSaver stateSaver(*context); if (!isHorizontal()) context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Clockwise)); FloatPoint textOrigin = FloatPoint(boxOrigin.x(), boxOrigin.y() + font.fontMetrics().ascent()); Color styleTextColor = renderer().resolveColor(style, CSSPropertyWebkitTextFillColor); if (styleTextColor != context->fillColor()) context->setFillColor(styleTextColor); if (selectionState() != RenderObject::SelectionNone) { paintSelection(context, boxOrigin, style, font); // Select the correct color for painting the text. Color foreground = paintInfo.forceBlackText() ? Color::black : renderer().selectionForegroundColor(); if (foreground != styleTextColor) context->setFillColor(foreground); } // Text shadows are disabled when printing. http://crbug.com/258321 const ShadowList* shadowList = context->printing() ? 0 : style->textShadow(); bool hasShadow = shadowList; if (hasShadow) { OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create(); for (size_t i = shadowList->shadows().size(); i--; ) { const ShadowData& shadow = shadowList->shadows()[i]; float shadowX = isHorizontal() ? shadow.x() : shadow.y(); float shadowY = isHorizontal() ? shadow.y() : -shadow.x(); FloatSize offset(shadowX, shadowY); drawLooperBuilder->addShadow(offset, shadow.blur(), shadow.color(), DrawLooperBuilder::ShadowRespectsTransforms, DrawLooperBuilder::ShadowIgnoresAlpha); } drawLooperBuilder->addUnmodifiedContent(); context->setDrawLooper(drawLooperBuilder.release()); } TextRun textRun = RenderBlockFlow::constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion); TextRunPaintInfo textRunPaintInfo(textRun); textRunPaintInfo.bounds = boxRect; context->drawText(font, textRunPaintInfo, textOrigin); // Restore the regular fill color. if (styleTextColor != context->fillColor()) context->setFillColor(styleTextColor); if (hasShadow) context->clearDrawLooper(); paintMarkupBox(paintInfo, paintOffset, lineTop, lineBottom, style); }
bool SVGPathParser::parseCurveToQuadraticSmoothSegment() { FloatPoint targetPoint; if (!m_source.parseCurveToQuadraticSmoothSegment(targetPoint)) return false; if (m_lastCommand != PathSegCurveToQuadraticAbs && m_lastCommand != PathSegCurveToQuadraticRel && m_lastCommand != PathSegCurveToQuadraticSmoothAbs && m_lastCommand != PathSegCurveToQuadraticSmoothRel) m_controlPoint = m_currentPoint; if (m_pathParsingMode == NormalizedParsing) { FloatPoint cubicPoint = m_currentPoint; cubicPoint.scale(2); cubicPoint.move(-m_controlPoint.x(), -m_controlPoint.y()); FloatPoint point1(m_currentPoint.x() + 2 * cubicPoint.x(), m_currentPoint.y() + 2 * cubicPoint.y()); FloatPoint point2(targetPoint.x() + 2 * cubicPoint.x(), targetPoint.y() + 2 * cubicPoint.y()); if (m_mode == RelativeCoordinates) { point2 += m_currentPoint; targetPoint += m_currentPoint; } point1.scale(gOneOverThree); point2.scale(gOneOverThree); m_consumer.curveToCubic(point1, point2, targetPoint, AbsoluteCoordinates); m_controlPoint = cubicPoint; m_currentPoint = targetPoint; } else m_consumer.curveToQuadraticSmooth(targetPoint, m_mode); return true; }
void GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const FloatPoint& point) { if (paintingDisabled()) return; BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; bidiResolver.setStatus(BidiStatus(run.direction(), run.directionalOverride())); bidiResolver.setPosition(TextRunIterator(&run, 0)); // FIXME: This ownership should be reversed. We should pass BidiRunList // to BidiResolver in createBidiRunsForLine. BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs(); bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length())); if (!bidiRuns.runCount()) return; FloatPoint currPoint = point; BidiCharacterRun* bidiRun = bidiRuns.firstRun(); while (bidiRun) { TextRun subrun = run; subrun.setText(run.data(bidiRun->start()), bidiRun->stop() - bidiRun->start()); bool isRTL = bidiRun->level() % 2; subrun.setDirection(isRTL ? RTL : LTR); subrun.setDirectionalOverride(bidiRun->dirOverride(false)); font.drawText(this, subrun, currPoint); bidiRun = bidiRun->next(); // FIXME: Have Font::drawText return the width of what it drew so that we don't have to re-measure here. if (bidiRun) currPoint.move(font.width(subrun), 0); } bidiRuns.deleteRuns(); }
void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom) { GraphicsContext* context = paintInfo.context; RenderStyle* style = renderer().style(isFirstLineStyle()); const Font& font = style->font(); FloatPoint boxOrigin = locationIncludingFlipping(); boxOrigin.moveBy(FloatPoint(paintOffset)); if (!isHorizontal()) boxOrigin.move(0, -virtualLogicalHeight()); FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), virtualLogicalHeight())); GraphicsContextStateSaver stateSaver(*context); if (!isHorizontal()) context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Clockwise)); FloatPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetrics().ascent()); bool isPrinting = renderer().document().printing(); bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip && selectionState() != RenderObject::SelectionNone; if (haveSelection) paintSelection(context, boxOrigin, style, font); else if (paintInfo.phase == PaintPhaseSelection) return; TextPainter::Style textStyle = TextPainter::textPaintingStyle(renderer(), style, paintInfo.forceBlackText(), isPrinting); if (haveSelection) textStyle = TextPainter::selectionPaintingStyle(renderer(), true, paintInfo.forceBlackText(), isPrinting, textStyle); TextRun textRun = constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion); TextPainter textPainter(context, font, textRun, textOrigin, boxRect, isHorizontal()); textPainter.paint(0, m_str.length(), m_str.length(), textStyle); paintMarkupBox(paintInfo, paintOffset, lineTop, lineBottom, style); }
void GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const FloatPoint& point) { if (paintingDisabled()) return; BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; WTF::Unicode::Direction paragraphDirection = run.ltr() ? WTF::Unicode::LeftToRight : WTF::Unicode::RightToLeft; bidiResolver.setStatus(BidiStatus(paragraphDirection, paragraphDirection, paragraphDirection, new BidiContext(run.ltr() ? 0 : 1, paragraphDirection, run.directionalOverride()))); bidiResolver.setPosition(TextRunIterator(&run, 0)); bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length())); if (!bidiResolver.runCount()) return; FloatPoint currPoint = point; BidiCharacterRun* bidiRun = bidiResolver.firstRun(); while (bidiRun) { TextRun subrun = run; subrun.setText(run.data(bidiRun->start()), bidiRun->stop() - bidiRun->start()); subrun.setRTL(bidiRun->level() % 2); subrun.setDirectionalOverride(bidiRun->dirOverride(false)); font.drawText(this, subrun, currPoint); bidiRun = bidiRun->next(); // FIXME: Have Font::drawText return the width of what it drew so that we don't have to re-measure here. if (bidiRun) currPoint.move(font.floatWidth(subrun), 0.f); } bidiResolver.deleteRuns(); }
void GraphicsContext::drawBidiText(const FontCascade& font, const TextRun& run, const FloatPoint& point, FontCascade::CustomFontNotReadyAction customFontNotReadyAction) { if (paintingDisabled()) return; BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; bidiResolver.setStatus(BidiStatus(run.direction(), run.directionalOverride())); bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0)); // FIXME: This ownership should be reversed. We should pass BidiRunList // to BidiResolver in createBidiRunsForLine. BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs(); bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length())); if (!bidiRuns.runCount()) return; FloatPoint currPoint = point; BidiCharacterRun* bidiRun = bidiRuns.firstRun(); while (bidiRun) { TextRun subrun = run.subRun(bidiRun->start(), bidiRun->stop() - bidiRun->start()); bool isRTL = bidiRun->level() % 2; subrun.setDirection(isRTL ? RTL : LTR); subrun.setDirectionalOverride(bidiRun->dirOverride(false)); float width = font.drawText(*this, subrun, currPoint, 0, -1, customFontNotReadyAction); currPoint.move(width, 0); bidiRun = bidiRun->next(); } bidiRuns.deleteRuns(); }
static inline void calculateGlyphBoundaries(const QueryData* queryData, const SVGTextFragment& fragment, int startPosition, FloatRect& extent) { float scalingFactor = queryData->textLayoutObject->scalingFactor(); ASSERT(scalingFactor); FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, startPosition); glyphPosition.move(0, -queryData->textLayoutObject->scaledFont().fontMetrics().floatAscent() / scalingFactor); extent.setLocation(glyphPosition); // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends // time attempting to compute more correct glyph bounds already, handling // cursive scripts to some degree.) const Vector<SVGTextMetrics>& textMetricsValues = queryData->textLayoutObject->layoutAttributes()->textMetricsValues(); const SVGTextMetrics& metrics = findMetricsForCharacter(textMetricsValues, fragment, startPosition); // TODO(fs): Negative glyph extents seems kind of weird to have, but // presently it can occur in some cases (like Arabic.) FloatSize glyphSize(std::max<float>(metrics.width(), 0), std::max<float>(metrics.height(), 0)); extent.setSize(glyphSize); // If RTL, adjust the starting point to align with the LHS of the glyph bounding box. if (!queryData->textBox->isLeftToRightDirection()) { if (queryData->isVerticalText) extent.move(0, -glyphSize.height()); else extent.move(-glyphSize.width(), 0); } AffineTransform fragmentTransform; fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::TransformIgnoringTextLength); extent = fragmentTransform.mapRect(extent); }
static inline FloatPoint getPhase(const FloatRect& dest, const FloatRect& tile) { FloatPoint phase = dest.location(); phase.move(-tile.x(), -tile.y()); return phase; }
void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const { FS_STATE* iType = font->platformData().scaledFont(context->getCTM().yScale()); if (!iType) return; FloatPoint adjustedPoint = point; if (font->platformData().orientation() == Vertical) adjustedPoint.move(-(font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent()), 0); bool softwareBlurRequired = context->state().shadowBlur / font->fontMetrics().xHeight() > 0.5; FloatSize currentShadowOffset; float currentShadowBlur; Color currentShadowColor; ColorSpace currentColorSpace; // If we have a shadow blur, and it is too big to apply at text-render time, we must render it now. if (context->hasShadow() && softwareBlurRequired) { context->getShadow(currentShadowOffset, currentShadowBlur, currentShadowColor, currentColorSpace); const GraphicsContextState state = context->state(); FloatSize offset = state.shadowOffset; if (state.shadowsIgnoreTransforms) offset.setHeight(-offset.height()); ShadowBlur shadow(FloatSize(state.shadowBlur, state.shadowBlur), offset, state.shadowColor, state.shadowColorSpace); FloatPoint minPoint(adjustedPoint.x(), adjustedPoint.y() - fontMetrics().ascent()); FloatPoint maxPoint(adjustedPoint.x(), adjustedPoint.y() + fontMetrics().descent()); FloatPoint currentPoint = adjustedPoint; for (int i = 0; i < numGlyphs; ++i) { currentPoint += *glyphBuffer.advances(from + i); minPoint.setX(std::min(minPoint.x(), currentPoint.x())); minPoint.setY(std::min(minPoint.y(), currentPoint.y())); maxPoint = maxPoint.expandedTo(currentPoint); } const FloatRect boundingRect(minPoint.x(), minPoint.y(), maxPoint.x() - minPoint.x(), maxPoint.y() - minPoint.y()); GraphicsContext* shadowContext = shadow.beginShadowLayer(context, boundingRect); if (shadowContext) { iType = font->platformData().scaledFont(shadowContext->getCTM().yScale()); shadowContext->platformContext()->addGlyphs(glyphBuffer.glyphs(from), reinterpret_cast<const BlackBerry::Platform::FloatSize*>(glyphBuffer.advances(from)), numGlyphs, adjustedPoint, iType, 0, 0); iType = font->platformData().scaledFont(context->getCTM().yScale()); shadow.endShadowLayer(context); } context->platformContext()->clearShadow(); } context->platformContext()->addGlyphs(glyphBuffer.glyphs(from), reinterpret_cast<const BlackBerry::Platform::FloatSize*>(glyphBuffer.advances(from)), numGlyphs, adjustedPoint, iType, context->fillGradient() ? context->fillGradient()->platformGradient() : (context->fillPattern() ? context->fillPattern()->platformPattern(AffineTransform()) : static_cast<BlackBerry::Platform::Graphics::Paint*>(0)), context->strokeGradient() ? context->strokeGradient()->platformGradient() : (context->strokePattern() ? context->strokePattern()->platformPattern(AffineTransform()) : static_cast<BlackBerry::Platform::Graphics::Paint*>(0))); if (softwareBlurRequired) context->platformContext()->setShadow(currentShadowOffset, currentShadowBlur, currentShadowColor.isValid() ? currentShadowColor.rgb() : makeRGBA(0, 0, 0, 0xFF / 3), context->state().shadowsIgnoreTransforms); }
static void drawSkipInkUnderline(GraphicsContext& context, const FontCascade& font, const TextRun& textRun, const FloatPoint& textOrigin, const FloatPoint& localOrigin, float underlineOffset, float width, bool isPrinting, bool doubleLines, StrokeStyle strokeStyle) { FloatPoint adjustedLocalOrigin = localOrigin; adjustedLocalOrigin.move(0, underlineOffset); FloatRect underlineBoundingBox = context.computeUnderlineBoundsForText(adjustedLocalOrigin, width, isPrinting); DashArray intersections = font.dashesForIntersectionsWithRect(textRun, textOrigin, underlineBoundingBox); DashArray a = translateIntersectionPointsToSkipInkBoundaries(intersections, underlineBoundingBox.height(), width); ASSERT(!(a.size() % 2)); context.drawLinesForText(adjustedLocalOrigin, a, isPrinting, doubleLines, strokeStyle); }
static void paintSliderRangeHighlight(const IntRect& rect, const ComputedStyle& style, GraphicsContext* context, int startPosition, int endPosition, Color startColor, Color endColor) { // Calculate border radius; need to avoid being smaller than half the slider height // because of https://bugs.webkit.org/show_bug.cgi?id=30143. float borderRadius = rect.height() / 2.0f; FloatSize radii(borderRadius, borderRadius); // Calculate highlight rectangle and edge dimensions. int startOffset = startPosition; int endOffset = rect.width() - endPosition; int rangeWidth = endPosition - startPosition; if (rangeWidth <= 0) return; // Make sure the range width is bigger than border radius at the edges to retain rounded corners. if (startOffset < borderRadius && rangeWidth < borderRadius) rangeWidth = borderRadius; if (endOffset < borderRadius && rangeWidth < borderRadius) rangeWidth = borderRadius; // Set rectangle to highlight range. IntRect highlightRect = rect; highlightRect.move(startOffset, 0); highlightRect.setWidth(rangeWidth); // Don't bother drawing an empty area. if (highlightRect.isEmpty()) return; // Calculate white-grey gradient. FloatPoint sliderTopLeft = highlightRect.location(); FloatPoint sliderBottomLeft = sliderTopLeft; sliderBottomLeft.move(0, highlightRect.height()); RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderBottomLeft); gradient->addColorStop(0.0, startColor); gradient->addColorStop(1.0, endColor); // Fill highlight rectangle with gradient, potentially rounded if on left or right edge. context->save(); context->setFillGradient(gradient); if (startOffset < borderRadius && endOffset < borderRadius) context->fillRoundedRect(FloatRoundedRect(highlightRect, radii, radii, radii, radii), startColor); else if (startOffset < borderRadius) context->fillRoundedRect(FloatRoundedRect(highlightRect, radii, FloatSize(0, 0), radii, FloatSize(0, 0)), startColor); else if (endOffset < borderRadius) context->fillRoundedRect(FloatRoundedRect(highlightRect, FloatSize(0, 0), radii, FloatSize(0, 0), radii), startColor); else context->fillRect(highlightRect); context->restore(); }
void SVGGlyphToPathTranslator::incrementIndex() { do { if (m_glyph) { float advance = m_glyphBuffer.advanceAt(m_index).width(); if (m_isVerticalText) m_currentPoint.move(0, advance); else m_currentPoint.move(advance, 0); } ++m_index; if (m_index >= m_stoppingPoint) break; m_glyph = m_glyphBuffer.glyphAt(m_index); if (!m_glyph) continue; m_svgGlyph = m_fontElement.svgGlyphForGlyph(m_glyph); ASSERT(!m_svgGlyph.isPartOfLigature); ASSERT(m_svgGlyph.tableEntry == m_glyph); SVGGlyphElement::inheritUnspecifiedAttributes(m_svgGlyph, &m_svgFontData); } while ((!m_glyph || m_svgGlyph.pathData.isEmpty()) && m_index < m_stoppingPoint); }
FloatPoint TransformState::mappedPoint(bool* wasClamped) const { if (wasClamped) *wasClamped = false; FloatPoint point = m_lastPlanarPoint; point.move((m_direction == ApplyTransformDirection) ? m_accumulatedOffset : -m_accumulatedOffset); if (!m_accumulatedTransform) return point; if (m_direction == ApplyTransformDirection) return m_accumulatedTransform->mapPoint(point); return m_accumulatedTransform->inverse().projectPoint(point, wasClamped); }
void DrawGlyphs::computeBounds() { // FIXME: This code doesn't actually take the extents of the glyphs into consideration. It assumes that // the glyph lies entirely within its [(ascent + descent), advance] rect. float ascent = m_font->fontMetrics().floatAscent(); float descent = m_font->fontMetrics().floatDescent(); FloatPoint current = toFloatPoint(localAnchor()); size_t numGlyphs = m_glyphs.size(); for (size_t i = 0; i < numGlyphs; ++i) { GlyphBufferAdvance advance = m_advances[i]; FloatRect glyphRect = FloatRect(current.x(), current.y() - ascent, advance.width(), ascent + descent); m_bounds.unite(glyphRect); current.move(advance.width(), advance.height()); } }
void MouseRelatedEvent::computeRelativePosition() { Node* targetNode = target() ? target()->toNode() : nullptr; if (!targetNode) return; // Compute coordinates that are based on the target. m_layerLocation = m_pageLocation; m_offsetLocation = m_pageLocation; // Must have an updated layout tree for this math to work correctly. targetNode->document().updateLayoutIgnorePendingStylesheets(); // Adjust offsetLocation to be relative to the target's padding box. if (LayoutObject* r = targetNode->layoutObject()) { FloatPoint localPos = r->absoluteToLocal(FloatPoint(absoluteLocation()), UseTransforms); // Adding this here to address crbug.com/570666. Basically we'd like to // find the local coordinates relative to the padding box not the border box. if (r->isBoxModelObject()) { LayoutBoxModelObject* layoutBox = toLayoutBoxModelObject(r); localPos.move(-layoutBox->borderLeft(), -layoutBox->borderTop()); } m_offsetLocation = roundedLayoutPoint(localPos); float scaleFactor = 1 / pageZoomFactor(this); if (scaleFactor != 1.0f) m_offsetLocation.scale(scaleFactor, scaleFactor); } // Adjust layerLocation to be relative to the layer. // FIXME: event.layerX and event.layerY are poorly defined, // and probably don't always correspond to PaintLayer offsets. // https://bugs.webkit.org/show_bug.cgi?id=21868 Node* n = targetNode; while (n && !n->layoutObject()) n = n->parentNode(); if (n) { // FIXME: This logic is a wrong implementation of convertToLayerCoords. for (PaintLayer* layer = n->layoutObject()->enclosingLayer(); layer; layer = layer->parent()) m_layerLocation -= toLayoutSize(layer->location()); } m_hasCachedRelativePosition = true; }
void RenderListBox::panScroll(const IntPoint& panStartMousePosition) { const int maxSpeed = 20; const int iconRadius = 7; const int speedReducer = 4; // FIXME: This doesn't work correctly with transforms. FloatPoint absOffset = localToAbsolute(); IntPoint currentMousePosition = document()->frame()->eventHandler()->currentMousePosition(); // We need to check if the current mouse position is out of the window. When the mouse is out of the window, the position is incoherent static IntPoint previousMousePosition; if (currentMousePosition.y() < 0) currentMousePosition = previousMousePosition; else previousMousePosition = currentMousePosition; int yDelta = currentMousePosition.y() - panStartMousePosition.y(); // If the point is too far from the center we limit the speed yDelta = max(min(yDelta, maxSpeed), -maxSpeed); if (abs(yDelta) < iconRadius) // at the center we let the space for the icon return; if (yDelta > 0) //offsetY = view()->viewHeight(); absOffset.move(0, listHeight()); else if (yDelta < 0) yDelta--; // Let's attenuate the speed yDelta /= speedReducer; IntPoint scrollPoint(0, 0); scrollPoint.setY(absOffset.y() + yDelta); int newOffset = scrollToward(scrollPoint); if (newOffset < 0) return; m_inAutoscroll = true; SelectElement* select = toSelectElement(static_cast<Element*>(node())); select->updateListBoxSelection(!select->multiple()); m_inAutoscroll = false; }
FloatPoint Widget::convertFromContainingWindow(const FloatPoint& windowPoint) const { // Widgets / windows are required to be IntPoint aligned, but we may need to convert // FloatPoint values within them (eg. for event co-ordinates). IntPoint flooredPoint = flooredIntPoint(windowPoint); FloatPoint parentPoint = this->convertFromContainingWindow(flooredPoint); FloatSize windowFraction = windowPoint - flooredPoint; // Use linear interpolation handle any fractional value (eg. for iframes subject to a transform // beyond just a simple translation). // FIXME: Add FloatPoint variants of all co-ordinate space conversion APIs. if (!windowFraction.isEmpty()) { const int kFactor = 1000; IntPoint parentLineEnd = this->convertFromContainingWindow(flooredPoint + roundedIntSize(windowFraction.scaledBy(kFactor))); FloatSize parentFraction = (parentLineEnd - parentPoint).scaledBy(1.0f / kFactor); parentPoint.move(parentFraction); } return parentPoint; }
void RenderWidget::updateWidgetPosition() { if (!m_widget || !node()) // Check the node in case destroy() has been called. return; // FIXME: This doesn't work correctly with transforms. FloatPoint absPos = localToAbsolute(); absPos.move(borderLeft() + paddingLeft(), borderTop() + paddingTop()); int w = width() - borderAndPaddingWidth(); int h = height() - borderAndPaddingHeight(); bool boundsChanged = setWidgetGeometry(IntRect(absPos.x(), absPos.y(), w, h)); // if the frame bounds got changed, or if view needs layout (possibly indicating // content size is wrong) we have to do a layout to set the right widget size if (m_widget && m_widget->isFrameView()) { FrameView* frameView = static_cast<FrameView*>(m_widget.get()); if (boundsChanged || frameView->needsLayout()) frameView->layout(); } }
HitTestCanvasResult* CanvasRenderingContext2D::getControlAndIdIfHitRegionExists( const LayoutPoint& location) { if (hitRegionsCount() <= 0) return HitTestCanvasResult::create(String(), nullptr); LayoutBox* box = canvas()->layoutBox(); FloatPoint localPos = box->absoluteToLocal(FloatPoint(location), UseTransforms); if (box->hasBorderOrPadding()) localPos.move(-box->contentBoxOffset()); localPos.scale(canvas()->width() / box->contentWidth(), canvas()->height() / box->contentHeight()); HitRegion* hitRegion = hitRegionAtPoint(localPos); if (hitRegion) { Element* control = hitRegion->control(); if (control && canvas()->isSupportedInteractiveCanvasFallback(*control)) return HitTestCanvasResult::create(hitRegion->id(), hitRegion->control()); return HitTestCanvasResult::create(hitRegion->id(), nullptr); } return HitTestCanvasResult::create(String(), nullptr); }
bool ScrollingTree::shouldHandleWheelEventSynchronously(const PlatformWheelEvent& wheelEvent) { // This method is invoked by the event handling thread MutexLocker lock(m_mutex); bool shouldSetLatch = wheelEvent.shouldConsiderLatching(); if (hasLatchedNode() && !shouldSetLatch) return false; if (shouldSetLatch) m_latchedNode = 0; if (!m_nonFastScrollableRegion.isEmpty() && m_rootNode) { ScrollingTreeFrameScrollingNode& frameScrollingNode = downcast<ScrollingTreeFrameScrollingNode>(*m_rootNode); // FIXME: This is not correct for non-default scroll origins. FloatPoint position = wheelEvent.position(); position.move(frameScrollingNode.viewToContentsOffset(m_mainFrameScrollPosition)); if (m_nonFastScrollableRegion.contains(roundedIntPoint(position))) return true; } return false; }