-Поиск по дневнику

Поиск сообщений в rss_planet_mozilla

 -Подписка по e-mail

 

 -Постоянные читатели

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 19.06.2007
Записей:
Комментариев:
Написано: 7


Karl Dubost: How CSS width is computed in Gecko?

Четверг, 26 Мая 2016 г. 09:22 + в цитатник

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.)

Yesterday's Summary

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;
}
  • The 49.99999 % of 360 px in Gecko
  • is not 179.999964 px (as you could mathematically expect)
  • but 179.98333740234375 px (rounded to 179.983 px in the devtools UI).

Gecko storage of CSS

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

  1. 49.99999% * 360
  2. 0.4999999 * (360 * 60)
  3. 0.4999999 * 21600
  4. 10799.99784

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 (

http://www.otsukare.info/2016/05/26/css-width-gecko


 

Добавить комментарий:
Текст комментария: смайлики

Проверка орфографии: (найти ошибки)

Прикрепить картинку:

 Переводить URL в ссылку
 Подписаться на комментарии
 Подписать картинку