Подтвердить что ты не робот

Линия UIBezierPath 1px и заполняет прямоугольник ширины 1px - разные результаты.

Вот простой рисунок

    

- (void)drawRect:(CGRect)rect
{
    //vertical line with 1 px stroking
    UIBezierPath *vertLine = [[UIBezierPath alloc] init];
    [vertLine moveToPoint:CGPointMake(20.0, 10.0)];
    [vertLine addLineToPoint:CGPointMake(20.0, 400.0)];
    vertLine.lineWidth = 1.0;
    [[UIColor blackColor] setStroke];
    [vertLine stroke];

    //vertical rectangle 1px width 
    UIBezierPath *vertRect= [UIBezierPath bezierPathWithRect:CGRectMake(40.0, 10.0, 1.0, 390.0)];
    [[UIColor blackColor] setFill];
    [vertRect fill];

}

На не сетчатке 3GS и симуляторе первая линия размыта и выглядит шире 1 px, но вторая строка четкая.

К сожалению, у меня нет ни iPhone4, ни нового iPad для тестирования, но на симуляторе сетчатки обе линии выглядят одинаково.

Вопрос. Является ли прямоугольник вместо инсульта единственным способом получить тот же результат для не сетчатых и сетчатых устройств?

4b9b3361

Ответ 1

Вы заполняете внутреннюю часть прямоугольника, но поглаживаете линию от центра. Поскольку координаты в обоих случаях (углы прямоугольника и начальные и конечные координаты в строке) определяются как значения целого числа (без дробей), координаты лежат на точных границах точки.

Я сказал "координаты" выше, когда говорил о точках линии, чтобы не путать их с точками на экране. Я также сказал "границы точек" вместо "границ пикселей" по той же причине. iOS определяет свои координаты и все точки в так называемых "точках" вместо пикселей. Точка - независимое от разрешения измерение. Оба устройства сетчатки и не сетчатки имеют одинаковое количество точек на экране, просто они соответствуют другому количеству фактических пикселей.

Посмотрим на поглаживание линии, лежащей на границах точек (например, в вашем вопросе), по сравнению с заполнением прямоугольника, где углы лежат на границах точек:

В приведенных ниже рисунках я глажу линию с черным и заполняя прямоугольник оранжевым цветом как на экране сетчатки, так и на сетчатке. Я также выделяю линию и прямоугольник синим цветом. В обоих случаях вы можете увидеть размер точки для этой резолюции и сравнить ее с реальной сеткой пикселей.

В случае, не относящемся к сетчатке, вы можете видеть, что попытка погладить линию из центра 1-точечной линией с (в данном случае соответствующей ширине линии 1 пиксель) заполнила бы половину пикселей сверху и половину на пикселях ниже. Поскольку пиксели заполнены только наполовину, непрозрачность для этих пикселей составляет 50%. Это приводит к более светлому цвету (на белом фоне). Так как пиксели сверху и снизу заполняются партиями, поглаживание заполняет как пиксели сверху, так и снизу. Это заставляет линию выглядеть так, как будто она имеет ширину в 2 пикселя вместо одной.

Вы можете быстро сравнить это с прямоугольником, который заполняется внутри.

non retina

Тот же самый случай на экране сетчатки выглядит иначе. В этом случае размер точки тот же, но он состоит из 4 пикселей вместо 1. На этот раз, поглаживая линию, половина точки над линией и половина точки ниже линии будет полностью заполнять ряд пикселей выше и ниже из-за экрана с более высоким разрешением. Это означает, что линия выглядит так, как будто она 1 точка ширины и что цвет выглядит полностью непрозрачным.

Мы также видим, что заполненный прямоугольник выглядит одинаково.

retina


Чтобы исправить это, вы бы поставили точки для своей линии на половину пикселей. Построение линии из центра на устройстве с низким разрешением означает, что линия простирается на половину точки вверх и на половину точки вниз. Так как центр линии теперь лежит в центре точки, это означает, что поглаженная линия полностью лежит в пикселях, и линия выглядит острой. Это не повлияет на линию сетчатки, так как перемещение вниз (или вверх) на половину точки, по-прежнему означает, что вы полностью заполняете пиксели выше и ниже.

На рисунке ниже (для сетчатки) я показал как сетку точек, так и сетку пикселей.

half pixel non-retinahalf pixel retina

Ответ 2

Причина, по которой вы получаете разные результаты с инсультом и заполнением, заключается в том, что их интерпретации аргументов различны.

Stroke добавляет половину ширины линии по каждой стороне координаты. Итак, ваша точка равна 20,0, а ширина линии - 1px. Результат будет иметь 1 пиксельную черную линию между (19.5-20.5), теоретически. Поскольку на экране устройства нет нецелого пикселя, он будет преобразован в 2 пикселя серой/размытой линии между (19-21). Чтобы обойти это, вам необходимо суммировать каждую из ваших координат с 0,5 (как в CGPointMake (20.5, 10.5)), чтобы ширина больше не делилась между пикселями.

Однако аргументы в заполнении используются для установки границ области для заполнения, CGRectMake (40.0, 10.0, 1.0, 390.0) подразумевает область между (40 - 41). В результате нет частичной части, падающей на пиксели, чтобы выглядеть размытым.