Как заполнить дорожку узором в кварце
Я создал вид и в своем методе рисования прямоугольника я создаю пути в зависимости от того, что пользователь делает с ползунками. Используя стандартные цвета, все работает и выглядит очень красиво. Я пытаюсь следовать фрагменту кода от Apple, который показывает, как рисовать шаблоны в прямоугольнике по этой ссылке: Apple Drawing Guide
В примере показано, как создать обратный вызов функции с желаемым шаблоном, а затем дополнительный вызов метода для рисования прямоугольника. Если я вызову код, как он написан из моего прямоугольника, он нарисует мой шаблон так, как я и ожидал, однако я не хочу заполнять мой прямоугольник, я хочу заполнить указанный путь в прямоугольнике. Если я изменю вызов в методе рисования с CGContextFillRect на CGContextFillPath, он не будет работать. Я уверен, что есть что-то, что я упускаю, чтобы изменить этот код, чтобы заставить его делать то, что я хочу.
Мой шаблон обратного вызова - простая шахматная доска:
код:
// Call Back function for Graphics Pattern
#define PATTERN_SIZE 10
void patternSpec(void *info , CGContextRef pContext){
NSLog(@"patternSpec Callback Called");
CGFloat subUnit = PATTERN_SIZE / 2;
CGRect square1 = {{0,0}, {subUnit, subUnit}},
square2 = {{subUnit, subUnit}, {subUnit, subUnit}},
square3 = {{0 , subUnit}, {subUnit, subUnit}},
square4 = {{subUnit , 0}, {subUnit, subUnit}};
CGContextSetRGBFillColor(pContext, 1.0, 0.0, 0.0, 1.0 );
CGContextFillRect(pContext, square1);
CGContextSetRGBFillColor(pContext, 1.0, 0.0, 0.0, 1.0 );
CGContextFillRect(pContext, square2);
CGContextSetRGBFillColor(pContext, 0.0, 0.0, 0.0, 1.0 );
CGContextFillRect(pContext, square3);
CGContextSetRGBFillColor(pContext, 0.0, 0.0, 0.0, 1.0 );
CGContextFillRect(pContext, square4);
}
// Method that draws the pattern
static void drawPattern (CGContextRef myContext)
{
NSLog(@"drawPattern Called ");
CGPatternRef pattern;
CGColorSpaceRef patternSpace;
CGFloat alpha = 1.0;
//width, height;
static const CGPatternCallbacks callbacks = {0, &patternSpec, NULL};
CGContextSaveGState (myContext);
patternSpace = CGColorSpaceCreatePattern (NULL);// 6
CGContextSetFillColorSpace (myContext, patternSpace);// 7
CGColorSpaceRelease (patternSpace);// 8
pattern = CGPatternCreate (NULL,CGRectMake (0, 0, PATTERN_SIZE, PATTERN_SIZE),
CGAffineTransformIdentity, PATTERN_SIZE, PATTERN_SIZE,
kCGPatternTilingConstantSpacing true, &callbacks);
CGContextSetFillPattern (myContext, pattern, &alpha);// 17
CGPatternRelease (pattern);// 18
//CGContextFillRect(myContext, rect);
CGContextDrawPath(myContext, kCGPathFill);
CGContextRestoreGState (myContext);
}
Вот фрагмент кода, где я хотел бы вызвать подпрограмму:
CGContextSetLineWidth(context, .7);
CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
// Standard non-inverted view scenario.
CGContextBeginPath(context);
CGContextMoveToPoint(context, 0.00 , bMargin);
CGContextAddLineToPoint(context, highPX - curveSP , bMargin);
[self addCurve:context startX:highPX startY:bMargin radius:bo curveSp:curveSP curveDir:FL_BL];
CGContextAddLineToPoint(context, highPX, ((h - tMargin) - curveSP) );
[self addCurve:context startX:highPX startY: (h - tMargin) radius:bo curveSp:curveSP curveDir:FL_TL];
CGContextAddLineToPoint(context, (lowPX - curveSP), (h - tMargin) );
[self addCurve:context startX: lowPX startY: (h - tMargin) radius:bo curveSp:curveSP curveDir:FL_TR];
CGContextAddLineToPoint(context, lowPX, (bMargin + curveSP) );
[self addCurve:context startX:lowPX startY: bMargin radius:bo curveSp:curveSP curveDir:FL_BR];
CGContextAddLineToPoint(context, w, bMargin);
//CGContextDrawPath(context, nonInvertedView);
CGContextDrawPath(context, kCGPathStroke);
// fill with pattern
drawPattern(context);
Фактический пример с яблоком также включает аргумент NSRect в методе рисования, но, поскольку я не хочу заполнять прямоугольник, я решил, что могу это опустить. не уверен, хотя.
Спасибо
2 ответа
CGContextDrawPath
сбрасывает текущий путь. (Раньше они упоминали об этом где-то, но я не смог найти это в быстром поиске.)
Сохраните графическое состояние до того, как вы его коснитесь, затем восстановите, прежде чем заполнить рисунком.
(Я предполагаю, что вы специально пытаетесь получить внешний удар, поглаживая и затем заполняя более половины его. Если вы хотите или можете принять центрированный удар, kCGPathFillStroke
будет делать работу с одним CGContextDrawPath
вызов.)
Итак, вот обновление: я не до конца понимаю, что происходит, но если я перетаскиваю код в методе drawPattern в тестовое приложение с пустым прямоугольником, он рисует так, как должен. Если я добавляю код в свой метод для рисования пути в представление, я получаю очень странное поведение; он даже пытается перерисовать части контроллера представления, о которых он даже не должен знать.
Как только я удалил CGContextSaveGState(), CGColorSpaceRelease(), CGPatternRelease() и CGContextRestoreGState(), код начал делать именно то, что я хотел. Я изменил метод к этому:
static void drawPattern(CGContextRef *pContext){
static CGPatternRef pattern;
static CGColorSpaceRef patternSpace;
static CGFloat alpha = 1.0;
static const CGPatternCallbacks callbacks = {0, &patternSpec, NULL};
patternSpace = CGColorSpaceCreatePattern (NULL);
CGContextSetFillColorSpace (pContext, patternSpace);
pattern = CGPatternCreate (NULL,
CGRectMake (0, 0, PATTERN_SIZE, PATTERN_SIZE),
CGAffineTransformIdentity,
PATTERN_SIZE,
PATTERN_SIZE,
kCGPatternTilingConstantSpacing,
true, &callbacks);
CGContextSetFillPattern (pContext, pattern, &alpha);
}
Теперь я могу либо вызвать определенный шаблон, либо установить определенный цвет заливки:
CGContextSetFillColor(context);
or:
drawPattern(context);
Я был бы признателен за это, потому что хотел бы знать, не является ли проблема, связанная с утечкой памяти, отсутствием некоторых из этих методов saveState или Release.
Спасибо