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);
}
Example #3
0
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 ;
}
Example #4
0
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;
}
Example #5
0
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);
}
Example #9
0
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);
}
Example #11
0
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);
}
Example #12
0
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);
}
Example #13
0
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();
  }
}
Example #14
0
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);
        }
    }
}
Example #17
0
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);
}
Example #18
0
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);
}
Example #19
0
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;
}
Example #21
0
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);
}
Example #23
0
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);
    }
}
Example #24
0
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()));
}
Example #27
0
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;
    }
}
Example #28
0
 bool characterStartsSurrogatePair(unsigned textPosition) const
 {
     return U16_IS_LEAD(m_run[textPosition]) && textPosition + 1 < textLength() && U16_IS_TRAIL(m_run[textPosition + 1]);
 }