void BackgroundImageGeometry::setRepeatY(const FillLayer& fillLayer, LayoutUnit unsnappedTileHeight, LayoutUnit snappedAvailableHeight, LayoutUnit unsnappedAvailableHeight, LayoutUnit extraOffset) { // We would like to identify the phase as a fraction of the image size in the // absence of snapping, then re-apply it to the snapped values. This is to // handle large positions. if (unsnappedTileHeight) { LayoutUnit computedYPosition = roundedMinimumValueForLength( fillLayer.yPosition(), unsnappedAvailableHeight); if (fillLayer.backgroundYOrigin() == BottomEdge) { float numberOfTilesInPosition = (snappedAvailableHeight - computedYPosition + extraOffset).toFloat() / unsnappedTileHeight.toFloat(); float fractionalPositionWithinTile = numberOfTilesInPosition - truncf(numberOfTilesInPosition); setPhaseY(LayoutUnit( roundf(fractionalPositionWithinTile * tileSize().height()))); } else { float numberOfTilesInPosition = (computedYPosition + extraOffset).toFloat() / unsnappedTileHeight.toFloat(); float fractionalPositionWithinTile = 1.0f - (numberOfTilesInPosition - truncf(numberOfTilesInPosition)); setPhaseY(LayoutUnit( roundf(fractionalPositionWithinTile * tileSize().height()))); } } else { setPhaseY(LayoutUnit()); } setSpaceSize(LayoutSize(spaceSize().width(), LayoutUnit())); }
LineSegment PolygonShape::getExcludedInterval(LayoutUnit logicalTop, LayoutUnit logicalHeight) const { float y1 = logicalTop.toFloat(); float y2 = logicalTop.toFloat() + logicalHeight.toFloat(); if (m_polygon.isEmpty() || !overlapsYRange(m_polygon.boundingBox(), y1 - shapeMargin(), y2 + shapeMargin())) return LineSegment(); Vector<const FloatPolygonEdge*> overlappingEdges; if (!m_polygon.overlappingEdges(y1 - shapeMargin(), y2 + shapeMargin(), overlappingEdges)) return LineSegment(); FloatShapeInterval excludedInterval; for (unsigned i = 0; i < overlappingEdges.size(); i++) { const FloatPolygonEdge& edge = *(overlappingEdges[i]); if (edge.maxY() == edge.minY()) continue; if (!shapeMargin()) { excludedInterval.unite(OffsetPolygonEdge(edge, FloatSize()).clippedEdgeXRange(y1, y2)); } else { excludedInterval.unite(OffsetPolygonEdge(edge, outwardEdgeNormal(edge) * shapeMargin()).clippedEdgeXRange(y1, y2)); excludedInterval.unite(OffsetPolygonEdge(edge, inwardEdgeNormal(edge) * shapeMargin()).clippedEdgeXRange(y1, y2)); excludedInterval.unite(clippedCircleXRange(edge.vertex1(), shapeMargin(), y1, y2)); } } if (excludedInterval.isEmpty()) return LineSegment(); return LineSegment(excludedInterval.x1(), excludedInterval.x2()); }
Vector<double> SnapCoordinator::snapOffsets(const ContainerNode& element, ScrollbarOrientation orientation) { const ComputedStyle* style = element.computedStyle(); const LayoutBox* snapContainer = element.layoutBox(); ASSERT(style); ASSERT(snapContainer); Vector<double> result; if (style->getScrollSnapType() == ScrollSnapTypeNone) return result; const ScrollSnapPoints& snapPoints = (orientation == HorizontalScrollbar) ? style->scrollSnapPointsX() : style->scrollSnapPointsY(); LayoutUnit clientSize = (orientation == HorizontalScrollbar) ? snapContainer->clientWidth() : snapContainer->clientHeight(); LayoutUnit scrollSize = (orientation == HorizontalScrollbar) ? snapContainer->scrollWidth() : snapContainer->scrollHeight(); if (snapPoints.hasRepeat) { LayoutUnit repeat = valueForLength(snapPoints.repeatOffset, clientSize); // calc() values may be negative or zero in which case we clamp them to 1px. // See: https://lists.w3.org/Archives/Public/www-style/2015Jul/0075.html repeat = std::max<LayoutUnit>(repeat, LayoutUnit(1)); for (LayoutUnit offset = repeat; offset <= (scrollSize - clientSize); offset += repeat) { result.append(offset.toFloat()); } } // Compute element-based snap points by mapping the snap coordinates from // snap areas to snap container. bool didAddSnapAreaOffset = false; if (SnapAreaSet* snapAreas = snapContainer->snapAreas()) { for (auto& snapArea : *snapAreas) { Vector<FloatPoint> snapCoordinates = localToContainerSnapCoordinates(*snapContainer, *snapArea); for (const FloatPoint& snapCoordinate : snapCoordinates) { float snapOffset = (orientation == HorizontalScrollbar) ? snapCoordinate.x() : snapCoordinate.y(); if (snapOffset > scrollSize - clientSize) continue; result.append(snapOffset); didAddSnapAreaOffset = true; } } } if (didAddSnapAreaOffset) std::sort(result.begin(), result.end()); return result; }
void FileUploadControlPainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (m_layoutFileUploadControl.style()->visibility() != 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::ClipFileUploadControlRect, 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); // FIXME: Shouldn't these offsets be rounded? crbug.com/350474 textRunPaintInfo.bounds = FloatRect(textX.toFloat(), textY.toFloat() - m_layoutFileUploadControl.style()->getFontMetrics().ascent(), textWidth, m_layoutFileUploadControl.style()->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); }
void FileUploadControlPainter::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (m_renderFileUploadControl.style()->visibility() != VISIBLE) return; // Push a clip. GraphicsContextStateSaver stateSaver(*paintInfo.context, false); if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) { IntRect clipRect = enclosingIntRect(LayoutRect(paintOffset.x() + m_renderFileUploadControl.borderLeft(), paintOffset.y() + m_renderFileUploadControl.borderTop(), m_renderFileUploadControl.width() - m_renderFileUploadControl.borderLeft() - m_renderFileUploadControl.borderRight(), m_renderFileUploadControl.height() - m_renderFileUploadControl.borderBottom() - m_renderFileUploadControl.borderTop() + buttonShadowHeight)); if (clipRect.isEmpty()) return; stateSaver.save(); paintInfo.context->clip(clipRect); } if (paintInfo.phase == PaintPhaseForeground) { const String& displayedFilename = m_renderFileUploadControl.fileTextValue(); const Font& font = m_renderFileUploadControl.style()->font(); TextRun textRun = constructTextRun(&m_renderFileUploadControl, font, displayedFilename, m_renderFileUploadControl.style(), TextRun::AllowTrailingExpansion, RespectDirection | RespectDirectionOverride); // Determine where the filename should be placed LayoutUnit contentLeft = paintOffset.x() + m_renderFileUploadControl.borderLeft() + m_renderFileUploadControl.paddingLeft(); Node* button = m_renderFileUploadControl.uploadButton(); if (!button) return; int buttonWidth = (button && button->renderBox()) ? button->renderBox()->pixelSnappedWidth() : 0; LayoutUnit buttonAndSpacingWidth = buttonWidth + RenderFileUploadControl::afterButtonSpacing; float textWidth = font.width(textRun); LayoutUnit textX; if (m_renderFileUploadControl.style()->isLeftToRightDirection()) textX = contentLeft + buttonAndSpacingWidth; else textX = contentLeft + m_renderFileUploadControl.contentWidth() - buttonAndSpacingWidth - textWidth; LayoutUnit textY = 0; // We want to match the button's baseline // FIXME: Make this work with transforms. if (RenderButton* buttonRenderer = toRenderButton(button->renderer())) textY = paintOffset.y() + m_renderFileUploadControl.borderTop() + m_renderFileUploadControl.paddingTop() + buttonRenderer->baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine); else textY = m_renderFileUploadControl.baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine); TextRunPaintInfo textRunPaintInfo(textRun); // FIXME: Shouldn't these offsets be rounded? crbug.com/350474 textRunPaintInfo.bounds = FloatRect(textX.toFloat(), textY.toFloat() - m_renderFileUploadControl.style()->fontMetrics().ascent(), textWidth, m_renderFileUploadControl.style()->fontMetrics().height()); paintInfo.context->setFillColor(m_renderFileUploadControl.resolveColor(CSSPropertyColor)); // Draw the filename paintInfo.context->drawBidiText(font, textRunPaintInfo, IntPoint(roundToInt(textX), roundToInt(textY))); } // Paint the children. m_renderFileUploadControl.RenderBlockFlow::paintObject(paintInfo, paintOffset); }
void KeyboardApplet::updateTooltip() { LayoutUnit layoutUnit = X11Helper::getCurrentLayout(); if( layoutUnit.isEmpty() ) return; const QIcon icon(getFlag(layoutUnit.layout)); Plasma::ToolTipContent data(name(), flags.getLongText(layoutUnit, rules), icon); Plasma::ToolTipManager::self()->setContent(this, data); }
Path HTMLAreaElement::getRegion(const LayoutSize& size) const { if (m_coords.isEmpty() && m_shape != Default) return Path(); LayoutUnit width = size.width(); LayoutUnit height = size.height(); // If element omits the shape attribute, select shape based on number of coordinates. Shape shape = m_shape; if (shape == Unknown) { if (m_coords.size() == 3) shape = Circle; else if (m_coords.size() == 4) shape = Rect; else if (m_coords.size() >= 6) shape = Poly; } Path path; switch (shape) { case Poly: if (m_coords.size() >= 6) { int numPoints = m_coords.size() / 2; path.moveTo(FloatPoint(minimumValueForLength(m_coords[0], width).toFloat(), minimumValueForLength(m_coords[1], height).toFloat())); for (int i = 1; i < numPoints; ++i) path.addLineTo(FloatPoint(minimumValueForLength(m_coords[i * 2], width).toFloat(), minimumValueForLength(m_coords[i * 2 + 1], height).toFloat())); path.closeSubpath(); } break; case Circle: if (m_coords.size() >= 3) { Length radius = m_coords[2]; float r = std::min(minimumValueForLength(radius, width).toFloat(), minimumValueForLength(radius, height).toFloat()); path.addEllipse(FloatRect(minimumValueForLength(m_coords[0], width).toFloat() - r, minimumValueForLength(m_coords[1], height).toFloat() - r, 2 * r, 2 * r)); } break; case Rect: if (m_coords.size() >= 4) { float x0 = minimumValueForLength(m_coords[0], width).toFloat(); float y0 = minimumValueForLength(m_coords[1], height).toFloat(); float x1 = minimumValueForLength(m_coords[2], width).toFloat(); float y1 = minimumValueForLength(m_coords[3], height).toFloat(); path.addRect(FloatRect(x0, y0, x1 - x0, y1 - y0)); } break; case Default: path.addRect(FloatRect(0, 0, width.toFloat(), height.toFloat())); break; case Unknown: break; } return path; }
int LayoutTextControl::textBlockLogicalWidth() const { Element* innerEditor = innerEditorElement(); ASSERT(innerEditor); LayoutUnit unitWidth = logicalWidth() - borderAndPaddingLogicalWidth(); if (innerEditor->layoutObject()) unitWidth -= innerEditor->layoutBox()->paddingStart() + innerEditor->layoutBox()->paddingEnd(); return unitWidth.toInt(); }
TEST(LayoutUnitTest, UnaryMinus) { EXPECT_EQ(LayoutUnit(), -LayoutUnit()); EXPECT_EQ(LayoutUnit(999), -LayoutUnit(-999)); EXPECT_EQ(LayoutUnit(-999), -LayoutUnit(999)); LayoutUnit negativeMax; negativeMax.setRawValue(LayoutUnit::min().rawValue() + 1); EXPECT_EQ(negativeMax, -LayoutUnit::max()); EXPECT_EQ(LayoutUnit::max(), -negativeMax); // -LayoutUnit::min() is saturated to LayoutUnit::max() EXPECT_EQ(LayoutUnit::max(), -LayoutUnit::min()); }
const Shape& ShapeOutsideInfo::computedShape() const { if (Shape* shape = m_shape.get()) return *shape; AutoReset<bool> isInComputingShape(&m_isComputingShape, true); const ComputedStyle& style = *m_layoutBox.style(); ASSERT(m_layoutBox.containingBlock()); const ComputedStyle& containingBlockStyle = *m_layoutBox.containingBlock()->style(); WritingMode writingMode = containingBlockStyle.getWritingMode(); // Make sure contentWidth is not negative. This can happen when containing // block has a vertical scrollbar and its content is smaller than the // scrollbar width. LayoutUnit maximumValue = m_layoutBox.containingBlock() ? std::max(LayoutUnit(), m_layoutBox.containingBlock()->contentWidth()) : LayoutUnit(); float margin = floatValueForLength(m_layoutBox.style()->shapeMargin(), maximumValue.toFloat()); float shapeImageThreshold = style.shapeImageThreshold(); ASSERT(style.shapeOutside()); const ShapeValue& shapeValue = *style.shapeOutside(); switch (shapeValue.type()) { case ShapeValue::Shape: ASSERT(shapeValue.shape()); m_shape = Shape::createShape( shapeValue.shape(), m_referenceBoxLogicalSize, writingMode, margin); break; case ShapeValue::Image: ASSERT(shapeValue.isImageValid()); m_shape = createShapeForImage(shapeValue.image(), shapeImageThreshold, writingMode, margin); break; case ShapeValue::Box: { const FloatRoundedRect& shapeRect = style.getRoundedBorderFor( LayoutRect(LayoutPoint(), m_referenceBoxLogicalSize), m_layoutBox.view()); m_shape = Shape::createLayoutBoxShape(shapeRect, writingMode, margin); break; } } ASSERT(m_shape); return *m_shape; }
unsigned RenderMultiColumnSet::columnCount() const { // We must always return a value of 1 or greater. Column count = 0 is a meaningless situation, // and will confuse and cause problems in other parts of the code. if (!computedColumnHeight()) return 1; // Our portion rect determines our column count. We have as many columns as needed to fit all the content. LayoutUnit logicalHeightInColumns = flowThread()->isHorizontalWritingMode() ? flowThreadPortionRect().height() : flowThreadPortionRect().width(); if (!logicalHeightInColumns) return 1; unsigned count = ceil(logicalHeightInColumns.toFloat() / computedColumnHeight().toFloat()); ASSERT(count >= 1); return count; }
LayoutUnit LayoutMultiColumnSet::nextLogicalTopForUnbreakableContent(LayoutUnit flowThreadOffset, LayoutUnit contentLogicalHeight) const { ASSERT(flowThreadOffset.mightBeSaturated() || pageLogicalTopForOffset(flowThreadOffset) == flowThreadOffset); FragmentationContext* enclosingFragmentationContext = multiColumnFlowThread()->enclosingFragmentationContext(); if (!enclosingFragmentationContext) { // If there's no enclosing fragmentation context, there'll ever be only one row, and all // columns there will have the same height. return flowThreadOffset; } // Assert the problematic situation. If we have no problem with the column height, why are we // even here? ASSERT(pageLogicalHeightForOffset(flowThreadOffset) < contentLogicalHeight); // There's a likelihood for subsequent rows to be taller than the first one. // TODO(mstensho): if we're doubly nested (e.g. multicol in multicol in multicol), we need to // look beyond the first row here. const MultiColumnFragmentainerGroup& firstRow = firstFragmentainerGroup(); LayoutUnit firstRowLogicalBottomInFlowThread = firstRow.logicalTopInFlowThread() + fragmentainerGroupCapacity(firstRow); if (flowThreadOffset >= firstRowLogicalBottomInFlowThread) return flowThreadOffset; // We're not in the first row. Give up. LayoutUnit newLogicalHeight = enclosingFragmentationContext->fragmentainerLogicalHeightAt(firstRow.blockOffsetInEnclosingFragmentationContext() + firstRow.logicalHeight()); if (contentLogicalHeight > newLogicalHeight) { // The next outer column or page doesn't have enough space either. Give up and stay where // we are. return flowThreadOffset; } return firstRowLogicalBottomInFlowThread; }
LineSegment RectangleShape::getExcludedInterval(LayoutUnit logicalTop, LayoutUnit logicalHeight) const { const FloatRect& bounds = shapeMarginBounds(); if (bounds.isEmpty()) return LineSegment(); float y1 = logicalTop.toFloat(); float y2 = (logicalTop + logicalHeight).toFloat(); if (y2 < bounds.y() || y1 >= bounds.maxY()) return LineSegment(); float x1 = bounds.x(); float x2 = bounds.maxX(); float marginRadiusX = rx() + shapeMargin(); float marginRadiusY = ry() + shapeMargin(); if (marginRadiusY > 0) { if (y2 < bounds.y() + marginRadiusY) { float yi = y2 - bounds.y() - marginRadiusY; float xi = ellipseXIntercept(yi, marginRadiusX, marginRadiusY); x1 = bounds.x() + marginRadiusX - xi; x2 = bounds.maxX() - marginRadiusX + xi; } else if (y1 > bounds.maxY() - marginRadiusY) { float yi = y1 - (bounds.maxY() - marginRadiusY); float xi = ellipseXIntercept(yi, marginRadiusX, marginRadiusY); x1 = bounds.x() + marginRadiusX - xi; x2 = bounds.maxX() - marginRadiusX + xi; } } return LineSegment(x1, x2); }
static LayoutUnit computeMargin(const Length& length, LayoutUnit referenceLength) { if (length.type() == Percent) return LayoutUnit(static_cast<int>(referenceLength.toFloat() * length.percent() / 100.0)); ASSERT(length.type() == Fixed); return LayoutUnit(length.intValue()); }
bool RasterShape::firstIncludedIntervalLogicalTop(LayoutUnit minLogicalIntervalTop, const LayoutSize& minLogicalIntervalSize, LayoutUnit& result) const { const RasterShapeIntervals& intervals = paddingIntervals(); if (intervals.isEmpty()) return false; return intervals.firstIncludedIntervalY(minLogicalIntervalTop.floor(), flooredIntSize(minLogicalIntervalSize), result); }
unsigned MultiColumnFragmentainerGroup::actualColumnCount() const { // We must always return a value of 1 or greater. Column count = 0 is a meaningless situation, // and will confuse and cause problems in other parts of the code. if (!m_columnHeight) return 1; // Our flow thread portion determines our column count. We have as many columns as needed to fit // all the content. LayoutUnit flowThreadPortionHeight = logicalHeightInFlowThread(); if (!flowThreadPortionHeight) return 1; unsigned count = ceil(flowThreadPortionHeight.toFloat() / m_columnHeight.toFloat()); ASSERT(count >= 1); return count; }
void LineWidth::updateLineDimension(LayoutUnit newLineTop, LayoutUnit newLineWidth, const float& newLineLeft, const float& newLineRight) { if (newLineWidth <= m_availableWidth) return; m_block.setLogicalHeight(newLineTop); m_availableWidth = newLineWidth.toFloat(); m_left = newLineLeft; m_right = newLineRight; }
void LayoutConfig::latinChanged() { QListViewItem *selLayout = widget->listLayoutsDst->selectedItem(); if(!selLayout) { widget->chkLatin->setChecked(false); widget->chkLatin->setEnabled(false); return; } QString include; if(widget->chkLatin->isChecked()) include = "us"; else include = ""; selLayout->setText(LAYOUT_COLUMN_INCLUDE, include); LayoutUnit layoutUnitKey = getLayoutUnitKey(selLayout); kdDebug() << "layout " << layoutUnitKey.toPair() << ", inc: " << include << endl; }
void KeyboardApplet::paintInterface(QPainter *p, const QStyleOptionGraphicsItem */*option*/, const QRect &contentsRect) { LayoutUnit layoutUnit = X11Helper::getCurrentLayout(); if( layoutUnit.isEmpty() ) return; const QIcon icon(getFlag(layoutUnit.layout)); if( ! icon.isNull() ) { p->save(); p->setRenderHint(QPainter::SmoothPixmapTransform); p->setRenderHint(QPainter::Antialiasing); QPixmap pixmap = icon.pixmap(contentsRect.size()); p->drawPixmap(contentsRect, pixmap); p->restore(); } if( icon.isNull() || keyboardConfig->isLabelShown() ) { QRect finalRect(m_pixmap.rect()); finalRect.moveCenter(contentsRect.center()); p->drawPixmap(finalRect, m_pixmap); } }
void EllipsisBox::paintSelection(GraphicsContext* context, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font) { Color textColor = renderer().resolveColor(style, CSSPropertyColor); Color c = renderer().selectionBackgroundColor(); if (!c.alpha()) return; // If the text color ends up being the same as the selection background, invert the selection // background. if (textColor == c) c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); GraphicsContextStateSaver stateSaver(*context); LayoutUnit top = root().selectionTop(); LayoutUnit h = root().selectionHeight(); const int deltaY = roundToInt(logicalTop() - top); const FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY); FloatRect clipRect(localOrigin, FloatSize(m_logicalWidth, h.toFloat())); context->clip(clipRect); context->drawHighlightForText(font, constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), localOrigin, h, c); }
bool X11Helper::setLayout(const LayoutUnit& layout) { QList<LayoutUnit> currentLayouts = getLayoutsList(); int idx = currentLayouts.indexOf(layout); if( idx == -1 || idx >= X11Helper::MAX_GROUP_COUNT ) { qCWarning(KCM_KEYBOARD) << "Layout" << layout.toString() << "is not found in current layout list" << getLayoutsListAsString(currentLayouts); return false; } return X11Helper::setGroup((unsigned int)idx); }
const Shape& ShapeOutsideInfo::computedShape() const { if (Shape* shape = m_shape.get()) return *shape; const RenderStyle& style = *m_renderer.style(); ASSERT(m_renderer.containingBlock()); const RenderStyle& containingBlockStyle = *m_renderer.containingBlock()->style(); WritingMode writingMode = containingBlockStyle.writingMode(); LayoutUnit maximumValue = m_renderer.containingBlock() ? m_renderer.containingBlock()->contentWidth() : LayoutUnit(); float margin = floatValueForLength(m_renderer.style()->shapeMargin(), maximumValue.toFloat()); float shapeImageThreshold = style.shapeImageThreshold(); ASSERT(style.shapeOutside()); const ShapeValue& shapeValue = *style.shapeOutside(); switch (shapeValue.type()) { case ShapeValue::Shape: ASSERT(shapeValue.shape()); m_shape = Shape::createShape(shapeValue.shape(), m_referenceBoxLogicalSize, writingMode, margin); break; case ShapeValue::Image: { Image* image; LayoutRect imageRect; getShapeImageAndRect(shapeValue, m_renderer, m_referenceBoxLogicalSize, image, imageRect); const LayoutRect& marginRect = getShapeImageMarginRect(m_renderer, m_referenceBoxLogicalSize); m_shape = Shape::createRasterShape(image, shapeImageThreshold, imageRect, marginRect, writingMode, margin); break; } case ShapeValue::Box: { const RoundedRect& shapeRect = style.getRoundedBorderFor(LayoutRect(LayoutPoint(), m_referenceBoxLogicalSize), m_renderer.view()); m_shape = Shape::createLayoutBoxShape(shapeRect, writingMode, margin); break; } } ASSERT(m_shape); return *m_shape; }
void BackgroundImageGeometry::setSpaceY(LayoutUnit space, LayoutUnit availableHeight, LayoutUnit extraOffset) { LayoutUnit computedYPosition = roundedMinimumValueForLength(Length(), availableHeight); setSpaceSize(LayoutSize(spaceSize().width().toInt(), space.round())); LayoutUnit actualHeight = tileSize().height() + space; setPhaseY(actualHeight ? LayoutUnit(roundf( actualHeight - fmodf((computedYPosition + extraOffset), actualHeight))) : LayoutUnit()); }
LayoutPoint RenderRegion::mapRegionPointIntoFlowThreadCoordinates(const LayoutPoint& point) { // Assuming the point is relative to the region block, 3 cases will be considered: // a) top margin, padding or border. // b) bottom margin, padding or border. // c) non-content region area. LayoutUnit pointLogicalTop(isHorizontalWritingMode() ? point.y() : point.x()); LayoutUnit pointLogicalLeft(isHorizontalWritingMode() ? point.x() : point.y()); LayoutUnit flowThreadLogicalTop(isHorizontalWritingMode() ? m_flowThreadPortionRect.y() : m_flowThreadPortionRect.x()); LayoutUnit flowThreadLogicalLeft(isHorizontalWritingMode() ? m_flowThreadPortionRect.x() : m_flowThreadPortionRect.y()); LayoutUnit flowThreadPortionTopBound(isHorizontalWritingMode() ? m_flowThreadPortionRect.height() : m_flowThreadPortionRect.width()); LayoutUnit flowThreadPortionLeftBound(isHorizontalWritingMode() ? m_flowThreadPortionRect.width() : m_flowThreadPortionRect.height()); LayoutUnit flowThreadPortionTopMax(isHorizontalWritingMode() ? m_flowThreadPortionRect.maxY() : m_flowThreadPortionRect.maxX()); LayoutUnit flowThreadPortionLeftMax(isHorizontalWritingMode() ? m_flowThreadPortionRect.maxX() : m_flowThreadPortionRect.maxY()); LayoutUnit effectiveFixedPointDenominator; effectiveFixedPointDenominator.setRawValue(1); if (pointLogicalTop < 0) { LayoutPoint pointInThread(0, flowThreadLogicalTop); return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint(); } if (pointLogicalTop >= flowThreadPortionTopBound) { LayoutPoint pointInThread(flowThreadPortionLeftBound, flowThreadPortionTopMax - effectiveFixedPointDenominator); return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint(); } if (pointLogicalLeft < 0) { LayoutPoint pointInThread(flowThreadLogicalLeft, pointLogicalTop + flowThreadLogicalTop); return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint(); } if (pointLogicalLeft >= flowThreadPortionLeftBound) { LayoutPoint pointInThread(flowThreadPortionLeftMax - effectiveFixedPointDenominator, pointLogicalTop + flowThreadLogicalTop); return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint(); } LayoutPoint pointInThread(pointLogicalLeft + flowThreadLogicalLeft, pointLogicalTop + flowThreadLogicalTop); return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint(); }
LayoutRect InlineTextBox::localSelectionRect(int startPos, int endPos) { int sPos = max(startPos - m_start, 0); int ePos = min(endPos - m_start, (int)m_len); if (sPos > ePos) return LayoutRect(); FontCachePurgePreventer fontCachePurgePreventer; LayoutUnit selTop = selectionTop(); LayoutUnit selHeight = selectionHeight(); RenderStyle* styleToUse = textRenderer().style(isFirstLineStyle()); const Font& font = styleToUse->font(); StringBuilder charactersWithHyphen; bool respectHyphen = ePos == m_len && hasHyphen(); TextRun textRun = constructTextRun(styleToUse, font, respectHyphen ? &charactersWithHyphen : 0); FloatPoint startingPoint = FloatPoint(logicalLeft(), selTop.toFloat()); LayoutRect r; if (sPos || ePos != static_cast<int>(m_len)) r = enclosingIntRect(font.selectionRectForText(textRun, startingPoint, selHeight, sPos, ePos)); else // Avoid computing the font width when the entire line box is selected as an optimization. r = enclosingIntRect(FloatRect(startingPoint, FloatSize(m_logicalWidth, selHeight.toFloat()))); LayoutUnit logicalWidth = r.width(); if (r.x() > logicalRight()) logicalWidth = 0; else if (r.maxX() > logicalRight()) logicalWidth = logicalRight() - r.x(); LayoutPoint topPoint = isHorizontal() ? LayoutPoint(r.x(), selTop) : LayoutPoint(selTop, r.x()); LayoutUnit width = isHorizontal() ? logicalWidth : selHeight; LayoutUnit height = isHorizontal() ? selHeight : logicalWidth; return LayoutRect(topPoint, LayoutSize(width, height)); }
LayoutRect RenderMathMLOperator::paintCharacter(PaintInfo& info, UChar character, const LayoutPoint& origin, CharacterPaintTrimming trim) { GlyphData data = style()->font().glyphDataForCharacter(character, false); FloatRect glyphBounds = data.fontData->boundsForGlyph(data.glyph); LayoutRect glyphPaintRect(origin, LayoutSize(glyphBounds.x() + glyphBounds.width(), glyphBounds.height())); glyphPaintRect.setY(origin.y() + glyphBounds.y()); // In order to have glyphs fit snugly with one another we snap the connecting edges to pixel boundaries // and trim off one pixel. The pixel trim is to account for fonts that have edge pixels that have less // than full coverage. These edge pixels can introduce small seams between connected glyphs FloatRect clipBounds = info.rect; switch (trim) { case TrimTop: glyphPaintRect.shiftYEdgeTo(glyphPaintRect.y().ceil() + 1); clipBounds.shiftYEdgeTo(glyphPaintRect.y()); break; case TrimBottom: glyphPaintRect.shiftMaxYEdgeTo(glyphPaintRect.maxY().floor() - 1); clipBounds.shiftMaxYEdgeTo(glyphPaintRect.maxY()); break; case TrimTopAndBottom: LayoutUnit temp = glyphPaintRect.y() + 1; glyphPaintRect.shiftYEdgeTo(temp.ceil()); glyphPaintRect.shiftMaxYEdgeTo(glyphPaintRect.maxY().floor() - 1); clipBounds.shiftYEdgeTo(glyphPaintRect.y()); clipBounds.shiftMaxYEdgeTo(glyphPaintRect.maxY()); break; } // Clipping the enclosing IntRect avoids any potential issues at joined edges. GraphicsContextStateSaver stateSaver(*info.context); info.context->clip(clipBounds); info.context->drawText(style()->font(), TextRun(&character, 1), origin); return glyphPaintRect; }
void MediaControls::notifyPanelWidthChanged(const LayoutUnit& newWidth) { // Don't bother to do any work if this matches the most recent panel // width, since we're called after layout. // Note that this code permits a bad frame on resize, since it is // run after the relayout / paint happens. It would be great to improve // this, but it would be even greater to move this code entirely to // JS and fix it there. m_panelWidth = newWidth.toInt(); // Adjust for effective zoom. if (!m_panel->layoutObject() || !m_panel->layoutObject()->style()) return; m_panelWidth = ceil(m_panelWidth / m_panel->layoutObject()->style()->effectiveZoom()); m_panelWidthChangedTimer.startOneShot(0, BLINK_FROM_HERE); }
void distanceDataForNode(FocusType type, const FocusCandidate& current, FocusCandidate& candidate) { if (areElementsOnSameLine(current, candidate)) { if ((type == FocusTypeUp && current.rect.y() > candidate.rect.y()) || (type == FocusTypeDown && candidate.rect.y() > current.rect.y())) { candidate.distance = 0; candidate.alignment = Full; return; } } LayoutRect nodeRect = candidate.rect; LayoutRect currentRect = current.rect; deflateIfOverlapped(currentRect, nodeRect); if (!isRectInDirection(type, currentRect, nodeRect)) return; LayoutPoint exitPoint; LayoutPoint entryPoint; entryAndExitPointsForDirection(type, currentRect, nodeRect, exitPoint, entryPoint); LayoutUnit xAxis = exitPoint.x() - entryPoint.x(); LayoutUnit yAxis = exitPoint.y() - entryPoint.y(); LayoutUnit navigationAxisDistance; LayoutUnit orthogonalAxisDistance; switch (type) { case FocusTypeLeft: case FocusTypeRight: navigationAxisDistance = xAxis.abs(); orthogonalAxisDistance = yAxis.abs(); break; case FocusTypeUp: case FocusTypeDown: navigationAxisDistance = yAxis.abs(); orthogonalAxisDistance = xAxis.abs(); break; default: ASSERT_NOT_REACHED(); return; } double euclidianDistancePow2 = (xAxis * xAxis + yAxis * yAxis).toDouble(); LayoutRect intersectionRect = intersection(currentRect, nodeRect); double overlap = (intersectionRect.width() * intersectionRect.height()).toDouble(); // Distance calculation is based on http://www.w3.org/TR/WICD/#focus-handling candidate.distance = sqrt(euclidianDistancePow2) + navigationAxisDistance+ orthogonalAxisDistance * 2 - sqrt(overlap); LayoutSize viewSize = candidate.visibleNode->document().page()->deprecatedLocalMainFrame()->view()->visibleContentRect().size(); candidate.alignment = alignmentForRects(type, currentRect, nodeRect, viewSize); }
QString Flags::getShortText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig) { if( layoutUnit.isEmpty() ) return QString("--"); QString layoutText = layoutUnit.layout; foreach(const LayoutUnit& lu, keyboardConfig.layouts) { if( layoutUnit.layout == lu.layout && layoutUnit.variant == lu.variant ) { layoutText = lu.getDisplayName(); break; } } //TODO: good autolabel // if( layoutText == layoutUnit.layout && layoutUnit.getDisplayName() != layoutUnit.layout ) { // layoutText = layoutUnit.getDisplayName(); // } return layoutText; }
const QIcon Flags::getIconWithText(const LayoutUnit& layoutUnit, const KeyboardConfig& keyboardConfig) { QString keySuffix(getPixmapKey(keyboardConfig)); QString key(layoutUnit.toString() + keySuffix); if( iconOrTextMap.contains(key) ) { return iconOrTextMap[ key ]; } if( keyboardConfig.indicatorType == KeyboardConfig::SHOW_FLAG ) { QIcon icon = getIcon(layoutUnit.layout); if( ! icon.isNull() ) { iconOrTextMap[ key ] = icon; return icon; } } QString layoutText = Flags::getShortText(layoutUnit, keyboardConfig); const QSize TRAY_ICON_SIZE(21, 14); QPixmap pixmap = QPixmap(TRAY_ICON_SIZE); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); // p.setRenderHint(QPainter::SmoothPixmapTransform); // p.setRenderHint(QPainter::Antialiasing); if( keyboardConfig.indicatorType == KeyboardConfig::SHOW_LABEL_ON_FLAG ) { QIcon iconf = createIcon(layoutUnit.layout); iconf.paint(&painter, painter.window(), Qt::AlignCenter); } drawLabel(painter, layoutText, keyboardConfig.isFlagShown()); painter.end(); QIcon icon(pixmap); iconOrTextMap[ key ] = icon; return icon; }