2012-06-24 16 views
21

Aquí es un simple dibujoUIBezierPath trazo 1px línea y relleno 1px ancho rectángulo - resultados diferentes.

 

- (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 retina no 3GS y el simulador de la primera línea es borrosa y se ve más ancha de 1 px, pero la segunda línea es nítido.

Lamentablemente no tengo ni 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?

Respuesta

51

Usted está llenando el interior del rectángulo pero está 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 puntos exactos.

Dije "coordenadas" arriba cuando hablo sobre 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 medida independiente de la resolución. Los dispositivos retina y no retina tienen el mismo número de puntos en la pantalla, solo que corresponden a un número diferente de píxeles reales. mirada

Vamos a acariciar una línea que se encuentran en los límites de punto (como en su pregunta) en comparación con el llenado de un rectángulo donde las esquinas se encuentran en los los límites de punto:

En las siguientes ilustraciones estoy acariciando una línea con negro y llenando un rectángulo con naranja tanto en una pantalla que no retina como en una 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 sin retina, puede ver que tratando de trazar la línea desde el centro con una línea de 1 punto (en este caso corresponde 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 de los píxeles a continuación. Como los píxeles están solo medio llenos, la opacidad de esos píxeles es del 50%. Esto da como resultado un color más claro (sobre un fondo blanco). Debido a que tanto los píxeles en la parte superior como en la inferior están llenos de fiesta, acariciando los rellenos tanto los píxeles en la parte superior como en la inferior. Esto hace que la línea parezca tener 2 píxeles de ancho en lugar de uno.

Puede comparar rápidamente eso con el rectángulo que está lleno en el interior.

non retina

El mismo caso en una pantalla de la 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 acariciar 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 que tiene 1 punto de ancho y que el color se ve completamente opaco.

También podemos ver que el rectángulo lleno tiene el mismo aspecto.

retina


Para solucionar esto, se pondría a los puntos de la línea en la mitad de píxeles.Acariciar 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 acariciada 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 al moverse hacia abajo (o hacia arriba) medio punto, significa que usted llena completamente los píxeles arriba y abajo.

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

half pixel non-retina half pixel retina

2

La razón se obtienen diferentes resultados con trazo y de relleno es que sus interpretaciones de los argumentos es diferente.

El 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 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 integrado en la pantalla del dispositivo, se convertirá en 2 píxeles gris/línea borrosa entre (19-21). para eludir esto, debe sumar cada una de sus coordenadas con 0.5 (como en CGPointMake (20.5, 10.5)) para que el ancho no se divida entre píxeles por más tiempo.

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

Cuestiones relacionadas