Karl Dubost: How CSS width is computed in Gecko? |
Yesterday, I have written about the strange value of the CSS width when set with a percentage. One Japanese night later, Boris Zbarsky sent me a private email explaining how CSS widths are computed in Gecko. These short emails are a gem of pleasure to read and insights into Gecko. I should almost open a new category here called "Santa Boris". I love them. Thanks.
So what did I learn with Boris? Here an extended version of Boris' email with C++ code. (I'm out of my comfort zone so if you see glaring mistakes, tell me I will happily fix them.)
In yesterday's article, the following CSS rule was applied on the child of a 360px
parent element.
.foo { width: 49.99999%; border-right: 1px solid #CCC; }
In Boris' words:
Gecko doesn't store CSS stuff as floating-point numbers. It stores them as integers, with the unit being 1/60 of a px (so that common fractions like 1/2, 1/3, 1/4, 1/5 are exactly representable).
Or said it another way 1 px = 60 (in Gecko). The 60 constant is defined in AppUnits.h (Brian Birtles helped me find it).
inline int32_t AppUnitsPerCSSPixel() { return 60; }
which in return is called a lot in Units.h.
Specifically in ToAppUnits()
static nsRect ToAppUnits(const CSSRect& aRect) { return nsRect(NSToCoordRoundWithClamp(aRect.x * float(AppUnitsPerCSSPixel())), NSToCoordRoundWithClamp(aRect.y * float(AppUnitsPerCSSPixel())), NSToCoordRoundWithClamp(aRect.width * float(AppUnitsPerCSSPixel())), NSToCoordRoundWithClamp(aRect.height * float(AppUnitsPerCSSPixel()))); }
Let's continue with Boris' explanation broken down in steps. So instead of 360 px, we have an integer which is 360
but as you can see above when computing the values, it uses a function NSToCoordRoundWithClamp()
.
inline nscoord NSToCoordRoundWithClamp(float aValue) { /* cut for clarity */ return NSToCoordRound(aValue); }
And it goes to a rounding function.
The return trip is similar with FromAppUnits()
static CSSIntRect FromAppUnitsRounded(const nsRect& aRect) { return CSSIntRect(NSAppUnitsToIntPixels(aRect.x, float(AppUnitsPerCSSPixel())), NSAppUnitsToIntPixels(aRect.y, float(AppUnitsPerCSSPixel())), NSAppUnitsToIntPixels(aRect.width, float(AppUnitsPerCSSPixel())), NSAppUnitsToIntPixels(aRect.height, float(AppUnitsPerCSSPixel()))); }
where
inline int32_t NSAppUnitsToIntPixels(nscoord aAppUnits, float aAppUnitsPerPixel) { return NSToIntRound(float(aAppUnits) / aAppUnitsPerPixel); /* NSToIntRound(*/ }
which calls NStoIntRound()
inline int32_t NSToIntRound(float aValue) { return NS_lroundf(aValue); }
which calls NS_lroundf()
inline int32_t NS_lroundf(float aNum) { return aNum >= 0.0f ? int32_t(aNum + 0.5f) : int32_t(aNum - 0.5f); }
(My C++ Kung-Fu (
Комментировать | « Пред. запись — К дневнику — След. запись » | Страницы: [1] [Новые] |