Bug 839957 - Avoid inaccuracies when computing SVG glyph positions. r=longsonr
authorCameron McCormack <cam@mcc.id.au>
Wed, 10 Apr 2013 22:58:55 +1000
changeset 128316 dffb1a1c78737b1e9da04d9abab81030f389a5fd
parent 128315 a3bdc9a0259fe7a3dacf8ba64c4e0bf8daed11ff
child 128317 0ff1755d6359bfbbb9585d7a041c57adfb06a6c7
push idunknown
push userunknown
push dateunknown
reviewerslongsonr
bugs839957
milestone23.0a1
Bug 839957 - Avoid inaccuracies when computing SVG glyph positions. r=longsonr
layout/svg/nsSVGTextFrame2.cpp
--- a/layout/svg/nsSVGTextFrame2.cpp
+++ b/layout/svg/nsSVGTextFrame2.cpp
@@ -4149,32 +4149,27 @@ nsSVGTextFrame2::ResolvePositions(nsTArr
 
 void
 nsSVGTextFrame2::DetermineCharPositions(nsTArray<nsPoint>& aPositions)
 {
   NS_ASSERTION(aPositions.IsEmpty(), "expected aPositions to be empty");
 
   nsPoint position, lastPosition;
 
-  float cssPxPerDevPx = PresContext()->
-    AppUnitsToFloatCSSPixels(PresContext()->AppUnitsPerDevPixel());
-
   TextFrameIterator frit(this);
   for (nsTextFrame* frame = frit.Current(); frame; frame = frit.Next()) {
     gfxSkipCharsIterator it = frame->EnsureTextRun(nsTextFrame::eInflated);
     gfxTextRun* textRun = frame->GetTextRun(nsTextFrame::eInflated);
 
     // Reset the position to the new frame's position.
     position = frit.Position();
     if (textRun->IsRightToLeft()) {
       position.x += frame->GetRect().width;
     }
     position.y += GetBaselinePosition(frame, textRun, frit.DominantBaseline());
-    position = nsPoint(nscoord(position.x * cssPxPerDevPx),
-                       nscoord(position.y * cssPxPerDevPx));
 
     // Any characters not in a frame, e.g. when display:none.
     for (uint32_t i = 0; i < frit.UndisplayedCharacters(); i++) {
       aPositions.AppendElement(position);
     }
 
     // Any white space characters trimmed at the start of the line of text.
     nsTextFrame::TrimmedOffsets trimmedOffsets =
@@ -4185,35 +4180,33 @@ nsSVGTextFrame2::DetermineCharPositions(
     }
 
     // If a ligature was started in the previous frame, we should record
     // the ligature's start position, not any partial position.
     while (it.GetOriginalOffset() < frame->GetContentEnd() &&
            !it.IsOriginalCharSkipped() &&
            (!textRun->IsLigatureGroupStart(it.GetSkippedOffset()) ||
             !textRun->IsClusterStart(it.GetSkippedOffset()))) {
-      gfxFloat advance =
-        textRun->GetAdvanceWidth(it.GetSkippedOffset(), 1,
-                                 nullptr) * cssPxPerDevPx;
+      nscoord advance = textRun->GetAdvanceWidth(it.GetSkippedOffset(), 1,
+                                                 nullptr);
       position.x += textRun->IsRightToLeft() ? -advance : advance;
       aPositions.AppendElement(lastPosition);
       it.AdvanceOriginal(1);
     }
 
     // The meat of the text frame.
     while (it.GetOriginalOffset() < frame->GetContentEnd()) {
       aPositions.AppendElement(position);
       if (!it.IsOriginalCharSkipped() &&
           textRun->IsLigatureGroupStart(it.GetSkippedOffset()) &&
           textRun->IsClusterStart(it.GetSkippedOffset())) {
         // A real visible character.
         uint32_t length = ClusterLength(textRun, it);
-        gfxFloat advance =
-          textRun->GetAdvanceWidth(it.GetSkippedOffset(), length,
-                                   nullptr) * cssPxPerDevPx;
+        nscoord advance = textRun->GetAdvanceWidth(it.GetSkippedOffset(),
+                                                   length, nullptr);
         position.x += textRun->IsRightToLeft() ? -advance : advance;
         lastPosition = position;
       }
       it.AdvanceOriginal(1);
     }
   }
 
   // Finally any characters at the end that are not in a frame.
@@ -4593,35 +4586,38 @@ nsSVGTextFrame2::DoGlyphPositioning()
   }
   if (!mPositions[0].IsYSpecified()) {
     mPositions[0].mPosition.y = 0.0;
   }
   if (!mPositions[0].IsAngleSpecified()) {
     mPositions[0].mAngle = 0.0;
   }
 
+  float cssPxPerDevPx = PresContext()->
+    AppUnitsToFloatCSSPixels(PresContext()->AppUnitsPerDevPixel());
+
   // Fill in any unspecified character positions based on the positions recorded
   // in charPositions, and also add in the dx/dy values.
   if (!deltas.IsEmpty()) {
     mPositions[0].mPosition += deltas[0];
   }
   for (uint32_t i = 1; i < mPositions.Length(); i++) {
     // Fill in unspecified x position.
     if (!mPositions[i].IsXSpecified()) {
       nscoord d = charPositions[i].x - charPositions[i - 1].x;
       mPositions[i].mPosition.x =
         mPositions[i - 1].mPosition.x +
-        presContext->AppUnitsToGfxUnits(d) / mFontSizeScaleFactor;
+        presContext->AppUnitsToGfxUnits(d) * cssPxPerDevPx / mFontSizeScaleFactor;
     }
     // Fill in unspecified y position.
     if (!mPositions[i].IsYSpecified()) {
       nscoord d = charPositions[i].y - charPositions[i - 1].y;
       mPositions[i].mPosition.y =
         mPositions[i - 1].mPosition.y +
-        presContext->AppUnitsToGfxUnits(d) / mFontSizeScaleFactor;
+        presContext->AppUnitsToGfxUnits(d) * cssPxPerDevPx / mFontSizeScaleFactor;
     }
     // Add in dx/dy.
     if (i < deltas.Length()) {
       mPositions[i].mPosition += deltas[i];
     }
     // Fill in unspecified rotation values.
     if (!mPositions[i].IsAngleSpecified()) {
       mPositions[i].mAngle = mPositions[i - 1].mAngle;
@@ -4637,19 +4633,19 @@ nsSVGTextFrame2::DoGlyphPositioning()
   //
   // XXX This may not be needed since ResolvePositions now initializes
   // mPositions with an (unspecified) value for each character.
   for (uint32_t i = mPositions.Length(); i < charPositions.Length(); i++) {
     nscoord dx = charPositions[i].x - charPositions[i - 1].x;
     nscoord dy = charPositions[i].y - charPositions[i - 1].y;
 
     gfxPoint pt(mPositions[i - 1].mPosition.x +
-                  presContext->AppUnitsToGfxUnits(dx),
+                  presContext->AppUnitsToGfxUnits(dx) * cssPxPerDevPx,
                 mPositions[i - 1].mPosition.y +
-                  presContext->AppUnitsToGfxUnits(dy));
+                  presContext->AppUnitsToGfxUnits(dy) * cssPxPerDevPx);
 
     mPositions.AppendElement(CharPosition(pt / mFontSizeScaleFactor,
                                           mPositions[i - 1].mAngle));
     if (i < deltas.Length()) {
       mPositions[i].mPosition += deltas[i];
     }
   }