float nsSVGTextContainerFrame::GetComputedTextLength() { float length = 0.0f; nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode(); while (node) { length += node->GetComputedTextLength(); node = GetNextGlyphFragmentChildNode(node); } return length; }
PRUint32 nsSVGTextContainerFrame::GetNumberOfChars() { PRUint32 nchars = 0; nsISVGGlyphFragmentNode* node; node = GetFirstGlyphFragmentChildNode(); while (node) { nchars += node->GetNumberOfChars(); node = GetNextGlyphFragmentChildNode(node); } return nchars; }
float nsSVGTextContainerFrame::GetSubStringLength(PRUint32 charnum, PRUint32 nchars) { float length = 0.0f; nsISVGGlyphFragmentNode *node = GetFirstGlyphFragmentChildNode(); while (node) { PRUint32 count = node->GetNumberOfChars(); if (count > charnum) { PRUint32 fragmentChars = NS_MIN(nchars, count); float fragmentLength = node->GetSubStringLength(charnum, fragmentChars); length += fragmentLength; nchars -= fragmentChars; if (nchars == 0) break; } charnum -= NS_MIN(charnum, count); node = GetNextGlyphFragmentChildNode(node); } return length; }
NS_IMETHODIMP nsSVGTextContainerFrame::GetRotationOfChar(PRUint32 charnum, float *_retval) { *_retval = 0.0f; if (charnum >= GetNumberOfChars()) { return NS_ERROR_DOM_INDEX_SIZE_ERR; } nsISVGGlyphFragmentNode *node = GetFirstGlyphFragmentChildNode(); if (!node) { return NS_ERROR_FAILURE; } PRUint32 offset; nsISVGGlyphFragmentLeaf *fragment = GetGlyphFragmentAtCharNum(node, charnum, &offset); if (!fragment) { return NS_ERROR_FAILURE; } return fragment->GetRotationOfChar(charnum - offset, _retval); }
PRInt32 nsSVGTextContainerFrame::GetCharNumAtPosition(nsIDOMSVGPoint *point) { PRInt32 index = -1; PRInt32 offset = 0; nsISVGGlyphFragmentNode *node = GetFirstGlyphFragmentChildNode(); while (node) { PRUint32 count = node->GetNumberOfChars(); if (count > 0) { PRInt32 charnum = node->GetCharNumAtPosition(point); if (charnum >= 0) { index = charnum + offset; } offset += count; // Keep going, multiple characters may match // and we must return the last one } node = GetNextGlyphFragmentChildNode(node); } return index; }
void nsSVGTextContainerFrame::SetWhitespaceHandling() { // init children: nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode(); nsISVGGlyphFragmentNode* next; PRUint8 whitespaceHandling = COMPRESS_WHITESPACE | TRIM_LEADING_WHITESPACE; for (nsIFrame *frame = this; frame != nsnull; frame = frame->GetParent()) { nsIContent *content = frame->GetContent(); static nsIContent::AttrValuesArray strings[] = {&nsGkAtoms::preserve, &nsGkAtoms::_default, nsnull}; PRInt32 index = content->FindAttrValueIn(kNameSpaceID_XML, nsGkAtoms::space, strings, eCaseMatters); if (index == 0) { whitespaceHandling = PRESERVE_WHITESPACE; break; } if (index != nsIContent::ATTR_MISSING || (frame->GetStateBits() & NS_STATE_IS_OUTER_SVG)) break; } while (node) { next = GetNextGlyphFragmentChildNode(node); if (!next && (whitespaceHandling & COMPRESS_WHITESPACE)) { whitespaceHandling |= TRIM_TRAILING_WHITESPACE; } node->SetWhitespaceHandling(whitespaceHandling); node = next; whitespaceHandling &= ~TRIM_LEADING_WHITESPACE; } }
void nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform) { if (mMetricsState == suspended || !mPositioningDirty) return; SetWhitespaceHandling(); nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode(); if (!node) return; mPositioningDirty = PR_FALSE; nsISVGGlyphFragmentLeaf *fragment, *firstFragment; firstFragment = node->GetFirstGlyphFragment(); if (!firstFragment) { return; } float x = 0, y = 0; { nsCOMPtr<nsIDOMSVGLengthList> list = GetX(); GetSingleValue(list, &x); } { nsCOMPtr<nsIDOMSVGLengthList> list = GetY(); GetSingleValue(list, &y); } // loop over chunks while (firstFragment) { { nsCOMPtr<nsIDOMSVGLengthList> list = firstFragment->GetX(); GetSingleValue(list, &x); } { nsCOMPtr<nsIDOMSVGLengthList> list = firstFragment->GetY(); GetSingleValue(list, &y); } // check for startOffset on textPath nsSVGTextPathFrame *textPath = firstFragment->FindTextPathParent(); if (textPath) { if (!textPath->GetPathFrame()) { // invalid text path, give up return; } x = textPath->GetStartOffset(); } // determine x offset based on text_anchor: PRUint8 anchor = firstFragment->GetTextAnchor(); float chunkLength = 0.0f; if (anchor != NS_STYLE_TEXT_ANCHOR_START) { // need to get the total chunk length fragment = firstFragment; while (fragment) { float dx = 0.0f; nsCOMPtr<nsIDOMSVGLengthList> list = fragment->GetDx(); GetSingleValue(list, &dx); chunkLength += dx + fragment->GetAdvance(aForceGlobalTransform); fragment = fragment->GetNextGlyphFragment(); if (fragment && fragment->IsAbsolutelyPositioned()) break; } } if (anchor == NS_STYLE_TEXT_ANCHOR_MIDDLE) x -= chunkLength/2.0f; else if (anchor == NS_STYLE_TEXT_ANCHOR_END) x -= chunkLength; // set position of each fragment in this chunk: fragment = firstFragment; while (fragment) { float dx = 0.0f, dy = 0.0f; { nsCOMPtr<nsIDOMSVGLengthList> list = fragment->GetDx(); GetSingleValue(list, &dx); } { nsCOMPtr<nsIDOMSVGLengthList> list = fragment->GetDy(); GetSingleValue(list, &dy); } fragment->SetGlyphPosition(x + dx, y + dy, aForceGlobalTransform); x += dx + fragment->GetAdvance(aForceGlobalTransform); y += dy; fragment = fragment->GetNextGlyphFragment(); if (fragment && fragment->IsAbsolutelyPositioned()) break; } firstFragment = fragment; } }