Vector<FloatQuad> collectAbsoluteQuads(const RenderObject& renderer, const Layout& layout, bool* wasFixed) { Vector<FloatQuad> quads; auto resolver = runResolver(downcast<RenderBlockFlow>(*renderer.parent()), layout); for (auto run : resolver.rangeForRenderer(renderer)) quads.append(renderer.localToAbsoluteQuad(FloatQuad(run.rect()), UseTransforms, wasFixed)); return quads; }
IntPoint computeTextFirstRunLocation(const RenderText& textRenderer, const Layout& layout) { auto resolver = runResolver(toRenderBlockFlow(*textRenderer.parent()), layout); auto begin = resolver.begin(); if (begin == resolver.end()) return IntPoint(); return flooredIntPoint((*begin).rect().location()); }
IntPoint computeFirstRunLocation(const RenderObject& renderer, const Layout& layout) { auto resolver = runResolver(downcast<RenderBlockFlow>(*renderer.parent()), layout); auto range = resolver.rangeForRenderer(renderer); auto begin = range.begin(); if (begin == range.end()) return IntPoint(0, 0); return flooredIntPoint((*begin).rect().location()); }
Vector<IntRect> collectAbsoluteRects(const RenderObject& renderer, const Layout& layout, const LayoutPoint& accumulatedOffset) { Vector<IntRect> rects; auto resolver = runResolver(downcast<RenderBlockFlow>(*renderer.parent()), layout); for (auto run : resolver.rangeForRenderer(renderer)) { FloatRect rect = run.rect(); rects.append(enclosingIntRect(FloatRect(accumulatedOffset + rect.location(), rect.size()))); } return rects; }
void paintFlow(const RenderBlockFlow& flow, const Layout& layout, PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (paintInfo.phase != PaintPhaseForeground) return; RenderStyle& style = flow.style(); if (style.visibility() != VISIBLE) return; bool debugBordersEnabled = flow.frame().settings().simpleLineLayoutDebugBordersEnabled(); TextPainter textPainter(paintInfo.context()); textPainter.setFont(style.fontCascade()); textPainter.setTextPaintStyle(computeTextPaintStyle(flow.frame(), style, paintInfo)); Optional<TextDecorationPainter> textDecorationPainter; if (style.textDecorationsInEffect() != TextDecorationNone) { const RenderText* textRenderer = childrenOfType<RenderText>(flow).first(); if (textRenderer) { textDecorationPainter = TextDecorationPainter(paintInfo.context(), style.textDecorationsInEffect(), *textRenderer, false); textDecorationPainter->setFont(style.fontCascade()); textDecorationPainter->setBaseline(style.fontMetrics().ascent()); } } LayoutRect paintRect = paintInfo.rect; paintRect.moveBy(-paintOffset); auto resolver = runResolver(flow, layout); float strokeOverflow = std::ceil(flow.style().textStrokeWidth()); float deviceScaleFactor = flow.document().deviceScaleFactor(); for (auto run : resolver.rangeForRect(paintRect)) { if (run.start() == run.end()) continue; FloatRect rect = run.rect(); FloatRect visualOverflowRect = rect; visualOverflowRect.inflate(strokeOverflow); if (paintRect.y() > visualOverflowRect.maxY() || paintRect.maxY() < visualOverflowRect.y()) continue; TextRun textRun(run.text()); textRun.setTabSize(!style.collapseWhiteSpace(), style.tabSize()); // x position indicates the line offset from the rootbox. It's always 0 in case of simple line layout. textRun.setXPos(0); FloatPoint textOrigin = FloatPoint(rect.x() + paintOffset.x(), roundToDevicePixel(run.baselinePosition() + paintOffset.y(), deviceScaleFactor)); textPainter.paintText(textRun, textRun.length(), rect, textOrigin); if (textDecorationPainter) { textDecorationPainter->setWidth(rect.width()); textDecorationPainter->paintTextDecoration(textRun, textOrigin, rect.location() + paintOffset); } if (debugBordersEnabled) paintDebugBorders(paintInfo.context(), LayoutRect(run.rect()), paintOffset); } }
Vector<FloatQuad> collectTextAbsoluteQuads(const RenderText& textRenderer, const Layout& layout, bool* wasFixed) { Vector<FloatQuad> quads; auto resolver = runResolver(toRenderBlockFlow(*textRenderer.parent()), layout); for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) { const auto& run = *it; auto rect = run.rect(); quads.append(textRenderer.localToAbsoluteQuad(FloatQuad(rect), 0, wasFixed)); } return quads; }
Vector<IntRect> collectTextAbsoluteRects(const RenderText& textRenderer, const Layout& layout, const LayoutPoint& accumulatedOffset) { Vector<IntRect> rects; auto resolver = runResolver(toRenderBlockFlow(*textRenderer.parent()), layout); for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) { const auto& run = *it; auto rect = run.rect(); rects.append(enclosingIntRect(FloatRect(accumulatedOffset + rect.location(), rect.size()))); } return rects; }
IntRect computeBoundingBox(const RenderObject& renderer, const Layout& layout) { auto resolver = runResolver(downcast<RenderBlockFlow>(*renderer.parent()), layout); FloatRect boundingBoxRect; for (auto run : resolver.rangeForRenderer(renderer)) { FloatRect rect = run.rect(); if (boundingBoxRect == FloatRect()) boundingBoxRect = rect; else boundingBoxRect.uniteEvenIfEmpty(rect); } return enclosingIntRect(boundingBoxRect); }
void showLineLayoutForFlow(const RenderBlockFlow& flow, const Layout& layout, int depth) { int printedCharacters = 0; printPrefix(printedCharacters, depth); fprintf(stderr, "SimpleLineLayout (%u lines, %u runs) (%p)\n", layout.lineCount(), layout.runCount(), &layout); ++depth; auto resolver = runResolver(flow, layout); for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) { const auto& run = *it; LayoutRect r = run.rect(); printPrefix(printedCharacters, depth); fprintf(stderr, "line %u run(%u, %u) (%.2f, %.2f) (%.2f, %.2f) \"%s\"\n", run.lineIndex(), run.start(), run.end(), r.x().toFloat(), r.y().toFloat(), r.width().toFloat(), r.height().toFloat(), run.text().toStringWithoutCopying().utf8().data()); } }
void showLineLayoutForFlow(const RenderBlockFlow& flow, const Layout& layout, int depth) { int printedCharacters = 0; printPrefix(printedCharacters, depth); fprintf(stderr, "SimpleLineLayout (%u lines, %u runs) (%p)\n", layout.lineCount(), layout.runCount(), &layout); ++depth; for (auto run : runResolver(flow, layout)) { FloatRect rect = run.rect(); printPrefix(printedCharacters, depth); if (run.start() < run.end()) { fprintf(stderr, "line %u run(%u, %u) (%.2f, %.2f) (%.2f, %.2f) \"%s\"\n", run.lineIndex(), run.start(), run.end(), rect.x(), rect.y(), rect.width(), rect.height(), run.text().toStringWithoutCopying().utf8().data()); } else { ASSERT(run.start() == run.end()); fprintf(stderr, "line break %u run(%u, %u) (%.2f, %.2f) (%.2f, %.2f)\n", run.lineIndex(), run.start(), run.end(), rect.x(), rect.y(), rect.width(), rect.height()); } } }
void paintFlow(const RenderBlockFlow& flow, const Layout& layout, PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (paintInfo.phase != PaintPhaseForeground) return; RenderStyle& style = flow.style(); if (style.visibility() != VISIBLE) return; RenderText& textRenderer = toRenderText(*flow.firstChild()); ASSERT(!textRenderer.firstTextBox()); bool debugBordersEnabled = flow.frame().settings().simpleLineLayoutDebugBordersEnabled(); GraphicsContext& context = *paintInfo.context; const Font& font = style.font(); TextPaintStyle textPaintStyle = computeTextPaintStyle(textRenderer, style, paintInfo); GraphicsContextStateSaver stateSaver(context, textPaintStyle.strokeWidth > 0); updateGraphicsContext(context, textPaintStyle); LayoutRect paintRect = paintInfo.rect; paintRect.moveBy(-paintOffset); auto resolver = runResolver(flow, layout); auto range = resolver.rangeForRect(paintRect); for (auto it = range.begin(), end = range.end(); it != end; ++it) { const auto& run = *it; if (!run.rect().intersects(paintRect)) continue; TextRun textRun(run.text()); textRun.setTabSize(!style.collapseWhiteSpace(), style.tabSize()); FloatPoint textOrigin = run.baseline() + paintOffset; textOrigin.setY(roundToDevicePixel(LayoutUnit(textOrigin.y()), flow.document().deviceScaleFactor())); context.drawText(font, textRun, textOrigin); if (debugBordersEnabled) paintDebugBorders(context, run.rect(), paintOffset); } }
void paintFlow(const RenderBlockFlow& flow, const Layout& layout, PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (paintInfo.phase != PaintPhaseForeground) return; RenderStyle& style = flow.style(); if (style.visibility() != VISIBLE) return; bool debugBordersEnabled = flow.frame().settings().simpleLineLayoutDebugBordersEnabled(); GraphicsContext& context = paintInfo.context(); const FontCascade& font = style.fontCascade(); TextPaintStyle textPaintStyle = computeTextPaintStyle(flow.frame(), style, paintInfo); GraphicsContextStateSaver stateSaver(context, textPaintStyle.strokeWidth > 0); updateGraphicsContext(context, textPaintStyle); LayoutRect paintRect = paintInfo.rect; paintRect.moveBy(-paintOffset); auto resolver = runResolver(flow, layout); float strokeOverflow = ceilf(flow.style().textStrokeWidth()); float deviceScaleFactor = flow.document().deviceScaleFactor(); for (const auto& run : resolver.rangeForRect(paintRect)) { FloatRect rect = run.rect(); rect.inflate(strokeOverflow); if (!rect.intersects(paintRect) || run.start() == run.end()) continue; TextRun textRun(run.text()); textRun.setTabSize(!style.collapseWhiteSpace(), style.tabSize()); // x position indicates the line offset from the rootbox. It's always 0 in case of simple line layout. textRun.setXPos(0); FloatPoint textOrigin = FloatPoint(rect.x() + paintOffset.x(), roundToDevicePixel(run.baselinePosition() + paintOffset.y(), deviceScaleFactor)); context.drawText(font, textRun, textOrigin); if (debugBordersEnabled) paintDebugBorders(context, LayoutRect(run.rect()), paintOffset); } }