Применение обводки к скругленному прямоугольнику в core-graphics - PullRequest
1 голос
/ 01 февраля 2010

У меня есть градиент с закругленными углами, который я использую для пользовательского фона 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);

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

альтернативный текст 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);

Но прямоугольник получается вот так ...

альтернативный текст http://grab.by/2714

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

альтернативный текст http://grab.by/27aM

Ответы [ 3 ]

5 голосов
/ 01 февраля 2010

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

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

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

CGContextClip

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

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

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

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

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

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

0 голосов
/ 01 февраля 2010

Вы либо рисуете градиент по обводке, и / или обрезаете область, которую обводите.

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

CGContextSaveGState(c);
CGContextClip(c);

//gradient drawing stuff

CGContextRestoreGState(c);
CGContextStrokePath(c);

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

0 голосов
/ 01 февраля 2010

Не уверен, но, может быть, вы рисуете градиент по штриху?

...