void InsertIntoTextNodeCommand::doApply(EditingState*) { bool passwordEchoEnabled = document().settings() && document().settings()->passwordEchoEnabled(); if (passwordEchoEnabled) document().updateStyleAndLayoutIgnorePendingStylesheets(); if (!hasEditableStyle(*m_node)) return; if (passwordEchoEnabled) { LayoutText* layoutText = m_node->layoutObject(); if (layoutText && layoutText->isSecure()) layoutText->momentarilyRevealLastTypedCharacter(m_offset + m_text.length() - 1); } m_node->insertData(m_offset, m_text, IGNORE_EXCEPTION); document().updateStyleAndLayout(); }
TEST_F(VisualRectMappingTest, LayoutView) { document().setBaseURLOverride(KURL(ParsedURLString, "http://test.com")); setBodyInnerHTML( "<style>body { margin: 0; }</style>" "<div id=frameContainer>" " <iframe src='http://test.com' width='50' height='50' " "frameBorder='0'></iframe>" "</div>"); setChildFrameHTML( "<style>body { margin: 0; }</style><span><img style='width: 20px; " "height: 100px'></span>text text text"); document().view()->updateAllLifecyclePhases(); LayoutBlock* frameContainer = toLayoutBlock(getLayoutObjectByElementId("frameContainer")); LayoutBlock* frameBody = toLayoutBlock(childDocument().body()->layoutObject()); LayoutText* frameText = toLayoutText(frameBody->lastChild()); // This case involves clipping: frame height is 50, y-coordinate of result // rect is 13, so height should be clipped to (50 - 13) == 37. childDocument().view()->setScrollOffset(ScrollOffset(0, 47), ProgrammaticScroll); LayoutRect originalRect(4, 60, 20, 80); LayoutRect rect = originalRect; EXPECT_TRUE(frameText->mapToVisualRectInAncestorSpace(frameContainer, rect)); EXPECT_EQ(rect, LayoutRect(4, 13, 20, 37)); rect = originalRect; EXPECT_TRUE(frameText->mapToVisualRectInAncestorSpace(&layoutView(), rect)); EXPECT_EQ(rect, LayoutRect(4, 13, 20, 37)); checkPaintInvalidationStateRectMapping(rect, originalRect, *frameText, layoutView(), layoutView()); rect = LayoutRect(4, 60, 0, 80); EXPECT_TRUE(frameText->mapToVisualRectInAncestorSpace(frameContainer, rect, EdgeInclusive)); EXPECT_EQ(rect, LayoutRect(4, 13, 0, 37)); }
LayoutText* SimplifiedBackwardsTextIteratorAlgorithm<Strategy>::handleFirstLetter(int& startOffset, int& offsetInNode) { LayoutText* layoutObject = toLayoutText(m_node->layoutObject()); startOffset = (m_node == m_startNode) ? m_startOffset : 0; if (!layoutObject->isTextFragment()) { offsetInNode = 0; return layoutObject; } LayoutTextFragment* fragment = toLayoutTextFragment(layoutObject); int offsetAfterFirstLetter = fragment->start(); if (startOffset >= offsetAfterFirstLetter) { ASSERT(!m_shouldHandleFirstLetter); offsetInNode = offsetAfterFirstLetter; return layoutObject; } if (!m_shouldHandleFirstLetter && offsetAfterFirstLetter < m_offset) { m_shouldHandleFirstLetter = true; offsetInNode = offsetAfterFirstLetter; return layoutObject; } m_shouldHandleFirstLetter = false; offsetInNode = 0; ASSERT(fragment->isRemainingTextLayoutObject()); ASSERT(fragment->firstLetterPseudoElement()); LayoutObject* pseudoElementLayoutObject = fragment->firstLetterPseudoElement()->layoutObject(); ASSERT(pseudoElementLayoutObject); ASSERT(pseudoElementLayoutObject->slowFirstChild()); LayoutText* firstLetterLayoutObject = toLayoutText(pseudoElementLayoutObject->slowFirstChild()); m_offset = firstLetterLayoutObject->caretMaxOffset(); m_offset += collapsedSpaceLength(firstLetterLayoutObject, m_offset); return firstLetterLayoutObject; }
TextRun SVGInlineTextBox::constructTextRun(const ComputedStyle& style, const SVGTextFragment& fragment) const { LayoutText* text = &layoutObject(); // FIXME(crbug.com/264211): This should not be necessary but can occur if we // layout during layout. Remove this when 264211 is fixed. RELEASE_ASSERT(!text->needsLayout()); TextRun run(static_cast<const LChar*>(0) // characters, will be set below if non-zero. , 0 // length, will be set below if non-zero. , 0 // xPos, only relevant with allowTabs=true , 0 // padding, only relevant for justified text, not relevant for SVG , TextRun::AllowTrailingExpansion , direction() , dirOverride() || style.rtlOrdering() == VisualOrder /* directionalOverride */); if (fragment.length) { if (text->is8Bit()) run.setText(text->characters8() + fragment.characterOffset, fragment.length); else run.setText(text->characters16() + fragment.characterOffset, fragment.length); } // We handle letter & word spacing ourselves. run.disableSpacing(); // Propagate the maximum length of the characters buffer to the TextRun, even when we're only processing a substring. run.setCharactersLength(text->textLength() - fragment.characterOffset); ASSERT(run.charactersLength() >= run.length()); return run; }
void LayoutTreeBuilderForText::createLayoutObject() { ComputedStyle& style = m_layoutObjectParent->mutableStyleRef(); ASSERT(m_node->textLayoutObjectIsNeeded(style, *m_layoutObjectParent)); LayoutText* newLayoutObject = m_node->createTextLayoutObject(style); if (!m_layoutObjectParent->isChildAllowed(newLayoutObject, style)) { newLayoutObject->destroy(); return; } // Make sure the LayoutObject already knows it is going to be added to a LayoutFlowThread before we set the style // for the first time. Otherwise code using inLayoutFlowThread() in the styleWillChange and styleDidChange will fail. newLayoutObject->setIsInsideFlowThread(m_layoutObjectParent->isInsideFlowThread()); LayoutObject* nextLayoutObject = this->nextLayoutObject(); m_node->setLayoutObject(newLayoutObject); // Parent takes care of the animations, no need to call setAnimatableStyle. newLayoutObject->setStyle(&style); m_layoutObjectParent->addChild(newLayoutObject, nextLayoutObject); }