void RenderTreeBuilder::createRendererForTextIfNeeded() { ASSERT(!m_node->renderer()); // If we're out of composition then we can't render since there's no parent to inherit from. if (!m_renderingParent) return; if (!shouldCreateRenderer()) return; Text* textNode = toText(m_node); RenderObject* parentRenderer = this->parentRenderer(); m_style = parentRenderer->style(); if (!textNode->textRendererIsNeeded(*m_style, *parentRenderer)) return; RenderText* newRenderer = textNode->createTextRenderer(m_style.get()); if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) { newRenderer->destroy(); return; } // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail. newRenderer->setFlowThreadState(parentRenderer->flowThreadState()); RenderObject* nextRenderer = this->nextRenderer(); textNode->setRenderer(newRenderer); // Parent takes care of the animations, no need to call setAnimatableStyle. newRenderer->setStyle(m_style.release()); parentRenderer->addChild(newRenderer, nextRenderer); }
Vector<FloatQuad> RenderTextLineBoxes::absoluteQuadsForRange(const RenderText& renderer, unsigned start, unsigned end, bool useSelectionHeight, bool* wasFixed) const { Vector<FloatQuad> quads; for (auto box = m_first; box; box = box->nextTextBox()) { // Note: box->end() returns the index of the last character, not the index past it if (start <= box->start() && box->end() < end) { FloatRect boundaries = box->calculateBoundaries(); if (useSelectionHeight) { LayoutRect selectionRect = box->localSelectionRect(start, end); if (box->isHorizontal()) { boundaries.setHeight(selectionRect.height()); boundaries.setY(selectionRect.y()); } else { boundaries.setWidth(selectionRect.width()); boundaries.setX(selectionRect.x()); } } quads.append(renderer.localToAbsoluteQuad(boundaries, 0, wasFixed)); continue; } FloatRect rect = localQuadForTextBox(*box, start, end, useSelectionHeight); if (!rect.isZero()) quads.append(renderer.localToAbsoluteQuad(rect, 0, wasFixed)); } return quads; }
void TextAutoSizingValue::addNode(Node* node, float size) { ASSERT(node); RenderText* renderText = toRenderText(node->renderer()); renderText->setCandidateComputedTextSize(size); m_autoSizedNodes.add(node); }
TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFragment& fragment) const { ASSERT(style); ASSERT(textRenderer()); RenderText* text = textRenderer(); ASSERT(text); TextRun run(text->characters() + fragment.positionListOffset , fragment.length , false /* allowTabs */ , 0 /* xPos, only relevant with allowTabs=true */ , 0 /* padding, only relevant for justified text, not relevant for SVG */ , TextRun::AllowTrailingExpansion , direction() == RTL , m_dirOverride || style->visuallyOrdered() /* directionalOverride */); #if ENABLE(SVG_FONTS) RenderObject* parentRenderer = parent()->renderer(); ASSERT(parentRenderer); run.setReferencingRenderObject(parentRenderer); #endif // Disable any word/character rounding. run.disableRoundingHacks(); // We handle letter & word spacing ourselves. run.disableSpacing(); return run; }
void NodeRenderingContext::createRendererForTextIfNeeded() { ASSERT(!m_node->renderer()); Text* textNode = toText(m_node); if (!shouldCreateRenderer()) return; RenderObject* parentRenderer = this->parentRenderer(); if (m_parentDetails.resetStyleInheritance()) m_style = textNode->document()->styleResolver()->defaultStyleForElement(); else m_style = parentRenderer->style(); if (!textNode->textRendererIsNeeded(*this)) return; RenderText* newRenderer = textNode->createTextRenderer(m_style.get()); if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) { newRenderer->destroy(); return; } // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail. newRenderer->setFlowThreadState(parentRenderer->flowThreadState()); RenderObject* nextRenderer = this->nextRenderer(); textNode->setRenderer(newRenderer); // Parent takes care of the animations, no need to call setAnimatableStyle. newRenderer->setStyle(m_style.release()); parentRenderer->addChild(newRenderer, nextRenderer); }
void visibleTextQuads(const Range& range, Vector<FloatQuad>& quads, bool useSelectionHeight) { // Range::textQuads includes hidden text, which we don't want. // To work around this, this is a copy of it which skips hidden elements. Node* startContainer = range.startContainer(); Node* endContainer = range.endContainer(); if (!startContainer || !endContainer) return; Node* stopNode = range.pastLastNode(); for (Node* node = range.firstNode(); node != stopNode; node = node->traverseNextNode()) { RenderObject* r = node->renderer(); if (!r || !r->isText()) continue; if (r->style()->visibility() != VISIBLE) continue; RenderText* renderText = toRenderText(r); int startOffset = node == startContainer ? range.startOffset() : 0; int endOffset = node == endContainer ? range.endOffset() : std::numeric_limits<int>::max(); renderText->absoluteQuadsForRange(quads, startOffset, endOffset, useSelectionHeight); } }
IntRect SVGInlineTextBox::calculateBoundaries() const { FloatRect textRect; RenderText* textRenderer = this->textRenderer(); ASSERT(textRenderer); RenderStyle* style = textRenderer->style(); ASSERT(style); int baseline = baselinePosition(AlphabeticBaseline); int heightDifference = baseline - style->fontMetrics().ascent(); unsigned textFragmentsSize = m_textFragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { const SVGTextFragment& fragment = m_textFragments.at(i); FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height + heightDifference); if (!fragment.transform.isIdentity()) fragmentRect = fragment.transform.mapRect(fragmentRect); textRect.unite(fragmentRect); } return enclosingIntRect(textRect); }
Vector<IntRect> RenderTextLineBoxes::absoluteRectsForRange(const RenderText& renderer, unsigned start, unsigned end, bool useSelectionHeight, bool* wasFixed) const { Vector<IntRect> rects; for (auto box = m_first; box; box = box->nextTextBox()) { // Note: box->end() returns the index of the last character, not the index past it if (start <= box->start() && box->end() < end) { FloatRect boundaries = box->calculateBoundaries(); if (useSelectionHeight) { LayoutRect selectionRect = box->localSelectionRect(start, end); if (box->isHorizontal()) { boundaries.setHeight(selectionRect.height()); boundaries.setY(selectionRect.y()); } else { boundaries.setWidth(selectionRect.width()); boundaries.setX(selectionRect.x()); } } rects.append(renderer.localToAbsoluteQuad(boundaries, 0, wasFixed).enclosingBoundingBox()); continue; } // FIXME: This code is wrong. It's converting local to absolute twice. http://webkit.org/b/65722 FloatRect rect = localQuadForTextBox(*box, start, end, useSelectionHeight); if (!rect.isZero()) rects.append(renderer.localToAbsoluteQuad(rect, 0, wasFixed).enclosingBoundingBox()); } return rects; }
Dart_Handle Paragraph::getWordBoundary(unsigned offset) { String text; int start = 0, end = 0; for (RenderObject* object = m_renderView.get(); object; object = object->nextInPreOrder()) { if (!object->isText()) continue; RenderText* renderText = toRenderText(object); text.append(renderText->text()); } TextBreakIterator* it = wordBreakIterator(text, 0, text.length()); if (it) { end = it->following(offset); if (end < 0) end = it->last(); start = it->previous(); } Dart_Handle result = Dart_NewList(2); Dart_ListSetAt(result, 0, ToDart(start)); Dart_ListSetAt(result, 1, ToDart(end)); return result; }
/** * \brief Draw, Call back from the GLMoblet. */ void draw() { mDTime.tick(); // update delta time ticker. our fps timer (resets for every tick call) MoGraph::Scene &scene = mGraph->getScene(); // get scene information const int iGridZ = scene.getGridZ(); // need to be able to read the grid size const int iGridX = scene.getGridX(); const int sz = iGridX * iGridZ; mGraph->setValues(mTables,sz); // set the value array to the Graph to read from mGraph->setColors(mColors,sz); // set the color array to the Graph to read from mGraph->draw(); // Draw the whole graph system // DRAW ADDITIONAL TEXT ON SCREEN (Orthogonal projections) //--------------------------------------------------------------------- glm::vec4 col(1.0f,1.0f,1.0f,1.0f); // White color glm::vec3 pos(0.0f,0.0f,10.0f); // set screen position upper left corner 0,0.. note need z depth value for order. float sy = (0.6f*(float)scene.getWidth())/320.0f; // scale size regardless to resolution our reference resolution is 320.. mText.setScale(sy,sy); char buf[64]; // create text string sprintf ( buf, "FPS=%.2f ms=%d",mDTime.currentFps(),mDTime.getElapsed()); mText.drawText(buf,pos,col); // call drawText }
TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFragment& fragment) const { ASSERT(style); ASSERT(textRenderer()); RenderText* text = textRenderer(); ASSERT(text); TextRun run(text->characters() + fragment.characterOffset , fragment.length , false /* allowTabs */ , 0 /* xPos, only relevant with allowTabs=true */ , 0 /* padding, only relevant for justified text, not relevant for SVG */ , TextRun::AllowTrailingExpansion , direction() , m_dirOverride || style->rtlOrdering() == VisualOrder /* directionalOverride */); if (textRunNeedsRenderingContext(style->font())) run.setRenderingContext(SVGTextRunRenderingContext::create(text)); run.disableRoundingHacks(); // 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; }
static PangoLayout* getPangoLayoutForAtk(AtkText* textObject) { AccessibilityObject* coreObject = core(textObject); HostWindow* hostWindow = coreObject->document()->view()->hostWindow(); if (!hostWindow) return 0; PlatformPageClient webView = hostWindow->platformPageClient(); if (!webView) return 0; GString* str = g_string_new(NULL); AccessibilityRenderObject* accObject = static_cast<AccessibilityRenderObject*>(coreObject); if (!accObject) return 0; RenderText* renderText = toRenderText(accObject->renderer()); if (!renderText) return 0; // Create a string with the layout as it appears on the screen InlineTextBox* box = renderText->firstTextBox(); while (box) { gchar *text = convertUniCharToUTF8(renderText->characters(), renderText->textLength(), box->start(), box->end()); g_string_append(str, text); g_string_append(str, "\n"); box = box->nextTextBox(); } PangoLayout* layout = gtk_widget_create_pango_layout(static_cast<GtkWidget*>(webView), g_string_free(str, FALSE)); g_object_set_data_full(G_OBJECT(textObject), "webkit-accessible-pango-layout", layout, g_object_unref); return layout; }
void writeSVGInlineText(TextStream& ts, const RenderText& text, int indent) { writeStandardPrefix(ts, text, indent); // Why not just linesBoundingBox()? ts << " " << FloatRect(text.firstRunOrigin(), text.linesBoundingBox().size()) << "\n"; writeSVGInlineTextBoxes(ts, text, indent); }
Position Position::upstream(EStayInBlock stayInBlock) const { Position start = equivalentDeepPosition(); NodeImpl *startNode = start.node(); if (!startNode) return Position(); NodeImpl *block = startNode->enclosingBlockFlowOrTableElement(); Position lastVisible; PositionIterator it(start); for (; !it.atStart(); it.previous()) { NodeImpl *currentNode = it.current().node(); if (stayInBlock) { NodeImpl *currentBlock = currentNode->enclosingBlockFlowOrTableElement(); if (block != currentBlock) return it.next(); } RenderObject *renderer = currentNode->renderer(); if (!renderer) continue; if (renderer->style()->visibility() != VISIBLE) continue; lastVisible = it.current(); if (renderer->isReplaced() || renderer->isBR()) { if (it.current().offset() >= renderer->caretMaxOffset()) return Position(currentNode, renderer->caretMaxOffset()); else continue; } if (renderer->isText() && static_cast<RenderText *>(renderer)->firstTextBox()) { if (currentNode != startNode) return Position(currentNode, renderer->caretMaxOffset()); if (it.current().offset() < 0) continue; uint textOffset = it.current().offset(); RenderText *textRenderer = static_cast<RenderText *>(renderer); for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) { if (textOffset > box->start() && textOffset <= box->start() + box->len()) return it.current(); else if (box != textRenderer->lastTextBox() && !box->nextOnLine() && textOffset == box->start() + box->len() + 1) return it.current(); } } } return lastVisible.isNotNull() ? lastVisible : *this; }
InlineTextBox * RenderText::findInlineTextBox( int offset, int &pos, bool checkFirstLetter ) { // The text boxes point to parts of the rendertext's str string // (they don't include '\n') // Find the text box that includes the character at @p offset // and return pos, which is the position of the char in the run. // FIXME: make this use binary search? Dirk says it won't work :-( (LS) (void)checkFirstLetter; #if 0 if (checkFirstLetter && forcedMinOffset()) { // kdDebug(6040) << "checkFirstLetter: forcedMinOffset: " << forcedMinOffset() << endl; RenderFlow *firstLetter = static_cast<RenderFlow *>(previousSibling()); if (firstLetter && firstLetter->isFlow() && firstLetter->isFirstLetter()) { RenderText *letterText = static_cast<RenderText *>(firstLetter->firstChild()); //kdDebug(6040) << "lettertext: " << letterText << " minOfs: " << letterText->minOffset() << " maxOfs: " << letterText->maxOffset() << endl; if (offset >= letterText->minOffset() && offset <= letterText->maxOffset()) { InlineTextBox *result = letterText->findInlineTextBox(offset, pos, false); //kdDebug(6040) << "result: " << result << endl; if (result) return result; } } } #endif if ( m_lines.isEmpty() ) return 0L; // The text boxes don't resemble a contiguous coverage of the text, there // may be holes. Therefore, we snap to the nearest previous text box if // the given offset happens to point to such a hole. InlineTextBox* s = m_lines[0]; uint count = m_lines.count(); uint si = 0; uint nearest_idx = 0; // index of nearest text box int nearest = INT_MAX; // nearest distance //kdDebug(6040) << "s[" << si << "] m_start " << s->m_start << " m_end " << (s->m_start + s->m_len) << endl; while(!(offset >= s->m_start && offset <= s->m_start + s->m_len) && ++si < count) { int dist = offset - (s->m_start + s->m_len); //kdDebug(6040) << "dist " << dist << " nearest " << nearest << endl; if (dist >= 0 && dist <= nearest) { nearest = dist; nearest_idx = si - 1; }/*end if*/ s = m_lines[si]; //kdDebug(6040) << "s[" << si << "] m_start " << s->m_start << " m_end " << (s->m_start + s->m_len) << endl; } //kdDebug(6040) << "nearest_idx " << nearest_idx << " count " << count << endl; if (si >= count) s = m_lines[nearest_idx]; // we are now in the correct text box pos = kMin(offset - s->m_start, int( s->m_len )); //kdDebug(6040) << "offset=" << offset << " s->m_start=" << s->m_start << endl; return s; }
TextDecorationPainter::TextDecorationPainter(GraphicsContext& context, TextDecoration decoration, const RenderText& renderer, bool isFirstLine) : m_context(context) , m_decoration(decoration) , m_wavyOffset(wavyOffsetFromDecoration()) , m_isPrinting(renderer.document().printing()) , m_styles(stylesForRenderer(renderer, m_decoration, isFirstLine)) , m_lineStyle(isFirstLine ? renderer.firstLineStyle() : renderer.style()) { }
void RenderTextLineBoxes::removeAllFromParent(RenderText& renderer) { if (!m_first) { if (renderer.parent()) renderer.parent()->dirtyLinesFromChangedChild(&renderer); return; } for (auto box = m_first; box; box = box->nextTextBox()) box->removeFromParent(); }
void Text::updateTextRenderer(unsigned offsetOfReplacedData, unsigned lengthOfReplacedData) { if (!attached()) return; RenderText* textRenderer = toRenderText(renderer()); if (!textRenderer || !textRendererIsNeeded(NodeRenderingContext(this, textRenderer->style()))) { reattach(); return; } textRenderer->setTextWithOffset(dataImpl(), offsetOfReplacedData, lengthOfReplacedData); }
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; }
int InlineTextBox::offsetForPosition(int _x, bool includePartialGlyphs) const { if (isLineBreak()) return 0; RenderText* text = static_cast<RenderText*>(m_object); RenderStyle *style = text->style(m_firstLine); const Font* f = &style->font(); return f->offsetForPosition(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()), _x - m_x, includePartialGlyphs); }
ValueShower::ValueShower(WinBase* pw, Style style, Point pt, unsigned n_characters, const char* lab) : Message(pw, style, lab, pt), Element(), size(Rect(pt.x, pt.y, 0, TTF_FontHeight(style.st==2? draw_ttf->ttf_font: draw_title_ttf->ttf_font))) { RenderText* rt = style.st==2? draw_ttf : draw_title_ttf; char* tmp = new char[n_characters]; for(unsigned i = 0; i < n_characters-1; i++) tmp[i] = '_'; tmp[n_characters-1] = '\0'; size.w = rt->text_width(tmp); delete [] tmp; }
static float textWidth(const RenderText& text, unsigned from, unsigned length, float xPosition, const RenderStyle& style) { if (style.font().isFixedPitch() || (!from && length == text.textLength())) return text.width(from, length, style.font(), xPosition, nullptr, nullptr); // FIXME: Add templated UChar/LChar paths. TextRun run = text.is8Bit() ? TextRun(text.characters8() + from, length) : TextRun(text.characters16() + from, length); run.setCharactersLength(text.textLength() - from); ASSERT(run.charactersLength() >= run.length()); run.setXPos(xPosition); return style.font().width(run); }
void Text::updateTextRenderer(unsigned offsetOfReplacedData, unsigned lengthOfReplacedData, RecalcStyleBehavior recalcStyleBehavior) { if (!inActiveDocument()) return; RenderText* textRenderer = renderer(); if (!textRenderer || !textRendererIsNeeded(*textRenderer->style(), *textRenderer->parent())) { lazyReattachIfAttached(); // FIXME: Editing should be updated so this is not neccesary. if (recalcStyleBehavior == DeprecatedRecalcStyleImmediatlelyForEditing) document().updateRenderTreeIfNeeded(); return; } textRenderer->setTextWithOffset(dataImpl(), offsetOfReplacedData, lengthOfReplacedData); }
/* addRenderText - This method adds text for rendering. Text only needs to be added once. */ void GameText::addRenderText(wstring *textToAdd, int initX, int initY, int initWidth, int initHeight) { RenderText *text = new RenderText(); text->setText(textToAdd); text->x = initX; text->y = initY; text->width = initWidth; text->height = initHeight; renderText.push_back(text); }
int Paragraph::absoluteOffsetForPosition(const PositionWithAffinity& position) { DCHECK(position.renderer()); unsigned offset = 0; for (RenderObject* object = m_renderView.get(); object; object = object->nextInPreOrder()) { if (object == position.renderer()) return offset + position.offset(); if (object->isText()) { RenderText* text = toRenderText(object); offset += text->textLength(); } } DCHECK(false); return 0; }
void Text::recalcTextStyle(StyleChange change) { RenderText* renderer = toRenderText(this->renderer()); if (change != NoChange && renderer) renderer->setStyle(document()->ensureStyleResolver()->styleForText(this)); if (needsStyleRecalc()) { if (renderer) renderer->setText(dataImpl()); else reattach(); } clearNeedsStyleRecalc(); }
static void updateTextStyle(Text* text, RenderStyle* parentElementStyle, Style::Change change) { RenderText* renderer = toRenderText(text->renderer()); if (change != Style::NoChange && renderer) renderer->setStyle(parentElementStyle); if (!text->needsStyleRecalc()) return; if (renderer) renderer->setText(text->dataImpl()); else text->attachText(); text->clearNeedsStyleRecalc(); }
IntRect computeTextBoundingBox(const RenderText& textRenderer, const Layout& layout) { auto resolver = lineResolver(toRenderBlockFlow(*textRenderer.parent()), layout); auto it = resolver.begin(); auto end = resolver.end(); if (it == end) return IntRect(); auto firstLineRect = *it; float left = firstLineRect.x(); float right = firstLineRect.maxX(); float bottom = firstLineRect.maxY(); for (++it; it != end; ++it) { auto rect = *it; if (rect.x() < left) left = rect.x(); if (rect.maxX() > right) right = rect.maxX(); if (rect.maxY() > bottom) bottom = rect.maxY(); } float x = left; float y = firstLineRect.y(); float width = right - left; float height = bottom - y; return enclosingIntRect(FloatRect(x, y, width, height)); }
int InlineTextBox::positionForOffset(int offset) const { ASSERT(offset >= m_start); ASSERT(offset <= m_start + m_len); if (isLineBreak()) return m_x; RenderText* text = static_cast<RenderText*>(m_object); const Font& f = text->style(m_firstLine)->font(); int from = direction() == RTL ? offset - m_start : 0; int to = direction() == RTL ? m_len : offset - m_start; // FIXME: Do we need to add rightBearing here? return enclosingIntRect(f.selectionRectForText(TextRun(text->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride), IntPoint(m_x, 0), 0, from, to)).right(); }
static void writeTextRun(TextStream& ts, const RenderText& o, const InlineTextBox& run) { // FIXME: Table cell adjustment is temporary until results can be updated. int y = run.m_y; if (o.containingBlock()->isTableCell()) y -= toRenderTableCell(o.containingBlock())->intrinsicPaddingTop(); ts << "text run at (" << run.m_x << "," << y << ") width " << run.m_width; if (run.direction() == RTL || run.m_dirOverride) { ts << (run.direction() == RTL ? " RTL" : " LTR"); if (run.m_dirOverride) ts << " override"; } ts << ": " << quoteAndEscapeNonPrintables(String(o.text()).substring(run.start(), run.len())) << "\n"; }