Я устанавливаю .contents CALayer в CGImage, полученный от рисования в NSBitMapImageRep.Как можно уменьшить края изображения CALayer при растяжении во время изменения размера?
Насколько я понимаю из документов docs и WWDC, устанавливая объект .contentsCenter слоя на NSRect, например {{0.5, 0.5}, {0, 0}}, в сочетании с .contentsGravity kCAGravityResize должен привести к Core Animation изменяет размер слоя, растягивая средний пиксель, верхний и нижний горизонтально, а стороны вертикально.
Это почти работает, но не совсем. Слой изменяется более или менее правильно, но если я рисую линии на краю растрового изображения, то при изменении размера окна можно увидеть, что линии очень незначительно колеблются. Это достаточно тонко, чтобы быть едва ли проблемой, пока изменение размера не уменьшится примерно до 1/4 от размера исходного слоя, ниже того, что линии могут быть тонкие и полностью исчезнуть. Если я рисую растровые изображения несколько раз при разных размерах, небольшие различия в толщине линии очень очевидны.
Первоначально я искал проблему выравнивания пикселей, но это не может быть так, потому что толщина неподвижного края LH (например) будет колебаться при изменении размера края RH. Это происходит на экранах 1x и 2x.
Вот несколько тестовых кодов. Это метод updateLayer из слоя спинками NSView подкласса (я использую альтернативный, не DrawRect рисовать путь):
- (void)updateLayer {
id image = [self imageForCurrentScaleFactor]; // CGImage
self.layer.contents = image;
// self.backingScaleFactor is set from the window's backingScaleFactor
self.layer.contentsScale = self.backingScaleFactor;
self.layer.contentsCenter = NSMakeRect(0.5, 0.5, 0, 0);
self.layer.contentsGravity = kCAGravityResize;
}
А вот некоторые тест рисунок кода (создание изображения, поступающего от imageForCurrentScaleFactor выше):
CGFloat width = rect.size.width;
CGFloat height = rect.size.height;
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
pixelsWide: width * scaleFactor
pixelsHigh: height * scaleFactor
bitsPerSample: 8
samplesPerPixel: 4
hasAlpha: YES
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bytesPerRow: 0
bitsPerPixel: 0];
[imageRep setSize:rect.size];
[NSGraphicsContext saveGraphicsState];
NSGraphicsContext *ctx = [NSGraphicsContext graphicsContextWithBitmapImageRep:imageRep];
[NSGraphicsContext setCurrentContext:ctx];
[[NSColor whiteColor] setFill];
[NSBezierPath fillRect:rect];
[[NSColor blackColor] setStroke];
[NSBezierPath setDefaultLineWidth:1.0f];
[NSBezierPath strokeRect:insetRect];
[NSGraphicsContext restoreGraphicsState];
// image for CALayer.contents is now [imageRep CGImage]
Я могу принять свой собственный ответ, поскольку он решает проблему. Но я до сих пор не понимаю, почему сохранение растрового прямоугольника малого размера имеет такое значение. Создание содержимогоЦентр 1 пиксель (т. Е. 0,5, 0,5, 0, 0) должен помешать вытянутым линиям вверху вертикально (или по сторонам, растянутым горизонтально), независимо от размера прямоугольника. Я приму ответ с убедительным объяснением этого. – Cris