ios drawing uibezierpath

ios - UIBezierPath traza una línea de 1px y llena un rectángulo de ancho de 1px-resultados diferentes.



drawing (2)

Aquí hay un dibujo simple.

- (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]; }

En la no retina 3GS y en el simulador, la primera línea es borrosa y parece más ancha que 1 px, pero la segunda línea es nítida.

Desafortunadamente, no tengo iPhone4 ni el nuevo iPad para probar, pero en el simulador de retina ambas líneas tienen el mismo aspecto.

Pregunta: ¿Es el rectángulo en lugar del trazo la única forma de obtener el mismo resultado para los dispositivos sin retina y retina?


Estás llenando el interior del rectángulo pero estás acariciando la línea desde el centro. Dado que las coordenadas en ambos casos (las esquinas del rectángulo y las coordenadas de inicio y final en la línea) se definen como valores de números enteros (sin fracciones), las coordenadas se encuentran en los límites de los puntos exactos.

Dije "coordenadas" arriba cuando se habla de los puntos de la línea, para no confundirlos con los puntos en la pantalla. También dije "límites de puntos" en lugar de "límites de píxeles" por la misma razón. iOS define sus coordenadas y todos los puntos en lo que se llama "puntos" en lugar de píxeles. Un punto es una resolución de medida independiente. Tanto el dispositivo de retina como el de no retina tienen el mismo número de puntos en la pantalla, es solo que corresponden a un número diferente de píxeles reales.

Observemos cómo trazar una línea que se encuentra en los límites de los puntos (como en tu pregunta) en comparación con el relleno de un rectángulo donde se encuentran las esquinas en los límites de los puntos:

En las siguientes ilustraciones, estoy trazando una línea con negro y rellenando un rectángulo con naranja tanto en una pantalla sin retina como en una pantalla de retina. También he delineado la línea y el rectángulo con azul. En ambos casos, puede ver el tamaño de un punto para esa resolución y compararlo con la cuadrícula de píxeles real.

En el caso de no retina, puede ver que tratar de trazar la línea desde el centro con una línea de 1 punto con (en este caso correspondiente a un ancho de línea de 1 píxel) llenaría la mitad de los píxeles en la parte superior y la mitad en los píxeles abajo. Dado que los píxeles están rellenos hasta la mitad, la opacidad de esos píxeles es del 50%. Esto resulta en el color más claro (sobre un fondo blanco). Dado que los píxeles en la parte superior y en la parte inferior están llenos de parte, al tocarlos se rellenan los píxeles en la parte superior e inferior. Esto hace que la línea se vea como si tuviera 2 píxeles de ancho en lugar de uno.

Puede compararlo rápidamente con el rectángulo que está relleno en el interior.

El mismo caso en una pantalla de retina se ve diferente. En este caso, el tamaño de un punto es el mismo pero consta de 4 píxeles en lugar de 1. Esta vez, al trazar la línea, medio punto por encima de la línea y medio punto por debajo de la línea llenará completamente la fila de píxeles. arriba y abajo debido a la pantalla de mayor resolución. Esto significa que la línea parece tener un ancho de 1 punto y que el color se ve completamente opaco.

También podemos ver que el rectángulo relleno se ve igual.

Para solucionar esto, pondría los puntos de su línea en medio píxeles. Trazar la línea desde el centro en un dispositivo de baja resolución significa que la línea se extiende medio punto hacia arriba y medio punto hacia abajo. Dado que el centro de la línea ahora se encuentra en el centro del punto, esto significa que la línea trazada se encuentra completamente dentro de los píxeles y la línea se ve nítida. Hacer esto no tendrá ningún efecto en la línea de la retina, ya que si se mueve hacia abajo (o hacia arriba) la mitad de un punto, significa que usted llena completamente los píxeles de arriba y abajo.

En la siguiente ilustración (para la retina), he mostrado tanto la cuadrícula de puntos como la cuadrícula de píxeles.


La razón por la que obtiene diferentes resultados con el trazo y el relleno es que sus interpretaciones de los argumentos son diferentes.

Trazo agrega la mitad del ancho de la línea a cada lado de la coordenada. Entonces, tu punto es 20.0 y el ancho de la línea es 1px. El resultado será una línea negra de 1 píxel entre (19.5-20.5), teóricamente. Como no hay ningún píxel no integral en la pantalla del dispositivo, se convertirá en una línea borrosa / gris de 2 píxeles entre (19-21). para evitar esto, debe sumar cada una de sus coordenadas con 0.5 (como en CGPointMake (20.5, 10.5)) para que el ancho ya no se divida entre los píxeles.

Sin embargo, los argumentos en el relleno se utilizan para establecer los bordes de la región a rellenar, CGRectMake (40.0, 10.0, 1.0, 390.0) implica una región entre (40 - 41). Como resultado, no hay ninguna parte fraccionaria que caiga sobre los píxeles para que se vea borrosa.