Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Linear shading function Objective-C -> RubyMotion port

REPL output

quadrant_view.rb:63:in `getLinearShadingFunctionRef:': expected instance of Pointer, got `#<Proc:0x7fcf0b727db0>' (Proc) (TypeError)
	from quadrant_view.rb:105:in `paintQuadrantBase:'

type expected by CGFunctionCallbacks.type

(main)> CGFunctionCallbacks.type
=> "{CGFunctionCallbacks=I^?^?}"

Apple docs mention that ? is used for function pointers. See: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html

RubyMotion docs for Pointer do not list function pointers. http://www.rubymotion.com/developer-center/api/Pointer.html

REPL crashes when running:

(terminal output)

(main)> Pointer.new('?')
Can't find pointer description for type `?'

================================================================================
The application terminated. A crash report file may have been generated by the
system, use `rake crashlog' to open it. Use `rake debug=1' to restart the app
in the debugger.
================================================================================

(first few lines of crashdump output)

Process:         SpinzyMac [10864]
Path:            /Users/USER/*/SpinzyMac.app/Contents/MacOS/SpinzyMac
Identifier:      com.yourcompany.SpinzyMac
Version:         1.0 (1.0)
Code Type:       X86-64 (Native)
Parent Process:  sim [10863]
Responsible:     Terminal [399]
User ID:         501

Date/Time:       2014-01-13 15:04:45.020 -0500
OS Version:      Mac OS X 10.9.1 (13B42)
Report Version:  11
Anonymous UUID:  2FFFD72A-A3E0-1BFD-4426-65FAC670F94A

Sleep/Wake UUID: D514428B-8BA0-4E72-8B3E-6FCED7BF25BD

Crashed Thread:  0  Dispatch queue: com.apple.main-thread

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000

Application Specific Information:
abort() called

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	0x00000001130c6866 __pthread_kill + 10
1   libsystem_pthread.dylib       	0x00000001131d435c pthread_kill + 92
2   libsystem_c.dylib             	0x0000000112ffcc5a __abort + 145
3   libsystem_c.dylib             	0x0000000112ffcbc9 abort + 140
4   com.yourcompany.SpinzyMac     	0x000000010ef50248 rb_pointer_s_new(unsigned long, objc_selector*, int, unsigned long*) + 360
def getLinearShadingFunctionRef(colorspace, colorPair)
input_value_range = [ 0, 1 ]
output_value_ranges = [ 0, 1, 0, 1, 0, 1, 0, 1 ]
callbacks = CGFunctionCallbacks.new
callbacks.version = 0
callbacks.evaluate = Proc.new do |colors, value_in, value_out|
components = 4
components.times do |index|
value_out[index] = (1.0 - value_in[0]) * colors[:start][index] + value_in[0] * colors[:start][index]
end
end
callbacks.releaseInfo = nil
components = 1 + CGColorSpaceGetNumberOfComponents(colorspace)
CGFunctionCreate(
colorPair,
1,
input_value_range,
components,
output_value_ranges,
callbacks
)
end
def paintQuadrantBase(context, bounds)
CGContextSaveGState(context)
white = [ 1, 1, 1, 1 ].to_pointer(:double)
CGContextSetFillColor(context, white);
CGContextFillRect(context, bounds);
lineWidth = 0.02
miterLimit = 100
startPoint = CGPointMake(1, 0)
endPoint = CGPointMake(0, 1)
colorspace = CGColorSpaceCreateDeviceRGB()
startColor = [0, 0, 0, 1]
endColor = [0, 0, 0xBA / 255.0, 0.38157895]
colorPair = {
start: startColor,
stop: endColor
}
shadingFunction = getLinearShadingFunctionRef(colorspace, colorPair)
shading = CGShadingCreateAxial(
colorspace,
startPoint,
endPoint,
shadingFunction,
false,
false
)
CGContextTranslateCTM(context, bounds.origin.x, bounds.origin.y)
CGContextScaleCTM(context, bounds.size.width, bounds.size.height)
CGContextSaveGState(context)
CGContextBeginPath(context)
CGContextAddRect(context, CGRectMake(0, 0, 1, 1))
CGContextClosePath(context)
CGContextClip(context)
CGContextDrawShading(context, shading)
CGColorSpaceRelease(colorspace)
CGShadingRelease(shading)
CGFunctionRelease(shadingFunction)
CGContextRestoreGState(context)
CGContextSetLineWidth(context, lineWidth)
CGContextSetLineJoin(context, KCGLineJoinRound)
CGContextSetLineCap(context, KCGLineCapRound)
CGContextSetMiterLimit(context, miterLimit)
CGContextSetRGBStrokeColor(context, 0, 0, 0, 1)
CGContextStrokeRect(context, CGRectMake(0, 0, 1, 1))
CGContextRestoreGState(context)
end
static void calculateLinearShadingValues(void *info, const float *in, float *out) {
const int components = 4;
ColorPair *colors = (ColorPair *) info;
int index;
for (index = 0; index < components; index++) {
out[index] = (1.0 - *in) * colors->start[index] + *in * colors->stop[index];
}
}
static CGFunctionRef getLinearShadingFunctionRef(CGColorSpaceRef colorspace, ColorPair* colorPair)
{
size_t components;
static const float input_value_range [2] = { 0, 1 };
static const float output_value_ranges [8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
static const CGFunctionCallbacks callbacks = { 0,
&calculateLinearShadingValues,
NULL };
components = 1 + CGColorSpaceGetNumberOfComponents (colorspace);
return CGFunctionCreate ((void *) colorPair,
1,
input_value_range,
components,
output_value_ranges,
&callbacks);
}
void paintQuadrantBase(CGContextRef context, CGRect bounds)
{
CGContextSaveGState(context);
static const float white[] = { 1, 1, 1, 1 };
CGContextSetFillColor(context, white);
CGContextFillRect(context, bounds);
CGPoint startPoint;
CGPoint endPoint;
const float lineWidth = 0.02;
const float miterLimit = 100;
startPoint = CGPointMake(1, 0);
endPoint = CGPointMake(0, 1);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
static const float startColor[] = {
0, 0, 0, 1
};
static const float endColor[] = {
0, 0, (float) 0xBA / 255.0, 0.38157895
};
ColorPair *colorPair = malloc(sizeof(ColorPair));
colorPair->start = (float *) &startColor;
colorPair->stop = (float *) &endColor;
CGFunctionRef shadingFunction = getLinearShadingFunctionRef(colorspace, colorPair);
CGShadingRef shading = CGShadingCreateAxial(colorspace,
startPoint,
endPoint,
shadingFunction,
false,
false);
CGContextTranslateCTM(context, bounds.origin.x, bounds.origin.y);
CGContextScaleCTM(context, bounds.size.width, bounds.size.height);
CGContextSaveGState(context);
CGContextBeginPath(context);
CGContextAddRect(context, CGRectMake(0, 0, 1, 1));
CGContextClosePath(context);
CGContextClip(context);
CGContextDrawShading(context, shading);
CGColorSpaceRelease(colorspace);
CGShadingRelease(shading);
CGFunctionRelease(shadingFunction);
CGContextRestoreGState(context);
CGContextSetLineWidth(context, lineWidth);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetMiterLimit(context, miterLimit);
CGContextSetRGBStrokeColor(context, 0, 0, 0, 1);
CGContextStrokeRect(context, CGRectMake(0, 0, 1, 1));
CGContextRestoreGState(context);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.