void MainWindow::onInsertTable(int rows, int columns, double width, bool relative) { qDebug() << "Insert table: rows = " << rows << ", columns = " << columns << ", width = " << width << ", relative = " << (relative ? "true" : "false"); QTextCursor cursor = ui->textEdit->textCursor(); QTextTableFormat tableFormat; QVector<QTextLength> columnWidthConstraints; columnWidthConstraints.reserve(columns); double averageColumnWidth = width / columns; if (relative) { for(int i = 0; i < columns; ++i) { QTextLength textLength(QTextLength::PercentageLength, averageColumnWidth); columnWidthConstraints.push_back(textLength); } } else { for(int i = 0; i < columns; ++i) { QTextLength textLength(QTextLength::FixedLength, averageColumnWidth); columnWidthConstraints.push_back(textLength); } } tableFormat.setColumnWidthConstraints(columnWidthConstraints); Q_UNUSED(cursor.insertTable(rows, columns, tableFormat)); }
IntRect RenderSVGInlineText::selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool /*clipToVisibleContent*/) { ASSERT(!needsLayout()); if (selectionState() == SelectionNone) return IntRect(); // Early exit if we're ie. a <text> within a <defs> section. if (isChildOfHiddenContainer(this)) return IntRect(); // Now calculate startPos and endPos for painting selection. // We include a selection while endPos > 0 int startPos, endPos; if (selectionState() == SelectionInside) { // We are fully selected. startPos = 0; endPos = textLength(); } else { selectionStartEnd(startPos, endPos); if (selectionState() == SelectionStart) endPos = textLength(); else if (selectionState() == SelectionEnd) startPos = 0; } if (startPos == endPos) return IntRect(); return computeRepaintRectForRange(repaintContainer, startPos, endPos); }
size_t *FrTextSpans::wordMapping(bool skip_white) const { if (!originalString() || textLength() == 0) return 0 ; size_t *map = FrNewN(size_t,textLength()+1) ; if (map) { size_t count = 0 ; map[0] = count ; if (skip_white) { size_t i ; for (i = 1 ; i <= textLength() ; i++) { if (m_positions[i] != m_positions[i-1] + 1) count++ ; map[i] = count ; } } else { for (size_t i = 1 ; i <= textLength() ; i++) { if (Fr_isspace(m_text[i-1]) && !Fr_isspace(m_text[i])) count++ ; map[i] = count ; } } } return map ; }
bool RenderSVGInlineText::characterStartsNewTextChunk(int position) const { ASSERT(m_attributes.xValues().size() == textLength()); ASSERT(m_attributes.yValues().size() == textLength()); ASSERT(position >= 0); ASSERT(position < static_cast<int>(textLength())); // Each <textPath> element starts a new text chunk, regardless of any x/y values. if (!position && parent()->isSVGTextPath() && !previousSibling()) return true; int currentPosition = 0; unsigned size = m_attributes.textMetricsValues().size(); for (unsigned i = 0; i < size; ++i) { const SVGTextMetrics& metrics = m_attributes.textMetricsValues().at(i); // We found the desired character. if (currentPosition == position) { return m_attributes.xValues().at(position) != SVGTextLayoutAttributes::emptyValue() || m_attributes.yValues().at(position) != SVGTextLayoutAttributes::emptyValue(); } currentPosition += metrics.length(); if (currentPosition > position) break; } // The desired position is available in the x/y list, but not in the character data values list. // That means the previous character data described a single glyph, consisting of multiple unicode characters. // The consequence is that the desired character does not define a new absolute x/y position, even if present in the x/y test. // This code is tested by svg/W3C-SVG-1.1/text-text-06-t.svg (and described in detail, why this influences chunk detection). return false; }
void LayoutSVGInlineText::updateMetricsList(bool& lastCharacterWasWhiteSpace) { m_metrics.clear(); if (!textLength()) return; TextRun run = constructTextRun(*this, 0, textLength(), styleRef().direction()); BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs(); bool bidiOverride = isOverride(styleRef().unicodeBidi()); BidiStatus status(LTR, bidiOverride); if (run.is8Bit() || bidiOverride) { WTF::Unicode::CharDirection direction = WTF::Unicode::LeftToRight; // If BiDi override is in effect, use the specified direction. if (bidiOverride && !styleRef().isLeftToRightDirection()) direction = WTF::Unicode::RightToLeft; bidiRuns.addRun(new BidiCharacterRun(0, run.charactersLength(), status.context.get(), direction)); } else { status.last = status.lastStrong = WTF::Unicode::OtherNeutral; bidiResolver.setStatus(status); bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0)); const bool hardLineBreak = false; const bool reorderRuns = false; bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length()), NoVisualOverride, hardLineBreak, reorderRuns); } for (const BidiCharacterRun* bidiRun = bidiRuns.firstRun(); bidiRun; bidiRun = bidiRun->next()) { TextRun subRun = constructTextRun(*this, bidiRun->start(), bidiRun->stop() - bidiRun->start(), bidiRun->direction()); addMetricsFromRun(subRun, lastCharacterWasWhiteSpace); } bidiResolver.runs().deleteRuns(); }
IntRect RenderSVGInlineText::selectionRect(bool) { ASSERT(!needsLayout()); IntRect rect; if (selectionState() == SelectionNone) return rect; // Early exit if we're ie. a <text> within a <defs> section. if (isChildOfHiddenContainer(this)) return rect; // Now calculate startPos and endPos for painting selection. // We include a selection while endPos > 0 int startPos, endPos; if (selectionState() == SelectionInside) { // We are fully selected. startPos = 0; endPos = textLength(); } else { selectionStartEnd(startPos, endPos); if (selectionState() == SelectionStart) endPos = textLength(); else if (selectionState() == SelectionEnd) startPos = 0; } if (startPos == endPos) return rect; return computeAbsoluteRectForRange(startPos, endPos); }
void SVGTextContentElement::parseMappedAttribute(MappedAttribute* attr) { if (attr->name() == SVGNames::lengthAdjustAttr) { if (attr->value() == "spacing") setLengthAdjustBaseValue(LENGTHADJUST_SPACING); else if (attr->value() == "spacingAndGlyphs") setLengthAdjustBaseValue(LENGTHADJUST_SPACINGANDGLYPHS); } else if (attr->name() == SVGNames::textLengthAttr) { setTextLengthBaseValue(SVGLength(this, LengthModeOther, attr->value())); if (textLength().value() < 0.0) document()->accessSVGExtensions()->reportError("A negative value for text attribute <textLength> is not allowed"); } else { if (SVGTests::parseMappedAttribute(attr)) return; if (SVGLangSpace::parseMappedAttribute(attr)) { if (attr->name().matches(XMLNames::spaceAttr)) { static const AtomicString preserveString("preserve"); if (attr->value() == preserveString) addCSSProperty(attr, CSSPropertyWhiteSpace, CSSValuePre); else addCSSProperty(attr, CSSPropertyWhiteSpace, CSSValueNowrap); } return; } if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) return; SVGStyledElement::parseMappedAttribute(attr); } }
VisiblePosition RenderSVGInlineText::positionForCoordinates(int x, int y) { SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(firstTextBox()); if (!textBox || textLength() == 0) return VisiblePosition(element(), 0, DOWNSTREAM); SVGRootInlineBox* rootBox = textBox->svgRootInlineBox(); RenderObject* object = rootBox ? rootBox->object() : 0; if (!object) return VisiblePosition(element(), 0, DOWNSTREAM); int offset = 0; for (SVGInlineTextBox* box = textBox; box; box = static_cast<SVGInlineTextBox*>(box->nextTextBox())) { if (box->svgCharacterHitsPosition(x + object->xPos(), y + object->yPos(), offset)) { // If we're not at the end/start of the box, stop looking for other selected boxes. if (box->direction() == LTR) { if (offset <= (int) box->end() + 1) break; } else { if (offset > (int) box->start()) break; } } } return VisiblePosition(element(), offset, DOWNSTREAM); }
bool FrTextSpans::compatibleWith(const FrTextSpans *other) const { if (other && textLength() == other->textLength()) { // same number of nonwhitespace chars, so check if they're the same chars for (size_t i = 0 ; i < textLength() ; i++) { char c1 = getChar(i) ; char c2 = other->getChar(i) ; if (c1 != c2) return false ; } return true ; } return false ; }
PositionWithAffinity LayoutSVGInlineText::positionForPoint(const LayoutPoint& point) { if (!firstTextBox() || !textLength()) return createPositionWithAffinity(0, DOWNSTREAM); ASSERT(m_scalingFactor); float baseline = m_scaledFont.fontMetrics().floatAscent() / m_scalingFactor; LayoutBlock* containingBlock = this->containingBlock(); ASSERT(containingBlock); // Map local point to absolute point, as the character origins stored in the text fragments use absolute coordinates. FloatPoint absolutePoint(point); absolutePoint.moveBy(containingBlock->location()); float closestDistance = std::numeric_limits<float>::max(); float closestDistancePosition = 0; const SVGTextFragment* closestDistanceFragment = 0; SVGInlineTextBox* closestDistanceBox = 0; AffineTransform fragmentTransform; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { if (!box->isSVGInlineTextBox()) continue; SVGInlineTextBox* textBox = toSVGInlineTextBox(box); Vector<SVGTextFragment>& fragments = textBox->textFragments(); unsigned textFragmentsSize = fragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { const SVGTextFragment& fragment = fragments.at(i); FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height); fragment.buildFragmentTransform(fragmentTransform); if (!fragmentTransform.isIdentity()) fragmentRect = fragmentTransform.mapRect(fragmentRect); float distance = 0; if (!fragmentRect.contains(absolutePoint)) distance = squaredDistanceToClosestPoint(fragmentRect, absolutePoint); if (distance <= closestDistance) { closestDistance = distance; closestDistanceBox = textBox; closestDistanceFragment = &fragment; closestDistancePosition = fragmentRect.x(); } } } if (!closestDistanceFragment) return createPositionWithAffinity(0, DOWNSTREAM); int offset = closestDistanceBox->offsetForPositionInFragment(*closestDistanceFragment, absolutePoint.x() - closestDistancePosition, true); return createPositionWithAffinity(offset + closestDistanceBox->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM); }
VisiblePosition RenderSVGInlineText::positionForPoint(const LayoutPoint& point, const RenderRegion*) { if (!firstTextBox() || !textLength()) return createVisiblePosition(0, DOWNSTREAM); float baseline = m_scaledFont.fontMetrics().floatAscent(); RenderBlock* containingBlock = this->containingBlock(); ASSERT(containingBlock); // Map local point to absolute point, as the character origins stored in the text fragments use absolute coordinates. FloatPoint absolutePoint(point); absolutePoint.moveBy(containingBlock->location()); float closestDistance = std::numeric_limits<float>::max(); float closestDistancePosition = 0; const SVGTextFragment* closestDistanceFragment = nullptr; SVGInlineTextBox* closestDistanceBox = nullptr; AffineTransform fragmentTransform; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { if (!is<SVGInlineTextBox>(*box)) continue; auto& textBox = downcast<SVGInlineTextBox>(*box); Vector<SVGTextFragment>& fragments = textBox.textFragments(); unsigned textFragmentsSize = fragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { const SVGTextFragment& fragment = fragments.at(i); FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height); fragment.buildFragmentTransform(fragmentTransform); if (!fragmentTransform.isIdentity()) fragmentRect = fragmentTransform.mapRect(fragmentRect); float distance = powf(fragmentRect.x() - absolutePoint.x(), 2) + powf(fragmentRect.y() + fragmentRect.height() / 2 - absolutePoint.y(), 2); if (distance < closestDistance) { closestDistance = distance; closestDistanceBox = &textBox; closestDistanceFragment = &fragment; closestDistancePosition = fragmentRect.x(); } } } if (!closestDistanceFragment) return createVisiblePosition(0, DOWNSTREAM); int offset = closestDistanceBox->offsetForPositionInFragment(*closestDistanceFragment, absolutePoint.x() - closestDistancePosition, true); return createVisiblePosition(offset + closestDistanceBox->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM); }
VisiblePosition RenderSVGInlineText::positionForPoint(const IntPoint& point) { if (!firstTextBox() || !textLength()) return createVisiblePosition(0, DOWNSTREAM); RenderStyle* style = this->style(); ASSERT(style); int baseline = style->font().ascent(); RenderBlock* containingBlock = this->containingBlock(); ASSERT(containingBlock); // Map local point to absolute point, as the character origins stored in the text fragments use absolute coordinates. FloatPoint absolutePoint(point); absolutePoint.move(containingBlock->x(), containingBlock->y()); float closestDistance = std::numeric_limits<float>::max(); float closestDistancePosition = 0; const SVGTextFragment* closestDistanceFragment = 0; SVGInlineTextBox* closestDistanceBox = 0; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { ASSERT(box->isSVGInlineTextBox()); SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(box); Vector<SVGTextFragment>& fragments = textBox->textFragments(); unsigned textFragmentsSize = fragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { const SVGTextFragment& fragment = fragments.at(i); FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height); if (!fragment.transform.isIdentity()) fragmentRect = fragment.transform.mapRect(fragmentRect); float distance = powf(fragmentRect.x() - absolutePoint.x(), 2) + powf(fragmentRect.y() + fragmentRect.height() / 2 - absolutePoint.y(), 2); if (distance < closestDistance) { closestDistance = distance; closestDistanceBox = textBox; closestDistanceFragment = &fragment; closestDistancePosition = fragmentRect.x(); } } } if (!closestDistanceFragment) return createVisiblePosition(0, DOWNSTREAM); int offset = closestDistanceBox->offsetForPositionInFragment(*closestDistanceFragment, absolutePoint.x() - closestDistancePosition, true); return createVisiblePosition(offset + closestDistanceBox->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM); }
void LayoutTextFragment::setText(PassRefPtr<StringImpl> text, bool force) { LayoutText::setText(std::move(text), force); m_start = 0; m_fragmentLength = textLength(); // If we're the remaining text from a first letter then we have to tell the // first letter pseudo element to reattach itself so it can re-calculate the // correct first-letter settings. if (isRemainingTextLayoutObject()) { ASSERT(firstLetterPseudoElement()); firstLetterPseudoElement()->updateTextFragments(); } }
void Edit::AddText(LPCTSTR str) { if(!str) return; if(textLength() <= 0) setText(str); else { tstring newStr = text(); newStr.append(str); setText(newStr.c_str()); } }
bool LayoutSVGInlineText::characterStartsNewTextChunk(int position) const { ASSERT(position >= 0); ASSERT(position < static_cast<int>(textLength())); // Each <textPath> element starts a new text chunk, regardless of any x/y values. if (!position && parent()->isSVGTextPath() && !previousSibling()) return true; const SVGCharacterDataMap::const_iterator it = m_layoutAttributes.characterDataMap().find(static_cast<unsigned>(position + 1)); if (it == m_layoutAttributes.characterDataMap().end()) return false; return it->value.x != SVGTextLayoutAttributes::emptyValue() || it->value.y != SVGTextLayoutAttributes::emptyValue(); }
void RenderTextFragment::setTextInternal(PassRefPtr<StringImpl> text) { RenderText::setTextInternal(text); if (m_firstLetter) { ASSERT(!m_contentString); m_firstLetter->destroy(); m_firstLetter = 0; m_start = 0; m_end = textLength(); if (Node* t = node()) { ASSERT(!t->renderer()); t->setRenderer(this); } } }
void RenderTextFragment::setText(const String& text, bool force) { RenderText::setText(text, force); m_start = 0; m_end = textLength(); if (!m_firstLetter) return; m_firstLetter->destroy(); m_firstLetter = 0; if (!textNode()) return; ASSERT(!textNode()->renderer()); textNode()->setRenderer(this); }
PositionWithAffinity LayoutSVGInlineText::positionForPoint(const LayoutPoint& point) { if (!hasTextBoxes() || !textLength()) return createPositionWithAffinity(0); ASSERT(m_scalingFactor); float baseline = m_scaledFont.getFontMetrics().floatAscent() / m_scalingFactor; LayoutBlock* containingBlock = this->containingBlock(); ASSERT(containingBlock); // Map local point to absolute point, as the character origins stored in the text fragments use absolute coordinates. FloatPoint absolutePoint(point); absolutePoint.moveBy(containingBlock->location()); float closestDistance = std::numeric_limits<float>::max(); float closestDistancePosition = 0; const SVGTextFragment* closestDistanceFragment = nullptr; SVGInlineTextBox* closestDistanceBox = nullptr; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { if (!box->isSVGInlineTextBox()) continue; SVGInlineTextBox* textBox = toSVGInlineTextBox(box); for (const SVGTextFragment& fragment : textBox->textFragments()) { FloatRect fragmentRect = fragment.boundingBox(baseline); float distance = 0; if (!fragmentRect.contains(absolutePoint)) distance = fragmentRect.squaredDistanceTo(absolutePoint); if (distance <= closestDistance) { closestDistance = distance; closestDistanceBox = textBox; closestDistanceFragment = &fragment; closestDistancePosition = fragmentRect.x(); } } } if (!closestDistanceFragment) return createPositionWithAffinity(0); int offset = closestDistanceBox->offsetForPositionInFragment(*closestDistanceFragment, LayoutUnit(absolutePoint.x() - closestDistancePosition), true); return createPositionWithAffinity(offset + closestDistanceBox->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : TextAffinity::Downstream); }
void FramebufferGFX::drawJustifiedText(char* text, int16_t xStart, int16_t xEnd, int16_t yOffset, const FONTSTRUCT* font, uint8_t mode, uint16_t col) { // Example: GFX.drawText("Test Text", 1, 100, 30, &UbuntuCondensed28_smoothed, JUST_CENTER, RGB(255, 255, 255) ); // This would draw the text at the center of the line defined by (1, 100) -- i.e. centered around pixel 50. int xLength = textLength(text, font); int numCharacters = strlen(text); // Left justified text (default) int x = xStart; // Right justified text if (mode == JUST_RIGHT) x = xEnd - xLength; // Center justified text if (mode == JUST_CENTER) x = xStart + ((xEnd - xStart)/2) - (xLength/2); for (int i=0; i<numCharacters; i++) { x += drawChar( text[i], x, yOffset, font, col); } }
bool Buffer::save(const QString &fileName) { // Save the file QFile file(fileName); if (!file.open(QIODevice::WriteOnly)) { return false; } // Save the text to a file. QTextStream output(&file); QByteArray content = getText(textLength() + 1); output.setCodec(m_encoding->name()); output << QString::fromUtf8(content); output.flush(); file.close(); // File saved setFileInfo(QFileInfo(fileName)); setSavePoint(); return true; }
void Edit::AddLine(LPCTSTR str) { int strLen; if(!str) strLen = 0; else strLen = lstrlen(str); if(textLength() <= 0) setText(str); else { tstring newStr = text(); newStr.reserve(newStr.length() + strLen + 3); // 3 == lstrlen("\r\n") + 1 newStr.append(TEXT("\r\n")); if(strLen > 0) // add empty line if strLen == 0 { newStr.append(str); } setText(newStr.c_str()); } }
VisiblePosition RenderSVGInlineText::positionForPoint(const IntPoint& point) { SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(firstTextBox()); if (!textBox || textLength() == 0) return createVisiblePosition(0, DOWNSTREAM); SVGRootInlineBox* rootBox = textBox->svgRootInlineBox(); RenderBlock* object = rootBox ? rootBox->block() : 0; if (!object) return createVisiblePosition(0, DOWNSTREAM); int closestOffsetInBox = 0; // FIXME: This approach is wrong. The correct code would first find the // closest SVGInlineTextBox to the point, and *then* ask only that inline box // what the closest text offset to that point is. This code instead walks // through all boxes in order, so when you click "near" a box, you'll actually // end up returning the nearest offset in the last box, even if the // nearest offset to your click is contained in another box. for (SVGInlineTextBox* box = textBox; box; box = static_cast<SVGInlineTextBox*>(box->nextTextBox())) { if (box->svgCharacterHitsPosition(point.x() + object->x(), point.y() + object->y(), closestOffsetInBox)) { // If we're not at the end/start of the box, stop looking for other selected boxes. if (box->direction() == LTR) { if (closestOffsetInBox <= (int) box->end() + 1) break; } else { if (closestOffsetInBox > (int) box->start()) break; } } } return createVisiblePosition(closestOffsetInBox, DOWNSTREAM); }
void RenderCombineText::combineText() { if (!m_needsFontUpdate) return; m_isCombined = false; m_needsFontUpdate = false; // CSS3 spec says text-combine works only in vertical writing mode. if (style().isHorizontalWritingMode()) return; auto description = originalFont().fontDescription(); float emWidth = description.computedSize() * textCombineMargin; bool shouldUpdateFont = false; description.setOrientation(Horizontal); // We are going to draw combined text horizontally. GlyphOverflow glyphOverflow; glyphOverflow.computeBounds = true; float combinedTextWidth = width(0, textLength(), originalFont(), 0, nullptr, &glyphOverflow); m_isCombined = combinedTextWidth <= emWidth; FontSelector* fontSelector = style().fontCascade().fontSelector(); if (m_isCombined) shouldUpdateFont = m_combineFontStyle->setFontDescription(description); // Need to change font orientation to horizontal. else { // Need to try compressed glyphs. static const FontWidthVariant widthVariants[] = { HalfWidth, ThirdWidth, QuarterWidth }; for (size_t i = 0 ; i < WTF_ARRAY_LENGTH(widthVariants) ; ++i) { description.setWidthVariant(widthVariants[i]); // When modifying this, make sure to keep it in sync with FontPlatformData::isForTextCombine()! FontCascade compressedFont(description, style().fontCascade().letterSpacing(), style().fontCascade().wordSpacing()); compressedFont.update(fontSelector); float runWidth = RenderText::width(0, textLength(), compressedFont, 0, nullptr, &glyphOverflow); if (runWidth <= emWidth) { combinedTextWidth = runWidth; m_isCombined = true; // Replace my font with the new one. shouldUpdateFont = m_combineFontStyle->setFontDescription(description); break; } } } if (!m_isCombined) shouldUpdateFont = m_combineFontStyle->setFontDescription(originalFont().fontDescription()); if (shouldUpdateFont) m_combineFontStyle->fontCascade().update(fontSelector); if (m_isCombined) { DEPRECATED_DEFINE_STATIC_LOCAL(String, objectReplacementCharacterString, (&objectReplacementCharacter, 1)); RenderText::setRenderedText(objectReplacementCharacterString.impl()); m_combinedTextSize = FloatSize(combinedTextWidth, glyphOverflow.bottom + glyphOverflow.top); } }
void iduTable::printText( FILE* aFile ) { iduTableColumn* sColumn; UInt sRowIterator; UInt sRowFence; UInt sColumnIterator; UInt sColumnFence; UInt sWidth; UInt sColumnWidth[16384]; sRowFence = rows(); sColumnFence = columns(); for( sColumnIterator = 0, sColumn = mColumns.next; sColumnIterator < sColumnFence; sColumnIterator++, sColumn = sColumn->next ) { if( mTitle == ID_TRUE ) { sColumnWidth[sColumnIterator] = textLength( sColumn->column ); } else { //fix for UMR sColumnWidth[sColumnIterator] = 0; } for( sRowIterator = 0; sRowIterator < sRowFence; sRowIterator++ ) { sWidth = textLength( value( sColumnIterator, sRowIterator ) ); if( sColumnWidth[sColumnIterator] < sWidth ) { sColumnWidth[sColumnIterator] = sWidth; } } } if( mTitle == ID_TRUE ) { sColumnIterator = 0; if( sColumnIterator < sColumnFence ) { textPrint( aFile, column( sColumnIterator ), sColumnWidth[sColumnIterator] ); for( sColumnIterator++; sColumnIterator < sColumnFence; sColumnIterator++ ) { idlOS::fprintf( aFile, "%c", ' ' ); textPrint( aFile, column( sColumnIterator ), sColumnWidth[sColumnIterator] ); } } idlOS::fprintf( aFile, "%c", '\n' ); } for( sRowIterator = 0; sRowIterator < sRowFence; sRowIterator++ ) { if( filter( sRowIterator ) == ID_TRUE ) { sColumnIterator = 0; if( sColumnIterator < sColumnFence ) { textPrint( aFile, value( sColumnIterator, sRowIterator ), sColumnWidth[sColumnIterator] ); for( sColumnIterator++; sColumnIterator < sColumnFence; sColumnIterator++ ) { idlOS::fprintf( aFile, "%c", ' ' ); textPrint( aFile, value( sColumnIterator, sRowIterator ), sColumnWidth[sColumnIterator] ); } } idlOS::fprintf( aFile, "%c", '\n' ); } } }
void RenderSVGInlineText::absoluteRects(Vector<IntRect>& rects, int, int, bool) { rects.append(computeAbsoluteRectForRange(0, textLength())); }
void RenderSVGInlineText::absoluteQuads(Vector<FloatQuad>& quads) { quads.append(computeRepaintQuadForRange(0, 0, textLength())); }
void RenderCombineText::combineText() { if (!m_needsFontUpdate) return; // An ancestor element may trigger us to lay out again, even when we're already combined. if (m_isCombined) RenderText::setRenderedText(originalText()); m_isCombined = false; m_needsFontUpdate = false; // CSS3 spec says text-combine works only in vertical writing mode. if (style().isHorizontalWritingMode()) return; auto description = originalFont().fontDescription(); float emWidth = description.computedSize() * textCombineMargin; bool shouldUpdateFont = false; description.setOrientation(Horizontal); // We are going to draw combined text horizontally. GlyphOverflow glyphOverflow; glyphOverflow.computeBounds = true; float combinedTextWidth = width(0, textLength(), originalFont(), 0, nullptr, &glyphOverflow); float bestFitDelta = combinedTextWidth - emWidth; auto bestFitDescription = description; m_isCombined = combinedTextWidth <= emWidth; FontSelector* fontSelector = style().fontCascade().fontSelector(); if (m_isCombined) shouldUpdateFont = m_combineFontStyle->setFontDescription(description); // Need to change font orientation to horizontal. else { // Need to try compressed glyphs. static const FontWidthVariant widthVariants[] = { HalfWidth, ThirdWidth, QuarterWidth }; for (size_t i = 0 ; i < WTF_ARRAY_LENGTH(widthVariants) ; ++i) { description.setWidthVariant(widthVariants[i]); // When modifying this, make sure to keep it in sync with FontPlatformData::isForTextCombine()! FontCascade compressedFont(description, style().fontCascade().letterSpacing(), style().fontCascade().wordSpacing()); compressedFont.update(fontSelector); glyphOverflow.left = glyphOverflow.top = glyphOverflow.right = glyphOverflow.bottom = 0; float runWidth = RenderText::width(0, textLength(), compressedFont, 0, nullptr, &glyphOverflow); if (runWidth <= emWidth) { combinedTextWidth = runWidth; m_isCombined = true; // Replace my font with the new one. shouldUpdateFont = m_combineFontStyle->setFontDescription(description); break; } float widthDelta = runWidth - emWidth; if (widthDelta < bestFitDelta) { bestFitDelta = widthDelta; bestFitDescription = description; } } } if (!m_isCombined) { float scaleFactor = std::max(0.4f, emWidth / (emWidth + bestFitDelta)); float originalSize = bestFitDescription.computedSize(); do { float computedSize = originalSize * scaleFactor; bestFitDescription.setComputedSize(computedSize); shouldUpdateFont = m_combineFontStyle->setFontDescription(bestFitDescription); FontCascade compressedFont(bestFitDescription, style().fontCascade().letterSpacing(), style().fontCascade().wordSpacing()); compressedFont.update(fontSelector); glyphOverflow.left = glyphOverflow.top = glyphOverflow.right = glyphOverflow.bottom = 0; float runWidth = RenderText::width(0, textLength(), compressedFont, 0, nullptr, &glyphOverflow); if (runWidth <= emWidth) { combinedTextWidth = runWidth; m_isCombined = true; break; } scaleFactor -= 0.05f; } while (scaleFactor >= 0.4f); } if (shouldUpdateFont) m_combineFontStyle->fontCascade().update(fontSelector); if (m_isCombined) { static NeverDestroyed<String> objectReplacementCharacterString(&objectReplacementCharacter, 1); RenderText::setRenderedText(objectReplacementCharacterString.get()); m_combinedTextWidth = combinedTextWidth; m_combinedTextAscent = glyphOverflow.top; m_combinedTextDescent = glyphOverflow.bottom; } }
bool characterStartsSurrogatePair(unsigned textPosition) const { return U16_IS_LEAD(m_run[textPosition]) && textPosition + 1 < textLength() && U16_IS_TRAIL(m_run[textPosition + 1]); }