NS_IMETHODIMP nsThebesRenderingContext::GetWidth(const PRUnichar *aString, PRUint32 aLength, nscoord &aWidth, PRInt32 *aFontID) { PRUint32 maxChunkLength = GetMaxChunkLength(this); aWidth = 0; if (aFontID) { *aFontID = 0; } while (aLength > 0) { PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength); nscoord width; nsresult rv = GetWidthInternal(aString, len, width); if (NS_FAILED(rv)) return rv; aWidth += width; aLength -= len; aString += len; } return NS_OK; }
NS_IMETHODIMP nsThebesRenderingContext::GetTextDimensions(const PRUnichar* aString, PRUint32 aLength, nsTextDimensions& aDimensions, PRInt32* aFontID) { PRUint32 maxChunkLength = GetMaxChunkLength(this); if (aLength <= maxChunkLength) return GetTextDimensionsInternal(aString, aLength, aDimensions); if (aFontID) { *aFontID = nsnull; } PRBool firstIteration = PR_TRUE; while (aLength > 0) { PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength); nsTextDimensions dimensions; nsresult rv = GetTextDimensionsInternal(aString, len, dimensions); if (NS_FAILED(rv)) return rv; if (firstIteration) { // Instead of combining with a Clear()ed nsTextDimensions, we // assign directly in the first iteration. This ensures that // negative ascent/ descent can be returned. aDimensions = dimensions; } else { aDimensions.Combine(dimensions); } aLength -= len; aString += len; firstIteration = PR_FALSE; } return NS_OK; }
void nsRenderingContext::DrawString(const PRUnichar *aString, PRUint32 aLength, nscoord aX, nscoord aY) { PRUint32 maxChunkLength = GetMaxChunkLength(); if (aLength <= maxChunkLength) { mFontMetrics->DrawString(aString, aLength, aX, aY, this, this); return; } PRBool isRTL = mFontMetrics->GetTextRunRTL(); // If we're drawing right to left, we must start at the end. if (isRTL) { aX += GetWidth(aString, aLength); } while (aLength > 0) { PRInt32 len = FindSafeLength(aString, aLength, maxChunkLength); nscoord width = mFontMetrics->GetWidth(aString, len, this); if (isRTL) { aX -= width; } mFontMetrics->DrawString(aString, len, aX, aY, this, this); if (!isRTL) { aX += width; } aLength -= len; aString += len; } }
NS_IMETHODIMP nsThebesRenderingContext::GetBoundingMetrics(const char* aString, PRUint32 aLength, nsBoundingMetrics& aBoundingMetrics) { PRUint32 maxChunkLength = GetMaxChunkLength(this); if (aLength <= maxChunkLength) return GetBoundingMetricsInternal(aString, aLength, aBoundingMetrics); PRBool firstIteration = PR_TRUE; while (aLength > 0) { PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength); nsBoundingMetrics metrics; nsresult rv = GetBoundingMetricsInternal(aString, len, metrics); if (NS_FAILED(rv)) return rv; if (firstIteration) { // Instead of combining with a Clear()ed nsBoundingMetrics, we // assign directly in the first iteration. This ensures that // negative ascent/ descent can be returned and the left bearing // is properly initialized. aBoundingMetrics = metrics; } else { aBoundingMetrics += metrics; } aLength -= len; aString += len; firstIteration = PR_FALSE; } return NS_OK; }
NS_IMETHODIMP nsThebesRenderingContext::DrawString(const PRUnichar *aString, PRUint32 aLength, nscoord aX, nscoord aY, PRInt32 aFontID, const nscoord* aSpacing) { PRUint32 maxChunkLength = GetMaxChunkLength(this); if (aLength <= maxChunkLength) { return DrawStringInternal(aString, aLength, aX, aY, aFontID, aSpacing); } PRBool isRTL = PR_FALSE; GetRightToLeftText(&isRTL); if (isRTL) { nscoord totalWidth = 0; if (aSpacing) { for (PRUint32 i = 0; i < aLength; ++i) { totalWidth += aSpacing[i]; } } else { nsresult rv = GetWidth(aString, aLength, totalWidth); if (NS_FAILED(rv)) return rv; } aX += totalWidth; } while (aLength > 0) { PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength); nscoord width = 0; if (aSpacing) { for (PRInt32 i = 0; i < len; ++i) { width += aSpacing[i]; } } else { nsresult rv = GetWidthInternal(aString, len, width); if (NS_FAILED(rv)) return rv; } if (isRTL) { aX -= width; } nsresult rv = DrawStringInternal(aString, len, aX, aY, aFontID, aSpacing); if (NS_FAILED(rv)) return rv; aLength -= len; if (!isRTL) { aX += width; } aString += len; if (aSpacing) { aSpacing += len; } } return NS_OK; }
NS_IMETHODIMP nsThebesRenderingContext::GetTextDimensions(const char* aString, PRInt32 aLength, PRInt32 aAvailWidth, PRInt32* aBreaks, PRInt32 aNumBreaks, nsTextDimensions& aDimensions, PRInt32& aNumCharsFit, nsTextDimensions& aLastWordDimensions, PRInt32* aFontID) { PRUint32 maxChunkLength = GetMaxChunkLength(this); if (aLength <= PRInt32(maxChunkLength)) return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks, aNumBreaks, aDimensions, aNumCharsFit, aLastWordDimensions, aFontID); if (aFontID) { *aFontID = 0; } // Do a naive implementation based on 3-arg GetTextDimensions PRInt32 x = 0; PRInt32 wordCount; for (wordCount = 0; wordCount < aNumBreaks; ++wordCount) { PRInt32 lastBreak = wordCount > 0 ? aBreaks[wordCount - 1] : 0; nsTextDimensions dimensions; NS_ASSERTION(aBreaks[wordCount] > lastBreak, "Breaks must be monotonically increasing"); NS_ASSERTION(aBreaks[wordCount] <= aLength, "Breaks can't exceed string length"); // Call safe method nsresult rv = GetTextDimensions(aString + lastBreak, aBreaks[wordCount] - lastBreak, dimensions); if (NS_FAILED(rv)) return rv; x += dimensions.width; // The first word always "fits" if (x > aAvailWidth && wordCount > 0) break; // aDimensions ascent/descent should exclude the last word (unless there // is only one word) so we let it run one word behind if (wordCount == 0) { aDimensions = dimensions; } else { aDimensions.Combine(aLastWordDimensions); } aNumCharsFit = aBreaks[wordCount]; aLastWordDimensions = dimensions; } // aDimensions width should include all the text aDimensions.width = x; return NS_OK; }
nscoord nsRenderingContext::GetWidth(const PRUnichar *aString, PRUint32 aLength) { PRUint32 maxChunkLength = GetMaxChunkLength(); nscoord width = 0; while (aLength > 0) { PRInt32 len = FindSafeLength(aString, aLength, maxChunkLength); width += mFontMetrics->GetWidth(aString, len, this); aLength -= len; aString += len; } return width; }
nscoord nsRenderingContext::GetWidth(const char16_t *aString, uint32_t aLength) { uint32_t maxChunkLength = GetMaxChunkLength(); nscoord width = 0; while (aLength > 0) { int32_t len = FindSafeLength(aString, aLength, maxChunkLength); width += mFontMetrics->GetWidth(aString, len, this); aLength -= len; aString += len; } return width; }
void nsRenderingContext::DrawString(const char *aString, PRUint32 aLength, nscoord aX, nscoord aY) { PRUint32 maxChunkLength = GetMaxChunkLength(); while (aLength > 0) { PRInt32 len = FindSafeLength(aString, aLength, maxChunkLength); mFontMetrics->DrawString(aString, len, aX, aY, this); aLength -= len; if (aLength > 0) { nscoord width = mFontMetrics->GetWidth(aString, len, this); aX += width; aString += len; } } }
NS_IMETHODIMP nsThebesRenderingContext::DrawString(const char *aString, PRUint32 aLength, nscoord aX, nscoord aY, const nscoord* aSpacing) { PRUint32 maxChunkLength = GetMaxChunkLength(this); while (aLength > 0) { PRInt32 len = FindSafeLength(this, aString, aLength, maxChunkLength); nsresult rv = DrawStringInternal(aString, len, aX, aY); if (NS_FAILED(rv)) return rv; aLength -= len; if (aLength > 0) { nscoord width; rv = GetWidthInternal(aString, len, width); if (NS_FAILED(rv)) return rv; aX += width; aString += len; } } return NS_OK; }
nsBoundingMetrics nsRenderingContext::GetBoundingMetrics(const PRUnichar* aString, PRUint32 aLength) { PRUint32 maxChunkLength = GetMaxChunkLength(); PRInt32 len = FindSafeLength(aString, aLength, maxChunkLength); // Assign directly in the first iteration. This ensures that // negative ascent/descent can be returned and the left bearing // is properly initialized. nsBoundingMetrics totalMetrics = mFontMetrics->GetBoundingMetrics(aString, len, this); aLength -= len; aString += len; while (aLength > 0) { len = FindSafeLength(aString, aLength, maxChunkLength); nsBoundingMetrics metrics = mFontMetrics->GetBoundingMetrics(aString, len, this); totalMetrics += metrics; aLength -= len; aString += len; } return totalMetrics; }