2010-02-01 9 views
1

У меня есть градиент, который имеет закругленные углы, которые я использую для пользовательского фона UITableViewCell. Я пытаюсь применить штрих к пути, но не могу это сделать, и не вижу, где я ошибаюсь.Применение штриха к закругленному прямоугольнику в ядре-графике

CGFloat minx = CGRectGetMinX(rect) , midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ; 
    CGFloat miny = CGRectGetMinY(rect) , maxy = CGRectGetMaxY(rect) ; 
    minx = minx + 1; 
    miny = miny ; 

    maxx = maxx - 1; 
    maxy = maxy - 1; 

    CGContextMoveToPoint(c, minx, miny); 
    CGContextAddArcToPoint(c, minx, maxy, midx, maxy, kDefaultMargin); 
    CGContextAddArcToPoint(c, maxx, maxy, maxx, miny, kDefaultMargin); 
    CGContextAddLineToPoint(c, maxx, miny); 
    CGContextAddLineToPoint(c, minx, miny); 

    // Fill and stroke the path 
    CGContextClip(c); 
    CGContextStrokePath(c); 

    CGFloat locations[2] = { 0.0, 1.0 }; 
    CGFloat mycomponents[8] = TABLE_CELL_BACKGROUND; 
    CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB(); 
    CGGradientRef myGradient = CGGradientCreateWithColorComponents(myColorspace, mycomponents, locations, 2); 
    CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0); 
    CGGradientRelease(myGradient); 
    CGColorSpaceRelease(myColorspace); 

Этот код округляет прямоугольник вправо и применяет градиент, но не перемещает строку. Где моя ошибка?

alt text http://grab.by/26Ye



EDIT: В соответствии с рекомендациями SubW, я изменил код, чтобы быть:

CGContextRef c = UIGraphicsGetCurrentContext(); 
    CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB(); 
    CGGradientRef myGradient = nil; 
    CGFloat components[8] = TABLE_CELL_BACKGROUND; 
    CGContextSetFillColorWithColor(c, [[UIColor redColor] CGColor]); 
    CGContextSetStrokeColorWithColor(c, [[UAColor redColor] CGColor]); 
    CGContextSetLineWidth(c, 2); 

    CGFloat minx = CGRectGetMinX(rect) , midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ; 
    CGFloat miny = CGRectGetMinY(rect) , maxy = CGRectGetMaxY(rect) ; 
    minx = minx + 1; 
    miny = miny ; 

    maxx = maxx - 1; 
    maxy = maxy - 1; 

    CGContextMoveToPoint(c, minx, miny); 
    CGContextAddArcToPoint(c, minx, maxy, midx, maxy, kDefaultMargin); 
    CGContextAddArcToPoint(c, maxx, maxy, maxx, miny, kDefaultMargin); 
    CGContextAddLineToPoint(c, maxx, miny); 
    CGContextAddLineToPoint(c, minx, miny); 

    // Fill and stroke the path 
    CGContextSaveGState(c); 
    CGContextClip(c); 

    CGFloat locations[2] = { 0.0, 1.0 }; 
    CGFloat mycomponents[8] = TABLE_CELL_BACKGROUND; 
    CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB(); 
    myGradient = CGGradientCreateWithColorComponents(myColorspace, mycomponents, locations, 2); 
    CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0); 

    CGContextRestoreGState(c); 
    CGContextStrokePath(c); 

Но Прямоугольник выходит, как это ...

alt text http://grab.by/2714

... без границ. Если я изменю CGContextStrokePath(c) на CGContextStrokeRect(c, rect), появится штрих (я сделал его красным для пояснения). Но как-то, когда поглаживая путь, я не получаю удар :(

alt text http://grab.by/27aM

ответ

5

В ответ на ваш пересмотренный кодекс, цитирую документацию:

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

После определения нового обтравочного контура функция сбрасывает текущий путь контекста на пустой путь.

- CGContextClip

Таким образом, текущий путь рисунок не часть графического состояния.Итак, вот что вы делаете:

  1. Построить чертеж путь
  2. Сохранить gstate
  3. Добавить текущий путь рисования в отсечения путь; ясного путь текущего рисунка
  4. Draw градиент
  5. Восстановления gstate (предыдущий путь обрезки восстанавливаются, рисунок пути остается пустым)
  6. Stroke ничего

Решения нарисовать путь в объект CGPath , затем добавьте его как текущий путь как перед обрезкой (после сохранения gstate), так и перед поглаживанием.

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

Если я изменю CGContextStrokePath(c) быть CGContextStrokeRect(c, rect), ход показывает вверх.

Поскольку эта функция добавляет путь этого прямоугольника к текущему пути рисования перед поглаживанием.

+0

Почему текущий путь очищается при настройке обтравочного контура? Документы для CGContextClip не упоминают об этом. – mrueg

+0

subw: Да, они делают. «После определения нового пути обрезки функция сбрасывает текущий путь контекста на пустой путь». Он делает это, потому что это делает PostScript (непосредственный предок PDF). –

+0

Имеет смысл. Я попробую это сегодня вечером – coneybeare

0

Не уверен, но, возможно, вы красите градиент над инсультом?

+0

Я так не думаю. Я рисую штрих после градиента в обновленном коде. – coneybeare

0

Вы или чертежу . градиент над инсультом, и/или отсечение области обводки

Я думаю, что следующее могут работать лучше:

CGContextSaveGState(c); 
CGContextClip(c); 

//gradient drawing stuff 

CGContextRestoreGState(c); 
CGContextStrokePath(c); 

Конечно, вы также должны правильно установить цвет и ширину хода.

+0

Я думал, что это сделает это, но это не так: http://grab.by/2714 – coneybeare

+0

Еще один вопрос: есть ли у вас вызов CGContextBeginPath (c) где-нибудь? Если нет, это может быть проблемой. – mrueg

+0

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