Re: border-image clarifications needed

Andrew Smith wrote:
> 
> Hello
> 
> I am implementing border-image in Mozilla. There are parts of the spec 
> which I don't understand. That may be because I'm clueless about style 
> sheets but it may also be because that the specification can use some 
> updating. I hope this is the right list to post on.
> 
> Regarding http://www.w3.org/TR/css3-background/#the-border-image

Ok, I've read the spec more carefully, and I think it's very clear in what it
says. I owe apologies to Bert and Dave Hyatt for speaking without doing my
research. :)

> 1) Of the three keywords (stretch, repeat, and round) only two are 
> explaned. If 'repeat' is explained somewhere else, a reference is needed.

Repeat is explained, it's just not mentioned explicitly in the algorithm.
If you follow through the algorithm in the case of 'repeat', you'll get the
spec author's intended result.

I'll step through it like we did on IRC so everyone else can follow.
For simplicity, let's just follow the top border region through the steps.
We have a 10*10 image tile, and the border region is 5px tall and 17px wide.

1. The spec says:
      "The two images for the top and bottom edges are made as tall as
      the top and bottom borders, respectively"

    We scale the height of our image tile down to 5px.

2. The spec says:
      "and their width is scaled proportionally."

    We scale the width of our image tile to 5px, restoring its original
    aspect ratio.

    * According to your image
        http://littlesvr.ca/border-image/safari-border-image-01.PNG
      Safari skips this step for 'repeat'.

    Note that this means the top, middle, and bottom borders will often have
    different widths; they won't tile together. We *could* change the spec
    so that the middle image stretches the same as at least one of the other
    border images: that would make all three match at least in the case where
    the top and bottom borders are the same width.

3-repeat. The spec doesn't mention 'repeat' in step 2, so we do nothing.

3-stretch. The spec says:
      "If the first keyword is 'stretch', the top, middle and bottom images
      are further scaled to be as wide as the element's padding box. The
      height is not changed any further."

    We scale the width of our image to 17px. The height remains at 5px.

3-round. The spec says:
      "If the first keyword is 'round', the top, middle and bottom images
      are reduced in width, so that exactly a whole number of them fit in
      the width of the padding box"

    If we don't scale the image, we can fit 17/5 = 3.4 tiles.
    We scale down the width of our image until a whole number can fit,
    i.e. ceil(17/5) = 4 tiles can fit. Our new width per image tile is
    17/4 = 4.25 px. (I hope this explains the use of the formula?)

    The CSS spec doesn't discuss how to round partial-pixel sizes.

    If we had a 400dpi screen resolution, we could render the tiles at
    4.25px by using 4*4.25 = 17 device pixels (see definition of 'px' in [1]).
    On a device where 1px = 1 device pixel, we'll have to fudge the
    partial-pixels by distributing extra pixels to some tiles and not to
    others. For our case this means one tile will be 5 pixels wide, and
    the others will be 4 pixels wide. All of them will be 5 pixels high.
    Ideally we'll distribute the wider tiles symmetrically rather than
    all on one side.

4. The spec says:
      "The resulting images are placed centered in their respective parts
      of the border and then tiled."

    So in all cases we take one tile, place it in the center of the top border,
    and then tile outwards. The goal with this was to keep the border
    symmetrical when a whole number of tiles didn't fit (which for repeat
    would be most of the time).

    * According to your image Safari does this correctly for 'round', but
      not for 'repeat'.

    However, for 'round', which is designed to force a whole number of tiles
    that fit, if we wind up with an *even* number of tiles, we end up with
    two partial tiles, as in the screenshot you posted. I consider this an
    error in the spec. If an even number of tiles would fit then the tiling
    should start at one end (or by placing the tile so its right or left
    edge is aligned with the center). That way we will not be splitting any
    tiles.

So changes I would suggest are:

  Replace:
   "The nine images are scaled in four steps"
  with
   "The nine images are scaled and tiled in three steps"

  Add as the third bullet point in step 2:
   "If the first keyword is 'repeat', the top, middle, and bottom images
   are not changed any further", to clarify that 'repeat' participates
   in this algorithm.

  Add after step 2, replacing the paragraph after it:
   "step 3
      * If the first keyword is 'round', the top, middle, and bottom images
        are placed at the left edge of their respective parts of the border
        (the middle image is put in the padding area). Otherwise the images
        centered horizontally in their respective areas.
      * If the second keyword is 'round', the left, middle, and right images
        are placed at the top edge of their respective parts of the border/
        padding area. Otherwise the images are centered vertically in their
        respective areas.
    step 4
      * The images are then tiled within their respective areas. All images
        are drawn behind the element's content, in front of the element's
        background."

Additionally, we may want to consider

  Remove the last bullet in step 2.

  Add to the end of the first bullet in step 1:
   "The width of the middle image is scaled by the same factor as the top
   image unless that factor is zero or infinity, in which case the scaling
   factor of the bottom image may be substituted, and failing that, 1."

  Add to the end of the second bullet in step 1:
   "The width of the middle image is scaled by the same factor as the top
   image unless that factor is zero or infinity, in which case the scaling
   factor of the bottom image may be substituted, and failing that, 1."

> 4) "If the first keyword is 'round', the top, middle and bottom images 
> are reduced in width, so that exactly a whole number of them fit in the 
> width of the padding box" - if the width of the padding box is a prime 
> number the only way to fit a whole number of images in it is to have 
> them sized to 1 or to the width of the padding area. Should clarify this.

The requirement is a whole number of tiles, not a whole number of pixels.

> 5) "X' = W / ceil(W / X)" - this doesn't give me a whole number, is it 
> supposed to? If not, what am I to do with this formula? If it does make 
> sense, a reference to where this is explained would help a lot.

No. See above, let me know if it still doesn't make sense.

> 6) If the width of two consecutive sides isn't the same, what's done to 
> the corner? There are at least three different ways to deal with it. 
> Should clarify this.

Each dimension is stretched independently.

[1] http://www.w3.org/TR/CSS21/syndata.html#length-units

~fantasai

Received on Thursday, 14 June 2007 15:03:56 UTC