From 8eda60256e256e6c0de96b0d74535480bacf6178 Mon Sep 17 00:00:00 2001 From: Brad Werth Date: Mon, 30 Apr 2018 17:01:24 -0700 Subject: [PATCH] Bug 1457602 Part 1: Correct shape-outside: image shape-margin calculation for vertical writing modes. r=jfkthame MozReview-Commit-ID: ChUL66vUkHu --HG-- extra : rebase_source : beadd474d6022b1f8672c39cb841da8590ffde51 --- layout/generic/nsFloatManager.cpp | 185 +++++++++++++++++++++--------- 1 file changed, 131 insertions(+), 54 deletions(-) diff --git a/layout/generic/nsFloatManager.cpp b/layout/generic/nsFloatManager.cpp index 47cbf50c43df..1488adc10832 100644 --- a/layout/generic/nsFloatManager.cpp +++ b/layout/generic/nsFloatManager.cpp @@ -2005,35 +2005,73 @@ nsFloatManager::ImageShapeInfo::ImageShapeInfo( df[index] = 0; } else { // Case 3: Other pixel. + if (aWM.IsVertical()) { + // Column-by-column, starting at the left, each column + // top-to-bottom. + // Backward-looking neighborhood distance from target pixel X + // with chamfer 5-7-11 looks like: + // + // +--+--+--+ + // | |11| | | + + // +--+--+--+ | /| + // |11| 7| 5| | / | + // +--+--+--+ | / V + // | | 5| X| |/ + // +--+--+--+ + + // |11| 7| | + // +--+--+--+ + // | |11| | + // +--+--+--+ + // + // X should be set to the minimum of MAX_MARGIN_5X and the + // values of all of the numbered neighbors summed with the + // value in that chamfer cell. + MOZ_ASSERT(index - wEx - 2 < (iSize * bSize) && + index + wEx - 2 < (iSize * bSize) && + index - (wEx * 2) - 1 < (iSize * bSize), + "Our distance field most extreme indices should be " + "in-bounds."); - // Backward-looking neighborhood distance from target pixel X - // with chamfer 5-7-11 looks like: - // - // +--+--+--+--+--+ - // | |11| |11| | - // +--+--+--+--+--+ - // |11| 7| 5| 7|11| - // +--+--+--+--+--+ - // | | 5| X| | | - // +--+--+--+--+--+ - // - // X should be set to the minimum of MAX_MARGIN_5X and the - // values of all of the numbered neighbors summed with the - // value in that chamfer cell. - MOZ_ASSERT(index - (wEx * 2) - 1 < (iSize * bSize) && - index - wEx - 2 < (iSize * bSize), - "Our distance field most extreme indices should be " - "in-bounds."); + df[index] = std::min(MAX_MARGIN_5X, + std::min(df[index - wEx - 2] + 11, + std::min(df[index + wEx - 2] + 11, + std::min(df[index - (wEx * 2) - 1] + 11, + std::min(df[index - wEx - 1] + 7, + std::min(df[index - 1] + 5, + std::min(df[index + wEx - 1] + 7, + std::min(df[index + (wEx * 2) - 1] + 11, + df[index - wEx] + 5)))))))); + } else { + // Row-by-row, starting at the top, each row left-to-right. + // Backward-looking neighborhood distance from target pixel X + // with chamfer 5-7-11 looks like: + // + // +--+--+--+--+--+ + // | |11| |11| | ----+ + // +--+--+--+--+--+ / + // |11| 7| 5| 7|11| / + // +--+--+--+--+--+ / + // | | 5| X| | | +--> + // +--+--+--+--+--+ + // + // X should be set to the minimum of MAX_MARGIN_5X and the + // values of all of the numbered neighbors summed with the + // value in that chamfer cell. + MOZ_ASSERT(index - (wEx * 2) - 1 < (iSize * bSize) && + index - wEx - 2 < (iSize * bSize), + "Our distance field most extreme indices should be " + "in-bounds."); - df[index] = std::min(MAX_MARGIN_5X, - std::min(df[index - (wEx * 2) - 1] + 11, - std::min(df[index - (wEx * 2) + 1] + 11, - std::min(df[index - wEx - 2] + 11, - std::min(df[index - wEx - 1] + 7, - std::min(df[index - wEx] + 5, - std::min(df[index - wEx + 1] + 7, - std::min(df[index - wEx + 2] + 11, - df[index - 1] + 5)))))))); + df[index] = std::min(MAX_MARGIN_5X, + std::min(df[index - (wEx * 2) - 1] + 11, + std::min(df[index - (wEx * 2) + 1] + 11, + std::min(df[index - wEx - 2] + 11, + std::min(df[index - wEx - 1] + 7, + std::min(df[index - wEx] + 5, + std::min(df[index - wEx + 1] + 7, + std::min(df[index - wEx + 2] + 11, + df[index - 1] + 5)))))))); + } } } } @@ -2078,34 +2116,73 @@ nsFloatManager::ImageShapeInfo::ImageShapeInfo( // Only apply the chamfer calculation if the df value is not // already 0, since the chamfer can only reduce the value. if (df[index]) { - // Forward-looking neighborhood distance from target pixel X - // with chamfer 5-7-11 looks like: - // - // +--+--+--+--+--+ - // | | | X| 5| | - // +--+--+--+--+--+ - // |11| 7| 5| 7|11| - // +--+--+--+--+--+ - // | |11| |11| | - // +--+--+--+--+--+ - // - // X should be set to the minimum of its current value and - // the values of all of the numbered neighbors summed with - // the value in that chamfer cell. - MOZ_ASSERT(index + (wEx * 2) + 1 < (wEx * hEx) && - index + wEx + 2 < (wEx * hEx), - "Our distance field most extreme indices should be " - "in-bounds."); + if (aWM.IsVertical()) { + // Column-by-column, starting at the right, each column + // bottom-to-top. + // Forward-looking neighborhood distance from target pixel X + // with chamfer 5-7-11 looks like: + // + // +--+--+--+ + // | |11| | + + // +--+--+--+ /| + // | | 7|11| A / | + // +--+--+--+ | / | + // | X| 5| | |/ | + // +--+--+--+ + | + // | 5| 7|11| + // +--+--+--+ + // | |11| | + // +--+--+--+ + // + // X should be set to the minimum of its current value and + // the values of all of the numbered neighbors summed with + // the value in that chamfer cell. + MOZ_ASSERT(index + wEx + 2 < (wEx * hEx) && + index + (wEx * 2) + 1 < (wEx * hEx) && + index - (wEx * 2) + 1 < (wEx * hEx), + "Our distance field most extreme indices should be " + "in-bounds."); - df[index] = std::min(df[index], - std::min(df[index + (wEx * 2) + 1] + 11, - std::min(df[index + (wEx * 2) - 1] + 11, - std::min(df[index + wEx + 2] + 11, - std::min(df[index + wEx + 1] + 7, - std::min(df[index + wEx] + 5, - std::min(df[index + wEx - 1] + 7, - std::min(df[index + wEx - 2] + 11, - df[index + 1] + 5)))))))); + df[index] = std::min(df[index], + std::min(df[index + wEx + 2] + 11, + std::min(df[index - wEx + 2] + 11, + std::min(df[index + (wEx * 2) + 1] + 11, + std::min(df[index + wEx + 1] + 7, + std::min(df[index + 1] + 5, + std::min(df[index - wEx + 1] + 7, + std::min(df[index - (wEx * 2) + 1] + 11, + df[index + wEx] + 5)))))))); + } else { + // Row-by-row, starting at the bottom, each row right-to-left. + // Forward-looking neighborhood distance from target pixel X + // with chamfer 5-7-11 looks like: + // + // +--+--+--+--+--+ + // | | | X| 5| | <--+ + // +--+--+--+--+--+ / + // |11| 7| 5| 7|11| / + // +--+--+--+--+--+ / + // | |11| |11| | +---- + // +--+--+--+--+--+ + // + // X should be set to the minimum of its current value and + // the values of all of the numbered neighbors summed with + // the value in that chamfer cell. + MOZ_ASSERT(index + (wEx * 2) + 1 < (wEx * hEx) && + index + wEx + 2 < (wEx * hEx), + "Our distance field most extreme indices should be " + "in-bounds."); + + df[index] = std::min(df[index], + std::min(df[index + (wEx * 2) + 1] + 11, + std::min(df[index + (wEx * 2) - 1] + 11, + std::min(df[index + wEx + 2] + 11, + std::min(df[index + wEx + 1] + 7, + std::min(df[index + wEx] + 5, + std::min(df[index + wEx - 1] + 7, + std::min(df[index + wEx - 2] + 11, + df[index + 1] + 5)))))))); + } } // Finally, we can check the df value and see if it's less than